tools/designer/src/lib/shared/qtresourcemodel.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 "qtresourcemodel_p.h"
       
    43 #include <rcc.h>
       
    44 
       
    45 #include <QtCore/QStringList>
       
    46 #include <QtCore/QMap>
       
    47 #include <QtCore/QResource>
       
    48 #include <QtCore/QFileInfo>
       
    49 #include <QtCore/QIODevice>
       
    50 #include <QtCore/QDir>
       
    51 #include <QtCore/QDebug>
       
    52 #include <QtCore/QBuffer>
       
    53 #include <QtCore/QFileSystemWatcher>
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 enum { debugResourceModel = 0 };
       
    58 
       
    59 // ------------------- QtResourceSetPrivate
       
    60 class QtResourceSetPrivate
       
    61 {
       
    62     QtResourceSet *q_ptr;
       
    63     Q_DECLARE_PUBLIC(QtResourceSet)
       
    64 public:
       
    65     QtResourceSetPrivate(QtResourceModel *model = 0);
       
    66 
       
    67     QtResourceModel *m_resourceModel;
       
    68 };
       
    69 
       
    70 QtResourceSetPrivate::QtResourceSetPrivate(QtResourceModel *model) :
       
    71    q_ptr(0),
       
    72    m_resourceModel(model)
       
    73 {
       
    74 }
       
    75 
       
    76 // -------------------- QtResourceModelPrivate
       
    77 class QtResourceModelPrivate
       
    78 {
       
    79     QtResourceModel *q_ptr;
       
    80     Q_DECLARE_PUBLIC(QtResourceModel)
       
    81     Q_DISABLE_COPY(QtResourceModelPrivate)
       
    82 public:
       
    83     QtResourceModelPrivate();
       
    84     void activate(QtResourceSet *resourceSet, const QStringList &newPaths, int *errorCount = 0, QString *errorMessages = 0);
       
    85     void removeOldPaths(QtResourceSet *resourceSet, const QStringList &newPaths);
       
    86 
       
    87     QMap<QString, bool>                     m_pathToModified;
       
    88     QMap<QtResourceSet *, QStringList>      m_resourceSetToPaths;
       
    89     QMap<QtResourceSet *, bool>             m_resourceSetToReload; // while path is recreated it needs to be reregistered
       
    90                                                                    // (it is - in the new current resource set, but when the path was used in
       
    91                                                                    // other resource set
       
    92                                                                    // then later when that resource set is activated it needs to be reregistered)
       
    93     QMap<QtResourceSet *, bool>             m_newlyCreated; // all created but not activated yet
       
    94                                                             // (if was active at some point and it's not now it will not be on that map)
       
    95     QMap<QString, QList<QtResourceSet *> >  m_pathToResourceSet;
       
    96     QtResourceSet                          *m_currentResourceSet;
       
    97 
       
    98     typedef QMap<QString, const QByteArray *> PathDataMap;
       
    99     PathDataMap m_pathToData;
       
   100 
       
   101     QMap<QString, QStringList> m_pathToContents; // qrc path to its contents.
       
   102     QMap<QString, QString>     m_fileToQrc; // this map contains the content of active resource set only.
       
   103                                             // Activating different resource set changes the contents.
       
   104 
       
   105     QFileSystemWatcher *m_fileWatcher;
       
   106     bool m_fileWatcherEnabled;
       
   107     QMap<QString, bool> m_fileWatchedMap;
       
   108 private:
       
   109     void registerResourceSet(QtResourceSet *resourceSet);
       
   110     void unregisterResourceSet(QtResourceSet *resourceSet);
       
   111     void setWatcherEnabled(const QString &path, bool enable);
       
   112     void addWatcher(const QString &path);
       
   113     void removeWatcher(const QString &path);
       
   114 
       
   115     void slotFileChanged(const QString &);
       
   116 
       
   117     const QByteArray *createResource(const QString &path, QStringList *contents, int *errorCount, QIODevice &errorDevice) const;
       
   118     void deleteResource(const QByteArray *data) const;
       
   119 };
       
   120 
       
   121 QtResourceModelPrivate::QtResourceModelPrivate() :
       
   122     q_ptr(0),
       
   123     m_currentResourceSet(0),
       
   124     m_fileWatcher(0),
       
   125     m_fileWatcherEnabled(true)
       
   126 {
       
   127 }
       
   128 
       
   129 // --------------------- QtResourceSet
       
   130 QtResourceSet::QtResourceSet() :
       
   131     d_ptr(new QtResourceSetPrivate)
       
   132 {
       
   133     d_ptr->q_ptr = this;
       
   134 }
       
   135 
       
   136 QtResourceSet::QtResourceSet(QtResourceModel *model) :
       
   137      d_ptr(new QtResourceSetPrivate(model))
       
   138 {
       
   139     d_ptr->q_ptr = this;
       
   140 }
       
   141 
       
   142 QtResourceSet::~QtResourceSet()
       
   143 {
       
   144 }
       
   145 
       
   146 QStringList QtResourceSet::activeQrcPaths() const
       
   147 {
       
   148     QtResourceSet *that = const_cast<QtResourceSet *>(this);
       
   149     return d_ptr->m_resourceModel->d_ptr->m_resourceSetToPaths.value(that);
       
   150 }
       
   151 
       
   152 void QtResourceSet::activateQrcPaths(const QStringList &paths, int *errorCount, QString *errorMessages)
       
   153 {
       
   154     d_ptr->m_resourceModel->d_ptr->activate(this, paths, errorCount, errorMessages);
       
   155 }
       
   156 
       
   157 bool QtResourceSet::isModified(const QString &path) const
       
   158 {
       
   159     return d_ptr->m_resourceModel->isModified(path);
       
   160 }
       
   161 
       
   162 void QtResourceSet::setModified(const QString &path)
       
   163 {
       
   164     d_ptr->m_resourceModel->setModified(path);
       
   165 }
       
   166 
       
   167 // ------------------- QtResourceModelPrivate
       
   168 const QByteArray *QtResourceModelPrivate::createResource(const QString &path, QStringList *contents, int *errorCount, QIODevice &errorDevice) const
       
   169 {
       
   170     typedef RCCResourceLibrary::ResourceDataFileMap ResourceDataFileMap;
       
   171     const QByteArray *rc = 0;
       
   172     *errorCount = -1;
       
   173     contents->clear();
       
   174     do {
       
   175         // run RCC
       
   176         RCCResourceLibrary library;
       
   177         library.setVerbose(true);
       
   178         library.setInputFiles(QStringList(path));
       
   179         library.setFormat(RCCResourceLibrary::Binary);
       
   180 
       
   181         QBuffer buffer;
       
   182         buffer.open(QIODevice::WriteOnly);
       
   183         if (!library.readFiles(/* ignore errors*/ true, errorDevice))
       
   184             break;
       
   185         // return code cannot be fully trusted, might still be empty
       
   186         const ResourceDataFileMap resMap = library.resourceDataFileMap();
       
   187         if (resMap.empty())
       
   188             break;
       
   189 
       
   190         if (!library.output(buffer, errorDevice))
       
   191             break;
       
   192 
       
   193         *errorCount = library.failedResources().size();
       
   194         *contents = resMap.keys();
       
   195 
       
   196         buffer.close();
       
   197         rc = new QByteArray(buffer.data());
       
   198     } while (false);
       
   199 
       
   200     if (debugResourceModel)
       
   201         qDebug() << "createResource" << path << "returns data=" << rc << " hasWarnings=" << *errorCount;
       
   202     return rc;
       
   203 }
       
   204 
       
   205 void QtResourceModelPrivate::deleteResource(const QByteArray *data) const
       
   206 {
       
   207     if (data) {
       
   208         if (debugResourceModel)
       
   209             qDebug() << "deleteResource";
       
   210         delete data;
       
   211     }
       
   212 }
       
   213 
       
   214 void QtResourceModelPrivate::registerResourceSet(QtResourceSet *resourceSet)
       
   215 {
       
   216     if (!resourceSet)
       
   217         return;
       
   218 
       
   219     // unregister old paths (all because the order of registration is important), later it can be optimized a bit
       
   220     QStringList toRegister = resourceSet->activeQrcPaths();
       
   221     QStringListIterator itRegister(toRegister);
       
   222     while (itRegister.hasNext()) {
       
   223         const QString path = itRegister.next();
       
   224         if (debugResourceModel)
       
   225             qDebug() << "registerResourceSet " << path;
       
   226         const PathDataMap::const_iterator itRcc = m_pathToData.constFind(path);
       
   227         if (itRcc != m_pathToData.constEnd()) { // otherwise data was not created yet
       
   228             if (!QResource::registerResource(reinterpret_cast<const uchar *>(itRcc.value()->constData()))) {
       
   229                 qDebug() << "** WARNING: Failed to register " << path << " (QResource failure).";
       
   230             } else {
       
   231                 QStringList contents = m_pathToContents.value(path);
       
   232                 QStringListIterator itContents(contents);
       
   233                 while (itContents.hasNext()) {
       
   234                     const QString filePath = itContents.next();
       
   235                     if (!m_fileToQrc.contains(filePath)) // the first loaded resource has higher priority in qt resource system
       
   236                         m_fileToQrc.insert(filePath, path);
       
   237                 }
       
   238             }
       
   239         }
       
   240     }
       
   241 }
       
   242 
       
   243 void QtResourceModelPrivate::unregisterResourceSet(QtResourceSet *resourceSet)
       
   244 {
       
   245     if (!resourceSet)
       
   246         return;
       
   247 
       
   248     // unregister old paths (all because the order of registration is importans), later it can be optimized a bit
       
   249     QStringList toUnregister = resourceSet->activeQrcPaths();
       
   250     QStringListIterator itUnregister(toUnregister);
       
   251     while (itUnregister.hasNext()) {
       
   252         const QString path = itUnregister.next();
       
   253         if (debugResourceModel)
       
   254             qDebug() << "unregisterResourceSet " << path;
       
   255         const PathDataMap::const_iterator itRcc = m_pathToData.constFind(path);
       
   256         if (itRcc != m_pathToData.constEnd()) { // otherwise data was not created yet
       
   257             if (!QResource::unregisterResource(reinterpret_cast<const uchar *>(itRcc.value()->constData())))
       
   258                 qDebug() << "** WARNING: Failed to unregister " << path << " (QResource failure).";
       
   259         }
       
   260     }
       
   261     m_fileToQrc.clear();
       
   262 }
       
   263 
       
   264 void QtResourceModelPrivate::activate(QtResourceSet *resourceSet, const QStringList &newPaths, int *errorCountPtr, QString *errorMessages)
       
   265 {
       
   266     if (debugResourceModel)
       
   267         qDebug() << "activate " << resourceSet;
       
   268     if (errorCountPtr)
       
   269         *errorCountPtr = 0;
       
   270     if (errorMessages)
       
   271         errorMessages->clear();
       
   272 
       
   273     QBuffer errorStream;
       
   274     errorStream.open(QIODevice::WriteOnly);
       
   275 
       
   276     int errorCount = 0;
       
   277     int generatedCount = 0;
       
   278     bool newResourceSetChanged = false;
       
   279 
       
   280     if (resourceSet && resourceSet->activeQrcPaths() != newPaths && !m_newlyCreated.contains(resourceSet))
       
   281         newResourceSetChanged = true;
       
   282 
       
   283     PathDataMap newPathToData = m_pathToData;
       
   284 
       
   285     QStringListIterator itPath(newPaths);
       
   286     while (itPath.hasNext()) {
       
   287         const QString path = itPath.next();
       
   288         if (resourceSet && !m_pathToResourceSet[path].contains(resourceSet))
       
   289             m_pathToResourceSet[path].append(resourceSet);
       
   290         const QMap<QString, bool>::iterator itMod = m_pathToModified.find(path);
       
   291         if (itMod == m_pathToModified.end() || itMod.value()) { // new path or path is already created, but needs to be recreated
       
   292             QStringList contents;
       
   293             int qrcErrorCount;
       
   294             generatedCount++;
       
   295             if (const QByteArray *data = createResource(path, &contents, &qrcErrorCount, errorStream)) {
       
   296                 newPathToData.insert(path, data);
       
   297                 if (qrcErrorCount) // Count single failed files as sort of 1/2 error
       
   298                     errorCount++;
       
   299                 addWatcher(path);
       
   300             } else {
       
   301                 newPathToData.remove(path);
       
   302                 errorCount++;
       
   303             }
       
   304             m_pathToModified.insert(path, false);
       
   305             m_pathToContents.insert(path, contents);
       
   306             newResourceSetChanged = true;
       
   307             const QMap<QString, QList<QtResourceSet *> >::iterator itReload = m_pathToResourceSet.find(path);
       
   308             if (itReload != m_pathToResourceSet.end()) {
       
   309                 QList<QtResourceSet *> resources = itReload.value();
       
   310                 QListIterator<QtResourceSet *> itRes(resources);
       
   311                 while (itRes.hasNext()) {
       
   312                     QtResourceSet *res = itRes.next();
       
   313                     if (res != resourceSet) {
       
   314                         m_resourceSetToReload[res] = true;
       
   315                     }
       
   316                 }
       
   317             }
       
   318         } else { // path is already created, don't need to recreate
       
   319         }
       
   320     }
       
   321 
       
   322     QList<const QByteArray *> oldData = m_pathToData.values();
       
   323     QList<const QByteArray *> newData = newPathToData.values();
       
   324 
       
   325     QList<const QByteArray *> toDelete;
       
   326     QListIterator<const QByteArray *> itOld(oldData);
       
   327     if (itOld.hasNext()) {
       
   328         const QByteArray *array = itOld.next();
       
   329         if (!newData.contains(array))
       
   330             toDelete.append(array);
       
   331     }
       
   332 
       
   333     // Nothing can fail below here?
       
   334     if (generatedCount) {
       
   335         if (errorCountPtr)
       
   336             *errorCountPtr = errorCount;
       
   337         errorStream.close();
       
   338         const QString stderrOutput = QString::fromUtf8(errorStream.data());
       
   339         if (debugResourceModel)
       
   340             qDebug() << "Output: (" << errorCount << ")\n" << stderrOutput;
       
   341         if (errorMessages)
       
   342             *errorMessages = stderrOutput;
       
   343     }
       
   344     // register
       
   345     const QMap<QtResourceSet *, bool>::iterator itReload = m_resourceSetToReload.find(resourceSet);
       
   346     if (itReload != m_resourceSetToReload.end()) {
       
   347         if (itReload.value()) {
       
   348             newResourceSetChanged = true;
       
   349             m_resourceSetToReload.insert(resourceSet, false);
       
   350         }
       
   351     }
       
   352 
       
   353     QStringList oldActivePaths;
       
   354     if (m_currentResourceSet)
       
   355         oldActivePaths = m_currentResourceSet->activeQrcPaths();
       
   356 
       
   357     const bool needReregister = (oldActivePaths != newPaths) || newResourceSetChanged;
       
   358 
       
   359     QMap<QtResourceSet *, bool>::iterator itNew = m_newlyCreated.find(resourceSet);
       
   360     if (itNew != m_newlyCreated.end()) {
       
   361         m_newlyCreated.remove(resourceSet);
       
   362         if (needReregister)
       
   363             newResourceSetChanged = true;
       
   364     }
       
   365 
       
   366     if (!newResourceSetChanged && !needReregister && (m_currentResourceSet == resourceSet)) {
       
   367         foreach (const QByteArray *data, toDelete)
       
   368             deleteResource(data);
       
   369 
       
   370         return; // nothing changed
       
   371     }
       
   372 
       
   373     if (needReregister)
       
   374         unregisterResourceSet(m_currentResourceSet);
       
   375 
       
   376     foreach (const QByteArray *data, toDelete)
       
   377         deleteResource(data);
       
   378 
       
   379     m_pathToData = newPathToData;
       
   380     m_currentResourceSet = resourceSet;
       
   381 
       
   382     if (resourceSet)
       
   383         removeOldPaths(resourceSet, newPaths);
       
   384 
       
   385     if (needReregister)
       
   386         registerResourceSet(m_currentResourceSet);
       
   387 
       
   388     emit q_ptr->resourceSetActivated(m_currentResourceSet, newResourceSetChanged);
       
   389 
       
   390     // deactivates the paths from old current resource set
       
   391     // add new paths to the new current resource set
       
   392     // reloads all paths which are marked as modified from the current resource set;
       
   393     // activates the paths from current resource set
       
   394     // emits resourceSetActivated() (don't emit only in case when old resource set is the same as new one
       
   395     // AND no path was reloaded AND the list of paths is exactly the same)
       
   396 }
       
   397 
       
   398 void QtResourceModelPrivate::removeOldPaths(QtResourceSet *resourceSet, const QStringList &newPaths)
       
   399 {
       
   400     QStringList oldPaths = m_resourceSetToPaths.value(resourceSet);
       
   401     if (oldPaths != newPaths) {
       
   402         // remove old
       
   403         QStringListIterator itOldPaths(oldPaths);
       
   404         while (itOldPaths.hasNext()) {
       
   405             QString oldPath = itOldPaths.next();
       
   406             if (!newPaths.contains(oldPath)) {
       
   407                 const QMap<QString, QList<QtResourceSet *> >::iterator itRemove = m_pathToResourceSet.find(oldPath);
       
   408                 if (itRemove != m_pathToResourceSet.end()) {
       
   409                     const int idx = itRemove.value().indexOf(resourceSet);
       
   410                     if (idx >= 0)
       
   411                         itRemove.value().removeAt(idx);
       
   412                     if (itRemove.value().count() == 0) {
       
   413                         PathDataMap::iterator it = m_pathToData.find(oldPath);
       
   414                         if (it != m_pathToData.end())
       
   415                             deleteResource(it.value());
       
   416                         m_pathToResourceSet.erase(itRemove);
       
   417                         m_pathToModified.remove(oldPath);
       
   418                         m_pathToContents.remove(oldPath);
       
   419                         m_pathToData.remove(oldPath);
       
   420                         removeWatcher(oldPath);
       
   421                     }
       
   422                 }
       
   423             }
       
   424         }
       
   425         m_resourceSetToPaths[resourceSet] = newPaths;
       
   426     }
       
   427 }
       
   428 
       
   429 void QtResourceModelPrivate::setWatcherEnabled(const QString &path, bool enable)
       
   430 {
       
   431     m_fileWatcher->removePath(path);
       
   432 
       
   433     if (!enable)
       
   434         return;
       
   435 
       
   436     QFileInfo fi(path);
       
   437     if (fi.exists())
       
   438         m_fileWatcher->addPath(path);
       
   439 }
       
   440 
       
   441 void QtResourceModelPrivate::addWatcher(const QString &path)
       
   442 {
       
   443     QMap<QString, bool>::ConstIterator it = m_fileWatchedMap.constFind(path);
       
   444     if (it != m_fileWatchedMap.constEnd() && it.value() == false)
       
   445         return;
       
   446 
       
   447     m_fileWatchedMap.insert(path, true);
       
   448     if (!m_fileWatcherEnabled)
       
   449         return;
       
   450     setWatcherEnabled(path, true);
       
   451 }
       
   452 
       
   453 void QtResourceModelPrivate::removeWatcher(const QString &path)
       
   454 {
       
   455     if (!m_fileWatchedMap.contains(path))
       
   456         return;
       
   457 
       
   458     m_fileWatchedMap.remove(path);
       
   459     if (!m_fileWatcherEnabled)
       
   460         return;
       
   461     setWatcherEnabled(path, false);
       
   462 }
       
   463 
       
   464 void QtResourceModelPrivate::slotFileChanged(const QString &path)
       
   465 {
       
   466     setWatcherEnabled(path, false);
       
   467     emit q_ptr->qrcFileModifiedExternally(path);
       
   468     setWatcherEnabled(path, true); //readd
       
   469 }
       
   470 
       
   471 // ----------------------- QtResourceModel
       
   472 QtResourceModel::QtResourceModel(QObject *parent) :
       
   473     QObject(parent),
       
   474     d_ptr(new QtResourceModelPrivate)
       
   475 {
       
   476     d_ptr->q_ptr = this;
       
   477 
       
   478     d_ptr->m_fileWatcher = new QFileSystemWatcher(this);
       
   479     connect(d_ptr->m_fileWatcher, SIGNAL(fileChanged(const QString &)),
       
   480             this, SLOT(slotFileChanged(const QString &)));
       
   481 }
       
   482 
       
   483 QtResourceModel::~QtResourceModel()
       
   484 {
       
   485     blockSignals(true);
       
   486     QList<QtResourceSet *> resourceList = resourceSets();
       
   487     QListIterator<QtResourceSet *> it(resourceList);
       
   488     while (it.hasNext())
       
   489         removeResourceSet(it.next());
       
   490     blockSignals(false);
       
   491 }
       
   492 
       
   493 QStringList QtResourceModel::loadedQrcFiles() const
       
   494 {
       
   495     return d_ptr->m_pathToModified.keys();
       
   496 }
       
   497 
       
   498 bool QtResourceModel::isModified(const QString &path) const
       
   499 {
       
   500     QMap<QString, bool>::const_iterator it = d_ptr->m_pathToModified.find(path);
       
   501     if (it != d_ptr->m_pathToModified.constEnd())
       
   502         return it.value();
       
   503     return true;
       
   504 }
       
   505 
       
   506 void QtResourceModel::setModified(const QString &path)
       
   507 {
       
   508     QMap<QString, bool>::const_iterator itMod = d_ptr->m_pathToModified.find(path);
       
   509     if (itMod == d_ptr->m_pathToModified.constEnd())
       
   510         return;
       
   511 
       
   512     d_ptr->m_pathToModified[path] = true;
       
   513     QMap<QString, QList<QtResourceSet *> >::const_iterator it = d_ptr->m_pathToResourceSet.constFind(path);
       
   514     if (it == d_ptr->m_pathToResourceSet.constEnd())
       
   515         return;
       
   516 
       
   517     QList<QtResourceSet *> resourceList = it.value();
       
   518     QListIterator<QtResourceSet *> itReload(resourceList);
       
   519     while (itReload.hasNext())
       
   520         d_ptr->m_resourceSetToReload.insert(itReload.next(), true);
       
   521 }
       
   522 
       
   523 QList<QtResourceSet *> QtResourceModel::resourceSets() const
       
   524 {
       
   525     return d_ptr->m_resourceSetToPaths.keys();
       
   526 }
       
   527 
       
   528 QtResourceSet *QtResourceModel::currentResourceSet() const
       
   529 {
       
   530     return d_ptr->m_currentResourceSet;
       
   531 }
       
   532 
       
   533 void QtResourceModel::setCurrentResourceSet(QtResourceSet *resourceSet, int *errorCount, QString *errorMessages)
       
   534 {
       
   535     d_ptr->activate(resourceSet, d_ptr->m_resourceSetToPaths.value(resourceSet), errorCount, errorMessages);
       
   536 }
       
   537 
       
   538 QtResourceSet *QtResourceModel::addResourceSet(const QStringList &paths)
       
   539 {
       
   540     QtResourceSet *newResource = new QtResourceSet(this);
       
   541     d_ptr->m_resourceSetToPaths.insert(newResource, paths);
       
   542     d_ptr->m_resourceSetToReload.insert(newResource, false);
       
   543     d_ptr->m_newlyCreated.insert(newResource, true);
       
   544     QStringListIterator it(paths);
       
   545     while (it.hasNext()) {
       
   546         const QString path = it.next();
       
   547         d_ptr->m_pathToResourceSet[path].append(newResource);
       
   548     }
       
   549     return newResource;
       
   550 }
       
   551 
       
   552 // TODO
       
   553 void QtResourceModel::removeResourceSet(QtResourceSet *resourceSet)
       
   554 {
       
   555     if (!resourceSet)
       
   556         return;
       
   557     if (currentResourceSet() == resourceSet)
       
   558         setCurrentResourceSet(0);
       
   559 
       
   560     // remove rcc files for those paths which are not used in any other resource set
       
   561     d_ptr->removeOldPaths(resourceSet, QStringList());
       
   562 
       
   563     d_ptr->m_resourceSetToPaths.remove(resourceSet);
       
   564     d_ptr->m_resourceSetToReload.remove(resourceSet);
       
   565     d_ptr->m_newlyCreated.remove(resourceSet);
       
   566     delete resourceSet;
       
   567 }
       
   568 
       
   569 void QtResourceModel::reload(const QString &path, int *errorCount, QString *errorMessages)
       
   570 {
       
   571     setModified(path);
       
   572 
       
   573     d_ptr->activate(d_ptr->m_currentResourceSet, d_ptr->m_resourceSetToPaths.value(d_ptr->m_currentResourceSet), errorCount, errorMessages);
       
   574 }
       
   575 
       
   576 void QtResourceModel::reload(int *errorCount, QString *errorMessages)
       
   577 {
       
   578     QMap<QString, bool>::iterator it = d_ptr->m_pathToModified.begin();
       
   579     QMap<QString, bool>::iterator itEnd = d_ptr->m_pathToModified.end(); // will it be valid when I iterate the map and change it???
       
   580     while (it != itEnd) {
       
   581         it = d_ptr->m_pathToModified.insert(it.key(), true);
       
   582         ++it;
       
   583     }
       
   584 
       
   585     QMap<QtResourceSet *, bool>::iterator itReload = d_ptr->m_resourceSetToReload.begin();
       
   586     QMap<QtResourceSet *, bool>::iterator itReloadEnd = d_ptr->m_resourceSetToReload.end();
       
   587     while (itReload != itReloadEnd) {
       
   588         itReload = d_ptr->m_resourceSetToReload.insert(itReload.key(), true); // empty resourceSets could be omitted here
       
   589         ++itReload;
       
   590     }
       
   591 
       
   592     d_ptr->activate(d_ptr->m_currentResourceSet, d_ptr->m_resourceSetToPaths.value(d_ptr->m_currentResourceSet), errorCount, errorMessages);
       
   593 }
       
   594 
       
   595 QMap<QString, QString> QtResourceModel::contents() const
       
   596 {
       
   597     return d_ptr->m_fileToQrc;
       
   598 }
       
   599 
       
   600 QString QtResourceModel::qrcPath(const QString &file) const
       
   601 {
       
   602     return d_ptr->m_fileToQrc.value(file);
       
   603 }
       
   604 
       
   605 void QtResourceModel::setWatcherEnabled(bool enable)
       
   606 {
       
   607     if (d_ptr->m_fileWatcherEnabled == enable)
       
   608         return;
       
   609 
       
   610     d_ptr->m_fileWatcherEnabled = enable;
       
   611 
       
   612     QMapIterator<QString, bool> it(d_ptr->m_fileWatchedMap);
       
   613     if (it.hasNext())
       
   614         d_ptr->setWatcherEnabled(it.next().key(), d_ptr->m_fileWatcherEnabled);
       
   615 }
       
   616 
       
   617 bool QtResourceModel::isWatcherEnabled() const
       
   618 {
       
   619     return d_ptr->m_fileWatcherEnabled;
       
   620 }
       
   621 
       
   622 void QtResourceModel::setWatcherEnabled(const QString &path, bool enable)
       
   623 {
       
   624     QMap<QString, bool>::Iterator it = d_ptr->m_fileWatchedMap.find(path);
       
   625     if (it == d_ptr->m_fileWatchedMap.end())
       
   626         return;
       
   627 
       
   628     if (it.value() == enable)
       
   629         return;
       
   630 
       
   631     it.value() = enable;
       
   632 
       
   633     if (!d_ptr->m_fileWatcherEnabled)
       
   634         return;
       
   635 
       
   636     d_ptr->setWatcherEnabled(it.key(), enable);
       
   637 }
       
   638 
       
   639 bool QtResourceModel::isWatcherEnabled(const QString &path)
       
   640 {
       
   641     return d_ptr->m_fileWatchedMap.value(path, false);
       
   642 }
       
   643 
       
   644 QT_END_NAMESPACE
       
   645 
       
   646 #include "moc_qtresourcemodel_p.cpp"