Line data Source code
1 : // SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2 : // SPDX-License-Identifier: GPL-3.0-or-later
3 : /**
4 : * @file
5 : * @brief StoreTree: owns the QFileSystemModel and StoreModel behind the
6 : * password tree view and maps view indexes to store paths.
7 : */
8 : #ifndef SRC_STORETREE_H_
9 : #define SRC_STORETREE_H_
10 :
11 : #include "storemodel.h"
12 : #include <QFileInfo>
13 : #include <QFileSystemModel>
14 : #include <QModelIndex>
15 : #include <QObject>
16 : #include <QString>
17 :
18 : class Pass;
19 : class QTreeView;
20 :
21 : /**
22 : * @class StoreTree
23 : * @ingroup store
24 : * @brief The password store as shown in the tree: the QFileSystemModel, the
25 : * StoreModel proxy on top of it and the QTreeView they drive, with
26 : * the path questions the main window keeps asking.
27 : *
28 : * Owns the two models. setStore() is the one place that re-roots the file
29 : * system model, the proxy and the view together (this sequence used to be
30 : * spelled out five times); dirFor()/fileFor() are the two path mappings
31 : * that were duplicated across MainWindow and Util.
32 : */
33 : class StoreTree : public QObject {
34 : Q_OBJECT
35 :
36 : public:
37 : /**
38 : * @brief Attach the proxy model to the view and set its look: hidden
39 : * header, indentation, scroll bars, context-menu policy. Column
40 : * hiding and sorting need a source model and happen in setStore().
41 : * @param view The tree view to drive.
42 : * @param parent Owner.
43 : */
44 : explicit StoreTree(QTreeView *view, QObject *parent = nullptr);
45 :
46 : /**
47 : * @brief Point everything at @p path: file system root, proxy store and
48 : * view root index. Also drops a search filter.
49 : * @param path Password store directory.
50 : */
51 : void setStore(const QString &path);
52 :
53 : /**
54 : * @brief Hand the proxy the backend it drops onto.
55 : * @param pass Active backend (not owned).
56 : */
57 : void setPass(Pass *pass);
58 :
59 : /**
60 : * @brief Filter the visible entries.
61 : * @param pattern Regular expression matched against entry names; an
62 : * invalid or empty one shows everything.
63 : */
64 : void setFilter(const QRegularExpression &pattern);
65 :
66 : /**
67 : * @brief The folder an index stands for.
68 : * @param index View index; a file maps to its folder, an invalid index to
69 : * the store root.
70 : * @param forPass true for a store-relative path ("" for the root),
71 : * false for an absolute one.
72 : * @return Folder path ending in the native separator (see forPass).
73 : */
74 : [[nodiscard]] auto dirFor(const QModelIndex &index, bool forPass) const
75 : -> QString;
76 :
77 : /**
78 : * @brief dirFor() applied to the view's current index.
79 : * @param forPass As in dirFor().
80 : * @return Folder path.
81 : */
82 : [[nodiscard]] auto currentDir(bool forPass) const -> QString;
83 :
84 : /**
85 : * @brief The entry an index stands for.
86 : * @param index View index; folders and invalid indexes yield an empty
87 : * string.
88 : * @param forPass true for the pass name (store-relative, no .gpg),
89 : * false for the absolute .gpg path.
90 : * @return Entry name or path, empty when @p index is not a file.
91 : */
92 : [[nodiscard]] auto fileFor(const QModelIndex &index, bool forPass) const
93 : -> QString;
94 :
95 : /**
96 : * @brief fileFor() applied to the view's current index.
97 : * @param forPass As in fileFor().
98 : * @return Entry name or path.
99 : */
100 : [[nodiscard]] auto currentFile(bool forPass) const -> QString;
101 :
102 : /**
103 : * @brief File system information for a view index.
104 : * @param index View index.
105 : * @return QFileInfo of the underlying path.
106 : */
107 : [[nodiscard]] auto fileInfo(const QModelIndex &index) const -> QFileInfo;
108 :
109 : /**
110 : * @brief The view index for an absolute path, or invalid when the file
111 : * system model does not (yet) know it.
112 : * @param path Absolute path inside the store.
113 : * @return Proxy index.
114 : */
115 : [[nodiscard]] auto indexFor(const QString &path) const -> QModelIndex;
116 :
117 : /**
118 : * @brief The proxy's root index for the current store.
119 : * @return Proxy index of the store root.
120 : */
121 : [[nodiscard]] auto rootIndex() -> QModelIndex;
122 :
123 : /**
124 : * @brief The view's current index.
125 : * @return Proxy index, possibly invalid.
126 : */
127 : [[nodiscard]] auto currentIndex() const -> QModelIndex;
128 :
129 : /// @return The store directory set with setStore().
130 : [[nodiscard]] auto store() const -> QString { return m_store; }
131 : /// @return The proxy the view shows.
132 : [[nodiscard]] auto proxy() -> StoreModel & { return m_proxy; }
133 : /// @return The file system model under the proxy.
134 8 : [[nodiscard]] auto fileSystem() -> QFileSystemModel & { return m_fs; }
135 : /// @return The tree view.
136 : [[nodiscard]] auto view() const -> QTreeView * { return m_view; }
137 :
138 : private:
139 : /** @brief The tree view this object drives; owned by the main window. */
140 : QTreeView *m_view;
141 : /**
142 : * @brief Source model over the store directory, filtered to `*.gpg`;
143 : * re-rooted by setStore().
144 : */
145 : QFileSystemModel m_fs;
146 : /**
147 : * @brief Proxy the view shows: hides `.git`, strips `.gpg`, applies the
148 : * search filter and handles drag and drop.
149 : */
150 : StoreModel m_proxy;
151 : /** @brief Absolute store directory last passed to setStore(). */
152 : QString m_store;
153 : };
154 :
155 : #endif // SRC_STORETREE_H_
|