Commit aeced4a1 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

All shortcuts should be configurable when no document is open

The problem happens because some actions are created/added-to-collection
only after a document is created. Now we workaround it by faking the
absent actions and deleting them together with KisActionsSnapshot.

Another problem is that some of the actions, e.g. "show_color_history",
is created long before it is added to the global action collection. It
is _created_ right at the start of Krita, but _added_ only when a new document
is constructed. If we change the shortcut between these two events, then
the changed value will be lost. Now we workaround this problem by connecting
to the action collection, listening to 'inserted()' signal and updating
shortcuts when an action is added to the collection.

BUG:370720
parent 794790e2
<!-- Disabled, since Connection Tool is disabled in Krita
<?xml version="1.0" encoding="UTF-8"?>
<ActionCollection version="2" name="Tools">
<Actions category="connection-tool">
......@@ -154,3 +156,5 @@
</Action>
</Actions>
</ActionCollection>
commented out! -->
......@@ -50,18 +50,6 @@
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="import_resources">
<icon></icon>
<text>Import Resources or Bundles...</text>
<whatsThis></whatsThis>
<toolTip>Import Resources or Bundles</toolTip>
<iconText>Import Resources or Bundles</iconText>
<activationFlags>0</activationFlags>
<activationConditions>0</activationConditions>
<shortcut></shortcut>
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="create_bundle">
<icon></icon>
<text>Create Resource Bundle...</text>
......@@ -512,26 +500,6 @@
<isCheckable>true</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="zoom_in">
<icon>zoom-in</icon>
<text>Zoom &amp;In</text>
<whatsThis></whatsThis>
<toolTip>Zoom In</toolTip>
<iconText>Zoom In</iconText>
<shortcut>Ctrl++; Ctrl+=</shortcut>
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="zoom_out">
<icon>zoom-out</icon>
<text>Zoom &amp;Out</text>
<whatsThis></whatsThis>
<toolTip>Zoom Out</toolTip>
<iconText>Zoom Out</iconText>
<shortcut>Ctrl+-</shortcut>
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="reset_fg_bg">
<icon></icon>
<text>Reset Foreground and Background Color</text>
......@@ -1614,20 +1582,12 @@
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="KisToolSelectBrush">
<icon></icon>
<text>Brush Selection Tool</text>
<whatsThis></whatsThis>
<toolTip>Brush Selection Tool</toolTip>
<iconText>Brush Selection Tool</iconText>
<shortcut></shortcut>
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
</Actions>
<Actions category="Blending Modes">
<text>Blending Modes</text>
<!-- commented out in the code right now
<Action name="Next Blending Mode">
<icon></icon>
<text>Next Blending Mode</text>
......@@ -1648,6 +1608,7 @@
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
-->
<Action name="Select Normal Blending Mode">
<icon></icon>
<text>Select Normal Blending Mode</text>
......@@ -2879,16 +2840,6 @@
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="merge_selected_layers">
<icon></icon>
<text>&amp;Merge Selected Layers</text>
<whatsThis></whatsThis>
<toolTip>Merge Selected Layers</toolTip>
<iconText>Merge Selected Layers</iconText>
<shortcut>Ctrl+Alt+E</shortcut>
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<Action name="layer_style">
<icon></icon>
<text>La&amp;yer Style...</text>
......
......@@ -62,6 +62,7 @@
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
<!-- commented out in the code right now
<Action name="file_reload_file">
<icon></icon>
<text>Reload</text>
......@@ -74,6 +75,7 @@
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
-->
<Action name="file_import_file">
<icon>document-import</icon>
<text>Open ex&amp;isting Document as Untitled Document...</text>
......
......@@ -150,7 +150,7 @@ class KisViewManager::KisViewManagerPrivate
public:
KisViewManagerPrivate(KisViewManager *_q, QWidget *_q_parent)
KisViewManagerPrivate(KisViewManager *_q, KActionCollection *_actionCollection, QWidget *_q_parent)
: filterManager(_q)
, createTemplate(0)
, saveIncremental(0)
......@@ -174,13 +174,14 @@ public:
, gridManager(_q)
, canvasControlsManager(_q)
, paintingAssistantsManager(_q)
, actionManager(_q)
, actionManager(_q, _actionCollection)
, mainWindow(0)
, showFloatingMessage(true)
, currentImageView(0)
, canvasResourceProvider(_q)
, canvasResourceManager()
, guiUpdateCompressor(30, KisSignalCompressor::POSTPONE, _q)
, actionCollection(_actionCollection)
, mirrorManager(_q)
, inputManager(_q)
, actionAuthor(0)
......@@ -248,7 +249,7 @@ public:
KisViewManager::KisViewManager(QWidget *parent, KActionCollection *_actionCollection)
: d(new KisViewManagerPrivate(this, parent))
: d(new KisViewManagerPrivate(this, _actionCollection, parent))
{
d->actionCollection = _actionCollection;
d->mainWindow = dynamic_cast<QMainWindow*>(parent);
......
......@@ -56,18 +56,22 @@ public:
}
KisViewManager* viewManager;
KActionCollection *actionCollection;
QList<KisAction*> actions;
KoGenericRegistry<KisOperationUIFactory*> uiRegistry;
KisOperationRegistry operationRegistry;
};
KisActionManager::KisActionManager(KisViewManager* viewManager)
KisActionManager::KisActionManager(KisViewManager* viewManager, KActionCollection *actionCollection)
: d(new Private)
{
d->viewManager = viewManager;
d->actionCollection = actionCollection;
connect(d->actionCollection,
SIGNAL(inserted(QAction*)), SLOT(slotActionAddedToCollection(QAction*)));
}
KisActionManager::~KisActionManager()
......@@ -121,15 +125,27 @@ void KisActionManager::setView(QPointer<KisView> imageView)
Q_UNUSED(imageView);
}
void KisActionManager::slotActionAddedToCollection(QAction *action)
{
/**
* Small hack alert: not all the actions are still created by the manager and
* immediately added to the action collection. Some plugins add actions
* directly to the action collection when a document is created. Here we
* catch these cases
*/
KisActionRegistry::instance()->updateShortcut(action->objectName(), action);
}
void KisActionManager::addAction(const QString& name, KisAction* action)
{
Q_ASSERT(!name.isEmpty());
Q_ASSERT(action);
Q_ASSERT(d->viewManager);
Q_ASSERT(d->viewManager->actionCollection());
Q_ASSERT(d->actionCollection);
d->viewManager->actionCollection()->addAction(name, action);
action->setParent(d->viewManager->actionCollection());
d->actionCollection->addAction(name, action);
action->setParent(d->actionCollection);
d->actions.append(action);
action->setActionManager(this);
......@@ -140,8 +156,8 @@ void KisActionManager::takeAction(KisAction* action)
d->actions.removeOne(action);
if (!action->objectName().isEmpty()) {
KIS_ASSERT_RECOVER_RETURN(d->viewManager->actionCollection());
d->viewManager->actionCollection()->takeAction(action);
KIS_ASSERT_RECOVER_RETURN(d->actionCollection);
d->actionCollection->takeAction(action);
}
}
......
......@@ -49,11 +49,11 @@ class KisOperation;
* Ultimately it would be nice to unify these things more fully.
*
*/
class KRITAUI_EXPORT KisActionManager
class KRITAUI_EXPORT KisActionManager : public QObject
{
Q_OBJECT
public:
KisActionManager(KisViewManager* viewManager);
KisActionManager(KisViewManager* viewManager, KActionCollection *actionCollection);
virtual ~KisActionManager();
void setView(QPointer<KisView> imageView);
......@@ -100,6 +100,9 @@ public:
KisAction *createStandardAction(KStandardAction::StandardAction,
const QObject *receiver, const char *member);
private Q_SLOTS:
void slotActionAddedToCollection(QAction *action);
private:
void dumpActionFlags();
......
......@@ -54,7 +54,7 @@ class KisZoomController : public KoZoomController
{
public:
KisZoomController(KoCanvasController *co, KisCoordinatesConverter *zh, KActionCollection *actionCollection, KoZoomAction::SpecialButtons specialButtons, QObject *parent)
: KoZoomController(co, zh, actionCollection, false, specialButtons, parent),
: KoZoomController(co, zh, actionCollection, specialButtons, parent),
m_converter(zh)
{
}
......
......@@ -33,8 +33,7 @@
void KoZoomController::Private::init(KoCanvasController *co,
KoZoomHandler *zh,
KActionCollection *actionCollection,
bool createZoomShortcuts)
KActionCollection *actionCollection)
{
canvasController = co;
fitMargin = co->margin();
......@@ -50,11 +49,6 @@ void KoZoomController::Private::init(KoCanvasController *co,
actionCollection->addAction("view_zoom", action);
if (createZoomShortcuts) {
actionCollection->addAction(KStandardAction::ZoomIn, "zoom_in", action, SLOT(zoomIn()));
actionCollection->addAction(KStandardAction::ZoomOut, "zoom_out", action, SLOT(zoomOut()));
}
connect(canvasController->proxyObject, SIGNAL( sizeChanged(const QSize & ) ), parent, SLOT( setAvailableSize() ) );
connect(canvasController->proxyObject, SIGNAL( zoomRelative(const qreal, const QPointF& ) ), parent, SLOT( requestZoomRelative( const qreal, const QPointF& ) ) );
......@@ -64,15 +58,7 @@ KoZoomController::KoZoomController(KoCanvasController *co, KoZoomHandler *zh, KA
: QObject(parent),
d(new Private(this, specialButtons))
{
d->init(co, zh, actionCollection, true);
}
KoZoomController::KoZoomController(KoCanvasController *co, KoZoomHandler *zh, KActionCollection *actionCollection, bool createZoomShortcuts, KoZoomAction::SpecialButtons specialButtons, QObject *parent)
: QObject(parent),
d(new Private(this, specialButtons))
{
d->init(co, zh, actionCollection, createZoomShortcuts);
d->init(co, zh, actionCollection);
}
KoZoomController::~KoZoomController()
......
......@@ -74,24 +74,6 @@ public:
KoZoomAction::SpecialButtons specialButtons = 0,
QObject *parent = 0);
/**
* A special override for for creation of a zoom controller
* without automatic generation of standard zoom in and zoom out
* actions. The caller is supposed create and connect the
* corresponding actions himself.
*
* @param createZoomShortcuts shows whether the zoom actions should be
* created or not.
*
* Used in KisZoomController.
*/
KoZoomController(KoCanvasController *controller,
KoZoomHandler *zoomHandler,
KActionCollection *actionCollection,
bool createZoomShortcuts,
KoZoomAction::SpecialButtons specialButtons = 0,
QObject *parent = 0);
/// destructor
~KoZoomController();
......
......@@ -69,8 +69,7 @@ public:
void init(KoCanvasController *co,
KoZoomHandler *zh,
KActionCollection *actionCollection,
bool createZoomShortcuts);
KActionCollection *actionCollection);
KoCanvasController *canvasController;
KoZoomHandler *zoomHandler;
......
......@@ -32,13 +32,19 @@ struct KisActionsSnapshot::Private
~Private() {
qDeleteAll(actionCollections);
qDeleteAll(fakeActions);
}
QSet<QString> nonRegisteredShortcuts;
QVector<QAction*> fakeActions;
};
KisActionsSnapshot::KisActionsSnapshot()
: m_d(new Private)
{
m_d->nonRegisteredShortcuts =
QSet<QString>::fromList(
KisActionRegistry::instance()->registeredShortcutIds());
}
KisActionsSnapshot::~KisActionsSnapshot()
......@@ -47,6 +53,7 @@ KisActionsSnapshot::~KisActionsSnapshot()
void KisActionsSnapshot::addAction(const QString &name, QAction *action)
{
m_d->nonRegisteredShortcuts.remove(name);
KisActionRegistry::ActionCategory cat = KisActionRegistry::instance()->fetchActionCategory(name);
if (!cat.isValid()) {
......@@ -70,8 +77,30 @@ void KisActionsSnapshot::addAction(const QString &name, QAction *action)
collection->addCategorizedAction(name, action, cat.categoryName);
}
QMap<QString, KActionCollection *> KisActionsSnapshot::actionCollections() const
QMap<QString, KActionCollection *> KisActionsSnapshot::actionCollections()
{
/**
* A small heruistics to show warnings only when unknown shortcuts arppear
* in the non-registered list
*/
if (m_d->nonRegisteredShortcuts.size() > 4 &&
m_d->nonRegisteredShortcuts.size() < 160) {
warnKrita << "WARNING: The following shortcuts are not registeren in the collection, "
"they might have wrong shortcuts in the end:";
Q_FOREACH (const QString &str, m_d->nonRegisteredShortcuts) {
warnKrita << str;
}
warnKrita << "=== end ===";
}
// try to workaround non-registered shortcuts by faking them manually
Q_FOREACH (const QString &str, m_d->nonRegisteredShortcuts) {
QAction *action = KisActionRegistry::instance()->makeQAction(str, 0);
m_d->fakeActions << action;
addAction(action->objectName(), action);
}
return m_d->actionCollections;
}
......@@ -49,7 +49,7 @@ public:
* WARNING: the collections are owned by the shapshot! Don't destroy
* the snapshot before you are done with the collections!
*/
QMap<QString, KActionCollection*> actionCollections() const;
QMap<QString, KActionCollection*> actionCollections();
private:
struct Private;
......
......@@ -238,6 +238,11 @@ bool KisActionRegistry::sanityCheckPropertized(const QString &name)
return d->sanityPropertizedShortcuts.contains(name);
}
QList<QString> KisActionRegistry::registeredShortcutIds() const
{
return d->actionInfoList.keys();
}
bool KisActionRegistry::propertizeAction(const QString &name, QAction * a)
{
if (!d->actionInfoList.contains(name)) {
......
......@@ -23,6 +23,7 @@
#include <QKeySequence>
#include <QDomElement>
#include <QAction>
#include <QList>
#include "kritawidgetutils_export.h"
......@@ -139,6 +140,8 @@ public:
bool sanityCheckPropertized(const QString &name);
QList<QString> registeredShortcutIds() const;
Q_SIGNALS:
void shortcutsUpdated();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment