blob: bab6a3338a25b001f9889fcf667ad8e4e9cea0d0 [file] [log] [blame]
jareda9541812013-01-09 00:08:46 -08001#include "filesystemwatcher.h"
2#include "ui_filesystemwatcher.h"
3
Jared Lindblom4d1d00a2013-01-11 01:14:23 -08004FileSystemWatcher::FileSystemWatcher(QString dirPath, QWidget *parent) :
jareda9541812013-01-09 00:08:46 -08005 QMainWindow(parent),
Jared Lindblom4d1d00a2013-01-11 01:14:23 -08006 m_ui(new Ui::FileSystemWatcher),
jareda9541812013-01-09 00:08:46 -08007 m_watcher(new QFileSystemWatcher()),
8 m_listViewModel(new QStringListModel()),
9 m_listView(new QListView()),
Jared Lindbloma9996302013-01-12 00:25:16 -080010 m_timer(new QTimer(this)),
jareda9541812013-01-09 00:08:46 -080011 m_dirPath(dirPath)
12{
13 // setup user interface
14 m_ui->setupUi(this);
15
16 // add main directory to monitor
17 m_watcher->addPath(m_dirPath);
18
19 // create the view
20 m_listView->setModel(m_listViewModel);
21 setCentralWidget(m_listView);
22
23 // set title
24 setWindowTitle("ChronoShare");
25
26 // register signals (callback functions)
Jared Lindbloma9996302013-01-12 00:25:16 -080027 connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(handleCallback()));
28 connect(m_timer, SIGNAL(timeout()), this, SLOT(handleCallback()));
jareda9541812013-01-09 00:08:46 -080029
Jared Lindbloma9996302013-01-12 00:25:16 -080030 // bootstrap
31 handleCallback();
32
33 // start timer
34 m_timer->start(10000);
jareda9541812013-01-09 00:08:46 -080035}
36
Jared Lindblom4d1d00a2013-01-11 01:14:23 -080037FileSystemWatcher::~FileSystemWatcher()
jareda9541812013-01-09 00:08:46 -080038{
39 // clean up
40 delete m_ui;
41 delete m_watcher;
42 delete m_listViewModel;
43 delete m_listView;
Jared Lindbloma9996302013-01-12 00:25:16 -080044 delete m_timer;
jareda9541812013-01-09 00:08:46 -080045}
46
Jared Lindbloma9996302013-01-12 00:25:16 -080047void FileSystemWatcher::handleCallback()
jareda9541812013-01-09 00:08:46 -080048{
Jared Lindblom4d1d00a2013-01-11 01:14:23 -080049 // scan directory and populate file list
Jared Lindbloma9996302013-01-12 00:25:16 -080050 QHash<QString, sFileInfo> currentState = scanDirectory(m_dirPath);
Jared Lindblom4d1d00a2013-01-11 01:14:23 -080051
Jared Lindbloma9996302013-01-12 00:25:16 -080052 QStringList dirChanges = reconcileDirectory(currentState);
Jared Lindblom4d1d00a2013-01-11 01:14:23 -080053
54 // update gui with list of changes in this directory
Jared Lindbloma9996302013-01-12 00:25:16 -080055 qDebug() << endl << m_watcher->directories() << endl;
56
57 if(!dirChanges.isEmpty())
58 m_listViewModel->setStringList(dirChanges);
jareda9541812013-01-09 00:08:46 -080059}
60
Jared Lindbloma9996302013-01-12 00:25:16 -080061QHash<QString, sFileInfo> FileSystemWatcher::scanDirectory(QString dirPath)
62{
jareda9541812013-01-09 00:08:46 -080063 // list of files in directory
Jared Lindbloma9996302013-01-12 00:25:16 -080064 QHash<QString, sFileInfo> currentState;
jareda9541812013-01-09 00:08:46 -080065
66 // directory iterator (recursive)
Jared Lindblom4d1d00a2013-01-11 01:14:23 -080067 QDirIterator dirIterator(dirPath, QDirIterator::Subdirectories |
jareda9541812013-01-09 00:08:46 -080068 QDirIterator::FollowSymlinks);
69
70 // iterate through directory recursively
71 while(dirIterator.hasNext())
72 {
73 // Get Next File/Dir
74 dirIterator.next();
75
76 // Get FileInfo
77 QFileInfo fileInfo = dirIterator.fileInfo();
78
79 // if not this directory or previous directory
80 if(fileInfo.absoluteFilePath() != ".." && fileInfo.absoluteFilePath() != ".")
81 {
Jared Lindbloma9996302013-01-12 00:25:16 -080082 QString absFilePath = fileInfo.absoluteFilePath();
83
jareda9541812013-01-09 00:08:46 -080084 // if this is a directory
85 if(fileInfo.isDir())
86 {
87 QStringList dirList = m_watcher->directories();
88
89 // if the directory is not already being watched
Jared Lindbloma9996302013-01-12 00:25:16 -080090 if (absFilePath.startsWith(m_dirPath) && !dirList.contains(absFilePath))
jareda9541812013-01-09 00:08:46 -080091 {
92 // add this directory to the watch list
Jared Lindbloma9996302013-01-12 00:25:16 -080093 m_watcher->addPath(absFilePath);
jareda9541812013-01-09 00:08:46 -080094 }
95 }
96 else
97 {
Jared Lindbloma9996302013-01-12 00:25:16 -080098 // construct struct
99 sFileInfo fileInfoStruct;
100 fileInfoStruct.fileInfo = fileInfo;
101
102 // initialize checksum
103 QCryptographicHash crypto(QCryptographicHash::Md5);
104
105 // open file
106 QFile file(fileInfo.absoluteFilePath());
107 file.open(QFile::ReadOnly);
108
109 // calculate checksum
110 while(!file.atEnd())
111 {
112 crypto.addData(file.read(8192));
113 }
114
115 fileInfoStruct.hash = crypto.result();
116
jareda9541812013-01-09 00:08:46 -0800117 // add this file to the file list
Jared Lindbloma9996302013-01-12 00:25:16 -0800118 currentState.insert(absFilePath, fileInfoStruct);
jareda9541812013-01-09 00:08:46 -0800119 }
120 }
121 }
122
Jared Lindbloma9996302013-01-12 00:25:16 -0800123 return currentState;
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800124}
125
Jared Lindbloma9996302013-01-12 00:25:16 -0800126QStringList FileSystemWatcher::reconcileDirectory(QHash<QString, sFileInfo> currentState)
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800127{
Jared Lindbloma9996302013-01-12 00:25:16 -0800128 // list of files changed
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800129 QStringList dirChanges;
130
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800131 // compare result (database/stored snapshot) to fileList (current snapshot)
Jared Lindbloma9996302013-01-12 00:25:16 -0800132 QMutableHashIterator<QString, sFileInfo> i(m_storedState);
133 while(i.hasNext())
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800134 {
Jared Lindbloma9996302013-01-12 00:25:16 -0800135 i.next();
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800136
Jared Lindbloma9996302013-01-12 00:25:16 -0800137 QString absFilePath = i.key();
138
139 sFileInfo storedFileInfoStruct = i.value();
140 QFileInfo storedFileInfo = storedFileInfoStruct.fileInfo;
141 QByteArray storedHash = storedFileInfoStruct.hash;
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800142
143 // check file existence
Jared Lindbloma9996302013-01-12 00:25:16 -0800144 if(currentState.contains(absFilePath))
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800145 {
Jared Lindbloma9996302013-01-12 00:25:16 -0800146 sFileInfo currentFileInfoStruct = currentState.value(absFilePath);
147 QFileInfo currentFileInfo = currentFileInfoStruct.fileInfo;
148 QByteArray currentHash = currentFileInfoStruct.hash;
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800149
Jared Lindbloma9996302013-01-12 00:25:16 -0800150 if((storedFileInfo != currentFileInfo) || (storedHash != currentHash))
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800151 {
Jared Lindbloma9996302013-01-12 00:25:16 -0800152 // update stored state
153 i.setValue(currentFileInfoStruct);
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800154
155 // this file has been modified
156 dirChanges.append(absFilePath);
157 }
158
Jared Lindbloma9996302013-01-12 00:25:16 -0800159 // delete this file from fileList we have processed it
160 currentState.remove(absFilePath);
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800161 }
162 else
163 {
Jared Lindbloma9996302013-01-12 00:25:16 -0800164 // delete from stored state
165 i.remove();
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800166
167 // this file has been deleted
168 dirChanges.append(absFilePath);
Jared Lindbloma9996302013-01-12 00:25:16 -0800169 }
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800170 }
171
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800172 // any files left in fileList have been added
Jared Lindbloma9996302013-01-12 00:25:16 -0800173 for(QHash<QString, sFileInfo>::iterator i = currentState.begin(); i != currentState.end(); ++i)
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800174 {
175 QString absFilePath = i.key();
Jared Lindbloma9996302013-01-12 00:25:16 -0800176 sFileInfo currentFileInfoStruct = i.value();
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800177
Jared Lindbloma9996302013-01-12 00:25:16 -0800178 m_storedState.insert(absFilePath, currentFileInfoStruct);
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800179
180 // this file has been added
181 dirChanges.append(absFilePath);
Jared Lindblom4d1d00a2013-01-11 01:14:23 -0800182 }
183
Jared Lindbloma9996302013-01-12 00:25:16 -0800184 return dirChanges;
jareda9541812013-01-09 00:08:46 -0800185}
Alexander Afanasyevff731962013-01-09 17:16:28 -0800186
187#if WAF
188#include "filesystemwatcher.moc"
189#include "filesystemwatcher.cpp.moc"
190#endif