Tulip  5.3.0
Large graphs analysis and drawing
PluginModel.h
1 /*
2  *
3  * This file is part of Tulip (http://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 <QIcon>
25 #include <QFont>
26 
27 #include <tulip/TulipModel.h>
28 #include <tulip/TlpQtTools.h>
29 #include <tulip/PluginLister.h>
30 
31 #include <string>
32 
33 namespace tlp {
34 /*
35  * @brief Build and manage a Qt Model of a list of plugins
36  */
37 class TLP_QT_SCOPE SimplePluginListModel : public tlp::TulipModel {
38 private:
39  QList<std::string> _list;
40 
41 public:
42  SimplePluginListModel(const QList<std::string> &plugins, QObject *parent = nullptr);
43  ~SimplePluginListModel() override;
44  int columnCount(const QModelIndex & = QModelIndex()) const override;
45  int rowCount(const QModelIndex &parent = QModelIndex()) const override;
46  QModelIndex parent(const QModelIndex &) const override;
47  QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
48  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
49  QList<std::string> plugins() const;
50  std::string pluginName(const QModelIndex &index) const;
51 };
52 
53 template <typename PLUGIN>
54 class PluginModel : public tlp::TulipModel {
55  struct TreeItem {
56  TreeItem(QString name, QString info = "", TreeItem *parent = nullptr)
57  : name(name), info(info), parent(parent) {}
58  virtual ~TreeItem() {
59  qDeleteAll(children);
60  }
61  TreeItem *addChild(QString name, QString info = "") {
62  TreeItem *result = new TreeItem(name, info, this);
63  children.push_back(result);
64  return result;
65  }
66 
67  QString name;
68  QString info;
69  TreeItem *parent;
70  QList<TreeItem *> children;
71  };
72  TreeItem *_root;
73 
74  // FIXME: Non-optimized piece of crap, should be fixed
75  void buildTree() {
76  delete _root;
77  _root = new TreeItem("root");
78  QMap<QString, QMap<QString, QStringList>> pluginTree;
79  std::list<std::string> plugins = PluginLister::instance()->availablePlugins<PLUGIN>();
80 
81  for (std::list<std::string>::iterator it = plugins.begin(); it != plugins.end(); ++it) {
82  std::string name = *it;
83  const Plugin &plugin = PluginLister::instance()->pluginInformation(name);
84  pluginTree[tlp::tlpStringToQString(plugin.category())]
85  [tlp::tlpStringToQString(plugin.group())]
86  .append(tlp::tlpStringToQString(name));
87  }
88 
89  for (const QString &cat : pluginTree.keys()) {
90  TreeItem *catItem = _root->addChild(cat);
91 
92  for (const QString &group : pluginTree[cat].keys()) {
93  TreeItem *groupItem = catItem;
94 
95  if ((!group.isEmpty()) && (pluginTree[cat].keys().size() > 1))
96  groupItem = catItem->addChild(group);
97 
98  // sort in case insensitive alphabetic order
99  qSort(pluginTree[cat][group].begin(), pluginTree[cat][group].end(), QStringCaseCmp);
100 
101  for (const QString &alg : pluginTree[cat][group]) {
102  const Plugin &plugin =
104  std::string info = plugin.info();
105 
106  // set info only if they contain more than one word
107  if (info.find(' ') != std::string::npos)
108  groupItem->addChild(alg, tlp::tlpStringToQString(info));
109  else
110  groupItem->addChild(alg);
111  }
112  }
113  }
114  }
115 
116  QList<int> indexHierarchy(TreeItem *item) const {
117  QList<int> result;
118  TreeItem *parent = item->parent;
119  TreeItem *child = item;
120 
121  while (child != _root) {
122  result.push_front(parent->children.indexOf(child));
123  parent = parent->parent;
124  child = child->parent;
125  }
126 
127  return result;
128  }
129 
130 public:
131  explicit PluginModel(QObject *parent = nullptr) : TulipModel(parent), _root(nullptr) {
132  buildTree();
133  }
134  ~PluginModel() override {
135  delete _root;
136  }
137 
138  int rowCount(const QModelIndex &parent = QModelIndex()) const override {
139  TreeItem *item = _root;
140 
141  if (parent.isValid())
142  item = static_cast<TreeItem *>(parent.internalPointer());
143 
144  return item->children.size();
145  }
146 
147  int columnCount(const QModelIndex & = QModelIndex()) const override {
148  return 1;
149  }
150 
151  QModelIndex parent(const QModelIndex &child) const override {
152  if (!child.isValid())
153  return QModelIndex();
154 
155  TreeItem *childItem = static_cast<TreeItem *>(child.internalPointer());
156 
157  if (childItem->parent == _root)
158  return QModelIndex();
159 
160  QList<int> indexes = indexHierarchy(childItem->parent);
161  int row = indexes[indexes.size() - 1];
162  return createIndex(row, child.column(), childItem->parent);
163  }
164 
165  QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override {
166  TreeItem *parentItem = _root;
167 
168  if (parent.isValid()) {
169  parentItem = static_cast<TreeItem *>(parent.internalPointer());
170  }
171 
172  if (row >= parentItem->children.size())
173  return QModelIndex();
174 
175  return createIndex(row, column, parentItem->children[row]);
176  }
177 
178  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
179  TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
180 
181  if (role == Qt::DisplayRole)
182  return item->name;
183  else if (role == Qt::ToolTipRole) {
184  if (item->info.isEmpty())
185  return item->name;
186  else
187  return QString("<table><tr><td>%1</td></tr><tr><td><i>%2</i></td></tr></table>")
188  .arg(item->name + ":")
189  .arg(item->info);
190  } else if (role == Qt::FontRole && !index.parent().parent().isValid()) {
191  QFont f;
192  f.setBold(true);
193  return f;
194  } else if (role == Qt::DecorationRole && item->children.isEmpty() &&
196  const tlp::Plugin &p =
198  QIcon icon(tlp::tlpStringToQString(p.icon()));
199  return icon;
200  }
201 
202  return QVariant();
203  }
204 
205  Qt::ItemFlags flags(const QModelIndex &index) const override {
206  Qt::ItemFlags result(QAbstractItemModel::flags(index));
207 
208  if (index.isValid()) {
209  TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
210 
212  result = Qt::ItemIsEnabled;
213  }
214 
215  return result;
216  }
217 };
218 } // namespace tlp
219 
220 #endif // PLUGINMODEL_H
221 ///@endcond
static std::list< std::string > availablePlugins()
Gets the list of plugins of a given type (template parameter).
virtual std::string info() const =0
Information about the plug-in, from the plug-in author. This information can contains anything...
bool QStringCaseCmp(const QString &s1, const QString &s2)
Case insensitive comparison of two QStrings.
Definition: TlpQtTools.h:62
std::string QStringToTlpString(const QString &toConvert)
Convert a QString to a Tulip UTF-8 encoded std::string.
Definition: TlpQtTools.h:49
static const Plugin & pluginInformation(const std::string &name)
Gets more detailed information about one specific plug-in.
virtual std::string icon() const
The icon (preferably a thumbnail) of the plugin.
#define PLUGIN(C)
Register a plugin into the plugin system. This macro is mandatory in order to register a plugin into ...
Definition: Plugin.h:285
Top-level interface for plug-ins.
Definition: Plugin.h:85
QString tlpStringToQString(const std::string &toConvert)
Convert a Tulip UTF-8 encoded std::string to a QString.
Definition: TlpQtTools.h:55
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:115
static tlp::PluginLister * instance()
Gets the static instance of this class. If not already done, creates it beforehand.