source: trunk/tools/designer/src/lib/shared/iconselector.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 18.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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 [email protected].
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 <QtCore/QDebug>
71
72QT_BEGIN_NAMESPACE
73
74namespace qdesigner_internal {
75
76// -------------------- LanguageResourceDialogPrivate
77class LanguageResourceDialogPrivate {
78 LanguageResourceDialog *q_ptr;
79 Q_DECLARE_PUBLIC(LanguageResourceDialog)
80
81public:
82 LanguageResourceDialogPrivate(QDesignerResourceBrowserInterface *rb);
83 void init(LanguageResourceDialog *p);
84
85 void setCurrentPath(const QString &filePath);
86 QString currentPath() const;
87
88 void slotAccepted();
89 void slotPathChanged(const QString &);
90
91private:
92 void setOkButtonEnabled(bool v) { m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(v); }
93 static bool checkPath(const QString &p);
94
95 QDesignerResourceBrowserInterface *m_browser;
96 QDialogButtonBox *m_dialogButtonBox;
97};
98
99LanguageResourceDialogPrivate::LanguageResourceDialogPrivate(QDesignerResourceBrowserInterface *rb) :
100 q_ptr(0),
101 m_browser(rb),
102 m_dialogButtonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel))
103{
104 setOkButtonEnabled(false);
105}
106
107void LanguageResourceDialogPrivate::init(LanguageResourceDialog *p)
108{
109 q_ptr = p;
110 QLayout *layout = new QVBoxLayout(p);
111 layout->addWidget(m_browser);
112 layout->addWidget(m_dialogButtonBox);
113 QObject::connect(m_dialogButtonBox, SIGNAL(accepted()), p, SLOT(slotAccepted()));
114 QObject::connect(m_dialogButtonBox, SIGNAL(rejected()), p, SLOT(reject()));
115 QObject::connect(m_browser, SIGNAL(currentPathChanged(QString)), p, SLOT(slotPathChanged(QString)));
116 QObject::connect(m_browser, SIGNAL(pathActivated(QString)), p, SLOT(slotAccepted()));
117 p->setModal(true);
118 p->setWindowTitle(LanguageResourceDialog::tr("Choose Resource"));
119 p->setWindowFlags(p->windowFlags() & ~Qt::WindowContextHelpButtonHint);
120 setOkButtonEnabled(false);
121}
122
123void LanguageResourceDialogPrivate::setCurrentPath(const QString &filePath)
124{
125 m_browser->setCurrentPath(filePath);
126 setOkButtonEnabled(checkPath(filePath));
127}
128
129QString LanguageResourceDialogPrivate::currentPath() const
130{
131 return m_browser->currentPath();
132}
133
134bool LanguageResourceDialogPrivate::checkPath(const QString &p)
135{
136 return p.isEmpty() ? false : IconSelector::checkPixmap(p, IconSelector::CheckFast);
137}
138
139void LanguageResourceDialogPrivate::slotAccepted()
140{
141 if (checkPath(currentPath()))
142 q_ptr->accept();
143}
144
145void LanguageResourceDialogPrivate::slotPathChanged(const QString &p)
146{
147 setOkButtonEnabled(checkPath(p));
148}
149
150// ------------ LanguageResourceDialog
151LanguageResourceDialog::LanguageResourceDialog(QDesignerResourceBrowserInterface *rb, QWidget *parent) :
152 QDialog(parent),
153 d_ptr(new LanguageResourceDialogPrivate(rb))
154{
155 d_ptr->init( this);
156}
157
158LanguageResourceDialog::~LanguageResourceDialog()
159{
160}
161
162void LanguageResourceDialog::setCurrentPath(const QString &filePath)
163{
164 d_ptr->setCurrentPath(filePath);
165}
166
167QString LanguageResourceDialog::currentPath() const
168{
169 return d_ptr->currentPath();
170}
171
172LanguageResourceDialog* LanguageResourceDialog::create(QDesignerFormEditorInterface *core, QWidget *parent)
173{
174 if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
175 if (QDesignerResourceBrowserInterface *rb = lang->createResourceBrowser(0))
176 return new LanguageResourceDialog(rb, parent);
177 if (QDesignerIntegration *di = qobject_cast<QDesignerIntegration*>(core->integration()))
178 if (QDesignerResourceBrowserInterface *rb = di->createResourceBrowser(0))
179 return new LanguageResourceDialog(rb, parent);
180 return 0;
181}
182
183// ------------ IconSelectorPrivate
184class IconSelectorPrivate
185{
186 IconSelector *q_ptr;
187 Q_DECLARE_PUBLIC(IconSelector)
188public:
189 IconSelectorPrivate();
190
191 void slotStateActivated();
192 void slotSetActivated();
193 void slotSetResourceActivated();
194 void slotSetFileActivated();
195 void slotResetActivated();
196 void slotResetAllActivated();
197 void slotUpdate();
198
199 QList<QPair<QPair<QIcon::Mode, QIcon::State>, QString> > m_stateToName; // could be static map
200
201 QMap<QPair<QIcon::Mode, QIcon::State>, int> m_stateToIndex;
202 QMap<int, QPair<QIcon::Mode, QIcon::State> > m_indexToState;
203
204 QIcon m_emptyIcon;
205 QComboBox *m_stateComboBox;
206 QToolButton *m_iconButton;
207 QAction *m_resetAction;
208 QAction *m_resetAllAction;
209 PropertySheetIconValue m_icon;
210 DesignerIconCache *m_iconCache;
211 DesignerPixmapCache *m_pixmapCache;
212 QtResourceModel *m_resourceModel;
213 QDesignerFormEditorInterface *m_core;
214};
215
216IconSelectorPrivate::IconSelectorPrivate() :
217 q_ptr(0),
218 m_stateComboBox(0),
219 m_iconButton(0),
220 m_resetAction(0),
221 m_resetAllAction(0),
222 m_iconCache(0),
223 m_pixmapCache(0),
224 m_resourceModel(0),
225 m_core(0)
226{
227}
228void IconSelectorPrivate::slotUpdate()
229{
230 QIcon icon;
231 if (m_iconCache)
232 icon = m_iconCache->icon(m_icon);
233
234 QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> paths = m_icon.paths();
235 QMapIterator<QPair<QIcon::Mode, QIcon::State>, int> itIndex(m_stateToIndex);
236 while (itIndex.hasNext()) {
237 const QPair<QIcon::Mode, QIcon::State> state = itIndex.next().key();
238 const PropertySheetPixmapValue pixmap = paths.value(state);
239 const int index = itIndex.value();
240
241 QIcon pixmapIcon = QIcon(icon.pixmap(16, 16, state.first, state.second));
242 if (pixmapIcon.isNull())
243 pixmapIcon = m_emptyIcon;
244 m_stateComboBox->setItemIcon(index, pixmapIcon);
245 QFont font = q_ptr->font();
246 if (!pixmap.path().isEmpty())
247 font.setBold(true);
248 m_stateComboBox->setItemData(index, font, Qt::FontRole);
249 }
250
251 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
252 PropertySheetPixmapValue currentPixmap = paths.value(state);
253 m_resetAction->setEnabled(!currentPixmap.path().isEmpty());
254 m_resetAllAction->setEnabled(!paths.isEmpty());
255 m_stateComboBox->update();
256}
257
258void IconSelectorPrivate::slotStateActivated()
259{
260 slotUpdate();
261}
262
263void IconSelectorPrivate::slotSetActivated()
264{
265 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
266 const PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
267 // Default to resource
268 const PropertySheetPixmapValue::PixmapSource ps = pixmap.path().isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : pixmap.pixmapSource(m_core);
269 switch (ps) {
270 case PropertySheetPixmapValue::LanguageResourcePixmap:
271 case PropertySheetPixmapValue::ResourcePixmap:
272 slotSetResourceActivated();
273 break;
274 case PropertySheetPixmapValue::FilePixmap:
275 slotSetFileActivated();
276 break;
277 }
278}
279
280// Choose a pixmap from resource; use language-dependent resource browser if present
281QString IconSelector::choosePixmapResource(QDesignerFormEditorInterface *core, QtResourceModel *resourceModel, const QString &oldPath, QWidget *parent)
282{
283 Q_UNUSED(resourceModel)
284 QString rc;
285
286 if (LanguageResourceDialog* ldlg = LanguageResourceDialog::create(core, parent)) {
287 ldlg->setCurrentPath(oldPath);
288 if (ldlg->exec() == QDialog::Accepted)
289 rc = ldlg->currentPath();
290 delete ldlg;
291 } else {
292 QtResourceViewDialog dlg(core, parent);
293
294 QDesignerIntegration *designerIntegration = qobject_cast<QDesignerIntegration *>(core->integration());
295 if (designerIntegration)
296 dlg.setResourceEditingEnabled(designerIntegration->isResourceEditingEnabled());
297
298 dlg.selectResource(oldPath);
299 if (dlg.exec() == QDialog::Accepted)
300 rc = dlg.selectedResource();
301 }
302 return rc;
303}
304
305void IconSelectorPrivate::slotSetResourceActivated()
306{
307 const QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
308
309 PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
310 const QString oldPath = pixmap.path();
311 const QString newPath = IconSelector::choosePixmapResource(m_core, m_resourceModel, oldPath, q_ptr);
312 if (newPath.isEmpty() || newPath == oldPath)
313 return;
314 const PropertySheetPixmapValue newPixmap = PropertySheetPixmapValue(newPath);
315 if (newPixmap != pixmap) {
316 m_icon.setPixmap(state.first, state.second, newPixmap);
317 slotUpdate();
318 emit q_ptr->iconChanged(m_icon);
319 }
320}
321
322// Helpers for choosing image files: Check for valid image.
323bool IconSelector::checkPixmap(const QString &fileName, CheckMode cm, QString *errorMessage)
324{
325 const QFileInfo fi(fileName);
326 if (!fi.exists() || !fi.isFile() || !fi.isReadable()) {
327 if (errorMessage)
328 *errorMessage = tr("The pixmap file '%1' cannot be read.").arg(fileName);
329 return false;
330 }
331 QImageReader reader(fileName);
332 if (!reader.canRead()) {
333 if (errorMessage)
334 *errorMessage = tr("The file '%1' does not appear to be a valid pixmap file: %2").arg(fileName).arg(reader.errorString());
335 return false;
336 }
337 if (cm == CheckFast)
338 return true;
339
340 const QImage image = reader.read();
341 if (image.isNull()) {
342 if (errorMessage)
343 *errorMessage = tr("The file '%1' could not be read: %2").arg(fileName).arg(reader.errorString());
344 return false;
345 }
346 return true;
347}
348
349// Helpers for choosing image files: Return an image filter for QFileDialog, courtesy of StyledButton
350static QString imageFilter()
351{
352 QString filter = QApplication::translate("IconSelector", "All Pixmaps (");
353 const QList<QByteArray> supportedImageFormats = QImageReader::supportedImageFormats();
354 const QString jpeg = QLatin1String("JPEG");
355 const int count = supportedImageFormats.count();
356 for (int i = 0; i< count; ++i) {
357 if (i)
358 filter += QLatin1Char(' ');
359 filter += QLatin1String("*.");
360 const QString outputFormat = QString::fromUtf8(supportedImageFormats.at(i));
361 if (outputFormat != jpeg)
362 filter += outputFormat.toLower();
363 else
364 filter += QLatin1String("jpg *.jpeg");
365 }
366 filter += QLatin1Char(')');
367 return filter;
368}
369
370// Helpers for choosing image files: Choose a file
371QString IconSelector::choosePixmapFile(const QString &directory, QDesignerDialogGuiInterface *dlgGui,QWidget *parent)
372{
373 QString errorMessage;
374 QString newPath;
375 do {
376 const QString title = tr("Choose a Pixmap");
377 static const QString filter = imageFilter();
378 newPath = dlgGui->getOpenImageFileName(parent, title, directory, filter);
379 if (newPath.isEmpty())
380 break;
381 if (checkPixmap(newPath, CheckFully, &errorMessage))
382 break;
383 dlgGui->message(parent, QDesignerDialogGuiInterface::ResourceEditorMessage, QMessageBox::Warning, tr("Pixmap Read Error"), errorMessage);
384 } while(true);
385 return newPath;
386}
387
388void IconSelectorPrivate::slotSetFileActivated()
389{
390 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
391
392 PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
393 const QString newPath = IconSelector::choosePixmapFile(pixmap.path(), m_core->dialogGui(), q_ptr);
394 if (!newPath.isEmpty()) {
395 const PropertySheetPixmapValue newPixmap = PropertySheetPixmapValue(newPath);
396 if (!(newPixmap == pixmap)) {
397 m_icon.setPixmap(state.first, state.second, newPixmap);
398 slotUpdate();
399 emit q_ptr->iconChanged(m_icon);
400 }
401 }
402}
403
404void IconSelectorPrivate::slotResetActivated()
405{
406 QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
407
408 PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
409 const PropertySheetPixmapValue newPixmap;
410 if (!(newPixmap == pixmap)) {
411 m_icon.setPixmap(state.first, state.second, newPixmap);
412 slotUpdate();
413 emit q_ptr->iconChanged(m_icon);
414 }
415}
416
417void IconSelectorPrivate::slotResetAllActivated()
418{
419 const PropertySheetIconValue newIcon;
420 if (!(m_icon == newIcon)) {
421 m_icon = newIcon;
422 slotUpdate();
423 emit q_ptr->iconChanged(m_icon);
424 }
425}
426
427// ------------- IconSelector
428IconSelector::IconSelector(QWidget *parent) :
429 QWidget(parent), d_ptr(new IconSelectorPrivate())
430{
431 d_ptr->q_ptr = this;
432
433 d_ptr->m_stateComboBox = new QComboBox(this);
434
435 QHBoxLayout *l = new QHBoxLayout(this);
436 d_ptr->m_iconButton = new QToolButton(this);
437 d_ptr->m_iconButton->setText(tr("..."));
438 d_ptr->m_iconButton->setPopupMode(QToolButton::MenuButtonPopup);
439 l->addWidget(d_ptr->m_stateComboBox);
440 l->addWidget(d_ptr->m_iconButton);
441 l->setMargin(0);
442
443 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Normal, QIcon::Off), tr("Normal Off") );
444 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Normal, QIcon::On), tr("Normal On") );
445 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Disabled, QIcon::Off), tr("Disabled Off") );
446 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Disabled, QIcon::On), tr("Disabled On") );
447 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Active, QIcon::Off), tr("Active Off") );
448 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Active, QIcon::On), tr("Active On") );
449 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::Off), tr("Selected Off") );
450 d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::On), tr("Selected On") );
451
452 QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
453 img.fill(0);
454 d_ptr->m_emptyIcon = QIcon(QPixmap::fromImage(img));
455
456 QMenu *setMenu = new QMenu(this);
457
458 QAction *setResourceAction = new QAction(tr("Choose Resource..."), this);
459 QAction *setFileAction = new QAction(tr("Choose File..."), this);
460 d_ptr->m_resetAction = new QAction(tr("Reset"), this);
461 d_ptr->m_resetAllAction = new QAction(tr("Reset All"), this);
462 d_ptr->m_resetAction->setEnabled(false);
463 d_ptr->m_resetAllAction->setEnabled(false);
464 //d_ptr->m_resetAction->setIcon(createIconSet(QString::fromUtf8("resetproperty.png")));
465
466 setMenu->addAction(setResourceAction);
467 setMenu->addAction(setFileAction);
468 setMenu->addSeparator();
469 setMenu->addAction(d_ptr->m_resetAction);
470 setMenu->addAction(d_ptr->m_resetAllAction);
471
472 int index = 0;
473 QStringList items;
474 QListIterator<QPair<QPair<QIcon::Mode, QIcon::State>, QString> > itName(d_ptr->m_stateToName);
475 while (itName.hasNext()) {
476 QPair<QPair<QIcon::Mode, QIcon::State>, QString> item = itName.next();
477 const QPair<QIcon::Mode, QIcon::State> state = item.first;
478 const QString name = item.second;
479
480 items.append(name);
481 d_ptr->m_stateToIndex[state] = index;
482 d_ptr->m_indexToState[index] = state;
483 index++;
484 }
485 d_ptr->m_stateComboBox->addItems(items);
486
487 d_ptr->m_iconButton->setMenu(setMenu);
488
489 connect(d_ptr->m_stateComboBox, SIGNAL(activated(int)), this, SLOT(slotStateActivated()));
490 connect(d_ptr->m_iconButton, SIGNAL(clicked()), this, SLOT(slotSetActivated()));
491 connect(setResourceAction, SIGNAL(triggered()), this, SLOT(slotSetResourceActivated()));
492 connect(setFileAction, SIGNAL(triggered()), this, SLOT(slotSetFileActivated()));
493 connect(d_ptr->m_resetAction, SIGNAL(triggered()), this, SLOT(slotResetActivated()));
494 connect(d_ptr->m_resetAllAction, SIGNAL(triggered()), this, SLOT(slotResetAllActivated()));
495
496 d_ptr->slotUpdate();
497}
498
499IconSelector::~IconSelector()
500{
501}
502
503void IconSelector::setIcon(const PropertySheetIconValue &icon)
504{
505 if (d_ptr->m_icon == icon)
506 return;
507
508 d_ptr->m_icon = icon;
509 d_ptr->slotUpdate();
510}
511
512PropertySheetIconValue IconSelector::icon() const
513{
514 return d_ptr->m_icon;
515}
516
517void IconSelector::setFormEditor(QDesignerFormEditorInterface *core)
518{
519 d_ptr->m_core = core;
520 d_ptr->m_resourceModel = core->resourceModel();
521 d_ptr->slotUpdate();
522}
523
524void IconSelector::setIconCache(DesignerIconCache *iconCache)
525{
526 d_ptr->m_iconCache = iconCache;
527 connect(iconCache, SIGNAL(reloaded()), this, SLOT(slotUpdate()));
528 d_ptr->slotUpdate();
529}
530
531void IconSelector::setPixmapCache(DesignerPixmapCache *pixmapCache)
532{
533 d_ptr->m_pixmapCache = pixmapCache;
534 connect(pixmapCache, SIGNAL(reloaded()), this, SLOT(slotUpdate()));
535 d_ptr->slotUpdate();
536}
537
538} // qdesigner_internal
539
540QT_END_NAMESPACE
541
542#include "moc_iconselector_p.cpp"
543
Note: See TracBrowser for help on using the repository browser.