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