Tulip 5.7.1
Large graphs analysis and drawing
Loading...
Searching...
No Matches
PluginModel.h
1/*
2 *
3 * This file is part of Tulip (https://tulip.labri.fr)
4 *
5 * Authors: David Auber and the Tulip development Team
6 * from LaBRI, University of Bordeaux
7 *
8 * Tulip is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation, either version 3
11 * of the License, or (at your option) any later version.
12 *
13 * Tulip is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
17 *
18 */
19///@cond DOXYGEN_HIDDEN
20
21#ifndef PLUGINMODEL_H
22#define PLUGINMODEL_H
23
24#include <algorithm>
25
26#include <QIcon>
27#include <QFont>
28#include <QWidget>
29
30#include <tulip/TulipModel.h>
31#include <tulip/TlpQtTools.h>
32#include <tulip/PluginLister.h>
33
34#include <string>
35
36namespace tlp {
37/*
38 * @brief Build and manage a Qt Model of a list of plugins
39 */
40class TLP_QT_SCOPE SimplePluginListModel : public tlp::TulipModel {
41private:
42 QList<std::string> _list;
43
44public:
45 SimplePluginListModel(const std::list<std::string> &plugins, QObject *parent = nullptr);
46 ~SimplePluginListModel() override;
47 int columnCount(const QModelIndex & = QModelIndex()) const override;
48 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
49 QModelIndex parent(const QModelIndex &) const override;
50 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
51 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
52 QList<std::string> plugins() const;
53 std::string pluginName(const QModelIndex &index) const;
54};
55
56template <typename PLUGIN>
57class PluginModel : public tlp::TulipModel {
58 struct TreeItem {
59 TreeItem(QString name, QString info = "", TreeItem *parent = nullptr)
60 : name(name), info(info), parent(parent) {}
61 virtual ~TreeItem() {
62 qDeleteAll(children);
63 }
64 TreeItem *addChild(QString name, QString info = "") {
65 TreeItem *result = new TreeItem(name, info, this);
66 children.push_back(result);
67 return result;
68 }
69
70 QString name;
71 QString info;
72 TreeItem *parent;
73 QList<TreeItem *> children;
74 };
75 TreeItem *_root;
76
77 // FIXME: Non-optimized piece of crap, should be fixed
78 void buildTree() {
79 delete _root;
80 _root = new TreeItem("root");
81 QMap<QString, QMap<QString, QStringList>> pluginTree;
82 std::list<std::string> plugins = PluginLister::availablePlugins<PLUGIN>();
83
84 for (std::list<std::string>::iterator it = plugins.begin(); it != plugins.end(); ++it) {
85 std::string name = *it;
86 const Plugin &plugin = PluginLister::pluginInformation(name);
87 pluginTree[tlp::tlpStringToQString(plugin.category())]
88 [tlp::tlpStringToQString(plugin.group())]
89 .append(tlp::tlpStringToQString(name));
90 }
91
92 for (const QString &cat : pluginTree.keys()) {
93 TreeItem *catItem = _root->addChild(cat);
94
95 for (const QString &group : pluginTree[cat].keys()) {
96 TreeItem *groupItem = catItem;
97
98 if ((!group.isEmpty()) && (pluginTree[cat].keys().size() > 1))
99 groupItem = catItem->addChild(group);
100
101 // sort in case insensitive alphabetic order
102 std::sort(pluginTree[cat][group].begin(), pluginTree[cat][group].end(), QStringCaseCmp);
103
104 for (const QString &alg : pluginTree[cat][group]) {
105 const Plugin &plugin = PluginLister::pluginInformation(tlp::QStringToTlpString(alg));
106 std::string info = plugin.info();
107
108 // set info only if they contain more than one word
109 if (info.find(' ') != std::string::npos)
110 groupItem->addChild(alg, tlp::tlpStringToQString(info));
111 else
112 groupItem->addChild(alg);
113 }
114 }
115 }
116 }
117
118 QList<int> indexHierarchy(TreeItem *item) const {
119 QList<int> result;
120 TreeItem *parent = item->parent;
121 TreeItem *child = item;
122
123 while (child != _root) {
124 result.push_front(parent->children.indexOf(child));
125 parent = parent->parent;
126 child = child->parent;
127 }
128
129 return result;
130 }
131
132public:
133 explicit PluginModel(QObject *parent = nullptr) : TulipModel(parent), _root(nullptr) {
134 buildTree();
135 }
136 ~PluginModel() override {
137 delete _root;
138 }
139
140 int rowCount(const QModelIndex &parent = QModelIndex()) const override {
141 TreeItem *item = _root;
142
143 if (parent.isValid())
144 item = static_cast<TreeItem *>(parent.internalPointer());
145
146 return item->children.size();
147 }
148
149 int columnCount(const QModelIndex & = QModelIndex()) const override {
150 return 1;
151 }
152
153 QModelIndex parent(const QModelIndex &child) const override {
154 if (!child.isValid())
155 return QModelIndex();
156
157 TreeItem *childItem = static_cast<TreeItem *>(child.internalPointer());
158
159 if (childItem->parent == _root)
160 return QModelIndex();
161
162 QList<int> indexes = indexHierarchy(childItem->parent);
163 int row = indexes[indexes.size() - 1];
164 return createIndex(row, child.column(), childItem->parent);
165 }
166
167 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override {
168 TreeItem *parentItem = _root;
169
170 if (parent.isValid()) {
171 parentItem = static_cast<TreeItem *>(parent.internalPointer());
172 }
173
174 if (row >= parentItem->children.size())
175 return QModelIndex();
176
177 return createIndex(row, column, parentItem->children[row]);
178 }
179
180 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
181 TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
182
183 if (role == Qt::DisplayRole)
184 return item->name;
185 else if (role == Qt::ToolTipRole) {
186 if (item->info.isEmpty())
187 return item->name;
188 else
189 return QString("<table><tr><td><b>%1</b></td></tr><tr><td><i>%2</i></td></tr></table>")
190 .arg(item->name)
191 .arg(item->info);
192 } else if (role == Qt::FontRole && !index.parent().parent().isValid()) {
193 QFont f;
194 QWidget *p = dynamic_cast<QWidget *>(QAbstractItemModel::parent());
195 if (p)
196 f = p->font();
197
198 f.setBold(true);
199 return f;
200 } else if (role == Qt::DecorationRole && item->children.isEmpty() &&
202 const tlp::Plugin &p =
204 QIcon icon(tlp::tlpStringToQString(p.icon()));
205 return icon;
206 }
207
208 return QVariant();
209 }
210
211 Qt::ItemFlags flags(const QModelIndex &index) const override {
212 Qt::ItemFlags result(QAbstractItemModel::flags(index));
213
214 if (index.isValid()) {
215 TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
216
217 if (!PluginLister::pluginExists<PLUGIN>(tlp::QStringToTlpString(item->name)))
218 result = Qt::ItemIsEnabled;
219 }
220
221 return result;
222 }
223};
224} // namespace tlp
225
226#endif // PLUGINMODEL_H
227///@endcond
Top-level interface for plug-ins.
Definition: Plugin.h:85
virtual std::string icon() const
The icon (preferably a thumbnail) of the plugin.
static bool pluginExists(const std::string &pluginName)
Checks if a plugin of a given type is loaded This method checks the plugin "pluginName" is currently ...
Definition: PluginLister.h:85
static const Plugin & pluginInformation(const std::string &name)
Gets more detailed information about one specific plug-in.
std::string QStringToTlpString(const QString &toConvert)
Convert a QString to a Tulip UTF-8 encoded std::string.
Definition: TlpQtTools.h:49
QString tlpStringToQString(const std::string &toConvert)
Convert a Tulip UTF-8 encoded std::string to a QString.
Definition: TlpQtTools.h:55