Tulip  4.2.0
Better Visualization Through Research
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Groups Pages
PluginModel.h
1 /*
2  *
3  * This file is part of Tulip (www.tulip-software.org)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux 1 and Inria Bordeaux - Sud Ouest
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 <tulip/TulipModel.h>
25 #include <tulip/TlpQtTools.h>
26 #include <string>
27 
28 namespace tlp {
29 /*
30  * @brief Build and manage a Qt Model of a list of plugins
31  */
32 class TLP_QT_SCOPE SimplePluginListModel : public tlp::TulipModel {
33 private:
34  QList<std::string> _list;
35 
36 public:
37 
38  SimplePluginListModel(const QList<std::string>& plugins,QObject *parent = NULL);
39  virtual ~SimplePluginListModel();
40  int columnCount ( const QModelIndex& = QModelIndex() ) const;
41  int rowCount(const QModelIndex &parent = QModelIndex()) const;
42  QModelIndex parent(const QModelIndex &) const;
43  QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const;
44  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
45  QList<std::string> plugins()const;
46  std::string pluginName(const QModelIndex& index) const;
47 };
48 
49 template<typename PLUGIN>
50 class PluginModel : public tlp::TulipModel {
51  struct TreeItem {
52  TreeItem(QString name, QString infos = QString::null,
53  TreeItem* parent = NULL): name(name), infos(infos), parent(parent) {}
54  virtual ~TreeItem() {
55  foreach(TreeItem* c, children)
56  delete c;
57  }
58  TreeItem* addChild(QString name, QString infos = QString::null) {
59  TreeItem* result = new TreeItem(name, infos, this);
60  children.push_back(result);
61  return result;
62  }
63 
64  QString name;
65  QString infos;
66  TreeItem* parent;
67  QList<TreeItem*> children;
68  };
69  TreeItem* _root;
70 
71  // FIXME: Non-optimized piece of crap, should be fixed
72  void buildTree() {
73  delete _root;
74  _root = new TreeItem("root");
75  QMap<QString,QMap<QString,QStringList > > pluginTree;
76  std::list<std::string> plugins = PluginLister::instance()->availablePlugins<PLUGIN>();
77 
78  for(std::list<std::string>::iterator it = plugins.begin(); it != plugins.end(); ++it) {
79  std::string name = *it;
80  const Plugin& plugin = PluginLister::instance()->pluginInformations(name);
81  pluginTree[plugin.category().c_str()][plugin.group().c_str()].append(name.c_str());
82  }
83 
84  foreach(QString cat, pluginTree.keys()) {
85  TreeItem* catItem = _root->addChild(cat);
86 
87  foreach(QString group, pluginTree[cat].keys()) {
88  TreeItem* groupItem = catItem;
89 
90  if ((group != "") && (pluginTree[cat].keys().size() > 1))
91  groupItem = catItem->addChild(group);
92 
93  // sort in case insensitive alphabetic order
94  std::sort(pluginTree[cat][group].begin(),
95  pluginTree[cat][group].end(), QStringCaseCmp);
96 
97  foreach(QString alg, pluginTree[cat][group]) {
98  const Plugin& plugin =
99  PluginLister::instance()->pluginInformations(alg.toStdString());
100  std::string infos = plugin.info();
101 
102  // set infos only if they contain more than one word
103  if (infos.find(' ') != std::string::npos)
104  groupItem->addChild(alg, infos.c_str());
105  else
106  groupItem->addChild(alg);
107  }
108  }
109  }
110  }
111 
112  QList<int> indexHierarchy(TreeItem* item) const {
113  QList<int> result;
114  TreeItem* parent = item->parent;
115  TreeItem* child = item;
116 
117  while (child != _root) {
118  result.push_front(parent->children.indexOf(child));
119  parent = parent->parent;
120  child = child->parent;
121  }
122 
123  return result;
124  }
125 
126 public:
127  explicit PluginModel(QObject *parent = NULL): TulipModel(parent), _root(NULL) {
128  buildTree();
129  }
130  virtual ~PluginModel() {
131  delete _root;
132  }
133 
134  int rowCount(const QModelIndex &parent = QModelIndex()) const {
135  TreeItem* item = _root;
136 
137  if (parent.isValid())
138  item = (TreeItem*)parent.internalPointer();
139 
140  return item->children.size();
141  }
142 
143  int columnCount(const QModelIndex & = QModelIndex()) const {
144  return 1;
145  }
146 
147  QModelIndex parent(const QModelIndex &child) const {
148  if (!child.isValid())
149  return QModelIndex();
150 
151  TreeItem* childItem = (TreeItem*)child.internalPointer();
152 
153  if (childItem->parent == _root)
154  return QModelIndex();
155 
156  QList<int> indexes = indexHierarchy(childItem->parent);
157  int row = indexes[indexes.size()-1];
158  return createIndex(row,child.column(),childItem->parent);
159  }
160 
161  QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const {
162  TreeItem* parentItem = _root;
163 
164  if (parent.isValid()) {
165  parentItem = (TreeItem*)parent.internalPointer();
166  }
167 
168  if (row >= parentItem->children.size())
169  return QModelIndex();
170 
171  return createIndex(row,column,parentItem->children[row]);
172  }
173 
174  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
175  TreeItem* item = (TreeItem*)index.internalPointer();
176 
177  if (role == Qt::DisplayRole)
178  return item->name;
179  else if (role == Qt::ToolTipRole) {
180  if (item->infos.isNull())
181  return item->name;
182  else
183  return QString("<table><tr><td>%1</td></tr><tr><td><i>%2</i></td></tr></table>").arg(item->name + " :").arg(item->infos);
184  }
185  else if (role == Qt::FontRole && !index.parent().parent().isValid()) {
186  QFont f;
187  f.setBold(true);
188  return f;
189  }
190  else if (role == Qt::DecorationRole && tlp::PluginLister::pluginExists(item->name.toStdString())) {
191  const tlp::Plugin& p = tlp::PluginLister::pluginInformations(item->name.toStdString());
192  QIcon icon(p.icon().c_str());
193  return icon;
194  }
195 
196  return QVariant();
197  }
198 
199  virtual Qt::ItemFlags flags ( const QModelIndex& index ) const {
200  Qt::ItemFlags result(QAbstractItemModel::flags(index));
201 
202  if(index.isValid()) {
203  TreeItem* item = (TreeItem*)index.internalPointer();
204 
205  if (!PluginLister::instance()->pluginExists<PLUGIN>(item->name.toStdString()))
206  result = Qt::ItemIsEnabled;
207  }
208 
209  return result;
210  }
211 };
212 }
213 
214 #endif // PLUGINMODEL_H
215 ///@endcond