diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,8 +30,6 @@ kactionconflictdetector.cpp kbugreport.cpp kedittoolbar.cpp - kgesture.cpp - kgesturemap.cpp khelpmenu.cpp kkeysequencewidget.cpp klicensedialog_p.cpp @@ -143,13 +141,6 @@ install(TARGETS KF5XmlGui EXPORT KF5XmlGuiTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) -install(FILES - kgesture_p.h - kgesturemap_p.h - ${CMAKE_CURRENT_BINARY_DIR}/kxmlgui_export.h - ${KXmlGui_HEADERS} - DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KXmlGui COMPONENT Devel -) # install this file to be compatible, it is bundled in the resource file, too install( FILES ui_standards.rc DESTINATION ${KDE_INSTALL_CONFDIR}/ui ) diff --git a/src/kgesture.cpp b/src/kgesture.cpp deleted file mode 100644 --- a/src/kgesture.cpp +++ /dev/null @@ -1,584 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2006,2007 Andreas Hartmetz (ahartmetz@gmail.com) - - 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 "kgesture_p.h" -#include -#include -#include - -inline float metric(float dx, float dy) -{ - //square root of that or not? - not square root has possible advantages - return (dx * dx + dy * dy); -} - -class KShapeGesturePrivate -{ -public: - KShapeGesturePrivate() - { - } - KShapeGesturePrivate(const KShapeGesturePrivate &other) - : m_shape(other.m_shape), - m_lengthTo(other.m_lengthTo), - m_curveLength(other.m_curveLength) - { - } - QPolygon m_shape; - QVector m_lengthTo; - float m_curveLength; - QString m_friendlyName; -}; - -KShapeGesture::KShapeGesture() - : d(new KShapeGesturePrivate) -{ -} - -KShapeGesture::KShapeGesture(const QPolygon &shape) - : d(new KShapeGesturePrivate) -{ - setShape(shape); -} - -KShapeGesture::KShapeGesture(const QString &description) - : d(new KShapeGesturePrivate) -{ - QStringList sl = description.split(QLatin1Char(',')); - d->m_friendlyName = sl.takeFirst(); - - bool ok = true; - QPolygon poly; - int x, y; - QStringList::const_iterator it = sl.constBegin(); - while (it != sl.constEnd()) { - x = (*it).toInt(&ok); - ++it; - if (!ok || it == sl.constEnd()) { - break; - } - y = (*it).toInt(&ok); - if (!ok) { - break; - } - ++it; - poly.append(QPoint(x, y)); - } - if (!ok) { - d->m_friendlyName.clear(); - return; - } - - setShape(poly); -} - -KShapeGesture::KShapeGesture(const KShapeGesture &other) - : d(new KShapeGesturePrivate(*(other.d))) -{ -} - -KShapeGesture::~KShapeGesture() -{ - delete d; -} - -void KShapeGesture::setShape(const QPolygon &shape) -{ - //Scale and translate into a 100x100 square with its - //upper left corner at origin. - d->m_shape = shape; - QRect bounding = shape.boundingRect(); - //TODO: don't change aspect ratio "too much" to avoid problems with straight lines - //TODO: catch all bad input, like null height/width - - //compensate for QRect weirdness - bounding.setWidth(bounding.width() - 1); - bounding.setHeight(bounding.height() - 1); - - float xScale = bounding.width() ? 100.0 / bounding.width() : 1.0; - float yScale = bounding.height() ? 100.0 / bounding.height() : 1.0; - d->m_shape.translate(-bounding.left(), -bounding.top()); - for (QPoint &shape : d->m_shape) { - shape.setX((int)(xScale * (float)shape.x())); - shape.setY((int)(yScale * (float)shape.y())); - } - - //calculate accumulated lengths of lines making up the polygon - Q_ASSERT(d->m_shape.size() > 1); - d->m_curveLength = 0.0; - d->m_lengthTo.clear(); - d->m_lengthTo.reserve(d->m_shape.size()); - d->m_lengthTo.append(d->m_curveLength); - - int prevX = d->m_shape[0].x(); - int prevY = d->m_shape[0].y(); - for (int i = 1; i < d->m_shape.size(); i++) { - int curX = d->m_shape[i].x(); - int curY = d->m_shape[i].y(); - d->m_curveLength += metric(curX - prevX, curY - prevY); - d->m_lengthTo.append(d->m_curveLength); - prevX = curX; - prevY = curY; - } -} - -void KShapeGesture::setShapeName(const QString &friendlyName) -{ - d->m_friendlyName = friendlyName; -} - -QString KShapeGesture::shapeName() const -{ - return d->m_friendlyName; -} - -bool KShapeGesture::isValid() const -{ - return !d->m_shape.isEmpty(); -} - -QString KShapeGesture::toString() const -{ - if (!isValid()) { - return QString(); - } - - //TODO: what if the name contains a "," or ";"? Limit the name to letters? - QString ret = d->m_friendlyName; - - for (const QPoint shape : qAsConst(d->m_shape)) { - ret += QLatin1Char(',') + QString::number(shape.x()) + - QLatin1Char(',') + QString::number(shape.y()); - } - - return ret; -} - -QByteArray KShapeGesture::toSvg(const QString &attributes) const -{ - if (!isValid()) { - return QByteArray(); - //TODO: KDE standard debug output - } - const char *prolog = "" - "" - "m_shape[0].x()).toUtf8()); - ret.append(","); - ret.append(QString::number(d->m_shape[0].y()).toUtf8()); - - for (int i = 1; i < d->m_shape.size(); i++) { - ret.append("L"); - ret.append(QString::number(d->m_shape[i].x()).toUtf8()); - ret.append(","); - ret.append(QString::number(d->m_shape[i].y()).toUtf8()); - } - - ret.append(epilog1); - ret.append(attributes.toUtf8()); - ret.append(epilog2); - return ret; -} - -/* - algorithm: iterate in order over 30 points on our shape and measure the - minimum distance to any point on the other shape. never go backwards on - the other shape to also check direction of movement. - This algorithm is best applied like a->distance(b) + b->distance(a). - fabs(a->distance(b) - b->distance(a)) might turn out to be very interesting, - too. in fact, i think it's the most interesting value. - */ -float KShapeGesture::distance(const KShapeGesture &other, float abortThreshold) const -{ - Q_UNUSED(abortThreshold); //for optimizations, later - const QPolygon &o_shape = other.d->m_shape; - const QVector &o_lengthTo = other.d->m_lengthTo; - float x = 0; - float y = 0; - float mx = 0; - float my = 0; - float position = 0; - float ox = 0; - float oy = 0; - float oposition = 0; - float omx = 0; - float omy = 0; - float oxB = 0; - float oyB = 0; - float opositionB = 0; - float omxB = 0; - float omyB = 0; - float dist = 0; - float distB = 0; - float desiredPosition = 0; - float strokeLength = 0; - float retval = 0.0; - int pointIndex = 0, opointIndex = 0, opointIndexB = 0; - - //set up starting point on our shape - x = d->m_shape[0].x(); - y = d->m_shape[0].y(); - strokeLength = d->m_lengthTo[1]; - mx = (d->m_shape[1].x() - x) / strokeLength; - my = (d->m_shape[1].y() - y) / strokeLength; - position = 0.0; - - //set up lower bound of search interval on other shape - ox = o_shape[0].x(); - oy = o_shape[0].y(); - strokeLength = o_lengthTo[1]; - omx = (o_shape[1].x() - ox) / strokeLength; - omy = (o_shape[1].y() - oy) / strokeLength; - oposition = 0.0; - dist = metric(ox - x, oy - y); - - for (int i = 0; i <= 30; i++) { - //go to comparison point on our own polygon - //30.0001 to prevent getting out-of-bounds pointIndex - desiredPosition = d->m_curveLength / 30.0001 * (float)i; - if (desiredPosition > d->m_lengthTo[pointIndex + 1]) { - - while (desiredPosition > d->m_lengthTo[pointIndex + 1]) { - pointIndex++; - } - - x = d->m_shape[pointIndex].x(); - y = d->m_shape[pointIndex].y(); - position = d->m_lengthTo[pointIndex]; - strokeLength = d->m_lengthTo[pointIndex + 1] - position; - mx = (d->m_shape[pointIndex + 1].x() - x) / strokeLength; - my = (d->m_shape[pointIndex + 1].y() - y) / strokeLength; - } - x += mx * (desiredPosition - position); - y += my * (desiredPosition - position); - position = desiredPosition; - - //set up upper bound of search interval on other shape - desiredPosition = qMin(oposition + other.d->m_curveLength / 15.00005, - other.d->m_curveLength - 0.0001); - if (i == 0 || desiredPosition > o_lengthTo[opointIndexB + 1]) { - - while (desiredPosition > o_lengthTo[opointIndexB + 1]) { - opointIndexB++; - } - - oxB = o_shape[opointIndexB].x(); - oyB = o_shape[opointIndexB].y(); - opositionB = o_lengthTo[opointIndexB]; - strokeLength = o_lengthTo[opointIndexB + 1] - opositionB; - omxB = (o_shape[opointIndexB + 1].x() - oxB) / strokeLength; - omyB = (o_shape[opointIndexB + 1].y() - oyB) / strokeLength; - } - oxB += omxB * (desiredPosition - opositionB); - oyB += omyB * (desiredPosition - opositionB); - opositionB = desiredPosition; - distB = metric(oxB - x, oyB - y); - - //binary search for nearest point on other shape - for (int j = 0; j < 6; j++) { - desiredPosition = (oposition + opositionB) * 0.5; - if (dist < distB) { - //retract upper bound to desiredPosition - //copy state of lower bound to upper bound, advance it from there - oxB = ox; oyB = oy; - omxB = omx; omyB = omy; - opointIndexB = opointIndex; opositionB = oposition; - - if (desiredPosition > o_lengthTo[opointIndexB + 1]) { - - while (desiredPosition > o_lengthTo[opointIndexB + 1]) { - opointIndexB++; - } - - oxB = o_shape[opointIndexB].x(); - oyB = o_shape[opointIndexB].y(); - opositionB = o_lengthTo[opointIndexB]; - strokeLength = o_lengthTo[opointIndexB + 1] - opositionB; - omxB = (o_shape[opointIndexB + 1].x() - oxB) / strokeLength; - omyB = (o_shape[opointIndexB + 1].y() - oyB) / strokeLength; - } - oxB += omxB * (desiredPosition - opositionB); - oyB += omyB * (desiredPosition - opositionB); - opositionB = desiredPosition; - distB = metric(oxB - x, oyB - y); - } else { - //advance lower bound to desiredPosition - if (desiredPosition > o_lengthTo[opointIndex + 1]) { - - while (desiredPosition > o_lengthTo[opointIndex + 1]) { - opointIndex++; - } - - ox = o_shape[opointIndex].x(); - oy = o_shape[opointIndex].y(); - oposition = o_lengthTo[opointIndex]; - strokeLength = o_lengthTo[opointIndex + 1] - oposition; - omx = (o_shape[opointIndex + 1].x() - ox) / strokeLength; - omy = (o_shape[opointIndex + 1].y() - oy) / strokeLength; - } - ox += omx * (desiredPosition - oposition); - oy += omy * (desiredPosition - oposition); - oposition = desiredPosition; - dist = metric(ox - x, oy - y); - } - } - retval += qMin(dist, distB); - } - //scale value to make it roughly invariant against step width - return retval / 30.0; -} - -KShapeGesture &KShapeGesture::operator=(const KShapeGesture &other) -{ - d->m_lengthTo = other.d->m_lengthTo; - d->m_shape = other.d->m_shape; - d->m_curveLength = other.d->m_curveLength; - return *this; -} - -bool KShapeGesture::operator==(const KShapeGesture &other) const -{ - //a really fast and workable shortcut - if (fabs(d->m_curveLength - other.d->m_curveLength) > 0.1) { - return false; - } - return d->m_shape == other.d->m_shape; -} - -bool KShapeGesture::operator!=(const KShapeGesture &other) const -{ - return !operator==(other); -} - -uint KShapeGesture::hashable() const -{ - uint hash = 0; - - for (const QPoint point : qAsConst(d->m_shape)) { - hash += qHash(point.x()) + qHash(point.y()); - } - - return hash; -} - -/******************************************************** - * KRockerGesture * - *******************************************************/ - -class KRockerGesturePrivate -{ -public: - KRockerGesturePrivate() - : m_hold(Qt::NoButton), - m_thenPush(Qt::NoButton) - { - } - KRockerGesturePrivate(const KRockerGesturePrivate &other) - : m_hold(other.m_hold), - m_thenPush(other.m_thenPush) - { - } - Qt::MouseButton m_hold; - Qt::MouseButton m_thenPush; -}; - -KRockerGesture::KRockerGesture() - : d(new KRockerGesturePrivate) -{ -} - -KRockerGesture::KRockerGesture(Qt::MouseButton hold, Qt::MouseButton thenPush) - : d(new KRockerGesturePrivate) -{ - setButtons(hold, thenPush); -} - -KRockerGesture::KRockerGesture(const QString &description) - : d(new KRockerGesturePrivate) -{ - if (description.length() != 2) { - return; - } - - Qt::MouseButton hold, thenPush; - Qt::MouseButton *current = &hold; - for (int i = 0; i < 2; i++) { - switch (description[i].toLatin1()) { - case 'L': - *current = Qt::LeftButton; - break; - case 'R': - *current = Qt::RightButton; - break; - case 'M': - *current = Qt::MidButton; - break; - case '1': - *current = Qt::XButton1; - break; - case '2': - *current = Qt::XButton2; - break; - default: - return; - } - current = &thenPush; - } - d->m_hold = hold; - d->m_thenPush = thenPush; -} - -KRockerGesture::KRockerGesture(const KRockerGesture &other) - : d(new KRockerGesturePrivate(*(other.d))) -{ -} - -KRockerGesture::~KRockerGesture() -{ - delete d; -} - -void KRockerGesture::setButtons(Qt::MouseButton hold, Qt::MouseButton thenPush) -{ - if (hold == thenPush) { - d->m_hold = Qt::NoButton; - d->m_thenPush = Qt::NoButton; - return; - } - - int button = hold; - for (int i = 0; i < 2; i++) { - switch (button) { - case Qt::LeftButton: - case Qt::RightButton: - case Qt::MidButton: - case Qt::XButton1: - case Qt::XButton2: - break; - default: - d->m_hold = Qt::NoButton; - d->m_thenPush = Qt::NoButton; - return; - } - button = thenPush; - } - - d->m_hold = hold; - d->m_thenPush = thenPush; -} - -void KRockerGesture::getButtons(Qt::MouseButton *hold, Qt::MouseButton *thenPush) const -{ - *hold = d->m_hold; - *thenPush = d->m_thenPush; -} - -QString KRockerGesture::mouseButtonName(Qt::MouseButton button) -{ - switch (button) { - case Qt::LeftButton: - return i18nc("left mouse button", "left button"); - case Qt::MidButton: - return i18nc("middle mouse button", "middle button"); - case Qt::RightButton: - return i18nc("right mouse button", "right button"); - default: - return i18nc("a nonexistent value of mouse button", "invalid button"); - } -} - -QString KRockerGesture::rockerName() const -{ - if (!isValid()) { - return QString(); - } - //return i18nc("an invalid mouse gesture of type \"hold down one button, then press another button\"", - // "invalid rocker gesture"); - else - return i18nc("a kind of mouse gesture: hold down one mouse button, then press another button", - "Hold %1, then push %2", mouseButtonName(d->m_hold), mouseButtonName(d->m_thenPush)); -} - -bool KRockerGesture::isValid() const -{ - return (d->m_hold != Qt::NoButton); -} - -QString KRockerGesture::toString() const -{ - if (!isValid()) { - return QString(); - } - QString ret; - int button = d->m_hold; - char desc; - for (int i = 0; i < 2; i++) { - switch (button) { - case Qt::LeftButton: - desc = 'L'; - break; - case Qt::RightButton: - desc = 'R'; - break; - case Qt::MidButton: - desc = 'M'; - break; - case Qt::XButton1: - desc = '1'; - break; - case Qt::XButton2: - desc = '2'; - break; - default: - return QString(); - } - ret.append(QLatin1Char(desc)); - button = d->m_thenPush; - } - return ret; -} - -KRockerGesture &KRockerGesture::operator=(const KRockerGesture &other) -{ - d->m_hold = other.d->m_hold; - d->m_thenPush = other.d->m_thenPush; - return *this; -} - -bool KRockerGesture::operator==(const KRockerGesture &other) const -{ - return d->m_hold == other.d->m_hold && d->m_thenPush == other.d->m_thenPush; -} - -bool KRockerGesture::operator!=(const KRockerGesture &other) const -{ - return !operator==(other); -} - -uint KRockerGesture::hashable() const -{ - //make it asymmetric - return qHash(d->m_hold) + d->m_thenPush; -} diff --git a/src/kgesture_p.h b/src/kgesture_p.h deleted file mode 100644 --- a/src/kgesture_p.h +++ /dev/null @@ -1,246 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2006,2007 Andreas Hartmetz (ahartmetz@gmail.com) - - 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 KGESTURE_H -#define KGESTURE_H - -#include - -#include -#include -#include - -/* - kinds of gestures: - -shapes like triangle, right angle, line - -"rocker" (i.e. two mouse button) gestures - */ - -class KShapeGesturePrivate; -//TODO: implement operator== for special situations like in KKeyChooser. -class KXMLGUI_EXPORT KShapeGesture -{ -public: - /** - * Create a new invalid shape gesture. - */ - KShapeGesture(); - - /** - * Creates a new gesture consisting of given shape. - * If the gesture belongs to a QAction, and the user draws approximately the same shape - * on the screen while holding down the right mouse button, the action will trigger. - * @p shape must be a "reasonable" polygon. It must contain at least two points - * and it should contain at most 50 for performance reasons. No two consecutive points - * are allowed to be at the same position. - * @param shape shape to draw to trigger this gesture - */ - explicit KShapeGesture(const QPolygon &shape); - - /** - * Creates a new gesture from a string description. - * @param description create gesture according to this - */ - explicit KShapeGesture(const QString &description); - - /** - * Copies the given gesture. - * @param other gesture to copy - */ - KShapeGesture(const KShapeGesture &other); - - /** - * Destructor. - */ - ~KShapeGesture(); - - /** - * Set the shape to draw to trigger this gesture. - */ - void setShape(const QPolygon &shape); - - /** - * set a user-visible name for this gesture's shape, like "triangle" or "line". - */ - void setShapeName(const QString &friendlyName); - - /** - * Return the user-visible name for this gesture's shape, like "triangle" or "line". - */ - QString shapeName() const; - - /** - * Return true if this gesture is valid. - * - */ - bool isValid() const; - - /** - * Return a string representation of this gesture. - * Return empty string if invalid. - * This function is mainly for use with config files. - * - * @see shapeName() - */ - QString toString() const; - - /** - * Return an idealized SVG image of this gesture. - * Return an empty image if invalid. - * @param attributes SVG attributes to apply to the SVG "path" element that - * makes up the drawing of the gesture. By default, only a 'fill="none"' - * attribute will be set. - */ - QByteArray toSvg(const QString &attributes = QString()) const; - - /** - * Return a difference measurement betwenn this gesture and the @p other - * gesture. Abort comparison if difference is larger than @p abortThreshold - * and return a very large difference in that case. - * Usual return values range from x to y //TODO: fill in x and y - */ - float distance(const KShapeGesture &other, float abortThreshold) const; - - /** - * Set this gesture to the other gesture. - */ - KShapeGesture &operator=(const KShapeGesture &other); - - /** - * Return whether this gesture is equal to the other gesture. - */ - bool operator==(const KShapeGesture &other) const; - - /** - * Return the opposite of operator==() - */ - bool operator!=(const KShapeGesture &other) const; - - /** - * Return an opaque value for use in hash tables - */ - uint hashable() const; - -private: - KShapeGesturePrivate *const d; -}; - -inline uint qHash(const KShapeGesture &key) -{ - return qHash(key.hashable()); -} - -class KRockerGesturePrivate; - -class KXMLGUI_EXPORT KRockerGesture -{ -public: - /** - * Create a new invalid rocker gesture. - */ - KRockerGesture(); - - /** - * Creates a new gesture consisting of given buttons. - * @param description create gesture according to this - */ - KRockerGesture(enum Qt::MouseButton hold, enum Qt::MouseButton thenPush); - - /** - * Creates a new gesture from a string description. - * @param description create gesture according to this - */ - explicit KRockerGesture(const QString &description); - - /** - * Copies the given gesture. - * @param other gesture to copy - */ - KRockerGesture(const KRockerGesture &other); - - /** - * Destructor. - */ - ~KRockerGesture(); - - /** - * set button combination to trigger - */ - void setButtons(Qt::MouseButton hold, Qt::MouseButton thenPush); - - /** - * Write the button combination to hold and thenPush - */ - void getButtons(Qt::MouseButton *hold, Qt::MouseButton *thenPush) const; - - /** - * Return a user-friendly name of the button combination. - */ - QString rockerName() const; - - /** - * Return a user-friendly name for the mouse button button - */ - static QString mouseButtonName(Qt::MouseButton button); - - /** - * Return true if this gesture is valid. - */ - bool isValid() const; - - /** - * Return a string representation of this gesture. - * Return an empty string if invalid. - * This function is mainly for use with config files. - * - * @see rockerName() - */ - QString toString() const; - - /** - * Set this gesture to the other gesture. - */ - KRockerGesture &operator=(const KRockerGesture &other); - - /** - * Return whether this gesture is equal to the other gesture. - */ - bool operator==(const KRockerGesture &other) const; - - /** - * Return the opposite of operator==() - */ - bool operator!=(const KRockerGesture &other) const; - - /** - * Return an opaque value for use in hash tables - */ - uint hashable() const; - -private: - KRockerGesturePrivate *const d; -}; - -inline uint qHash(const KRockerGesture &key) -{ - return qHash(key.hashable()); -} - -//KGESTURE_H -#endif diff --git a/src/kgesturemap.cpp b/src/kgesturemap.cpp deleted file mode 100644 --- a/src/kgesturemap.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2006,2007 Andreas Hartmetz (ahartmetz@gmail.com) - - 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 "kgesturemap_p.h" -#include "debug.h" - -#include -#include -#include - -/* - This is a class for internal use by the KDE libraries only. This class - may change or go away without notice so don't try to use it in non-kdelibs - code. - */ - -class KGestureMapContainer -{ -public: - KGestureMap gestureMap; -}; - -Q_GLOBAL_STATIC(KGestureMapContainer, g_instance) - -KGestureMap::~KGestureMap() -{ -} - -KGestureMap *KGestureMap::self() -{ - return &g_instance()->gestureMap; -} - -KGestureMap::KGestureMap() -{ - m_gestureTimeout.setSingleShot(true); - connect(&m_gestureTimeout, &QTimer::timeout, - this, &KGestureMap::stopAcquisition); - //It would be nice to install the filter on demand. Unfortunately, - //undesired behavior might result due to changing invocation - //orders of different event filters. - if (qApp) { - qApp->installEventFilter(this); - } -} - -void KGestureMap::setShapeGesture(QAction *act, const KShapeGesture &gesture) -{ - if (!gesture.isValid() || !act) { - return; - } - qCDebug(DEBUG_KXMLGUI) << "KGestureMap::addGesture(KShapeGesture ...)"; - if (m_shapeGestures.contains(gesture)) { - qCWarning(DEBUG_KXMLGUI) << "Replacing an action for a gesture already taken"; - } - m_shapeGestures.insert(gesture, act); -} - -void KGestureMap::setRockerGesture(QAction *act, const KRockerGesture &gesture) -{ - if (!gesture.isValid() || !act) { - return; - } - qCDebug(DEBUG_KXMLGUI) << "KGestureMap::addGesture(KRockerGesture ...)"; - if (m_rockerGestures.contains(gesture)) { - qCWarning(DEBUG_KXMLGUI) << "Replacing an action for a gesture already taken"; - } - m_rockerGestures.insert(gesture, act); -} - -void KGestureMap::setDefaultShapeGesture(QAction *act, const KShapeGesture &gesture) -{ - if (!gesture.isValid() || !act) { - return; - } - qCDebug(DEBUG_KXMLGUI) << "KGestureMap::addGesture(KShapeGesture ...)"; - if (m_defaultShapeGestures.contains(gesture)) { - qCWarning(DEBUG_KXMLGUI) << "Replacing an action for a gesture already taken"; - } - m_defaultShapeGestures.insert(gesture, act); -} - -void KGestureMap::setDefaultRockerGesture(QAction *act, const KRockerGesture &gesture) -{ - if (!gesture.isValid() || !act) { - return; - } - qCDebug(DEBUG_KXMLGUI) << "KGestureMap::addGesture(KRockerGesture ...)"; - if (m_defaultRockerGestures.contains(gesture)) { - qCWarning(DEBUG_KXMLGUI) << "Replacing an action for a gesture already taken"; - } - m_defaultRockerGestures.insert(gesture, act); -} - -void KGestureMap::removeAllGestures(QAction *kact) -{ - KShapeGesture activeGesture; - ShapeGestureHash::iterator si = m_shapeGestures.begin(); - ShapeGestureHash::iterator send = m_shapeGestures.end(); - for (; si != send; ++si) { - if (si.value() == kact) { - m_shapeGestures.remove(si.key()); - break; - } - } - - si = m_defaultShapeGestures.begin(); - send = m_defaultShapeGestures.end(); - for (; si != send; ++si) { - if (si.value() == kact) { - m_defaultShapeGestures.remove(si.key()); - break; - } - } - - RockerGestureHash::iterator ri = m_rockerGestures.begin(); - RockerGestureHash::iterator rend = m_rockerGestures.end(); - for (; ri != rend; ++ri) { - if (ri.value() == kact) { - m_rockerGestures.remove(ri.key()); - break; - } - } - - ri = m_defaultRockerGestures.begin(); - rend = m_defaultRockerGestures.end(); - for (; ri != rend; ++ri) { - if (ri.value() == kact) { - m_defaultRockerGestures.remove(ri.key()); - break; - } - } -} - -QAction *KGestureMap::findAction(const KShapeGesture &gesture) const -{ - return m_shapeGestures.value(gesture); -} - -QAction *KGestureMap::findAction(const KRockerGesture &gesture) const -{ - return m_rockerGestures.value(gesture); -} - -void KGestureMap::installEventFilterOnMe(QApplication *app) -{ - app->installEventFilter(this); -} - -KShapeGesture KGestureMap::shapeGesture(const QAction *kact) const -{ - KShapeGesture activeGesture; - ShapeGestureHash::const_iterator it = m_shapeGestures.constBegin(); - ShapeGestureHash::const_iterator end = m_shapeGestures.constEnd(); - for (; it != end; ++it) { - if (it.value() == kact) { - activeGesture = it.key(); - break; - } - } - return activeGesture; -} - -KShapeGesture KGestureMap::defaultShapeGesture(const QAction *kact) const -{ - KShapeGesture defaultGesture; - ShapeGestureHash::const_iterator it = m_defaultShapeGestures.constBegin(); - ShapeGestureHash::const_iterator end = m_defaultShapeGestures.constEnd(); - for (; it != end; ++it) { - if (it.value() == kact) { - defaultGesture = it.key(); - break; - } - } - return defaultGesture; -} - -KRockerGesture KGestureMap::rockerGesture(const QAction *kact) const -{ - KRockerGesture activeGesture; - RockerGestureHash::const_iterator it = m_rockerGestures.constBegin(); - RockerGestureHash::const_iterator end = m_rockerGestures.constEnd(); - for (; it != end; ++it) { - if (it.value() == kact) { - activeGesture = it.key(); - break; - } - } - return activeGesture; -} - -KRockerGesture KGestureMap::defaultRockerGesture(const QAction *kact) const -{ - KRockerGesture defaultGesture; - RockerGestureHash::const_iterator it = m_defaultRockerGestures.constBegin(); - RockerGestureHash::const_iterator end = m_defaultRockerGestures.constEnd(); - for (; it != end; ++it) { - if (it.value() == kact) { - defaultGesture = it.key(); - break; - } - } - return defaultGesture; -} - -inline int KGestureMap::bitCount(int n) -{ - int count = 0; - while (n) { - n &= (n - 1); - count++; - } - return count; -} - -void KGestureMap::handleAction(QAction *kact) -{ - if (!kact) { - return; - } - qCDebug(DEBUG_KXMLGUI) << "handleAction"; - //TODO: only activate in the action's context, just like keyboard shortcuts - kact->trigger(); - return; -} - -void KGestureMap::matchShapeGesture() -{ - //TODO: tune and tweak until satisfied with result :) - m_shapeGesture.setShape(m_points); - float dist, minDist = 20.0; - QAction *bestMatch = nullptr; - - for (QHash::const_iterator it = m_shapeGestures.constBegin(); - it != m_shapeGestures.constEnd(); ++it) { - dist = m_shapeGesture.distance(it.key(), 1000.0); - if (dist < minDist) { - minDist = dist; - bestMatch = it.value(); - } - } - handleAction(bestMatch); -} - -//slot -void KGestureMap::stopAcquisition() -{ - m_gestureTimeout.stop(); - m_acquiring = false; -} - -//TODO: Probably kwin, kded and others should not have a gesture map. -//Maybe making them friends and providing a private "die()" function would work. -/* - * Act on rocker gestures immediately and collect movement data for evaluation. - * The decision when to consume and when to relay an event is quite tricky. - * I decided to only consume clicks that belong to completed rocker gestures. - * A user might e.g. go back in a browser several times using rocker gestures, - * thus changing what's under the cursor every time. This might lead to - * unintended clicks on links where there was free space before. - */ - -bool KGestureMap::eventFilter(QObject *obj, QEvent *e) -{ - //disable until it does not interfere with other input any more - return false; - Q_UNUSED(obj); - int type = e->type(); - - //catch right-clicks disguised as context menu events. if we ignore a - //context menu event caused by a right-click, it should get resent - //as a right-click event, according to documentation. - //### this is preliminary - if (type == QEvent::ContextMenu) { - QContextMenuEvent *cme = static_cast(e); - if (cme->reason() == QContextMenuEvent::Mouse) { - cme->ignore(); - return true; - } - return false; - } - - if (type < QEvent::MouseButtonPress || type > QEvent::MouseMove) { - return false; - } - - QMouseEvent *me = static_cast(e); - if (type == QEvent::MouseButtonPress) { - int nButtonsDown = bitCount(me->buttons()); - qCDebug(DEBUG_KXMLGUI) << "number of buttons down:" << nButtonsDown; - - //right button down starts gesture acquisition - if (nButtonsDown == 1 && me->button() == Qt::RightButton) { - //"startAcquisition()" - m_acquiring = true; - m_gestureTimeout.start(4000); - qCDebug(DEBUG_KXMLGUI) << "========================"; - m_points.clear(); - m_points.append(me->pos()); - return true; - } else if (nButtonsDown != 2) { - return false; - } - - //rocker gestures. do not trigger any movement gestures from now on. - stopAcquisition(); - int buttonHeld = me->buttons() ^ me->button(); - m_rockerGesture.setButtons(static_cast(buttonHeld), me->button()); - QAction *match = m_rockerGestures.value(m_rockerGesture); - if (!match) { - return false; - } - handleAction(match); - return true; - } - - if (m_acquiring) { - if (type == QEvent::MouseMove) { - m_points.append(me->pos()); - //abort to avoid using too much memory. 1010 points should be enough - //for everyone! :) - //next reallocation of m_points would happen at 1012 items - if (m_points.size() > 1010) { - stopAcquisition(); - } - return true; - } else if (type == QEvent::MouseButtonRelease && me->button() == Qt::RightButton) { - stopAcquisition(); - - //TODO: pre-selection of gestures by length (optimization), if necessary - //possibly apply other heuristics - //then try all remaining gestures for sufficiently small distance - int dist = 0; - for (int i = 1; i < m_points.size(); i++) { - dist += (m_points[i] - m_points[i - 1]).manhattanLength(); - if (dist > 40) { - matchShapeGesture(); - return true; - } - //this was probably a small glitch while right-clicking if we get here. - //TODO: open the context menu or do whatever happens on right-click (how?) - } - return false; - } - } - return false; -} - diff --git a/src/kgesturemap_p.h b/src/kgesturemap_p.h deleted file mode 100644 --- a/src/kgesturemap_p.h +++ /dev/null @@ -1,87 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2006,2007 Andreas Hartmetz (ahartmetz@gmail.com) - - 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 KGESTUREMAP_H -#define KGESTUREMAP_H - -#include -#include -#include -#include - -#include "kgesture_p.h" - -class QApplication; -class QAction; -class QEvent; - -class KXMLGUI_EXPORT KGestureMap : public QObject -{ - Q_OBJECT -public: - static KGestureMap *self(); - - bool eventFilter(QObject *obj, QEvent *e) override; - void setShapeGesture(QAction *kact, const KShapeGesture &gesture); - void setRockerGesture(QAction *kact, const KRockerGesture &gesture); - void setDefaultShapeGesture(QAction *kact, const KShapeGesture &gesture); - void setDefaultRockerGesture(QAction *kact, const KRockerGesture &gesture); - /** - * This method will remove all gestures defined for a given action - */ - void removeAllGestures(QAction *kact); - QAction *findAction(const KShapeGesture &gesture) const; - QAction *findAction(const KRockerGesture &gesture) const; - KShapeGesture shapeGesture(const QAction *kact) const; - KShapeGesture defaultShapeGesture(const QAction *kact) const; - KRockerGesture rockerGesture(const QAction *kact) const; - KRockerGesture defaultRockerGesture(const QAction *kact) const; - -private Q_SLOTS: - void stopAcquisition(); - -private: - friend class KGestureMapContainer; - KGestureMap(); - ~KGestureMap() override; - - friend class KApplicationPrivate; - //intended to be used at application initialization - void installEventFilterOnMe(QApplication *app); - - inline int bitCount(int n); - void handleAction(QAction *kact); - void matchShapeGesture(); - - //this is an internal class so don't bother with a d-pointer - typedef QHash< KShapeGesture, QAction * > ShapeGestureHash; - typedef QHash< KRockerGesture, QAction * > RockerGestureHash; - ShapeGestureHash m_shapeGestures; - ShapeGestureHash m_defaultShapeGestures; - RockerGestureHash m_rockerGestures; - RockerGestureHash m_defaultRockerGestures; - QPolygon m_points; - QTimer m_gestureTimeout; - bool m_acquiring; - - KShapeGesture m_shapeGesture; - KRockerGesture m_rockerGesture; -}; - -#endif //KGESTUREMAP_H diff --git a/src/kshortcutsdialog_p.h b/src/kshortcutsdialog_p.h --- a/src/kshortcutsdialog_p.h +++ b/src/kshortcutsdialog_p.h @@ -25,10 +25,6 @@ #include "kshortcutseditor.h" #include "kkeysequencewidget.h" -#if 0 -#include -#endif - #include #include diff --git a/src/kshortcutseditor.h b/src/kshortcutseditor.h --- a/src/kshortcutseditor.h +++ b/src/kshortcutseditor.h @@ -29,10 +29,6 @@ #include -#if 0 -#include -#endif - class KActionCollection; class KConfig; class KConfigBase; diff --git a/src/kshortcutseditor.cpp b/src/kshortcutseditor.cpp --- a/src/kshortcutseditor.cpp +++ b/src/kshortcutseditor.cpp @@ -406,20 +406,6 @@ changeKeyShortcut(item, GlobalAlternate, alternateSequence(defaultShortcut)); } #endif - -#if 0 - KShapeGesture actShapeGesture = KGestureMap::self()->shapeGesture(act); - KShapeGesture actDefaultShapeGesture = KGestureMap::self()->defaultShapeGesture(act); - if (actShapeGesture != actDefaultShapeGesture) { - changeShapeGesture(item, actDefaultShapeGesture); - } - - KRockerGesture actRockerGesture = KGestureMap::self()->rockerGesture(act); - KRockerGesture actDefaultRockerGesture = KGestureMap::self()->defaultRockerGesture(act); - if (actRockerGesture != actDefaultRockerGesture) { - changeRockerGesture(item, actDefaultRockerGesture); - } -#endif } } @@ -463,13 +449,6 @@ if (column >= LocalPrimary && column <= GlobalAlternate) { changeKeyShortcut(item, column, newShortcut.value()); } -#if 0 - else if (column == ShapeGesture) { - changeShapeGesture(item, newShortcut.value()); - } else if (column == RockerGesture) { - changeRockerGesture(item, newShortcut.value()); - } -#endif } void KShortcutsEditorPrivate::changeKeyShortcut(KShortcutsEditorItem *item, uint column, const QKeySequence &capture) @@ -485,80 +464,6 @@ item->setText(column, capture.toString(QKeySequence::NativeText)); } -#if 0 -void KShortcutsEditorPrivate::changeShapeGesture(KShortcutsEditorItem *item, const KShapeGesture &capture) -{ - if (capture == KGestureMap::self()->shapeGesture(item->m_action)) { - return; - } - - if (capture.isValid()) { - bool conflict = false; - KShortcutsEditorItem *otherItem; - - //search for conflicts - for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { - if (!(*it)->parent() || (*it == item)) { - continue; - } - - otherItem = static_cast(*it); - - //comparisons are possibly expensive - KShapeGesture otherGesture = KGestureMap::self()->shapeGesture(otherItem->m_action); - if (!otherGesture.isValid()) { - continue; - } - - if (capture == otherGesture) { - conflict = true; - break; - } - } - - if (conflict && !stealShapeGesture(otherItem, capture)) { - return; - } - } - - item->setShapeGesture(capture); -} -#endif - -#if 0 -void KShortcutsEditorPrivate::changeRockerGesture(KShortcutsEditorItem *item, const KRockerGesture &capture) -{ - if (capture == KGestureMap::self()->rockerGesture(item->m_action)) { - return; - } - - if (capture.isValid()) { - bool conflict = false; - KShortcutsEditorItem *otherItem; - - for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { - if (!(*it)->parent() || (*it == item)) { - continue; - } - - otherItem = static_cast(*it); - - KRockerGesture otherGesture = KGestureMap::self()->rockerGesture(otherItem->m_action); - if (capture == otherGesture) { - conflict = true; - break; - } - } - - if (conflict && !stealRockerGesture(otherItem, capture)) { - return; - } - } - - item->setRockerGesture(capture); -} -#endif - void KShortcutsEditorPrivate::clearConfiguration() { for (QTreeWidgetItemIterator it(ui.list); (*it); ++it) { @@ -573,10 +478,6 @@ changeKeyShortcut(item, GlobalPrimary, QKeySequence()); changeKeyShortcut(item, GlobalAlternate, QKeySequence()); - -#if 0 - changeShapeGesture(item, KShapeGesture()); -#endif } } @@ -626,43 +527,6 @@ } } -#if 0 -bool KShortcutsEditorPrivate::stealShapeGesture(KShortcutsEditorItem *item, const KShapeGesture &gst) -{ - QString title = i18n("Key Conflict"); - QString message = i18n("The '%1' shape gesture has already been allocated to the \"%2\" action.\n" - "Do you want to reassign it from that action to the current one?", - gst.shapeName(), item->m_action->text()); - - if (KMessageBox::warningContinueCancel(q, message, title, KGuiItem(i18n("Reassign"))) - != KMessageBox::Continue) { - return false; - } - item->setShapeGesture(KShapeGesture()); - - return true; -} -#endif - -#if 0 -bool KShortcutsEditorPrivate::stealRockerGesture(KShortcutsEditorItem *item, const KRockerGesture &gst) -{ - QString title = i18n("Key Conflict"); - QString message = i18n("The '%1' rocker gesture has already been allocated to the \"%2\" action.\n" - "Do you want to reassign it from that action to the current one?", - gst.rockerName(), item->m_action->text()); - - if (KMessageBox::warningContinueCancel(q, message, title, KGuiItem(i18n("Reassign"))) - != KMessageBox::Continue) { - return false; - } - - item->setRockerGesture(KRockerGesture()); - - return true; -} -#endif - /*TODO for the printShortcuts function Nice to have features (which I'm not sure I can do before may due to more important things): diff --git a/src/kshortcutseditoritem.cpp b/src/kshortcutseditoritem.cpp --- a/src/kshortcutseditoritem.cpp +++ b/src/kshortcutseditoritem.cpp @@ -30,10 +30,6 @@ #include #include -#if 0 -#include -#endif - #if HAVE_GLOBALACCEL # include #endif @@ -44,10 +40,6 @@ , m_isNameBold(false) , m_oldLocalShortcut(nullptr) , m_oldGlobalShortcut(nullptr) -#if 0 - , m_oldShapeGesture(0) - , m_oldRockerGesture(0) -#endif { // Filtering message requested by translators (scripting). m_id = m_action->objectName(); @@ -65,19 +57,11 @@ { delete m_oldLocalShortcut; delete m_oldGlobalShortcut; -#if 0 - delete m_oldShapeGesture; - delete m_oldRockerGesture; -#endif } bool KShortcutsEditorItem::isModified() const { -#if 0 - return m_oldLocalShortcut || m_oldGlobalShortcut || m_oldShapeGesture || m_oldRockerGesture; -#else return m_oldLocalShortcut || m_oldGlobalShortcut; -#endif } QVariant KShortcutsEditorItem::data(int column, int role) const @@ -94,12 +78,6 @@ case GlobalPrimary: case GlobalAlternate: return keySequence(column); -#if 0 - case ShapeGesture: - return KGestureMap::self()->shapeGesture(m_action).shapeName(); - case RockerGesture: - return KGestureMap::self()->rockerGesture(m_action).rockerName(); -#endif default: break; } @@ -150,18 +128,6 @@ case GlobalPrimary: case GlobalAlternate: return keySequence(column); -#if 0 - case ShapeGesture: { //scoping for "ret" - QVariant ret; - ret.setValue(KGestureMap::self()->shapeGesture(m_action)); - return ret; - } - case RockerGesture: { - QVariant ret; - ret.setValue(KGestureMap::self()->rockerGesture(m_action)); - return ret; - } -#endif default: // Column not valid for this role Q_ASSERT(false); @@ -184,18 +150,6 @@ return primarySequence(defaultGlobalShortcuts); case GlobalAlternate: return alternateSequence(defaultGlobalShortcuts); -#endif -#if 0 - case ShapeGesture: { - QVariant ret; - ret.setValue(KGestureMap::self()->defaultShapeGesture(m_action)); - return ret; - } - case RockerGesture: { - QVariant ret; - ret.setValue(KGestureMap::self()->defaultRockerGesture(m_action)); - return ret; - } #endif default: // Column not valid for this role @@ -292,30 +246,6 @@ updateModified(); } -#if 0 -void KShortcutsEditorItem::setShapeGesture(const KShapeGesture &gst) -{ - if (!m_oldShapeGesture) { - m_oldShapeGesture = new KShapeGesture(gst); - } - KGestureMap::self()->setShapeGesture(m_action, gst); - KGestureMap::self()->setDefaultShapeGesture(m_action, gst); - updateModified(); -} -#endif - -#if 0 -void KShortcutsEditorItem::setRockerGesture(const KRockerGesture &gst) -{ - if (!m_oldRockerGesture) { - m_oldRockerGesture = new KRockerGesture(gst); - } - KGestureMap::self()->setRockerGesture(m_action, gst); - KGestureMap::self()->setDefaultRockerGesture(m_action, gst); - updateModified(); -} -#endif - //our definition of modified is "modified since the chooser was shown". void KShortcutsEditorItem::updateModified() { @@ -329,16 +259,6 @@ m_oldGlobalShortcut = nullptr; } #endif -#if 0 - if (m_oldShapeGesture && *m_oldShapeGesture == KGestureMap::self()->shapeGesture(m_action)) { - delete m_oldShapeGesture; - m_oldShapeGesture = 0; - } - if (m_oldRockerGesture && *m_oldRockerGesture == KGestureMap::self()->rockerGesture(m_action)) { - delete m_oldRockerGesture; - m_oldRockerGesture = 0; - } -#endif } bool KShortcutsEditorItem::isModified(uint column) const @@ -367,27 +287,14 @@ } else { return alternateSequence(*m_oldGlobalShortcut) != alternateSequence(KGlobalAccel::self()->shortcut(m_action)); } -#endif -#if 0 - case ShapeGesture: - return static_cast(m_oldShapeGesture); - case RockerGesture: - return static_cast(m_oldRockerGesture); #endif default: return false; } } void KShortcutsEditorItem::undo() { -#ifndef NDEBUG -#if 0 - if (m_oldLocalShortcut || m_oldGlobalShortcut || m_oldShapeGesture || m_oldRockerGesture) { - //qCDebug(DEBUG_KXMLGUI) << "Undoing changes for " << data(Name, Qt::DisplayRole).toString(); - } -#endif -#endif if (m_oldLocalShortcut) { // We only ever reset the active Shortcut m_action->setShortcuts(*m_oldLocalShortcut); @@ -399,39 +306,13 @@ } #endif -#if 0 - if (m_oldShapeGesture) { - KGestureMap::self()->setShapeGesture(m_action, *m_oldShapeGesture); - KGestureMap::self()->setDefaultShapeGesture(m_action, *m_oldShapeGesture); - } - - if (m_oldRockerGesture) { - KGestureMap::self()->setRockerGesture(m_action, *m_oldRockerGesture); - KGestureMap::self()->setDefaultRockerGesture(m_action, *m_oldRockerGesture); - } -#endif - updateModified(); } void KShortcutsEditorItem::commit() { -#ifndef NDEBUG -#if 0 - if (m_oldLocalShortcut || m_oldGlobalShortcut || m_oldShapeGesture || m_oldRockerGesture) { - //qCDebug(DEBUG_KXMLGUI) << "Committing changes for " << data(Name, Qt::DisplayRole).toString(); - } -#endif -#endif - delete m_oldLocalShortcut; m_oldLocalShortcut = nullptr; delete m_oldGlobalShortcut; m_oldGlobalShortcut = nullptr; -#if 0 - delete m_oldShapeGesture; - m_oldShapeGesture = 0; - delete m_oldRockerGesture; - m_oldRockerGesture = 0; -#endif }