I have made the following changes intended for :
  CE:Apps / apps-client

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/4439

Thank You,
-

[This message was auto-generated]

---

Request # 4439:

Messages from BOSS:

State: review at 2012-02-29T15:20:33 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: home:xfade:NemoApps / apps-client -> CE:Apps / apps-client
  
changes files:
--------------
--- apps-client.changes
+++ apps-client.changes
@@ -0,0 +1,3 @@
+* Wed Feb 29 2012 Niels Breet <[email protected]> - 0.9.19
+- Graphical improvements and refactoring
+

old:
----
  apps-client-0.9.18.tar.gz

new:
----
  apps-client-0.9.19.tar.gz

spec files:
-----------
--- apps-client.spec
+++ apps-client.spec
@@ -7,7 +7,7 @@
 
 Name:       apps-client
 Summary:    Apps for Nemo client
-Version:    0.9.18
+Version:    0.9.19
 Release:    1
 Group:      Applications/System
 License:    GPLv2

other changes:
--------------

++++++ apps-client-0.9.18.tar.gz -> apps-client-0.9.19.tar.gz
--- appsformeego/appsformeego.pro
+++ appsformeego/appsformeego.pro
@@ -30,7 +30,8 @@
     src/flavour.cpp \
     src/schemeservice.cpp \
     src/roles.cpp \
-    src/configuration.cpp
+    src/configuration.cpp \
+    src/datatree.cpp
 
 HEADERS += \
     src/window.h \
@@ -43,7 +44,8 @@
     src/flavour.h \
     src/schemeservice.h \
     src/roles.h \
-    src/configuration.h
+    src/configuration.h \
+    src/datatree.h
 
 OTHER_FILES += \
     qml-harmattan/main.qml \
@@ -155,7 +157,9 @@
     qml/status-installed.png \
     qml-harmattan/SettingsPage.qml \
     xdg-harmattan/splash.png \
-    qml-harmattan/CommentPage.qml
+    qml-harmattan/CommentPage.qml \
+    xdg-harmattan/org.formeego.apps-service.desktop \
+    qml/Background.qml
 
 RESOURCES += \
     qml/qml.qrc
