1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "iconselector_p.h"
43 #include "qdesigner_utils_p.h"
44 #include "qtresourcemodel_p.h"
45 #include "qtresourceview_p.h"
46 #include "iconloader_p.h"
47 #include "qdesigner_integration_p.h"
48 #include "formwindowbase_p.h"
49
50 #include <abstractdialoggui_p.h>
51 #include <qdesigner_integration_p.h>
52 #include <QtDesigner/QDesignerFormEditorInterface>
53 #include <QtDesigner/QDesignerResourceBrowserInterface>
54 #include <QtDesigner/QDesignerLanguageExtension>
55 #include <QtDesigner/QExtensionManager>
56
57 #include <QtGui/QToolButton>
58 #include <QtCore/QSignalMapper>
59 #include <QtGui/QComboBox>
60 #include <QtGui/QAction>
61 #include <QtGui/QDialogButtonBox>
62 #include <QtGui/QPushButton>
63 #include <QtGui/QDialog>
64 #include <QtGui/QMenu>
65 #include <QtGui/QApplication>
66 #include <QtGui/QVBoxLayout>
67 #include <QtGui/QImageReader>
68 #include <QtGui/QDialogButtonBox>
69 #include <QtGui/QVBoxLayout>
70 #include <QtGui/QLineEdit>
71 #include <QtGui/QLabel>
72 #include <QtGui/QValidator>
73 #include <QtCore/QDebug>
74
75
76 QT_BEGIN_NAMESPACE
77
78 namespace qdesigner_internal {
79
80 // -------------------- LanguageResourceDialogPrivate
81 class LanguageResourceDialogPrivate {
82 LanguageResourceDialog *q_ptr;
83 Q_DECLARE_PUBLIC(LanguageResourceDialog)
84
85 public:
86 LanguageResourceDialogPrivate(QDesignerResourceBrowserInterface *rb);
87 void init(LanguageResourceDialog *p);
88
89 void setCurrentPath(const QString &filePath);
90 QString currentPath() const;
91
92 void slotAccepted();
93 void slotPathChanged(const QString &);
94
95 private:
setOkButtonEnabled(bool v)96 void setOkButtonEnabled(bool v) { m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(v); }
97 static bool checkPath(const QString &p);
98
99 QDesignerResourceBrowserInterface *m_browser;
100 QDialogButtonBox *m_dialogButtonBox;
101 };
102
LanguageResourceDialogPrivate(QDesignerResourceBrowserInterface * rb)103 LanguageResourceDialogPrivate::LanguageResourceDialogPrivate(QDesignerResourceBrowserInterface *rb) :
104 q_ptr(0),
105 m_browser(rb),
106 m_dialogButtonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel))
107 {
108 setOkButtonEnabled(false);
109 }
110
init(LanguageResourceDialog * p)111 void LanguageResourceDialogPrivate::init(LanguageResourceDialog *p)
112 {
113 q_ptr = p;
114 QLayout *layout = new QVBoxLayout(p);
115 layout->addWidget(m_browser);
116 layout->addWidget(m_dialogButtonBox);
117 QObject::connect(m_dialogButtonBox, SIGNAL(accepted()), p, SLOT(slotAccepted()));
118 QObject::connect(m_dialogButtonBox, SIGNAL(rejected()), p, SLOT(reject()));
119 QObject::connect(m_browser, SIGNAL(currentPathChanged(QString)), p, SLOT(slotPathChanged(QString)));
120 QObject::connect(m_browser, SIGNAL(pathActivated(QString)), p, SLOT(slotAccepted()));
121 p->setModal(true);
122 p->setWindowTitle(LanguageResourceDialog::tr("Choose Resource"));
123 p->setWindowFlags(p->windowFlags() & ~Qt::WindowContextHelpButtonHint);
124 setOkButtonEnabled(false);
125 }
126
setCurrentPath(const QString & filePath)127 void LanguageResourceDialogPrivate::setCurrentPath(const QString &filePath)
128 {
129 m_browser->setCurrentPath(filePath);
130 setOkButtonEnabled(checkPath(filePath));
131 }
132
currentPath() const133 QString LanguageResourceDialogPrivate::currentPath() const
134 {
135 return m_browser->currentPath();
136 }
137
checkPath(const QString & p)138 bool LanguageResourceDialogPrivate::checkPath(const QString &p)
139 {
140 return p.isEmpty() ? false : IconSelector::checkPixmap(p, IconSelector::CheckFast);
141 }
142
slotAccepted()143 void LanguageResourceDialogPrivate::slotAccepted()
144 {
145 if (checkPath(currentPath()))
146 q_ptr->accept();
147 }
148
slotPathChanged(const QString & p)149 void LanguageResourceDialogPrivate::slotPathChanged(const QString &p)
150 {
151 setOkButtonEnabled(checkPath(p));
152 }
153
154 // ------------ LanguageResourceDialog
LanguageResourceDialog(QDesignerResourceBrowserInterface * rb,QWidget * parent)155 LanguageResourceDialog::LanguageResourceDialog(QDesignerResourceBrowserInterface *rb, QWidget *parent) :
156 QDialog(parent),
157 d_ptr(new LanguageResourceDialogPrivate(rb))
158 {
159 d_ptr->init( this);
160 }
161
~LanguageResourceDialog()162 LanguageResourceDialog::~LanguageResourceDialog()
163 {
164 }
165
setCurrentPath(const QString & filePath)166 void LanguageResourceDialog::setCurrentPath(const QString &filePath)
167 {
168 d_ptr->setCurrentPath(filePath);
169 }
170
currentPath() const171 QString LanguageResourceDialog::currentPath() const
172 {
173 return d_ptr->currentPath();
174 }
175
create(QDesignerFormEditorInterface * core,QWidget * parent)176 LanguageResourceDialog* LanguageResourceDialog::create(QDesignerFormEditorInterface *core, QWidget *parent)
177 {
178 if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
179 if (QDesignerResourceBrowserInterface *rb = lang->createResourceBrowser(0))
180 return new LanguageResourceDialog(rb, parent);
181 if (QDesignerIntegration *di = qobject_cast<QDesignerIntegration*>(core->integration()))
182 if (QDesignerResourceBrowserInterface *rb = di->createResourceBrowser(0))
183 return new LanguageResourceDialog(rb, parent);
184 return 0;
185 }
186
187 // ------------ IconSelectorPrivate
188
emptyPixmap()189 static inline QPixmap emptyPixmap()
190 {
191 QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
192 img.fill(0);
193 return QPixmap::fromImage(img);
194 }
195
196 class IconSelectorPrivate
197 {
198 IconSelector *q_ptr;
199 Q_DECLARE_PUBLIC(IconSelector)
200 public:
201 IconSelectorPrivate();
202
203 void slotStateActivated();
204 void slotSetActivated();
205 void slotSetResourceActivated();
206 void slotSetFileActivated();
207 void slotResetActivated();
208 void slotResetAllActivated();
209 void slotUpdate();
210
211 QList<QPair<QPair<QIcon::Mode, QIcon::State>, QString> > m_stateToName; // could be static map
212
213 QMap<QPair<QIcon::Mode, QIcon::State>, int> m_stateToIndex;
214 QMap<int, QPair<QIcon::Mode, QIcon::State> > m_indexToState;
215
216 const QIcon m_emptyIcon;
217 QComboBox *m_stateComboBox;
218 QToolButton *m_iconButton;
219 QAction *m_resetAction;
220 QAction *m_resetAllAction;
221 PropertySheetIconValue m_icon;
222 DesignerIconCache *m_iconCache;
223 DesignerPixmapCache *m_pixmapCache;
224 QtResourceModel *m_resourceModel;
225 QDesignerFormEditorInterface *m_core;
226 };
227
IconSelectorPrivate()228 IconSelectorPrivate::IconSelectorPrivate() :
229 q_ptr(0),
230 m_emptyIcon(emptyPixmap()),
231 m_stateComboBox(0),
232 m_iconButton(0),
233 m_resetAction(0),
234 m_resetAllAction(0),
235 m_iconCache(0),
236 m_pixmapCache(0),
237 m_resourceModel(0),
238 m_core(0)
239 {
240 }
slotUpdate()241 void IconSelectorPrivate::slotUpdate()
242 {
243 QIcon icon;
244 if (m_iconCache)
245 icon = m_iconCache->icon(m_icon);
246
247 QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> paths = m_icon.paths();
248 QMapIterator<QPair<QIcon::Mode, QIcon::State>, int> itIndex(m_stateToIndex);
249 while (itIndex.hasNext()) {
250 const QPair<QIcon::Mode, QIcon::State> state = itIndex.next().key();
251 const PropertySheetPixmapValue pixmap = paths.value(state);
252 const int index = itIndex.value();
253
254 QIcon pixmapIcon = QIcon(icon.pixmap(16, 16, state.first, state.second));
255 if (pixmapIcon.isNull())
256 pixmapIcon = m_emptyIcon;
257 m_stateComboBox->setItemIcon(index, pixmapIcon);
258 QFont font = q_ptr->font();
259 if (!pixmap.path().isEmpty())
260 font.setBold(true);
261 m_stateComboBox->setItemData(index, font, Qt::FontRole);
262 }
263
264 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
265 PropertySheetPixmapValue currentPixmap = paths.value(state);
266 m_resetAction->setEnabled(!currentPixmap.path().isEmpty());
267 m_resetAllAction->setEnabled(!paths.isEmpty());
268 m_stateComboBox->update();
269 }
270
slotStateActivated()271 void IconSelectorPrivate::slotStateActivated()
272 {
273 slotUpdate();
274 }
275
slotSetActivated()276 void IconSelectorPrivate::slotSetActivated()
277 {
278 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
279 const PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
280 // Default to resource
281 const PropertySheetPixmapValue::PixmapSource ps = pixmap.path().isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : pixmap.pixmapSource(m_core);
282 switch (ps) {
283 case PropertySheetPixmapValue::LanguageResourcePixmap:
284 case PropertySheetPixmapValue::ResourcePixmap:
285 slotSetResourceActivated();
286 break;
287 case PropertySheetPixmapValue::FilePixmap:
288 slotSetFileActivated();
289 break;
290 }
291 }
292
293 // Choose a pixmap from resource; use language-dependent resource browser if present
choosePixmapResource(QDesignerFormEditorInterface * core,QtResourceModel * resourceModel,const QString & oldPath,QWidget * parent)294 QString IconSelector::choosePixmapResource(QDesignerFormEditorInterface *core, QtResourceModel *resourceModel, const QString &oldPath, QWidget *parent)
295 {
296 Q_UNUSED(resourceModel)
297 QString rc;
298
299 if (LanguageResourceDialog* ldlg = LanguageResourceDialog::create(core, parent)) {
300 ldlg->setCurrentPath(oldPath);
301 if (ldlg->exec() == QDialog::Accepted)
302 rc = ldlg->currentPath();
303 delete ldlg;
304 } else {
305 QtResourceViewDialog dlg(core, parent);
306
307 QDesignerIntegration *designerIntegration = qobject_cast<QDesignerIntegration *>(core->integration());
308 if (designerIntegration)
309 dlg.setResourceEditingEnabled(designerIntegration->isResourceEditingEnabled());
310
311 dlg.selectResource(oldPath);
312 if (dlg.exec() == QDialog::Accepted)
313 rc = dlg.selectedResource();
314 }
315 return rc;
316 }
317
slotSetResourceActivated()318 void IconSelectorPrivate::slotSetResourceActivated()
319 {
320 const QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
321
322 PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
323 const QString oldPath = pixmap.path();
324 const QString newPath = IconSelector::choosePixmapResource(m_core, m_resourceModel, oldPath, q_ptr);
325 if (newPath.isEmpty() || newPath == oldPath)
326 return;
327 const PropertySheetPixmapValue newPixmap = PropertySheetPixmapValue(newPath);
328 if (newPixmap != pixmap) {
329 m_icon.setPixmap(state.first, state.second, newPixmap);
330 slotUpdate();
331 emit q_ptr->iconChanged(m_icon);
332 }
333 }
334
335 // Helpers for choosing image files: Check for valid image.
checkPixmap(const QString & fileName,CheckMode cm,QString * errorMessage)336 bool IconSelector::checkPixmap(const QString &fileName, CheckMode cm, QString *errorMessage)
337 {
338 const QFileInfo fi(fileName);
339 if (!fi.exists() || !fi.isFile() || !fi.isReadable()) {
340 if (errorMessage)
341 *errorMessage = tr("The pixmap file '%1' cannot be read.").arg(fileName);
342 return false;
343 }
344 QImageReader reader(fileName);
345 if (!reader.canRead()) {
346 if (errorMessage)
347 *errorMessage = tr("The file '%1' does not appear to be a valid pixmap file: %2").arg(fileName).arg(reader.errorString());
348 return false;
349 }
350 if (cm == CheckFast)
351 return true;
352
353 const QImage image = reader.read();
354 if (image.isNull()) {
355 if (errorMessage)
356 *errorMessage = tr("The file '%1' could not be read: %2").arg(fileName).arg(reader.errorString());
357 return false;
358 }
359 return true;
360 }
361
362 // Helpers for choosing image files: Return an image filter for QFileDialog, courtesy of StyledButton
imageFilter()363 static QString imageFilter()
364 {
365 QString filter = QApplication::translate("IconSelector", "All Pixmaps (");
366 const QList<QByteArray> supportedImageFormats = QImageReader::supportedImageFormats();
367 const QString jpeg = QLatin1String("JPEG");
368 const int count = supportedImageFormats.count();
369 for (int i = 0; i< count; ++i) {
370 if (i)
371 filter += QLatin1Char(' ');
372 filter += QLatin1String("*.");
373 const QString outputFormat = QString::fromUtf8(supportedImageFormats.at(i));
374 if (outputFormat != jpeg)
375 filter += outputFormat.toLower();
376 else
377 filter += QLatin1String("jpg *.jpeg");
378 }
379 filter += QLatin1Char(')');
380 return filter;
381 }
382
383 // Helpers for choosing image files: Choose a file
choosePixmapFile(const QString & directory,QDesignerDialogGuiInterface * dlgGui,QWidget * parent)384 QString IconSelector::choosePixmapFile(const QString &directory, QDesignerDialogGuiInterface *dlgGui,QWidget *parent)
385 {
386 QString errorMessage;
387 QString newPath;
388 do {
389 const QString title = tr("Choose a Pixmap");
390 static const QString filter = imageFilter();
391 newPath = dlgGui->getOpenImageFileName(parent, title, directory, filter);
392 if (newPath.isEmpty())
393 break;
394 if (checkPixmap(newPath, CheckFully, &errorMessage))
395 break;
396 dlgGui->message(parent, QDesignerDialogGuiInterface::ResourceEditorMessage, QMessageBox::Warning, tr("Pixmap Read Error"), errorMessage);
397 } while(true);
398 return newPath;
399 }
400
slotSetFileActivated()401 void IconSelectorPrivate::slotSetFileActivated()
402 {
403 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
404
405 PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
406 const QString newPath = IconSelector::choosePixmapFile(pixmap.path(), m_core->dialogGui(), q_ptr);
407 if (!newPath.isEmpty()) {
408 const PropertySheetPixmapValue newPixmap = PropertySheetPixmapValue(newPath);
409 if (!(newPixmap == pixmap)) {
410 m_icon.setPixmap(state.first, state.second, newPixmap);
411 slotUpdate();
412 emit q_ptr->iconChanged(m_icon);
413 }
414 }
415 }
416
slotResetActivated()417 void IconSelectorPrivate::slotResetActivated()
418 {
419 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
420
421 PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
422 const PropertySheetPixmapValue newPixmap;
423 if (!(newPixmap == pixmap)) {
424 m_icon.setPixmap(state.first, state.second, newPixmap);
425 slotUpdate();
426 emit q_ptr->iconChanged(m_icon);
427 }
428 }
429
slotResetAllActivated()430 void IconSelectorPrivate::slotResetAllActivated()
431 {
432 const PropertySheetIconValue newIcon;
433 if (!(m_icon == newIcon)) {
434 m_icon = newIcon;
435 slotUpdate();
436 emit q_ptr->iconChanged(m_icon);
437 }
438 }
439
440 // ------------- IconSelector
IconSelector(QWidget * parent)441 IconSelector::IconSelector(QWidget *parent) :
442 QWidget(parent), d_ptr(new IconSelectorPrivate())
443 {
444 d_ptr->q_ptr = this;
445
446 d_ptr->m_stateComboBox = new QComboBox(this);
447
448 QHBoxLayout *l = new QHBoxLayout(this);
449 d_ptr->m_iconButton = new QToolButton(this);
450 d_ptr->m_iconButton->setText(tr("..."));
451 d_ptr->m_iconButton->setPopupMode(QToolButton::MenuButtonPopup);
452 l->addWidget(d_ptr->m_stateComboBox);
453 l->addWidget(d_ptr->m_iconButton);
454 l->setMargin(0);
455
456 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Normal, QIcon::Off), tr("Normal Off") );
457 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Normal, QIcon::On), tr("Normal On") );
458 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Disabled, QIcon::Off), tr("Disabled Off") );
459 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Disabled, QIcon::On), tr("Disabled On") );
460 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Active, QIcon::Off), tr("Active Off") );
461 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Active, QIcon::On), tr("Active On") );
462 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::Off), tr("Selected Off") );
463 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::On), tr("Selected On") );
464
465 QMenu *setMenu = new QMenu(this);
466
467 QAction *setResourceAction = new QAction(tr("Choose Resource..."), this);
468 QAction *setFileAction = new QAction(tr("Choose File..."), this);
469 d_ptr->m_resetAction = new QAction(tr("Reset"), this);
470 d_ptr->m_resetAllAction = new QAction(tr("Reset All"), this);
471 d_ptr->m_resetAction->setEnabled(false);
472 d_ptr->m_resetAllAction->setEnabled(false);
473 //d_ptr->m_resetAction->setIcon(createIconSet(QString::fromUtf8("resetproperty.png")));
474
475 setMenu->addAction(setResourceAction);
476 setMenu->addAction(setFileAction);
477 setMenu->addSeparator();
478 setMenu->addAction(d_ptr->m_resetAction);
479 setMenu->addAction(d_ptr->m_resetAllAction);
480
481 int index = 0;
482 QStringList items;
483 QListIterator<QPair<QPair<QIcon::Mode, QIcon::State>, QString> > itName(d_ptr->m_stateToName);
484 while (itName.hasNext()) {
485 QPair<QPair<QIcon::Mode, QIcon::State>, QString> item = itName.next();
486 const QPair<QIcon::Mode, QIcon::State> state = item.first;
487 const QString name = item.second;
488
489 items.append(name);
490 d_ptr->m_stateToIndex[state] = index;
491 d_ptr->m_indexToState[index] = state;
492 index++;
493 }
494 d_ptr->m_stateComboBox->addItems(items);
495
496 d_ptr->m_iconButton->setMenu(setMenu);
497
498 connect(d_ptr->m_stateComboBox, SIGNAL(activated(int)), this, SLOT(slotStateActivated()));
499 connect(d_ptr->m_iconButton, SIGNAL(clicked()), this, SLOT(slotSetActivated()));
500 connect(setResourceAction, SIGNAL(triggered()), this, SLOT(slotSetResourceActivated()));
501 connect(setFileAction, SIGNAL(triggered()), this, SLOT(slotSetFileActivated()));
502 connect(d_ptr->m_resetAction, SIGNAL(triggered()), this, SLOT(slotResetActivated()));
503 connect(d_ptr->m_resetAllAction, SIGNAL(triggered()), this, SLOT(slotResetAllActivated()));
504
505 d_ptr->slotUpdate();
506 }
507
~IconSelector()508 IconSelector::~IconSelector()
509 {
510 }
511
setIcon(const PropertySheetIconValue & icon)512 void IconSelector::setIcon(const PropertySheetIconValue &icon)
513 {
514 if (d_ptr->m_icon == icon)
515 return;
516
517 d_ptr->m_icon = icon;
518 d_ptr->slotUpdate();
519 }
520
icon() const521 PropertySheetIconValue IconSelector::icon() const
522 {
523 return d_ptr->m_icon;
524 }
525
setFormEditor(QDesignerFormEditorInterface * core)526 void IconSelector::setFormEditor(QDesignerFormEditorInterface *core)
527 {
528 d_ptr->m_core = core;
529 d_ptr->m_resourceModel = core->resourceModel();
530 d_ptr->slotUpdate();
531 }
532
setIconCache(DesignerIconCache * iconCache)533 void IconSelector::setIconCache(DesignerIconCache *iconCache)
534 {
535 d_ptr->m_iconCache = iconCache;
536 connect(iconCache, SIGNAL(reloaded()), this, SLOT(slotUpdate()));
537 d_ptr->slotUpdate();
538 }
539
setPixmapCache(DesignerPixmapCache * pixmapCache)540 void IconSelector::setPixmapCache(DesignerPixmapCache *pixmapCache)
541 {
542 d_ptr->m_pixmapCache = pixmapCache;
543 connect(pixmapCache, SIGNAL(reloaded()), this, SLOT(slotUpdate()));
544 d_ptr->slotUpdate();
545 }
546
547 // --- IconThemeEditor
548
549 // Validator for theme line edit, accepts empty or non-blank strings.
550 class BlankSuppressingValidator : public QValidator {
551 public:
BlankSuppressingValidator(QObject * parent=0)552 explicit BlankSuppressingValidator(QObject * parent = 0) : QValidator(parent) {}
553
validate(QString & input,int & pos) const554 virtual State validate(QString &input, int &pos) const {
555 const int blankPos = input.indexOf(QLatin1Char(' '));
556 if (blankPos != -1) {
557 pos = blankPos;
558 return Invalid;
559 }
560 return Acceptable;
561 }
562 };
563
564 struct IconThemeEditorPrivate {
565 IconThemeEditorPrivate();
566
567 const QPixmap m_emptyPixmap;
568 QLineEdit *m_themeLineEdit;
569 QLabel *m_themeLabel;
570 };
571
IconThemeEditorPrivate()572 IconThemeEditorPrivate::IconThemeEditorPrivate() :
573 m_emptyPixmap(emptyPixmap()),
574 m_themeLineEdit(new QLineEdit),
575 m_themeLabel(new QLabel)
576 {
577 }
578
IconThemeEditor(QWidget * parent,bool wantResetButton)579 IconThemeEditor::IconThemeEditor(QWidget *parent, bool wantResetButton) :
580 QWidget (parent), d(new IconThemeEditorPrivate)
581 {
582 QHBoxLayout *mainHLayout = new QHBoxLayout;
583 mainHLayout->setMargin(0);
584
585 // Vertically center theme preview label
586 d->m_themeLabel->setPixmap(d->m_emptyPixmap);
587
588 QVBoxLayout *themeLabelVLayout = new QVBoxLayout;
589 d->m_themeLabel->setMargin(1);
590 themeLabelVLayout->setMargin(0);
591 themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
592 themeLabelVLayout->addWidget(d->m_themeLabel);
593 themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
594 mainHLayout->addLayout(themeLabelVLayout);
595
596 d->m_themeLineEdit = new QLineEdit;
597 d->m_themeLineEdit->setValidator(new BlankSuppressingValidator(d->m_themeLineEdit));
598 connect(d->m_themeLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged(QString)));
599 connect(d->m_themeLineEdit, SIGNAL(textEdited(QString)), this, SIGNAL(edited(QString)));
600 mainHLayout->addWidget(d->m_themeLineEdit);
601
602 if (wantResetButton) {
603 QToolButton *themeResetButton = new QToolButton;
604 themeResetButton->setIcon(createIconSet(QLatin1String("resetproperty.png")));
605 connect(themeResetButton, SIGNAL(clicked()), this, SLOT(reset()));
606 mainHLayout->addWidget(themeResetButton);
607 }
608
609 setLayout(mainHLayout);
610 setFocusProxy(d->m_themeLineEdit);
611 }
612
~IconThemeEditor()613 IconThemeEditor::~IconThemeEditor()
614 {
615 }
616
reset()617 void IconThemeEditor::reset()
618 {
619 d->m_themeLineEdit->clear();
620 emit edited(QString());
621 }
622
slotChanged(const QString & theme)623 void IconThemeEditor::slotChanged(const QString &theme)
624 {
625 updatePreview(theme);
626 }
627
updatePreview(const QString & t)628 void IconThemeEditor::updatePreview(const QString &t)
629 {
630 // Update preview label with icon.
631 if (t.isEmpty() || !QIcon::hasThemeIcon(t)) { // Empty
632 const QPixmap *currentPixmap = d->m_themeLabel->pixmap();
633 if (currentPixmap == 0 || currentPixmap->serialNumber() != d->m_emptyPixmap.serialNumber())
634 d->m_themeLabel->setPixmap(d->m_emptyPixmap);
635 } else {
636 const QIcon icon = QIcon::fromTheme(t);
637 d->m_themeLabel->setPixmap(icon.pixmap(d->m_emptyPixmap.size()));
638 }
639 }
640
theme() const641 QString IconThemeEditor::theme() const
642 {
643 return d->m_themeLineEdit->text();
644 }
645
setTheme(const QString & t)646 void IconThemeEditor::setTheme(const QString &t)
647 {
648 d->m_themeLineEdit->setText(t);
649 }
650
651 } // qdesigner_internal
652
653 QT_END_NAMESPACE
654
655 #include "moc_iconselector_p.cpp"
656