tools/designer/src/lib/shared/previewconfigurationwidget.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Designer of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /* It is possible to link the skins as resources into Designer by specifying:
       
    43  * QVFB_ROOT=$$QT_SOURCE_TREE/tools/qvfb
       
    44  * RESOURCES += $$QVFB_ROOT/ClamshellPhone.qrc  $$QVFB_ROOT/PDAPhone.qrc ...
       
    45  * in lib/shared/shared.pri. However, this exceeds a limit of Visual Studio 6. */
       
    46 
       
    47 #include "previewconfigurationwidget_p.h"
       
    48 #include "ui_previewconfigurationwidget.h"
       
    49 #include "previewmanager_p.h"
       
    50 #include "abstractsettings_p.h"
       
    51 #include "shared_settings_p.h"
       
    52 
       
    53 #include <iconloader_p.h>
       
    54 #include <stylesheeteditor_p.h>
       
    55 
       
    56 #include <deviceskin.h>
       
    57 
       
    58 #include <QtGui/QFileDialog>
       
    59 #include <QtGui/QStyleFactory>
       
    60 #include <QtGui/QFileDialog>
       
    61 #include <QtGui/QMessageBox>
       
    62 #include <QtCore/QPair>
       
    63 #include <QtCore/QList>
       
    64 #include <QtCore/QDebug>
       
    65 #include <QtCore/QFileInfo>
       
    66 #include <QtCore/QSharedData>
       
    67 
       
    68 
       
    69 static const char *skinResourcePathC = ":/skins/";
       
    70 
       
    71 QT_BEGIN_NAMESPACE
       
    72 
       
    73 static const char *skinExtensionC = "skin";
       
    74 
       
    75 // Pair of skin name, path
       
    76 typedef QPair<QString, QString> SkinNamePath;
       
    77 typedef QList<SkinNamePath> Skins;
       
    78 enum { SkinComboNoneIndex = 0 };
       
    79 
       
    80 // find default skins (resources)
       
    81 static const Skins &defaultSkins() {
       
    82     static Skins rc;
       
    83     if (rc.empty()) {
       
    84         const QString skinPath = QLatin1String(skinResourcePathC);
       
    85         QString pattern = QLatin1String("*.");
       
    86         pattern += QLatin1String(skinExtensionC);
       
    87         const QDir dir(skinPath, pattern);
       
    88         const QFileInfoList list = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot, QDir::Name);
       
    89         if (list.empty())
       
    90             return rc;
       
    91         const QFileInfoList::const_iterator lcend = list.constEnd();
       
    92         for (QFileInfoList::const_iterator it = list.constBegin(); it != lcend; ++it)
       
    93             rc.push_back(SkinNamePath(it->baseName(), it->filePath()));
       
    94     }
       
    95     return rc;
       
    96 }
       
    97 
       
    98 namespace qdesigner_internal {
       
    99 
       
   100 // ------------- PreviewConfigurationWidgetPrivate
       
   101 class PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate {
       
   102 public:
       
   103     PreviewConfigurationWidgetPrivate(QDesignerFormEditorInterface *core, QGroupBox *g);
       
   104 
       
   105     void slotEditAppStyleSheet();
       
   106     void slotDeleteSkinEntry();
       
   107     void slotSkinChanged(int index);
       
   108 
       
   109     void retrieveSettings();
       
   110     void storeSettings() const;
       
   111 
       
   112     QAbstractButton *appStyleSheetChangeButton() const { return m_ui.m_appStyleSheetChangeButton; }
       
   113     QAbstractButton *skinRemoveButton() const { return m_ui.m_skinRemoveButton; }
       
   114     QComboBox *skinCombo() const { return m_ui.m_skinCombo; }
       
   115 
       
   116     QDesignerFormEditorInterface *m_core;
       
   117 
       
   118 private:
       
   119     PreviewConfiguration previewConfiguration() const;
       
   120     void setPreviewConfiguration(const PreviewConfiguration &pc);
       
   121 
       
   122     QStringList userSkins() const;
       
   123     void addUserSkins(const QStringList &files);
       
   124     bool canRemoveSkin(int index) const;
       
   125     int browseSkin();
       
   126 
       
   127     const QString m_defaultStyle;
       
   128     QGroupBox *m_parent;
       
   129     Ui::PreviewConfigurationWidget m_ui;
       
   130 
       
   131     int m_firstUserSkinIndex;
       
   132     int m_browseSkinIndex;
       
   133     int m_lastSkinIndex; // required in case browse fails
       
   134 };
       
   135 
       
   136 PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::PreviewConfigurationWidgetPrivate(
       
   137         QDesignerFormEditorInterface *core, QGroupBox *g) :
       
   138     m_core(core),
       
   139     m_defaultStyle(PreviewConfigurationWidget::tr("Default")),
       
   140     m_parent(g),
       
   141     m_firstUserSkinIndex(0),
       
   142     m_browseSkinIndex(0),
       
   143     m_lastSkinIndex(0)
       
   144 {
       
   145     m_ui.setupUi(g);
       
   146     // styles
       
   147     m_ui.m_styleCombo->setEditable(false);
       
   148     QStringList styleItems(m_defaultStyle);
       
   149     styleItems += QStyleFactory::keys();
       
   150     m_ui.m_styleCombo->addItems(styleItems);
       
   151 
       
   152     // sheet
       
   153     m_ui.m_appStyleSheetLineEdit->setTextPropertyValidationMode(qdesigner_internal::ValidationStyleSheet);
       
   154     m_ui.m_appStyleSheetClearButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("resetproperty.png")));
       
   155     QObject::connect(m_ui.m_appStyleSheetClearButton, SIGNAL(clicked()), m_ui.m_appStyleSheetLineEdit, SLOT(clear()));
       
   156 
       
   157     m_ui.m_skinRemoveButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("editdelete.png")));
       
   158     // skins: find default skins (resources)
       
   159     m_ui.m_skinRemoveButton->setEnabled(false);
       
   160     Skins skins = defaultSkins();
       
   161     skins.push_front(SkinNamePath(PreviewConfigurationWidget::tr("None"), QString()));
       
   162 
       
   163     const Skins::const_iterator scend = skins.constEnd();
       
   164     for (Skins::const_iterator it = skins.constBegin(); it != scend; ++it)
       
   165         m_ui.m_skinCombo->addItem (it->first, QVariant(it->second));
       
   166     m_browseSkinIndex = m_firstUserSkinIndex = skins.size();
       
   167     m_ui.m_skinCombo->addItem(PreviewConfigurationWidget::tr("Browse..."), QString());
       
   168 
       
   169     m_ui.m_skinCombo->setMaxVisibleItems (qMax(15, 2 * m_browseSkinIndex));
       
   170     m_ui.m_skinCombo->setEditable(false);
       
   171 
       
   172     retrieveSettings();
       
   173 }
       
   174 
       
   175 bool PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::canRemoveSkin(int index) const
       
   176 {
       
   177     return index >= m_firstUserSkinIndex && index != m_browseSkinIndex;
       
   178 }
       
   179 
       
   180 QStringList PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::userSkins() const
       
   181 {
       
   182     QStringList rc;
       
   183     for (int i = m_firstUserSkinIndex; i < m_browseSkinIndex; i++)
       
   184         rc.push_back(m_ui.m_skinCombo->itemData(i).toString());
       
   185     return rc;
       
   186 }
       
   187 
       
   188 void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::addUserSkins(const QStringList &files)
       
   189 {
       
   190     if (files.empty())
       
   191         return;
       
   192     const QStringList ::const_iterator fcend = files.constEnd();
       
   193     for (QStringList::const_iterator it = files.constBegin(); it != fcend; ++it) {
       
   194         const QFileInfo fi(*it);
       
   195         if (fi.isDir() && fi.isReadable()) {
       
   196             m_ui.m_skinCombo->insertItem(m_browseSkinIndex++, fi.baseName(), QVariant(*it));
       
   197         } else {
       
   198             qWarning() << "Unable to access the skin directory '" << *it << "'.";
       
   199         }
       
   200     }
       
   201 }
       
   202 
       
   203 PreviewConfiguration PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::previewConfiguration() const
       
   204 {
       
   205     PreviewConfiguration  rc;
       
   206     QString style = m_ui.m_styleCombo->currentText();
       
   207     if (style == m_defaultStyle)
       
   208         style.clear();
       
   209     const QString applicationStyleSheet = m_ui.m_appStyleSheetLineEdit->text();
       
   210     // Figure out skin. 0 is None by definition..
       
   211     const int skinIndex = m_ui.m_skinCombo->currentIndex();
       
   212     QString deviceSkin;
       
   213     if (skinIndex != SkinComboNoneIndex &&  skinIndex != m_browseSkinIndex)
       
   214         deviceSkin = m_ui.m_skinCombo->itemData(skinIndex).toString();
       
   215 
       
   216     return PreviewConfiguration(style, applicationStyleSheet, deviceSkin);
       
   217 }
       
   218 
       
   219 void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::setPreviewConfiguration(const PreviewConfiguration &pc)
       
   220 {
       
   221     int styleIndex = m_ui.m_styleCombo->findText(pc.style());
       
   222     if (styleIndex == -1)
       
   223         styleIndex = m_ui.m_styleCombo->findText(m_defaultStyle);
       
   224     m_ui.m_styleCombo->setCurrentIndex(styleIndex);
       
   225     m_ui.m_appStyleSheetLineEdit->setText(pc.applicationStyleSheet());
       
   226     // find skin by file name. 0 is "none"
       
   227     const QString deviceSkin = pc.deviceSkin();
       
   228     int skinIndex = deviceSkin.isEmpty() ? 0 : m_ui.m_skinCombo->findData(QVariant(deviceSkin));
       
   229     if (skinIndex == -1) {
       
   230         qWarning() << "Unable to find skin '" << deviceSkin << "'.";
       
   231         skinIndex = 0;
       
   232     }
       
   233     m_ui.m_skinCombo->setCurrentIndex(skinIndex);
       
   234 }
       
   235 
       
   236 void  PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::slotEditAppStyleSheet()
       
   237 {
       
   238     StyleSheetEditorDialog dlg(m_core, m_parent, StyleSheetEditorDialog::ModeGlobal);
       
   239     dlg.setText(m_ui.m_appStyleSheetLineEdit->text());
       
   240     if (dlg.exec() == QDialog::Accepted)
       
   241         m_ui.m_appStyleSheetLineEdit->setText(dlg.text());
       
   242 }
       
   243 
       
   244 void  PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::slotDeleteSkinEntry()
       
   245 {
       
   246     const int index = m_ui.m_skinCombo->currentIndex();
       
   247     if (canRemoveSkin(index)) {
       
   248         m_ui.m_skinCombo->setCurrentIndex(SkinComboNoneIndex);
       
   249         m_ui.m_skinCombo->removeItem(index);
       
   250         m_browseSkinIndex--;
       
   251     }
       
   252 }
       
   253 
       
   254 void  PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::slotSkinChanged(int index)
       
   255 {
       
   256     if (index == m_browseSkinIndex) {
       
   257         m_ui.m_skinCombo->setCurrentIndex(browseSkin());
       
   258     } else {
       
   259         m_lastSkinIndex = index;
       
   260         m_ui.m_skinRemoveButton->setEnabled(canRemoveSkin(index));
       
   261         m_ui.m_skinCombo->setToolTip(index != SkinComboNoneIndex ? m_ui.m_skinCombo->itemData(index).toString() : QString());
       
   262     }
       
   263 }
       
   264 
       
   265 void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::retrieveSettings()
       
   266 {
       
   267     QDesignerSharedSettings settings(m_core);
       
   268     m_parent->setChecked(settings.isCustomPreviewConfigurationEnabled());
       
   269     setPreviewConfiguration(settings.customPreviewConfiguration());
       
   270     addUserSkins(settings.userDeviceSkins());
       
   271 }
       
   272 
       
   273 void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::storeSettings() const
       
   274 {
       
   275     QDesignerSharedSettings settings(m_core);
       
   276     settings.setCustomPreviewConfigurationEnabled(m_parent->isChecked());
       
   277     settings.setCustomPreviewConfiguration(previewConfiguration());
       
   278     settings.setUserDeviceSkins(userSkins());
       
   279 }
       
   280 
       
   281 int  PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::browseSkin()
       
   282 {
       
   283     QFileDialog dlg(m_parent);
       
   284     dlg.setFileMode(QFileDialog::DirectoryOnly);
       
   285     const QString title = tr("Load Custom Device Skin");
       
   286     dlg.setWindowTitle(title);
       
   287     dlg.setFilter(tr("All QVFB Skins (*.%1)").arg(QLatin1String(skinExtensionC)));
       
   288 
       
   289     int rc = m_lastSkinIndex;
       
   290     do {
       
   291         if (!dlg.exec())
       
   292             break;
       
   293 
       
   294         const QStringList directories =  dlg.selectedFiles();
       
   295         if (directories.size() != 1)
       
   296             break;
       
   297 
       
   298         // check: 1) name already there
       
   299         const QString directory = directories.front();
       
   300         const QString name = QFileInfo(directory).baseName();
       
   301         const int existingIndex = m_ui.m_skinCombo->findText(name);
       
   302         if (existingIndex != -1 && existingIndex != SkinComboNoneIndex &&  existingIndex != m_browseSkinIndex) {
       
   303             const QString msgTitle = tr("%1 - Duplicate Skin").arg(title);
       
   304             const QString msg = tr("The skin '%1' already exists.").arg(name);
       
   305             QMessageBox::information(m_parent, msgTitle, msg);
       
   306             break;
       
   307         }
       
   308         // check: 2) can read
       
   309         DeviceSkinParameters parameters;
       
   310         QString readError;
       
   311         if (parameters.read(directory, DeviceSkinParameters::ReadSizeOnly, &readError)) {
       
   312             const QString name = QFileInfo(directory).baseName();
       
   313             m_ui.m_skinCombo->insertItem(m_browseSkinIndex, name, QVariant(directory));
       
   314             rc = m_browseSkinIndex++;
       
   315 
       
   316             break;
       
   317         } else {
       
   318             const QString msgTitle = tr("%1 - Error").arg(title);
       
   319             const QString msg = tr("%1 is not a valid skin directory:\n%2").arg(directory).arg(readError);
       
   320             QMessageBox::warning (m_parent, msgTitle, msg);
       
   321         }
       
   322     } while (true);
       
   323     return rc;
       
   324 }
       
   325 
       
   326 // ------------- PreviewConfigurationWidget
       
   327 PreviewConfigurationWidget::PreviewConfigurationWidget(QDesignerFormEditorInterface *core,
       
   328                                                        QWidget *parent) :
       
   329     QGroupBox(parent),
       
   330     m_impl(new PreviewConfigurationWidgetPrivate(core, this))
       
   331 {
       
   332     connect(m_impl->appStyleSheetChangeButton(), SIGNAL(clicked()), this, SLOT(slotEditAppStyleSheet()));
       
   333     connect(m_impl->skinRemoveButton(), SIGNAL(clicked()), this, SLOT(slotDeleteSkinEntry()));
       
   334     connect(m_impl->skinCombo(), SIGNAL(currentIndexChanged(int)), this, SLOT(slotSkinChanged(int)));
       
   335 
       
   336     m_impl->retrieveSettings();
       
   337 }
       
   338 
       
   339 PreviewConfigurationWidget::~PreviewConfigurationWidget()
       
   340 {
       
   341     delete m_impl;
       
   342 }
       
   343 
       
   344 void PreviewConfigurationWidget::saveState()
       
   345 {
       
   346     m_impl->storeSettings();
       
   347 }
       
   348 
       
   349 void PreviewConfigurationWidget::slotEditAppStyleSheet()
       
   350 {
       
   351     m_impl->slotEditAppStyleSheet();
       
   352 }
       
   353 
       
   354 void PreviewConfigurationWidget::slotDeleteSkinEntry()
       
   355 {
       
   356     m_impl->slotDeleteSkinEntry();
       
   357 }
       
   358 
       
   359 void PreviewConfigurationWidget::slotSkinChanged(int index)
       
   360 {
       
   361     m_impl->slotSkinChanged(index);
       
   362 }
       
   363 
       
   364 }
       
   365 
       
   366 QT_END_NAMESPACE