39#include <QTabletEvent>
42#include <QApplication>
48#include <klocalizedstring.h>
49#include <QKeySequence>
52#include <QGlobalStatic>
72 delete dummyToolWidget;
78 disabledGlobalActions.clear();
82 if (!windowActionCollection) {
83 qWarning() <<
"We haven't got an action collection";
89 QMap<QKeySequence, QStringList> shortcutMap;
93 Q_FOREACH(QAction *action, windowActionCollection->
actions()) {
95 if (action->property(
"tool_action").isValid()) {
96 QStringList tools = action->property(
"tool_action").toStringList();
100 action->setEnabled(
true);
101 toolActions << action->objectName();
104 if (tools.contains(activeToolId) || action->property(
"always_enabled").toBool()) {
106 action->setEnabled(
true);
107 toolActions << action->objectName();
111 action->setDisabled(
true);
116 globalActions << action->objectName();
119 Q_FOREACH(QKeySequence keySequence, action->shortcuts()) {
121 if (keySequence.toString() !=
"") {
122 if (shortcutMap.contains(keySequence)) {
123 shortcutMap[keySequence].append(action->objectName());
126 shortcutMap[keySequence] =
QStringList() << action->objectName();
133 Q_FOREACH(
const QKeySequence &k, shortcutMap.keys()) {
134 if (shortcutMap[k].size() > 1) {
137 bool toolActionFound =
false;
138 Q_FOREACH(
const QString &action, actions) {
139 if (toolActions.contains(action)) {
140 toolActionFound =
true;
143 Q_FOREACH(
const QString &action, actions) {
144 if (toolActionFound && globalActions.contains(action)) {
146 windowActionCollection->
action(action)->setEnabled(
false);
147 disabledGlobalActions << action;
166 Q_FOREACH(
const QString &action, toolActions) {
168 windowActionCollection->
action(action)->setDisabled(
true);
170 Q_FOREACH(
const QString &action, disabledGlobalActions) {
172 windowActionCollection->
action(action)->setEnabled(
true);
195 connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
206 return d->toolActionList;
211 if (
d->canvasses.contains(controller)) {
212 d->switchTool(
d->canvasses.value(controller).first()->activeToolId);
218 return d->inputDevice;
228 Q_ASSERT(controller);
229 if (
d->canvasses.contains(controller))
232 d->attachCanvas(controller);
240 Q_ASSERT(controller);
243 d->detachCanvas(controller);
249 if (controllerActual) {
261 if (!
d->canvasData)
return;
262 d->switchInputDevice(
id);
267 if (!
d->canvasData)
return;
268 if (
d->canvasData->mostRecentTools.isEmpty())
return;
269 d->switchTool(
d->canvasData->mostRecentTools.first()->toolId());
277 return d->canvasData->allTools.value(
id);
284 if (!
d->canvasData)
return 0;
290 QSet<QString> shapeTypes;
291 Q_FOREACH (
KoShape *shape, shapes) {
292 shapeTypes << shape->
shapeId();
302 bool toolWillWork =
false;
303 foreach (
const QString &type, shapeTypes) {
311 toolType = helper->
id();
323 d->disconnectActiveTool();
324 d->connectActiveTool();
346 if (!
d->canvasData)
return QString();
347 return d->canvasData->activeToolId;
372 layerExplicitlyDisabled(false)
376KoToolManager::Private::~Private()
378 qDeleteAll(toolActionList);
384 QHash<QString, KoToolBase*> toolsHash;
386 KoToolBase* tool = createTool(controller, toolAction);
388 toolsHash.insert(tool->
toolId(), tool);
400 QHash<QString, KoToolBase*> origHash;
402 if (canvasses.contains(controller)) {
403 origHash = canvasses.value(controller).first()->allTools;
406 if (origHash.contains(toolAction->
id())) {
407 return origHash.value(toolAction->
id());
415 tool->setObjectName(toolAction->
id());
426void KoToolManager::Private::setup()
428 if (toolActionList.size() > 0)
433 Q_FOREACH (
const QString &
id, registry->
keys()) {
438void KoToolManager::Private::connectActiveTool()
440 if (canvasData->activeTool) {
441 connect(canvasData->activeTool, SIGNAL(cursorChanged(QCursor)),
443 connect(canvasData->activeTool, SIGNAL(activateTool(QString)),
444 q, SLOT(switchToolRequested(QString)));
445 connect(canvasData->activeTool, SIGNAL(statusTextChanged(QString)),
446 q, SIGNAL(changedStatusText(QString)));
447 connect(canvasData->activeTool, SIGNAL(textModeChanged(
bool)),
448 q, SIGNAL(textModeChanged(
bool)));
453 const QHash<int, KoAbstractCanvasResourceInterfaceSP> abstractResources =
454 canvasData->activeTool->toolAbstractResources();
455 const QHash<int, KoDerivedResourceConverterSP> converters = canvasData->activeTool->toolConverters();
471void KoToolManager::Private::disconnectActiveTool()
473 if (canvasData->activeTool) {
477 const QList<int> abstractKeys = canvasData->activeTool->toolAbstractResources().keys();
478 const QList<int> derivedKeys = canvasData->activeTool->toolConverters().keys();
479 for (
int key : abstractKeys) {
483 for (
int key : derivedKeys) {
489 canvasData->deactivateToolActions();
492 Q_EMIT q->aboutToChangeTool(canvasData->canvas);
493 canvasData->activeTool->deactivate();
494 disconnect(canvasData->activeTool, SIGNAL(cursorChanged(QCursor)),
496 disconnect(canvasData->activeTool, SIGNAL(activateTool(QString)),
497 q, SLOT(switchToolRequested(QString)));
498 disconnect(canvasData->activeTool, SIGNAL(statusTextChanged(QString)),
499 q, SIGNAL(changedStatusText(QString)));
500 disconnect(canvasData->activeTool, SIGNAL(textModeChanged(
bool)),
501 q, SIGNAL(textModeChanged(
bool)));
505 Q_EMIT q->changedStatusText(QString());
508void KoToolManager::Private::switchTool(
const QString &
id)
510 if (!canvasData)
return;
512 canvasData->activeToolId = id;
513 KoToolBase *tool = canvasData->allTools.value(
id);
523 disconnectActiveTool();
525 if (canvasData->activeTool) {
526 canvasData->mostRecentTools.prepend(canvasData->activeTool);
528 canvasData->activeTool = tool;
529 canvasData->mostRecentTools.removeOne(tool);
535void KoToolManager::Private::postSwitchTool()
550 Q_ASSERT(canvasData);
551 if (!canvasData)
return;
553 QSet<KoShape*> shapesToOperateOn;
554 if (canvasData->activeTool
555 && canvasData->activeTool->canvas()
556 && canvasData->activeTool->canvas()->shapeManager()) {
557 KoSelection *selection = canvasData->activeTool->canvas()->shapeManager()->selection();
560 if (!shapesDelegatesList.isEmpty()) {
561 shapesToOperateOn = QSet<KoShape*>(shapesDelegatesList.begin(),
562 shapesDelegatesList.end());
566 if (canvasData->canvas->canvas()) {
568 updateToolForProxy();
575 canvasData->activateToolActions();
577 canvasData->activeTool->activate(shapesToOperateOn);
585 canvasData->activateToolActions();
587 canvasData->activeTool->activate(shapesToOperateOn);
591 if (optionWidgetList.empty()) {
593 QString title = canvasData->activeTool->factory()->toolTip();
594 toolWidget = canvasData->dummyToolWidget;
595 if (toolWidget == 0) {
596 toolWidget =
new QWidget();
597 toolWidget->setObjectName(
"DummyToolWidget");
598 QVBoxLayout *
layout =
new QVBoxLayout(toolWidget);
599 layout->setContentsMargins(3, 3, 3, 3);
600 canvasData->dummyToolLabel =
new QLabel(toolWidget);
601 layout->addWidget(canvasData->dummyToolLabel);
602 layout->addItem(
new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding));
603 canvasData->dummyToolWidget = toolWidget;
605 canvasData->dummyToolLabel->setText(i18n(
"Active tool: %1", title));
606 optionWidgetList.append(toolWidget);
610 Q_EMIT q->changedTool(canvasData->canvas);
612 Q_EMIT q->toolOptionWidgetsChanged(canvasData->canvas, optionWidgetList);
616void KoToolManager::Private::switchCanvasData(
CanvasData *cd)
625 oldInputDevice = canvasData->inputDevice;
627 if (canvasData->activeTool) {
628 disconnectActiveTool();
639 if (canvasData->activeTool) {
644 if (oldInputDevice != canvasData->inputDevice) {
645 Q_EMIT q->inputDeviceChanged(canvasData->inputDevice);
648 if (oldCanvas != canvasData->canvas->canvas()) {
649 Q_EMIT q->changedCanvas(canvasData->canvas->canvas());
655 Q_ASSERT(controller);
657 if (canvasData && canvasData->canvas == controller) {
661 if (canvas != controller) {
668 switchCanvasData(canvasses.value(newCanvas).first());
670 disconnectActiveTool();
682 Q_FOREACH (
CanvasData *canvasData, canvasses.value(controller)) {
684 if (! tools.contains(tool)) {
693 canvasses.remove(controller);
694 Q_EMIT q->changedCanvas(canvasData ? canvasData->
canvas->
canvas() : 0);
699 Q_ASSERT(controller);
703 switchCanvasData(cd);
707 canvasses_.append(cd);
708 canvasses[controller] = canvasses_;
716 int highestPriority = INT_MAX;
720 if (th->
priority() < highestPriority) {
721 highestPriority = qMin(highestPriority, th->
priority());
727 switchTool(helper->
id());
737 Q_EMIT q->changedCanvas(canvasData ? canvasData->
canvas->
canvas() : 0);
740void KoToolManager::Private::movedFocus(QWidget *from, QWidget *to)
744 if (!canvasData || to == 0) {
767 if (newCanvas == 0) {
772 Q_FOREACH (
CanvasData *data, canvasses.value(newCanvas)) {
774 switchCanvasData(data);
779 switchCanvasData(canvasses.value(newCanvas).first());
782void KoToolManager::Private::updateCursor(
const QCursor &cursor)
784 Q_ASSERT(canvasData);
785 Q_ASSERT(canvasData->
canvas);
790void KoToolManager::Private::selectionChanged(
const QList<KoShape*> &shapes)
793 Q_FOREACH (
KoShape *shape, shapes) {
795 if (delegates.isEmpty()) {
799 foreach (
KoShape *shape2, delegates) {
801 if (! types.contains(shape2->
shapeId())) {
802 types.append(shape2->
shapeId());
815 && !activationShapeIds.contains(
"flake/always")
816 && !activationShapeIds.contains(
"flake/edit")) {
818 bool currentToolWorks =
false;
819 foreach (
const QString &type, types) {
820 if (activationShapeIds.contains(type)) {
821 currentToolWorks =
true;
825 if (!currentToolWorks) {
830 Q_EMIT q->toolCodesSelected(types);
833void KoToolManager::Private::currentLayerChanged(
const KoShapeLayer *layer)
835 Q_EMIT q->currentLayerChanged(canvasData->
canvas, layer);
837 updateToolForProxy();
839 debugFlake <<
"Layer changed to" << layer <<
"explicitly disabled:" << layerExplicitlyDisabled;
842void KoToolManager::Private::updateToolForProxy()
847 bool canUseTool = !layerExplicitlyDisabled || canvasData->
activationShapeId.endsWith(QLatin1String(
"/always"));
851void KoToolManager::Private::switchInputDevice(
const KoInputDevice &device)
853 Q_ASSERT(canvasData);
854 if (!canvasData)
return;
855 if (inputDevice == device)
return;
856 if (inputDevice.isMouse() && device.
isMouse())
return;
857 if (device.
isMouse() && !inputDevice.isMouse()) {
870 switchCanvasData(cd);
886 canvasses[cd->
canvas] = items;
888 switchCanvasData(cd);
895 proxies.insert(canvas, proxy);
897 if (controller->
canvas() == canvas) {
905#include "moc_KoToolManager.cpp"
QList< QString > QStringList
Q_GLOBAL_STATIC(KisStoragePluginRegistry, s_instance)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
QList< KoToolBase * > mostRecentTools
const KoInputDevice inputDevice
QStringList disabledGlobalActions
QString activationShapeId
QWidget * dummyToolWidget
QHash< QString, KoToolBase * > allTools
void deactivateToolActions()
CanvasData(KoCanvasController *cc, const KoInputDevice &id)
void activateToolActions()
KoCanvasController *const canvas
A container for a set of QAction objects.
QAction * action(int index) const
QList< QAction * > actions() const
virtual void setCursor(const QCursor &cursor)=0
virtual KoShapeManager * shapeManager() const =0
virtual QWidget * canvasWidget()=0
QPointer< KoCanvasResourceProvider > resourceManager
virtual KoSelectedShapesProxy * selectedShapesProxy() const =0
selectedShapesProxy() is a special interface for keeping a persistent connections to selectionChanged...
KoCanvasController * canvasController() const
QPointer< KoCanvasControllerProxyObject > proxyObject
virtual KoCanvasBase * canvas() const
bool hasDerivedResourceConverter(int key)
bool hasAbstractResource(int key)
void removeAbstractResource(int key)
void removeDerivedResourceConverter(int key)
void setAbstractResource(KoAbstractCanvasResourceInterfaceSP abstractResource)
void addDerivedResourceConverter(KoDerivedResourceConverterSP converter)
const T value(const QString &id) const
QList< QString > keys() const
const QList< KoShape * > selectedEditableShapesAndDelegates() const
static KoShapeRegistry * instance()
virtual bool isShapeEditable(bool recursive=true) const
checks recursively if the shape or one of its parents is not visible or locked
QSet< KoShape * > toolDelegates() const
#define KIS_ASSERT_RECOVER_RETURN(cond)