initial import
authorDavid Solbach <david@katze.home>
Sun, 3 Oct 2010 08:34:41 +0000 (10:34 +0200)
committerDavid Solbach <david@katze.home>
Sun, 3 Oct 2010 08:34:41 +0000 (10:34 +0200)
37 files changed:
BundesligaWidget.pro [new file with mode: 0644]
Icons/Bayern.png [new file with mode: 0644]
Icons/Bremen.png [new file with mode: 0644]
Icons/Dortmund.png [new file with mode: 0644]
Icons/Frankfurt.png [new file with mode: 0644]
Icons/Freiburg.png [new file with mode: 0644]
Icons/Hamburg.png [new file with mode: 0644]
Icons/Hannover.png [new file with mode: 0644]
Icons/Hoffenheim.png [new file with mode: 0644]
Icons/Kaiserslautern.png [new file with mode: 0644]
Icons/Köln.png [new file with mode: 0644]
Icons/Leverkusen.png [new file with mode: 0644]
Icons/Mainz.png [new file with mode: 0644]
Icons/Mönchengladbach.png [new file with mode: 0644]
Icons/Nürnberg.png [new file with mode: 0644]
Icons/Schalke.png [new file with mode: 0644]
Icons/St.Pauli.png [new file with mode: 0644]
Icons/Stuttgart.png [new file with mode: 0644]
Icons/Wolfsburg.png [new file with mode: 0644]
bundesligawidget.desktop [new file with mode: 0644]
qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.cpp [new file with mode: 0644]
qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.h [new file with mode: 0644]
qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.pri [new file with mode: 0644]
resources.qrc [new file with mode: 0644]
src/backendkicker.cpp [new file with mode: 0644]
src/backendkicker.h [new file with mode: 0644]
src/livescores.cpp [new file with mode: 0644]
src/livescores.h [new file with mode: 0644]
src/main.cpp [new file with mode: 0644]
src/mainwidget.cpp [new file with mode: 0644]
src/mainwidget.h [new file with mode: 0644]
src/match.cpp [new file with mode: 0644]
src/match.h [new file with mode: 0644]
src/matchdaymodel.cpp [new file with mode: 0644]
src/matchdaymodel.h [new file with mode: 0644]
src/scoretable.cpp [new file with mode: 0644]
src/scoretable.h [new file with mode: 0644]

