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