WARNING: USE THIS SOFTWARE AT YOUR OWN RISK! THIS IS EXPERIMENTAL SOFTWARE NOT INTENDED FOR PRODUCTION USE! Zuble is currently an early stage prototype. As such Zuble is minimally tested and inherently unstable. It is provided for experimental, development, and demonstration purposes only. Zuble QML Types   |  Zuble C++ Classes   |  Zuble Overview
Zuble  0.1
Zuble Framework C++/QML extension API
ZFileSystemWatcher.cpp
Go to the documentation of this file.
1 /*
2  * Zuble - A run-time system for QML/Javascript applications
3  * Copyright (C) 2015 Bob Dinitto
4  *
5  * Filename: ZFileSystemWatcher.cpp
6  * Created on: 10/26/2015
7  * Author: Bob Dinitto
8  *
9  * Zuble is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include <QtQml>
26 #include "ZFileSystemWatcher.h"
27 
28 namespace Zbl
29 {
30 
32 
34  QObject(parent), m_lock(QMutex::Recursive), m_restoreDeletedFiles(false)
35 {
36  connect(&m_watcher, &QFileSystemWatcher::fileChanged,
38  connect(&m_watcher, &QFileSystemWatcher::directoryChanged,
40 }
41 
43 {
45 
46  qmlRegisterType<ZFileSystemWatcher>("org.zuble.qml", 1, 0, "ZFileSystemWatcher");
47 }
48 
49 
50 bool ZFileSystemWatcher::addPath(const QString &file)
51 {
53  QMutexLocker lock(&m_lock);
54 
55  zFileWatcherMap::iterator it = m_paths.find(file);
56 
57  int fileReferenceCount = -1;
58  bool ret = false;
59 
60  if(it == m_paths.end())
61  {
62  fileReferenceCount = 1;
63  ret = m_watcher.addPath(file);
64  if(ret)
65  m_paths.insert(file, fileReferenceCount);
66  else
67  zCritical() << "Zuble can't watch file path: " << file;
68  }
69  else
70  {
71  fileReferenceCount = it.value();
72  fileReferenceCount++;
73  m_paths.insert(file, fileReferenceCount);
74  ret = true;
75  }
76 
77  ZBL_SLOT_END_RETURN(ret, false,
79 }
80 
81 QStringList ZFileSystemWatcher::addPaths(const QStringList &files)
82 {
83  QStringList failedPaths;
84 
86  QMutexLocker lock(&m_lock);
87 
88  const int fileCount = files.count();
89 
90  for(int i=0; i<fileCount; i++)
91  {
92  if(!addPath(files.at(i)))
93  failedPaths.append(files.at(i));
94  }
95 
96  ZBL_SLOT_END_RETURN(failedPaths, failedPaths,
98 }
99 
100 bool ZFileSystemWatcher::removePath(const QString &file)
101 {
103  QMutexLocker lock(&m_lock);
104 
105  zFileWatcherMap::iterator it = m_paths.find(file);
106 
107  int fileReferenceCount = -1;
108  bool ret = true;
109 
110  if(it != m_paths.end())
111  {
112  fileReferenceCount = it.value();
113 
114  if(fileReferenceCount == 1)
115  {
116  ret = m_watcher.removePath(file);
117  }
118  else
119  {
120  fileReferenceCount--;
121  m_paths.insert(file, fileReferenceCount);
122  }
123  }
124 
125  ZBL_SLOT_END_RETURN(ret, false,
127 }
128 
129 QStringList ZFileSystemWatcher::removePaths(const QStringList &files)
130 {
131  QStringList failedPaths;
132 
134  QMutexLocker lock(&m_lock);
135 
136  const int fileCount = files.count();
137 
138  for(int i=0; i<fileCount; i++)
139  {
140  if(!removePath(files.at(i)))
141  failedPaths.append(files.at(i));
142  }
143 
144  ZBL_SLOT_END_RETURN(failedPaths, failedPaths,
146 }
147 
148 QStringList ZFileSystemWatcher::files() const
149 {
151  QMutexLocker lock(const_cast<QMutex*>(&m_lock));
152  ZBL_SLOT_END_RETURN(m_watcher.files(), QStringList(),
154 }
155 
157 {
159  QMutexLocker lock(const_cast<QMutex*>(&m_lock));
160  ZBL_SLOT_END_RETURN(m_watcher.directories(), QStringList(),
162 }
163 
165 {
166  QMutexLocker lock(const_cast<QMutex*>(&m_lock));
167 
168  return m_restoreDeletedFiles;
169 }
170 
172 {
173  QMutexLocker lock(const_cast<QMutex*>(&m_lock));
174 
175  m_restoreDeletedFiles = restoreFiles;
176 }
177 
179 {
180  zFileWatcherMap::const_iterator i = m_paths.find(path);
181 
182  if(i == m_paths.end())
183  return false;
184 
185  static const int max_iterations = 300; // 3 second timeout
186 
187  for(int iterations = 0; !QFile::exists(path); iterations++)
188  {
189  if(iterations > max_iterations)
190  {
191  zCritical() << "ERROR: ZFileSystemWatcher timed out waiting for creation of file: "
192  << path;
193 
194  m_paths.remove(path);
195  return false;
196  }
197  QThread::msleep(10);
198  }
199  return true;
200 }
201 
202 void ZFileSystemWatcher::onFileChanged(const QString& path)
203 {
204  {
205  QMutexLocker lock(const_cast<QMutex*>(&m_lock));
206 
208  {
209  if(waitForFileCreation(path))
210  m_watcher.addPath(path);
211  }
212  }
213  emit fileChanged(path);
214 }
215 
216 } // Zbl
bool waitForFileCreation(const QString &path)
This class wraps QFileSystemWatcher and adds path reference counting.
Q_INVOKABLE QStringList removePaths(const QStringList &files)
Q_INVOKABLE QStringList directories() const
void onFileChanged(const QString &path)
#define Z_FAC_JS
Definition: zglobal.h:123
#define ZBL_REGISTER_LOGGED_OBJECT
Definition: zglobal.h:104
Q_INVOKABLE bool removePath(const QString &file)
Q_INVOKABLE bool addPath(const QString &file)
void setRestoreDeletedFiles(bool restoreFiles)
Q_INVOKABLE QStringList addPaths(const QStringList &files)
Definition: ZAndGate.cpp:6
#define ZBL_SLOT_BEGIN_TRY
Definition: zglobal.h:128
#define ZBL_DEFINE_LOGGED_OBJECT(class_name)
Definition: zglobal.h:99
static void registerType()
Registers ZFileSystemWatcher as a QML type.
Q_INVOKABLE QStringList files() const
QFileSystemWatcher m_watcher
#define ZBL_SLOT_END_RETURN(return_success, return_failed, facility, code, error_message)
Definition: zglobal.h:141
#define zCritical()
Definition: zglobal.h:112
void fileChanged(const QString &path)
void directoryChanged(const QString &path)