author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> |
Mon, 15 Mar 2010 12:43:09 +0200 | |
branch | RCL_3 |
changeset 6 | dee5afe5301f |
parent 4 | 3b1da2848fc7 |
child 30 | 5dc02b23752f |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 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 |