Loading...
Searching...
No Matches
ProcessesItemModel.hpp
1#pragma once
2#include <Process/ProcessFactory.hpp>
3#include <Process/ProcessMimeSerialization.hpp>
4
5#include <Library/LibrarySettings.hpp>
6
7#include <score/application/ApplicationContext.hpp>
8#include <score/model/tree/TreeNode.hpp>
9#include <score/model/tree/TreeNodeItemModel.hpp>
10#include <score/tools/File.hpp>
11#include <score/tools/RecursiveWatch.hpp>
12#include <score/tools/std/Optional.hpp>
13#include <score/tools/std/StringHash.hpp>
14
15#include <ossia/detail/hash_map.hpp>
16
17#include <QDir>
18#include <QIcon>
19
20#include <nano_observer.hpp>
21#include <score_plugin_library_export.h>
22
23#include <verdigris>
24
25namespace score
26{
27struct GUIApplicationContext;
28}
29
30namespace Library
31{
33{
34 QIcon icon;
35};
36
38SCORE_PLUGIN_LIBRARY_EXPORT
39ProcessNode& addToLibrary(ProcessNode& parent, Library::ProcessData&& data);
40
41class SCORE_PLUGIN_LIBRARY_EXPORT ProcessesItemModel
42 : public TreeNodeBasedItemModel<ProcessNode>
43 , public Nano::Observer
44{
45public:
46 using QAbstractItemModel::beginInsertRows;
47 using QAbstractItemModel::endInsertRows;
48
49 using QAbstractItemModel::beginRemoveRows;
50 using QAbstractItemModel::endRemoveRows;
51
52 // async scanners (LV2, CLAP) rebuild whole subtrees on descriptorsChanged
53 using QAbstractItemModel::beginResetModel;
54 using QAbstractItemModel::endResetModel;
55
56 ProcessesItemModel(const score::GUIApplicationContext& ctx, QObject* parent);
57
58 void rescan();
59 QModelIndex find(const Process::ProcessModelFactory::ConcreteKey& k);
60
61 ProcessNode& rootNode() override;
62 const ProcessNode& rootNode() const override;
63
64 // Data reading
65 int columnCount(const QModelIndex& parent) const override;
66 QVariant data(const QModelIndex& index, int role) const override;
67
68 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
69 Qt::ItemFlags flags(const QModelIndex& index) const override;
70
71 // Drag, drop, etc.
72 QStringList mimeTypes() const override;
73 QMimeData* mimeData(const QModelIndexList& indexes) const override;
74 Qt::DropActions supportedDragActions() const override;
75
76 void on_newPlugin(const score::InterfaceBase& fact);
77
78private:
79 ProcessNode& addCategory(const QString& cat);
80 const score::GUIApplicationContext& context;
81 ProcessNode m_root;
82};
83
89{
90 Library::ProcessNode* parent{};
91 QDir libraryFolder;
92 std::string libraryFolderPath{};
93 std::string defaultPresetsPath{};
94 ossia::hash_map<QString, Library::ProcessNode*> categories;
95
96 void init(
97 std::string process_name, const QModelIndex& idx,
99 {
100 categories.clear();
101 parent = reinterpret_cast<Library::ProcessNode*>(idx.internalPointer());
102 SCORE_ASSERT(parent);
103
104 // We use the parent folder as category...
105 libraryFolder.setPath(ctx.settings<Library::Settings::Model>().getPackagesPath());
106 libraryFolderPath = libraryFolder.absolutePath().toStdString();
107
108 // Also so that stuff in Presets/<Name of the process> does not needlessly go into a subfolder
109 defaultPresetsPath = "Presets/" + process_name;
110 }
111
112 [[deprecated]] void add(const QFileInfo& file, Library::ProcessData&& pdata)
113 {
114 SCORE_ASSERT(parent);
115 auto parentFolder = file.dir().dirName();
116 if(auto it = categories.find(parentFolder); it != categories.end())
117 {
118 Library::addToLibrary(*it->second, std::move(pdata));
119 }
120 else
121 {
122 if(file.dir() == libraryFolder
123 || file.absolutePath().endsWith(defaultPresetsPath.c_str()))
124 {
125 Library::addToLibrary(*parent, std::move(pdata));
126 }
127 else
128 {
129 auto& category = Library::addToLibrary(
130 *parent, Library::ProcessData{{{}, parentFolder, {}}, {}});
131 Library::addToLibrary(category, std::move(pdata));
132 categories[parentFolder] = &category;
133 }
134 }
135 }
136
137 void add(const score::PathInfo& file, Library::ProcessData&& pdata)
138 {
139 SCORE_ASSERT(parent);
140 auto parentFolder
141 = QString::fromUtf8(file.parentDirName.data(), file.parentDirName.size());
142 if(auto it = categories.find(parentFolder); it != categories.end())
143 {
144 Library::addToLibrary(*it->second, std::move(pdata));
145 }
146 else
147 {
148 if(file.absolutePath == libraryFolderPath
149 || file.absolutePath.ends_with(defaultPresetsPath))
150 {
151 Library::addToLibrary(*parent, std::move(pdata));
152 }
153 else
154 {
155 auto& category = Library::addToLibrary(
156 *parent, Library::ProcessData{{{}, parentFolder, {}}, {}});
157 Library::addToLibrary(category, std::move(pdata));
158 categories[parentFolder] = &category;
159 }
160 }
161 }
162};
163
170template <typename T>
172 std::function<std::optional<T>(std::string_view)> filter,
173 std::function<void(std::string_view, T&&)> commit)
174{
175 struct State
176 {
177 std::function<std::optional<T>(std::string_view)> filter;
178 std::function<void(std::string_view, T&&)> commit;
179 };
180 auto state = std::make_shared<State>(State{std::move(filter), std::move(commit)});
181
182 return {.filter = [state = std::move(state)](std::string_view path)
183 -> std::function<void()> {
184 auto result = state->filter(path);
185 if(!result)
186 return {};
187
188 return [commit = state->commit, p = std::string(path),
189 data = std::move(*result)]() mutable { commit(p, std::move(data)); };
190 }};
191}
192
193}
194
195inline QDataStream& operator<<(QDataStream& i, const Library::ProcessData& sel)
196{
197 return i;
198}
199inline QDataStream& operator>>(QDataStream& i, Library::ProcessData& sel)
200{
201 return i;
202}
203
204W_REGISTER_ARGTYPE(Library::ProcessData)
205Q_DECLARE_METATYPE(Library::ProcessData)
206W_REGISTER_ARGTYPE(std::optional<Library::ProcessData>)
Definition ProcessesItemModel.hpp:44
Definition LibrarySettings.hpp:46
Definition TreeNodeItemModel.hpp:38
Base class for plug-in interfaces.
Definition Interface.hpp:52
Utilities for OSSIA data structures.
Definition DeviceInterface.hpp:33
Base toolkit upon which the software is built.
Definition Application.cpp:113
Definition ProcessesItemModel.hpp:33
Definition ProcessesItemModel.hpp:89
Definition ProcessMimeSerialization.hpp:38
Used to access all the application-wide state and structures.
Definition ApplicationContext.hpp:25
Specializes ApplicationContext with the QMainWindow.
Definition GUIApplicationContext.hpp:15
Definition lib/score/tools/File.hpp:20
Definition RecursiveWatch.hpp:39