Tulip  4.4.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 <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 infos = QString::null,
58  TreeItem* parent = NULL): name(name), infos(infos), parent(parent) {}
59  virtual ~TreeItem() {
60  foreach(TreeItem* c, children)
61  delete c;
62  }
63  TreeItem* addChild(QString name, QString infos = QString::null) {
64  TreeItem* result = new TreeItem(name, infos, this);
65  children.push_back(result);
66  return result;
67  }
68 
69  QString name;
70  QString infos;
71  TreeItem* parent;
72  QList<TreeItem*> children;
73  };
74  TreeItem* _root;
75 
76  // FIXME: Non-optimized piece of crap, should be fixed
77  void buildTree() {
78  delete _root;
79  _root = new TreeItem("root");
80  QMap<QString,QMap<QString,QStringList > > pluginTree;
81  std::list<std::string> plugins = PluginLister::instance()->availablePlugins<PLUGIN>();
82 
83  for(std::list<std::string>::iterator it = plugins.begin(); it != plugins.end(); ++it) {
84  std::string name = *it;
85  const Plugin& plugin = PluginLister::instance()->pluginInformation(name);
86  pluginTree[plugin.category().c_str()][plugin.group().c_str()].append(name.c_str());
87  }
88 
89  foreach(QString cat, pluginTree.keys()) {
90  TreeItem* catItem = _root->addChild(cat);
91 
92  foreach(QString group, pluginTree[cat].keys()) {
93  TreeItem* groupItem = catItem;
94 
95  if ((group != "") && (pluginTree[cat].keys().size() > 1))
96  groupItem = catItem->addChild(group);
97 
98  // sort in case insensitive alphabetic order
99  std::sort(pluginTree[cat][group].begin(),
100  pluginTree[cat][group].end(), QStringCaseCmp);
101 
102  foreach(QString alg, pluginTree[cat][group]) {
103  const Plugin& plugin =
104  PluginLister::instance()->pluginInformation(alg.toStdString());
105  std::string infos = plugin.info();
106 
107  // set infos only if they contain more than one word
108  if (infos.find(' ') != std::string::npos)
109  groupItem->addChild(alg, infos.c_str());
110  else
111  groupItem->addChild(alg);
112  }
113  }
114  }
115  }
116 
117  QList<int> indexHierarchy(TreeItem* item) const {
118  QList<int> result;
119  TreeItem* parent = item->parent;
120  TreeItem* child = item;
121 
122  while (child != _root) {
123  result.push_front(parent->children.indexOf(child));
124  parent = parent->parent;
125  child = child->parent;
126  }
127 
128  return result;
129  }
130 
131 public:
132  explicit PluginModel(QObject *parent = NULL): TulipModel(parent), _root(NULL) {
133  buildTree();
134  }
135  virtual ~PluginModel() {
136  delete _root;
137  }
138 
139  int rowCount(const QModelIndex &parent = QModelIndex()) const {
140  TreeItem* item = _root;
141 
142  if (parent.isValid())
143  item = (TreeItem*)parent.internalPointer();
144 
145  return item->children.size();
146  }
147 
148  int columnCount(const QModelIndex & = QModelIndex()) const {
149  return 1;
150  }
151 
152  QModelIndex parent(const QModelIndex &child) const {
153  if (!child.isValid())
154  return QModelIndex();
155 
156  TreeItem* childItem = (TreeItem*)child.internalPointer();
157 
158  if (childItem->parent == _root)
159  return QModelIndex();
160 
161  QList<int> indexes = indexHierarchy(childItem->parent);
162  int row = indexes[indexes.size()-1];
163  return createIndex(row,child.column(),childItem->parent);
164  }
165 
166  QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const {
167  TreeItem* parentItem = _root;
168 
169  if (parent.isValid()) {
170  parentItem = (TreeItem*)parent.internalPointer();
171  }
172 
173  if (row >= parentItem->children.size())
174  return QModelIndex();
175 
176  return createIndex(row,column,parentItem->children[row]);
177  }
178 
179  QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
180  TreeItem* item = (TreeItem*)index.internalPointer();
181 
182  if (role == Qt::DisplayRole)
183  return item->name;
184  else if (role == Qt::ToolTipRole) {
185  if (item->infos.isNull())
186  return item->name;
187  else
188  return QString("<table><tr><td>%1</td></tr><tr><td><i>%2</i></td></tr></table>").arg(item->name + " :").arg(item->infos);
189  }
190  else if (role == Qt::FontRole && !index.parent().parent().isValid()) {
191  QFont f;
192  f.setBold(true);
193  return f;
194  }
195  else if (role == Qt::DecorationRole && tlp::PluginLister::pluginExists(item->name.toStdString())) {
196  const tlp::Plugin& p = tlp::PluginLister::pluginInformation(item->name.toStdString());
197  QIcon icon(p.icon().c_str());
198  return icon;
199  }
200 
201  return QVariant();
202  }
203 
204  virtual Qt::ItemFlags flags ( const QModelIndex& index ) const {
205  Qt::ItemFlags result(QAbstractItemModel::flags(index));
206 
207  if(index.isValid()) {
208  TreeItem* item = (TreeItem*)index.internalPointer();
209 
210  if (!PluginLister::instance()->pluginExists<PLUGIN>(item->name.toStdString()))
211  result = Qt::ItemIsEnabled;
212  }
213 
214  return result;
215  }
216 };
217 }
218 
219 #endif // PLUGINMODEL_H
220 ///@endcond