Commit 709ac34d authored by Wolthera van Hövell's avatar Wolthera van Hövell 🐛

Initial prototype for pressure callibration helper.

This adds a little widget to the tablet settings to help users
to callibrate their tablet pressure.

This still needs UI work, and am contemplating to make it more
time based.
parent 3540f1ae
......@@ -263,6 +263,7 @@ set(kritaui_LIB_SRCS
widgets/kis_elided_label.cpp
widgets/kis_stopgradient_slider_widget.cpp
widgets/kis_preset_live_preview_view.cpp
widgets/kis_pressure_callibration_helper.cpp
widgets/KisScreenColorPicker.cpp
widgets/KoDualColorButton.cpp
widgets/KoStrokeConfigWidget.cpp
......
......@@ -767,6 +767,9 @@ TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget
m_page->chkUseRightMiddleClickWorkaround->setChecked(
cfg.useRightMiddleTabletButtonWorkaround());
//
connect(m_page->pressure_callibration, SIGNAL(callibrationDone()), this, SLOT(slotSetPressureCurve()));
#if defined Q_OS_WIN && (!defined USE_QT_TABLET_WINDOWS || defined QT_HAS_WINTAB_SWITCH)
#ifdef USE_QT_TABLET_WINDOWS
// ask Qt if WinInk is actually available
......@@ -815,6 +818,12 @@ void TabletSettingsTab::slotResolutionSettings()
#endif
}
void TabletSettingsTab::slotSetPressureCurve()
{
KisCubicCurve curve(m_page->pressure_callibration->callibrationInfo());
m_page->pressureCurve->setCurve(curve);
}
//---------------------------------------------------------------------------------------------------
#include "kis_acyclic_signal_connector.h"
......
......@@ -198,6 +198,7 @@ public:
private Q_SLOTS:
void slotTabletTest();
void slotResolutionSettings();
void slotSetPressureCurve();
public:
void setDefault();
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>569</width>
<height>461</height>
<width>778</width>
<height>554</height>
</rect>
</property>
<property name="sizePolicy">
......@@ -33,6 +33,63 @@
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="chkUseRightMiddleClickWorkaround">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Some tablet devices don't pass barrel-button clicks via tablet API. If you have such a device, you can try activate this workaround. Krita will try to read right- and middle-button clicks from the mouse events stream. It may or may not work on your device (depends on the tablet driver implementation).&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;After changing this option Krita should be restarted.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use mouse events for right- and middle-clicks (workaround for convertible devices, needs restart)</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="grpTabletApi">
<property name="title">
<string>Tablet Input API (changing this requires restarting Krita)</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="radioWintab">
<property name="text">
<string>WinTab</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnResolutionSettings">
<property name="text">
<string>Advanced...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="radioWin8PointerInput">
<property name="text">
<string>Windows 8+ Pointer Input (Windows Ink)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
......@@ -158,13 +215,6 @@
</item>
</layout>
</item>
<item row="4" column="0" colspan="2">
<widget class="QPushButton" name="btnTabletTest">
<property name="text">
<string>Open Tablet Tester...</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
......@@ -172,60 +222,26 @@
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="grpTabletApi">
<property name="title">
<string>Tablet Input API (changing this requires restarting Krita)</string>
<item row="4" column="0" colspan="2">
<widget class="QPushButton" name="btnTabletTest">
<property name="text">
<string>Open Tablet Tester...</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="radioWintab">
<property name="text">
<string>WinTab</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnResolutionSettings">
<property name="text">
<string>Advanced...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="radioWin8PointerInput">
<property name="text">
<string>Windows 8+ Pointer Input (Windows Ink)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="chkUseRightMiddleClickWorkaround">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Some tablet devices don't pass barrel-button clicks via tablet API. If you have such a device, you can try activate this workaround. Krita will try to read right- and middle-button clicks from the mouse events stream. It may or may not work on your device (depends on the tablet driver implementation).&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;After changing this option Krita should be restarted.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<item row="6" column="0">
<widget class="KisPressureCallibrationHelper" name="pressure_callibration" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use mouse events for right- and middle-clicks (workaround for convertible devices, needs restart)</string>
<property name="minimumSize">
<size>
<width>0</width>
<height>256</height>
</size>
</property>
</widget>
</item>
......@@ -238,6 +254,12 @@
<header>widgets/kis_curve_widget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>KisPressureCallibrationHelper</class>
<extends>QWidget</extends>
<header>widgets/kis_pressure_callibration_helper.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
......
/*
* Copyright (c) 2019 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
*
* 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 2 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 "kis_pressure_callibration_helper.h"
#include <QPainter>
#include <QPaintEvent>
#include <QApplication>
KisPressureCallibrationHelper::KisPressureCallibrationHelper(QWidget *parent) :
QWidget(parent),
m_highestValue(0.0),
m_lowestValue(1.0),
m_progress(WAITING)
{
setMinimumHeight(256);
}
KisPressureCallibrationHelper::~KisPressureCallibrationHelper()
{
}
QList<QPointF> KisPressureCallibrationHelper::callibrationInfo()
{
if (!m_callibrationInfo.isEmpty()) {
return m_callibrationInfo;
}
QList<QPointF> dummy;
dummy.append(QPointF(0.0, 0.0));
dummy.append(QPointF(0.5, 0.5));
dummy.append(QPointF(1.0, 1.0));
return dummy;
}
void KisPressureCallibrationHelper::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e);
const int w = width();
const int h = height();
QPainter p(this);
p.fillRect(0, 0, w, h, QApplication::palette().background());
p.setBrush(QApplication::palette().foreground());
QString text = QString();
switch (m_progress) {
case WAITING:
text = "Please click to start callibrating tablet pressure.";
break;
case LIGHT_STROKE:
text = "Press as lightly as you can.";
break;
case MEDIUM_STROKE:
text = "Draw a medium stroke.";
break;
case HEAVY_STROKE:
text = "Press as hard as you hard.";
break;
case DONE:
text = "Done! Click me to start again.";
}
int center = (w/2) - (this->fontMetrics().width(text)/2);
QPoint o = QPoint(center, h/2);
p.drawText(o, text);
p.setBrush(Qt::transparent);
p.setPen(QPen(QApplication::palette().foreground(), 2));
p.drawPolyline(m_currentPath);
p.drawRect(0, 0, w, h);
}
void KisPressureCallibrationHelper::tabletEvent(QTabletEvent *e)
{
if(e->type() == QEvent::TabletRelease) {
if (m_progress == LIGHT_STROKE) {
m_callibrationInfo.append(QPointF(m_lowestValue, 0.0));
} else if (m_progress == MEDIUM_STROKE) {
m_callibrationInfo.append(QPointF((m_lowestValue+m_highestValue)/2, 0.5));
} else if (m_progress == HEAVY_STROKE) {
m_callibrationInfo.append(QPointF(m_highestValue, 1.0));
} else {
m_callibrationInfo.clear();
}
m_highestValue = 0.0;
m_lowestValue = 1.0;
nextSection();
return;
}
if(e->type() == QEvent::TabletPress || e->type() == QEvent::TabletMove) {
if (e->pressure() > m_highestValue) {
m_highestValue = e->pressure();
}
if (e->pressure() < m_lowestValue) {
m_lowestValue = e->pressure();
}
m_currentPath.append(e->pos());
repaint();
}
}
void KisPressureCallibrationHelper::nextSection()
{
m_currentPath.clear();
switch (m_progress) {
case WAITING:
m_progress = LIGHT_STROKE;
break;
case LIGHT_STROKE:
m_progress = MEDIUM_STROKE;
break;
case MEDIUM_STROKE:
m_progress = HEAVY_STROKE;
break;
case HEAVY_STROKE:
m_progress = DONE;
emit(callibrationDone());
break;
case DONE:
m_progress = LIGHT_STROKE;
break;
}
repaint();
}
/*
* Copyright (c) 2019 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
*
* 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 2 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.
*/
#ifndef KIS_PRESSURE_CALLIBRATION_HELPER_H
#define KIS_PRESSURE_CALLIBRATION_HELPER_H
#include <QWidget>
#include <kritaui_export.h>
#include <QTabletEvent>
#include <QPolygon>
/**
* @brief The KisPressureCallibrationHelper class
* This class helps users configure the tablet pressure.
*/
class KRITAUI_EXPORT KisPressureCallibrationHelper : public QWidget
{
Q_OBJECT
public:
explicit KisPressureCallibrationHelper(QWidget *parent = nullptr);
~KisPressureCallibrationHelper() override;
/**
* @brief callibrationInfo
* @return QVector<float> with values for lowest pressure, middle pressure and highest presure.
*/
QList<QPointF> callibrationInfo();
enum progressState {
WAITING = 0,
MEDIUM_STROKE,
HEAVY_STROKE,
LIGHT_STROKE,
DONE
};
Q_SIGNALS:
void callibrationDone();
protected:
void paintEvent(QPaintEvent *e) override;
void tabletEvent(QTabletEvent *e) override;
private:
void nextSection();
QList<QPointF> m_callibrationInfo;
qreal m_highestValue;
qreal m_lowestValue;
progressState m_progress;
QPolygon m_currentPath;
};
#endif /* KIS_PRESSURE_CALLIBRATION_HELPER_H */
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