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