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