Add Flickable.
authorAkos Polster <akos@pipacs.com>
Sat, 16 Oct 2010 23:12:29 +0000 (01:12 +0200)
committerAkos Polster <akos@pipacs.com>
Sat, 16 Oct 2010 23:12:29 +0000 (01:12 +0200)
bookview.h
dorian.pro
widgets/flickable.cpp [new file with mode: 0755]
widgets/flickable.h [new file with mode: 0755]

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