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;
};