diff --git a/BundesligaWidget.pro b/BundesligaWidget.pro
new file mode 100644 (file)
index 0000000..af9ee39
--- /dev/null
@@ -0,0 +1,26 @@
+include (./qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.pri)
+
+QT += network
+
+OTHER_FILES += \
+    bundesligawidget.desktop
+
+HEADERS += \
+    src/livescores.h \
+    src/match.h \
+    src/backendkicker.h \
+    src/mainwidget.h \
+    src/matchdaymodel.h \
+    src/scoretable.h
+
+SOURCES += \
+    src/main.cpp \
+    src/livescores.cpp \
+    src/match.cpp \
+    src/backendkicker.cpp \
+    src/mainwidget.cpp \
+    src/matchdaymodel.cpp \
+    src/scoretable.cpp
+
+RESOURCES += \
+    resources.qrc
diff --git a/Icons/Bayern.png b/Icons/Bayern.png
new file mode 100644 (file)
index 0000000..5504680
Binary files /dev/null and b/Icons/Bayern.png differ
diff --git a/Icons/Bremen.png b/Icons/Bremen.png
new file mode 100644 (file)
index 0000000..6b608f6
Binary files /dev/null and b/Icons/Bremen.png differ
diff --git a/Icons/Dortmund.png b/Icons/Dortmund.png
new file mode 100644 (file)
index 0000000..c809b71
Binary files /dev/null and b/Icons/Dortmund.png differ
diff --git a/Icons/Frankfurt.png b/Icons/Frankfurt.png
new file mode 100644 (file)
index 0000000..4ef34d1
Binary files /dev/null and b/Icons/Frankfurt.png differ
diff --git a/Icons/Freiburg.png b/Icons/Freiburg.png
new file mode 100644 (file)
index 0000000..7831a7c
Binary files /dev/null and b/Icons/Freiburg.png differ
diff --git a/Icons/Hamburg.png b/Icons/Hamburg.png
new file mode 100644 (file)
index 0000000..dc6112a
Binary files /dev/null and b/Icons/Hamburg.png differ
diff --git a/Icons/Hannover.png b/Icons/Hannover.png
new file mode 100644 (file)
index 0000000..564fc62
Binary files /dev/null and b/Icons/Hannover.png differ
diff --git a/Icons/Hoffenheim.png b/Icons/Hoffenheim.png
new file mode 100644 (file)
index 0000000..4442849
Binary files /dev/null and b/Icons/Hoffenheim.png differ
diff --git a/Icons/Kaiserslautern.png b/Icons/Kaiserslautern.png
new file mode 100644 (file)
index 0000000..9e9e85e
Binary files /dev/null and b/Icons/Kaiserslautern.png differ
diff --git a/Icons/Köln.png b/Icons/Köln.png
new file mode 100644 (file)
index 0000000..ba32a3a
Binary files /dev/null and "b/Icons/K\303\266ln.png" differ
diff --git a/Icons/Leverkusen.png b/Icons/Leverkusen.png
new file mode 100644 (file)
index 0000000..c52ed7d
Binary files /dev/null and b/Icons/Leverkusen.png differ
diff --git a/Icons/Mainz.png b/Icons/Mainz.png
new file mode 100644 (file)
index 0000000..092c6cc
Binary files /dev/null and b/Icons/Mainz.png differ
diff --git a/Icons/Mönchengladbach.png b/Icons/Mönchengladbach.png
new file mode 100644 (file)
index 0000000..79bd857
Binary files /dev/null and "b/Icons/M\303\266nchengladbach.png" differ
diff --git a/Icons/Nürnberg.png b/Icons/Nürnberg.png
new file mode 100644 (file)
index 0000000..4e12c80
Binary files /dev/null and "b/Icons/N\303\274rnberg.png" differ
diff --git a/Icons/Schalke.png b/Icons/Schalke.png
new file mode 100644 (file)
index 0000000..f85290b
Binary files /dev/null and b/Icons/Schalke.png differ
diff --git a/Icons/St.Pauli.png b/Icons/St.Pauli.png
new file mode 100644 (file)
index 0000000..7d26859
Binary files /dev/null and b/Icons/St.Pauli.png differ
diff --git a/Icons/Stuttgart.png b/Icons/Stuttgart.png
new file mode 100644 (file)
index 0000000..a85845e
Binary files /dev/null and b/Icons/Stuttgart.png differ
diff --git a/Icons/Wolfsburg.png b/Icons/Wolfsburg.png
new file mode 100644 (file)
index 0000000..bb45dc3
Binary files /dev/null and b/Icons/Wolfsburg.png differ
diff --git a/bundesligawidget.desktop b/bundesligawidget.desktop
new file mode 100644 (file)
index 0000000..eaa82ed
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Bundesliga Widget
+Comment=Live scores of the German Bundesliga.
+Type=qt
+X-Path=BundesligaWidget
+X-Multiple-Instances=false
+X-home-applet-minwidth=400
+X-home-applet-minheight=250
+Name[en_US]=Live scores of the German Bundesliga.
+Name[de_DE]=Aktuelle Ergebnisse der Bundesliga.
diff --git a/qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.cpp b/qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.cpp
new file mode 100644 (file)
index 0000000..ddd962d
--- /dev/null
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmaemo5homescreenadaptor.h"
+
+#include <QtCore/qsocketnotifier.h>
+#include <QtCore/qpointer.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qx11info_x11.h>
+#include <QtGui/qwidget.h>
+#include <QtGui/qevent.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+static QCoreApplication::EventFilter oldEventFilter;
+static QList<QMaemo5HomescreenAdaptor *> allDesktopItems;
+
+static Atom atomByName(const char *name)
+{
+    Atom atom = XInternAtom(QX11Info::display(), name, False);
+    if (!atom)
+        qWarning("Unable to obtain %s atom. This class requires a running Hildon session.", name);
+
+    return atom;
+}
+
+enum HomescreenAtoms
+{
+    HildonAppletId               = 0,
+    NetWmWindowType              = 1,
+    Utf8String                   = 2,
+    HildonTypeHomeApplet         = 3,
+    HildonAppletSettings         = 4,
+    HildonAppletShowSettings     = 5,
+    HildonAppletOnCurrentDesktop = 6,
+    EnumCount                    = 7
+};
+
+static Atom hsAtoms[EnumCount] = { 0, 0, 0, 0, 0, 0, 0 };
+
+static void initAtoms()
+{
+    hsAtoms[HildonAppletId] = atomByName("_HILDON_APPLET_ID");
+    hsAtoms[NetWmWindowType] = atomByName("_NET_WM_WINDOW_TYPE");
+    hsAtoms[Utf8String] = atomByName("UTF8_STRING");
+    hsAtoms[HildonTypeHomeApplet] = atomByName("_HILDON_WM_WINDOW_TYPE_HOME_APPLET");
+    hsAtoms[HildonAppletSettings] = atomByName("_HILDON_APPLET_SETTINGS");
+    hsAtoms[HildonAppletShowSettings] = atomByName("_HILDON_APPLET_SHOW_SETTINGS");
+    hsAtoms[HildonAppletOnCurrentDesktop] = atomByName("_HILDON_APPLET_ON_CURRENT_DESKTOP");
+}
+
+/*! \class QMaemo5HomescreenAdaptor
+
+    \brief The QMaemo5HomescreenAdaptor flags a top-level QWidget as homescreen widget
+
+    QMaemo5HomescreenAdaptor is used in conjunction with the Qt for Maemo homescreen
+    loader. It evaluates the two command line arguments "-plugin-id" and "-write-pipe"
+    to set up a Qt top-level widget as Maemo 5 homescreen widget.
+
+    Note: By default, the widget will have a black background. In order to make the
+    widget transparent, set the Qt::WA_TranslucentBackground widget attribute.
+
+    Example:
+
+    \code
+    QLabel *label = new QLabel("Hello Homescreen");
+    new QMaemo5HomescreenAdaptor(label);
+    label->show();
+    \endcode
+
+    Maemo 5 supports homescreen widgets with settings dialogs. To use it, set
+    the settingsAvailable() property and show a settings dialog when the
+    settingsRequested() signal is emitted.
+
+    Maemo 5 supports more than one homescreen. In order to determine whether
+    the homescreen widget is on the currently visible homescreen, connect to
+    the homescreenChanged() signal.
+*/
+
+/*! \property QMaemo5HomescreenAdaptor::settingsAvailable
+
+    Set this property to true if the widget can make use of a settings dialog,
+    otherwise to false. When this property is set to true, the Maemo 5 homescreen
+    renders a small settings icon on top of the homescreen widget when the
+    user enters the desktop menu. When the user clicks that settings icon, the
+    settingsRequested() signal is emitted.
+
+    The default is false.
+
+    \sa settingsRequested()
+ */
+
+/*! \fn void settingsRequested()
+
+    This signal is emitted every time the homescreen widget's settings icon is
+    invoked by the user. Note that this icon is only visible when the settingsAvailable()
+    property is set.
+
+    \sa settingsAvailable()
+ */
+
+/*! \fn void homescreenChanged(bool isOnCurrentHomescreen)
+
+    This is signal is emitted when current homescreen changes and the homescreen
+    widget becomes visible or invisible. The \a isOnCurrentHomescreen argument
+    indicates whether the homescreen widget is on the current homescreen or not.
+
+    This signal can be used to start/stop background processing in order to save
+    battery life.
+ */
+
+/*!
+    Constructs a new QMaemo5HomescreenAdaptor for the given \a widget.
+
+    Note: The widget must be a top-level widget, and must not be reparented
+    during the lifetime of this adaptor.
+
+    Note: \a widget is also the parent of this class, if the widget is destroyed,
+    so is this adaptor.
+ */
+QMaemo5HomescreenAdaptor::QMaemo5HomescreenAdaptor(QWidget *widget)
+    : QObject(widget),
+      hasSettings(false)
+{
+    Q_ASSERT(widget->isWindow());
+
+    if (!hsAtoms[0])
+        initAtoms();
+
+    Display *display = QX11Info::display();
+
+    const QStringList args = QApplication::arguments();
+
+    // parse the command line arguments.
+    int idx;
+    if ((idx = args.indexOf(QLatin1String("-plugin-id"))) != -1) {
+        appletId = args.value(idx + 1);
+        const QByteArray pluginId = appletId.toUtf8();
+        if (!pluginId.isEmpty()) {
+            XChangeProperty(display,
+                    widget->winId(),
+                    hsAtoms[HildonAppletId],
+                    hsAtoms[Utf8String], 8, PropModeReplace,
+                    reinterpret_cast<const unsigned char *>(pluginId.constData()),
+                    pluginId.length());
+        }
+    }
+    if ((idx = args.indexOf(QLatin1String("-write-pipe"))) != -1) {
+        bool ok;
+        int sockId = args.value(idx + 1).toInt(&ok);
+        if (ok) {
+            socketNotifier = new QSocketNotifier(sockId, QSocketNotifier::Exception, this);
+            connect(socketNotifier, SIGNAL(activated(int)), this, SLOT(socketException()));
+        }
+    }
+
+    // set the X11 atoms to flag our widget as homescreen widget
+    if (!appletId.isEmpty()) {
+        XChangeProperty(display,
+                widget->winId(),
+                hsAtoms[NetWmWindowType],
+                XA_ATOM, 32, PropModeReplace,
+                reinterpret_cast<const unsigned char *>(&hsAtoms[HildonTypeHomeApplet]),
+                1);
+
+        updateStatus();
+
+        // --- make this window a child of root
+        XSetTransientForHint(display, widget->winId(),
+                             RootWindow(display, widget->x11Info().screen()));
+
+        // --- add an x11 event filter
+        if (!oldEventFilter)
+            oldEventFilter = QCoreApplication::instance()->setEventFilter(applicationEventFilter);
+
+        allDesktopItems.append(this);
+
+        // --- set WM input hints indicating that we don't want focus events
+        XWMHints *h = XGetWMHints(display, widget->winId());
+        XWMHints wm_hints;
+        if (!h) {
+            memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
+            h = &wm_hints;
+        }
+        h->flags |= InputHint;
+        h->input = False;
+
+        XSetWMHints(display, widget->winId(), h);
+        if (h != &wm_hints)
+            XFree(h);
+
+        widget->setMouseTracking(true);
+    }
+}
+
+QMaemo5HomescreenAdaptor::~QMaemo5HomescreenAdaptor()
+{
+    allDesktopItems.removeOne(this);
+}
+
+/*! \internal */
+void QMaemo5HomescreenAdaptor::updateStatus()
+{
+    if (appletId.isEmpty())
+        return;
+
+    Display *display = QX11Info::display();
+
+    // Set or remove settings property
+    if (hasSettings)
+        XChangeProperty(display,
+                appletWidget()->winId(),
+                hsAtoms[HildonAppletSettings],
+                XA_CARDINAL, 32, PropModeReplace,
+                (const unsigned char *) &(hasSettings), 1);
+    else
+        XDeleteProperty(display,
+                appletWidget()->winId(),
+                hsAtoms[HildonAppletSettings]);
+}
+
+/*! \internal */
+void QMaemo5HomescreenAdaptor::socketException()
+{
+    socketNotifier->setEnabled(false);
+    appletWidget()->close();
+}
+
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
+{
+    return QCoreApplication::sendSpontaneousEvent(receiver, event);
+}
+
+
+
+/*! \internal */
+bool QMaemo5HomescreenAdaptor::applicationEventFilter(void *message, long *result)
+{
+    static QPointer<QWidget> lastMouseWidget;
+    bool retval = false;
+
+    if (oldEventFilter)
+        retval = oldEventFilter(message, result);
+
+    if (allDesktopItems.isEmpty())
+        return retval;
+
+    XEvent *ev = reinterpret_cast<XEvent *>(message);
+
+    // Generate a mouse release for a leave Notify (as we don't get the mouse release from X11)
+    if (ev->type == ButtonPress) {
+        QPoint globalPos( ev->xbutton.x_root, ev->xbutton.y_root);
+        QWidget *widget = QWidget::find((WId)ev->xany.window);
+        if (widget) {
+            lastMouseWidget = widget->childAt(widget->mapFromGlobal(globalPos));
+            if (!lastMouseWidget)
+                lastMouseWidget = widget;
+        }
+
+    } else if (ev->type == ButtonRelease) {
+        lastMouseWidget = 0;
+
+    } else if (ev->type == LeaveNotify) {
+        if (lastMouseWidget) {
+            // create a mouse up event that lies in Nirvana.
+            QPoint pos(-1000, -1000);
+            QMouseEvent e(QEvent::MouseButtonRelease, pos, pos, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
+            qt_sendSpontaneousEvent(lastMouseWidget, &e);
+            lastMouseWidget = 0;
+       }
+
+    } else if (ev->type == ClientMessage) {
+        XClientMessageEvent *cm = (XClientMessageEvent *)message;
+        if (cm->message_type == hsAtoms[HildonAppletShowSettings]) {
+            for (int i = 0; i < allDesktopItems.count(); ++i) {
+                if (allDesktopItems.at(i)->appletWidget()->winId() == ev->xproperty.window) {
+                    emit allDesktopItems.at(i)->settingsRequested();
+                    retval = true;
+                }
+            }
+        }
+    } else if (ev->type == PropertyNotify) {
+        if (ev->xproperty.atom == hsAtoms[HildonAppletOnCurrentDesktop]) {
+            for (int i = 0; i < allDesktopItems.count(); ++i) {
+                if (allDesktopItems.at(i)->appletWidget()->winId() == ev->xproperty.window) {
+                    emit allDesktopItems.at(i)->homescreenChanged(ev->xproperty.window == 0);
+                    retval = true;
+                }
+            }
+        }
+    }
+
+    return retval;
+}
+
diff --git a/qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.h b/qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.h
new file mode 100644 (file)
index 0000000..9270649
--- /dev/null
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMAEMO5HOMESCREENADAPTOR_H
+#define QMAEMO5HOMESCREENADAPTOR_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qpointer.h>
+#include <QtGui/qwidget.h>
+
+class QWidget;
+class QSocketNotifier;
+
+class QMaemo5HomescreenAdaptor : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(bool settingsAvailable READ settingsAvailable WRITE setSettingsAvailable)
+
+public:
+    QMaemo5HomescreenAdaptor(QWidget *widget);
+    ~QMaemo5HomescreenAdaptor();
+
+    inline void setSettingsAvailable(bool available)
+    {
+        hasSettings = available;
+        updateStatus();
+    }
+
+    inline bool settingsAvailable() const
+    {
+        return hasSettings;
+    }
+
+Q_SIGNALS:
+    void settingsRequested();
+    void homescreenChanged(bool isOnCurrentHomescreen);
+
+private Q_SLOTS:
+    void socketException();
+
+private:
+    inline QWidget *appletWidget() const { return static_cast<QWidget *>(parent()); }
+
+    void updateStatus();
+
+    static bool applicationEventFilter(void *message, long *result);
+
+    bool hasSettings;
+    QString appletId;
+    QSocketNotifier *socketNotifier;
+};
+
+#endif
diff --git a/qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.pri b/qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.pri
new file mode 100644 (file)
index 0000000..73d41c3
--- /dev/null
@@ -0,0 +1,4 @@
+HEADERS += $$PWD/qmaemo5homescreenadaptor.h
+SOURCES += $$PWD/qmaemo5homescreenadaptor.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/resources.qrc b/resources.qrc
new file mode 100644 (file)
index 0000000..7bbfdf3
--- /dev/null
@@ -0,0 +1,22 @@
+<RCC>
+    <qresource prefix="/">
+        <file>Icons/Bayern.png</file>
+        <file>Icons/Bremen.png</file>
+        <file>Icons/Dortmund.png</file>
+        <file>Icons/Frankfurt.png</file>
+        <file>Icons/Freiburg.png</file>
+        <file>Icons/Hamburg.png</file>
+        <file>Icons/Hannover.png</file>
+        <file>Icons/Hoffenheim.png</file>
+        <file>Icons/Kaiserslautern.png</file>
+        <file>Icons/Köln.png</file>
+        <file>Icons/Leverkusen.png</file>
+        <file>Icons/Mainz.png</file>
+        <file>Icons/Mönchengladbach.png</file>
+        <file>Icons/Nürnberg.png</file>
+        <file>Icons/Schalke.png</file>
+        <file>Icons/St.Pauli.png</file>
+        <file>Icons/Stuttgart.png</file>
+        <file>Icons/Wolfsburg.png</file>
+    </qresource>
+</RCC>
diff --git a/src/backendkicker.cpp b/src/backendkicker.cpp
new file mode 100644 (file)
index 0000000..8c44c4c
--- /dev/null
@@ -0,0 +1,193 @@
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtNetwork/QNetworkRequest>
+#include <QUrl>
+#include <QRegExp>
+#include <QDebug>
+#include <QStringList>
+#include <QDateTime>
+
+#include "backendkicker.h"
+#include "livescores.h"
+
+BackendKicker::BackendKicker(QObject *parent) :
+    QObject(parent)
+{
+    this->update();
+}
+
+Match* BackendKicker::getMatch(QString hometeam, QString awayteam)
+{
+    QListIterator<Match*> iter(m_matchlist);
+    Match*        match;
+
+    while (iter.hasNext()) {
+        match = iter.next();
+        if (match->awayteam() == awayteam &&
+            match->hometeam() == hometeam) {
+            return match;
+        }
+    }
+
+    match = new Match(hometeam, awayteam, this);
+    m_matchlist.append(match);
+
+    emit matchListChanged();
+
+    return match;
+}
+
+QList<Match*> BackendKicker::matchList()
+{
+    return m_matchlist;
+}
+
+static QDateTime parseDate(QString datehtml)
+{
+    static QDateTime    lastParsedDate;
+    QStringList         tokens;
+    QDate               date;
+
+    int month, day, hour, minute;
+
+    //qDebug() << "parseDate in: " << datehtml;
+
+    tokens = datehtml.split(QRegExp("[>.&;:<\"]"), QString::SkipEmptyParts);
+    date = QDate::currentDate();
+
+    qDebug() << tokens;
+    if (tokens.count() < 6) {
+        return lastParsedDate;
+    }
+
+    month  = (tokens.at(2)).toInt();
+    day    = (tokens.at(1)).toInt();
+    hour   = (tokens.at(4)).toInt();
+    minute = (tokens.at(5)).toInt();
+
+    lastParsedDate =  QDateTime(QDate(date.year(), month, day),
+                                QTime(hour, minute));
+
+    return lastParsedDate;
+}
+
+static QString parseTeam(QString teamhtml)
+{
+    QString team;
+
+    //qDebug() << "parseTeam in: " << teamhtml;
+
+    teamhtml.truncate(teamhtml.indexOf("</a>"));
+    team = teamhtml.mid(teamhtml.lastIndexOf(">") + 1);
+
+    qDebug() << "parseTeam out: " << team;
+    return team;
+}
+
+static int parseScore(QString scorehtml, bool home, bool firsthalf)
+{
+    int         score = -1;
+    int         index = 0;
+    QStringList tokens;
+
+    qDebug() << "parseScore in: " << scorehtml;
+
+    tokens = scorehtml.split(QRegExp("[>&();:<]"), QString::SkipEmptyParts);
+    qDebug() << tokens;
+
+    index = 1;
+    if (!home)      { index++;    }
+    if (firsthalf)  { index += 3; }
+
+    score = tokens.at(index).toInt();
+
+    qDebug() << "parseScore out: " << score;
+
+    return score;
+}
+
+void BackendKicker::parsePage (QString htmlstr)
+{
+    QStringList     rawmatches;
+    QString         hometeam, awayteam, tmp;
+    QRegExp         rx;
+    QDateTime       date;
+    Match*          match;
+
+    int             pos     = 0;
+    int             count   = 0;
+    int             homescore, awayscore;
+    int             homescorefh, awayscorefh;
+
+
+    //qDebug() << "parsePage in: " << htmlstr;
+
+    rx.setPattern("<td class=\"first\">(.*)<td class=\"aligncenter last\">");
+    rx.setMinimal(true);
+    while ((pos = rx.indexIn(htmlstr, pos)) != -1) {
+         ++count;
+         rawmatches.append(htmlstr.mid(pos, rx.matchedLength()));
+         qDebug() << "MATCH " << count << ":" << htmlstr.mid(pos, rx.matchedLength()) << "\n\n";
+         pos += rx.matchedLength();
+     }
+
+    rx.setPattern("<td.*>(.*)</td>");
+
+    QStringList::iterator i;
+    for (i = rawmatches.begin(); i != rawmatches.end(); ++i) {
+        pos = 0;
+        count = 0;
+        while ((pos = rx.indexIn(*i, pos)) != -1) {
+             ++count;
+             tmp = (*i).mid(pos, rx.matchedLength());
+             pos += rx.matchedLength();
+             switch (count) {
+             case 2: // date
+                 date = parseDate(tmp);
+                 break;
+             case 3: // hometeam
+                 hometeam = parseTeam(tmp);
+                 break;
+             case 5: // awayteam
+                 awayteam = parseTeam(tmp);
+                 break;
+             case 6: // scores
+                 homescore   = parseScore(tmp, true, false);
+                 homescorefh = parseScore(tmp, true, true);
+                 awayscore   = parseScore(tmp, false, false);
+                 awayscorefh = parseScore(tmp, false, true);
+                 break;
+             default:
+                ;;
+             }
+        }
+        match = getMatch(hometeam, awayteam);
+        match->setScore(homescore, awayscore);
+    }
+
+
+}
+
+void BackendKicker::update()
+{
+    QString URL = "http://www.kicker.de/news/fussball/bundesliga/spieltag/1-bundesliga/2010-11/spieltag.html";
+
+    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
+    connect(manager, SIGNAL(finished(QNetworkReply*)),
+            this, SLOT(dlndFinished(QNetworkReply*)));
+
+    qDebug() << "URL: " << URL;
+    manager->get(QNetworkRequest(QUrl(URL)));
+}
+
+void BackendKicker::dlndFinished(QNetworkReply *reply)
+{
+    QString         rawdata;
+
+    if (reply->error() != QNetworkReply::NoError) {
+        // TODO proper user friendly error handling here!
+        qDebug() << "dlnd failed: error: " << reply->error();
+    }
+
+    rawdata = reply->readAll();
+    parsePage(rawdata);
+}
diff --git a/src/backendkicker.h b/src/backendkicker.h
new file mode 100644 (file)
index 0000000..77d9705
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef BACKENDKICKER_H
+#define BACKENDKICKER_H
+
+#include <QObject>
+#include <QNetworkReply>
+#include "livescores.h"
+
+class BackendKicker : public QObject
+{
+    Q_OBJECT
+private:
+    QList<Match*> m_matchlist;
+
+    void parsePage (QString htmlstr);
+
+public:
+    explicit BackendKicker(QObject *parent = 0);
+
+    Match*        getMatch(QString hometeam, QString awayteam);
+
+    QList<Match*> matchList();
+
+signals:
+    void matchListChanged(void);
+
+private slots:
+    void dlndFinished(QNetworkReply *reply);
+
+public slots:
+    void update();
+};
+
+#endif // BACKENDKICKER_H
diff --git a/src/livescores.cpp b/src/livescores.cpp
new file mode 100644 (file)
index 0000000..a86c0e2
--- /dev/null
@@ -0,0 +1,22 @@
+#include "livescores.h"
+#include "match.h"
+#include "QDate"
+
+
+
+LiveScores::LiveScores(QObject *parent) :
+    QObject(parent)
+{
+
+
+}
+
+
+QList<Match*> LiveScores::getMatchList()
+{
+
+
+    return m_matchlist;
+}
+
+
diff --git a/src/livescores.h b/src/livescores.h
new file mode 100644 (file)
index 0000000..1c14d16
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef LIVESCORES_H
+#define LIVESCORES_H
+
+#include <QObject>
+#include "match.h"
+
+class LiveScores : public QObject
+{
+    Q_OBJECT
+
+private:
+    QList<Match*>   m_matchlist;
+
+public:
+    explicit LiveScores(QObject *parent = 0);
+
+    Match*        getMatch(QString hometeam, QString awayteam);
+    QList<Match*> getMatchList();
+
+signals:
+
+public slots:
+
+};
+
+#endif // LIVESCORES_H
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644 (file)
index 0000000..3035873
--- /dev/null
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmaemo5homescreenadaptor.h"
+#include "backendkicker.h"
+
+#include <QtGui>
+#include <QLabel>
+#include <src/mainwidget.h>
+
+int main(int argc, char *argv[])
+{
+    // enforce native graphics system for now due to a bug in transparency handling
+    // you can remove this line if you only target PR 1.2
+    QApplication::setGraphicsSystem("native");
+    QApplication app(argc, argv);
+    MainWidget mw;
+
+    QMaemo5HomescreenAdaptor *adaptor = new QMaemo5HomescreenAdaptor(&mw);
+    adaptor->setSettingsAvailable(true);
+    QObject::connect(adaptor, SIGNAL(settingsRequested()), &mw, SLOT(showSettingsDialog()));
+
+    mw.show();
+    app.exec();
+}
+
diff --git a/src/mainwidget.cpp b/src/mainwidget.cpp
new file mode 100644 (file)
index 0000000..739e621
--- /dev/null
@@ -0,0 +1,18 @@
+#include <QVBoxLayout>
+
+#include "mainwidget.h"
+
+MainWidget::MainWidget(QWidget *parent) :
+    QWidget(parent)
+{
+    QVBoxLayout layout;
+
+    this->setAttribute(Qt::WA_TranslucentBackground);
+
+    layout.addWidget(&m_scoretbl);
+
+    this->setLayout(&layout);
+
+
+    this->setAutoFillBackground(false);
+}
diff --git a/src/mainwidget.h b/src/mainwidget.h
new file mode 100644 (file)
index 0000000..87c8e7f
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef MAINWIDGET_H
+#define MAINWIDGET_H
+
+#include <QWidget>
+#include "scoretable.h"
+
+
+class MainWidget : public QWidget
+{
+    Q_OBJECT
+private:
+    ScoreTable m_scoretbl;
+
+public:
+    explicit MainWidget(QWidget *parent = 0);
+
+signals:
+
+public slots:
+
+};
+
+#endif // MAINWIDGET_H
diff --git a/src/match.cpp b/src/match.cpp
new file mode 100644 (file)
index 0000000..8d9efea
--- /dev/null
@@ -0,0 +1,38 @@
+#include "match.h"
+
+Match::Match(QString hometeam, QString awayteam, QObject *parent) :
+    QObject(parent)
+{
+    m_hometeam = hometeam;
+    m_awayteam = awayteam;
+
+    m_awayEmblem = getEmblemByName(awayteam);
+    m_homeEmblem = getEmblemByName(hometeam);
+}
+
+QIcon Match::getEmblemByName(QString team)
+{
+    QIcon i;
+
+    i = QIcon(":/Icons/Frankfurt.png");
+    return i;
+}
+
+void Match::setScore(int home, int away)
+{
+    bool changed;
+
+    if (m_homescore != home) {
+        m_homescore = home;
+        changed = true;
+    }
+
+    if (m_awayscore != away) {
+        m_awayscore = away;
+        changed = true;
+    }
+
+    if (changed) {
+        emit scoreChanged(home, away);
+    }
+}
diff --git a/src/match.h b/src/match.h
new file mode 100644 (file)
index 0000000..e65d486
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef MATCH_H
+#define MATCH_H
+
+#include <QIcon>
+#include <QObject>
+#include <QDateTime>
+
+class Match : public QObject
+{
+    Q_OBJECT
+
+private:
+    QDateTime m_date;
+    QIcon     m_homeEmblem;
+    QIcon     m_awayEmblem;
+    QString   m_hometeam;
+    QString   m_awayteam;
+    int       m_homescore;
+    int       m_homescorefh;
+    int       m_awayscore;
+    int       m_awayscorefh;
+    bool      m_FirstHalfFinished;
+
+    QIcon     getEmblemByName(QString team);
+
+public:
+    explicit Match(QString hometeam, QString awayteam, QObject *parent = 0);
+
+    void setScore(int home, int away);
+    void setFirstHalfFinished(bool finished);
+
+    QString hometeam()    {return m_hometeam;}
+    QString awayteam()    {return m_awayteam;}
+    QIcon   homeEmblem()  {return m_homeEmblem;}
+    QIcon   awayEmblem()  {return m_awayEmblem;}
+
+    int     homescore() {return m_homescore;}
+    int     awayscore() {return m_awayscore;}
+
+
+
+signals:
+    void scoreChanged(int homescore, int awayscore);
+
+
+public slots:
+
+};
+
+#endif // MATCH_H
diff --git a/src/matchdaymodel.cpp b/src/matchdaymodel.cpp
new file mode 100644 (file)
index 0000000..970dec4
--- /dev/null
@@ -0,0 +1,149 @@
+#include "matchdaymodel.h"
+#include <QColor>
+#include <QFontMetrics>
+#include <QFont>
+#include <QIcon>
+
+MatchDayModel::MatchDayModel(QObject *parent) :
+    QAbstractTableModel(parent)
+{
+    backendkicker = new BackendKicker(this);
+
+    connect(backendkicker, SIGNAL(matchListChanged()),
+            this, SLOT(onMatchListChanged()));
+
+}
+
+int MatchDayModel::rowCount(const QModelIndex& index) const
+{
+    int count = backendkicker->matchList().count();
+
+    return count;
+}
+
+int MatchDayModel::columnCount(const QModelIndex& index) const
+{
+    return 7;
+}
+
+QVariant MatchDayModel::data(const QModelIndex& index, int role) const
+{
+    Match*       match;
+    QFont        f;
+    QSize        s;
+    QIcon        i;
+
+    f.setPixelSize(14);
+
+    if ((match = backendkicker->matchList().at(index.row())) == NULL) {
+        return QVariant(QVariant::Invalid);
+    }
+
+    // DisplayRole
+    switch (role) {
+    case Qt::DecorationRole:
+        switch (index.column()) {
+        case AwayIcon:
+            i = match->awayEmblem().pixmap(25,25);
+            break;
+        case HomeIcon:
+            i = match->homeEmblem().pixmap(25,25);
+            break;
+        }
+        return i;
+        break;
+
+    case Qt::DisplayRole:
+        switch (index.column()) {
+        case AwayIcon:
+            return match->awayEmblem();
+            break;
+        case AwayTeam:
+            return match->awayteam();
+            break;
+        case AwayScore:
+            return match->awayscore();
+            break;
+        case HomeIcon:
+            return match->homeEmblem();
+            break;
+        case HomeTeam:
+            return match->hometeam();
+            break;
+        case HomeScore:
+            return match->homescore();
+            break;
+        default:
+            return QVariant(QVariant::Invalid);
+            break;
+        }
+        break;
+
+    case Qt::SizeHintRole:
+        s.setHeight(25);
+        switch (index.column()) {
+        case AwayIcon:
+            s.setWidth(29);
+            break;
+        case AwayTeam:
+            s.setWidth(120);
+            break;
+        case AwayScore:
+            s.setWidth(4);
+            break;
+        case HomeIcon:
+            s.setWidth(29);
+            break;
+        case HomeTeam:
+            s.setWidth(120);
+            break;
+        case HomeScore:
+            s.setWidth(4);
+            break;
+        case Seperator:
+            s.setWidth(3);
+            break;
+        default:
+            return QVariant(QVariant::Invalid);
+            break;
+        }
+        return s;
+        break;
+
+    case Qt::BackgroundRole:
+        return QColor(0, 0, 0, 120);
+        break;
+
+    case Qt::TextAlignmentRole:
+        if (index.column() < 3) {
+            return 0x0002 | 0x0080;
+        } else if (index.column() > 3) {
+            return 0x0001 | 0x0080;
+        } else {
+            return Qt::AlignCenter;
+        }
+        break;
+    case Qt::FontRole:
+
+
+        return f;
+
+    default:
+        return QVariant(QVariant::Invalid);
+    }
+}
+
+
+// only adds for now
+void MatchDayModel::onMatchListChanged(void)
+{
+    beginInsertRows(QModelIndex(),
+                    rowCount(QModelIndex()),
+                    rowCount(QModelIndex()));
+    endInsertRows();
+
+    // invalidate complete data
+    emit dataChanged(index(0, 0),
+                     index(rowCount(QModelIndex()) - 1, columnCount(QModelIndex()) - 1));
+
+}
diff --git a/src/matchdaymodel.h b/src/matchdaymodel.h
new file mode 100644 (file)
index 0000000..8005e57
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef MATCHDAYMODEL_H
+#define MATCHDAYMODEL_H
+
+#include <QAbstractTableModel>
+#include <QFontMetrics>
+
+#include "backendkicker.h"
+
+class MatchDayModel : public QAbstractTableModel
+{
+    Q_OBJECT
+
+    enum {
+        HomeIcon  = 0,
+        HomeTeam  = 1,
+        HomeScore = 2,
+        Seperator = 3,
+        AwayScore = 4,
+        AwayTeam  = 5,
+        AwayIcon  = 6
+    };
+
+private:
+    BackendKicker*  backendkicker;
+
+public:
+    explicit MatchDayModel(QObject *parent = 0);
+
+    int rowCount(const QModelIndex& index) const;
+    int columnCount(const QModelIndex& index) const;
+    QVariant data(const QModelIndex& index, int role) const;
+
+signals:
+
+
+protected slots:
+    void onMatchListChanged(void);
+
+public slots:
+
+};
+
+#endif // MATCHDAYMODEL_H
diff --git a/src/scoretable.cpp b/src/scoretable.cpp
new file mode 100644 (file)
index 0000000..2b5f1c3
--- /dev/null
@@ -0,0 +1,54 @@
+#include <QHeaderView>
+#include <QDebug>
+#include <QRect>
+
+#include "scoretable.h"
+#include "matchdaymodel.h"
+
+ScoreTable::ScoreTable(QWidget *parent) :
+    QTableView(parent)
+{
+    this->setAttribute(Qt::WA_TranslucentBackground);
+    this->setModel(new MatchDayModel(this));
+    this->setSelectionMode(QAbstractItemView::NoSelection);
+
+    //this->verticalHeader()->hide();
+    this->verticalHeader()->setStretchLastSection(false);
+    this->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+    this->verticalHeader()->setMinimumSectionSize(1);
+
+    //this->horizontalHeader()->hide();
+    this->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+    this->horizontalHeader()->setMinimumSectionSize(1);
+
+    qDebug() << "Min VertHeaderSize: " << this->verticalHeader()->minimumSectionSize();
+
+
+    this->viewport()->setAutoFillBackground(false);
+    this->setShowGrid(false);
+}
+
+QSize ScoreTable::sizeHint() const
+{
+    QSize i;
+
+    i = (QSize(this->horizontalHeader()->width(),
+               this->verticalHeader()->height()));
+
+    return i;
+}
+
+void ScoreTable::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+    QTableView::dataChanged(topLeft, bottomRight);
+
+    qDebug() << "QTBV CR Size: " << this->childrenRect().size();
+    qDebug() << "QTBVVP CR Size: " << this->childrenRect().size();
+
+
+    this->viewport()->resize(QSize(this->horizontalHeader()->width(),
+                                   this->verticalHeader()->height()));
+
+    updateGeometry();
+
+}
diff --git a/src/scoretable.h b/src/scoretable.h
new file mode 100644 (file)
index 0000000..3232a0c
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef SCORETABLE_H
+#define SCORETABLE_H
+
+#include <QTableView>
+
+class ScoreTable : public QTableView
+{
+    Q_OBJECT
+public:
+    explicit ScoreTable(QWidget *parent = 0);
+    QSize sizeHint() const;
+
+signals:
+
+protected slots:
+    void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+
+};
+
+#endif // SCORETABLE_H