Tulip  5.1.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 
43  SimplePluginListModel(const QList<std::string>& plugins,QObject *parent = NULL);
44  virtual ~SimplePluginListModel();
45  int columnCount ( const QModelIndex& = QModelIndex() ) const;
46  int rowCount(const QModelIndex &parent = QModelIndex()) const;
47  QModelIndex parent(const QModelIndex &) const;
48  QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const;
49  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
50  QList<std::string> plugins()const;
51  std::string pluginName(const QModelIndex& index) const;
52 };
53 
54 template<typename PLUGIN>
55 class PluginModel : public tlp::TulipModel {
56  struct TreeItem {
57  TreeItem(QString name, QString info = "",
58  TreeItem* parent = NULL): name(name), info(info), parent(parent) {}
59  virtual ~TreeItem() {
60  qDeleteAll(children);
61  }
62  TreeItem* addChild(QString name, QString info = "") {
63  TreeItem* result = new TreeItem(name, info, this);
64  children.push_back(result);
65  return result;
66  }
67 
68  QString name;
69  QString info;
70  TreeItem* parent;
71  QList<TreeItem*> children;
72  };
73  TreeItem* _root;
74 
75  // FIXME: Non-optimized piece of crap, should be fixed
76  void buildTree() {
77  delete _root;
78  _root = new TreeItem("root");
79  QMap<QString,QMap<QString,QStringList > > pluginTree;
80  std::list<std::string> plugins = PluginLister::instance()->availablePlugins<PLUGIN>();
81 
82  for(std::list<std::string>::iterator it = plugins.begin(); it != plugins.end(); ++it) {
83  std::string name = *it;
84  const Plugin& plugin = PluginLister::instance()->pluginInformation(name);
85  pluginTree[tlp::tlpStringToQString(plugin.category())][tlp::tlpStringToQString(plugin.group())].append(tlp::tlpStringToQString(name));
86  }
87 
88  foreach(const QString& cat, pluginTree.keys()) {
89  TreeItem* catItem = _root->addChild(cat);
90 
91  foreach(const QString& group, pluginTree[cat].keys()) {
92  TreeItem* groupItem = catItem;
93 
94  if ((!group.isEmpty()) && (pluginTree[cat].keys().size() > 1))
95  groupItem = catItem->addChild(group);
96 
97  // sort in case insensitive alphabetic order
98  qSort(pluginTree[cat][group].begin(),
99  pluginTree[cat][group].end(), QStringCaseCmp);
100 
101  foreach(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 = NULL): TulipModel(parent), _root(NULL) {
132  buildTree();
133  }
134  virtual ~PluginModel() {
135  delete _root;
136  }
137 
138  int rowCount(const QModelIndex &parent = QModelIndex()) const {
139  TreeItem* item = _root;
140 
141  if (parent.isValid())
142  item = (TreeItem*)parent.internalPointer();
143 
144  return item->children.size();
145  }
146 
147  int columnCount(const QModelIndex & = QModelIndex()) const {
148  return 1;
149  }
150 
151  QModelIndex parent(const QModelIndex &child) const {
152  if (!child.isValid())
153  return QModelIndex();
154 
155  TreeItem* childItem = (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 {
166  TreeItem* parentItem = _root;
167 
168  if (parent.isValid()) {
169  parentItem = (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 {
179  TreeItem* item = (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>").arg(item->name + ":").arg(item->info);
188  }
189  else if (role == Qt::FontRole && !index.parent().parent().isValid()) {
190  QFont f;
191  f.setBold(true);
192  return f;
193  }
194  else if (role == Qt::DecorationRole && item->children.isEmpty() && tlp::PluginLister::pluginExists(tlp::QStringToTlpString(item->name))) {
196  QIcon icon(tlp::tlpStringToQString(p.icon()));
197  return icon;
198  }
199 
200  return QVariant();
201  }
202 
203  virtual Qt::ItemFlags flags ( const QModelIndex& index ) const {
204  Qt::ItemFlags result(QAbstractItemModel::flags(index));
205 
206  if(index.isValid()) {
207  TreeItem* item = (TreeItem*)index.internalPointer();
208 
209  if (!PluginLister::instance()->pluginExists<PLUGIN>(tlp::QStringToTlpString(item->name)))
210  result = Qt::ItemIsEnabled;
211  }
212 
213  return result;
214  }
215 };
216 }
217 
218 #endif // PLUGINMODEL_H
219 ///@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:61
virtual std::string icon() const
The icon (preferably a thumbnail) of the plugin.
std::string QStringToTlpString(const QString &toConvert)
Convert a QString to a Tulip UTF-8 encoded std::string.
Definition: TlpQtTools.h:48
static const Plugin & pluginInformation(const std::string &name)
Gets more detailed information about one specific plug-in.
#define PLUGIN(C)
Register a plugin into the plugin system. This macro is mandatory in order to register a plugin into ...
Definition: Plugin.h:238
Top-level interface for plug-ins.
Definition: Plugin.h:79
QString tlpStringToQString(const std::string &toConvert)
Convert a Tulip UTF-8 encoded std::string to a QString.
Definition: TlpQtTools.h:54
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:110
static tlp::PluginLister * instance()
Gets the static instance of this class. If not already done, creates it beforehand.