I have made the following changes intended for : CE:UX:MTF / lipstick CE:UX:MTF / lipstick-colorful-home
Please review and accept or decline. BOSS has already run some checks on this request. See the "Messages from BOSS" section below. https://build.pub.meego.com//request/show/6264 Thank You, Marko Saukko [This message was auto-generated] --- Request # 6264: Messages from BOSS: State: review at 2012-08-28T11:24:21 by bossbot Reviews: accepted by bossbot : Prechecks succeeded. new for CE-maintainers : Please replace this text with a review and approve/reject the review (not the SR). BOSS will take care of the rest Changes: submit: Project:MTF:UX / lipstick -> CE:UX:MTF / lipstick changes files: -------------- --- lipstick.changes +++ lipstick.changes @@ -0,0 +1,4 @@ +* Tue Aug 28 2012 Marko Saukko <[email protected]> - 0.3.3 +- Fixes NEMO#406: Home reads also other files than .desktop files (from Timur) +- Implement lockscreen support (from Robin) + old: ---- lipstick-0.3.1.tar.bz2 new: ---- lipstick-0.3.3.tar.bz2 spec files: ----------- --- lipstick.spec +++ lipstick.spec @@ -1,6 +1,6 @@ # # Do NOT Edit the Auto-generated Part! -# Generated by: spectacle version 0.24.1 +# Generated by: spectacle version 0.25 # Name: lipstick @@ -9,7 +9,7 @@ # << macros Summary: QML toolkit for homescreen creation -Version: 0.3.1 +Version: 0.3.3 Release: 1 Group: System/Libraries License: LGPLv2.1 @@ -21,6 +21,7 @@ BuildRequires: pkgconfig(QtCore) BuildRequires: pkgconfig(QtDeclarative) BuildRequires: pkgconfig(QtOpenGL) +BuildRequires: pkgconfig(QtSensors) BuildRequires: pkgconfig(contentaction-0.1) BuildRequires: pkgconfig(mlite) BuildRequires: pkgconfig(xcomposite) @@ -40,7 +41,7 @@ %prep -%setup -q -n %{name} +%setup -q -n %{name}-%{version} # >> setup # << setup other changes: -------------- ++++++ lipstick-0.3.1.tar.bz2 -> lipstick-0.3.3.tar.bz2 --- src/components/launcheritem.cpp +++ src/components/launcheritem.cpp @@ -20,6 +20,7 @@ #include <QFile> #include <QDir> #include <QSettings> +#include <QTimer> #include <mlite/mdesktopentry.h> #ifdef HAVE_CONTENTACTION @@ -27,6 +28,7 @@ #endif #include "launcheritem.h" +#include "xtools/homewindowmonitor.h" // Define this if you'd like to see debug messages from the launcher #ifdef DEBUG_LAUNCHER @@ -35,6 +37,28 @@ #define LAUNCHER_DEBUG(things) #endif +static bool iconNameSizeSortHelper(const QString &s1, const QString &s2) +{ + int x1 = s1.indexOf(QChar('x')); + int x2 = s2.indexOf(QChar('x')); + + if (x1 == -1) + return true; + if (x2 == -1) + return false; + + int ss1 = s1.left(x1).toInt(); + int ss2 = s2.left(x2).toInt(); + + if (!ss1) + return true; + if (!ss2) + return false; + + // The > is NOT a mistake, we need the higher res things before the lower res things + return ss1 > ss2; +} + static QString findIconHelper(const QString &pathName, const QString &icon) { QStringList extensions; @@ -78,6 +102,7 @@ return cachedPath; } + QString retval; QStringList themes = QDir("/usr/share/themes").entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot); if (!themes.isEmpty()) @@ -93,7 +118,7 @@ foreach (const QString &theme, themes) { - QString retval = findIconHelper("/usr/share/themes/" + theme, name); + retval = findIconHelper("/usr/share/themes/" + theme, name); if (!retval.isNull()) { @@ -107,7 +132,7 @@ } // they also seem to get plonked here - QString retval = findIconHelper("/usr/share/pixmaps/", name); + retval = findIconHelper("/usr/share/pixmaps/", name); if (!retval.isNull()) { @@ -118,26 +143,45 @@ } } + // I hate all application developers - retval = findIconHelper("/usr/share/icons/hicolor/64x64/", name); - if (!retval.isNull()) + // Going through all folders in here too + QStringList hiColorSizes = QDir("/usr/share/icons/hicolor").entryList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot); + // Ordering them in a way that scalable comes first and then resolutions in descending order + qSort(hiColorSizes.begin(), hiColorSizes.end(), iconNameSizeSortHelper); + + if (!hiColorSizes.isEmpty()) { - if (QFile::exists(retval)) + foreach (const QString &hiColorSize, hiColorSizes) { - settings.setValue(name, retval); - return retval; + retval = findIconHelper("/usr/share/icons/hicolor/" + hiColorSize, name); + + if (!retval.isNull()) + { + if (QFile::exists(retval)) + { + settings.setValue(name, retval); + return retval; + } + } } } + // If everything fails, return an empty string return QString(); } LauncherItem::LauncherItem(const QString &path, QObject *parent) - : QObject(parent), - _desktopEntry(new MDesktopEntry(path)) + : QObject(parent) + , _desktopEntry(new MDesktopEntry(path)) + , _isLaunching(false) { emit this->itemChanged(); + + // TODO: instead of this, match the PID of the window thumbnails with the launcher processes + // Launching animation will be disabled if the window of the launched app shows up + connect(HomeWindowMonitor::instance(), SIGNAL(isHomeWindowOnTopChanged()), this, SLOT(disableIsLaunching())); } LauncherItem::~LauncherItem() @@ -164,9 +208,21 @@ LAUNCHER_DEBUG("icon path is:" << _desktopEntry->icon()); if (_desktopEntry->icon().length() == 0) + { + LAUNCHER_DEBUG("desktop entry has empty icon setting:" << _desktopEntry->path()); + return QString(); + } + + QString path = getIconPath(_desktopEntry->icon()); + + if (path.length() == 0) + { + LAUNCHER_DEBUG("could not find icon for iconname:" << _desktopEntry->icon()); return QString(); + } - return "file://" + getIconPath(_desktopEntry->icon()); + LAUNCHER_DEBUG("icon file found for iconname:" << _desktopEntry->icon() << path); + return "file://" + path; } QStringList LauncherItem::desktopCategories() const @@ -184,7 +240,18 @@ return _desktopEntry->isValid(); } -void LauncherItem::launchApplication() const +bool LauncherItem::isLaunching() const +{ + return _isLaunching; +} + +void LauncherItem::disableIsLaunching() +{ + _isLaunching = false; + emit this->isLaunchingChanged(); +} + +void LauncherItem::launchApplication() { #if defined(HAVE_CONTENTACTION) LAUNCHER_DEBUG("launching content action for" << _desktopEntry->name()); @@ -211,4 +278,11 @@ // Launch the application QProcess::startDetached(commandText); #endif + + _isLaunching = true; + emit this->isLaunchingChanged(); + + // TODO: instead of this, match the PID of the window thumbnails with the launcher processes + // Launching animation will stop after 5 seconds + QTimer::singleShot(5000, this, SLOT(disableIsLaunching())); } --- src/components/launcheritem.h +++ src/components/launcheritem.h @@ -38,8 +38,13 @@ Q_PROPERTY(QStringList desktopCategories READ desktopCategories NOTIFY itemChanged) Q_PROPERTY(bool shouldDisplay READ shouldDisplay NOTIFY itemChanged) Q_PROPERTY(bool isValid READ isValid NOTIFY itemChanged) + Q_PROPERTY(bool isLaunching READ isLaunching NOTIFY isLaunchingChanged) QSharedPointer<MDesktopEntry> _desktopEntry; + bool _isLaunching; + +private slots: + void disableIsLaunching(); public: explicit LauncherItem(const QString &path, QObject *parent = 0); @@ -52,11 +57,13 @@ QStringList desktopCategories() const; bool shouldDisplay() const; bool isValid() const; + bool isLaunching() const; - Q_INVOKABLE void launchApplication() const; + Q_INVOKABLE void launchApplication(); signals: void itemChanged(); + void isLaunchingChanged(); }; #endif // LAUNCHERITEM_H --- src/components/launchermodel.cpp +++ src/components/launchermodel.cpp @@ -70,6 +70,10 @@ this->getList<LauncherItem>()->end(), [fileInfo](LauncherItem* item) -> bool { return item->filePath() == fileInfo.fileName(); })) { + // Skip files which are not desktop entries + if (!fileInfo.fileName().endsWith(".desktop")) + continue; + LAUNCHER_DEBUG("Creating LauncherItem for desktop entry" << fileInfo.absoluteFilePath()); LauncherItem *item = new LauncherItem(fileInfo.absoluteFilePath(), this); --- src/components/statusbar.cpp +++ src/components/statusbar.cpp @@ -22,6 +22,8 @@ #include <QDBusInterface> #include <QDBusConnection> #include <QGraphicsScene> +#include <QGraphicsSceneMouseEvent> +#include <QGraphicsSceneContextMenuEvent> #include <QGraphicsView> #include <QTimer> @@ -120,12 +122,19 @@ setFlag(QGraphicsItem::ItemHasNoContents, false); setAcceptedMouseButtons(Qt::LeftButton); setImplicitHeight(36); - QTimer::singleShot(3000, this, SLOT(initializeStatusBar())); + QTimer::singleShot(0, this, SLOT(initializeStatusBar())); } void StatusBar::initializeStatusBar() { _sharedPixmap = fetchSharedPixmap(); + + if (_sharedPixmap.isNull()) + { + QTimer::singleShot(1000, this, SLOT(initializeStatusBar())); + return; + } + setImplicitHeight(_sharedPixmap.height() / 2); updateXThings(); } @@ -166,17 +175,28 @@ int angle = isPortrait() ? 270 : 0; STATUSBAR_DEBUG("orientation angle:" << angle); + if (!this->scene() || this->scene()->views().length() == 0) + { + STATUSBAR_DEBUG("Something's not ok, trying to get back here later"); + QTimer::singleShot(0, this, SLOT(updateXThings())); + return; + } + // Stuff for X QWidget *activeWindow = this->scene()->views().at(0); Display *dpy = QX11Info::display(); + STATUSBAR_DEBUG("starting to set X properties"); + // Setting the status bar geometry atom (probably not necessary here) Atom statusBarGeometryAtom = XInternAtom(dpy, "_MEEGOTOUCH_MSTATUSBAR_GEOMETRY", False); XChangeProperty(dpy, activeWindow->effectiveWinId(), statusBarGeometryAtom, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)data, 4); + STATUSBAR_DEBUG("called XChangeProperty for _MEEGOTOUCH_MSTATUSBAR_GEOMETRY"); // Setting the orientation angle atom (sysuid uses this to determine what orientation it should draw itself) Atom orientationAngleAtom = XInternAtom(dpy, "_MEEGOTOUCH_ORIENTATION_ANGLE", False); XChangeProperty(dpy, activeWindow->effectiveWinId(), orientationAngleAtom, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&angle, 1); + STATUSBAR_DEBUG("called XChangeProperty for _MEEGOTOUCH_ORIENTATION_ANGLE"); update(); } @@ -193,12 +213,15 @@ emit isPortraitChanged(); } -void StatusBar::mousePressEvent(QGraphicsSceneMouseEvent * /*event */) +void StatusBar::mousePressEvent(QGraphicsSceneMouseEvent *event) { + event->accept(); } -void StatusBar::mouseReleaseEvent(QGraphicsSceneMouseEvent * /* event */) +void StatusBar::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + event->accept(); + QDBusInterface interface("com.meego.core.MStatusIndicatorMenu", "/statusindicatormenu", "com.meego.core.MStatusIndicatorMenu", @@ -207,27 +230,33 @@ interface.call(QDBus::NoBlock, "open"); } -void StatusBar::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /* event */) +void StatusBar::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { + event->accept(); } -void StatusBar::mouseMoveEvent(QGraphicsSceneMouseEvent * /* event */) +void StatusBar::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { + event->accept(); } -void StatusBar::hoverEnterEvent(QGraphicsSceneHoverEvent * /* event */) +void StatusBar::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { + event->accept(); } -void StatusBar::hoverMoveEvent(QGraphicsSceneHoverEvent * /* event */) +void StatusBar::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { + event->accept(); } -void StatusBar::hoverLeaveEvent(QGraphicsSceneHoverEvent * /* event */) +void StatusBar::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { + event->accept(); } -void StatusBar::contextMenuEvent(QGraphicsSceneContextMenuEvent * /* event */) +void StatusBar::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { + event->accept(); } --- src/components/statusbar.h +++ src/components/statusbar.h @@ -29,6 +29,7 @@ QPixmap _sharedPixmap; bool _isPortrait; +private slots: void updateXThings(); public: --- src/components/windowmanager.cpp +++ src/components/windowmanager.cpp @@ -21,6 +21,7 @@ WindowManager::WindowManager(QObject *parent) : QObject(parent) { + connect(HomeWindowMonitor::instance(), SIGNAL(isHomeWindowOnTopChanged()), this, SIGNAL(isHomeWindowOnTopChanged())); } void WindowManager::windowToFront(qulonglong windowId) --- src/components/windowmanager.h +++ src/components/windowmanager.h @@ -25,11 +25,16 @@ Q_OBJECT Q_DISABLE_COPY(WindowManager) + Q_PROPERTY(bool isHomeWindowOnTop READ isHomeWindowOnTop NOTIFY isHomeWindowOnTopChanged) + public: explicit WindowManager(QObject *parent = 0); Q_INVOKABLE void closeWindow(qulonglong windowId); Q_INVOKABLE void windowToFront(qulonglong windowId); - Q_INVOKABLE bool isHomeWindowOnTop(); + bool isHomeWindowOnTop(); + +signals: + void isHomeWindowOnTopChanged(); }; --- src/homeapplication.cpp +++ src/homeapplication.cpp @@ -42,8 +42,10 @@ #include "xtools/homewindowmonitor.h" #include "components/windowmanager.h" #include "components/windowinfo.h" +#include "lipsticksettings.h" +#include "lipstickdbusinterface.h" -// Define this if you'd like to see debug messages from the switcher +// Define this if you'd like to see debug messages from the home app #ifdef DEBUG_HOME #define HOME_DEBUG(things) qDebug() << Q_FUNC_INFO << things #else @@ -77,6 +79,14 @@ // Initialize the home window monitor HomeWindowMonitor::instance(); + + new LipstickDBusInterface(this); + QDBusConnection::sessionBus().registerService("org.nemomobile.lipstick"); + if (!QDBusConnection::sessionBus().registerObject("/request", this)) { + qWarning("CAN'T REGISTER DBUS"); + } else { + qDebug("DBUS REGISTERED OK"); + } } HomeApplication::~HomeApplication() @@ -84,6 +94,11 @@ delete _mainWindowInstance; } +HomeApplication *HomeApplication::instance() +{ + return qobject_cast<HomeApplication *>(QApplication::instance()); +} + void HomeApplication::addXEventListener(XEventListener *listener) { if (listener != NULL && !xEventListeners.contains(listener)) { @@ -215,6 +230,7 @@ QObject::connect(_mainWindowInstance->engine(), SIGNAL(quit()), QApplication::instance(), SLOT(quit())); _mainWindowInstance->rootContext()->setContextProperty("initialSize", QApplication::desktop()->screenGeometry(_mainWindowInstance).size()); _mainWindowInstance->rootContext()->setContextProperty("windowManager", new WindowManager(this)); + _mainWindowInstance->rootContext()->setContextProperty("LipstickSettings", LipstickSettings::instance()); // Setting the source, if present if (!_qmlPath.isEmpty()) --- src/homeapplication.h +++ src/homeapplication.h @@ -56,6 +56,8 @@ */ virtual ~HomeApplication(); + static HomeApplication *instance(); + /*! * Adds an X event listener object for this application. When X events arrive, * they are forwarded to the listener. --- src/lipstickdbusinterface.cpp +++ src/lipstickdbusinterface.cpp @@ -0,0 +1,62 @@ + +// This file is part of lipstick, a QML desktop library +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation +// and appearing in the file LICENSE.LGPL included in the packaging +// of this file. +// +// This code is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// Copyright (c) 2012, Robin Burchell <[email protected]> + +#include <QDebug> + +#include "lipstickdbusinterface.h" +#include "lipsticksettings.h" + +// Define this if you'd like to see debug messages from the dbus interface class +#ifdef DEBUG_DBUSINTERFACE +#define DBUSINTERFACE_DEBUG(things) qDebug() << Q_FUNC_INFO << things +#else +#define DBUSINTERFACE_DEBUG(things) +#endif + +LipstickDBusInterface::LipstickDBusInterface(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + LipstickSettings *settings = LipstickSettings::instance(); + connect(settings, SIGNAL(lockscreenVisibleChanged()), this, SLOT(lockscreenVisibilityChanged())); +} + +void LipstickDBusInterface::showLockScreen() +{ + DBUSINTERFACE_DEBUG("Received signal to show lockscreen"); + + LipstickSettings *settings = LipstickSettings::instance(); + settings->setLockscreenVisible(true); +} + +void LipstickDBusInterface::hideLockScreen() +{ + DBUSINTERFACE_DEBUG("Received signal to hide lockscreen"); + + LipstickSettings *settings = LipstickSettings::instance(); + settings->setLockscreenVisible(false); +} + +void LipstickDBusInterface::lockscreenVisibilityChanged() +{ + LipstickSettings *settings = LipstickSettings::instance(); + + if (!settings->lockscreenVisible()) + { + DBUSINTERFACE_DEBUG("Lockscreen unlocked, emitting signal"); + + emit screenUnlocked(); + } +} --- src/lipstickdbusinterface.h +++ src/lipstickdbusinterface.h @@ -0,0 +1,41 @@ + +// This file is part of lipstick, a QML desktop library +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation +// and appearing in the file LICENSE.LGPL included in the packaging +// of this file. +// +// This code is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// Copyright (c) 2012, Robin Burchell <[email protected]> + +#ifndef DBUSINTERFACE_H +#define DBUSINTERFACE_H + +#include <QDBusAbstractAdaptor> + +class LipstickDBusInterface : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.nemomobile.lipstick") + +public: + LipstickDBusInterface(QObject *parent); + +public slots: + Q_NOREPLY void showLockScreen(); + Q_NOREPLY void hideLockScreen(); + +private slots: + void lockscreenVisibilityChanged(); + +signals: + void screenUnlocked(); +}; + +#endif // DBUSINTERFACE_H --- src/lipsticksettings.cpp +++ src/lipsticksettings.cpp @@ -0,0 +1,90 @@ + +// This file is part of lipstick, a QML desktop library +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation +// and appearing in the file LICENSE.LGPL included in the packaging +// of this file. +// +// This code is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// Copyright (c) 2012, Robin Burchell <[email protected]> +// + +#include <QX11Info> +#include <QDeclarativeView> +#include <QApplication> +#include <QDesktopWidget> +#include <QDebug> +#include <QtSensors/QOrientationSensor> +#include <QtSensors/QOrientationReading> + +#include "lipsticksettings.h" +#include "homeapplication.h" + +#include <X11/Xatom.h> +#include <X11/Xlib.h> + +Q_GLOBAL_STATIC(LipstickSettings, settingsInstance) + +LipstickSettings::LipstickSettings() + : QObject() + , _lockscreenVisible(false) +{ +} + +LipstickSettings *LipstickSettings::instance() +{ + return settingsInstance(); +} + +bool LipstickSettings::lockscreenVisible() const +{ + return _lockscreenVisible; +} + +void LipstickSettings::setLockscreenVisible(bool lockscreenVisible) +{ + if (lockscreenVisible == _lockscreenVisible) + return; + + _lockscreenVisible = lockscreenVisible; + QDeclarativeView *view = HomeApplication::instance()->mainWindowInstance(); + + long layer = 0; + if (lockscreenVisible) { + // mcompositor searches for exactly this title when marking a window as + // a lockscreen, so make it happy + view->setWindowTitle("Screen Lock"); + layer = 2; + } else { + view->setWindowTitle("Lipstick"); + } + + // Set the stacking layer + Display *display = QX11Info::display(); + Atom stackingLayerAtom = XInternAtom(display, "_MEEGO_STACKING_LAYER", False); + if (stackingLayerAtom != None) + XChangeProperty(display, view->winId(), stackingLayerAtom, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&layer, 1); + + emit lockscreenVisibleChanged(); +} + +QSize LipstickSettings::getScreenSize() +{ + return QApplication::desktop()->screenGeometry(HomeApplication::instance()->mainWindowInstance()).size(); +} + +bool LipstickSettings::getIsInPortrait() +{ + QtMobility::QOrientationSensor sensor; + sensor.start(); + QtMobility::QOrientationReading::Orientation orientation = sensor.reading()->orientation(); + qDebug() << Q_FUNC_INFO << "current orientation is" << orientation; + sensor.stop(); + return orientation == QtMobility::QOrientationReading::TopUp; +} --- src/lipsticksettings.h +++ src/lipsticksettings.h @@ -0,0 +1,51 @@ + +// This file is part of lipstick, a QML desktop library +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License version 2.1 as published by the Free Software Foundation +// and appearing in the file LICENSE.LGPL included in the packaging +// of this file. +// +// This code is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// Copyright (c) 2012, Robin Burchell <[email protected]> + +#ifndef LIPSTICKSETTINGS_H +#define LIPSTICKSETTINGS_H + +#include <QObject> +#include <QMetaType> +#include <QSize> + +class LipstickSettings : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool lockscreenVisible READ lockscreenVisible WRITE setLockscreenVisible NOTIFY lockscreenVisibleChanged) + Q_PROPERTY(QSize screenSize READ getScreenSize NOTIFY screenSizeChanged) + + bool _lockscreenVisible; + +public: + explicit LipstickSettings(); + static LipstickSettings *instance(); + + bool lockscreenVisible() const; + void setLockscreenVisible(bool lockscreenVisible); + + QSize getScreenSize(); + Q_INVOKABLE bool getIsInPortrait(); + +signals: + void lockscreenVisibleChanged(); + void screenSizeChanged(); + +}; + +Q_DECLARE_METATYPE(LipstickSettings *) + +#endif // LIPSTICKSETTINGS_H + --- src/src.pro +++ src/src.pro @@ -38,9 +38,13 @@ xtools/xeventlistener.h \ xtools/xatomcache.h \ xtools/xwindowmanager.h \ + lipstickdbusinterface.h \ + lipsticksettings.h SOURCES += \ homeapplication.cpp \ + lipstickdbusinterface.cpp \ + lipsticksettings.cpp \ utilities/qobjectlistmodel.cpp \ xtools/homewindowmonitor.cpp \ xtools/xeventlistener.cpp \ --- src/xtools/homewindowmonitor.cpp +++ src/xtools/homewindowmonitor.cpp @@ -113,6 +113,7 @@ } } eventHandled = true; + emit this->isHomeWindowOnTopChanged(); } return eventHandled; --- src/xtools/homewindowmonitor.h +++ src/xtools/homewindowmonitor.h @@ -53,6 +53,9 @@ //! Returns true if Home is highest window excluding windows defined by ignoredWindows bool isHomeWindowOnTop(QSet<Atom> ignoredWindows) const; +signals: + void isHomeWindowOnTopChanged(); + protected: /*! * Constructor. ++++++ lipstick.yaml --- lipstick.yaml +++ lipstick.yaml @@ -1,6 +1,6 @@ Name: lipstick Summary: QML toolkit for homescreen creation -Version: 0.3.1 +Version: 0.3.3 Release: 1 Group: System/Libraries License: LGPLv2.1 @@ -13,6 +13,7 @@ - QtCore - QtDeclarative - QtOpenGL # TODO: remove + - QtSensors - contentaction-0.1 - mlite - xcomposite submit: Project:MTF:UX / lipstick-colorful-home -> CE:UX:MTF / lipstick-colorful-home changes files: -------------- --- lipstick-colorful-home.changes +++ lipstick-colorful-home.changes @@ -0,0 +1,5 @@ +* Tue Aug 28 2012 Marko Saukko <[email protected]> - 0.0.5 +- Update to version 0.0.5 +- Fixes NEMO#357: AppLauncher: give indication of app launching +- Fixes NEMO#413: lipstick-colorful-home shows only black screen on x86 + old: ---- lipstick-colorful-home-0.0.3.tar.bz2 new: ---- lipstick-colorful-home-0.0.5.tar.bz2 spec files: ----------- --- lipstick-colorful-home.spec +++ lipstick-colorful-home.spec @@ -1,6 +1,6 @@ # # Do NOT Edit the Auto-generated Part! -# Generated by: spectacle version 0.24.1 +# Generated by: spectacle version 0.25 # Name: lipstick-colorful-home @@ -9,7 +9,7 @@ # << macros Summary: A nice homescreen -Version: 0.0.3 +Version: 0.0.5 Release: 1 Group: System/GUI/Other License: BSD @@ -17,6 +17,7 @@ Source0: %{name}-%{version}.tar.bz2 Source1: lipstick.desktop Source100: lipstick-colorful-home.yaml +Requires: lipstick >= 0.3.3 BuildRequires: pkgconfig(QtCore) BuildRequires: pkgconfig(QtDeclarative) BuildRequires: pkgconfig(QtOpenGL) @@ -30,7 +31,7 @@ %prep -%setup -q -n %{name} +%setup -q -n %{name}-%{version} # >> setup # << setup other changes: -------------- ++++++ lipstick-colorful-home-0.0.3.tar.bz2 -> lipstick-colorful-home-0.0.5.tar.bz2 --- src/qml/MainScreen.qml +++ src/qml/MainScreen.qml @@ -31,12 +31,8 @@ // The item representing the main screen; size is constant Item { id: mainScreen - width: initialSize.width - height: initialSize.height - visible: false -// Component.onCompleted: { -// tabBar.currentIndex = 2 -// } + width: LipstickSettings.screenSize.width + height: LipstickSettings.screenSize.height // This is used for detecting the current device orientation and // adjusting the desktop accordingly. @@ -53,26 +49,12 @@ // The right side of the device is upwards - meaning: landscape desktop.isPortrait = false; } - - // Prevent flickering if the desktop is started in portrait, - // thus only showing it after the first orientation reading is received - if (!mainScreen.visible) - mainScreen.visible = true; } } - // If the orientation sensor doesn't work for some reason, - // this will still show the desktop anyway. - Timer { - interval: 2000 - repeat: false - triggeredOnStart: true - onTriggered: mainScreen.visible = true - } - // This is the "desktop" - the item whose size changes when the orientation changes Item { - property bool isPortrait: false + property bool isPortrait: LipstickSettings.getIsInPortrait() id: desktop anchors.top: parent.top @@ -174,7 +156,7 @@ height: pager.height columnNumber: 2 } -/* +/*y Search { id: search width: pager.width @@ -184,5 +166,11 @@ } onCurrentIndexChanged: tabBar.currentIndex = pager.currentIndex } + + Lockscreen { + height: desktop.height + width: desktop.width + z: 200 + } } } --- src/qml/components/Lockscreen.qml +++ src/qml/components/Lockscreen.qml @@ -0,0 +1,78 @@ +import QtQuick 1.1 + +Rectangle { + id: lockScreen + color: "red" + visible: LipstickSettings.lockscreenVisible + + states: [ + State { + name: "locked" + when: LipstickSettings.lockscreenVisible + PropertyChanges { + target: lockScreen + y: 0 + } + }, + State { + name: "unlocked" + when: !LipstickSettings.lockscreenVisible + PropertyChanges { + target: lockScreen + y: -lockScreen.height + } + } + ] + transitions: Transition { + PropertyAnimation { + properties: "y" + easing.type: Easing.OutBounce + duration: 400 + } + } + + MouseArea { + property int pressY: 0 + anchors.fill: parent + + onPressed: pressY = mouseY + onPositionChanged: { + var delta = pressY - mouseY + pressY = mouseY + delta + if (parent.y - delta > 0) + return + parent.y = parent.y - delta + } + onReleased: { + if (Math.abs(parent.y) > parent.height / 3) { + console.log("Going away") + + LipstickSettings.lockscreenVisible = false + } else if (LipstickSettings.lockscreenVisible) { + console.log("No dice") + parent.state = "unlocked" + parent.state = "locked" + } + } + } + + Text { + id: time + text: Qt.formatDateTime(new Date(), "hh:mm") + font.pixelSize: 130 + color: "white" + horizontalAlignment: Text.AlignHCenter + anchors.top: parent.top + width: parent.width + } + + Text { + horizontalAlignment: Text.AlignHCenter + anchors.top: time.bottom + text: Qt.formatDateTime(new Date(), "dd/MM/yyyy") + color: "white" + font.pixelSize: 50 + width: parent.width + } +} + --- src/qml/pages/AppLauncher.qml +++ src/qml/pages/AppLauncher.qml @@ -33,18 +33,20 @@ id: launcherRoot property alias cellWidth: gridview.cellWidth - contentHeight: gridview.height - anchors.topMargin: 30 - anchors.bottomMargin: 20 + contentHeight: gridview.height + 50 GridView { id: gridview cellWidth: 80 + 60 cellHeight: cellWidth width: Math.floor(parent.width / cellWidth) * cellWidth - height: contentHeight + height: gridview.contentHeight interactive: false - anchors.horizontalCenter: parent.horizontalCenter + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: 30 + } model: LauncherModel { } --- src/qml/pages/AppLauncher/LauncherItem.qml +++ src/qml/pages/AppLauncher/LauncherItem.qml @@ -32,18 +32,58 @@ Image { id: iconImage anchors { - top: parent.top horizontalCenter: parent.horizontalCenter - margins: 8 + top: parent.top + topMargin: 8 } width: 80 height: width asynchronous: true onStatusChanged: { if (status === Image.Error) { + console.log("Error loading an app icon, falling back to default."); iconImage.source = ":/images/icons/apps.png"; } } + + Connections { + target: model.object + onIsLaunchingChanged: { + if (model.object.isLaunching) { + launchAnimationStage1.start() + } + else { + if (launchAnimationStage1.running) + launchAnimationStage1.stop(); + if (launchAnimationStage2.running) + launchAnimationStage2.stop(); + + iconImage.scale = 1.0; + } + } + } + NumberAnimation on scale { + id: launchAnimationStage1 + from: 1 + to: 0.6 + duration: 700 + onCompleted: { + if (model.object.isLaunching) + launchAnimationStage2.start(); + else + iconImage.scale = 1.0; + } + } + NumberAnimation on scale { + id: launchAnimationStage2 + from: 0.6 + to: 1 + duration: 700 + onCompleted: { + if (model.object.isLaunching) + launchAnimationStage1.start(); + } + } } // Caption for the icon --- src/resources-qml.qrc +++ src/resources-qml.qrc @@ -2,6 +2,7 @@ <qresource prefix="/"> <file>qml/components/Pager.qml</file> <file>qml/components/TabBar.qml</file> + <file>qml/components/Lockscreen.qml</file> <file>qml/pages/AppLauncher.qml</file> <file>qml/pages/AppSwitcher.qml</file> <file>qml/pages/AppSwitcher/SwitcherItem.qml</file> --- src/src.pro +++ src/src.pro @@ -29,6 +29,7 @@ qml/components/Pager.qml \ qml/components/TabBar.qml \ qml/MainScreen.qml \ + qml/components/Lockscreen.qml \ qml/pages/AppSwitcher/CloseButton.qml \ qml/pages/AppLauncher/LauncherItem.qml \ qml/pages/Search.qml \ ++++++ lipstick-colorful-home.yaml --- lipstick-colorful-home.yaml +++ lipstick-colorful-home.yaml @@ -1,6 +1,6 @@ Name: lipstick-colorful-home Summary: A nice homescreen -Version: 0.0.3 +Version: 0.0.5 Release: 1 Group: System/GUI/Other License: BSD @@ -14,6 +14,8 @@ - meegotouch-home <= 1.3.2 Description: A homescreen for Nemo Mobile Builder: qmake +Requires: + - lipstick >= 0.3.3 PkgConfigBR: - QtCore - QtDeclarative
