1414#include < qqmlparserstatus.h>
1515#include < qrunnable.h>
1616#include < qstringview.h>
17+ #include < qtclasshelpermacros.h>
1718#include < qtmetamacros.h>
1819
1920#include " ../core/doc.hpp"
@@ -140,11 +141,13 @@ class FileViewWriter: public FileViewOperation {
140141 bool doAtomicWrite;
141142};
142143
143- // /! Simplified reader for small files.
144+ class FileViewAdapter ;
145+
146+ // /! Simple accessor for small files.
144147// / A reader for small to medium files that don't need seeking/cursor access,
145148// / suitable for most text files.
146149// /
147- // / #### Example: Reading a JSON
150+ // / #### Example: Reading a JSON as text
148151// / ```qml
149152// / FileView {
150153// / id: jsonFile
@@ -156,6 +159,8 @@ class FileViewWriter: public FileViewOperation {
156159// /
157160// / readonly property var jsonData: JSON.parse(jsonFile.text())
158161// / ```
162+ // /
163+ // / Also see @@JsonAdapter for an alternative way to handle reading and writing JSON files.
159164class FileView : public QObject {
160165 Q_OBJECT;
161166 // clang-format off
@@ -215,6 +220,14 @@ class FileView: public QObject {
215220 // / > }
216221 // / > ```
217222 Q_PROPERTY (bool watchChanges READ default WRITE default NOTIFY watchChangesChanged BINDABLE bindableWatchChanges);
223+ // / In addition to directly reading/writing the file as text, *adapters* can be used to
224+ // / expose a file's content in new ways.
225+ // /
226+ // / An adapter will automatically be given the loaded file's content.
227+ // / Its state may be saved with @@writeAdapter().
228+ // /
229+ // / Currently the only adapter is @@JsonAdapter.
230+ Q_PROPERTY (FileViewAdapter* adapter READ adapter WRITE setAdapter NOTIFY adapterChanged);
218231
219232 QSDOC_HIDE Q_PROPERTY (QString __path READ path WRITE setPath NOTIFY pathChanged);
220233 QSDOC_HIDE Q_PROPERTY (QString __text READ text NOTIFY internalTextChanged);
@@ -230,11 +243,14 @@ class FileView: public QObject {
230243 QSDOC_HIDE Q_PROPERTY (bool __blockAllReads READ blockAllReads WRITE setBlockAllReads NOTIFY blockAllReadsChanged);
231244 QSDOC_HIDE Q_PROPERTY (bool __printErrors READ default WRITE default NOTIFY printErrorsChanged BINDABLE bindablePrintErrors);
232245 // clang-format on
246+ Q_CLASSINFO (" DefaultProperty" , " adapter" );
233247 QML_NAMED_ELEMENT (FileViewInternal);
234248 QSDOC_NAMED_ELEMENT (FileView);
235249
236250public:
237251 explicit FileView (QObject* parent = nullptr ): QObject(parent) {}
252+ ~FileView () override ;
253+ Q_DISABLE_COPY_MOVE (FileView);
238254
239255 // / Returns the data of the file specified by @@path as text.
240256 // /
@@ -280,6 +296,8 @@ class FileView: public QObject {
280296 // / This will not block if @@blockLoading is set, only if @@blockAllReads is true.
281297 // / It acts the same as changing @@path to a new file, except loading the same file.
282298 Q_INVOKABLE void reload ();
299+ // / Write the content of the current @@adapter to the selected file.
300+ Q_INVOKABLE void writeAdapter ();
283301
284302 [[nodiscard]] QString path () const ;
285303 void setPath (const QString& path);
@@ -312,6 +330,9 @@ class FileView: public QObject {
312330 [[nodiscard]] QBindable<bool > bindablePrintErrors () { return &this ->bPrintErrors ; }
313331 [[nodiscard]] QBindable<bool > bindableWatchChanges () { return &this ->bWatchChanges ; }
314332
333+ [[nodiscard]] FileViewAdapter* adapter () const ;
334+ void setAdapter (FileViewAdapter* adapter);
335+
315336signals:
316337 // / Emitted if the file was loaded successfully.
317338 void loaded ();
@@ -323,6 +344,8 @@ class FileView: public QObject {
323344 void saveFailed (qs::io::FileViewError::Enum error);
324345 // / Emitted if the file changes on disk and @@watchChanges is true.
325346 void fileChanged ();
347+ // / Emitted when the active @@adapter$'s data is changed.
348+ void adapterUpdated ();
326349
327350 void pathChanged ();
328351 QSDOC_HIDE void internalTextChanged ();
@@ -337,9 +360,11 @@ class FileView: public QObject {
337360 void atomicWritesChanged ();
338361 void printErrorsChanged ();
339362 void watchChangesChanged ();
363+ void adapterChanged ();
340364
341365private slots:
342366 void operationFinished ();
367+ void onAdapterDestroyed ();
343368
344369private:
345370 void loadAsync (bool doStringConversion);
@@ -373,6 +398,7 @@ private slots:
373398 bool mBlockLoading = false ;
374399 bool mBlockAllReads = false ;
375400
401+ FileViewAdapter* mAdapter = nullptr ;
376402 QFileSystemWatcher* watcher = nullptr ;
377403
378404 GuardedEmitter<&FileView::internalTextChanged> textChangedEmitter;
@@ -406,4 +432,26 @@ private slots:
406432 void setBlockAllReads (bool blockAllReads);
407433};
408434
435+ // / See @@FileView.adapter.
436+ class FileViewAdapter : public QObject {
437+ Q_OBJECT;
438+ QML_ELEMENT;
439+ QML_UNCREATABLE (" " );
440+
441+ public:
442+ void setFileView (FileView* fileView);
443+ virtual void deserializeAdapter (const QByteArray& data) = 0;
444+ [[nodiscard]] virtual QByteArray serializeAdapter () = 0;
445+
446+ signals:
447+ // / This signal is fired when data in the adapter changes, and triggers @@FileView.adapterUpdated(s).
448+ void adapterUpdated ();
449+
450+ private slots:
451+ void onDataChanged ();
452+
453+ protected:
454+ FileView* mFileView = nullptr ;
455+ };
456+
409457} // namespace qs::io
0 commit comments