Remove Qt Designer's dependency on rcc code from qtbase.
[qt:qttools.git] / src / designer / src / lib / shared / qtresourcemodel.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qtresourcemodel_p.h"
43 #include "rcc_p.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::activeResourceFilePaths() 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::activateResourceFilePaths(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 (!library.output(buffer, errorDevice))
188             break;
189
190         *errorCount = library.failedResources().size();
191         *contents = resMap.keys();
192
193         if (resMap.empty())
194             break;
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->activeResourceFilePaths();
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             const QByteArray *data = itRcc.value();
229             if (data) {
230                 if (!QResource::registerResource(reinterpret_cast<const uchar *>(data->constData()))) {
231                     qWarning() << "** WARNING: Failed to register " << path << " (QResource failure).";
232                 } else {
233                     QStringList contents = m_pathToContents.value(path);
234                     QStringListIterator itContents(contents);
235                     while (itContents.hasNext()) {
236                         const QString filePath = itContents.next();
237                         if (!m_fileToQrc.contains(filePath)) // the first loaded resource has higher priority in qt resource system
238                             m_fileToQrc.insert(filePath, path);
239                     }
240                 }
241             }
242         }
243     }
244 }
245
246 void QtResourceModelPrivate::unregisterResourceSet(QtResourceSet *resourceSet)
247 {
248     if (!resourceSet)
249         return;
250
251     // unregister old paths (all because the order of registration is importans), later it can be optimized a bit
252     QStringList toUnregister = resourceSet->activeResourceFilePaths();
253     QStringListIterator itUnregister(toUnregister);
254     while (itUnregister.hasNext()) {
255         const QString path = itUnregister.next();
256         if (debugResourceModel)
257             qDebug() << "unregisterResourceSet " << path;
258         const PathDataMap::const_iterator itRcc = m_pathToData.constFind(path);
259         if (itRcc != m_pathToData.constEnd()) { // otherwise data was not created yet
260             const QByteArray *data = itRcc.value();
261             if (data) {
262                 if (!QResource::unregisterResource(reinterpret_cast<const uchar *>(itRcc.value()->constData())))
263                     qWarning() << "** WARNING: Failed to unregister " << path << " (QResource failure).";
264             }
265         }
266     }
267     m_fileToQrc.clear();
268 }
269
270 void QtResourceModelPrivate::activate(QtResourceSet *resourceSet, const QStringList &newPaths, int *errorCountPtr, QString *errorMessages)
271 {
272     if (debugResourceModel)
273         qDebug() << "activate " << resourceSet;
274     if (errorCountPtr)
275         *errorCountPtr = 0;
276     if (errorMessages)
277         errorMessages->clear();
278
279     QBuffer errorStream;
280     errorStream.open(QIODevice::WriteOnly);
281
282     int errorCount = 0;
283     int generatedCount = 0;
284     bool newResourceSetChanged = false;
285
286     if (resourceSet && resourceSet->activeResourceFilePaths() != newPaths && !m_newlyCreated.contains(resourceSet))
287         newResourceSetChanged = true;
288
289     PathDataMap newPathToData = m_pathToData;
290
291     QStringListIterator itPath(newPaths);
292     while (itPath.hasNext()) {
293         const QString path = itPath.next();
294         if (resourceSet && !m_pathToResourceSet[path].contains(resourceSet))
295             m_pathToResourceSet[path].append(resourceSet);
296         const QMap<QString, bool>::iterator itMod = m_pathToModified.find(path);
297         if (itMod == m_pathToModified.end() || itMod.value()) { // new path or path is already created, but needs to be recreated
298             QStringList contents;
299             int qrcErrorCount;
300             generatedCount++;
301             const QByteArray *data = createResource(path, &contents, &qrcErrorCount, errorStream);
302
303             newPathToData.insert(path, data);
304             if (qrcErrorCount) // Count single failed files as sort of 1/2 error
305                 errorCount++;
306             addWatcher(path);
307
308             m_pathToModified.insert(path, false);
309             m_pathToContents.insert(path, contents);
310             newResourceSetChanged = true;
311             const QMap<QString, QList<QtResourceSet *> >::iterator itReload = m_pathToResourceSet.find(path);
312             if (itReload != m_pathToResourceSet.end()) {
313                 QList<QtResourceSet *> resources = itReload.value();
314                 QListIterator<QtResourceSet *> itRes(resources);
315                 while (itRes.hasNext()) {
316                     QtResourceSet *res = itRes.next();
317                     if (res != resourceSet) {
318                         m_resourceSetToReload[res] = true;
319                     }
320                 }
321             }
322         } else { // path is already created, don't need to recreate
323         }
324     }
325
326     QList<const QByteArray *> oldData = m_pathToData.values();
327     QList<const QByteArray *> newData = newPathToData.values();
328
329     QList<const QByteArray *> toDelete;
330     QListIterator<const QByteArray *> itOld(oldData);
331     if (itOld.hasNext()) {
332         const QByteArray *array = itOld.next();
333         if (array && !newData.contains(array))
334             toDelete.append(array);
335     }
336
337     // Nothing can fail below here?
338     if (generatedCount) {
339         if (errorCountPtr)
340             *errorCountPtr = errorCount;
341         errorStream.close();
342         const QString stderrOutput = QString::fromUtf8(errorStream.data());
343         if (debugResourceModel)
344             qDebug() << "Output: (" << errorCount << ")\n" << stderrOutput;
345         if (errorMessages)
346             *errorMessages = stderrOutput;
347     }
348     // register
349     const QMap<QtResourceSet *, bool>::iterator itReload = m_resourceSetToReload.find(resourceSet);
350     if (itReload != m_resourceSetToReload.end()) {
351         if (itReload.value()) {
352             newResourceSetChanged = true;
353             m_resourceSetToReload.insert(resourceSet, false);
354         }
355     }
356
357     QStringList oldActivePaths;
358     if (m_currentResourceSet)
359         oldActivePaths = m_currentResourceSet->activeResourceFilePaths();
360
361     const bool needReregister = (oldActivePaths != newPaths) || newResourceSetChanged;
362
363     QMap<QtResourceSet *, bool>::iterator itNew = m_newlyCreated.find(resourceSet);
364     if (itNew != m_newlyCreated.end()) {
365         m_newlyCreated.remove(resourceSet);
366         if (needReregister)
367             newResourceSetChanged = true;
368     }
369
370     if (!newResourceSetChanged && !needReregister && (m_currentResourceSet == resourceSet)) {
371         foreach (const QByteArray *data, toDelete)
372             deleteResource(data);
373
374         return; // nothing changed
375     }
376
377     if (needReregister)
378         unregisterResourceSet(m_currentResourceSet);
379
380     foreach (const QByteArray *data, toDelete)
381         deleteResource(data);
382
383     m_pathToData = newPathToData;
384     m_currentResourceSet = resourceSet;
385
386     if (resourceSet)
387         removeOldPaths(resourceSet, newPaths);
388
389     if (needReregister)
390         registerResourceSet(m_currentResourceSet);
391
392     emit q_ptr->resourceSetActivated(m_currentResourceSet, newResourceSetChanged);
393
394     // deactivates the paths from old current resource set
395     // add new paths to the new current resource set
396     // reloads all paths which are marked as modified from the current resource set;
397     // activates the paths from current resource set
398     // emits resourceSetActivated() (don't emit only in case when old resource set is the same as new one
399     // AND no path was reloaded AND the list of paths is exactly the same)
400 }
401
402 void QtResourceModelPrivate::removeOldPaths(QtResourceSet *resourceSet, const QStringList &newPaths)
403 {
404     QStringList oldPaths = m_resourceSetToPaths.value(resourceSet);
405     if (oldPaths != newPaths) {
406         // remove old
407         QStringListIterator itOldPaths(oldPaths);
408         while (itOldPaths.hasNext()) {
409             QString oldPath = itOldPaths.next();
410             if (!newPaths.contains(oldPath)) {
411                 const QMap<QString, QList<QtResourceSet *> >::iterator itRemove = m_pathToResourceSet.find(oldPath);
412                 if (itRemove != m_pathToResourceSet.end()) {
413                     const int idx = itRemove.value().indexOf(resourceSet);
414                     if (idx >= 0)
415                         itRemove.value().removeAt(idx);
416                     if (itRemove.value().count() == 0) {
417                         PathDataMap::iterator it = m_pathToData.find(oldPath);
418                         if (it != m_pathToData.end())
419                             deleteResource(it.value());
420                         m_pathToResourceSet.erase(itRemove);
421                         m_pathToModified.remove(oldPath);
422                         m_pathToContents.remove(oldPath);
423                         m_pathToData.remove(oldPath);
424                         removeWatcher(oldPath);
425                     }
426                 }
427             }
428         }
429         m_resourceSetToPaths[resourceSet] = newPaths;
430     }
431 }
432
433 void QtResourceModelPrivate::setWatcherEnabled(const QString &path, bool enable)
434 {
435     if (!enable) {
436         m_fileWatcher->removePath(path);
437         return;
438     }
439
440     QFileInfo fi(path);
441     if (fi.exists())
442         m_fileWatcher->addPath(path);
443 }
444
445 void QtResourceModelPrivate::addWatcher(const QString &path)
446 {
447     QMap<QString, bool>::ConstIterator it = m_fileWatchedMap.constFind(path);
448     if (it != m_fileWatchedMap.constEnd() && it.value() == false)
449         return;
450
451     m_fileWatchedMap.insert(path, true);
452     if (!m_fileWatcherEnabled)
453         return;
454     setWatcherEnabled(path, true);
455 }
456
457 void QtResourceModelPrivate::removeWatcher(const QString &path)
458 {
459     if (!m_fileWatchedMap.contains(path))
460         return;
461
462     m_fileWatchedMap.remove(path);
463     if (!m_fileWatcherEnabled)
464         return;
465     setWatcherEnabled(path, false);
466 }
467
468 void QtResourceModelPrivate::slotFileChanged(const QString &path)
469 {
470     setWatcherEnabled(path, false);
471     emit q_ptr->qrcFileModifiedExternally(path);
472     setWatcherEnabled(path, true); //readd
473 }
474
475 // ----------------------- QtResourceModel
476 QtResourceModel::QtResourceModel(QObject *parent) :
477     QObject(parent),
478     d_ptr(new QtResourceModelPrivate)
479 {
480     d_ptr->q_ptr = this;
481
482     d_ptr->m_fileWatcher = new QFileSystemWatcher(this);
483     connect(d_ptr->m_fileWatcher, SIGNAL(fileChanged(QString)),
484             this, SLOT(slotFileChanged(QString)));
485 }
486
487 QtResourceModel::~QtResourceModel()
488 {
489     blockSignals(true);
490     QList<QtResourceSet *> resourceList = resourceSets();
491     QListIterator<QtResourceSet *> it(resourceList);
492     while (it.hasNext())
493         removeResourceSet(it.next());
494     blockSignals(false);
495 }
496
497 QStringList QtResourceModel::loadedQrcFiles() const
498 {
499     return d_ptr->m_pathToModified.keys();
500 }
501
502 bool QtResourceModel::isModified(const QString &path) const
503 {
504     QMap<QString, bool>::const_iterator it = d_ptr->m_pathToModified.find(path);
505     if (it != d_ptr->m_pathToModified.constEnd())
506         return it.value();
507     return true;
508 }
509
510 void QtResourceModel::setModified(const QString &path)
511 {
512     QMap<QString, bool>::const_iterator itMod = d_ptr->m_pathToModified.find(path);
513     if (itMod == d_ptr->m_pathToModified.constEnd())
514         return;
515
516     d_ptr->m_pathToModified[path] = true;
517     QMap<QString, QList<QtResourceSet *> >::const_iterator it = d_ptr->m_pathToResourceSet.constFind(path);
518     if (it == d_ptr->m_pathToResourceSet.constEnd())
519         return;
520
521     QList<QtResourceSet *> resourceList = it.value();
522     QListIterator<QtResourceSet *> itReload(resourceList);
523     while (itReload.hasNext())
524         d_ptr->m_resourceSetToReload.insert(itReload.next(), true);
525 }
526
527 QList<QtResourceSet *> QtResourceModel::resourceSets() const
528 {
529     return d_ptr->m_resourceSetToPaths.keys();
530 }
531
532 QtResourceSet *QtResourceModel::currentResourceSet() const
533 {
534     return d_ptr->m_currentResourceSet;
535 }
536
537 void QtResourceModel::setCurrentResourceSet(QtResourceSet *resourceSet, int *errorCount, QString *errorMessages)
538 {
539     d_ptr->activate(resourceSet, d_ptr->m_resourceSetToPaths.value(resourceSet), errorCount, errorMessages);
540 }
541
542 QtResourceSet *QtResourceModel::addResourceSet(const QStringList &paths)
543 {
544     QtResourceSet *newResource = new QtResourceSet(this);
545     d_ptr->m_resourceSetToPaths.insert(newResource, paths);
546     d_ptr->m_resourceSetToReload.insert(newResource, false);
547     d_ptr->m_newlyCreated.insert(newResource, true);
548     QStringListIterator it(paths);
549     while (it.hasNext()) {
550         const QString path = it.next();
551         d_ptr->m_pathToResourceSet[path].append(newResource);
552     }
553     return newResource;
554 }
555
556 // TODO
557 void QtResourceModel::removeResourceSet(QtResourceSet *resourceSet)
558 {
559     if (!resourceSet)
560         return;
561     if (currentResourceSet() == resourceSet)
562         setCurrentResourceSet(0);
563
564     // remove rcc files for those paths which are not used in any other resource set
565     d_ptr->removeOldPaths(resourceSet, QStringList());
566
567     d_ptr->m_resourceSetToPaths.remove(resourceSet);
568     d_ptr->m_resourceSetToReload.remove(resourceSet);
569     d_ptr->m_newlyCreated.remove(resourceSet);
570     delete resourceSet;
571 }
572
573 void QtResourceModel::reload(const QString &path, int *errorCount, QString *errorMessages)
574 {
575     setModified(path);
576
577     d_ptr->activate(d_ptr->m_currentResourceSet, d_ptr->m_resourceSetToPaths.value(d_ptr->m_currentResourceSet), errorCount, errorMessages);
578 }
579
580 void QtResourceModel::reload(int *errorCount, QString *errorMessages)
581 {
582     QMap<QString, bool>::iterator it = d_ptr->m_pathToModified.begin();
583     QMap<QString, bool>::iterator itEnd = d_ptr->m_pathToModified.end(); // will it be valid when I iterate the map and change it???
584     while (it != itEnd) {
585         it = d_ptr->m_pathToModified.insert(it.key(), true);
586         ++it;
587     }
588
589     QMap<QtResourceSet *, bool>::iterator itReload = d_ptr->m_resourceSetToReload.begin();
590     QMap<QtResourceSet *, bool>::iterator itReloadEnd = d_ptr->m_resourceSetToReload.end();
591     while (itReload != itReloadEnd) {
592         itReload = d_ptr->m_resourceSetToReload.insert(itReload.key(), true); // empty resourceSets could be omitted here
593         ++itReload;
594     }
595
596     d_ptr->activate(d_ptr->m_currentResourceSet, d_ptr->m_resourceSetToPaths.value(d_ptr->m_currentResourceSet), errorCount, errorMessages);
597 }
598
599 QMap<QString, QString> QtResourceModel::contents() const
600 {
601     return d_ptr->m_fileToQrc;
602 }
603
604 QString QtResourceModel::qrcPath(const QString &file) const
605 {
606     return d_ptr->m_fileToQrc.value(file);
607 }
608
609 void QtResourceModel::setWatcherEnabled(bool enable)
610 {
611     if (d_ptr->m_fileWatcherEnabled == enable)
612         return;
613
614     d_ptr->m_fileWatcherEnabled = enable;
615
616     QMapIterator<QString, bool> it(d_ptr->m_fileWatchedMap);
617     if (it.hasNext())
618         d_ptr->setWatcherEnabled(it.next().key(), d_ptr->m_fileWatcherEnabled);
619 }
620
621 bool QtResourceModel::isWatcherEnabled() const
622 {
623     return d_ptr->m_fileWatcherEnabled;
624 }
625
626 void QtResourceModel::setWatcherEnabled(const QString &path, bool enable)
627 {
628     QMap<QString, bool>::Iterator it = d_ptr->m_fileWatchedMap.find(path);
629     if (it == d_ptr->m_fileWatchedMap.end())
630         return;
631
632     if (it.value() == enable)
633         return;
634
635     it.value() = enable;
636
637     if (!d_ptr->m_fileWatcherEnabled)
638         return;
639
640     d_ptr->setWatcherEnabled(it.key(), enable);
641 }
642
643 bool QtResourceModel::isWatcherEnabled(const QString &path)
644 {
645     return d_ptr->m_fileWatchedMap.value(path, false);
646 }
647
648 QT_END_NAMESPACE
649
650 #include "moc_qtresourcemodel_p.cpp"