File indexing completed on 2024-05-12 15:56:52
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2005-2006 Boudewijn Rempt <boud@valdyas.org> 0003 * SPDX-FileCopyrightText: 2006, 2008 Thomas Zander <zander@kde.org> 0004 * SPDX-FileCopyrightText: 2006 Thorsten Zachmann <zachmann@kde.org> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 #ifndef KO_TOOL_MANAGER 0009 #define KO_TOOL_MANAGER 0010 0011 #include "KoInputDevice.h" 0012 #include "kritaflake_export.h" 0013 0014 #include <QObject> 0015 #include <QList> 0016 0017 class KoCanvasController; 0018 class KoShapeControllerBase; 0019 class KoToolFactoryBase; 0020 class KoCanvasBase; 0021 class KoToolBase; 0022 class KisKActionCollection; 0023 class KoShape; 0024 class KoShapeLayer; 0025 class QKeySequence; 0026 0027 class QCursor; 0028 0029 /** 0030 * This class serves as a QAction-like control object for activation of a tool. 0031 * 0032 * It allows to implement a custom UI to control the activation of tools. 0033 * See KoToolBox & KoModeBox in the kowidgets library. 0034 * 0035 * KoToolAction objects are owned by the KoToolManager singleton 0036 * and live until the end of its lifetime. 0037 */ 0038 class KRITAFLAKE_EXPORT KoToolAction : public QObject 0039 { 0040 Q_OBJECT 0041 public: 0042 explicit KoToolAction(KoToolFactoryBase *toolFactory); 0043 ~KoToolAction() override; 0044 0045 public: 0046 QString id() const; ///< The id of the tool 0047 QString iconText() const; ///< The icontext of the tool 0048 QString toolTip() const; ///< The tooltip of the tool 0049 QString iconName() const; ///< The icon name of the tool 0050 QKeySequence shortcut() const; ///< The shortcut to activate the tool 0051 0052 QString section() const; ///< The section the tool wants to be in. 0053 int priority() const; ///< Lower number (higher priority) means coming first in the section. 0054 int buttonGroupId() const; ///< A unique ID for this tool as passed by changedTool(), >= 0 0055 QString visibilityCode() const; ///< This tool should become visible when we emit this string in toolCodesSelected() 0056 0057 KoToolFactoryBase *toolFactory() const; ///< Factory to create new tool object instances 0058 0059 public Q_SLOTS: 0060 void trigger(); ///< Request the activation of the tool 0061 0062 Q_SIGNALS: 0063 void changed(); ///< Emitted when a property changes (shortcut ATM) 0064 0065 private: 0066 class Private; 0067 Private *const d; 0068 }; 0069 0070 0071 /** 0072 * This class manages the activation and deactivation of tools for 0073 * each input device. 0074 * 0075 * Managing the active tool and switching tool based on various variables. 0076 * 0077 * The state of the toolbox will be the same for all views in the process so practically 0078 * you can say we have one toolbox per application instance (process). Implementation 0079 * does not allow one widget to be in more then one view, so we just make sure the toolbox 0080 * is hidden in not-in-focus views. 0081 * 0082 * The ToolManager is a singleton and will manage all views in all applications that 0083 * are loaded in this process. This means you will have to register and unregister your view. 0084 * When creating your new view you should use a KoCanvasController() and register that 0085 * with the ToolManager like this: 0086 @code 0087 MyGuiWidget::MyGuiWidget() { 0088 m_canvasController = new KoCanvasController(this); 0089 m_canvasController->setCanvas(m_canvas); 0090 KoToolManager::instance()->addControllers(m_canvasController)); 0091 } 0092 MyGuiWidget::~MyGuiWidget() { 0093 KoToolManager::instance()->removeCanvasController(m_canvasController); 0094 } 0095 @endcode 0096 * 0097 * For a new view that extends KoView all you need to do is implement KoView::createToolBox() 0098 * 0099 * KoToolManager also keeps track of the current tool based on a 0100 complex set of conditions and heuristics: 0101 0102 - there is one active tool per KoCanvasController (and there is one KoCanvasController 0103 per view, because this is a class with scrollbars and a zoomlevel and so on) 0104 - for every pointing device (determined by the unique id of tablet, 0105 or 0 for mice -- you may have more than one mouse attached, but 0106 Qt cannot distinguish between them, there is an associated tool. 0107 - depending on things like tablet leave/enter proximity, incoming 0108 mouse or tablet events and a little timer (that gets stopped when 0109 we know what is what), the active pointing device is determined, 0110 and the active tool is set accordingly. 0111 0112 Nota bene: if you use KoToolManager and register your canvases with 0113 it you no longer have to manually implement methods to route mouse, 0114 tablet, key or wheel events to the active tool. In fact, it's no 0115 longer interesting to you which tool is active; you can safely 0116 route the paint event through KoToolProxy::paint(). 0117 0118 (The reason the input events are handled completely by the 0119 toolmanager and the paint events not is that, generally speaking, 0120 it's okay if the tools get the input events first, but you want to 0121 paint your shapes or other canvas stuff first and only then paint 0122 the tool stuff.) 0123 0124 */ 0125 class KRITAFLAKE_EXPORT KoToolManager : public QObject 0126 { 0127 Q_OBJECT 0128 0129 public: 0130 KoToolManager(); 0131 /// Return the toolmanager singleton 0132 static KoToolManager* instance(); 0133 ~KoToolManager() override; 0134 0135 /** 0136 * Register actions for switching to tools at the actionCollection parameter. 0137 * The actions will have the text / shortcut as stated by the toolFactory. 0138 * If the application calls this in their KoView extending class they will have all the benefits 0139 * from allowing this in the menus and to allow the use to configure the shortcuts used. 0140 * @param ac the actionCollection that will be the parent of the actions. 0141 * @param controller tools registered with this controller will have all their actions added as well. 0142 */ 0143 void registerToolActions(KisKActionCollection *ac, KoCanvasController *controller); 0144 0145 /** 0146 * Register a new canvas controller 0147 * @param controller the view controller that this toolmanager will manage the tools for 0148 */ 0149 void addController(KoCanvasController *controller); 0150 0151 /** 0152 * Remove a set of controllers 0153 * When the controller is no longer used it should be removed so all tools can be 0154 * deleted and stop eating memory. 0155 * @param controller the controller that is removed 0156 */ 0157 void removeCanvasController(KoCanvasController *controller); 0158 /** 0159 * Attempt to remove a controller. 0160 * This is automatically called when a controller's proxy object is deleted, and 0161 * it ensures that the controller is, in fact, removed, even if the creator forgot 0162 * to do so. 0163 * @param controller the proxy object of the controller to be removed 0164 */ 0165 Q_SLOT void attemptCanvasControllerRemoval(QObject *controller); 0166 0167 /// @return the active canvas controller 0168 KoCanvasController *activeCanvasController() const; 0169 0170 /** 0171 * Returns the tool for the given tool id. The tool may be 0 0172 * @param canvas the canvas that is a child of a previously registered controller 0173 * who's tool you want. 0174 * @param id the tool identifier 0175 * @see addController() 0176 */ 0177 KoToolBase *toolById(KoCanvasBase *canvas, const QString &id) const; 0178 0179 /// @return the currently active pointing device 0180 KoInputDevice currentInputDevice() const; 0181 0182 /** 0183 * For the list of shapes find out which tool is the highest priority tool that can handle it. 0184 * @returns the toolId for the shapes. 0185 * @param shapes a list of shapes, a selection for example, that is used to look for the tool. 0186 */ 0187 QString preferredToolForSelection(const QList<KoShape*> &shapes); 0188 0189 /** 0190 * Returns the list of toolActions for the current tools. 0191 * @returns lists of toolActions for the current tools. 0192 */ 0193 QList<KoToolAction*> toolActionList() const; 0194 0195 /// Request tool activation for the given canvas controller 0196 void requestToolActivation(KoCanvasController *controller); 0197 0198 /// Returns the toolId of the currently active tool 0199 QString activeToolId() const; 0200 0201 void initializeCurrentToolForCanvas(); 0202 0203 class Private; 0204 /** 0205 * \internal return the private object for the toolmanager. 0206 */ 0207 KoToolManager::Private *priv(); 0208 0209 public Q_SLOTS: 0210 /** 0211 * Request switching tool 0212 * @param id the id of the tool 0213 */ 0214 void switchToolRequested(const QString &id); 0215 0216 /** 0217 * Request change input device 0218 * @param id the id of the input device 0219 */ 0220 void switchInputDeviceRequested(const KoInputDevice &id); 0221 0222 /** 0223 * Switches to the last tool used just before the current one, if any. 0224 */ 0225 void switchBackRequested(); 0226 0227 /** 0228 * Notify theme changes 0229 */ 0230 void themeChanged(); 0231 0232 Q_SIGNALS: 0233 /** 0234 * Emitted when a new tool is going to override the current tool 0235 * @param canvas the currently active canvas. 0236 */ 0237 void aboutToChangeTool(KoCanvasController *canvas); 0238 0239 /** 0240 * Emitted when a new tool was selected or became active. 0241 * @param canvas the currently active canvas. 0242 */ 0243 void changedTool(KoCanvasController *canvas); 0244 0245 /** 0246 * Emitted after the selection changed to state which unique shape-types are now 0247 * in the selection. 0248 * @param types a list of string that are the shape types of the selected objects. 0249 */ 0250 void toolCodesSelected(const QList<QString> &types); 0251 0252 /** 0253 * Emitted after the current layer changed either its properties or to a new layer. 0254 * @param canvas the currently active canvas. 0255 * @param layer the layer that is selected. 0256 */ 0257 void currentLayerChanged(const KoCanvasController *canvas, const KoShapeLayer *layer); 0258 0259 /** 0260 * Every time a new input device gets used by a tool, this event is emitted. 0261 * @param device the new input device that the user picked up. 0262 */ 0263 void inputDeviceChanged(const KoInputDevice &device); 0264 0265 /** 0266 * Emitted whenever the active canvas changed. 0267 * @param canvas the new activated canvas (might be 0) 0268 */ 0269 void changedCanvas(const KoCanvasBase *canvas); 0270 0271 /** 0272 * Emitted whenever the active tool changes the status text. 0273 * @param statusText the new status text 0274 */ 0275 void changedStatusText(const QString &statusText); 0276 0277 /** 0278 * emitted whenever a new tool is dynamically added for the given canvas 0279 */ 0280 void addedTool(KoToolAction *toolAction, KoCanvasController *canvas); 0281 0282 /** 0283 * Emit the new tool option widgets to be used with this canvas. 0284 */ 0285 void toolOptionWidgetsChanged(KoCanvasController *controller, const QList<QPointer<QWidget> > &widgets); 0286 private: 0287 KoToolManager(const KoToolManager&); 0288 KoToolManager operator=(const KoToolManager&); 0289 0290 Q_PRIVATE_SLOT(d, void detachCanvas(KoCanvasController *controller)) 0291 Q_PRIVATE_SLOT(d, void attachCanvas(KoCanvasController *controller)) 0292 Q_PRIVATE_SLOT(d, void movedFocus(QWidget *from, QWidget *to)) 0293 Q_PRIVATE_SLOT(d, void updateCursor(const QCursor &cursor)) 0294 Q_PRIVATE_SLOT(d, void selectionChanged(const QList<KoShape*> &shapes)) 0295 Q_PRIVATE_SLOT(d, void currentLayerChanged(const KoShapeLayer *layer)) 0296 0297 Private *const d; 0298 }; 0299 0300 #endif