source: trunk/tools/designer/src/lib/shared/qtresourceview.cpp@ 846

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

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 31.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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 "abstractsettings_p.h"
43#include "qtresourceview_p.h"
44#include "qtresourcemodel_p.h"
45#include "qtresourceeditordialog_p.h"
46#include "iconloader_p.h"
47#include "filterwidget_p.h" // For FilterWidget
48
49#include <QtDesigner/QDesignerFormEditorInterface>
50
51#include <QtGui/QToolBar>
52#include <QtGui/QAction>
53#include <QtGui/QSplitter>
54#include <QtGui/QTreeWidget>
55#include <QtGui/QListWidget>
56#include <QtGui/QHeaderView>
57#include <QtGui/QVBoxLayout>
58#include <QtGui/QPainter>
59#include <QtCore/QFileInfo>
60#include <QtCore/QDir>
61#include <QtCore/QQueue>
62#include <QtGui/QPainter>
63#include <QtGui/QDialogButtonBox>
64#include <QtGui/QPushButton>
65#include <QtGui/QMessageBox>
66#include <QtGui/QApplication>
67#include <QtGui/QClipboard>
68#include <QtGui/QMenu>
69#include <QtGui/QDrag>
70#include <QtCore/QMimeData>
71#include <QtXml/QDomDocument>
72
73QT_BEGIN_NAMESPACE
74
75static const char *elementResourceData = "resource";
76static const char *typeAttribute = "type";
77static const char *typeImage = "image";
78static const char *typeStyleSheet = "stylesheet";
79static const char *typeOther = "other";
80static const char *fileAttribute = "file";
81static const char *SplitterPosition = "SplitterPosition";
82static const char *Geometry = "Geometry";
83static const char *ResourceViewDialogC = "ResourceDialog";
84
85// ---------------- ResourceListWidget: A list widget that has drag enabled
86class ResourceListWidget : public QListWidget {
87public:
88 ResourceListWidget(QWidget *parent = 0);
89
90protected:
91 virtual void startDrag(Qt::DropActions supportedActions);
92};
93
94ResourceListWidget::ResourceListWidget(QWidget *parent) :
95 QListWidget(parent)
96{
97#ifndef QT_NO_DRAGANDDROP
98 setDragEnabled(true);
99#endif
100}
101
102void ResourceListWidget::startDrag(Qt::DropActions supportedActions)
103{
104 if (supportedActions == Qt::MoveAction)
105 return;
106
107 QListWidgetItem *item = currentItem();
108 if (!item)
109 return;
110
111#ifndef QT_NO_DRAGANDDROP
112 const QString filePath = item->data(Qt::UserRole).toString();
113 const QIcon icon = item->icon();
114
115 QMimeData *mimeData = new QMimeData;
116 const QtResourceView::ResourceType type = icon.isNull() ? QtResourceView::ResourceOther : QtResourceView::ResourceImage;
117 mimeData->setText(QtResourceView::encodeMimeData(type , filePath));
118
119 QDrag *drag = new QDrag(this);
120 if (!icon.isNull()) {
121 const QSize size = icon.actualSize(iconSize());
122 drag->setPixmap(icon.pixmap(size));
123 drag->setHotSpot(QPoint(size.width() / 2, size.height() / 2));
124 }
125
126 drag->setMimeData(mimeData);
127 drag->exec(Qt::CopyAction);
128#endif
129}
130
131/* TODO
132
133 1) load the icons in separate thread...Hmm..if Qt is configured with threads....
134*/
135
136// ---------------------------- QtResourceViewPrivate
137class QtResourceViewPrivate
138{
139 QtResourceView *q_ptr;
140 Q_DECLARE_PUBLIC(QtResourceView)
141public:
142 QtResourceViewPrivate(QDesignerFormEditorInterface *core);
143
144 void slotResourceSetActivated(QtResourceSet *resourceSet);
145 void slotCurrentPathChanged(QTreeWidgetItem *);
146 void slotCurrentResourceChanged(QListWidgetItem *);
147 void slotResourceActivated(QListWidgetItem *);
148 void slotEditResources();
149 void slotReloadResources();
150 void slotCopyResourcePath();
151 void slotListWidgetContextMenuRequested(const QPoint &pos);
152 void slotFilterChanged(const QString &pattern);
153 void createPaths();
154 QTreeWidgetItem *createPath(const QString &path, QTreeWidgetItem *parent);
155 void createResources(const QString &path);
156 void storeExpansionState();
157 void applyExpansionState();
158 void restoreSettings();
159 void saveSettings();
160 void updateActions();
161 void filterOutResources();
162
163 QPixmap makeThumbnail(const QPixmap &pix) const;
164
165 QDesignerFormEditorInterface *m_core;
166 QtResourceModel *m_resourceModel;
167 QToolBar *m_toolBar;
168 qdesigner_internal::FilterWidget *m_filterWidget;
169 QTreeWidget *m_treeWidget;
170 QListWidget *m_listWidget;
171 QSplitter *m_splitter;
172 QMap<QString, QStringList> m_pathToContents; // full path to contents file names (full path to its resource filenames)
173 QMap<QString, QString> m_pathToParentPath; // full path to full parent path
174 QMap<QString, QStringList> m_pathToSubPaths; // full path to full sub paths
175 QMap<QString, QTreeWidgetItem *> m_pathToItem;
176 QMap<QTreeWidgetItem *, QString> m_itemToPath;
177 QMap<QString, QListWidgetItem *> m_resourceToItem;
178 QMap<QListWidgetItem *, QString> m_itemToResource;
179 QAction *m_editResourcesAction;
180 QAction *m_reloadResourcesAction;
181 QAction *m_copyResourcePathAction;
182
183 QMap<QString, bool> m_expansionState;
184
185 bool m_ignoreGuiSignals;
186 QString m_settingsKey;
187 bool m_resourceEditingEnabled;
188 QString m_filterPattern;
189};
190
191QtResourceViewPrivate::QtResourceViewPrivate(QDesignerFormEditorInterface *core) :
192 q_ptr(0),
193 m_core(core),
194 m_resourceModel(0),
195 m_toolBar(new QToolBar),
196 m_treeWidget(new QTreeWidget),
197 m_listWidget(new ResourceListWidget),
198 m_splitter(0),
199 m_editResourcesAction(0),
200 m_reloadResourcesAction(0),
201 m_copyResourcePathAction(0),
202 m_ignoreGuiSignals(false),
203 m_resourceEditingEnabled(true)
204{
205}
206
207void QtResourceViewPrivate::restoreSettings()
208{
209 if (m_settingsKey.isEmpty())
210 return;
211
212 QDesignerSettingsInterface *settings = m_core->settingsManager();
213 settings->beginGroup(m_settingsKey);
214
215 m_splitter->restoreState(settings->value(QLatin1String(SplitterPosition)).toByteArray());
216 settings->endGroup();
217}
218
219void QtResourceViewPrivate::saveSettings()
220{
221 if (m_settingsKey.isEmpty())
222 return;
223
224 QDesignerSettingsInterface *settings = m_core->settingsManager();
225 settings->beginGroup(m_settingsKey);
226
227 settings->setValue(QLatin1String(SplitterPosition), m_splitter->saveState());
228 settings->endGroup();
229}
230
231void QtResourceViewPrivate::slotEditResources()
232{
233 const QString selectedResource
234 = QtResourceEditorDialog::editResources(m_core, m_resourceModel,
235 m_core->dialogGui(), q_ptr);
236 if (!selectedResource.isEmpty())
237 q_ptr->selectResource(selectedResource);
238}
239
240void QtResourceViewPrivate::slotReloadResources()
241{
242 if (m_resourceModel) {
243 int errorCount;
244 QString errorMessages;
245 m_resourceModel->reload(&errorCount, &errorMessages);
246 if (errorCount)
247 QtResourceEditorDialog::displayResourceFailures(errorMessages, m_core->dialogGui(), q_ptr);
248 }
249}
250
251void QtResourceViewPrivate::slotCopyResourcePath()
252{
253 const QString path = q_ptr->selectedResource();
254 QClipboard *clipboard = QApplication::clipboard();
255 clipboard->setText(path);
256}
257
258void QtResourceViewPrivate::slotListWidgetContextMenuRequested(const QPoint &pos)
259{
260 QMenu menu(q_ptr);
261 menu.addAction(m_copyResourcePathAction);
262 menu.exec(m_listWidget->mapToGlobal(pos));
263}
264
265void QtResourceViewPrivate::slotFilterChanged(const QString &pattern)
266{
267 m_filterPattern = pattern;
268 filterOutResources();
269}
270
271void QtResourceViewPrivate::storeExpansionState()
272{
273 QMapIterator<QString, QTreeWidgetItem *> it(m_pathToItem);
274 while (it.hasNext()) {
275 it.next();
276 m_expansionState[it.key()] = it.value()->isExpanded();
277 }
278}
279
280void QtResourceViewPrivate::applyExpansionState()
281{
282 QMapIterator<QString, QTreeWidgetItem *> it(m_pathToItem);
283 while (it.hasNext()) {
284 it.next();
285 it.value()->setExpanded(m_expansionState.value(it.key(), true));
286 }
287}
288
289QPixmap QtResourceViewPrivate::makeThumbnail(const QPixmap &pix) const
290{
291 int w = qMax(48, pix.width());
292 int h = qMax(48, pix.height());
293 QRect imgRect(0, 0, w, h);
294 QImage img(w, h, QImage::Format_ARGB32_Premultiplied);
295 img.fill(0);
296 if (!pix.isNull()) {
297 QRect r(0, 0, pix.width(), pix.height());
298 r.moveCenter(imgRect.center());
299 QPainter p(&img);
300 p.drawPixmap(r.topLeft(), pix);
301 }
302 return QPixmap::fromImage(img);
303}
304
305void QtResourceViewPrivate::updateActions()
306{
307 bool resourceActive = false;
308 if (m_resourceModel)
309 resourceActive = m_resourceModel->currentResourceSet();
310
311 m_editResourcesAction->setVisible(m_resourceEditingEnabled);
312 m_editResourcesAction->setEnabled(resourceActive);
313 m_reloadResourcesAction->setEnabled(resourceActive);
314 m_filterWidget->setEnabled(resourceActive);
315}
316
317void QtResourceViewPrivate::slotResourceSetActivated(QtResourceSet *resourceSet)
318{
319 Q_UNUSED(resourceSet)
320
321 updateActions();
322
323 storeExpansionState();
324 const QString currentPath = m_itemToPath.value(m_treeWidget->currentItem());
325 const QString currentResource = m_itemToResource.value(m_listWidget->currentItem());
326 m_treeWidget->clear();
327 m_pathToContents.clear();
328 m_pathToParentPath.clear();
329 m_pathToSubPaths.clear();
330 m_pathToItem.clear();
331 m_itemToPath.clear();
332 m_listWidget->clear();
333 m_resourceToItem.clear();
334 m_itemToResource.clear();
335
336 createPaths();
337 applyExpansionState();
338
339 if (!currentResource.isEmpty())
340 q_ptr->selectResource(currentResource);
341 else if (!currentPath.isEmpty())
342 q_ptr->selectResource(currentPath);
343 filterOutResources();
344}
345
346void QtResourceViewPrivate::slotCurrentPathChanged(QTreeWidgetItem *item)
347{
348 if (m_ignoreGuiSignals)
349 return;
350
351 m_listWidget->clear();
352 m_resourceToItem.clear();
353 m_itemToResource.clear();
354
355 if (!item)
356 return;
357
358 const QString currentPath = m_itemToPath.value(item);
359 createResources(currentPath);
360}
361
362void QtResourceViewPrivate::slotCurrentResourceChanged(QListWidgetItem *item)
363{
364 m_copyResourcePathAction->setEnabled(item);
365 if (m_ignoreGuiSignals)
366 return;
367
368 emit q_ptr->resourceSelected(m_itemToResource.value(item));
369}
370
371void QtResourceViewPrivate::slotResourceActivated(QListWidgetItem *item)
372{
373 if (m_ignoreGuiSignals)
374 return;
375
376 emit q_ptr->resourceActivated(m_itemToResource.value(item));
377}
378
379void QtResourceViewPrivate::createPaths()
380{
381 if (!m_resourceModel)
382 return;
383
384 // Resource root up until 4.6 was ':', changed to ":/" as of 4.7
385 const QString root(QLatin1String(":/"));
386
387 QMap<QString, QString> contents = m_resourceModel->contents();
388 QMapIterator<QString, QString> itContents(contents);
389 while (itContents.hasNext()) {
390 const QString filePath = itContents.next().key();
391 const QFileInfo fi(filePath);
392 QString dirPath = fi.absolutePath();
393 m_pathToContents[dirPath].append(fi.fileName());
394 while (!m_pathToParentPath.contains(dirPath) && dirPath != root) { // create all parent paths
395 const QFileInfo fd(dirPath);
396 const QString parentDirPath = fd.absolutePath();
397 m_pathToParentPath[dirPath] = parentDirPath;
398 m_pathToSubPaths[parentDirPath].append(dirPath);
399 dirPath = parentDirPath;
400 }
401 }
402
403 QQueue<QPair<QString, QTreeWidgetItem *> > pathToParentItemQueue;
404 pathToParentItemQueue.enqueue(qMakePair(root, static_cast<QTreeWidgetItem *>(0)));
405 while (!pathToParentItemQueue.isEmpty()) {
406 QPair<QString, QTreeWidgetItem *> pathToParentItem = pathToParentItemQueue.dequeue();
407 const QString path = pathToParentItem.first;
408 QTreeWidgetItem *item = createPath(path, pathToParentItem.second);
409 QStringList subPaths = m_pathToSubPaths.value(path);
410 QStringListIterator itSubPaths(subPaths);
411 while (itSubPaths.hasNext())
412 pathToParentItemQueue.enqueue(qMakePair(itSubPaths.next(), item));
413 }
414}
415
416void QtResourceViewPrivate::filterOutResources()
417{
418 QMap<QString, bool> pathToMatchingContents; // true means the path has any matching contents
419 QMap<QString, bool> pathToVisible; // true means the path has to be shown
420
421 // 1) we go from root path recursively.
422 // 2) we check every path if it contains at least one matching resource - if empty we add it
423 // to pathToMatchingContents and pathToVisible with false, if non empty
424 // we add it with true and change every parent path in pathToVisible to true.
425 // 3) we hide these items which has pathToVisible value false.
426
427 const bool matchAll = m_filterPattern.isEmpty();
428 const QString root(QLatin1String(":/"));
429
430 QQueue<QString> pathQueue;
431 pathQueue.enqueue(root);
432 while (!pathQueue.isEmpty()) {
433 const QString path = pathQueue.dequeue();
434
435 QStringList fileNames = m_pathToContents.value(path);
436 QStringListIterator it(fileNames);
437 bool hasContents = matchAll;
438 if (!matchAll) { // the case filter is not empty - we check if the path contains anything
439 while (it.hasNext()) {
440 QString fileName = it.next();
441 hasContents = fileName.contains(m_filterPattern, Qt::CaseInsensitive);
442 if (hasContents) // the path contains at least one resource which matches the filter
443 break;
444 }
445 }
446
447 pathToMatchingContents[path] = hasContents;
448 pathToVisible[path] = hasContents;
449
450 if (hasContents) { // if the path is going to be shown we need to show all its parent paths
451 QString parentPath = m_pathToParentPath.value(path);
452 while (!parentPath.isEmpty()) {
453 QString p = parentPath;
454 if (pathToVisible.value(p)) // parent path is already shown, we break the loop
455 break;
456 pathToVisible[p] = true;
457 parentPath = m_pathToParentPath.value(p);
458 }
459 }
460
461 QStringList subPaths = m_pathToSubPaths.value(path); // we do the same for children paths
462 QStringListIterator itSubPaths(subPaths);
463 while (itSubPaths.hasNext())
464 pathQueue.enqueue(itSubPaths.next());
465 }
466
467 // we setup here new path and resource to be activated
468 const QString currentPath = m_itemToPath.value(m_treeWidget->currentItem());
469 QString newCurrentPath = currentPath;
470 QString currentResource = m_itemToResource.value(m_listWidget->currentItem());
471 if (!matchAll) {
472 bool searchForNewPathWithContents = true;
473
474 if (!currentPath.isEmpty()) { // if the currentPath is empty we will search for a new path too
475 QMap<QString, bool>::ConstIterator it = pathToMatchingContents.constFind(currentPath);
476 if (it != pathToMatchingContents.constEnd() && it.value()) // the current item has contents, we don't need to search for another path
477 searchForNewPathWithContents = false;
478 }
479
480 if (searchForNewPathWithContents) {
481 // we find the first path with the matching contents
482 QMap<QString, bool>::ConstIterator itContents = pathToMatchingContents.constBegin();
483 while (itContents != pathToMatchingContents.constEnd()) {
484 if (itContents.value()) {
485 newCurrentPath = itContents.key(); // the new path will be activated
486 break;
487 }
488
489 itContents++;
490 }
491 }
492
493 QFileInfo fi(currentResource);
494 if (!fi.fileName().contains(m_filterPattern, Qt::CaseInsensitive)) { // the case when the current resource is filtered out
495 const QStringList fileNames = m_pathToContents.value(newCurrentPath);
496 QStringListIterator it(fileNames);
497 while (it.hasNext()) { // we try to select the first matching resource from the newCurrentPath
498 QString fileName = it.next();
499 if (fileName.contains(m_filterPattern, Qt::CaseInsensitive)) {
500 QDir dirPath(newCurrentPath);
501 currentResource = dirPath.absoluteFilePath(fileName); // the new resource inside newCurrentPath will be activated
502 break;
503 }
504 }
505 }
506 }
507
508 QTreeWidgetItem *newCurrentItem = m_pathToItem.value(newCurrentPath);
509 if (currentPath != newCurrentPath)
510 m_treeWidget->setCurrentItem(newCurrentItem);
511 else
512 slotCurrentPathChanged(newCurrentItem); // trigger filtering on the current path
513
514 QListWidgetItem *currentResourceItem = m_resourceToItem.value(currentResource);
515 if (currentResourceItem) {
516 m_listWidget->setCurrentItem(currentResourceItem);
517 m_listWidget->scrollToItem(currentResourceItem);
518 }
519
520 QMapIterator<QString, bool> it(pathToVisible); // hide all paths filtered out
521 while (it.hasNext()) {
522 const QString path = it.next().key();
523 QTreeWidgetItem *item = m_pathToItem.value(path);
524 if (item)
525 item->setHidden(!it.value());
526 }
527}
528
529QTreeWidgetItem *QtResourceViewPrivate::createPath(const QString &path, QTreeWidgetItem *parent)
530{
531 QTreeWidgetItem *item = 0;
532 if (parent)
533 item = new QTreeWidgetItem(parent);
534 else
535 item = new QTreeWidgetItem(m_treeWidget);
536 m_pathToItem[path] = item;
537 m_itemToPath[item] = path;
538 QString substPath;
539 if (parent) {
540 QFileInfo di(path);
541 substPath = di.fileName();
542 } else {
543 substPath = QLatin1String("<resource root>");
544 }
545 item->setText(0, substPath);
546 item->setToolTip(0, path);
547 return item;
548}
549
550void QtResourceViewPrivate::createResources(const QString &path)
551{
552 const bool matchAll = m_filterPattern.isEmpty();
553
554 QDir dir(path);
555 QStringList fileNames = m_pathToContents.value(path);
556 QStringListIterator it(fileNames);
557 while (it.hasNext()) {
558 QString fileName = it.next();
559 const bool showProperty = matchAll || fileName.contains(m_filterPattern, Qt::CaseInsensitive);
560 if (showProperty) {
561 QString filePath = dir.absoluteFilePath(fileName);
562 QFileInfo fi(filePath);
563 if (fi.isFile()) {
564 QListWidgetItem *item = new QListWidgetItem(fi.fileName(), m_listWidget);
565 const QPixmap pix = QPixmap(filePath);
566 if (pix.isNull()) {
567 item->setToolTip(filePath);
568 } else {
569 item->setIcon(QIcon(makeThumbnail(pix)));
570 const QSize size = pix.size();
571 item->setToolTip(QtResourceView::tr("Size: %1 x %2\n%3").arg(size.width()).arg(size.height()).arg(filePath));
572 }
573 item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
574 item->setData(Qt::UserRole, filePath);
575 m_itemToResource[item] = filePath;
576 m_resourceToItem[filePath] = item;
577 }
578 }
579 }
580}
581
582// -------------- QtResourceView
583
584QtResourceView::QtResourceView(QDesignerFormEditorInterface *core, QWidget *parent) :
585 QWidget(parent),
586 d_ptr(new QtResourceViewPrivate(core))
587{
588 d_ptr->q_ptr = this;
589
590 QIcon editIcon = QIcon::fromTheme("document-properties", qdesigner_internal::createIconSet(QLatin1String("edit.png")));
591 d_ptr->m_editResourcesAction = new QAction(editIcon, tr("Edit Resources..."), this);
592 d_ptr->m_toolBar->addAction(d_ptr->m_editResourcesAction);
593 connect(d_ptr->m_editResourcesAction, SIGNAL(triggered()), this, SLOT(slotEditResources()));
594 d_ptr->m_editResourcesAction->setEnabled(false);
595
596 QIcon refreshIcon = QIcon::fromTheme("view-refresh", qdesigner_internal::createIconSet(QLatin1String("reload.png")));
597 d_ptr->m_reloadResourcesAction = new QAction(refreshIcon, tr("Reload"), this);
598
599 d_ptr->m_toolBar->addAction(d_ptr->m_reloadResourcesAction);
600 connect(d_ptr->m_reloadResourcesAction, SIGNAL(triggered()), this, SLOT(slotReloadResources()));
601 d_ptr->m_reloadResourcesAction->setEnabled(false);
602
603 QIcon copyIcon = QIcon::fromTheme("edit-copy", qdesigner_internal::createIconSet(QLatin1String("editcopy.png")));
604 d_ptr->m_copyResourcePathAction = new QAction(copyIcon, tr("Copy Path"), this);
605 connect(d_ptr->m_copyResourcePathAction, SIGNAL(triggered()), this, SLOT(slotCopyResourcePath()));
606 d_ptr->m_copyResourcePathAction->setEnabled(false);
607
608 //d_ptr->m_filterWidget = new qdesigner_internal::FilterWidget(0, qdesigner_internal::FilterWidget::LayoutAlignNone);
609 d_ptr->m_filterWidget = new qdesigner_internal::FilterWidget(d_ptr->m_toolBar);
610 d_ptr->m_toolBar->addWidget(d_ptr->m_filterWidget);
611 connect(d_ptr->m_filterWidget, SIGNAL(filterChanged(QString)), this, SLOT(slotFilterChanged(QString)));
612
613 d_ptr->m_splitter = new QSplitter;
614 d_ptr->m_splitter->setChildrenCollapsible(false);
615 d_ptr->m_splitter->addWidget(d_ptr->m_treeWidget);
616 d_ptr->m_splitter->addWidget(d_ptr->m_listWidget);
617
618 QLayout *layout = new QVBoxLayout(this);
619 layout->setMargin(0);
620 layout->setSpacing(0);
621 layout->addWidget(d_ptr->m_toolBar);
622 layout->addWidget(d_ptr->m_splitter);
623
624 d_ptr->m_treeWidget->setColumnCount(1);
625 d_ptr->m_treeWidget->header()->hide();
626 d_ptr->m_treeWidget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
627
628 d_ptr->m_listWidget->setViewMode(QListView::IconMode);
629 d_ptr->m_listWidget->setResizeMode(QListView::Adjust);
630 d_ptr->m_listWidget->setIconSize(QSize(48, 48));
631 d_ptr->m_listWidget->setGridSize(QSize(64, 64));
632
633 connect(d_ptr->m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
634 this, SLOT(slotCurrentPathChanged(QTreeWidgetItem*)));
635 connect(d_ptr->m_listWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
636 this, SLOT(slotCurrentResourceChanged(QListWidgetItem*)));
637 connect(d_ptr->m_listWidget, SIGNAL(itemActivated(QListWidgetItem*)),
638 this, SLOT(slotResourceActivated(QListWidgetItem*)));
639 d_ptr->m_listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
640 connect(d_ptr->m_listWidget, SIGNAL(customContextMenuRequested(QPoint)),
641 this, SLOT(slotListWidgetContextMenuRequested(QPoint)));
642}
643
644QtResourceView::~QtResourceView()
645{
646 if (!d_ptr->m_settingsKey.isEmpty())
647 d_ptr->saveSettings();
648}
649
650bool QtResourceView::event(QEvent *event)
651{
652 if (event->type() == QEvent::Show) {
653 d_ptr->m_listWidget->scrollToItem(d_ptr->m_listWidget->currentItem());
654 d_ptr->m_treeWidget->scrollToItem(d_ptr->m_treeWidget->currentItem());
655 }
656 return QWidget::event(event);
657}
658
659QtResourceModel *QtResourceView::model() const
660{
661 return d_ptr->m_resourceModel;
662}
663
664QString QtResourceView::selectedResource() const
665{
666 QListWidgetItem *item = d_ptr->m_listWidget->currentItem();
667 return d_ptr->m_itemToResource.value(item);
668}
669
670void QtResourceView::selectResource(const QString &resource)
671{
672 if (resource.isEmpty())
673 return;
674 QFileInfo fi(resource);
675 QDir dir = fi.absoluteDir();
676 if (fi.isDir())
677 dir = QDir(resource);
678 QString dirPath = dir.absolutePath();
679 QMap<QString, QTreeWidgetItem *>::const_iterator it;
680 while ((it = d_ptr->m_pathToItem.find(dirPath)) == d_ptr->m_pathToItem.constEnd()) {
681 if (!dir.cdUp())
682 break;
683 dirPath = dir.absolutePath();
684 }
685 if (it != d_ptr->m_pathToItem.constEnd()) {
686 QTreeWidgetItem *treeItem = it.value();
687 d_ptr->m_treeWidget->setCurrentItem(treeItem);
688 d_ptr->m_treeWidget->scrollToItem(treeItem);
689 // expand all up to current one is done by qt
690 // list widget is already propagated (currrent changed was sent by qt)
691 QListWidgetItem *item = d_ptr->m_resourceToItem.value(resource);
692 if (item) {
693 d_ptr->m_listWidget->setCurrentItem(item);
694 d_ptr->m_listWidget->scrollToItem(item);
695 }
696 }
697}
698
699QString QtResourceView::settingsKey() const
700{
701 return d_ptr->m_settingsKey;
702}
703
704void QtResourceView::setSettingsKey(const QString &key)
705{
706 if (d_ptr->m_settingsKey == key)
707 return;
708
709 d_ptr->m_settingsKey = key;
710
711 if (key.isEmpty())
712 return;
713
714 d_ptr->restoreSettings();
715}
716
717void QtResourceView::setResourceModel(QtResourceModel *model)
718{
719 if (d_ptr->m_resourceModel) {
720 disconnect(d_ptr->m_resourceModel, SIGNAL(resourceSetActivated(QtResourceSet*,bool)),
721 this, SLOT(slotResourceSetActivated(QtResourceSet*)));
722 }
723
724 // clear here
725 d_ptr->m_treeWidget->clear();
726 d_ptr->m_listWidget->clear();
727
728 d_ptr->m_resourceModel = model;
729
730 if (!d_ptr->m_resourceModel)
731 return;
732
733 connect(d_ptr->m_resourceModel, SIGNAL(resourceSetActivated(QtResourceSet*,bool)),
734 this, SLOT(slotResourceSetActivated(QtResourceSet*)));
735
736 // fill new here
737 d_ptr->slotResourceSetActivated(d_ptr->m_resourceModel->currentResourceSet());
738}
739
740bool QtResourceView::isResourceEditingEnabled() const
741{
742 return d_ptr->m_resourceEditingEnabled;
743}
744
745void QtResourceView::setResourceEditingEnabled(bool enable)
746{
747 d_ptr->m_resourceEditingEnabled = enable;
748 d_ptr->updateActions();
749}
750
751void QtResourceView::setDragEnabled(bool dragEnabled)
752{
753#ifndef QT_NO_DRAGANDDROP
754 d_ptr->m_listWidget->setDragEnabled(dragEnabled);
755#endif
756}
757
758bool QtResourceView::dragEnabled() const
759{
760#ifndef QT_NO_DRAGANDDROP
761 return d_ptr->m_listWidget->dragEnabled();
762#endif
763}
764
765QString QtResourceView::encodeMimeData(ResourceType resourceType, const QString &path)
766{
767 QDomDocument doc;
768 QDomElement elem = doc.createElement(QLatin1String(elementResourceData));
769 switch (resourceType) {
770 case ResourceImage:
771 elem.setAttribute(QLatin1String(typeAttribute), QLatin1String(typeImage));
772 break;
773 case ResourceStyleSheet:
774 elem.setAttribute(QLatin1String(typeAttribute), QLatin1String(typeStyleSheet));
775 break;
776 case ResourceOther:
777 elem.setAttribute(QLatin1String(typeAttribute), QLatin1String(typeOther));
778 break;
779 }
780 elem.setAttribute(QLatin1String(fileAttribute), path);
781 doc.appendChild(elem);
782 return doc.toString();
783}
784
785bool QtResourceView::decodeMimeData(const QMimeData *md, ResourceType *t, QString *file)
786{
787 return md->hasText() ? decodeMimeData(md->text(), t, file) : false;
788}
789
790bool QtResourceView::decodeMimeData(const QString &text, ResourceType *t, QString *file)
791{
792
793 const QString docElementName = QLatin1String(elementResourceData);
794 static const QString docElementString = QLatin1Char('<') + docElementName;
795
796 if (text.isEmpty() || text.indexOf(docElementString) == -1)
797 return false;
798
799 QDomDocument doc;
800 if (!doc.setContent(text))
801 return false;
802
803 const QDomElement domElement = doc.documentElement();
804 if (domElement.tagName() != docElementName)
805 return false;
806
807 if (t) {
808 const QString typeAttr = QLatin1String(typeAttribute);
809 if (domElement.hasAttribute (typeAttr)) {
810 const QString typeValue = domElement.attribute(typeAttr, QLatin1String(typeOther));
811 if (typeValue == QLatin1String(typeImage)) {
812 *t = ResourceImage;
813 } else {
814 *t = typeValue == QLatin1String(typeStyleSheet) ? ResourceStyleSheet : ResourceOther;
815 }
816 }
817 }
818 if (file) {
819 const QString fileAttr = QLatin1String(fileAttribute);
820 if (domElement.hasAttribute(fileAttr)) {
821 *file = domElement.attribute(fileAttr, QString());
822 } else {
823 file->clear();
824 }
825 }
826 return true;
827}
828
829// ---------------------------- QtResourceViewDialogPrivate
830
831class QtResourceViewDialogPrivate
832{
833 QtResourceViewDialog *q_ptr;
834 Q_DECLARE_PUBLIC(QtResourceViewDialog)
835public:
836 QtResourceViewDialogPrivate(QDesignerFormEditorInterface *core);
837
838 void slotResourceSelected(const QString &resource) { setOkButtonEnabled(!resource.isEmpty()); }
839 void setOkButtonEnabled(bool v) { m_box->button(QDialogButtonBox::Ok)->setEnabled(v); }
840
841 QDesignerFormEditorInterface *m_core;
842 QtResourceView *m_view;
843 QDialogButtonBox *m_box;
844};
845
846QtResourceViewDialogPrivate::QtResourceViewDialogPrivate(QDesignerFormEditorInterface *core) :
847 q_ptr(0),
848 m_core(core),
849 m_view(new QtResourceView(core)),
850 m_box(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel))
851{
852 m_view->setSettingsKey(QLatin1String(ResourceViewDialogC));
853}
854
855// ------------ QtResourceViewDialog
856QtResourceViewDialog::QtResourceViewDialog(QDesignerFormEditorInterface *core, QWidget *parent) :
857 QDialog(parent),
858 d_ptr(new QtResourceViewDialogPrivate(core))
859{
860 setWindowTitle(tr("Select Resource"));
861 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
862 d_ptr->q_ptr = this;
863 QVBoxLayout *layout = new QVBoxLayout(this);
864 layout->addWidget(d_ptr->m_view);
865 layout->addWidget(d_ptr->m_box);
866 connect(d_ptr->m_box, SIGNAL(accepted()), this, SLOT(accept()));
867 connect(d_ptr->m_box, SIGNAL(rejected()), this, SLOT(reject()));
868 connect(d_ptr->m_view, SIGNAL(resourceActivated(QString)), this, SLOT(accept()));
869 connect(d_ptr->m_view, SIGNAL(resourceSelected(QString)), this, SLOT(slotResourceSelected(QString)));
870 d_ptr->setOkButtonEnabled(false);
871 d_ptr->m_view->setResourceModel(core->resourceModel());
872
873 QDesignerSettingsInterface *settings = core->settingsManager();
874 settings->beginGroup(QLatin1String(ResourceViewDialogC));
875
876 if (settings->contains(QLatin1String(Geometry)))
877 setGeometry(settings->value(QLatin1String(Geometry)).toRect());
878
879 settings->endGroup();
880}
881
882QtResourceViewDialog::~QtResourceViewDialog()
883{
884 QDesignerSettingsInterface *settings = d_ptr->m_core->settingsManager();
885 settings->beginGroup(QLatin1String(ResourceViewDialogC));
886
887 settings->setValue(QLatin1String(Geometry), geometry());
888
889 settings->endGroup();
890}
891
892QString QtResourceViewDialog::selectedResource() const
893{
894 return d_ptr->m_view->selectedResource();
895}
896
897void QtResourceViewDialog::selectResource(const QString &path)
898{
899 d_ptr->m_view->selectResource(path);
900}
901
902bool QtResourceViewDialog::isResourceEditingEnabled() const
903{
904 return d_ptr->m_view->isResourceEditingEnabled();
905}
906
907void QtResourceViewDialog::setResourceEditingEnabled(bool enable)
908{
909 d_ptr->m_view->setResourceEditingEnabled(enable);
910}
911
912QT_END_NAMESPACE
913
914#include "moc_qtresourceview_p.cpp"
Note: See TracBrowser for help on using the repository browser.