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