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