diff --git a/krita/data/actions/TextTool.action b/krita/data/actions/TextTool.action index e20e2a6f26..df4327bd31 100644 --- a/krita/data/actions/TextTool.action +++ b/krita/data/actions/TextTool.action @@ -1,443 +1,443 @@ Align Right Ctrl+Alt+R Align Right format-justify-right false Align Right Ctrl+Alt+R Decrease Indent Decrease Indent - format-indent-less + false Decrease Indent Paragraph Ctrl+Alt+P Change paragraph margins, text flow, borders, bullets, numbering etc. <p>Change paragraph margins, text flow, borders, bullets, numbering etc.</p><p>Select text in multiple paragraphs to change the formatting of all selected paragraphs.</p><p>If no text is selected, the paragraph where the cursor is located will be changed.</p> false Paragraph... Ctrl+Alt+P Text Color Text Color... format-text-color false Text Color Special Character Alt+Shift+C Insert one or more symbols or characters not found on the keyboard character-set Insert one or more symbols or characters not found on the keyboard. false Special Character... Alt+Shift+C Shrink To Fit Shrink To Fit zoom-fit-best false Shrink To Fit Styles Debug Ctrl+Alt+Shift+S Styles Debug false Styles Debug Ctrl+Alt+Shift+S Increase Indent Increase Indent - format-indent-more + false Increase Indent Underline Ctrl+U Underline format-text-underline false Underline Ctrl+U Grow To Fit Width Grow To Fit Width zoom-fit-best false Grow To Fit Width Subscript Ctrl+Shift+B Subscript format-text-subscript false Subscript Ctrl+Shift+B Insert Non-Breaking Hyphen Ctrl+Shift+- Insert Non-Breaking Hyphen false Insert Non-Breaking Hyphen Ctrl+Shift+- Align Left Align Left format-justify-left false Align Left Insert Comment Ctrl+Shift+C Insert Comment false Insert Comment Ctrl+Shift+C Strikethrough Strikethrough format-text-strikethrough false Strikethrough Configure current section Configure current section configure false Configure current section Change text direction Ctrl+Shift+D Change writing direction format-text-direction-rtl false Change text direction Ctrl+Shift+D Insert Non-Breaking Space Ctrl+Space Insert Non-Breaking Space false Insert Non-Breaking Space Ctrl+Space Insert Soft Hyphen Insert Soft Hyphen false Insert Soft Hyphen Variable Variable false Variable Bullet list Bullet list format-list-unordered false Bullet list Insert Index Ctrl+T Insert Index false Insert Index Ctrl+T Align Center Ctrl+Alt+C Align Center format-justify-center false Align Center Ctrl+Alt+C Background Background Color... format-fill-color false Background Decrease Font Size Ctrl+< Decrease Font Size false Decrease Font Size Ctrl+< Insert new section Insert new section insert-text false Insert new section Font Size Font Size false Font Size Italic Ctrl+I Italic format-text-italic false Italic Ctrl+I Bold Ctrl+B Bold format-text-bold false Bold Ctrl+B Increase Font Size Ctrl+> Increase Font Size false Increase Font Size Ctrl+> Superscript Ctrl+Shift+P Superscript format-text-superscript false Superscript Ctrl+Shift+P Select All Ctrl+A Select All edit-select-all false Select &All Ctrl+A Numbered list Numbered list format-list-ordered false Numbered list Style Manager Ctrl+Alt+S Change attributes of styles <p>Change font and paragraph attributes of styles.</p><p>Multiple styles can be changed using the dialog box.</p> false Style Manager... Ctrl+Alt+S Align Block Ctrl+Alt+R Align Block format-justify-fill false Align Block Ctrl+Alt+R Grow To Fit Height Grow To Fit Height zoom-fit-best false Grow To Fit Height Paragraph Debug Ctrl+Alt+Shift+P Paragraph Debug false Paragraph Debug Ctrl+Alt+Shift+P Font Family Font Family false Font Family Font Ctrl+Alt+F Change character size, font, boldface, italics etc. Change the attributes of the currently selected characters. false Font... Ctrl+Alt+F Repaint Repaint view-refresh false Repaint 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 index 0ac9eba159..49c6ca13f7 100644 --- 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 @@ -1,220 +1,224 @@ /* * Copyright (c) 2010 Adam Celarek * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_color_selector_ng_docker_widget.h" #include "ui_wdg_color_selector_settings.h" #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_node_manager.h" #include "kis_canvas_resource_provider.h" #include "kis_color_space_selector.h" #include "kis_preference_set_registry.h" #include "kis_node.h" #include "kis_paint_device.h" #include "kis_color_history.h" #include "kis_common_colors.h" #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), m_commonColorsAction(0), m_verticalColorPatchesLayout(0), m_horizontalColorPatchesLayout(0), m_canvas(0) { setAutoFillBackground(true); m_colorSelectorContainer = new KisColorSelectorContainer(this); m_colorHistoryWidget = new KisColorHistory(this); m_commonColorsWidget = new KisCommonColors(this); //default settings //remember to also change the default in the ui file //shade selector //layout m_verticalColorPatchesLayout = new QHBoxLayout(); m_verticalColorPatchesLayout->setSpacing(0); m_verticalColorPatchesLayout->setMargin(0); m_verticalColorPatchesLayout->addWidget(m_colorSelectorContainer); m_horizontalColorPatchesLayout = new QVBoxLayout(this); m_horizontalColorPatchesLayout->setSpacing(0); m_horizontalColorPatchesLayout->setMargin(0); m_horizontalColorPatchesLayout->addLayout(m_verticalColorPatchesLayout); updateLayout(); connect(m_colorSelectorContainer, SIGNAL(openSettings()), this, SLOT(openSettings())); //emit settingsChanged() if the settings are changed in krita preferences KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); KisColorSelectorSettingsFactory* factory = dynamic_cast(preferenceSetRegistry->get("KisColorSelectorSettingsFactory")); Q_ASSERT(factory); connect(&(factory->repeater), SIGNAL(settingsUpdated()), this, SIGNAL(settingsChanged()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), this, SLOT(updateLayout()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), m_commonColorsWidget, SLOT(updateSettings()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), m_colorHistoryWidget, SLOT(updateSettings()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), m_colorSelectorContainer, SIGNAL(settingsChanged()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), this, SLOT(update()), Qt::UniqueConnection); emit settingsChanged(); 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); } void KisColorSelectorNgDockerWidget::unsetCanvas() { m_canvas = 0; m_commonColorsWidget->unsetCanvas(); m_colorHistoryWidget->unsetCanvas(); m_colorSelectorContainer->unsetCanvas(); } void KisColorSelectorNgDockerWidget::setCanvas(KisCanvas2 *canvas) { if (m_canvas) { m_canvas->disconnect(this); KActionCollection *ac = m_canvas->viewManager()->actionCollection(); ac->takeAction(ac->action("show_color_history")); ac->takeAction(ac->action("show_common_colors")); } m_canvas = canvas; m_commonColorsWidget->setCanvas(canvas); m_colorHistoryWidget->setCanvas(canvas); m_colorSelectorContainer->setCanvas(canvas); if (m_canvas && m_canvas->viewManager()) { if (m_canvas->viewManager()->nodeManager()) { connect(m_canvas->viewManager()->nodeManager(), SIGNAL(sigLayerActivated(KisLayerSP)), SLOT(reactOnLayerChange()), Qt::UniqueConnection); } KActionCollection* actionCollection = canvas->viewManager()->actionCollection(); actionCollection->addAction("show_color_history", m_colorHistoryAction); actionCollection->addAction("show_common_colors", m_commonColorsAction); } reactOnLayerChange(); } void KisColorSelectorNgDockerWidget::openSettings() { if (!m_canvas) return; KisColorSelectorSettingsDialog settings; if(settings.exec()==QDialog::Accepted) { emit settingsChanged(); } } void KisColorSelectorNgDockerWidget::updateLayout() { KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); //color patches bool m_lastColorsShow = cfg.readEntry("lastUsedColorsShow", true); KisColorPatches::Direction m_lastColorsDirection; if(cfg.readEntry("lastUsedColorsAlignment", false)) m_lastColorsDirection=KisColorPatches::Vertical; else m_lastColorsDirection=KisColorPatches::Horizontal; bool m_commonColorsShow = cfg.readEntry("commonColorsShow", true); KisColorPatches::Direction m_commonColorsDirection; if(cfg.readEntry("commonColorsAlignment", false)) m_commonColorsDirection=KisColorPatches::Vertical; else m_commonColorsDirection=KisColorPatches::Horizontal; m_verticalColorPatchesLayout->removeWidget(m_colorHistoryWidget); m_verticalColorPatchesLayout->removeWidget(m_commonColorsWidget); m_horizontalColorPatchesLayout->removeWidget(m_colorHistoryWidget); m_horizontalColorPatchesLayout->removeWidget(m_commonColorsWidget); if(m_lastColorsShow==false) m_colorHistoryWidget->hide(); else m_colorHistoryWidget->show(); if(m_commonColorsShow==false) { m_commonColorsWidget->hide(); } else { m_commonColorsWidget->show(); } if(m_lastColorsShow && m_lastColorsDirection==KisColorPatches::Vertical) { m_verticalColorPatchesLayout->addWidget(m_colorHistoryWidget); } if(m_commonColorsShow && m_commonColorsDirection==KisColorPatches::Vertical) { m_verticalColorPatchesLayout->addWidget(m_commonColorsWidget); } if(m_lastColorsShow && m_lastColorsDirection==KisColorPatches::Horizontal) { m_horizontalColorPatchesLayout->addWidget(m_colorHistoryWidget); } if(m_commonColorsShow && m_commonColorsDirection==KisColorPatches::Horizontal) { m_horizontalColorPatchesLayout->addWidget(m_commonColorsWidget); } updateGeometry(); } void KisColorSelectorNgDockerWidget::reactOnLayerChange() { /** * Trigger the update for the case if some legacy code needs it. * Now the node's color space is managed by the * KisDisplayColorConverter and KisColorSelectorBase objects, so * technically this call is not needed anymore. Please remove it * when you are totally sure this will not break something. */ emit settingsChanged(); } diff --git a/krita/ui/KisPart.cpp b/krita/ui/KisPart.cpp index 200acf109c..284c8e2caf 100644 --- a/krita/ui/KisPart.cpp +++ b/krita/ui/KisPart.cpp @@ -1,723 +1,664 @@ /* This file is part of the KDE project * Copyright (C) 1998-1999 Torben Weis * Copyright (C) 2000-2005 David Faure * Copyright (C) 2007-2008 Thorsten Zachmann * Copyright (C) 2010-2012 Boudewijn Rempt * Copyright (C) 2011 Inge Wallin * Copyright (C) 2015 Michael Abrahams * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisPart.h" #include "KoProgressProxy.h" #include #include #include #include #include #include #include #include #include "KisApplication.h" #include "KisDocument.h" #include "KisView.h" #include "KisViewManager.h" #include "KisOpenPane.h" #include "KisImportExportManager.h" -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisView.h" #include "KisDocument.h" #include "kis_config.h" #include "kis_clipboard.h" #include "kis_custom_image_widget.h" #include "kis_image_from_clipboard_widget.h" #include "kis_shape_controller.h" #include "kis_resource_server_provider.h" #include "kis_animation_cache_populator.h" #include "kis_idle_watcher.h" #include "kis_image.h" #include "KisImportExportManager.h" #include "KisDocumentEntry.h" #include "kis_color_manager.h" #include "kis_debug.h" #include "kis_action.h" #include "kis_action_registry.h" Q_GLOBAL_STATIC(KisPart, s_instance) class Q_DECL_HIDDEN KisPart::Private { public: Private(KisPart *_part) : part(_part) , idleWatcher(2500) , animationCachePopulator(_part) { } ~Private() { delete canvasItem; } KisPart *part; QList > views; QList > mainWindows; QList > documents; QString templatesResourcePath; QGraphicsItem *canvasItem{0}; KisOpenPane *startupWidget{0}; KActionCollection *actionCollection{0}; KisIdleWatcher idleWatcher; KisAnimationCachePopulator animationCachePopulator; void loadActions(); }; void KisPart::Private::loadActions() { actionCollection = new KActionCollection(part, "krita"); KisActionRegistry * actionRegistry = KisActionRegistry::instance(); QStringList actionNames = actionRegistry->allActions(); actionCollection->readSettings(); // XXX: consider relocating & managing this 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); } else { dbgAction << "duplicate action" << name << a << "from" << actionCollection; // delete a; } } - // 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; - // } - // } + }; KisPart* KisPart::instance() { return s_instance; } KisPart::KisPart() : d(new Private(this)) { setTemplatesResourcePath(QLatin1String("krita/templates/")); // Preload all the resources in the background Q_UNUSED(KoResourceServerProvider::instance()); Q_UNUSED(KisResourceServerProvider::instance()); Q_UNUSED(KisColorManager::instance()); connect(this, SIGNAL(documentOpened(QString)), this, SLOT(updateIdleWatcherConnections())); connect(this, SIGNAL(documentClosed(QString)), this, SLOT(updateIdleWatcherConnections())); connect(&d->idleWatcher, SIGNAL(startedIdleMode()), &d->animationCachePopulator, SLOT(slotRequestRegeneration())); d->animationCachePopulator.slotRequestRegeneration(); } KisPart::~KisPart() { while (!d->documents.isEmpty()) { delete d->documents.takeFirst(); } while (!d->views.isEmpty()) { delete d->views.takeFirst(); } while (!d->mainWindows.isEmpty()) { delete d->mainWindows.takeFirst(); } delete d; } void KisPart::updateIdleWatcherConnections() { QVector images; foreach (QPointer document, documents()) { images << document->image(); } d->idleWatcher.setTrackedImages(images); } void KisPart::addDocument(KisDocument *document) { //dbgUI << "Adding document to part list" << document; Q_ASSERT(document); if (!d->documents.contains(document)) { d->documents.append(document); emit documentOpened('/'+objectName()); } } QList > KisPart::documents() const { return d->documents; } KisDocument *KisPart::createDocument() const { KisDocument *doc = new KisDocument(); return doc; } int KisPart::documentCount() const { return d->documents.size(); } void KisPart::removeDocument(KisDocument *document) { d->documents.removeAll(document); emit documentClosed('/'+objectName()); document->deleteLater(); } KisMainWindow *KisPart::createMainWindow() { KisMainWindow *mw = new KisMainWindow(); dbgUI <<"mainWindow" << (void*)mw << "added to view" << this; d->mainWindows.append(mw); return mw; } KisView *KisPart::createView(KisDocument *document, KoCanvasResourceManager *resourceManager, KActionCollection *actionCollection, QWidget *parent) { // If creating the canvas fails, record this and disable OpenGL next time KisConfig cfg; KConfigGroup grp( KSharedConfig::openConfig(), "krita/crashprevention"); if (grp.readEntry("CreatingCanvas", false)) { cfg.setUseOpenGL(false); } if (cfg.canvasState() == "OPENGL_FAILED") { cfg.setUseOpenGL(false); } grp.writeEntry("CreatingCanvas", true); grp.sync(); QApplication::setOverrideCursor(Qt::WaitCursor); KisView *view = new KisView(document, resourceManager, actionCollection, parent); QApplication::restoreOverrideCursor(); // Record successful canvas creation grp.writeEntry("CreatingCanvas", false); grp.sync(); addView(view); return view; } void KisPart::addView(KisView *view) { if (!view) return; if (!d->views.contains(view)) { d->views.append(view); } connect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); emit sigViewAdded(view); } void KisPart::removeView(KisView *view) { if (!view) return; emit sigViewRemoved(view); QPointer doc = view->document(); d->views.removeAll(view); if (doc) { bool found = false; foreach(QPointer view, d->views) { if (view && view->document() == doc) { found = true; break; } } if (!found) { removeDocument(doc); } } } QList > KisPart::views() const { return d->views; } int KisPart::viewCount(KisDocument *doc) const { if (!doc) { return d->views.count(); } else { int count = 0; foreach(QPointer view, d->views) { if (view->document() == doc) { count++; } } return count; } } QGraphicsItem *KisPart::canvasItem(KisDocument *document, bool create) { if (create && !d->canvasItem) { d->canvasItem = createCanvasItem(document); } return d->canvasItem; } QGraphicsItem *KisPart::createCanvasItem(KisDocument *document) { if (!document) return 0; KisView *view = createView(document, 0, 0, 0); QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(); QWidget *canvasController = view->findChild(); proxy->setWidget(canvasController); return proxy; } void KisPart::removeMainWindow(KisMainWindow *mainWindow) { dbgUI <<"mainWindow" << (void*)mainWindow <<"removed from doc" << this; if (mainWindow) { d->mainWindows.removeAll(mainWindow); } } const QList > &KisPart::mainWindows() const { return d->mainWindows; } int KisPart::mainwindowCount() const { return d->mainWindows.count(); } KisMainWindow *KisPart::currentMainwindow() const { QWidget *widget = qApp->activeWindow(); KisMainWindow *mainWindow = qobject_cast(widget); while (!mainWindow && widget) { widget = widget->parentWidget(); mainWindow = qobject_cast(widget); } if (!mainWindow && mainWindows().size() > 0) { mainWindow = mainWindows().first(); } return mainWindow; } KisIdleWatcher* KisPart::idleWatcher() const { return &d->idleWatcher; } KisAnimationCachePopulator* KisPart::cachePopulator() const { return &d->animationCachePopulator; } void KisPart::openExistingFile(const QUrl &url) { Q_ASSERT(url.isLocalFile()); qApp->setOverrideCursor(Qt::BusyCursor); KisDocument *document = createDocument(); if (!document->openUrl(url)) { delete document; return; } if (!document->image()) { delete document; return; } document->setModified(false); addDocument(document); KisMainWindow *mw = 0; if (d->startupWidget) { mw = qobject_cast(d->startupWidget->parent()); } if (!mw) { mw = currentMainwindow(); } mw->addViewAndNotifyLoadingCompleted(document); if (d->startupWidget) { d->startupWidget->setParent(0); d->startupWidget->hide(); } qApp->restoreOverrideCursor(); } void KisPart::configureShortcuts() { if (!d->actionCollection) { d->loadActions(); } // In kdelibs4 a hack was used to hide the shortcut schemes widget in the // normal shortcut editor KShortcutsDialog from kdelibs, by setting the // bottom buttons oneself. This does not work anymore (as the buttons are // no longer exposed), so for now running with a plain copy of the sources // of KShortcutsDialog, where the schemes editor is disabled directly. // Not nice, but then soon custom Krita-specific shortcut handling is // 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. foreach(KisMainWindow *mainWindow, d->mainWindows) { KActionCollection *ac = mainWindow->actionCollection(); ac->readSettings(); // Loop through mainWindow->actionCollections() to modify tooltips // so that they list shortcuts at the end in parentheses foreach( QAction* action, ac->actions()) { // Remove any existing suffixes from the tooltips. // Note this regexp starts with a space, e.g. " (Ctrl-a)" QString strippedTooltip = action->toolTip().remove(QRegExp("\\s\\(.*\\)")); // Now update the tooltips with the new shortcut info. if(action->shortcut() == QKeySequence(0)) action->setToolTip(strippedTooltip); else action->setToolTip( strippedTooltip + " (" + action->shortcut().toString() + ")"); } } } void KisPart::openTemplate(const QUrl &url) { qApp->setOverrideCursor(Qt::BusyCursor); KisDocument *document = createDocument(); bool ok = document->loadNativeFormat(url.toLocalFile()); document->setModified(false); document->undoStack()->clear(); if (ok) { QMimeDatabase db; QString mimeType = db.mimeTypeForFile(url.path(), QMimeDatabase::MatchExtension).name(); // in case this is a open document template remove the -template from the end mimeType.remove( QRegExp( "-template$" ) ); document->setMimeTypeAfterLoading(mimeType); document->resetURL(); document->setEmpty(); } else { document->showLoadingErrorDialog(); document->initEmpty(); } addDocument(document); KisMainWindow *mw = qobject_cast(d->startupWidget->parent()); if (!mw) mw = currentMainwindow(); mw->addViewAndNotifyLoadingCompleted(document); d->startupWidget->setParent(0); d->startupWidget->hide(); qApp->restoreOverrideCursor(); } void KisPart::viewDestroyed() { KisView *view = qobject_cast(sender()); if (view) { removeView(view); } } void KisPart::addRecentURLToAllMainWindows(QUrl url) { // Add to recent actions list in our mainWindows foreach(KisMainWindow *mainWindow, d->mainWindows) { mainWindow->addRecentURL(url); } } void KisPart::showStartUpWidget(KisMainWindow *mainWindow, bool alwaysShow) { #ifndef NDEBUG if (d->templatesResourcePath.isEmpty()) dbgUI << "showStartUpWidget called, but setTemplatesResourcePath() never called. This will not show a lot"; #endif if (!alwaysShow) { KConfigGroup cfgGrp( KSharedConfig::openConfig(), "TemplateChooserDialog"); QString fullTemplateName = cfgGrp.readPathEntry("AlwaysUseTemplate", QString()); if (!fullTemplateName.isEmpty()) { QUrl url(fullTemplateName); QFileInfo fi(url.toLocalFile()); if (!fi.exists()) { const QString templatesResourcePath = this->templatesResourcePath(); QString desktopfile = KoResourcePaths::findResource("data", templatesResourcePath + "*/" + fullTemplateName); if (desktopfile.isEmpty()) { desktopfile = KoResourcePaths::findResource("data", templatesResourcePath + fullTemplateName); } if (desktopfile.isEmpty()) { fullTemplateName.clear(); } else { KDesktopFile f(desktopfile); fullTemplateName = QFileInfo(desktopfile).absolutePath() + '/' + f.readUrl(); } } if (!fullTemplateName.isEmpty()) { openTemplate(QUrl::fromLocalFile(fullTemplateName)); return; } } } if (d->startupWidget) { delete d->startupWidget; } const QStringList mimeFilter = KisImportExportManager::mimeFilter(KIS_MIME_TYPE, KisImportExportManager::Import, KisDocumentEntry::extraNativeMimeTypes()); d->startupWidget = new KisOpenPane(0, mimeFilter, d->templatesResourcePath); d->startupWidget->setWindowModality(Qt::WindowModal); QList widgetList = createCustomDocumentWidgets(d->startupWidget); foreach(const CustomDocumentWidgetItem & item, widgetList) { d->startupWidget->addCustomDocumentWidget(item.widget, item.title, item.icon); connect(item.widget, SIGNAL(documentSelected(KisDocument*)), this, SLOT(startCustomDocument(KisDocument*))); } connect(d->startupWidget, SIGNAL(openExistingFile(const QUrl&)), this, SLOT(openExistingFile(const QUrl&))); connect(d->startupWidget, SIGNAL(openTemplate(const QUrl&)), this, SLOT(openTemplate(const QUrl&))); d->startupWidget->setParent(mainWindow); d->startupWidget->setWindowFlags(Qt::Dialog); d->startupWidget->exec(); } QList KisPart::createCustomDocumentWidgets(QWidget * parent) { KisConfig cfg; int w = cfg.defImageWidth(); int h = cfg.defImageHeight(); const double resolution = cfg.defImageResolution(); const QString colorModel = cfg.defColorModel(); const QString colorDepth = cfg.defaultColorDepth(); const QString colorProfile = cfg.defColorProfile(); QList widgetList; { KisPart::CustomDocumentWidgetItem item; item.widget = new KisCustomImageWidget(parent, w, h, resolution, colorModel, colorDepth, colorProfile, i18n("Unnamed")); item.icon = "application-x-krita"; widgetList << item; } { QSize sz = KisClipboard::instance()->clipSize(); if (sz.isValid() && sz.width() != 0 && sz.height() != 0) { w = sz.width(); h = sz.height(); } KisPart::CustomDocumentWidgetItem item; item.widget = new KisImageFromClipboard(parent, w, h, resolution, colorModel, colorDepth, colorProfile, i18n("Unnamed")); item.title = i18n("Create from Clipboard"); item.icon = "klipper"; widgetList << item; } return widgetList; } void KisPart::setTemplatesResourcePath(const QString &templatesResourcePath) { Q_ASSERT(!templatesResourcePath.isEmpty()); Q_ASSERT(templatesResourcePath.endsWith(QLatin1Char('/'))); d->templatesResourcePath = templatesResourcePath; } QString KisPart::templatesResourcePath() const { return d->templatesResourcePath; } void KisPart::startCustomDocument(KisDocument* doc) { addDocument(doc); KisMainWindow *mw = qobject_cast(d->startupWidget->parent()); if (!mw) mw = currentMainwindow(); mw->addViewAndNotifyLoadingCompleted(doc); d->startupWidget->setParent(0); d->startupWidget->hide(); } KisInputManager* KisPart::currentInputManager() { return instance()->currentMainwindow()->viewManager()->inputManager(); } #include #include #include diff --git a/krita/ui/tool/kis_tool_polyline_base.cpp b/krita/ui/tool/kis_tool_polyline_base.cpp index e8f11c6488..ee4d6c01a0 100644 --- a/krita/ui/tool/kis_tool_polyline_base.cpp +++ b/krita/ui/tool/kis_tool_polyline_base.cpp @@ -1,268 +1,270 @@ /* This file is part of the KDE project * Copyright (C) 2009 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "kis_tool_polyline_base.h" #include "kis_canvas2.h" #include #include #include +#include "kis_action_registry.h" + #define SNAPPING_THRESHOLD 10 #define SNAPPING_HANDLE_RADIUS 8 #define PREVIEW_LINE_WIDTH 1 KisToolPolylineBase::KisToolPolylineBase(KoCanvasBase * canvas, KisToolPolylineBase::ToolType type, const QCursor & cursor) : KisToolShape(canvas, cursor), m_dragging(false), m_type(type), m_closeSnappingActivated(false) { KisCanvas2 * kiscanvas = dynamic_cast(this->canvas()); KActionCollection *collection = this->canvas()->canvasController()->actionCollection(); if (kiscanvas && kiscanvas->viewManager()) { QAction *undo_polygon_selection = new QAction("Undo Polygon Selection Points",this); undo_polygon_selection->setShortcut(QKeySequence(Qt::ShiftModifier + Qt::Key_Z)); collection->addAction("undo_polygon_selection", undo_polygon_selection); addAction("undo_polygon_selection", undo_polygon_selection); } } void KisToolPolylineBase::activate(KoToolBase::ToolActivation activation, const QSet &shapes) { KisToolShape::activate(activation, shapes); connect(actions().value("undo_polygon_selection"), SIGNAL(triggered()), SLOT(undoSelection()), Qt::UniqueConnection); } void KisToolPolylineBase::deactivate() { disconnect(actions().value("undo_polygon_selection"), 0, this, 0); cancelStroke(); KisToolShape::deactivate(); } void KisToolPolylineBase::requestStrokeEnd() { endStroke(); } void KisToolPolylineBase::requestStrokeCancellation() { cancelStroke(); } void KisToolPolylineBase::beginPrimaryAction(KoPointerEvent *event) { Q_UNUSED(event); if ((m_type == PAINT && (!nodeEditable() || nodePaintAbility() == NONE)) || (m_type == SELECT && !selectionEditable())) { event->ignore(); return; } setMode(KisTool::PAINT_MODE); if(m_dragging && m_closeSnappingActivated) { m_points.append(m_points.first()); endStroke(); } else { m_dragging = true; } } void KisToolPolylineBase::endPrimaryAction(KoPointerEvent *event) { CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); setMode(KisTool::HOVER_MODE); if(m_dragging) { m_dragStart = convertToPixelCoord(event); m_dragEnd = m_dragStart; m_points.append(m_dragStart); } } void KisToolPolylineBase::beginPrimaryDoubleClickAction(KoPointerEvent *event) { endStroke(); // this action will have no continuation event->ignore(); } void KisToolPolylineBase::beginAlternateAction(KoPointerEvent *event, AlternateAction action) { if (action != ChangeSize || !m_dragging) { KisToolPaint::beginAlternateAction(event, action); } if (m_closeSnappingActivated) { m_points.append(m_points.first()); } endStroke(); } void KisToolPolylineBase::mouseMoveEvent(KoPointerEvent *event) { if (m_dragging && !m_points.empty()) { // erase old lines on canvas QRectF updateRect = dragBoundingRect(); // get current mouse position m_dragEnd = convertToPixelCoord(event); // draw new lines on canvas updateRect |= dragBoundingRect(); updateCanvasViewRect(updateRect); QPointF basePoint = pixelToView(m_points.first()); m_closeSnappingActivated = m_points.size() > 1 && (basePoint - pixelToView(m_dragEnd)).manhattanLength() < SNAPPING_THRESHOLD; updateCanvasViewRect(QRectF(basePoint, 2 * QSize(SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH, SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH)).translated(-SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH,-SNAPPING_HANDLE_RADIUS + PREVIEW_LINE_WIDTH)); KisToolPaint::requestUpdateOutline(event->point, event); } else { KisToolPaint::mouseMoveEvent(event); } } void KisToolPolylineBase::undoSelection() { if(m_dragging) { //Update canvas for drag before undo QRectF updateRect = dragBoundingRect(); updateRect |= dragBoundingRect(); updateCanvasViewRect(updateRect); //Update canvas for last segment QRectF rect; if (m_points.size() > 2) { rect = pixelToView(QRectF(m_points.last(), m_points.at(m_points.size()-2)).normalized()); rect.adjust(-PREVIEW_LINE_WIDTH, -PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH); rect |= rect; updateCanvasViewRect(rect); } if (m_points.size() > 0) { m_points.pop_back(); } if (m_points.size() > 0) { m_dragStart = m_points.last(); } } } void KisToolPolylineBase::paint(QPainter& gc, const KoViewConverter &converter) { Q_UNUSED(converter); if (!canvas() || !currentImage()) return; QPointF start, end; QPointF startPos; QPointF endPos; QPainterPath path; if (m_dragging && !m_points.empty()) { startPos = pixelToView(m_dragStart); endPos = pixelToView(m_dragEnd); path.moveTo(startPos); path.lineTo(endPos); } for (vQPointF::iterator it = m_points.begin(); it != m_points.end(); ++it) { if (it == m_points.begin()) { start = (*it); } else { end = (*it); startPos = pixelToView(start); endPos = pixelToView(end); path.moveTo(startPos); path.lineTo(endPos); start = end; } } if (m_closeSnappingActivated) { QPointF basePoint = pixelToView(m_points.first()); path.addEllipse(basePoint, SNAPPING_HANDLE_RADIUS, SNAPPING_HANDLE_RADIUS); } paintToolOutline(&gc, path); KisToolPaint::paint(gc,converter); } void KisToolPolylineBase::updateArea() { updateCanvasPixelRect(image()->bounds()); } void KisToolPolylineBase::endStroke() { if (!m_dragging) return; m_dragging = false; if(m_points.count() > 1) { finishPolyline(m_points); } m_points.clear(); m_closeSnappingActivated = false; updateArea(); } void KisToolPolylineBase::cancelStroke() { if (!m_dragging) return; m_dragging = false; m_points.clear(); m_closeSnappingActivated = false; updateArea(); } QRectF KisToolPolylineBase::dragBoundingRect() { QRectF rect = pixelToView(QRectF(m_dragStart, m_dragEnd).normalized()); rect.adjust(-PREVIEW_LINE_WIDTH, -PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH, PREVIEW_LINE_WIDTH); return rect; } void KisToolPolylineBase::listenToModifiers(bool listen) { Q_UNUSED(listen) } bool KisToolPolylineBase::listeningToModifiers() { //Never grab modifier keys return false; } diff --git a/libs/widgetutils/kis_action_registry.cpp b/libs/widgetutils/kis_action_registry.cpp index bc724a76aa..fcdf2fd70a 100644 --- a/libs/widgetutils/kis_action_registry.cpp +++ b/libs/widgetutils/kis_action_registry.cpp @@ -1,172 +1,330 @@ /* * Copyright (c) 2015 Michael Abrahams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #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" namespace { struct actionInfoItem { QDomElement xmlData; QKeySequence defaultShortcut; QKeySequence customShortcut; }; QKeySequence getShortcutFromXml(QDomElement node) { return node.firstChildElement("shortcut").text(); }; actionInfoItem emptyActionInfo; // Used as default return value }; class Q_DECL_HIDDEN KisActionRegistry::Private { 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 * the .action XML file. The second and third are QKeySequences, the first * of which is the default shortcut, the last of which is any custom * shortcut. * * QHash is most efficient as long as the action name keys are kept relatively short. */ 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; }; Q_GLOBAL_STATIC(KisActionRegistry, s_instance); KisActionRegistry *KisActionRegistry::instance() { return s_instance; }; 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. QKeySequence KisActionRegistry::getPreferredShortcut(QString name) { QKeySequence customShortcut = getCustomShortcut(name); if (customShortcut.isEmpty()) { return getDefaultShortcut(name); } else { return getCustomShortcut(name); } }; QKeySequence KisActionRegistry::getDefaultShortcut(QString name) { return d->actionInfo(name).defaultShortcut; }; QKeySequence KisActionRegistry::getCustomShortcut(QString name) { return d->actionInfo(name).customShortcut; }; QStringList KisActionRegistry::allActions() { return d->actionInfoList.keys(); }; QDomElement KisActionRegistry::getActionXml(QString name) { 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"); auto searchType = KoResourcePaths::Recursive | KoResourcePaths::NoDuplicates; QStringList actionDefinitions = KoResourcePaths::findAllResources("kis_actions", "*.action", searchType); // Extract actions all XML .action files. foreach(const QString &actionDefinition, actionDefinitions) { QDomDocument doc; QFile f(actionDefinition); f.open(QFile::ReadOnly); doc.setContent(f.readAll()); QDomElement actions = doc.documentElement(); // Whole document QString collection = actions.attribute("name"); QDomElement actionXml = actions.firstChild().toElement(); // Single Action while (!actionXml.isNull()) { if (actionXml.tagName() == "Action") { // Read name from format QString name = actionXml.attribute("name"); // Very bad things if (name.isEmpty()) { errAction << "Unnamed action in definitions file " << actionDefinition; continue; } if (actionInfoList.contains(name)) { errAction << "Warning: Duplicated action name: " << name; } actionInfoItem info; info.xmlData = actionXml; info.defaultShortcut = getShortcutFromXml(actionXml); info.customShortcut = info.defaultShortcut; //TODO: Read from KisConfig dbgAction << "default shortcut for" << name << " - " << info.defaultShortcut; actionInfoList.insert(name,info); } actionXml = actionXml.nextSiblingElement(); } } }; diff --git a/libs/widgetutils/kis_action_registry.h b/libs/widgetutils/kis_action_registry.h index 9183e8b44e..6ebeb8c66b 100644 --- a/libs/widgetutils/kis_action_registry.h +++ b/libs/widgetutils/kis_action_registry.h @@ -1,90 +1,117 @@ /* * Copyright (c) 2015 Michael Abrahams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include +#include #include "kritawidgetutils_export.h" class KActionCollection; class QDomElement; /** * KisShortcutRegistry is intended to manage the global shortcut configuration * for Krita. It is intended to provide the user's choice of shortcuts * the .action files, the configuration files that were done with XMLGUI, and * the * * It is a global static. Grab an ::instance. */ class KRITAWIDGETUTILS_EXPORT KisActionRegistry : public QObject { Q_OBJECT public: static KisActionRegistry *instance(); /** * Get shortcut for an action */ QKeySequence getPreferredShortcut(QString name); /** * Get shortcut for an action */ QKeySequence getDefaultShortcut(QString name); /** * Get custom shortcut for an action */ QKeySequence getCustomShortcut(QString name); /** * @return DOM info for an action @a name. * * Allows somewhat flexible info structure for KisActions, QActions, * whatever else we decide on doing later. */ QDomElement getActionXml(QString name); + /** + * 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(); /** * Save settings. Not implemented yet. */ // void writeSettings(KActionCollection *ac); + /** + * Run shortcuts dialog. + */ + void configureShortcuts(KActionCollection *ac); + /** * Constructor. Please don't touch! */ KisActionRegistry(); private: class Private; Private * const d; };