Added database backend for filesystemwatcher
diff --git a/filesystemwatcher/filesystemwatcher.cpp b/filesystemwatcher/filesystemwatcher.cpp
index c0fd350..98f3857 100644
--- a/filesystemwatcher/filesystemwatcher.cpp
+++ b/filesystemwatcher/filesystemwatcher.cpp
@@ -1,9 +1,9 @@
 #include "filesystemwatcher.h"
 #include "ui_filesystemwatcher.h"
 
-filesystemwatcher::filesystemwatcher(QString dirPath, QWidget *parent) :
+FileSystemWatcher::FileSystemWatcher(QString dirPath, QWidget *parent) :
     QMainWindow(parent),
-    m_ui(new Ui::filesystemwatcher),
+    m_ui(new Ui::FileSystemWatcher),
     m_watcher(new QFileSystemWatcher()),
     m_listViewModel(new QStringListModel()),
     m_listView(new QListView()),
@@ -22,36 +22,59 @@
     // set title
     setWindowTitle("ChronoShare");
 
+    // open database
+    m_db = QSqlDatabase::addDatabase("QSQLITE");
+    m_db.setDatabaseName("filesystem.db");
+
+    if(!m_db.open())
+    {
+        qDebug() << "Error: Could not open database.";
+        return;
+    }
+
+    if(!createFileTable())
+    {
+        qDebug() << "Error: Could not create table.";
+        return;
+    }
+
     // register signals (callback functions)
-    connect(m_watcher,SIGNAL(fileChanged(QString)),this,SLOT(fileChangedSlot(QString)));
-    connect(m_watcher,SIGNAL(directoryChanged(QString)),this,SLOT(dirChangedSlot(QString)));
+    connect(m_watcher, SIGNAL(directoryChanged(QString)),this,SLOT(dirChangedSlot(QString)));
 
     // bootstrap file list
     dirChangedSlot(m_dirPath);
 }
 
-filesystemwatcher::~filesystemwatcher()
+FileSystemWatcher::~FileSystemWatcher()
 {
     // clean up
     delete m_ui;
     delete m_watcher;
     delete m_listViewModel;
     delete m_listView;
+
+    // close database
+    m_db.close();
 }
 
-void filesystemwatcher::fileChangedSlot(QString filePath)
+void FileSystemWatcher::dirChangedSlot(QString dirPath)
 {
-    QStringList fileList;
-    fileList.append(filePath);
+    // scan directory and populate file list
+    QHash<QString, QFileInfo> fileList = scanDirectory(dirPath);
+
+    QStringList dirChanges = reconcileDirectory(fileList);
+
+    // update gui with list of changes in this directory
+    m_listViewModel->setStringList(dirChanges);
 }
 
-void filesystemwatcher::dirChangedSlot(QString dirPath)
+QHash<QString, QFileInfo> FileSystemWatcher::scanDirectory(QString dirPath)
 {
     // list of files in directory
-    QStringList fileList;
+    QHash<QString, QFileInfo> fileList;
 
     // directory iterator (recursive)
-    QDirIterator dirIterator(m_dirPath, QDirIterator::Subdirectories |
+    QDirIterator dirIterator(dirPath, QDirIterator::Subdirectories |
                                         QDirIterator::FollowSymlinks);
 
     // iterate through directory recursively
@@ -81,13 +104,127 @@
             else
             {
                 // add this file to the file list
-                fileList.append(fileInfo.absoluteFilePath());
+                fileList.insert(fileInfo.absoluteFilePath(), fileInfo);
             }
         }
     }
 
-    // update gui with list of files in this directory
-    m_listViewModel->setStringList(fileList);
+    return fileList;
+}
+
+QStringList FileSystemWatcher::reconcileDirectory(QHash<QString, QFileInfo> fileList)
+{
+    QStringList dirChanges;
+
+    // setup database query
+    QSqlQuery storedRecord(m_db);
+
+    // query database for list of files
+    storedRecord.exec("SELECT absFilePath, lastModified FROM files");
+
+    // Debug
+    qDebug() << storedRecord.lastQuery();
+
+    // compare result (database/stored snapshot) to fileList (current snapshot)
+    while(storedRecord.next())
+    {
+        QString absFilePath = storedRecord.value(0).toString();
+        qint64 lMStored = storedRecord.value(1).toLongLong();
+
+        // debug
+        qDebug() << absFilePath << ", " << lMStored;
+
+        // check file existence
+        /*if(fileList.contains(absFilePath))
+        {
+            QFileInfo fileInfo = fileList.value(absFilePath);
+
+            // last Modified
+            qint64 lMCurrent = fileInfo.lastModified().currentMSecsSinceEpoch();
+
+            if(lMStored != lMCurrent)
+            {
+                storedRecord.prepare("UPDATE files SET lastModified = :lastModified "
+                              "WHERE absFilePath= :absFilePath");
+                storedRecord.bindValue(":lastModified", lMCurrent);
+                storedRecord.bindValue(":absFilePath", absFilePath);
+                storedRecord.exec();
+
+                // Debug
+                qDebug() << storedRecord.lastQuery();
+
+                // this file has been modified
+                dirChanges.append(absFilePath);
+            }
+
+            // delete this file from fileList, we have processed it
+            fileList.remove(absFilePath);
+        }
+        else
+        {
+            storedRecord.prepare("DELETE FROM files WHERE absFilePath= :absFilePath");
+            storedRecord.bindValue(":absFilePath", absFilePath);
+            storedRecord.exec();
+
+            // Debug
+            qDebug() << storedRecord.lastQuery();
+
+            // this file has been deleted
+            dirChanges.append(absFilePath);
+        }*/
+    }
+
+    /*storedRecord.prepare("INSERT INTO files (absFilePath, lastModified) "
+                  "VALUES (:absFilePath, :lastModified)");
+
+    // any files left in fileList have been added
+    for(QHash<QString, QFileInfo>::iterator i = fileList.begin(); i != fileList.end(); ++i)
+    {
+        QString absFilePath = i.key();
+        qint64 lastModified = i.value().lastModified().currentMSecsSinceEpoch();
+
+        storedRecord.bindValue(":absFilePath", absFilePath);
+        storedRecord.bindValue(":lastModified", lastModified);
+        storedRecord.exec();
+
+        // this file has been added
+        dirChanges.append(absFilePath);
+    }*/
+
+    // close query
+    storedRecord.finish();
+
+    return dirChanges;
+}
+
+bool FileSystemWatcher::createFileTable()
+{
+    bool success = false;
+
+    if(m_db.isOpen())
+    {
+        if(m_db.tables().contains("files"))
+        {
+            success = true;
+        }
+        else
+        {
+            QSqlQuery query(m_db);
+
+            // create file table
+            success = query.exec("CREATE TABLE files "
+                                 "(absFilePath TEXT primary key, "
+                                 "lastModified UNSIGNED BIG INT, "
+                                 "fileSize UNSIGNED BIG INT)");
+
+            // Debug
+            qDebug() << query.lastQuery();
+
+            query.finish();
+        }
+    }
+
+    return success;
 }
 
 #if WAF
