From: Max Lapan Date: Sun, 7 Mar 2010 16:38:46 +0000 (+0300) Subject: REquired infrastructure for Qt desktop plugin. X-Git-Tag: v0.1~70 X-Git-Url: http://vcs.maemo.org/git/?a=commitdiff_plain;h=ced1b56be40a82b0c83bbf939a1f8ce098dd7377;hp=14bf56e0c6fc74b9710fe2605e6012b9e2c08bcb;p=yandex-traffic REquired infrastructure for Qt desktop plugin. --- diff --git a/README b/README index e69de29..39e564d 100644 --- a/README +++ b/README @@ -0,0 +1,7 @@ +Desktop widget for maemo which displays traffic information from Yandex.Maps. + +Source code of this program can be distributed according to GPL license. + +All bug repots, patches, donations, etc could be sent to max.lapan@gmail.com + +Copyright (c) 2009, Max Lapan \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..075f0f7 --- /dev/null +++ b/main.cpp @@ -0,0 +1,18 @@ +#include "qmaemo5homescreenadaptor.h" +#include "mainwidget.hpp" + + +int main(int argc, char *argv[]) +{ + QApplication::setGraphicsSystem ("native"); + QApplication app (argc, argv); + MainWidget w; + QMaemo5HomescreenAdaptor *adaptor = new QMaemo5HomescreenAdaptor (&w); + + adaptor->setSettingsAvailable (true); + + w.show (); + + return app.exec (); +} + diff --git a/mainwidget.hpp b/mainwidget.hpp new file mode 100644 index 0000000..5298de5 --- /dev/null +++ b/mainwidget.hpp @@ -0,0 +1,23 @@ +#ifndef __MAINWIDGET_H__ +#define __MAINWIDGET_H__ + +#include + +class MainWidget : public QLabel +{ + Q_OBJECT +public: + MainWidget () + : QLabel (tr ("Hello, World")) + { + setAlignment(Qt::AlignCenter); + setAttribute(Qt::WA_TranslucentBackground); + } + + QSize sizeHint() const + { + return 2 * QLabel::sizeHint(); + } +}; + +#endif /* __MAINWIDGET_H__ */ diff --git a/qmaemo5homescreenadaptor.cpp b/qmaemo5homescreenadaptor.cpp new file mode 100644 index 0000000..b473fea --- /dev/null +++ b/qmaemo5homescreenadaptor.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** 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 + +#include +#include +#include + +#include +#include + +static QCoreApplication::EventFilter oldEventFilter; +static QList 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(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(&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); + } +} + +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(); +} + +/*! \internal */ +bool QMaemo5HomescreenAdaptor::applicationEventFilter(void *message, long *result) +{ + bool retval = false; + + if (oldEventFilter) + retval = oldEventFilter(message, result); + + if (allDesktopItems.isEmpty()) + return retval; + + XEvent *ev = reinterpret_cast(message); + + 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.h b/qmaemo5homescreenadaptor.h new file mode 100644 index 0000000..68c4d5b --- /dev/null +++ b/qmaemo5homescreenadaptor.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 +#include + +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(parent()); } + + void updateStatus(); + + static bool applicationEventFilter(void *message, long *result); + + bool hasSettings; + QString appletId; + QSocketNotifier *socketNotifier; +}; + +#endif diff --git a/yandex-traffic-widget.desktop b/yandex-traffic-widget.desktop new file mode 100644 index 0000000..9120f05 --- /dev/null +++ b/yandex-traffic-widget.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Yandex.Traffic +Comment=Widget wich displays Yandex.Traffic information +Type=qt +X-Path=yandex-traffic-widget +X-Multiple-Instances=false +X-home-applet-minwidth=100 +X-home-applet-minheight=72 +Name[en_US]=Yandex.Traffic widget diff --git a/yandex-traffic-widget.pro b/yandex-traffic-widget.pro new file mode 100644 index 0000000..9a239ea --- /dev/null +++ b/yandex-traffic-widget.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +SOURCES += qmaemo5homescreenadaptor.cpp +HEADERS += qmaemo5homescreenadaptor.h + +SOURCES += main.cpp +HEADERS += mainwidget.hpp + +desktop.path = /usr/share/applications/hildon-home +desktop.files = yandex-traffic-widget.desktop + +target.path = /usr/lib/hildon-desktop +INSTALLS += target desktop