Tulip  4.2.0
Better Visualization Through Research
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Groups Pages
Interactor.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 
20 #ifndef _INTERACTOR_H
21 #define _INTERACTOR_H
22 
23 #include <QtCore/QObject>
24 #include <QtGui/QAction>
25 
26 #include <tulip/TulipRelease.h>
27 
28 #include <tulip/Plugin.h>
29 #include <tulip/PluginLister.h>
30 #include <tulip/Plugin.h>
31 
32 namespace tlp {
33 
34 static const std::string INTERACTOR_CATEGORY = QObject::trUtf8("Interactor").toStdString();
35 
36 class View;
37 
38 /**
39  @ingroup Plugins
40  @brief Interactor provides a way to handle user inputs over a view.
41  Basically, The interactor class is an overlay to the Qt's event filtering mechanism. It adds several features like the ability to define priorities, custom cursors, etc
42 
43  When an interactor is constructed, the following methods are called in this order:
44  @li The constructor. This method should almost be a no-op. Interactors may be instantiated by the plugin manager system and doing unneeded operations in the constructor may lead to poor performances when the application loads up.
45  @li isCompatible. When creating a View, the application will check for all interactors to see if they could be installed on it. This is done using the isCompatible method.
46  @li construct. Initialize the interactor. Since the constructor should be a no-op, initialization code should be put here.
47  @li setView. Defines the view this interactor is bound to. The Interactor may keep a reference to the view object to perform specific operations on user inputs.
48 
49  Methods listed above are only called once. Once the interactor is initialized, it may be installed/removed several times on different QObjects. It will then repond to user inputs via the eventFilter method
50  @see QObject::eventFilter()
51  */
52 class TLP_QT_SCOPE Interactor: public QObject, public tlp::Plugin {
53  Q_OBJECT
54  Q_PROPERTY(unsigned int priority READ priority)
55  Q_PROPERTY(QAction* action READ action)
56  Q_PROPERTY(tlp::View* view READ view WRITE setView)
57  Q_PROPERTY(QCursor cursor READ cursor)
58 
59 public:
60  virtual std::string category() const {
61  return INTERACTOR_CATEGORY;
62  }
63  std::string icon() const {
64  return ":/tulip/gui/icons/32/plugin_interactor.png";
65  }
66  /**
67  @brief Checks the compatibility between the interactor and the given view (identified by its name).
68  If this method returns true, it's very likely that the interactor will be installed on the associated view.
69  */
70  virtual bool isCompatible(const std::string& viewName) const=0;
71 
72  /**
73  @return the configuration widget used to set up the interactor.
74  @warning This method MUST ALWAYS return the same pointer. Doing otherwise may lead to memory leaks.
75  @note The configuration widget has to be instantiated from the construct method.
76  @note It is up to the interactor developper to delete the configuration widget
77  */
78  virtual QWidget* configurationWidget() const=0;
79 
80  /**
81  @return the interactor's priority.
82  Priority defines how interactors gets ordered when displayed in the View's toolbar.
83  Interactors with the top-most priority value will be displayed at the beginning of the list while lowest priority will be position at the end.
84  */
85  virtual unsigned int priority() const=0;
86 
87  /**
88  @return a QAction associated to this interactor.
89  This is used by the overleying system to associate an icon/text to the interactor.
90  @warning The parent (QObject::parent()) object of this QAction MUST BE the Interactor.
91  */
92  virtual QAction* action() const=0;
93 
94  /**
95  @return the View object associated to this Interactor.
96  @warning The returned object MUST be the same as the one passed down to the setView method.
97  */
98  virtual tlp::View* view() const=0;
99 
100  /**
101  @return The cursor associated to this interactor.
102  When the interactor gets active on a view, the View's cursor is changed to what this method returns.
103  */
104  virtual QCursor cursor() const=0;
105 
106  /**
107  @brief Builds up the interactor's internal state.
108  This method should be used instead of the constructor to initialize the interactor.
109  */
110  virtual void construct()=0;
111 
112 public slots:
113  /**
114  @brief Defines the view object associated to this interactor.
115  @warning The view() method MUST ALWAYS return the same pointer as the one passed down to this method.
116  */
117  virtual void setView(tlp::View*)=0;
118 
119  /**
120  @brief Install the interactor on the given target
121  A call to this method means thatr the interactor should start listening to the target's events and handle them.
122  Returning true prevents further handling of the event. Doing otherwise means that the interactor will let following filters to hand over this kind of event.
123  */
124  virtual void install(QObject* target)=0;
125 
126  /**
127  @brief Removes the interactor from the previously set target.
128  Interactors can be installed on only one target at once.
129  */
130  virtual void uninstall()=0;
131 
132  /**
133  @brief Informs the interactor when the undo command (Ctrl+Z) has been triggered
134  */
135  virtual void undoIsDone()=0;
136 
137 protected:
138  /**
139  @brief Provides input filtering for the interactor
140  @see QObject::eventFilter()
141  */
142  inline virtual bool eventFilter(QObject* obj, QEvent* ev) {
143  return QObject::eventFilter(obj,ev);
144  }
145 };
146 
147 /**
148  * @ingroup Plugins
149  * @brief The InteractorLister class lists compatible interactors for a given tlp::View
150  */
151 class TLP_QT_SCOPE InteractorLister {
152  static QMap<std::string,QList<std::string> > _compatibilityMap;
153 public:
154  static void initInteractorsDependencies();
155  static QList<std::string> compatibleInteractors(const std::string& viewName);
156 };
157 
158 /**
159  * @ingroup Plugins
160  * @def INTERACTORPLUGINVIEWEXTENSION(CLASS_NAME,STRING_CLASS_NAME,BASE_INTERACTOR_STRING_NAME,VIEW_STRING_NAME,AUTHOR,DATE,DESCRIPTION,VERSION)
161  *
162  * @brief Copy an existing Tulip interactor and sets it compatible with a given View.
163  *
164  * This macro is used when you're making your own View and want to use an existing interactor with it. Interactors are declared to be compatible with a list of View. This macro extends the compatibility of an existing interactor by subclassing it.
165  *
166  * @note: This macro used the same interactor priority as the base interactor. To define your own priority, see INTERACTORPLUGINVIEWEXTENSIONWITHPRIORITY
167  *
168  * @param CLASS_NAME The name of the interactor class to generate.
169  * @param STRING_CLASS_NAME The name of the interactor plugin to generate (see tlp::Plugin::name())
170  * @param BASE_INTERACTOR_STRING_NAME The name of the interactor to extend
171  * @param VIEW_STRING_NAME The name of the View to set the interactor compatible with
172  * @param AUTHOR see tlp::Plugin::author()
173  * @param DATE see tlp::Plugin::date()
174  * @param DESCRIPTION see tlp::Plugin::info()
175  * @param VERSION see tlp::Plugin::version()
176  */
177 #define INTERACTORPLUGINVIEWEXTENSION(CLASS_NAME,STRING_CLASS_NAME,BASE_INTERACTOR_STRING_NAME,VIEW_STRING_NAME,AUTHOR,DATE,DESCRIPTION,VERSION)\
178 class CLASS_NAME : public tlp::Interactor {\
179  mutable tlp::Interactor* _component;\
180 public:\
181  std::string name() const { return std::string(STRING_CLASS_NAME); } \
182  std::string author() const { return std::string(AUTHOR); }\
183  std::string date() const { return std::string(DATE); } \
184  std::string info() const { return std::string(DESCRIPTION); } \
185  std::string release() const { return std::string(VERSION); }\
186  std::string tulipRelease() const { return std::string(TULIP_RELEASE); }\
187  std::string group() const { return getComponent()->group(); }\
188  CLASS_NAME(const PluginContext *):_component(NULL) {}\
189  bool isCompatible(const std::string& viewName) const { return viewName == VIEW_STRING_NAME; }\
190  QWidget* configurationWidget() const { return getComponent()->configurationWidget(); }\
191  unsigned int priority() const { return getComponent()->priority(); }\
192  QAction* action() const { return getComponent()->action(); }\
193  tlp::View* view() const { return getComponent()->view(); }\
194  QCursor cursor() const { return getComponent()->cursor(); }\
195  void construct() { getComponent()->construct(); }\
196  void setView(tlp::View* v) { getComponent()->setView(v); }\
197  void install(QObject* target) { getComponent()->install(target); }\
198  void uninstall() { getComponent()->uninstall(); }\
199  void undoIsDone() { getComponent()->undoIsDone(); }\
200  tlp::Interactor* getComponent() const {\
201  if(!_component) {\
202  _component = tlp::PluginLister::instance()->getPluginObject<Interactor>(BASE_INTERACTOR_STRING_NAME,NULL); assert(_component != NULL);\
203  }\
204  return _component;\
205  }\
206 };\
207 PLUGIN(CLASS_NAME)
208 
209 /**
210  * @ingroup Plugins
211  * @def INTERACTORPLUGINVIEWEXTENSIONWITHPRIORITY(CLASS_NAME,STRING_CLASS_NAME,BASE_INTERACTOR_STRING_NAME,VIEW_STRING_NAME,AUTHOR,DATE,DESCRIPTION,VERSION,PRIORITY)
212  * @brief Similar to INTERACTORPLUGINVIEWEXTENSION but allows to define the generated interactor's priority.
213  * @see tlp::Interactor::priority()
214  * @see INTERACTORPLUGINVIEWEXTENSION
215  */
216 #define INTERACTORPLUGINVIEWEXTENSIONWITHPRIORITY(CLASS_NAME,STRING_CLASS_NAME,BASE_INTERACTOR_STRING_NAME,VIEW_STRING_NAME,AUTHOR,DATE,DESCRIPTION,VERSION,PRIORITY) \
217 class CLASS_NAME : public tlp::Interactor {\
218  mutable tlp::Interactor* _component;\
219 public:\
220  std::string name() const { return std::string(STRING_CLASS_NAME); } \
221  std::string author() const { return std::string(AUTHOR); }\
222  std::string date() const { return std::string(DATE); } \
223  std::string info() const { return std::string(DESCRIPTION); } \
224  std::string release() const { return std::string(VERSION); }\
225  std::string tulipRelease() const { return std::string(TULIP_RELEASE); }\
226  std::string group() const { return getComponent()->group(); }\
227  CLASS_NAME(const PluginContext *):_component(NULL) {}\
228  bool isCompatible(const std::string& viewName) const { return viewName == VIEW_STRING_NAME; }\
229  QWidget* configurationWidget() const { return getComponent()->configurationWidget(); }\
230  unsigned int priority() const { return PRIORITY; }\
231  QAction* action() const { return getComponent()->action(); }\
232  tlp::View* view() const { return getComponent()->view(); }\
233  QCursor cursor() const { return getComponent()->cursor(); }\
234  void construct() { getComponent()->construct(); }\
235  void setView(tlp::View* v) { getComponent()->setView(v); }\
236  void install(QObject* target) { getComponent()->install(target); }\
237  void uninstall() { getComponent()->uninstall(); }\
238  void undoIsDone() { getComponent()->undoIsDone(); }\
239  tlp::Interactor* getComponent() const {\
240  if(!_component) {\
241  _component = tlp::PluginLister::instance()->getPluginObject<Interactor>(BASE_INTERACTOR_STRING_NAME,NULL); assert(_component != NULL);\
242  }\
243  return _component;\
244  }\
245 };\
246 PLUGIN(CLASS_NAME)
247 
248 }
249 
250 #endif