diff options
author | Bernd Lamecker <bernd.lamecker@basyskom.de> | 2010-02-22 10:37:04 +0100 |
---|---|---|
committer | Bernd Lamecker <bernd.lamecker@basyskom.de> | 2010-02-22 14:35:30 +0100 |
commit | a538a0b10755f246ebce89e848096852deb55e40 (patch) | |
tree | ddcdbe588bff264fa423083edfde4d5dbfda2e53 | |
parent | b8f20b8ebb65f4d78ab5717b861808aff3acf020 (diff) |
Changes: Added kinetic scrolling support to plain Qt
RevBy: TrustMe
-rw-r--r-- | debian/dui-demos-plainqt.install | 1 | ||||
-rw-r--r-- | demos/demos.pro | 1 | ||||
-rw-r--r-- | demos/qtstylekinetic/MainWindow.cpp | 49 | ||||
-rw-r--r-- | demos/qtstylekinetic/MainWindow.h | 35 | ||||
-rw-r--r-- | demos/qtstylekinetic/MainWindow.ui | 334 | ||||
-rw-r--r-- | demos/qtstylekinetic/main.cpp | 33 | ||||
-rw-r--r-- | demos/qtstylekinetic/qtstylekinetic.pro | 54 | ||||
-rw-r--r-- | plainqt/style/qtmaemo6kineticscrolling.cpp | 286 | ||||
-rw-r--r-- | plainqt/style/qtmaemo6kineticscrolling.h | 171 | ||||
-rw-r--r-- | plainqt/style/qtmaemo6pangesture.cpp | 121 | ||||
-rw-r--r-- | plainqt/style/qtmaemo6pangesture.h | 67 | ||||
-rw-r--r-- | plainqt/style/qtmaemo6style.cpp | 60 | ||||
-rw-r--r-- | plainqt/style/qtmaemo6style.h | 92 | ||||
-rw-r--r-- | plainqt/style/qtmaemo6style_p.h | 6 | ||||
-rw-r--r-- | plainqt/style/style.pri | 8 |
15 files changed, 1116 insertions, 202 deletions
diff --git a/debian/dui-demos-plainqt.install b/debian/dui-demos-plainqt.install index 67ad5117..69d5ad69 100644 --- a/debian/dui-demos-plainqt.install +++ b/debian/dui-demos-plainqt.install @@ -1,5 +1,6 @@ usr/bin/qtstyledialogs usr/bin/qtstyleexample +usr/bin/qtstylekinetic usr/share/applications/qtstyledialogs.desktop usr/share/applications/qtstyledialogs-windows-style.desktop usr/share/applications/qtstyleexample.desktop diff --git a/demos/demos.pro b/demos/demos.pro index 77ed6385..4fa99332 100644 --- a/demos/demos.pro +++ b/demos/demos.pro @@ -7,6 +7,7 @@ SUBDIRS = \ animatedlayout/translations \ qtstyleexample \ qtstyledialogs \ + qtstylekinetic \ appletinstallationsource # we do not have compiled QtDBusd4 diff --git a/demos/qtstylekinetic/MainWindow.cpp b/demos/qtstylekinetic/MainWindow.cpp new file mode 100644 index 00000000..f0a4b833 --- /dev/null +++ b/demos/qtstylekinetic/MainWindow.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libdui. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#include "MainWindow.h" + +#include <QPushButton> +#include <QTableWidgetItem> +#include <QDebug> + +MainWindow::MainWindow() : QMainWindow(NULL) +{ + setupUi(this); + + QWidget* w = new QWidget(); + w->setLayout(new QVBoxLayout); + for(int i = 0; i < 100; ++i) + w->layout()->addWidget(new QPushButton(QString("Button %1").arg(i))); + scrollArea->setWidget(w); + + for(int i = 0; i < 100; ++i) + new QListWidgetItem(QString("Item %1").arg(i), listWidget); + + for(int row = 0; row < 100; ++row) + for(int col = 0; col < 100; ++col) { + QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(row*col)); + tableWidget->setItem(row, col, item); + } +} + +MainWindow::~MainWindow() +{ + +} diff --git a/demos/qtstylekinetic/MainWindow.h b/demos/qtstylekinetic/MainWindow.h new file mode 100644 index 00000000..8126fa2b --- /dev/null +++ b/demos/qtstylekinetic/MainWindow.h @@ -0,0 +1,35 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libdui. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +#include "ui_MainWindow.h" + +class MainWindow : public QMainWindow, Ui::MainWindow +{ + Q_OBJECT +public: + MainWindow(); + ~MainWindow(); +}; + +#endif diff --git a/demos/qtstylekinetic/MainWindow.ui b/demos/qtstylekinetic/MainWindow.ui new file mode 100644 index 00000000..4fd85726 --- /dev/null +++ b/demos/qtstylekinetic/MainWindow.ui @@ -0,0 +1,334 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>527</width> + <height>427</height> + </rect> + </property> + <property name="windowTitle"> + <string>Qt Style Dialog Test</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>2</number> + </property> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>ScrollArea</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>495</width> + <height>353</height> + </rect> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>ListView</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QListWidget" name="listWidget"/> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_3"> + <attribute name="title"> + <string>TableView</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QTableWidget" name="tableWidget"> + <property name="rowCount"> + <number>100</number> + </property> + <property name="columnCount"> + <number>100</number> + </property> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <row/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + <column/> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <action name="actionNew"> + <property name="text"> + <string>New</string> + </property> + </action> + <action name="actionQuit"> + <property name="text"> + <string>Quit</string> + </property> + </action> + <action name="actionOpen"> + <property name="icon"> + <iconset> + <normaloff>:/images/images/icon-m-save.svg</normaloff>:/images/images/icon-m-save.svg</iconset> + </property> + <property name="text"> + <string>Open...</string> + </property> + </action> + <action name="actionOrder"> + <property name="icon"> + <iconset> + <normaloff>:/images/images/icon-m-message-send-receive.svg</normaloff>:/images/images/icon-m-message-send-receive.svg</iconset> + </property> + <property name="text"> + <string>order</string> + </property> + </action> + <action name="actionAction_1"> + <property name="text"> + <string>Action 1</string> + </property> + </action> + <action name="actionAction_2"> + <property name="text"> + <string>Action 2</string> + </property> + </action> + <action name="actionAction_3"> + <property name="text"> + <string>Action 3</string> + </property> + </action> + <action name="actionAction_4"> + <property name="text"> + <string>Action 4</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> diff --git a/demos/qtstylekinetic/main.cpp b/demos/qtstylekinetic/main.cpp new file mode 100644 index 00000000..fd97c863 --- /dev/null +++ b/demos/qtstylekinetic/main.cpp @@ -0,0 +1,33 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libdui. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#include <QApplication> +#include <QMainWindow> + +#include "MainWindow.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + MainWindow mw; + mw.show(); + + return app.exec(); +} + diff --git a/demos/qtstylekinetic/qtstylekinetic.pro b/demos/qtstylekinetic/qtstylekinetic.pro new file mode 100644 index 00000000..93e680ed --- /dev/null +++ b/demos/qtstylekinetic/qtstylekinetic.pro @@ -0,0 +1,54 @@ +DUIROOT = ../.. +include($$DUIROOT/mkspecs/common.pri) +TEMPLATE = app +TARGET = qtstylekinetic +target.path = $$DUI_INSTALL_BIN +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp \ + MainWindow.cpp +HEADERS += MainWindow.h +FORMS += MainWindow.ui + +# UI style definition +style_sheet.path = $$DUI_THEME_DIR/../qtstylekinetic/themes/style +style_sheet.files = style/qtstylekinetic.css +view_configuration.path = $$DUI_THEME_DIR/../qtstylekinetic/themes +view_configuration.files = style/qtstylekinetic.conf +style_images.path = $$DUI_THEME_DIR/../qtstylekinetic/themes/images +style_images.files = images/*.png \ + images/*.jpg +style_svg.path = $$DUI_THEME_DIR/../qtstylekinetic/themes/svg +style_svg.files = images/*.svg + +desktop_entry.path = $$DUI_INSTALL_DATA/applications +desktop_entry.files = \ + qtstylekinetic.desktop \ + qtstylekinetic-windows-style.desktop + +myname = com.nokia.qtstylekinetic + +services.CONFIG += no_check_exist +services.target = $${myname}.service +services.commands = cat $$IN_PWD/$${myname}.service.in \ + | sed -e "s:@DUI_INSTALL_BIN@:$${DUI_INSTALL_BIN}:g" \ + > $${myname}.service +services.files = $$OUT_PWD/$${myname}.service +services.path = $$DUI_DBUS_SERVICES_DIR + + +DEFINES += IMAGES_DIR=\"\\\"$$style_images.path/\\\"\" + +# Install instructions +INSTALLS += target \ + style_sheet \ + style_images \ + style_svg \ + desktop_entry \ + +!win32:!macx { + INSTALLS += services +} + diff --git a/plainqt/style/qtmaemo6kineticscrolling.cpp b/plainqt/style/qtmaemo6kineticscrolling.cpp new file mode 100644 index 00000000..e2211d79 --- /dev/null +++ b/plainqt/style/qtmaemo6kineticscrolling.cpp @@ -0,0 +1,286 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libdui. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#include "qtmaemo6kineticscrolling.h" + +#include <QAbstractItemView> +#include <QAbstractScrollArea> +#include <QApplication> +#include <QList> +#include <QMouseEvent> +#include <QEvent> +#include <QScrollBar> +#include <QDebug> + +QtMaemo6KineticScrolling::QtMaemo6KineticScrolling(QObject *parent) + : QObject(parent), + m_scrollStartDelay(50), + m_scrollStartOffset(5), + m_deaccelerationInterval(20), + m_deaccelerationStrength(2), + m_maxKineticScrollSpeed(64) +{ +} + +QtMaemo6KineticScrolling::~QtMaemo6KineticScrolling() +{ +} + +void QtMaemo6KineticScrolling::enableOn(QAbstractScrollArea *scrollArea) +{ + QWidget *viewport = scrollArea->viewport(); + viewport->installEventFilter(this); + + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->installEventFilter(this); + + m_kineticData.remove(viewport); + m_kineticData[viewport] = new KineticData; + m_kineticData[viewport]->widget = scrollArea; + m_kineticData[viewport]->state = KineticData::Waiting; + + if(QAbstractItemView* itemView = qobject_cast<QAbstractItemView*>(scrollArea)) { + //FIXME: public API usage... scrollPerItem prevents the kinetic from working + // proberly + itemView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); + itemView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + } + return; +} + +static QPoint scrollOffset(QWidget *widget) +{ + QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget); + if (scrollArea) { + return QPoint(scrollArea->horizontalScrollBar()->value(), + scrollArea->verticalScrollBar()->value()); + } + return QPoint(); +} + +static void setScrollOffset(QWidget *widget, const QPoint &p) +{ + QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget); + if (scrollArea) { + scrollArea->horizontalScrollBar()->setValue(p.x()); + scrollArea->verticalScrollBar()->setValue(p.y()); + } +} + +static QPoint deaccelerate(const QPoint &speed, int a, int max) +{ + int x = qBound(-max, speed.x(), max); + int y = qBound(-max, speed.y(), max); + if(x > 0) + x = qMax(0, x - a); + else + x = qMin(0, x + a); + + if(y > 0) + y = qMax(0, y - a); + else + y = qMin(0, y + a); + //x = (x == 0) ? x : (x > 0) ? qMax(0, x - a) : qMin(0, x + a); + //y = (y == 0) ? y : (y > 0) ? qMax(0, y - a) : qMin(0, y + a); + return QPoint(x, y); +} + +bool QtMaemo6KineticScrolling::eventFilter(QObject *object, QEvent *event) +{ + if (!object->isWidgetType()) + return false; + + QEvent::Type type = event->type(); + if (type != QEvent::MouseButtonPress && + type != QEvent::MouseButtonRelease && + type != QEvent::MouseMove && + type != QEvent::Show) + return false; + + QWidget *viewport = qobject_cast<QWidget*>(object); + //if object is not the viewport itself, search if one of the parents is the viewport + if(!qobject_cast<QAbstractScrollArea*>(viewport->parentWidget())) { + QWidget* parentViewPort = viewport->parentWidget(); + QAbstractScrollArea* scrollArea = NULL; + while ( parentViewPort ) { + if((scrollArea = qobject_cast<QAbstractScrollArea*>(parentViewPort))){ + viewport = scrollArea->viewport(); + break; + } else + parentViewPort = parentViewPort->parentWidget(); + } + } + KineticData *data = m_kineticData.value(viewport); + + if(viewport && data && type == QEvent::Show) { + //we have the viewport here + if(data) { + installEventFilter(viewport->children()); + } + } + + //skip if the event is on ignoreList + if (!viewport || !data || data->ignored.removeAll(event)) + return false; + + QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event); + if (!mouseEvent || mouseEvent->modifiers() != Qt::NoModifier) + return false; + + bool consumed = false; + + switch (data->state) { + case KineticData::Waiting: + if (mouseEvent->type() == QEvent::MouseButtonPress) + if (mouseEvent->buttons() == Qt::LeftButton) { + consumed = true; + data->state = KineticData::Pressed; + data->pressPos = mouseEvent->pos(); + data->pressedWidget = qobject_cast<QWidget*>(object); + data->offset = scrollOffset(data->widget); + if (!m_ticker.isActive()) + m_ticker.start(m_scrollStartDelay, this); + } + break; + + case KineticData::Pressed: + if (mouseEvent->type() == QEvent::MouseButtonRelease) { + consumed = true; + data->state = KineticData::Waiting; + + QMouseEvent *event1 = new QMouseEvent(QEvent::MouseButtonPress, + data->pressPos, Qt::LeftButton, + Qt::LeftButton, Qt::NoModifier); + QMouseEvent *event2 = new QMouseEvent(*mouseEvent); + + data->ignored << event1; + data->ignored << event2; + QApplication::postEvent(object, event1); + QApplication::postEvent(object, event2); + } + if (mouseEvent->type() == QEvent::MouseMove) { + consumed = true; + QPoint offset = mouseEvent->pos() - data->pressPos; + if(offset.manhattanLength() > m_scrollStartOffset) { + data->state = KineticData::Panning; + data->dragPos = QCursor::pos(); + if(m_ticker.isActive()) + m_ticker.stop(); + } + } + break; + + case KineticData::Panning: + if (mouseEvent->type() == QEvent::MouseMove) { + consumed = true; + QPoint delta = mouseEvent->pos() - data->pressPos; + //it occurs, that the last move event before release is a (0,0) + // move. In this case keep the last speed setting. + QPoint speed = QCursor::pos() - data->dragPos; + if(speed != QPoint(0,0)) + data->speed = speed; + data->dragPos = QCursor::pos(); + setScrollOffset(data->widget, data->offset - delta); + } + if (mouseEvent->type() == QEvent::MouseButtonRelease) { + consumed = true; + data->state = KineticData::KineticScroll; + if (!m_ticker.isActive()) + m_ticker.start(m_deaccelerationInterval, this); + } + break; + + case KineticData::KineticScroll: + if (mouseEvent->type() == QEvent::MouseButtonPress) { + consumed = true; + data->state = KineticData::Stop; + if (!m_ticker.isActive()) + m_ticker.start(m_scrollStartDelay, this); + } + if (mouseEvent->type() == QEvent::MouseButtonRelease) { + consumed = true; + data->state = KineticData::Waiting; + data->speed = QPoint(0, 0); + } + break; + + case KineticData::Stop: + if (mouseEvent->type() == QEvent::MouseButtonRelease) { + consumed = true; + data->state = KineticData::Waiting; + } + if (mouseEvent->type() == QEvent::MouseMove) { + consumed = true; + data->state = KineticData::Panning; + data->dragPos = QCursor::pos(); + if (!m_ticker.isActive()) + m_ticker.start(m_deaccelerationInterval, this); + } + break; + + default: + break; + } + + return consumed; +} + +void QtMaemo6KineticScrolling::timerEvent(QTimerEvent *event) +{ + QHashIterator<QWidget*, KineticData*> item(m_kineticData); + while (item.hasNext()) { + item.next(); + KineticData *data = item.value(); + if( data->state == KineticData::Pressed) { + m_ticker.stop(); + QMouseEvent *newPressEvent = new QMouseEvent(QEvent::MouseButtonPress, + data->pressPos, Qt::LeftButton, + Qt::LeftButton, Qt::NoModifier); + data->ignored << newPressEvent; + data->state = KineticData::Waiting; + QApplication::postEvent(data->pressedWidget, newPressEvent); + } + if (data->state == KineticData::KineticScroll) { + data->speed = deaccelerate(data->speed, m_deaccelerationStrength, m_maxKineticScrollSpeed); + QPoint p = scrollOffset(data->widget); + setScrollOffset(data->widget, p - data->speed); + if (data->speed == QPoint(0, 0)) { + data->state = KineticData::Waiting; + m_ticker.stop(); + } + } + if (data->state == KineticData::Stop) { + data->state = KineticData::Waiting; + data->speed = QPoint(0,0); + m_ticker.stop(); + } + } + QObject::timerEvent(event); +} + +void QtMaemo6KineticScrolling::installEventFilter(QObjectList list) { + foreach(QObject* obj, list) { + QWidget* w = qobject_cast<QWidget*>(obj); + if(w) { + w->installEventFilter(this); + installEventFilter(w->children()); + } + } +} diff --git a/plainqt/style/qtmaemo6kineticscrolling.h b/plainqt/style/qtmaemo6kineticscrolling.h new file mode 100644 index 00000000..1845893c --- /dev/null +++ b/plainqt/style/qtmaemo6kineticscrolling.h @@ -0,0 +1,171 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libdui. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#ifndef QTMAEMO6KINETICSCROLLING_H +#define QTMAEMO6KINETICSCROLLING_H + +#include <QObject> +#include <QBasicTimer> +#include <QHash> +#include <QPoint> + +class QWidget; +class QAbstractScrollArea; + +class QtMaemo6KineticScrolling: public QObject +{ + Q_OBJECT + Q_PROPERTY(int scrollStartDelay READ scrollStartDelay WRITE setScrollStartDelay); + Q_PROPERTY(int scrollStartOffset READ scrollStartOffset WRITE setScrollStartOffset); + Q_PROPERTY(int deaccelerationInterval READ deaccelerationInterval WRITE setDeaccelerationInterval); + Q_PROPERTY(int deaccelerationStrength READ deaccelerationStrength WRITE setDeaccelerationStrength); + Q_PROPERTY(int maxKineticScrollSpeed READ maxKineticScrollSpeed WRITE setMaxKineticScrollSpeed); +public: + QtMaemo6KineticScrolling(QObject *parent = 0); + ~QtMaemo6KineticScrolling(); + + /*! + * Enables the kinetic scrolling on the given scrollarea. + */ + void enableOn(QAbstractScrollArea *scrollArea); + + /*! \reimp */ + bool eventFilter(QObject *object, QEvent *event); + /*! \reimp_end */ + + /*! + * \brief Returns the current scroll delay in milliseconds. + * After a press event a move must been made within this time + * before the scrolling starts. If there is no move within this time + * the mouse press event is forwarded to the widget under the mouse. + * Default is 50ms. + * \see scrollStartOffset + */ + int scrollStartDelay() const { + return m_scrollStartDelay; + }; + + /*! + * \brief Sets the scroll delay in milliseconds. + * \see scrollStartDelay() + */ + void setScrollStartDelay(int delay) { + m_scrollStartDelay = delay; + }; + + /*! + * \brief Rturns the current scroll offset in milliseconds. + * After a press event a move must been made with at least this manhattan + * length before the scrolling starts. If there is no move within this length + * the mouse press event is forwarded to the widget under the mouse. + * Default is 5. + * \see scrollStartDelay() + */ + int scrollStartOffset() const { + return m_scrollStartOffset; + }; + + /*! + * \brief Sets the scroll offset in milliseconds. + * \see scrollStartOffset() + */ + void setScrollStartOffset(int offset) { + m_scrollStartDelay = offset; + }; + + /*! + * \brief Returns the current intervall in milliseconds the deacceleration methode is called. + * After a press event a move must been made with at least this manhattan + * length before the scrolling starts. If there is no move within this length + * the mouse press event is forwarded to the widget under the mouse. + * Default is 20ms. + */ + int deaccelerationInterval() const { + return m_deaccelerationInterval; + }; + + /*! + * \brief Sets the deaccelaration interval in milliseconds. + * \see deaccelerationInterval() + */ + void setDeaccelerationInterval(int interval) { + m_deaccelerationInterval = interval; + }; + + /*! + * \brief Returns the current deaccelaration strength. + * this is the value of speed in pixels the kinetic scrolling will be decreased + * every deaccelaration interval. + * Default is 1. + */ + int deaccelerationStrength() const { + return m_deaccelerationStrength; + }; + + /*! + * \brief Sets the deaccelaration strength. + * \see deaccelerationStrength() + */ + void setDeaccelerationStrength(int strength) { + m_deaccelerationStrength = strength; + }; + + /*! + * \brief Returns the max value of the kinetic scrolling speed in pixels per interval. + * Default is 64. + */ + int maxKineticScrollSpeed() const { + return m_maxKineticScrollSpeed; + }; + /*! + * \brief Sets the maximum speed of kinetic scrolling in pixels per interval. + * \see maxKineticScrollSpeed() + */ + void setMaxKineticScrollSpeed(int speed) { + m_maxKineticScrollSpeed = speed; + }; + +protected: + void timerEvent(QTimerEvent *event); + void installEventFilter(QObjectList list); + +private: + struct KineticData { + typedef enum { Waiting, Pressed, Panning, KineticScroll, Stop } State; + State state; + QWidget *widget; + QWidget* pressedWidget; + QPoint pressPos; + QPoint offset; + QPoint dragPos; + QPoint speed; + QList<QEvent*> ignored; + }; + + QHash<QWidget*, KineticData*> m_kineticData; + QBasicTimer m_ticker; + + int m_scrollStartDelay; + int m_scrollStartOffset; + int m_deaccelerationInterval; + int m_deaccelerationStrength; + int m_maxKineticScrollSpeed; +}; + +#endif // QTMAEMO6KINETICSCROLLING_H diff --git a/plainqt/style/qtmaemo6pangesture.cpp b/plainqt/style/qtmaemo6pangesture.cpp deleted file mode 100644 index a0a8f32c..00000000 --- a/plainqt/style/qtmaemo6pangesture.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (directui@nokia.com) -** -** This file is part of libdui. -** -** If you have questions regarding the use of this file, please contact -** Nokia at directui@nokia.com. -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation -** and appearing in the file LICENSE.LGPL included in the packaging -** of this file. -** -****************************************************************************/ - -#include "qtmaemo6pangesture.h" - -#include <QApplication> -#include <QWidget> -#include <QMouseEvent> -#include <QAbstractScrollArea> -#include <QScrollBar> -#include <QDebug> - -void QtMaemo6PanGesture::enableOn(QWidget *w) -{ - if (w) { - w->installEventFilter(this); - ScrollState *state = new ScrollState; - state->widget = w; - state->panState = ScrollState::None; - m_activeWidgets.insert(w, state); - } -} - -bool QtMaemo6PanGesture::eventFilter(QObject *object, QEvent *event) -{ - if (!qobject_cast<QWidget *>(object)) - return false; - - QEvent::Type type = event->type(); - if (type != QEvent::MouseButtonPress && - type != QEvent::MouseButtonRelease && - type != QEvent::MouseMove) - return false; - - QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent *>(event); - if (!mouseEvent || (mouseEvent->modifiers() != Qt::NoModifier)) - return false; - - QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(object); - ScrollState *scrollState = m_activeWidgets.value(scrollArea); - if (scrollArea && scrollState) { - //return if the event is on the ignore list - if (scrollState->ignoreEvents.removeAll(event)) - return false; - - switch (scrollState->panState) { - case ScrollState::None: - if (mouseEvent->type() == QEvent::MouseButtonPress - && mouseEvent->buttons() == Qt::LeftButton) { - qDebug() << "Gesture State None Press Event"; - scrollState->pressPos = mouseEvent->pos(); - scrollState->panState = ScrollState::Pressed; - scrollState->scrollOffset = QPoint(scrollArea->horizontalScrollBar()->value(), - scrollArea->verticalScrollBar()->value()); - } - break; - case ScrollState::Pressed: - if (mouseEvent->type() == QEvent::MouseButtonRelease) { - qDebug() << "Gesture State Pressed Release Event"; - //generate new press and release event and - scrollState->panState = ScrollState::None; - - QMouseEvent *pressEvent = new QMouseEvent(QEvent::MouseButtonPress, - scrollState->pressPos, Qt::LeftButton, - Qt::LeftButton, Qt::NoModifier); - QMouseEvent *releaseEvent = new QMouseEvent(*mouseEvent); - - //these generated events must not be handled by this filter again! - scrollState->ignoreEvents << pressEvent << releaseEvent; - - QApplication::postEvent(object, pressEvent); - QApplication::postEvent(object, releaseEvent); - } - if (mouseEvent->type() == QEvent::MouseMove) { - qDebug() << "Gesture State Pressed Move Event"; - scrollState->panState = ScrollState::Scroll; - QPoint delta = mouseEvent->pos() - scrollState->pressPos; - - scrollArea->horizontalScrollBar()->setValue(scrollState->scrollOffset.x() - delta.x()); - scrollArea->verticalScrollBar()->setValue(scrollState->scrollOffset.y() - delta.y()); - } - break; - case ScrollState::Scroll: - if (mouseEvent->type() == QEvent::MouseMove) { - qDebug() << "Gesture State Scroll Move Event"; - QPoint delta = mouseEvent->pos() - scrollState->pressPos; - - scrollArea->horizontalScrollBar()->setValue(scrollState->scrollOffset.x() - delta.x()); - scrollArea->verticalScrollBar()->setValue(scrollState->scrollOffset.y() - delta.y()); - - qDebug() << "Gesture delta" << delta; - qDebug() << "ScrollBars Value" << scrollArea->horizontalScrollBar()->value() << scrollArea->verticalScrollBar()->value(); - } - if (mouseEvent->type() == QEvent::MouseButtonRelease) { - qDebug() << "Gesture State Scroll Release Event"; - scrollState->panState = ScrollState::None; - } - break; - default: - return false; - } - return true; - } else - return false; -} diff --git a/plainqt/style/qtmaemo6pangesture.h b/plainqt/style/qtmaemo6pangesture.h deleted file mode 100644 index 64538f5f..00000000 --- a/plainqt/style/qtmaemo6pangesture.h +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (directui@nokia.com) -** -** This file is part of libdui. -** -** If you have questions regarding the use of this file, please contact -** Nokia at directui@nokia.com. -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation -** and appearing in the file LICENSE.LGPL included in the packaging -** of this file. -** -****************************************************************************/ - -#ifndef QTMAEMO6PANGESTURE_H -#define QTMAEMO6PANGESTURE_H - -#include <QObject> -#include <QPoint> -#include <QList> -#include <QMap> - -class QWidget; - -/*! - * this class implements a pan gesture recognition which can be enabled on - * plain scrollareas. - * this class may be deprecated in future, because dui gestures may be used - */ -class QtMaemo6PanGesture : public QObject -{ - Q_OBJECT -public: - QtMaemo6PanGesture(QObject *parent) : QObject(parent) {}; - - /*! - * enables the pan gesture recognition onto the given widget - */ - void enableOn(QWidget *w); - - /*! \reimp */ - /* ! - * the recognition is handled here - */ - bool eventFilter(QObject *object, QEvent *event); - /*! \reimp_end */ -private: - /*! - * this struct holdes the different states when panning is active - */ - struct ScrollState { - enum PanState { None, Pressed, Scroll, PostScroll, Stop }; - PanState panState; - QPoint pressPos; - QPoint scrollOffset; - QWidget *widget; - QList<QEvent *> ignoreEvents; - }; - QMap<QWidget *, ScrollState *> m_activeWidgets; -}; - -#endif diff --git a/plainqt/style/qtmaemo6style.cpp b/plainqt/style/qtmaemo6style.cpp index 98432741..e47b4cb7 100644 --- a/plainqt/style/qtmaemo6style.cpp +++ b/plainqt/style/qtmaemo6style.cpp @@ -79,13 +79,12 @@ #include <duiwidgetfadeoutanimationstyle.h> #include <duideviceprofile.h> -#include "qtmaemo6pangesture.h" #include "qtmaemo6titlebar.h" #include "qtmaemo6dialogtitle.h" #include "qtmaemo6windowdecoration.h" #include "qtmaemo6dialogproxy.h" #include "qtmaemo6menu.h" - +#include "qtmaemo6kineticscrolling.h" //krazy:excludeall=qclasses //#include "duicontainerheader_p.h" @@ -123,8 +122,8 @@ QtMaemo6StylePrivate::QtMaemo6StylePrivate() m_isDuiInitialized(false), m_isDuiApplication(false), m_scrollBarEventFilter(0), - m_panGestureScrolling(0), - m_menuBar(0) + m_menuBar(0), + m_kinetic(0) { } @@ -155,10 +154,9 @@ void QtMaemo6StylePrivate::initDui() } m_windowEventFilter = new QtMaemo6StyleEventFilter(q); - m_panGestureScrolling = new QtMaemo6PanGesture(q); m_scrollBarEventFilter = new QtMaemo6ScrollBarEventFilter(q); m_scrollBarEventFilter->setScrollBarsAlwaysVisible(false); - m_panGestureScrolling = new QtMaemo6PanGesture(q); + m_kinetic = new QtMaemo6KineticScrolling(q); if (DuiComponentData::instance() != 0) { m_isDuiApplication = true; @@ -710,7 +708,55 @@ void QtMaemo6Style::init() // QPixmapCache::setCacheLimit( 1000 ); } +int QtMaemo6Style::kineticScrollStartDelay() const { + Q_D(const QtMaemo6Style); + return d->m_kinetic->scrollStartDelay(); +} + +void QtMaemo6Style::setKineticScrollStartDelay(int delay) { + Q_D(QtMaemo6Style); + d->m_kinetic->setScrollStartDelay(delay); +} + +int QtMaemo6Style::kineticScrollStartOffset() const { + Q_D(const QtMaemo6Style); + return d->m_kinetic->scrollStartOffset(); +} + +void QtMaemo6Style::setKineticScrollStartOffset(int offset) { + Q_D(QtMaemo6Style); + d->m_kinetic->setScrollStartOffset(offset); +} + +int QtMaemo6Style::kineticDeaccelerationInterval() const { + Q_D(const QtMaemo6Style); + return d->m_kinetic->deaccelerationInterval(); +} +void QtMaemo6Style::setKineticDeaccelerationInterval(int interval) { + Q_D(QtMaemo6Style); + d->m_kinetic->setDeaccelerationInterval(interval); +} + +int QtMaemo6Style::kineticDeaccelerationStrength() const { + Q_D(const QtMaemo6Style); + return d->m_kinetic->deaccelerationStrength(); +} + +void QtMaemo6Style::setKineticDeaccelerationStrength(int strength) { + Q_D(QtMaemo6Style); + d->m_kinetic->setDeaccelerationStrength(strength); +} + +int QtMaemo6Style::kineticMaxKineticScrollSpeed() const { + Q_D(const QtMaemo6Style); + return d->m_kinetic->maxKineticScrollSpeed(); +} + +void QtMaemo6Style::setKineticMaxKineticScrollSpeed(int speed) { + Q_D(QtMaemo6Style); + d->m_kinetic->setMaxKineticScrollSpeed(speed); +} void QtMaemo6Style::polish(QApplication *app) @@ -772,7 +818,7 @@ void QtMaemo6Style::polish(QWidget *widget) } if (QAbstractScrollArea *abstractScrollArea = qobject_cast<QAbstractScrollArea *>(widget)) { - d->m_panGestureScrolling->enableOn(abstractScrollArea); + d->m_kinetic->enableOn(abstractScrollArea); d->m_scrollBarEventFilter->enableOn(abstractScrollArea); //FIXME: public API usage //widget->setAutoFillBackground(false); diff --git a/plainqt/style/qtmaemo6style.h b/plainqt/style/qtmaemo6style.h index a01c3d9b..7aa5b52b 100644 --- a/plainqt/style/qtmaemo6style.h +++ b/plainqt/style/qtmaemo6style.h @@ -25,6 +25,8 @@ #include <QLabel> #include "qtmaemo6teststyle.h" + + #include <duiexport.h> class DuiComponentData; @@ -59,6 +61,11 @@ class DUI_EXPORT QtMaemo6Style : public QtMaemo6TestStyle Q_OBJECT Q_DECLARE_PRIVATE(QtMaemo6Style) friend class QtMaemo6StyleEventFilter; + Q_PROPERTY(int kineticScrollStartDelay READ kineticScrollStartDelay WRITE setKineticScrollStartDelay); + Q_PROPERTY(int kineticScrollStartOffset READ kineticScrollStartOffset WRITE setKineticScrollStartOffset); + Q_PROPERTY(int kineticDeaccelerationInterval READ kineticDeaccelerationInterval WRITE setKineticDeaccelerationInterval); + Q_PROPERTY(int kineticDeaccelerationStrength READ kineticDeaccelerationStrength WRITE setKineticDeaccelerationStrength); + Q_PROPERTY(int kineticMaxKineticScrollSpeed READ kineticMaxKineticScrollSpeed WRITE setKineticMaxKineticScrollSpeed); public: QtMaemo6Style(); virtual ~QtMaemo6Style(); @@ -97,8 +104,93 @@ public: const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget = 0) const; + /*! \reimp_end */ + /*! + * \brief Returns the current scroll delay in milliseconds. + * + * After a press event a move must been made within this time + * before the scrolling starts. If there is no move within this time + * the mouse press event is forwarded to the widget under the mouse. + * Default is 50ms. + * \see kineticScrollStartOffset + */ + int kineticScrollStartDelay() const; + + /*! + * \brief Sets the scroll delay in milliseconds. + * + * /see kineticScrollStartDelay() + */ + void setKineticScrollStartDelay(int delay); + + /*! + * \brief Returns the current scroll offset in milliseconds. + * + * After a press event a move must been made with at least this manhattan + * length before the scrolling starts. If there is no move within this length + * the mouse press event is forwarded to the widget under the mouse. + * Default is 5. + * \see kineticScrollStartDelay() + */ + int kineticScrollStartOffset() const; + + /*! + * \brief Sets the scroll offset in milliseconds. + * + * \see kineticScrollStartOffset() + */ + void setKineticScrollStartOffset(int offset); + + /*! + * \brief Returns the current intervall in milliseconds the deacceleration methode + * is called. + * + * After a press event a move must been made with at least this manhattan + * length before the scrolling starts. If there is no move within this length + * the mouse press event is forwarded to the widget under the mouse. + * Default is 20ms. + */ + int kineticDeaccelerationInterval() const; + + /*! + * \brief sets the deaccelaration interval in milliseconds + * + * /see kineticDeaccelerationInterval() + */ + void setKineticDeaccelerationInterval(int interval); + + /*! + * \brief Returns the current deaccelaration strength. + * + * This is the value of speed in pixels the kinetic scrolling will be decreased + * every deaccelaration interval. + * Default is 1. + */ + int kineticDeaccelerationStrength() const; + + /*! + * \brief Sets the deaccelaration strength. + * + * \see kineticDeaccelerationStrength() + */ + void setKineticDeaccelerationStrength(int strength); + + /*! + * \brief Returns the max value of the kinetic scrolling speed in pixels per interval. + * + * Default is 64. + */ + int kineticMaxKineticScrollSpeed() const; + + /*! + * \brief Sets the maximum speed of kinetic scrolling in pixels per interval. + * + * \see kineticMaxKineticScrollSpeed() + */ + void setKineticMaxKineticScrollSpeed(int speed); protected Q_SLOTS: + /*! \reimp */ QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget = 0) const; diff --git a/plainqt/style/qtmaemo6style_p.h b/plainqt/style/qtmaemo6style_p.h index 15549d26..9f573906 100644 --- a/plainqt/style/qtmaemo6style_p.h +++ b/plainqt/style/qtmaemo6style_p.h @@ -27,14 +27,13 @@ #include "qtmaemo6styleeventfilter.h" #include "qtmaemo6scrollbareventfilter.h" -class QtMaemo6PanGesture; - class DuiComponentData; class DuiWidgetController; class QToolButton; class QAction; class QStatusBar; class QMenuBar; +class QtMaemo6KineticScrolling; class QtMaemo6StylePrivate : public QtMaemo6TestStylePrivate { @@ -305,11 +304,12 @@ public: bool m_isDuiInitialized; bool m_isDuiApplication; QtMaemo6ScrollBarEventFilter *m_scrollBarEventFilter; - QtMaemo6PanGesture *m_panGestureScrolling; QtMaemo6StyleEventFilter *m_windowEventFilter; QMenuBar *m_menuBar; + QtMaemo6KineticScrolling* m_kinetic; + }; #endif diff --git a/plainqt/style/style.pri b/plainqt/style/style.pri index 2e5b34c4..bbe1fe03 100644 --- a/plainqt/style/style.pri +++ b/plainqt/style/style.pri @@ -8,7 +8,6 @@ PRIVATE_HEADERS += \ qtmaemo6teststyle.h \ qtmaemo6teststyle_p.h \ qtmaemo6style_p.h \ - qtmaemo6pangesture.h \ qtmaemo6styleeventfilter.h \ qtmaemo6scrollbareventfilter.h \ qtmaemo6styleplugin.h \ @@ -21,12 +20,12 @@ PRIVATE_HEADERS += \ qtmaemo6menuproxy.h \ qtmaemo6menu.h \ qtmaemo6submenu.h \ - qtmaemo6comboboxpopup.h + qtmaemo6comboboxpopup.h \ + qtmaemo6kineticscrolling.h SOURCES = \ qtmaemo6teststyle.cpp \ qtmaemo6style.cpp \ - qtmaemo6pangesture.cpp \ qtmaemo6styleeventfilter.cpp \ qtmaemo6scrollbareventfilter.cpp \ qtmaemo6styleplugin.cpp \ @@ -38,4 +37,5 @@ SOURCES = \ qtmaemo6menuproxy.cpp \ qtmaemo6menu.cpp \ qtmaemo6submenu.cpp \ - qtmaemo6comboboxpopup.cpp + qtmaemo6comboboxpopup.cpp \ + qtmaemo6kineticscrolling.cpp |