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 ProcessesItemModel(const score::GUIApplicationContext& ctx, QObject* parent);
53
54 void rescan();
55 QModelIndex find(const Process::ProcessModelFactory::ConcreteKey& k);
56
57 ProcessNode& rootNode() override;
58 const ProcessNode& rootNode() const override;
59
60 // Data reading
61 int columnCount(const QModelIndex& parent) const override;
62 QVariant data(const QModelIndex& index, int role) const override;
63
64 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
65 Qt::ItemFlags flags(const QModelIndex& index) const override;
66
67 // Drag, drop, etc.
68 QStringList mimeTypes() const override;
69 QMimeData* mimeData(const QModelIndexList& indexes) const override;
70 Qt::DropActions supportedDragActions() const override;
71
72 void on_newPlugin(const score::InterfaceBase& fact);
73
74private:
75 ProcessNode& addCategory(const QString& cat);
76 const score::GUIApplicationContext& context;
77 ProcessNode m_root;
78};
79
85{
86 Library::ProcessNode* parent{};
87 QDir libraryFolder;
88 std::string libraryFolderPath{};
89 std::string defaultPresetsPath{};
90 ossia::hash_map<QString, Library::ProcessNode*> categories;
91
92 void init(
93 std::string process_name, const QModelIndex& idx,
95 {
96 categories.clear();
97 parent = reinterpret_cast<Library::ProcessNode*>(idx.internalPointer());
98 SCORE_ASSERT(parent);
99
100 // We use the parent folder as category...
101 libraryFolder.setPath(ctx.settings<Library::Settings::Model>().getPackagesPath());
102 libraryFolderPath = libraryFolder.absolutePath().toStdString();
103
104 // Also so that stuff in Presets/<Name of the process> does not needlessly go into a subfolder
105 defaultPresetsPath = "Presets/" + process_name;
106 }
107
108 [[deprecated]] void add(const QFileInfo& file, Library::ProcessData&& pdata)
109 {
110 SCORE_ASSERT(parent);
111 auto parentFolder = file.dir().dirName();
112 if(auto it = categories.find(parentFolder); it != categories.end())
113 {
114 Library::addToLibrary(*it->second, std::move(pdata));
115 }
116 else
117 {
118 if(file.dir() == libraryFolder
119 || file.absolutePath().endsWith(defaultPresetsPath.c_str()))
120 {
121 Library::addToLibrary(*parent, std::move(pdata));
122 }
123 else
124 {
125 auto& category = Library::addToLibrary(
126 *parent, Library::ProcessData{{{}, parentFolder, {}}, {}});
127 Library::addToLibrary(category, std::move(pdata));
128 categories[parentFolder] = &category;
129 }
130 }
131 }
132
133 void add(const score::PathInfo& file, Library::ProcessData&& pdata)
134 {
135 SCORE_ASSERT(parent);
136 auto parentFolder
137 = QString::fromUtf8(file.parentDirName.data(), file.parentDirName.size());
138 if(auto it = categories.find(parentFolder); it != categories.end())
139 {
140 Library::addToLibrary(*it->second, std::move(pdata));
141 }
142 else
143 {
144 if(file.absolutePath == libraryFolderPath
145 || file.absolutePath.ends_with(defaultPresetsPath))
146 {
147 Library::addToLibrary(*parent, std::move(pdata));
148 }
149 else
150 {
151 auto& category = Library::addToLibrary(
152 *parent, Library::ProcessData{{{}, parentFolder, {}}, {}});
153 Library::addToLibrary(category, std::move(pdata));
154 categories[parentFolder] = &category;
155 }
156 }
157 }
158};
159
166template <typename T>
168 std::function<std::optional<T>(std::string_view)> filter,
169 std::function<void(std::string_view, T&&)> commit)
170{
171 return {.filter = [filter = std::move(filter),
172 commit = std::move(commit)](std::string_view path)
173 -> std::function<void()> {
174 auto result = filter(path);
175 if(!result)
176 return {};
177
178 return [commit, p = std::string(path), data = std::move(*result)]() mutable {
179 commit(p, std::move(data));
180 };
181 }};
182}
183
184}
185
186inline QDataStream& operator<<(QDataStream& i, const Library::ProcessData& sel)
187{
188 return i;
189}
190inline QDataStream& operator>>(QDataStream& i, Library::ProcessData& sel)
191{
192 return i;
193}
194
195W_REGISTER_ARGTYPE(Library::ProcessData)
196Q_DECLARE_METATYPE(Library::ProcessData)
197W_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
Base toolkit upon which the software is built.
Definition Application.cpp:113
Definition ProcessesItemModel.hpp:33
Definition ProcessesItemModel.hpp:85
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:38