1 #ifndef REMOTEMODEL_H 2 #define REMOTEMODEL_H 3 4 #include <QAbstractItemModel> 5 #include <QUrl> 6 7 #include <json.hpp> 8 9 // List of fields stored in the JSON data 10 enum RemoteModelColumns 11 { 12 RemoteModelColumnName, 13 RemoteModelColumnType, 14 RemoteModelColumnUrl, 15 RemoteModelColumnCommitId, 16 RemoteModelColumnSize, 17 RemoteModelColumnLastModified, 18 RemoteModelColumnDefaultBranch, 19 RemoteModelColumnLicence, 20 RemoteModelColumnOneLineDescription, 21 RemoteModelColumnPublic, 22 RemoteModelColumnRepoModified, 23 RemoteModelColumnSha256, 24 25 RemoteModelColumnCount 26 }; 27 28 class RemoteModelItem 29 { 30 public: 31 explicit RemoteModelItem(RemoteModelItem* parent = nullptr); 32 ~RemoteModelItem(); 33 34 QVariant value(RemoteModelColumns column) const; 35 void setValue(RemoteModelColumns column, QVariant value); 36 37 bool fetchedDirectoryList() const; 38 void setFetchedDirectoryList(bool fetched); 39 40 void appendChild(RemoteModelItem* item); 41 RemoteModelItem* child(int row) const; 42 RemoteModelItem* parent() const; 43 int childCount() const; 44 int row() const; 45 46 // This function assumes the JSON value it's getting passed is an array ("[{...}, {...}, {...}, ...]"). It returns a list of model items, one 47 // per array entry and each with the specified parent set. 48 static std::vector<RemoteModelItem*> loadArray(const nlohmann::json& array, RemoteModelItem* parent = nullptr); 49 50 private: 51 // These are just the fields from the json objects returned by the dbhub.io server 52 QVariant m_values[RemoteModelColumnCount]; 53 54 // Child items and parent item 55 std::vector<RemoteModelItem*> m_children; 56 RemoteModelItem* m_parent; 57 58 // Indicates whether we already tried fetching a directory listing for this item. This serves two purposes: 59 // 1) When having an empty directory this allows us to remove the expandable flag for this item. 60 // 2) Between sending a network request and getting the reply this flag is already set, avoiding a second or third request being sent in the meantime. 61 bool m_fetchedDirectoryList; 62 }; 63 64 class RemoteModel : public QAbstractItemModel 65 { 66 Q_OBJECT 67 68 public: 69 explicit RemoteModel(QObject* parent); 70 ~RemoteModel() override; 71 72 void setNewRootDir(const QString& url, const QString& cert); 73 void refresh(); 74 75 QModelIndex index(int row, int column,const QModelIndex& parent = QModelIndex()) const override; 76 QModelIndex parent(const QModelIndex& index) const override; 77 78 QVariant data(const QModelIndex& index, int role) const override; 79 QVariant headerData(int section, Qt::Orientation orientation, int role) const override; 80 81 int rowCount(const QModelIndex& parent = QModelIndex()) const override; 82 int columnCount(const QModelIndex& parent = QModelIndex()) const override; 83 bool hasChildren(const QModelIndex& parent) const override; 84 85 bool canFetchMore(const QModelIndex& parent) const override; 86 void fetchMore(const QModelIndex& parent) override; 87 88 // This helper function takes a model index and returns the according model item. An invalid model index is used to indicate the 89 // root item, so if the index is invalid the root item is returned. This means that if you need to check for actual invalid indices 90 // this needs to be done prior to calling this function. 91 const RemoteModelItem* modelIndexToItem(const QModelIndex& idx) const; 92 93 // Returns the current client certificate 94 const QString& currentClientCertificate() const; 95 96 signals: 97 // This signal is emitted whenever a directory listing has been received and parsed 98 void directoryListingParsed(QModelIndex parent); 99 100 private slots: 101 // This is called whenever a network reply containing a directory listing arrives 102 void parseDirectoryListing(const QString& text, QModelIndex parent); 103 104 private: 105 // The header list is a list of column titles 106 const std::vector<QString> headerList; 107 108 // Pointer to the root item. This contains all the actual item data. 109 RemoteModelItem* rootItem; 110 111 // This stores the currently used network identity so it can be used for further requests, e.g. for 112 // lazy population. 113 QUrl currentRootDirectory; 114 QString currentClientCert; 115 QString currentUserName; 116 }; 117 118 #endif 119