@@ -166,7 +170,8 @@
 
 for_harmattan {
     RESOURCES += qml-harmattan/qml-harmattan.qrc
-    xdg_apps.files += xdg-harmattan/org.formeego.apps.desktop
+    xdg_apps.files += xdg-harmattan/org.formeego.apps.desktop \
+                      xdg-harmattan/org.formeego.apps-service.desktop
     xdg_icons.files += xdg-harmattan/80x80/org-formeego-apps.png
 
     dbusservice.path = /usr/share/dbus-1/services
--- appsformeego/qml-harmattan/AppsPage.qml
+++ appsformeego/qml-harmattan/AppsPage.qml
@@ -7,10 +7,16 @@
     id: appsPage
     orientationLock: PageOrientation.LockPortrait
 
-    Image {
+    Background {
+        id: background
+        anchors.fill: parent
+    }
+
+    Item {
         id: categorycombo
-        source: "combobox.png"
         anchors.top: parent.top
+        width: parent.width
+        height: 70
 
         Image {
             id: categoryIcon
@@ -23,6 +29,15 @@
                                                      : "categ48-other.png"
         }
 
+        Image {
+            anchors.verticalCenter: parent.verticalCenter
+            anchors.right: parent.right
+            anchors.rightMargin: 20
+            width: 48
+            height: 48
+            source: "combobox.png"
+        }
+
         Label {
             id: categoryName
             anchors.verticalCenter: parent.verticalCenter
@@ -34,30 +49,24 @@
             text: categorySelector.model.count > 0 ? 
categorySelector.model.get(categorySelector.selectedIndex).name
                                                    : qsTr("Loading...")
         }
+        Connections {
+            target: gears.categoriesModel
+            onReadyChanged: {
+                categorySelector.fillModel(gears.categoriesModel);
+            }
+        }
+
         MouseArea{
             anchors.fill: parent
             onClicked: {
                 if (gears.categoriesModel.count > 0)
+                {
                     categorySelector.open();
+                }
             }
         }
     }
 
-    Rectangle {
-        id: background
-        anchors.top: categorycombo.bottom
-        anchors.left: parent.left
-        anchors.right: parent.right
-        anchors.bottom: parent.bottom
-
-        gradient: Gradient {
-            GradientStop { position: 0.0; color: "#ffffff" }
-            GradientStop { position: 0.8; color: "#ffffff" }
-            //GradientStop { position: 0.801; color: "#97d5b0" }
-            GradientStop { position: 1.0; color: "#54b87c" }
-        }
-    }
-
     SortSelector {
         id: sortSelector
         anchors.top: categorycombo.bottom
@@ -121,7 +130,7 @@
         id: categorySelector
         titleText: qsTr("Choose category")
         selectedIndex: 0
-        model: fillModel(gears.categoriesModel)
+        model: catModel
         onSelectedIndexChanged: {
             gears.appListModel.category = model.get(selectedIndex).category
         }
--- appsformeego/qml-harmattan/SearchPage.qml
+++ appsformeego/qml-harmattan/SearchPage.qml
@@ -7,16 +7,9 @@
     id: searchPage
     orientationLock: PageOrientation.LockPortrait
 
-    Rectangle {
+    Background {
         id: background
         anchors.fill: parent
-
-        gradient: Gradient {
-            GradientStop { position: 0.0; color: "#ffffff" }
-            GradientStop { position: 0.8; color: "#ffffff" }
-            //GradientStop { position: 0.801; color: "#97d5b0" }
-            GradientStop { position: 1.0; color: "#54b87c" }
-        }
     }
 
     SearchField {
@@ -35,7 +28,8 @@
 
     SortSelector {
         id: sortSelector
-        anchors.top: searchField.bottom
+        anchors.top: parent.top
+        anchors.topMargin: 70
         width: parent.width
 
         onSelected: {
--- appsformeego/qml-harmattan/SettingsPage.qml
+++ appsformeego/qml-harmattan/SettingsPage.qml
@@ -21,19 +21,9 @@
     }
 
     // TODO: maybe this should be an extra component AppsForMeegoBackground
-    Rectangle {
+    Background {
         id: background
-        anchors.top: parent.top
-        anchors.left: parent.left
-        anchors.right: parent.right
-        anchors.bottom: parent.bottom
-
-        gradient: Gradient {
-            GradientStop { position: 0.0; color: "#ffffff" }
-            GradientStop { position: 0.8; color: "#ffffff" }
-            //GradientStop { position: 0.801; color: "#97d5b0" }
-            GradientStop { position: 1.0; color: "#54b87c" }
-        }
+        anchors.fill: parent
     }
 
     Flickable {
@@ -68,69 +58,71 @@
                 width: parent.width
                 height: childrenRect.height
 
-                Label {
-                    id: lblInfo
+                Column {
                     width: parent.width
-                    text: qsTr("Log in with your MeeGo.com account to post " +
-                               "comments and rate applications.")
-                    wrapMode: Text.WordWrap
-                }
+                    spacing: 20
 
-                Label {
-                    id: lblUser
-                    text: qsTr("User")
-                    font.bold: true
-                    width: parent.width * 0.4
-                    height: entryUser.height
-                    anchors.top: lblInfo.bottom
-                    anchors.topMargin: 10
-                    verticalAlignment: Text.AlignVCenter
-                }
+                    Item {
+                        width: parent.width
+                        height: childrenRect.height
 
-                Label {
-                    id: lblPassword
-                    text: qsTr("Password")
-                    font.bold: true
-                    width: parent.width * 0.4
-                    height: entryPassword.height
-                    anchors.top: lblUser.bottom
-                    anchors.topMargin: 10
-                    verticalAlignment: Text.AlignVCenter
-                }
+                        Label {
+                            id: lblInfo
+                            width: parent.width
+                            text: qsTr("Log in with your MeeGo.com account to 
post " +
+                                       "comments and rate applications.")
+                            wrapMode: Text.WordWrap
+                        }
 
-                TextField {
-                    id: entryUser
-                    inputMethodHints: Qt.ImhNoPredictiveText
-                    enableSoftwareInputPanel: true
-                    anchors.top: lblInfo.bottom
-                    anchors.left: lblUser.right
-                    anchors.right: parent.right
-                    anchors.topMargin: 10
-                }
+                        Label {
+                            id: lblUser
+                            text: qsTr("User")
+                            font.bold: true
+                            width: parent.width * 0.4
+                            height: entryUser.height
+                            anchors.top: lblInfo.bottom
+                            anchors.topMargin: 10
+                            verticalAlignment: Text.AlignVCenter
+                        }
 
-                TextField {
-                    id: entryPassword
-                    inputMethodHints: Qt.ImhHiddenText | Qt.ImhNoPredictiveText
-                    enableSoftwareInputPanel: true
-                    echoMode: TextInput.Password
-                    anchors.top: entryUser.bottom
-                    anchors.left: lblPassword.right
-                    anchors.right: parent.right
-                    anchors.topMargin: 10
-                }
+                        Label {
+                            id: lblPassword
+                            text: qsTr("Password")
+                            font.bold: true
+                            width: parent.width * 0.4
+                            height: entryPassword.height
+                            anchors.top: lblUser.bottom
+                            anchors.topMargin: 10
+                            verticalAlignment: Text.AlignVCenter
+                        }
 
-                Column {
-                    id: loginButtonsBox
-                    width: parent.width
-                    anchors.top: lblPassword.bottom
-                    anchors.topMargin: 20
-                    spacing: 20
+                        TextField {
+                            id: entryUser
+                            inputMethodHints: Qt.ImhNoPredictiveText
+                            enableSoftwareInputPanel: true
+                            anchors.top: lblInfo.bottom
+                            anchors.left: lblUser.right
+                            anchors.right: parent.right
+                            anchors.topMargin: 10
+                        }
+
+                        TextField {
+                            id: entryPassword
+                            inputMethodHints: Qt.ImhHiddenText | 
Qt.ImhNoPredictiveText
+                            enableSoftwareInputPanel: true
+                            echoMode: TextInput.Password
+                            anchors.top: entryUser.bottom
+                            anchors.left: lblPassword.right
+                            anchors.right: parent.right
+                            anchors.topMargin: 10
+                        }
+
+                    }
 
                     Button {
                         text: gears.ocsProvider.loggedIn ? qsTr("Log Out")
                                                          : qsTr("Log In")
-                        anchors.left: parent.left
-                        anchors.right: parent.right
+                        width: parent.width
                         visible: ! sectionLogin.isLoggingIn
 
                         onClicked: {
@@ -170,8 +162,7 @@
                             sectionLogin.isLoggingIn = false;
                         }
                     }
-
-                }//Login Buttons Box
+                }//Column
 
             }//Section
 
@@ -197,6 +188,7 @@
                     width: parent.width
                     spacing: 20
 
+
                     Button {
                         id: btnTesting
                         width: parent.width
@@ -227,8 +219,6 @@
                     }
 
                     Label {
-                        anchors.top: btnTesting.bottom
-                        anchors.topMargin: 12
                         width: parent.width
 
                         text: qsTr("Review Mode shows you apps waiting for " +
@@ -329,26 +319,42 @@
     Dialog {
         id: aboutDialog
 
-        title: Text {
+        title: Column {
             width: parent.width
-            height: 72
-            horizontalAlignment: Text.AlignHCenter
-            verticalAlignment: Text.AlignTop
-            text: "Apps For MeeGo"
-            color: "white"
-            font.pixelSize: 36
-            font.bold: true
+            spacing: 24
+
+            Image {
+                anchors.horizontalCenter: parent.horizontalCenter
+                source: 
"file:///usr/share/icons/hicolor/64x64/apps/org-formeego-apps.png"
+            }
+
+            Text {
+                anchors.horizontalCenter: parent.horizontalCenter
+                height: 72
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignTop
+                text: "Apps For MeeGo"
+                color: "white"
+                font.pixelSize: 36
+                font.bold: true
+            }
         }
 
         content: Text {
             width: parent.width
             text: "© 2011, 2012 Martin Grimme\n" +
                   "\n" +
+                  "\n" +
                   "Graphics by:\n" +
                   "\n" +
-                  "Manuel Kimmerle\n" +
-                  "and\n" +
-                  "DevCenter.hu"
+                  "Manuel Kimmerle and DevCenter.hu\n" +
+                  "\n" +
+                  "\n" +
+                  "Many thanks to:\n" +
+                  "\n" +
+                  "Henri Bergius, " +
+                  "Niels Breet, " +
+                  "Ferenc Szekely"
             color: "white"
             horizontalAlignment: Text.AlignHCenter
             font.pixelSize: 24
Binary files appsformeego/qml-harmattan/combobox.png and 
appsformeego/qml-harmattan/combobox.png differ
--- appsformeego/qml/Background.qml
+++ appsformeego/qml/Background.qml
@@ -0,0 +1,11 @@
+import Qt 4.7
+
+Rectangle {
+    gradient: Gradient {
+        GradientStop { position: 0.0; color: "#b4edf9" }
+        GradientStop { position: 0.1; color: "#ffffff" }
+        GradientStop { position: 0.8; color: "#ffffff" }
+        //GradientStop { position: 0.801; color: "#97d5b0" }
+        GradientStop { position: 1.0; color: "#54b87c" }
+    }
+}
--- appsformeego/qml/Gears.qml
+++ appsformeego/qml/Gears.qml
@@ -103,6 +103,10 @@
     PackageDB {
         id: myPackageDB
         provider: myOcsProvider
+
+        onEndOfTransaction: {
+            myApplication.refresh();
+        }
     }
 
     CategoriesModel {
--- appsformeego/qml/qml.qrc
+++ appsformeego/qml/qml.qrc
@@ -38,5 +38,6 @@
         <file>categ48-system.png</file>
         <file>categ48-utilities.png</file>
         <file>status-installed.png</file>
+        <file>Background.qml</file>
     </qresource>
 </RCC>
--- appsformeego/src/application.cpp
+++ appsformeego/src/application.cpp
@@ -176,6 +176,14 @@
     }
 }
 
+void Application::refresh()
+{
+    if (! myAppId.isEmpty())
+    {
+        setAppId(myAppId);
+    }
+}
+
 void Application::sendRating(uint score)
 {
     if (score > 100)
@@ -233,6 +241,10 @@
             myAppAuthor = item.author();
         }
 
+        if (item.attributes().contains("x-ratings"))
+        {
+            qDebug() << "Ratings:" << item.attribute("x-ratings");
+        }
 
         if (! item.icons().isEmpty())
         {
--- appsformeego/src/application.h
+++ appsformeego/src/application.h
@@ -63,6 +63,7 @@
     Q_INVOKABLE void launch();
     Q_INVOKABLE void sendRating(uint score);
     Q_INVOKABLE void sendComment(QString user, QString comment);
+    Q_INVOKABLE void refresh();
 
     static QString decodeOct(const QString& data);
 
--- appsformeego/src/categoriesmodel.cpp
+++ appsformeego/src/categoriesmodel.cpp
@@ -501,13 +501,15 @@
                 item->author = content.author();
             }
 
-            // the summary is 60 characters max
+            // the summary is 70 characters max
             item->summary = content.summary().isEmpty() ? 
Application::decodeOct(content.description())
                                                         : 
Application::decodeOct(content.summary());
-            if (item->summary.length() > 60)
+            int nlPos = item->summary.indexOf("\n");
+            item->summary = item->summary.trimmed().left(nlPos);
+
+            if (item->summary.length() > 70)
             {
-                int nlPos = item->summary.indexOf("\n");
-                item->summary = item->summary.left((nlPos > 0 && nlPos < 60) ? 
nlPos : 60);
+                item->summary = item->summary.left(67) + "...";
             }
 
             item->category = category;
--- appsformeego/src/configuration.h
+++ appsformeego/src/configuration.h
@@ -15,7 +15,7 @@
 
     Q_PROPERTY(bool showTesting READ showTesting WRITE setShowTesting NOTIFY 
valueChanged);
 
-    Q_PROPERTY(bool haveTestingMode READ haveTestingMode);
+    Q_PROPERTY(bool haveTestingMode READ haveTestingMode NOTIFY valueChanged);
 
 public:
     explicit Configuration(QObject *parent = 0);
--- appsformeego/src/datatree.cpp
+++ appsformeego/src/datatree.cpp
@@ -0,0 +1,248 @@
+#include "datatree.h"
+
+#include <QChar>
+#include <QDebug>
+
+DataTree::DataTree()
+{
+}
+
+DataTree::DataTree(const QString& data)
+{
+    int pos = 0;
+    parseNode(data, pos);
+}
+
+void DataTree::parseNode(const QString& data, int& pos)
+{
+    myType = readType(data, pos);
+    pos++;
+    mySize = readSize(data, pos);
+    pos++;
+
+    if (myType == ARRAY)
+    {
+        parseArray(data, pos, mySize);
+    }
+    else if (myType == STRING)
+    {
+        parseString(data, pos, mySize);
+    }
+    else if (myType == INTEGER)
+    {
+        myStringValue = QString::number(mySize);
+    }
+}
+
+void DataTree::parseArray(const QString& data, int& pos, size_t size)
+{
+    pos++; // skip {
+
+    for (size_t i = 0; i < size; i++)
+    {
+        // read key
+        DataTree keyNode;
+        keyNode.parseNode(data, pos);
+
+        // read value
+        DataTree valueNode;
+        valueNode.parseNode(data, pos);
+        myChildren[keyNode] = valueNode;
+    }
+
+    pos++; // skip }
+}
+
+void DataTree::parseString(const QString& data, int& pos, size_t size)
+{
+    pos++; // skip "
+
+    myStringValue = data.mid(pos, size);
+    pos += size;
+
+    pos++; // skip "
+    pos++; // skip ;
+}
+
+QString DataTree::toString() const
+{
+    QStringList items;
+
+    switch (myType)
+    {
+    case ARRAY:
+        items << "a";
+        break;
+    case INTEGER:
+        items << "i";
+        break;
+    default:
+        items << "s";
+        break;
+    }
+
+    items << ":" << QString::number(mySize);
+    if (myType == ARRAY)
+    {
+        items << ":{";
+        foreach (const DataTree& key, myChildren.keys())
+        {
+            items << key.toString() << myChildren[key].toString();
+        }
+        items << "}";
+    }
+    else if (myType == INTEGER)
+    {
+        items << ";";
+    }
+    else
+    {
+        items << ":\"" << myStringValue << "\";";
+    }
+
+
+    return items.join("");
+}
+
+void DataTree::dump(int indent) const
+{
+    QString indentString(indent, ' ');
+    if (myType == ARRAY)
+    {
+        qDebug() << indentString << "Array {";
+        foreach (const DataTree& keyNode, myChildren.keys())
+        {
+            qDebug() << indentString << "Key:";
+            keyNode.dump(indent + 2);
+            qDebug() << indentString << "Value:";
+            myChildren[keyNode].dump(indent + 2);
+        }
+        qDebug() << indentString << "}";
+    }
+    else if (myType == STRING)
+    {
+        qDebug() << indentString << "String {" << myStringValue << "}";
+    }
+    else if (myType == INTEGER)
+    {
+        qDebug() << indentString << "Integer {" << myStringValue << "}";
+    }
+}
+
+DataTree::NodeType DataTree::readType(const QString& data, int &pos)
+{
+    const QChar chr = data.at(pos);
+    pos++;
+
+    if (chr == 'a')
+        return ARRAY;
+    else if (chr == 'i')
+        return INTEGER;
+    else
+        return STRING;
+}
+
+size_t DataTree::readSize(const QString& data, int &pos)
+{
+    int idx1 = data.indexOf(':', pos);
+    int idx2 = data.indexOf(';', pos);
+    int idx = idx1 < idx2 ? idx1 : idx2;
+
+    if (idx != -1)
+    {
+        QString number = data.mid(pos, idx - pos);
+        pos += (idx - pos);
+        return number.toUInt();
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+QStringList DataTree::list(const QString& path) const
+{
+    QStringList parts = path.split('/', QString::SkipEmptyParts);
+
+    if (parts.count() == 0)
+    {
+        QStringList keys;
+        foreach (const DataTree& keyNode, myChildren.keys())
+        {
+            if (! keyNode.myStringValue.isNull())
+            {
+                keys << keyNode.myStringValue;
+            }
+        }
+        return keys;
+    }
+    else
+    {
+        // find key of that name
+        QString name = parts.at(0);
+        const DataTree* keyNode = findKeyNode(name);
+        if (keyNode)
+        {
+            DataTree valueNode = myChildren[*keyNode];
+            QString subPath = QStringList(parts.mid(1)).join("/");
+            return valueNode.list(subPath);
+        }
+        else
+        {
+            return QStringList();
+        }
+
+    }
+
+}
+
+QString DataTree::get(const QString& path) const
+{
+    QStringList parts = path.split('/', QString::SkipEmptyParts);
+
+    if (parts.count() == 1)
+    {
+        // find key of that name
+        QString name = parts.at(0);
+        const DataTree* keyNode = findKeyNode(name);
+        if (keyNode)
+        {
+            DataTree valueNode = myChildren[*keyNode];
+            return valueNode.myStringValue;
+        }
+        else
+        {
+            return "";
+        }
+    }
+    else
+    {
+        // find key of that name
+        QString name = parts.at(0);
+        const DataTree* keyNode = findKeyNode(name);
+        if (keyNode)
+        {
+            DataTree valueNode = myChildren[*keyNode];
+            QString subPath = QStringList(parts.mid(1)).join("/");
+            return valueNode.get(subPath);
+        }
+        else
+        {
+            return "";
+        }
+    }
+}
+
+const DataTree* DataTree::findKeyNode(const QString &name) const
+{
+    foreach (const DataTree& keyNode, myChildren.keys())
+    {
+        if (keyNode.myStringValue == name)
+        {
+            return &keyNode;
+        }
+    }
+    return 0;
+}
+
+
--- appsformeego/src/datatree.h
+++ appsformeego/src/datatree.h
@@ -0,0 +1,43 @@
+#ifndef DATATREE_H
+#define DATATREE_H
+
+#include <QMap>
+#include <QString>
+#include <QStringList>
+
+class DataTree
+{
+public:
+    enum NodeType { ARRAY, STRING, INTEGER };
+    DataTree();
+    explicit DataTree(const QString& data);
+
+    QStringList list(const QString& path) const;
+    QString get(const QString& path) const;
+
+    QString toString() const;
+
+    void dump(int indent = 0) const;
+
+    bool operator<(const DataTree& other) const
+    {
+        return myStringValue < other.myStringValue;
+    }
+
+private:
+    NodeType myType;
+    size_t mySize;
+    QMap<DataTree, DataTree> myChildren;
+    QString myStringValue;
+
+    void parseNode(const QString& data, int& pos);
+    void parseArray(const QString& data, int& pos, size_t size);
+    void parseString(const QString& data, int& pos, size_t size);
+
+    static NodeType readType(const QString& data, int& pos);
+    static size_t readSize(const QString& data, int& pos);
+
+    const DataTree* findKeyNode(const QString& name) const;
+};
+
+#endif // DATATREE_H
--- appsformeego/src/roles.cpp
+++ appsformeego/src/roles.cpp
@@ -1,203 +1,14 @@
 #include "roles.h"
-#include <QChar>
+#include "datatree.h"
 #include <QDebug>
 
-Roles::Roles()
-{
-}
-
-Roles::Roles(const QString& data)
-{
-    int pos = 0;
-    parseNode(data, pos);
-}
-
-void Roles::parseNode(const QString& data, int& pos)
-{
-    myType = readType(data, pos);
-    pos++;
-    size_t size = readSize(data, pos);
-    pos++;
-
-    if (myType == ARRAY)
-    {
-        parseArray(data, pos, size);
-    }
-    else if (myType == STRING)
-    {
-        parseString(data, pos, size);
-    }
-}
-
-void Roles::parseArray(const QString& data, int& pos, size_t size)
-{
-    pos++; // skip {
-
-    for (size_t i = 0; i < size; i++)
-    {
-        // read key
-        Roles keyNode;
-        keyNode.parseNode(data, pos);
-
-        // read value
-        Roles valueNode;
-        valueNode.parseNode(data, pos);
-        myChildren[keyNode] = valueNode;
-    }
-
-    pos++; // skip }
-}
-
-void Roles::parseString(const QString& data, int& pos, size_t size)
-{
-    pos++; // skip "
-
-    myStringValue = data.mid(pos, size);
-    pos += size;
-
-    pos++; // skip "
-    pos++; // skip ;
-}
-
-void Roles::dump(int indent) const
-{
-    QString indentString(indent, ' ');
-    if (myType == ARRAY)
-    {
-        qDebug() << indentString << "Array {";
-        foreach (const Roles& keyNode, myChildren.keys())
-        {
-            qDebug() << indentString << "Key:";
-            keyNode.dump(indent + 2);
-            qDebug() << indentString << "Value:";
-            myChildren[keyNode].dump(indent + 2);
-        }
-        qDebug() << indentString << "}";
-    }
-    else if (myType == STRING)
-    {
-        qDebug() << indentString << "String {" << myStringValue << "}";
-    }
-}
-
-Roles::NodeType Roles::readType(const QString& data, int &pos)
-{
-    const QChar chr = data.at(pos);
-    pos++;
-
-    if (chr == 'a')
-        return ARRAY;
-    else
-        return STRING;
-}
-
-size_t Roles::readSize(const QString& data, int &pos)
-{
-    int idx = data.indexOf(':', pos);
-    if (idx != -1)
-    {
-        QString number = data.mid(pos, idx - pos);
-        pos += (idx - pos);
-        return number.toUInt();
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-QStringList Roles::list(const QString& path) const
-{
-    QStringList parts = path.split('/', QString::SkipEmptyParts);
-
-    if (parts.count() == 0)
-    {
-        QStringList keys;
-        foreach (const Roles& keyNode, myChildren.keys())
-        {
-            if (! keyNode.myStringValue.isNull())
-            {
-                keys << keyNode.myStringValue;
-            }
-        }
-        return keys;
-    }
-    else
-    {
-        // find key of that name
-        QString name = parts.at(0);
-        const Roles* keyNode = findKeyNode(name);
-        if (keyNode)
-        {
-            Roles valueNode = myChildren[*keyNode];
-            QString subPath = QStringList(parts.mid(1)).join("/");
-            return valueNode.list(subPath);
-        }
-        else
-        {
-            return QStringList();
-        }
-
-    }
-
-}
-
-QString Roles::get(const QString& path) const
-{
-    QStringList parts = path.split('/', QString::SkipEmptyParts);
-
-    if (parts.count() == 1)
-    {
-        // find key of that name
-        QString name = parts.at(0);
-        const Roles* keyNode = findKeyNode(name);
-        if (keyNode)
-        {
-            Roles valueNode = myChildren[*keyNode];
-            return valueNode.myStringValue;
-        }
-        else
-        {
-            return "";
-        }
-    }
-    else
-    {
-        // find key of that name
-        QString name = parts.at(0);
-        const Roles* keyNode = findKeyNode(name);
-        if (keyNode)
-        {
-            Roles valueNode = myChildren[*keyNode];
-            QString subPath = QStringList(parts.mid(1)).join("/");
-            return valueNode.get(subPath);
-        }
-        else
-        {
-            return "";
-        }
-    }
-}
-
-const Roles* Roles::findKeyNode(const QString &name) const
-{
-    foreach (const Roles& keyNode, myChildren.keys())
-    {
-        if (keyNode.myStringValue == name)
-        {
-            return &keyNode;
-        }
-    }
-    return 0;
-}
-
 /* Convenience method for finding the authors on apps.formeego.org.
  */
-QString Roles::findAuthor(const QString &rolesData)
+QString Roles::findAuthor(const QString& rolesData)
 {
     qDebug() << "parsing x-roles" << rolesData;
 
-    Roles roles(rolesData);
+    DataTree roles(rolesData);
     QStringList users = roles.list("downloader/users");
     qDebug() << "found authors" << users;
 
@@ -210,3 +21,12 @@
         return users.at(0) + " et al.";
     }
 }
+
+void Roles::test(const QString &data)
+{
+    DataTree t(data);
+    qDebug() << "from data:" << data;
+    //t.dump();
+    qDebug() << "from tree:" << t.toString();
+    qDebug() << data.length() << ", " << t.toString().length();
+}
--- appsformeego/src/roles.h
+++ appsformeego/src/roles.h
@@ -1,42 +1,13 @@
 #ifndef ROLES_H
 #define ROLES_H
 
-#include <QMap>
 #include <QString>
-#include <QStringList>
 
 class Roles
 {
 public:
-    enum NodeType { ARRAY, STRING };
-    Roles();
-    explicit Roles(const QString& data);
-
-    QStringList list(const QString& path) const;
-    QString get(const QString& path) const;
-
-    void dump(int indent = 0) const;
-
-    bool operator<(const Roles& other) const
-    {
-        return myStringValue < other.myStringValue;
-    }
-
-    static QString findAuthor(const QString &rolesData);
-
-private:
-    NodeType myType;
-    QMap<Roles, Roles> myChildren;
-    QString myStringValue;
-
-    void parseNode(const QString& data, int& pos);
-    void parseArray(const QString& data, int& pos, size_t size);
-    void parseString(const QString& data, int& pos, size_t size);
-
-    static NodeType readType(const QString& data, int& pos);
-    static size_t readSize(const QString& data, int& pos);
-
-    const Roles* findKeyNode(const QString& name) const;
+    static QString findAuthor(const QString& rolesData);
+    static void test(const QString& data);
 };
 
 #endif // ROLES_H
--- appsformeego/xdg-harmattan/org.formeego.apps-service.desktop
+++ appsformeego/xdg-harmattan/org.formeego.apps-service.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Type=Application
+Name=Open In Apps
+Icon=/usr/share/icons/hicolor/64x64/apps/org-formeego-apps.png
+MimeType=x-maemo-urischeme/apps;
+X-Maemo-Service=org.formeego.apps
+X-Maemo-Method=org.formeego.apps.install
+NotShowIn=X-MeeGo;
+
--- appsformeego/xdg-harmattan/org.formeego.apps.desktop
+++ appsformeego/xdg-harmattan/org.formeego.apps.desktop
@@ -1,10 +1,7 @@
 [Desktop Entry]
-Version=1.0
 Type=Application
 Name=Apps
-Comment=MeeGo Community Apps
-Exec=/usr/bin/invoker --single-instance 
--splash=/opt/org.formeego.apps/splash.png --type=e 
/opt/org.formeego.apps/bin/appsformeego
 Icon=/usr/share/icons/hicolor/64x64/apps/org-formeego-apps.png
-MimeType=x-maemo-urischeme/apps;
-X-Maemo-Service=org.formeego.apps
-X-Maemo-Method=org.formeego.apps.install
+Exec=/usr/bin/invoker --single-instance 
--splash=/opt/org.formeego.apps/splash.png --type=e 
/opt/org.formeego.apps/bin/appsformeego
+Categories=X-MeeGo;
+OnlyShowIn=X-MeeGo;
Binary files appsformeego/xdg-harmattan/splash.png and 
appsformeego/xdg-harmattan/splash.png differ

++++++ apps-client.yaml
--- apps-client.yaml
+++ apps-client.yaml
@@ -1,6 +1,6 @@
 Name: apps-client
 Summary: Apps for Nemo client
-Version: 0.9.18
+Version: 0.9.19
 Release: 1
 Group: Applications/System
 License: GPLv2



Reply via email to