diff --git a/krita/data/actions/TextTool.action b/krita/data/actions/TextTool.action --- a/krita/data/actions/TextTool.action +++ b/krita/data/actions/TextTool.action @@ -15,7 +15,7 @@ Decrease Indent Decrease Indent - format-indent-less + false @@ -81,7 +81,7 @@ Increase Indent Increase Indent - format-indent-more + false diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp @@ -42,6 +42,8 @@ #include "kis_color_selector_settings.h" #include "kis_color_selector_container.h" +#include "kis_action_registry.h" + KisColorSelectorNgDockerWidget::KisColorSelectorNgDockerWidget(QWidget *parent) : QWidget(parent), m_colorHistoryAction(0), @@ -93,11 +95,13 @@ m_colorHistoryAction = new QAction("Show color history", this); m_colorHistoryAction->setShortcut(QKeySequence(tr("H"))); + // m_colorHistoryAction = KisActionRegistry::instance()->makeQAction("show_color_history", this, "Color Selector"); connect(m_colorHistoryAction, SIGNAL(triggered()), m_colorHistoryWidget, SLOT(showPopup()), Qt::UniqueConnection); m_commonColorsAction = new QAction("Show common colors", this); m_commonColorsAction->setShortcut(QKeySequence(tr("U"))); + // m_colorHistoryAction = KisActionRegistry::instance()->makeQAction("show_common_colors", this, "Color Selector"); connect(m_commonColorsAction, SIGNAL(triggered()), m_commonColorsWidget, SLOT(showPopup()), Qt::UniqueConnection); } diff --git a/krita/ui/KisPart.cpp b/krita/ui/KisPart.cpp --- a/krita/ui/KisPart.cpp +++ b/krita/ui/KisPart.cpp @@ -40,7 +40,6 @@ #include "KisViewManager.h" #include "KisOpenPane.h" #include "KisImportExportManager.h" -#include #include #include @@ -126,44 +125,10 @@ foreach (const QString &name, actionNames) { - QDomElement actionXml = actionRegistry->getActionXml(name); - - // Convenience macros to extract text of a child node. - auto getChildContent = [=](QString node){return actionXml.firstChildElement(node).text();}; - // i18n requires converting format from QString. - auto getChildContent_i18n = [=](QString node) { - if (getChildContent(node).isEmpty()) { - // dbgAction << "Found empty string to translate for property" << node; - return QString(); - } - return i18n(getChildContent(node).toUtf8().constData()); - }; - - QString icon = getChildContent("icon"); - QString text = getChildContent("text"); - - // Note: these fields in the .action definitions are marked for translation. - QString whatsthis = getChildContent_i18n("whatsThis"); - QString toolTip = getChildContent_i18n("toolTip"); - QString statusTip = getChildContent_i18n("statusTip"); - QString iconText = getChildContent_i18n("iconText"); - - bool isCheckable = getChildContent("isCheckable") == QString("true"); - QKeySequence shortcut = QKeySequence(getChildContent("shortcut")); - QKeySequence defaultShortcut = QKeySequence(getChildContent("defaultShortcut")); - - KisAction *a = new KisAction(KisIconUtils::loadIcon(icon.toLatin1()), text); - a->setObjectName(name); - a->setWhatsThis(whatsthis); - a->setToolTip(toolTip); - a->setStatusTip(statusTip); - a->setIconText(iconText); - a->setDefaultShortcut(shortcut); - a->setShortcut(shortcut); //TODO: Make this configurable from custom settings - a->setCheckable(isCheckable); - - - // XXX: these checks may become important again after refactoring + + KisAction *a = new KisAction(); + actionRegistry->propertizeAction(a, name); + if (!actionCollection->action(name)) { actionCollection->addAction(name, a); } @@ -174,30 +139,7 @@ } - // TODO: check for colliding shortcuts - // - // Ultimately we want to have more than one KActionCollection, so we can - // have things like Ctrl+I be italics in the text editor widget, while not - // complaining about conflicts elsewhere. Right now, we use only one - // collection, and we don't make things like the text editor configurable, - // so duplicate shortcuts are handled mostly automatically by the shortcut - // editor. - // - // QMap existingShortcuts; - // foreach(QAction* action, actionCollection->actions()) { - // if(action->shortcut() == QKeySequence(0)) { - // continue; - // } - // if (existingShortcuts.contains(action->shortcut())) { - // dbgAction << QString("Actions %1 and %2 have the same shortcut: %3") \ - // .arg(action->text()) \ - // .arg(existingShortcuts[action->shortcut()]->text()) \ - // .arg(action->shortcut()); - // } - // else { - // existingShortcuts[action->shortcut()] = action; - // } - // } + }; @@ -501,9 +443,8 @@ // planned anyway. // WidgetAction + WindowAction + ApplicationAction leaves only GlobalAction excluded - KisShortcutsDialog dlg; - dlg.addCollection(d->actionCollection); - dlg.configure(); // Show the dialog. + + KisActionRegistry::instance()->configureShortcuts(d->actionCollection); // Now update the widget tooltips in the UI. diff --git a/krita/ui/tool/kis_tool_polyline_base.cpp b/krita/ui/tool/kis_tool_polyline_base.cpp --- a/krita/ui/tool/kis_tool_polyline_base.cpp +++ b/krita/ui/tool/kis_tool_polyline_base.cpp @@ -32,6 +32,8 @@ #include #include +#include "kis_action_registry.h" + #define SNAPPING_THRESHOLD 10 #define SNAPPING_HANDLE_RADIUS 8 #define PREVIEW_LINE_WIDTH 1 diff --git a/libs/widgetutils/kis_action_registry.h b/libs/widgetutils/kis_action_registry.h --- a/libs/widgetutils/kis_action_registry.h +++ b/libs/widgetutils/kis_action_registry.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "kritawidgetutils_export.h" @@ -68,6 +69,27 @@ /** + * Saves action in a category. Note that this grabs ownership of the action. + */ + void addAction(QString name, QAction *a, QString category = "Krita"); + + + /** + * Produces a new QAction based on the .action data files. + */ + QAction * makeQAction(QString name, QObject *parent, QString category = QString()); + + KActionCollection * getDefaultCollection(); + + /** + * Fills the standard QAction properties of an action. + * + * @return true if the action was loaded successfully. + */ + bool propertizeAction(QString name, QAction *a); + + + /** * @return list of actions with data available. */ QStringList allActions(); @@ -79,6 +101,11 @@ /** + * Run shortcuts dialog. + */ + void configureShortcuts(KActionCollection *ac); + + /** * Constructor. Please don't touch! */ KisActionRegistry(); diff --git a/libs/widgetutils/kis_action_registry.cpp b/libs/widgetutils/kis_action_registry.cpp --- a/libs/widgetutils/kis_action_registry.cpp +++ b/libs/widgetutils/kis_action_registry.cpp @@ -19,16 +19,17 @@ #include #include -#include -#include #include -#include -#include -#include -#include "kis_debug.h" -#include #include +#include +#include +#include +#include +#include "kis_debug.h" +#include "KoResourcePaths.h" +#include "kis_icon_utils.h" +#include "kactioncollection.h" #include "kis_action_registry.h" @@ -54,6 +55,8 @@ { public: + Private(KisActionRegistry *_q) : q(_q) {}; + /** * We associate three pieces of information with each shortcut name. The * first piece of information is a QDomElement, containing the raw data from @@ -65,10 +68,15 @@ */ QHash actionInfoList; KSharedConfigPtr cfg{0}; - void loadActions(); + void loadActionFiles(); + void loadActionCollections(); actionInfoItem actionInfo(QString name) { return actionInfoList.value(name, emptyActionInfo); }; + + KisActionRegistry *q; + KActionCollection * defaultActionCollection; + QHash actionCollections; }; @@ -81,10 +89,15 @@ KisActionRegistry::KisActionRegistry() - : d(new KisActionRegistry::Private()) + : d(new KisActionRegistry::Private(this)) { - d->cfg = KSharedConfig::openConfig("kritashortcutsrc"); - d->loadActions(); + d->cfg = KSharedConfig::openConfig("krbitashortcutsrc"); + d->loadActionFiles(); + + // Should change to , then translate + d->defaultActionCollection = new KActionCollection(this, "Krita"); + d->actionCollections.insert("Krita", d->defaultActionCollection); + } // No this isn't the most efficient logic, but it's nice and readable. @@ -120,7 +133,152 @@ return d->actionInfo(name).xmlData; }; -void KisActionRegistry::Private::loadActions() +KActionCollection * KisActionRegistry::getDefaultCollection() +{ + return d->defaultActionCollection; +}; + +void KisActionRegistry::addAction(QString name, QAction *a, QString category) +{ + KActionCollection *ac; + if (d->actionCollections.contains(category)) { + ac = d->actionCollections.value(category); + } else { + ac = new KActionCollection(this, category); + d->actionCollections.insert("Krita", ac); + dbgAction << "Adding a new KActionCollection - " << category; + } + + if (!ac->action(name)) { + ac->addAction(name, a); + } + else { + dbgAction << "duplicate action" << name << a << "in collection" << ac->componentName(); + } + + // TODO: look into the loading/saving mechanism + ac->readSettings(); +}; + + + +QAction * KisActionRegistry::makeQAction(QString name, QObject *parent, QString category) +{ + + QAction * a = new QAction(parent); + if (!d->actionInfoList.contains(name)) { + dbgAction << "Warning: requested data for unknown action" << name; + return a; + } + + propertizeAction(name, a); + addAction(name, a, category); + + return a; +}; + + +void KisActionRegistry::configureShortcuts(KActionCollection *ac) +{ + + KisShortcutsDialog dlg; + dlg.addCollection(ac); + foreach (auto collection, d->actionCollections) { + dlg.addCollection(collection); + } + + dlg.configure(); // Show the dialog. +} + + + +bool KisActionRegistry::propertizeAction(QString name, QAction * a) +{ + + QStringList actionNames = allActions(); + QDomElement actionXml = getActionXml(name); + + + // Convenience macros to extract text of a child node. + auto getChildContent = [=](QString node){return actionXml.firstChildElement(node).text();}; + // i18n requires converting format from QString. + auto getChildContent_i18n = [=](QString node) { + if (getChildContent(node).isEmpty()) { + dbgAction << "Found empty string to translate for property" << node; + return QString(); + } + return i18n(getChildContent(node).toUtf8().constData()); + }; + + + QString icon = getChildContent("icon"); + QString text = getChildContent("text"); + + // Note: these fields in the .action definitions are marked for translation. + QString whatsthis = getChildContent_i18n("whatsThis"); + QString toolTip = getChildContent_i18n("toolTip"); + QString statusTip = getChildContent_i18n("statusTip"); + QString iconText = getChildContent_i18n("iconText"); + + bool isCheckable = getChildContent("isCheckable") == QString("true"); + QKeySequence shortcut = QKeySequence(getChildContent("shortcut")); + QKeySequence defaultShortcut = QKeySequence(getChildContent("defaultShortcut")); + + + a->setObjectName(name); // This is helpful!! + a->setIcon(KisIconUtils::loadIcon(icon.toLatin1())); + a->setText(text); + a->setObjectName(name); + a->setWhatsThis(whatsthis); + a->setToolTip(toolTip); + a->setStatusTip(statusTip); + a->setIconText(iconText); + a->setShortcut(shortcut); + a->setCheckable(isCheckable); + + + // XXX: this totally duplicates KisAction::setDefaultShortcut + QList listifiedShortcut; + listifiedShortcut.append(shortcut); + setProperty("defaultShortcuts", qVariantFromValue(listifiedShortcut)); + + + + + // TODO: check for colliding shortcuts, or make sure it happens smartly inside kactioncollection + // + // Ultimately we want to have more than one KActionCollection, so we can + // have things like Ctrl+I be italics in the text editor widget, while not + // complaining about conflicts elsewhere. Right now, we use only one + // collection, and we don't make things like the text editor configurable, + // so duplicate shortcuts are handled mostly automatically by the shortcut + // editor. + // + // QMap existingShortcuts; + // foreach(QAction* action, actionCollection->actions()) { + // if(action->shortcut() == QKeySequence(0)) { + // continue; + // } + // if (existingShortcuts.contains(action->shortcut())) { + // dbgAction << QString("Actions %1 and %2 have the same shortcut: %3") \ + // .arg(action->text()) \ + // .arg(existingShortcuts[action->shortcut()]->text()) \ + // .arg(action->shortcut()); + // } + // else { + // existingShortcuts[action->shortcut()] = action; + // } + // } + + + return true; +} + + + + + +void KisActionRegistry::Private::loadActionFiles() { KoResourcePaths::addResourceType("kis_actions", "data", "krita/actions");