From 3b121044d50c15f5b82d986537b5f2ca115bc859 Mon Sep 17 00:00:00 2001 From: Akos Polster Date: Sun, 17 Oct 2010 01:12:29 +0200 Subject: [PATCH] Add Flickable. --- bookview.h | 7 +- dorian.pro | 308 ++++++++++++++++++++++++------------------------- widgets/flickable.cpp | 284 +++++++++++++++++++++++++++++++++++++++++++++ widgets/flickable.h | 80 +++++++++++++ 4 files changed, 523 insertions(+), 156 deletions(-) create mode 100755 widgets/flickable.cpp create mode 100755 widgets/flickable.h diff --git a/bookview.h b/bookview.h index e3c7700..994fe5d 100644 --- a/bookview.h +++ b/bookview.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "book.h" @@ -15,6 +16,9 @@ class QAbstractKineticScroller; /** Visual representation of a book. */ class BookView: public QWebView +#ifdef Q_OS_SYMBIAN + , public Flickable +#endif { Q_OBJECT @@ -95,10 +99,9 @@ private: bool mousePressed; int contentsHeight; /**< Last know height of the frame. */ -#ifdef Q_WS_MAEMO_5 +#if def(Q_WS_MAEMO_5) int scrollerMonitor; QAbstractKineticScroller *scroller; -#endif }; #endif // BOOKVIEW_H diff --git a/dorian.pro b/dorian.pro index 2bdb4b7..fe08054 100644 --- a/dorian.pro +++ b/dorian.pro @@ -1,154 +1,154 @@ -QT += webkit xml sql - -INCLUDEPATH += $$PWD \ - $$PWD/model \ - $$PWD/widgets - -SOURCES += \ - main.cpp \ - mainwindow.cpp \ - bookview.cpp \ - model/unzip/unzip.c \ - model/unzip/ioapi.c \ - model/extractzip.cpp \ - model/library.cpp \ - model/book.cpp \ - librarydialog.cpp \ - devtools.cpp \ - infodialog.cpp \ - widgets/translucentbutton.cpp \ - settingswindow.cpp \ - model/settings.cpp \ - bookmarksdialog.cpp \ - model/sortedlibrary.cpp \ - bookmarkinfodialog.cpp \ - widgets/dyalog.cpp \ - chaptersdialog.cpp \ - widgets/fullscreenwindow.cpp \ - trace.cpp \ - widgets/toolbuttonbox.cpp \ - model/bookfinder.cpp \ - widgets/listwindow.cpp \ - widgets/progress.cpp \ - widgets/adopterwindow.cpp \ - platform.cpp \ - model/bookdb.cpp \ - searchdialog.cpp \ - search.cpp - -HEADERS += \ - mainwindow.h \ - bookview.h \ - model/opshandler.h \ - model/unzip/unzip.h \ - model/unzip/ioapi.h \ - model/extractzip.h \ - model/library.h \ - model/book.h \ - librarydialog.h \ - devtools.h \ - infodialog.h \ - widgets/translucentbutton.h \ - settingswindow.h \ - model/settings.h \ - bookmarksdialog.h \ - model/xmlerrorhandler.h \ - model/containerhandler.h \ - model/sortedlibrary.h \ - model/ncxhandler.h \ - bookmarkinfodialog.h \ - widgets/dyalog.h \ - chaptersdialog.h \ - widgets/fullscreenwindow.h \ - trace.h \ - widgets/toolbuttonbox.h \ - model/bookfinder.h \ - widgets/listwindow.h \ - widgets/progress.h \ - widgets/adopterwindow.h \ - widgets/listview.h \ - model/xmlhandler.h \ - platform.h \ - model/bookdb.h \ - searchdialog.h \ - search.h - -RESOURCES += \ - dorian.qrc - -OTHER_FILES += \ - TODO.txt \ - pkg/acknowledgements.txt \ - pkg/maemo/postinst \ - pkg/maemo/dorian.desktop \ - pkg/maemo/control \ - pkg/maemo/changelog \ - pkg/maemo/build.sh \ - styles/night.css \ - pkg/changelog \ - pkg/maemo/build-scratchbox.sh \ - styles/sand.css \ - styles/default.css \ - pkg/version.txt \ - styles/sand.js \ - styles/night.js \ - styles/default.js \ - styles/day.js \ - www/index.html \ - pkg/maemo/autobuild.sh \ - pkg/maemo/autobuild-scratchbox.sh \ - LICENSE.txt \ - pkg/symbian/book.svg - -DEFINES += \ - USE_FILE32API \ - DORIAN_TEST_MODEL - -include(model/modeltest/modeltest.pri) - -unix { - symbian { - } else { - LIBS += -lz - } -} -win32 { - DEFINES += ZLIB_WINAPI - INCLUDEPATH += $$PWD/model/zlib - LIBS += pkg/win32/zlibstat.lib -} -symbian { - ICON = $$PWD/pkg/symbian/book.svgt - TARGET.UID3 = 0xEA633557 - # TARGET.CAPABILITY = ... - # FIXME: Add OpenC ZLIB? - INCLUDEPATH += C:/NokiaQtSDK/Symbian/SDK/src/3rdparty/zlib \ - c:/Qt/4.7.0/src/3rdparty/zlib -} -maemo5 { - QT += maemo5 dbus - isEmpty(PREFIX) { - PREFIX = /usr - } - BINDIR = $$PREFIX/bin - DATADIR =$$PREFIX/share - DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\" - - # For "make install" - - INSTALLS += target desktop icon48 iconscalable - - target.path = $$BINDIR - - desktop.path = $$DATADIR/applications/hildon - desktop.files += pkg/maemo/dorian.desktop - - icon48.path = $$DATADIR/icons/hicolor/48x48/hildon - icon48.files += pkg/maemo/icon-48/dorian.png - - iconscalable.path = $$DATADIR/icons/hicolor/scalable/hildon - iconscalable.files += pkg/maemo/icon-scalable/dorian.png -} -macx { - CONFIG += x86 -} +QT += webkit xml sql + +INCLUDEPATH += $$PWD \ + $$PWD/model \ + $$PWD/widgets + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + bookview.cpp \ + model/unzip/unzip.c \ + model/unzip/ioapi.c \ + model/extractzip.cpp \ + model/library.cpp \ + model/book.cpp \ + librarydialog.cpp \ + devtools.cpp \ + infodialog.cpp \ + widgets/translucentbutton.cpp \ + settingswindow.cpp \ + model/settings.cpp \ + bookmarksdialog.cpp \ + model/sortedlibrary.cpp \ + bookmarkinfodialog.cpp \ + widgets/dyalog.cpp \ + chaptersdialog.cpp \ + widgets/fullscreenwindow.cpp \ + trace.cpp \ + widgets/toolbuttonbox.cpp \ + model/bookfinder.cpp \ + widgets/listwindow.cpp \ + widgets/progress.cpp \ + widgets/adopterwindow.cpp \ + platform.cpp \ + model/bookdb.cpp \ + searchdialog.cpp \ + search.cpp + +HEADERS += \ + mainwindow.h \ + bookview.h \ + model/opshandler.h \ + model/unzip/unzip.h \ + model/unzip/ioapi.h \ + model/extractzip.h \ + model/library.h \ + model/book.h \ + librarydialog.h \ + devtools.h \ + infodialog.h \ + widgets/translucentbutton.h \ + settingswindow.h \ + model/settings.h \ + bookmarksdialog.h \ + model/xmlerrorhandler.h \ + model/containerhandler.h \ + model/sortedlibrary.h \ + model/ncxhandler.h \ + bookmarkinfodialog.h \ + widgets/dyalog.h \ + chaptersdialog.h \ + widgets/fullscreenwindow.h \ + trace.h \ + widgets/toolbuttonbox.h \ + model/bookfinder.h \ + widgets/listwindow.h \ + widgets/progress.h \ + widgets/adopterwindow.h \ + widgets/listview.h \ + model/xmlhandler.h \ + platform.h \ + model/bookdb.h \ + searchdialog.h \ + search.h + +RESOURCES += \ + dorian.qrc + +OTHER_FILES += \ + TODO.txt \ + pkg/acknowledgements.txt \ + pkg/maemo/postinst \ + pkg/maemo/dorian.desktop \ + pkg/maemo/control \ + pkg/maemo/changelog \ + pkg/maemo/build.sh \ + styles/night.css \ + pkg/changelog \ + pkg/maemo/build-scratchbox.sh \ + styles/sand.css \ + styles/default.css \ + pkg/version.txt \ + styles/sand.js \ + styles/night.js \ + styles/default.js \ + styles/day.js \ + www/index.html \ + pkg/maemo/autobuild.sh \ + pkg/maemo/autobuild-scratchbox.sh \ + LICENSE.txt \ + pkg/symbian/book.svg + +DEFINES += \ + USE_FILE32API + +!symbian { + DEFINES += DORIAN_TEST_MODEL + include(model/modeltest/modeltest.pri) +} + +unix { + symbian { + } else { + LIBS += -lz + } +} +win32 { + DEFINES += ZLIB_WINAPI + INCLUDEPATH += $$PWD/model/zlib + LIBS += pkg/win32/zlibstat.lib +} +symbian { + ICON = $$PWD/pkg/symbian/book.svgt + TARGET.UID3 = 0xEA633557 + # FIXME: TARGET.CAPABILITY = ... + # FIXME: Include path to OpenC ZLIB? + INCLUDEPATH += c:/Qt/4.7.0/src/3rdparty/zlib + SOURCES += widgets/flickable.cpp + HEADERS += widgets/flickable.h +} +maemo5 { + QT += maemo5 dbus + isEmpty(PREFIX) { + PREFIX = /usr + } + BINDIR = $$PREFIX/bin + DATADIR =$$PREFIX/share + DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\" + + # For "make install" + + INSTALLS += target desktop icon48 iconscalable + + target.path = $$BINDIR + + desktop.path = $$DATADIR/applications/hildon + desktop.files += pkg/maemo/dorian.desktop + + icon48.path = $$DATADIR/icons/hicolor/48x48/hildon + icon48.files += pkg/maemo/icon-48/dorian.png + + iconscalable.path = $$DATADIR/icons/hicolor/scalable/hildon + iconscalable.files += pkg/maemo/icon-scalable/dorian.png +} diff --git a/widgets/flickable.cpp b/widgets/flickable.cpp new file mode 100755 index 0000000..7841d7d --- /dev/null +++ b/widgets/flickable.cpp @@ -0,0 +1,284 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used 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. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "flickable.h" + +#include +#include + +class FlickableTicker: QObject +{ +public: + FlickableTicker(Flickable *scroller) { + m_scroller = scroller; + } + + void start(int interval) { + if (!m_timer.isActive()) + m_timer.start(interval, this); + } + + void stop() { + m_timer.stop(); + } + +protected: + void timerEvent(QTimerEvent *event) { + Q_UNUSED(event); + m_scroller->tick(); + } + +private: + Flickable *m_scroller; + QBasicTimer m_timer; +}; + +class FlickablePrivate +{ +public: + typedef enum { + Steady, + Pressed, + ManualScroll, + AutoScroll, + Stop + } State; + + State state; + int threshold; + QPoint pressPos; + QPoint offset; + QPoint delta; + QPoint speed; + FlickableTicker *ticker; + QTime timeStamp; + QWidget *target; + QList ignoreList; +}; + +Flickable::Flickable() +{ + d = new FlickablePrivate; + d->state = FlickablePrivate::Steady; + d->threshold = 10; + d->ticker = new FlickableTicker(this); + d->timeStamp = QTime::currentTime(); + d->target = 0; +} + +Flickable::~Flickable() +{ + delete d; +} + +void Flickable::setThreshold(int th) +{ + if (th >= 0) + d->threshold = th; +} + +int Flickable::threshold() const +{ + return d->threshold; +} + +void Flickable::setAcceptMouseClick(QWidget *target) +{ + d->target = target; +} + +static QPoint deaccelerate(const QPoint &speed, int a = 1, int max = 64) +{ + int x = qBound(-max, speed.x(), max); + int y = qBound(-max, speed.y(), max); + 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); +} + +void Flickable::handleMousePress(QMouseEvent *event) +{ + event->ignore(); + + if (event->button() != Qt::LeftButton) + return; + + if (d->ignoreList.removeAll(event)) + return; + + switch (d->state) { + + case FlickablePrivate::Steady: + event->accept(); + d->state = FlickablePrivate::Pressed; + d->pressPos = event->pos(); + break; + + case FlickablePrivate::AutoScroll: + event->accept(); + d->state = FlickablePrivate::Stop; + d->speed = QPoint(0, 0); + d->pressPos = event->pos(); + d->offset = scrollOffset(); + d->ticker->stop(); + break; + + default: + break; + } +} + +void Flickable::handleMouseRelease(QMouseEvent *event) +{ + event->ignore(); + + if (event->button() != Qt::LeftButton) + return; + + if (d->ignoreList.removeAll(event)) + return; + + QPoint delta; + + switch (d->state) { + + case FlickablePrivate::Pressed: + event->accept(); + d->state = FlickablePrivate::Steady; + if (d->target) { + QMouseEvent *event1 = new QMouseEvent(QEvent::MouseButtonPress, + d->pressPos, Qt::LeftButton, + Qt::LeftButton, Qt::NoModifier); + QMouseEvent *event2 = new QMouseEvent(*event); + d->ignoreList << event1; + d->ignoreList << event2; + QApplication::postEvent(d->target, event1); + QApplication::postEvent(d->target, event2); + } + break; + + case FlickablePrivate::ManualScroll: + event->accept(); + delta = event->pos() - d->pressPos; + if (d->timeStamp.elapsed() > 100) { + d->timeStamp = QTime::currentTime(); + d->speed = delta - d->delta; + d->delta = delta; + } + d->offset = scrollOffset(); + d->pressPos = event->pos(); + if (d->speed == QPoint(0, 0)) { + d->state = FlickablePrivate::Steady; + } else { + d->speed /= 4; + d->state = FlickablePrivate::AutoScroll; + d->ticker->start(20); + } + break; + + case FlickablePrivate::Stop: + event->accept(); + d->state = FlickablePrivate::Steady; + d->offset = scrollOffset(); + break; + + default: + break; + } +} + +void Flickable::handleMouseMove(QMouseEvent *event) +{ + event->ignore(); + + if (!(event->buttons() & Qt::LeftButton)) + return; + + if (d->ignoreList.removeAll(event)) + return; + + QPoint delta; + + switch (d->state) { + + case FlickablePrivate::Pressed: + case FlickablePrivate::Stop: + delta = event->pos() - d->pressPos; + if (delta.x() > d->threshold || delta.x() < -d->threshold || + delta.y() > d->threshold || delta.y() < -d->threshold) { + d->timeStamp = QTime::currentTime(); + d->state = FlickablePrivate::ManualScroll; + d->delta = QPoint(0, 0); + d->pressPos = event->pos(); + event->accept(); + } + break; + + case FlickablePrivate::ManualScroll: + event->accept(); + delta = event->pos() - d->pressPos; + setScrollOffset(d->offset - delta); + if (d->timeStamp.elapsed() > 100) { + d->timeStamp = QTime::currentTime(); + d->speed = delta - d->delta; + d->delta = delta; + } + break; + + default: + break; + } +} + +void Flickable::tick() +{ + if (d->state == FlickablePrivate:: AutoScroll) { + d->speed = deaccelerate(d->speed); + setScrollOffset(d->offset - d->speed); + d->offset = scrollOffset(); + if (d->speed == QPoint(0, 0)) { + d->state = FlickablePrivate::Steady; + d->ticker->stop(); + } + } else { + d->ticker->stop(); + } +} diff --git a/widgets/flickable.h b/widgets/flickable.h new file mode 100755 index 0000000..4211a2f --- /dev/null +++ b/widgets/flickable.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used 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. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FLICKABLE_H +#define FLICKABLE_H + +class QMouseEvent; +class QPoint; +class QWidget; + +class FlickableTicker; +class FlickablePrivate; + +class Flickable +{ +public: + + Flickable(); + virtual ~Flickable(); + + void setThreshold(int threshold); + int threshold() const; + + void setAcceptMouseClick(QWidget *target); + + void handleMousePress(QMouseEvent *event); + void handleMouseMove(QMouseEvent *event); + void handleMouseRelease(QMouseEvent *event); + +protected: + virtual QPoint scrollOffset() const = 0; + virtual void setScrollOffset(const QPoint &offset) = 0; + +private: + void tick(); + +private: + FlickablePrivate *d; + friend class FlickableTicker; +}; + +#endif // FLICKABLE_H -- 1.7.9.5