Commit d2d8f2ed authored by Boudewijn Rempt's avatar Boudewijn Rempt

FEATURE: a touch docker

The touch docker is for people with 2:1 devices without real buttons.
It mimics the wacom tablet buttons/rocker switch, a bit. The top 6
buttons and the "rocker switch" buttons aren't configurable, the
other 8 buttons can be configured by adding a line to kritarc

touchdockermapping=action1,action2,action3,action4,action5,action6,action7,action8

Note that the default configuration is useful, but shows a bad lack
of icons.

To figure out: how to toggle modifiers, like shift, ctrl and alt,
so pressing buttons configured with those keys actually apply
the modifier keys to all events until toggled off.
parent f6383313
......@@ -38,6 +38,7 @@ set(kritasketch_kritaintegrationmodels_SRCS
models/ColorModelModel.cpp
models/ColorDepthModel.cpp
models/ColorProfileModel.cpp
models/IconImageProvider.cpp
)
......
......@@ -36,6 +36,7 @@
#include "PresetImageProvider.h"
#include "RecentImageImageProvider.h"
#include "RecentFileManager.h"
#include "IconImageProvider.h"
#include "KisMultiFeedRSSModel.h"
#include "FileSystemModel.h"
#include "CompositeOpModel.h"
......@@ -46,6 +47,7 @@
#include <TemplatesModel.h>
#include "Theme.h"
#include "Constants.h"
#include "Settings.h"
#include "SimpleTouchArea.h"
......@@ -132,6 +134,7 @@ void KritaSketchPlugin::initializeEngine(QQmlEngine* engine, const char* uri)
engine->addImageProvider(QLatin1String("presetthumb"), new PresetImageProvider);
engine->addImageProvider(QLatin1String("color"), new ColorImageProvider);
engine->addImageProvider(QLatin1String("recentimage"), new RecentImageImageProvider);
engine->addImageProvider(QLatin1String("icon"), new IconImageProvider);
RecentFileManager *recentFileManager = DocumentManager::instance()->recentFileManager();
engine->rootContext()->setContextProperty("RecentFileManager", recentFileManager);
......
/*
* Copyright (C) 2017 Boudewijn Rempt <boud@valdyas.org>
*
* 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 "IconImageProvider.h"
#include <QDebug>
#include "kis_icon_utils.h"
IconImageProvider::IconImageProvider()
: QQuickImageProvider(QQuickImageProvider::Image)
{
}
QImage IconImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
QIcon icon = KisIconUtils::loadIcon(id);
Q_ASSERT(!icon.isNull());
return icon.pixmap(requestedSize).toImage();
}
/*
* Copyright (C) 2017 Boudewijn Rempt <boud@valdyas.org>
*
* 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.
*/
#ifndef ICONIMAGEPROVIDER_H
#define ICONIMAGEPROVIDER_H
#include <QQuickImageProvider>
class IconImageProvider : public QQuickImageProvider
{
public:
explicit IconImageProvider();
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
};
#endif // ICONIMAGEPROVIDER_H
......@@ -41,7 +41,6 @@ PresetImageProvider::PresetImageProvider()
QImage PresetImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
Q_UNUSED(size);
Q_UNUSED(requestedSize);
QImage image(requestedSize, QImage::Format_ARGB32);
QList<KisPaintOpPresetSP> resources = d->rserver->resources();
int theID = id.toInt();
......
......@@ -117,6 +117,7 @@ public:
void loadActionFiles();
void loadCustomShortcuts(QString filename = QStringLiteral("kritashortcutsrc"));
// XXX: this adds a default item for the given name to the list of actioninfo objects!
ActionInfoItem &actionInfo(const QString &name) {
if (!actionInfoList.contains(name)) {
dbgAction << "Tried to look up info for unknown action" << name;
......@@ -136,6 +137,11 @@ KisActionRegistry *KisActionRegistry::instance()
return s_instance;
}
bool KisActionRegistry::hasAction(const QString &name) const
{
return d->actionInfoList.contains(name);
}
KisActionRegistry::KisActionRegistry()
: d(new KisActionRegistry::Private(this))
......
......@@ -61,6 +61,12 @@ class KRITAWIDGETUTILS_EXPORT KisActionRegistry : public QObject
public:
static KisActionRegistry *instance();
/**
* @return true if the given action exists
*/
bool hasAction(const QString &name) const;
/**
* @return value @p property for an action @p name.
*
......@@ -80,7 +86,7 @@ public:
*
* N.B. this action will not be saved in the registry.
*/
QAction * makeQAction(const QString &name, QObject *parent);
QAction *makeQAction(const QString &name, QObject *parent);
/**
* Fills the standard QAction properties of an action.
......
......@@ -22,12 +22,16 @@
#include <QQmlContext>
#include <QAction>
#include <QUrl>
#include <QAction>
#include <QKeyEvent>
#include <QApplication>g
#include <klocalizedstring.h>
#include <kactioncollection.h>
#include <ksharedconfig.h>
#include <kconfiggroup.h>
#include <kis_action_registry.h>
#include <KoDialog.h>
#include <KoResourcePaths.h>
#include <kis_icon.h>
......@@ -35,13 +39,13 @@
#include <KisViewManager.h>
#include <kis_canvas2.h>
#include <KisMainWindow.h>
#include <KisViewManager.h>
#include <kis_config.h>
#include <KisPart.h>
#include <KisDocument.h>
#include <KisMimeDatabase.h>
#include <kis_action_manager.h>
#include <kis_action.h>
#include <kis_config.h>
#include <Theme.h>
#include <Settings.h>
......@@ -57,18 +61,45 @@ public:
TouchDockerDock *q;
bool allowClose {true};
KisViewManager *viewManager {0};
KisSketchView *sketchView {0};
QString currentSketchPage;
KoDialog *openDialog {0};
KoDialog *saveAsDialog {0};
QMap<QString, QString> buttonMapping;
bool shiftOn {false};
bool ctrlOn {false};
bool altOn {false};
};
TouchDockerDock::TouchDockerDock( )
TouchDockerDock::TouchDockerDock()
: QDockWidget(i18n("Touch Docker"))
, d(new Private())
{
QStringList defaultMapping = QStringList() << "decrease_opacity"
<< "increase_opacity"
<< "make_brush_color_lighter"
<< "make_brush_color_darker"
<< "decrease_brush_size"
<< "increase_brush_size"
<< "previous_preset"
<< "clear";
QStringList mapping = KisConfig().readEntry<QString>("touchdockermapping", defaultMapping.join(',')).split(',');
for (int i = 0; i < 8; ++i) {
if (i < mapping.size()) {
d->buttonMapping[QString("button%1").arg(i + 1)] = mapping[i];
}
else if (i < defaultMapping.size()) {
d->buttonMapping[QString("button%1").arg(i + 1)] = defaultMapping[i];
}
}
qDebug() << d->buttonMapping;
m_quickWidget = new QQuickWidget(this);
setWidget(m_quickWidget);
setEnabled(true);
......@@ -87,8 +118,10 @@ TouchDockerDock::TouchDockerDock( )
settings->setTheme(theme);
}
m_quickWidget->setSource(QUrl("qrc:/touchstrip.qml"));
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_quickWidget->setSource(QUrl("qrc:/touchstrip.qml"));
}
......@@ -141,7 +174,7 @@ void TouchDockerDock::slotButtonPressed(const QString &id)
else if (id == "fileSaveAsButton" && m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->document()) {
showFileSaveAsDialog();
}
else if (m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->actionManager()) {
else {
QAction *a = action(id);
if (a) {
if (a->isCheckable()) {
......@@ -151,15 +184,32 @@ void TouchDockerDock::slotButtonPressed(const QString &id)
a->trigger();
}
}
}
else if (id == "Key_Shift") {
// set shift state for the next pointer event, somehow
}
else if (id == "Key_Ctrl") {
// set ctrl state for the next pointer event, somehow
}
else if (id == "Key_Alt") {
// set alt state for the next pointer event, somehow
else if (id == "shift") {
// set shift state for the next pointer event, somehow
QKeyEvent event(d->shiftOn ? QEvent::KeyRelease : QEvent::KeyPress,
0,
Qt::ShiftModifier);
QApplication::sendEvent(KisPart::instance()->currentMainwindow(), &event);
d->shiftOn == !d->shiftOn;
}
else if (id == "ctrl") {
// set ctrl state for the next pointer event, somehow
QKeyEvent event(d->ctrlOn ? QEvent::KeyRelease : QEvent::KeyPress,
0,
Qt::ControlModifier);
QApplication::sendEvent(KisPart::instance()->currentMainwindow(), &event);
d->ctrlOn == !d->ctrlOn;
}
else if (id == "alt") {
// set alt state for the next pointer event, somehow
QKeyEvent event(d->altOn ? QEvent::KeyRelease : QEvent::KeyPress,
0,
Qt::AltModifier);
QApplication::sendEvent(KisPart::instance()->currentMainwindow(), &event);
d->altOn == !d->altOn;
}
}
}
......@@ -194,9 +244,47 @@ void TouchDockerDock::hideFileSaveAsDialog()
}
}
QAction *TouchDockerDock::action(const QString id) const
QString TouchDockerDock::imageForButton(QString id)
{
qDebug() << id << d->buttonMapping.contains(id);
if (d->buttonMapping.contains(id)) {
id = d->buttonMapping[id];
}
if (KisActionRegistry::instance()->hasAction(id)) {
QString a = KisActionRegistry::instance()->getActionProperty(id, "icon");
if (!a.isEmpty()) {
return "image://icon/" + a;
}
}
return QString();
}
QString TouchDockerDock::textForButton(QString id)
{
return m_canvas->viewManager()->actionManager()->actionByName(id);
if (d->buttonMapping.contains(id)) {
id = d->buttonMapping[id];
}
if (KisActionRegistry::instance()->hasAction(id)) {
QString a = KisActionRegistry::instance()->getActionProperty(id, "iconText");
if (a.isEmpty()) {
a = KisActionRegistry::instance()->getActionProperty(id, "text");
}
return a;
}
return id;
}
QAction *TouchDockerDock::action(QString id) const
{
if (m_canvas && m_canvas->viewManager()) {
if (d->buttonMapping.contains(id)) {
id = d->buttonMapping[id];
}
return m_canvas->viewManager()->actionManager()->actionByName(id);
}
return 0;
}
void TouchDockerDock::showFileOpenDialog()
......
......@@ -19,6 +19,7 @@
#define TOUCHDOCKER_DOCK_H
#include <QDockWidget>
#include <QIcon>
#include <KoCanvasObserverBase.h>
class KoDialog;
......@@ -49,7 +50,6 @@ public:
virtual void closeEvent(QCloseEvent *event);
Q_SIGNALS:
void closeRequested();
void currentSketchPageChanged();
......@@ -64,8 +64,9 @@ public Q_SLOTS:
void hideFileOpenDialog();
void hideFileSaveAsDialog();
QAction *action(const QString id) const;
QString imageForButton(QString id);
QString textForButton(QString id);
QAction *action(QString id) const;
private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment