浏览代码

Replace textual model with proper dir model

Change-Id: Ib16a0e943a3134dd8542a933b90854ef0e9f5818
Donald Carr 9 年之前
父节点
当前提交
b3c76134a7
共有 3 个文件被更改,包括 71 次插入70 次删除
  1. 10 16
      main.cpp
  2. 50 38
      picturemodel.cpp
  3. 11 16
      picturemodel.h

+ 10 - 16
main.cpp

@@ -4,20 +4,10 @@
 #include <QThread>
 #include <QSettings>
 #include <QSurfaceFormat>
+#include <QTimer>
 
 #include <picturemodel.h>
 
-class PictureThreadWrapper : public QObject {
-public:
-    PictureThreadWrapper(QObject *parent = 0) : QObject (parent) {
-        QSettings settings;
-        const QString &artPath = settings.value("artPath","/blackhole/media/art/Banksy").toString();
-        PictureModel::instance()->addSupportedExtension("jpg");
-        PictureModel::instance()->setModelRoot(artPath);
-        settings.setValue("artPath", artPath);
-    }
-};
-
 int main(int argc, char *argv[])
 {
     qsrand(time(NULL));
@@ -41,14 +31,18 @@ int main(int argc, char *argv[])
     }
 
     QQmlApplicationEngine engine;
-
     QThread scanningThread;
-    PictureThreadWrapper *wrapper = new PictureThreadWrapper();
-    wrapper->moveToThread(&scanningThread);
-    scanningThread.start();
+    PictureModel *model = new PictureModel();
+    const QString &artPath = settings.value("artPath","/blackhole/media/art").toString();
 
-    engine.rootContext()->setContextProperty("imageModel", PictureModel::instance());
+    model->addSupportedExtension("jpg");
+    model->moveToThread(&scanningThread);
+    scanningThread.start();
+    //QTimer::singleShot(0, model, [model,artPath]() { model->setModelRoot(artPath); });
+    QMetaObject::invokeMethod(model, "setModelRoot", Qt::QueuedConnection, Q_ARG(QString,artPath));
+    settings.setValue("artPath", artPath);
 
+    engine.rootContext()->setContextProperty("imageModel", model);
     engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
 
     return app.exec();

+ 50 - 38
picturemodel.cpp

@@ -1,79 +1,91 @@
 #include "picturemodel.h"
 
-#include <ftw.h>
-#include <stdio.h>
-
 #include <QDir>
 
 #include <QDebug>
 
-PictureModel* PictureModel::model = 0;
+struct FSNode {
+  FSNode(const QString& rname, const FSNode *pparent = nullptr)
+      : name(rname),
+        parent(pparent) { /**/ }
 
-int handleDirNode(const char *fpath, const struct stat *sb, int type, struct FTW *ftwbuf) {
-    if (type == FTW_F) {
-      PictureModel::instance()->addPath(fpath);
-    }
-    return 0;
-}
+  const QString name;
+  const FSNode *parent;
+};
 
 PictureModel::PictureModel(QObject *parent)
+    : QAbstractListModel(parent)
 { /**/ }
 
-PictureModel *PictureModel::instance()
+PictureModel::~PictureModel()
 {
-    if (!model) {
-        model = new PictureModel();
-    }
-    return model;
+    // TODO: Destroy model
 }
 
-bool PictureModel::setModelRoot(const QString &root)
+void PictureModel::addModelNode(const FSNode* parentNode)
 {
-    qDebug() << "Flattening" << root;
+    // TODO: Check for symlink recursion
+    QDir parentDir(qualifyNode(parentNode));
 
+    foreach(const QString &currentDir, parentDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
+        const FSNode *dir = new FSNode(currentDir, parentNode);
+        addModelNode(dir);
+    }
+
+    foreach(const QString &currentFile, parentDir.entryList(QDir::Files)) {
+        if (!extensions.isEmpty()) {
+            QString extension = currentFile.mid(currentFile.length() - 3);
+            if (!extensions.contains(extension))
+                continue;
+        }
+        const FSNode *file = new FSNode(currentFile, parentNode);
+        files << file;
+    }
+}
+
+void PictureModel::setModelRoot(const QString &root)
+{
     QDir currentDir(root);
     if (!currentDir.exists()) {
         qDebug() << "Being told to watch a non existent directory";
-        return false;
     }
+    addModelNode(new FSNode(root));
 
-//    QString dirName = currentDir.dirName();
-//    qDebug() << dirName;
-//    currentDir.cdUp();
-//    QDir::setCurrent(currentDir.path());
-
-    nftw(root.toLatin1().data(), handleDirNode, 1000, FTW_PHYS);
-    qDebug() << "Finished flattening";
-    return true;
+//    foreach(FSNode *node, files) {
+//        qDebug() << "Contains:" << qualifyNode(node);
+//    }
 }
 
 int PictureModel::rowCount(const QModelIndex &parent) const
 {
-    return paths.length();
+    return files.length();
 }
 
 QString PictureModel::randomPicture() const
 {
-    return paths.at(qrand()%paths.size());
+    return qualifyNode(files.at(qrand()%files.size()));
 }
 
 QVariant PictureModel::data(const QModelIndex &index, int role) const
 {
-    if (index.row() < 0 || index.row() >= paths.length())
+    if (index.row() < 0 || index.row() >= files.length())
         return QVariant();
 
-    return paths.at(index.row());
+    const FSNode *node = files.at(index.row());
+
+    return qualifyNode(node);
 }
 
-bool PictureModel::addPath(const QString &path)
-{
-    if (!extensions.isEmpty()) {
-        QString extension = path.mid(path.length() - 3);
-        if (!extensions.contains(extension))
-            return false;
+QString PictureModel::qualifyNode(const FSNode *node) const {
+    QString qualifiedPath;
+
+    while(node->parent != nullptr) {
+        qualifiedPath = "/" + node->name + qualifiedPath;
+        node = node->parent;
     }
-    paths << path;
-    return true;
+    qualifiedPath = node->name + qualifiedPath;
+
+    return qualifiedPath;
 }
 
 void PictureModel::addSupportedExtension(const QString &extension)

+ 11 - 16
picturemodel.h

@@ -3,40 +3,35 @@
 
 #include <QAbstractListModel>
 
-class Node {
-public:
-  Node(const QString &name) : m_name(name) {}
-  // TODO: symlink considerations
-  // parentNode is clearly always a directory
-private:
-  Node *m_parentNode;
-  QString m_name;
-};
+class FSNode;
 
 class PictureModel : public QAbstractListModel
 {
     Q_OBJECT
+
 public:
     enum PictureRoles {
         PathRole = Qt::UserRole + 1
     };
 
-    static PictureModel* instance();
-    bool setModelRoot(const QString &root);
+    PictureModel(QObject *parent = nullptr);
+    ~PictureModel();
+
     int rowCount(const QModelIndex & parent = QModelIndex()) const;
 
     Q_INVOKABLE QString randomPicture() const;
     QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
 
-    bool addPath(const QString &path);
+    Q_INVOKABLE void setModelRoot(const QString &root);
     void addSupportedExtension(const QString &extension);
+    void addModelNode(const FSNode *parent);
+    QString qualifyNode(const FSNode *node) const;
+
 protected:
     QHash<int, QByteArray> roleNames() const;
+
 private:
-    static PictureModel* model;
-    PictureModel(QObject *parent = 0);
-    QList<Node> nodes;
-    QStringList paths;
+    QList<const FSNode*> files;
     QStringList extensions;
 };