source: trunk/tools/designer/src/lib/shared/previewconfigurationwidget.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 13.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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/TouchScreenPhone.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
69static const char *skinResourcePathC = ":/skins/";
70
71QT_BEGIN_NAMESPACE
72
73static const char *skinExtensionC = "skin";
74
75// Pair of skin name, path
76typedef QPair<QString, QString> SkinNamePath;
77typedef QList<SkinNamePath> Skins;
78enum { SkinComboNoneIndex = 0 };
79
80// find default skins (resources)
81static 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
98namespace qdesigner_internal {
99
100// ------------- PreviewConfigurationWidgetPrivate
101class PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate {
102public:
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
118private:
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
136PreviewConfigurationWidget::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
175bool PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::canRemoveSkin(int index) const
176{
177 return index >= m_firstUserSkinIndex && index != m_browseSkinIndex;
178}
179
180QStringList 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
188void 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
203PreviewConfiguration 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
219void 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
236void 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
244void 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
254void 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
265void 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
273void 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
281int 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
327PreviewConfigurationWidget::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
339PreviewConfigurationWidget::~PreviewConfigurationWidget()
340{
341 delete m_impl;
342}
343
344void PreviewConfigurationWidget::saveState()
345{
346 m_impl->storeSettings();
347}
348
349void PreviewConfigurationWidget::slotEditAppStyleSheet()
350{
351 m_impl->slotEditAppStyleSheet();
352}
353
354void PreviewConfigurationWidget::slotDeleteSkinEntry()
355{
356 m_impl->slotDeleteSkinEntry();
357}
358
359void PreviewConfigurationWidget::slotSkinChanged(int index)
360{
361 m_impl->slotSkinChanged(index);
362}
363
364}
365
366QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.