Tulip  5.2.1
Large graphs analysis and drawing
Interactor.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 
20 #ifndef _INTERACTOR_H
21 #define _INTERACTOR_H
22 
23 #include <tulip/Plugin.h>
24 
25 #include <QObject>
26 #include <QCursor>
27 #include <QMap>
28 
29 #include <string>
30 
31 class QAction;
32 
33 namespace tlp {
34 
35 static const std::string INTERACTOR_CATEGORY = "Interactor";
36 
37 class View;
38 
39 /**
40  @ingroup Plugins
41  @brief Interactor provides a way to handle user inputs over a view.
42  Basically, The interactor class is an overlay to the Qt's event filtering mechanism. It adds
43  several features like the ability to define priorities, custom cursors, etc
44 
45  When an interactor is constructed, the following methods are called in this order:
46  @li The constructor. This method should almost be a no-op. Interactors may be instantiated by the
47  plugin manager system and doing unneeded operations in the constructor may lead to poor
48  performances when the application loads up.
49  @li isCompatible. When creating a View, the application will check for all interactors to see if
50  they could be installed on it. This is done using the isCompatible method.
51  @li construct. Initialize the interactor. Since the constructor should be a no-op, initialization
52  code should be put here.
53  @li setView. Defines the view this interactor is bound to. The Interactor may keep a reference to
54  the view object to perform specific operations on user inputs.
55 
56  Methods listed above are only called once. Once the interactor is initialized, it may be
57  installed/removed several times on different QObjects. It will then repond to user inputs via the
58  eventFilter method
59  @see QObject::eventFilter()
60  */
61 class TLP_QT_SCOPE Interactor : public QObject, public Plugin {
62  Q_OBJECT
63  Q_PROPERTY(unsigned int priority READ priority)
64  Q_PROPERTY(QAction *action READ action)
65  Q_PROPERTY(tlp::View *view READ view WRITE setView)
66  Q_PROPERTY(QCursor cursor READ cursor)
67 
68 public:
69  std::string category() const override {
70  return INTERACTOR_CATEGORY;
71  }
72  std::string icon() const override {
73  return ":/tulip/gui/icons/32/plugin_interactor.png";
74  }
75  /**
76  @brief Checks the compatibility between the interactor and the given view (identified by its
77  name).
78  If this method returns true, it's very likely that the interactor will be installed on the
79  associated view.
80  */
81  virtual bool isCompatible(const std::string &viewName) const = 0;
82 
83  /**
84  @return the configuration widget used to set up the interactor.
85  @warning This method MUST ALWAYS return the same pointer. Doing otherwise may lead to memory
86  leaks.
87  @note The configuration widget has to be instantiated from the construct method.
88  @note It is up to the interactor developper to delete the configuration widget
89  */
90  virtual QWidget *configurationWidget() const = 0;
91 
92  /**
93  @return the interactor's priority.
94  Priority defines how interactors gets ordered when displayed in the View's toolbar.
95  Interactors with the top-most priority value will be displayed at the beginning of the list
96  while lowest priority will be position at the end.
97  */
98  virtual unsigned int priority() const = 0;
99 
100  /**
101  @return a QAction associated to this interactor.
102  This is used by the overleying system to associate an icon/text to the interactor.
103  @warning The parent (QObject::parent()) object of this QAction MUST BE the Interactor.
104  */
105  virtual QAction *action() const = 0;
106 
107  /**
108  @return the View object associated to this Interactor.
109  @warning The returned object MUST be the same as the one passed down to the setView method.
110  */
111  virtual tlp::View *view() const = 0;
112 
113  /**
114  @return The cursor associated to this interactor.
115  When the interactor gets active on a view, the View's cursor is changed to what this method
116  returns.
117  */
118  virtual QCursor cursor() const = 0;
119 
120  /**
121  @brief Builds up the interactor's internal state.
122  This method should be used instead of the constructor to initialize the interactor.
123  */
124  virtual void construct() = 0;
125 
126 public slots:
127  /**
128  @brief Defines the view object associated to this interactor.
129  @warning The view() method MUST ALWAYS return the same pointer as the one passed down to this
130  method.
131  */
132  virtual void setView(tlp::View *) = 0;
133 
134  /**
135  @brief Install the interactor on the given target
136  A call to this method means thatr the interactor should start listening to the target's events
137  and handle them.
138  Returning true prevents further handling of the event. Doing otherwise means that the interactor
139  will let following filters to hand over this kind of event.
140  */
141  virtual void install(QObject *target) = 0;
142 
143  /**
144  @brief Removes the interactor from the previously set target.
145  Interactors can be installed on only one target at once.
146  */
147  virtual void uninstall() = 0;
148 
149  /**
150  @brief Informs the interactor when the undo command (Ctrl+Z) has been triggered
151  */
152  virtual void undoIsDone() = 0;
153 
154 protected:
155  /**
156  @brief Provides input filtering for the interactor
157  @see QObject::eventFilter()
158  */
159  inline bool eventFilter(QObject *obj, QEvent *ev) override {
160  return QObject::eventFilter(obj, ev);
161  }
162 };
163 
164 /**
165  * @ingroup Plugins
166  * @brief The InteractorLister class lists compatible interactors for a given tlp::View
167  */
168 class TLP_QT_SCOPE InteractorLister {
169  static QMap<std::string, QList<std::string>> _compatibilityMap;
170 
171 public:
172  static void initInteractorsDependencies();
173  static QList<std::string> compatibleInteractors(const std::string &viewName);
174 };
175 
176 /**
177  * @ingroup Plugins
178  * @def
179  * INTERACTORPLUGINVIEWEXTENSION(CLASS_NAME,STRING_CLASS_NAME,BASE_INTERACTOR_STRING_NAME,VIEW_STRING_NAME,AUTHOR,DATE,DESCRIPTION,VERSION)
180  *
181  * @brief Copy an existing Tulip interactor and sets it compatible with a given View.
182  *
183  * This macro is used when you're making your own View and want to use an existing interactor with
184  * it. Interactors are declared to be compatible with a list of View. This macro extends the
185  * compatibility of an existing interactor by subclassing it.
186  *
187  * @note: This macro used the same interactor priority as the base interactor. To define your own
188  * priority, see INTERACTORPLUGINVIEWEXTENSIONWITHPRIORITY
189  *
190  * @param CLASS_NAME The name of the interactor class to generate.
191  * @param STRING_CLASS_NAME The name of the interactor plugin to generate (see tlp::Plugin::name())
192  * @param BASE_INTERACTOR_STRING_NAME The name of the interactor to extend
193  * @param VIEW_STRING_NAME The name of the View to set the interactor compatible with
194  * @param AUTHOR see tlp::Plugin::author()
195  * @param DATE see tlp::Plugin::date()
196  * @param DESCRIPTION see tlp::Plugin::info()
197  * @param VERSION see tlp::Plugin::version()
198  */
199 #define INTERACTORPLUGINVIEWEXTENSION(CLASS_NAME, STRING_CLASS_NAME, BASE_INTERACTOR_STRING_NAME, \
200  VIEW_STRING_NAME, AUTHOR, DATE, DESCRIPTION, VERSION) \
201  class CLASS_NAME : public tlp::Interactor { \
202  mutable tlp::Interactor *_component; \
203  \
204  public: \
205  std::string name() const { \
206  return std::string(STRING_CLASS_NAME); \
207  } \
208  std::string author() const { \
209  return std::string(AUTHOR); \
210  } \
211  std::string date() const { \
212  return std::string(DATE); \
213  } \
214  std::string info() const { \
215  return std::string(DESCRIPTION); \
216  } \
217  std::string release() const { \
218  return std::string(VERSION); \
219  } \
220  std::string tulipRelease() const { \
221  return std::string(TULIP_VERSION); \
222  } \
223  std::string group() const { \
224  return getComponent()->group(); \
225  } \
226  CLASS_NAME(const PluginContext *) : _component(nullptr) {} \
227  bool isCompatible(const std::string &viewName) const { \
228  return viewName == VIEW_STRING_NAME; \
229  } \
230  QWidget *configurationWidget() const { \
231  return getComponent()->configurationWidget(); \
232  } \
233  unsigned int priority() const { \
234  return getComponent()->priority(); \
235  } \
236  QAction *action() const { \
237  return getComponent()->action(); \
238  } \
239  tlp::View *view() const { \
240  return getComponent()->view(); \
241  } \
242  QCursor cursor() const { \
243  return getComponent()->cursor(); \
244  } \
245  void construct() { \
246  getComponent()->construct(); \
247  } \
248  void setView(tlp::View *v) { \
249  getComponent()->setView(v); \
250  } \
251  void install(QObject *target) { \
252  getComponent()->install(target); \
253  } \
254  void uninstall() { \
255  getComponent()->uninstall(); \
256  } \
257  void undoIsDone() { \
258  getComponent()->undoIsDone(); \
259  } \
260  tlp::Interactor *getComponent() const { \
261  if (!_component) { \
262  _component = tlp::PluginLister::instance()->getPluginObject<Interactor>( \
263  BASE_INTERACTOR_STRING_NAME, nullptr); \
264  assert(_component != nullptr); \
265  } \
266  return _component; \
267  } \
268  }; \
269  PLUGIN(CLASS_NAME)
270 
271 /**
272  * @ingroup Plugins
273  * @def
274  * INTERACTORPLUGINVIEWEXTENSIONWITHPRIORITY(CLASS_NAME,STRING_CLASS_NAME,BASE_INTERACTOR_STRING_NAME,VIEW_STRING_NAME,AUTHOR,DATE,DESCRIPTION,VERSION,PRIORITY)
275  * @brief Similar to INTERACTORPLUGINVIEWEXTENSION but allows to define the generated interactor's
276  * priority.
277  * @see tlp::Interactor::priority()
278  * @see INTERACTORPLUGINVIEWEXTENSION
279  */
280 #define INTERACTORPLUGINVIEWEXTENSIONWITHPRIORITY(CLASS_NAME, STRING_CLASS_NAME, \
281  BASE_INTERACTOR_STRING_NAME, VIEW_STRING_NAME, \
282  AUTHOR, DATE, DESCRIPTION, VERSION, PRIORITY) \
283  class CLASS_NAME : public tlp::Interactor { \
284  mutable tlp::Interactor *_component; \
285  \
286  public: \
287  std::string name() const { \
288  return std::string(STRING_CLASS_NAME); \
289  } \
290  std::string author() const { \
291  return std::string(AUTHOR); \
292  } \
293  std::string date() const { \
294  return std::string(DATE); \
295  } \
296  std::string info() const { \
297  return std::string(DESCRIPTION); \
298  } \
299  std::string release() const { \
300  return std::string(VERSION); \
301  } \
302  std::string tulipRelease() const { \
303  return std::string(TULIP_VERSION); \
304  } \
305  std::string group() const { \
306  return getComponent()->group(); \
307  } \
308  CLASS_NAME(const PluginContext *) : _component(nullptr) {} \
309  bool isCompatible(const std::string &viewName) const { \
310  return viewName == VIEW_STRING_NAME; \
311  } \
312  QWidget *configurationWidget() const { \
313  return getComponent()->configurationWidget(); \
314  } \
315  unsigned int priority() const { \
316  return PRIORITY; \
317  } \
318  QAction *action() const { \
319  return getComponent()->action(); \
320  } \
321  tlp::View *view() const { \
322  return getComponent()->view(); \
323  } \
324  QCursor cursor() const { \
325  return getComponent()->cursor(); \
326  } \
327  void construct() { \
328  getComponent()->construct(); \
329  } \
330  void setView(tlp::View *v) { \
331  getComponent()->setView(v); \
332  } \
333  void install(QObject *target) { \
334  getComponent()->install(target); \
335  } \
336  void uninstall() { \
337  getComponent()->uninstall(); \
338  } \
339  void undoIsDone() { \
340  getComponent()->undoIsDone(); \
341  } \
342  tlp::Interactor *getComponent() const { \
343  if (!_component) { \
344  _component = tlp::PluginLister::instance()->getPluginObject<Interactor>( \
345  BASE_INTERACTOR_STRING_NAME, nullptr); \
346  assert(_component != nullptr); \
347  } \
348  return _component; \
349  } \
350  }; \
351  PLUGIN(CLASS_NAME)
352 } // namespace tlp
353 
354 #endif
bool eventFilter(QObject *obj, QEvent *ev) override
Provides input filtering for the interactor.
Definition: Interactor.h:159
Interactor provides a way to handle user inputs over a view. Basically, The interactor class is an ov...
Definition: Interactor.h:61
Top-level interface for plug-ins.
Definition: Plugin.h:85
std::string category() const override
A string identifier for a plugin used for categorization purposes.
Definition: Interactor.h:69
View plugins provide a way to dynamically add to a Tulip plateform various ways to visualize a graph...
Definition: View.h:90
The InteractorLister class lists compatible interactors for a given tlp::View.
Definition: Interactor.h:168
std::string icon() const override
The icon (preferably a thumbnail) of the plugin.
Definition: Interactor.h:72