diff --git a/filesystemwatcher/filesystemwatcher.h b/filesystemwatcher/filesystemwatcher.h
index d4ed8b6..3f78b6b 100644
--- a/filesystemwatcher/filesystemwatcher.h
+++ b/filesystemwatcher/filesystemwatcher.h
@@ -2,35 +2,49 @@
 #define FILESYSTEMWATCHER_H
 
 #include <QtGui>
+#include <QSqlDatabase>
+#include <QSqlQuery>
+#include <QSqlResult>
+#include <QDebug>
+#include <QHash>
 
 namespace Ui {
-class filesystemwatcher;
+class FileSystemWatcher;
 }
 
-class filesystemwatcher : public QMainWindow
+class FileSystemWatcher : public QMainWindow
 {
     Q_OBJECT
-    
+
 public:
     // constructor
-    filesystemwatcher(QString dirPath, QWidget *parent = 0);
+    FileSystemWatcher(QString dirPath, QWidget *parent = 0);
 
     // destructor
-    ~filesystemwatcher();
+    ~FileSystemWatcher();
 
 private slots:
-    // signal for changes to monitored files
-    void fileChangedSlot(QString filePath);
-
     // signal for changes to monitored directories
     void dirChangedSlot(QString dirPath);
-    
+
 private:
-    Ui::filesystemwatcher* m_ui; // user interface
+    // scan directory and populate file list
+    QHash<QString, QFileInfo> scanDirectory(QString filePath);
+
+    // reconcile directory, find changes
+    QStringList reconcileDirectory(QHash<QString, QFileInfo> fileList);
+
+    // create file table in database
+    bool createFileTable();
+
+private:
+    Ui::FileSystemWatcher* m_ui; // user interface
     QFileSystemWatcher* m_watcher; // filesystem watcher
     QStringListModel* m_listViewModel; // list view model
     QListView* m_listView; // list
     QString m_dirPath; // monitored path
+
+    QSqlDatabase m_db; // filesystem database
 };
 
 #endif // FILESYSTEMWATCHER_H
diff --git a/filesystemwatcher/filesystemwatcher.ui b/filesystemwatcher/filesystemwatcher.ui
index 1c5e766..2abbaa9 100644
--- a/filesystemwatcher/filesystemwatcher.ui
+++ b/filesystemwatcher/filesystemwatcher.ui
@@ -1,6 +1,6 @@
 <ui version="4.0">
- <class>filesystemwatcher</class>
- <widget class="QMainWindow" name="filesystemwatcher" >
+ <class>FileSystemWatcher</class>
+ <widget class="QMainWindow" name="FileSystemWatcher" >
   <property name="geometry" >
    <rect>
     <x>0</x>
@@ -10,7 +10,7 @@
    </rect>
   </property>
   <property name="windowTitle" >
-   <string>filesystemwatcher</string>
+   <string>FileSystemWatcher</string>
   </property>
   <widget class="QMenuBar" name="menuBar" />
   <widget class="QToolBar" name="mainToolBar" />
diff --git a/filesystemwatcher/main.cpp b/filesystemwatcher/main.cpp
index dc2bc85..e9949ec 100644
--- a/filesystemwatcher/main.cpp
+++ b/filesystemwatcher/main.cpp
@@ -6,8 +6,8 @@
     QApplication app(argc, argv);
 
     // invoke file system watcher on specified path
-    filesystemwatcher watcher("/Users/jared/Desktop");
+    FileSystemWatcher watcher("/Users/jared/Desktop");
     watcher.show();
-    
+
     return app.exec();
 }
diff --git a/wscript b/wscript
index 449ad2f..23d2679 100644
--- a/wscript
+++ b/wscript
@@ -142,5 +142,5 @@
         defines = "WAF",
         source = "filesystemwatcher/filesystemwatcher.cpp filesystemwatcher/filesystemwatcher.ui filesystemwatcher/main.cpp",
         includes = "filesystemwatcher src include .",
-        use = "QTCORE QTGUI"
+        use = "QTCORE QTGUI QTSQL"
         )