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

Thank You,
-

[This message was auto-generated]

---

Request # 4368:

Messages from BOSS:

State: review at 2012-02-16T11:40:13 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 @@
+* Thu Feb 16 2012 Niels Breet <[email protected]> - 0.9.18
+- Add rating
+

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

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

spec files:
-----------
--- apps-client.spec
+++ apps-client.spec
@@ -1,13 +1,13 @@
 # 
 # Do NOT Edit the Auto-generated Part!
-# Generated by: spectacle version 0.23
+# Generated by: spectacle version 0.22
 # 
 # >> macros
 # << macros
 
 Name:       apps-client
 Summary:    Apps for Nemo client
-Version:    0.9.16
+Version:    0.9.18
 Release:    1
 Group:      Applications/System
 License:    GPLv2

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

++++++ apps-client-0.9.16.tar.gz -> apps-client-0.9.18.tar.gz
--- appsformeego/qml-harmattan/ApplicationPage.qml
+++ appsformeego/qml-harmattan/ApplicationPage.qml
@@ -26,7 +26,11 @@
         for (var i = 0; i < comments.length; i++)
         {
             console.log("adding comment: " + comments[i]);
-            commentModel.append({"comment": comments[i]});
+            var parts = gears.splitComment(comments[i]);
+            commentModel.append({"user": parts[0],
+                                 "date": parts[1],
+                                 "version": parts[2],
+                                 "comment": parts[3]});
         }
 
         return commentModel;
@@ -108,11 +112,28 @@
                 anchors.left: parent.left
                 anchors.right: parent.right
                 anchors.margins: 25
-                height: 48
+                height: 36
                 filled: "star-filled.png"
                 unfilled: "star.png"
                 maximum: 5
                 percents: gears.application.appRating
+                interactive: false
+
+                MouseArea {
+                    anchors.fill: parent
+                    onClicked: {
+                        if (gears.ocsProvider.loggedIn)
+                        {
+                            commentPage.haveComments = false;
+                            pageStack.push(commentPage);
+                        }
+                        else
+                        {
+                            errorDialog.message = qsTr("Please login to rate 
this application.");
+                            errorDialog.open();
+                        }
+                    }
+                }
             }
         }// black half
 
@@ -242,15 +263,11 @@
                 Button {
                     id: btnComment
                     width: parent.width
-                    visible: gears.isLoggedIn
+                    visible: gears.ocsProvider.loggedIn
                     text: qsTr("Write a Comment")
 
-                    Component {
-                        id: commentPage
-                        CommentPage { }
-                    }
-
                     onClicked: {
+                        commentPage.haveComments = true;
                         pageStack.push(commentPage);
                     }
                 }
@@ -265,13 +282,46 @@
                 Repeater {
                     id: commentRepeater
                     model: makeCommentModel(gears.application.appComments)
-                    delegate: Text {
-                        text: comment
+                    delegate: Column {
                         width: commentList.width
-                        font.pixelSize: 20
-                        color: "#000000"
-                        wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+                        spacing: 4
+
+                        Text {
+                            text: user + " (version " + version + ")"
+                            width: parent.width
+                            font.pixelSize: 20
+                            font.bold: true
+                            color: "#313131"
+                        }
+
+                        Rectangle {
+                            radius: 6
+                            color: "#e0e0e0"
+                            width: parent.width
+                            height: childrenRect.height + 8
+
+                            Text {
+                                x: 4
+                                y: 4
+                                text: comment
+                                width: parent.width - 8
+                                font.pixelSize: 20
+                                color: "#000000"
+                                wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+                            }
+                        }
+
+                        Text {
+                            text: date
+                            width: parent.width
+                            horizontalAlignment: Text.AlignRight
+                            font.pixelSize: 16
+                            font.italic: true
+                            color: "#313131"
+                        }
+
                     }
+
                 }
             }
 
@@ -299,6 +349,11 @@
     }
 
 
+    CommentPage {
+        id: commentPage
+    }
+
+
     Page {
         id: screenshotsPage
         orientationLock: PageOrientation.LockPortrait
@@ -351,4 +406,39 @@
             }
         }
     }
+
+
+    // TODO: this dialog should be shared among the pages
+    Dialog {
+        id: errorDialog
+        property alias message: lblMessage.text
+
+        title: Text {
+            width: parent.width
+            height: 72
+            horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignTop
+            text: ""
+            color: "white"
+            font.pixelSize: 36
+            font.bold: true
+        }
+
+        content: Text {
+            id: lblMessage
+            width: parent.width
+            height: 72
+            color: "white"
+            horizontalAlignment: Text.AlignHCenter
+            font.pixelSize: 24
+        }
+
+        buttons: Button {
+            text: "OK"
+            onClicked: {
+                errorDialog.accept();
+            }
+        }
+    }
+
 }
--- appsformeego/qml-harmattan/CommentPage.qml
+++ appsformeego/qml-harmattan/CommentPage.qml
@@ -3,6 +3,8 @@
 
 Page {
 
+    property bool haveComments: true
+
     orientationLock: PageOrientation.LockPortrait
     anchors.fill: parent
 
@@ -12,29 +14,69 @@
 
         spacing: 12
 
-        // TODO: place rating here
+        Label {
+            width: parent.width
+            font.bold: true
+            text: "Rating"
+        }
+
+        Rater {
+            id: rater
+
+            anchors.left: parent.left
+            anchors.right: parent.right
+            anchors.margins: 25
+            height: 48
+            filled: "star-filled.png"
+            unfilled: "star.png"
+            maximum: 5
+            percents: 0
+            interactive: true
+
+            Text {
+                anchors.centerIn: parent
+                text: qsTr("unrated")
+                font.pixelSize: 32
+                font.bold: true
+                font.italic: true
+                visible: parent.percents == 0
+            }
+        }
 
         Label {
             width: parent.width
             font.bold: true
-            text: "Your Comment"
+            text: "Comment"
+            visible: haveComments
         }
 
         TextArea {
             id: commentBox
             width: parent.width
             height: 200
+            placeholderText: qsTr("Please enter a comment")
+            visible: haveComments
         }
 
         Button {
-            id: btnSendComment
+            id: btnCommit
             width: parent.width
-            text: qsTr("Send Comment")
+            text: qsTr("Commit")
+            enabled: rater.percents > 0 || commentBox.text != ""
 
             onClicked: {
-                gears.application.sendComment(gears.configuration.loginUser,
-                                              commentBox.text);
+                if (commentBox.text != "")
+                {
+                    
gears.application.sendComment(gears.configuration.loginUser,
+                                                  commentBox.text);
+                }
+                if (rater.percents > 0)
+                {
+                    gears.application.sendRating(rater.percents);
+                }
+
                 pageStack.pop();
+                rater.percents = 0;
                 commentBox.text = "";
             }
         }
@@ -47,6 +89,7 @@
             iconId: "icon-m-toolbar-back"
             onClicked:{
                 pageStack.pop();
+                rater.percents = 0;
                 commentBox.text = "";
             }
         }
--- appsformeego/qml-harmattan/SettingsPage.qml
+++ appsformeego/qml-harmattan/SettingsPage.qml
@@ -6,6 +6,20 @@
     id: settingsPage
     orientationLock: PageOrientation.LockPortrait
 
+    Component.onCompleted: {
+        entryUser.text = gears.configuration.loginUser;
+        entryPassword.text = gears.configuration.loginPassword;
+    }
+
+
+    Connections {
+        target: gears.ocsProvider
+        onLoginError: {
+            errorDialog.message = message;
+            errorDialog.open();
+        }
+    }
+
     // TODO: maybe this should be an extra component AppsForMeegoBackground
     Rectangle {
         id: background
@@ -43,8 +57,14 @@
                 height: 1
             }
 
+
+            // Login Section
+            //
             Item {
                 id: sectionLogin
+
+                property bool isLoggingIn: false
+
                 width: parent.width
                 height: childrenRect.height
 
@@ -86,8 +106,6 @@
                     anchors.left: lblUser.right
                     anchors.right: parent.right
                     anchors.topMargin: 10
-
-                    text: gears.configuration.loginUser
                 }
 
                 TextField {
@@ -99,8 +117,6 @@
                     anchors.left: lblPassword.right
                     anchors.right: parent.right
                     anchors.topMargin: 10
-
-                    text: gears.configuration.loginPassword
                 }
 
                 Column {
@@ -111,13 +127,16 @@
                     spacing: 20
 
                     Button {
-                        text: gears.isLoggedIn ? qsTr("Log Out")
-                                               : qsTr("Log In")
+                        text: gears.ocsProvider.loggedIn ? qsTr("Log Out")
+                                                         : qsTr("Log In")
                         anchors.left: parent.left
                         anchors.right: parent.right
+                        visible: ! sectionLogin.isLoggingIn
 
                         onClicked: {
-                            if (gears.isLoggedIn)
+                            sectionLogin.isLoggingIn = true;
+
+                            if (gears.ocsProvider.loggedIn)
                             {
                                 gears.logout();
                             }
@@ -132,11 +151,26 @@
                         text: qsTr("Register")
                         anchors.left: parent.left
                         anchors.right: parent.right
+                        visible: ! sectionLogin.isLoggingIn && ! 
gears.ocsProvider.loggedIn
 
                         onClicked: {
                             
Qt.openUrlExternally("https://meego.com/user/register";);
                         }
                     }
+
+                    ProgressBar {
+                        width: parent.width
+                        indeterminate: true
+                        visible: sectionLogin.isLoggingIn
+                    }
+
+                    Connections {
+                        target: gears.ocsProvider
+                        onLoginChanged: {
+                            sectionLogin.isLoggingIn = false;
+                        }
+                    }
+
                 }//Login Buttons Box
 
             }//Section
@@ -147,53 +181,77 @@
                 color: "#313131"
             }
 
+
+            // Testing Section
+            //
             Item {
                 id: sectionTesting
+
+                property bool isTogglingTesting: false
+
                 width: parent.width
                 height: childrenRect.height
+                visible: gears.configuration.haveTestingMode
 
-                Button {
-                    id: btnTesting
+                Column {
                     width: parent.width
-                    text: gears.configuration.showTesting ? qsTr("Disable 
Review Mode")
-                                                          : qsTr("Enable 
Review Mode")
-                    onClicked: {
-                        testingEnablerDialog.open();
-                        enableTestingTimer.start();
-                    }
+                    spacing: 20
 
-                    Timer {
-                        id: enableTestingTimer
-                        repeat: false
-                        interval: 500
+                    Button {
+                        id: btnTesting
+                        width: parent.width
+                        text: gears.configuration.showTesting ? qsTr("Disable 
Review Mode")
+                                                              : qsTr("Enable 
Review Mode")
+                        enabled: ! gears.packageDB.installing
+                        visible: ! sectionTesting.isTogglingTesting
 
-                        onTriggered: {
+                        onClicked: {
+                            sectionTesting.isTogglingTesting = true;
                             if (gears.configuration.showTesting)
                             {
                                 gears.packageDB.enableTesting(false);
-                                gears.configuration.showTesting = false;
                             }
                             else
                             {
                                 gears.packageDB.enableTesting(true);
-                                gears.configuration.showTesting = true;
                             }
-                            // reload list models to reflect the change 
immediately
-                            gears.appListModel.load();
-                            gears.appSearchModel.load();
+
                         }
+
+                    }
+
+                    ProgressBar {
+                        width: parent.width
+                        indeterminate: true
+                        visible: sectionTesting.isTogglingTesting
+                    }
+
+                    Label {
+                        anchors.top: btnTesting.bottom
+                        anchors.topMargin: 12
+                        width: parent.width
+
+                        text: qsTr("Review Mode shows you apps waiting for " +
+                                   "review and allows you to help 
reviewing.\n" +
+                                   "Please note that apps waiting for review 
may " +
+                                   "be untested and may harm your device.")
                     }
                 }
 
-                Label {
-                    anchors.top: btnTesting.bottom
-                    anchors.topMargin: 12
-                    width: parent.width
+                Connections {
+                    target: gears.packageDB
+                    onEndOfTransaction: {
+                        console.log("END OF TRANSACTION");
+                        if (sectionTesting.isTogglingTesting)
+                        {
+                            sectionTesting.isTogglingTesting = false;
 
-                    text: qsTr("Review Mode shows you apps waiting for " +
-                               "review and allows you to help reviewing.\n" +
-                               "Please note that apps waiting for review may " 
+
-                               "be untested and may harm your device.")
+                            // reload list models to reflect the change 
immediately
+                            gears.configuration.showTesting = true;
+                            gears.appListModel.load();
+                            gears.appSearchModel.load();
+                        }
+                    }
                 }
 
             }//Section
@@ -202,8 +260,12 @@
                 width: parent.width
                 height: 2
                 color: "#313131"
+                visible: sectionTesting.visible
             }
 
+
+            // About Section
+            //
             Item {
                 id: sectionAbout
                 width: parent.width
@@ -233,15 +295,35 @@
     ScrollDecorator { flickableItem: contentFlickable }
 
     Dialog {
-        id: testingEnablerDialog
+        id: errorDialog
+        property alias message: lblMessage.text
 
-        content: Text {
-            text: qsTr("Please Wait")
+        title: Text {
+            width: parent.width
+            height: 72
             horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignTop
+            text: "Login Error"
             color: "white"
             font.pixelSize: 36
             font.bold: true
         }
+
+        content: Text {
+            id: lblMessage
+            width: parent.width
+            height: 72
+            color: "white"
+            horizontalAlignment: Text.AlignHCenter
+            font.pixelSize: 24
+        }
+
+        buttons: Button {
+            text: "OK"
+            onClicked: {
+                errorDialog.accept();
+            }
+        }
     }
 
     Dialog {
--- appsformeego/qml/AppItem.qml
+++ appsformeego/qml/AppItem.qml
@@ -79,7 +79,7 @@
         anchors.top: parent.top
         anchors.left: iconBox.right
         anchors.right: parent.right
-        anchors.topMargin: 24
+        anchors.topMargin: 8
         anchors.leftMargin: 12
         anchors.rightMargin: 48
         height: childrenRect.height
@@ -97,11 +97,10 @@
             id: rater
             width: 5 * 26
             height: 24
-            //visible: stage == "stable"
-
             filled: "star-filled.png"
             unfilled: "star.png"
             maximum: 5
+            interactive: false
         }
 
         /*
--- appsformeego/qml/Gears.qml
+++ appsformeego/qml/Gears.qml
@@ -12,7 +12,6 @@
     property alias appSearchModel: myAppSearchModel
     property alias application: myApplication
 
-    property bool isLoggedIn: false
 
     /* Returns the status of the given package as known to the package DB.
      */
@@ -44,11 +43,8 @@
     {
         console.log("user: " + user);
 
-        if (user != "" && password != "")
-        {
-            myOcsProvider.login(user, password);
-            isLoggedIn = true;
-        }
+        myOcsProvider.login(user, password);
+
         if (storeCredentials)
         {
             myConfiguration.loginUser = user;
@@ -61,7 +57,26 @@
         myOcsProvider.login("", "", true);
         myConfiguration.loginUser = "";
         myConfiguration.loginPassword = "";
-        isLoggedIn = false;
+    }
+
+    function splitComment(data)
+    {
+        var pos1 = data.indexOf("\n");
+        var user = data.substring(0, pos1);
+        var pos2 = data.indexOf("\n", pos1 + 1);
+        var date = data.substring(pos1 + 1, pos2);
+        var pos3 = data.indexOf("\n", pos2 + 1);
+        var version = data.substring(pos2 + 1, pos3);
+        var comment = data.substring(pos3 + 1, data.length);
+
+        /*
+        console.log(pos1 + " " + pos2 + " " + pos3);
+        console.log("User: " + user);
+        console.log("Date: " + date);
+        console.log("Version: " + version);
+        console.log("Comment: " + comment);
+        */
+        return [user, date, version, comment];
     }
 
     Component.onCompleted: {
--- appsformeego/qml/Rater.qml
+++ appsformeego/qml/Rater.qml
@@ -6,6 +6,7 @@
     property url unfilled
     property int maximum: 5
     property int percents: 0
+    property bool interactive: false
 
     id: rater
 
@@ -21,9 +22,18 @@
                 sourceSize.width: width
                 sourceSize.height: rater.height
                 smooth: false
-                fillMode: Image.Tile
+                fillMode: Image.Stretch
                 source: (index < percents / 100.0 * maximum) ? filled
                                                              : unfilled
+
+                MouseArea {
+                    anchors.fill: parent
+                    enabled: rater.interactive
+
+                    onEntered: {
+                        rater.percents = ((index + 1) / rater.maximum) * 100.0
+                    }
+                }
             }
         }
     }
--- appsformeego/src/application.cpp
+++ appsformeego/src/application.cpp
@@ -56,6 +56,29 @@
     QProcess::startDetached(execResolved, QStringList(), path);
 }
 
+QString parseComment(Attica::Comment &comment)
+{
+    QString version = "";
+    QString subject = comment.subject();
+    int pos = comment.subject().indexOf(':');
+    if (pos != -1)
+    {
+        version = comment.subject().left(pos);
+        subject = comment.subject().mid(pos + 1);
+    }
+
+    // burn those useless CRs used by descendants of the CP/M OS
+    QString commentText = comment.text();
+    commentText.replace('\r', "");
+
+    QString out = comment.user() + "\n" +
+                  
comment.date().toLocalTime().toString(Qt::SystemLocaleLongDate) + "\n" +
+                  version + "\n" +
+                  commentText;
+
+    return out;
+}
+
 }
 
 Application::Application(QObject *parent)
@@ -121,11 +144,7 @@
     qDebug() << "COMMENT";
     qDebug() << comment.user();
     qDebug() << comment.text();
-    myAppComments.prepend(comment.user() +
-                          "\n" +
-                          
comment.date().toLocalTime().toString(Qt::SystemLocaleLongDate) +
-                          "\n" +
-                          comment.text());
+    myAppComments.prepend(parseComment(comment));
 
     foreach (Attica::Comment child, comment.children())
     {
@@ -157,6 +176,19 @@
     }
 }
 
+void Application::sendRating(uint score)
+{
+    if (score > 100)
+    {
+        score = 100;
+    }
+    Attica::PostJob* raterJob =
+            myProvider->get().voteForContent(myAppId, score);
+    connect(raterJob, SIGNAL(finished(Attica::BaseJob*)),
+            this, SLOT(slotRatingFinished(Attica::BaseJob*)));
+    raterJob->start();
+}
+
 void Application::sendComment(QString user, QString comment)
 {
     qDebug() << "sending comment" << comment;
@@ -170,7 +202,7 @@
     addCommentJob->start();
 
     // make new comment available instantly
-    myAppComments.prepend(user + "\n" + "just now" + "\n" + comment);
+    myAppComments.prepend(user + "\n" + "just now" + "\n" + myAppVersion + 
"\n" + comment);
     emit commentsChanged();
 }
 
@@ -296,6 +328,18 @@
     }
 }
 
+void Application::slotRatingFinished(Attica::BaseJob *job)
+{
+    if (job->metadata().error() == Attica::Metadata::NoError)
+    {
+        qDebug() << "rating sent";
+    }
+    else
+    {
+        qDebug() << "error sending rating:" << job->metadata().message();
+    }
+}
+
 QString Application::decodeOct(const QString& data)
 {
     QByteArray output;
--- appsformeego/src/application.h
+++ appsformeego/src/application.h
@@ -61,6 +61,7 @@
     bool isLaunchable() { return myIsLaunchable; }
 
     Q_INVOKABLE void launch();
+    Q_INVOKABLE void sendRating(uint score);
     Q_INVOKABLE void sendComment(QString user, QString comment);
 
     static QString decodeOct(const QString& data);
@@ -93,9 +94,10 @@
     void readyChanged();
 
 private slots:
-    void handleSearchJobFinished(Attica::BaseJob *job);
-    void handleCommentJobFinished(Attica::BaseJob *job);
-    void slotAddCommentFinished(Attica::BaseJob *job);
+    void handleSearchJobFinished(Attica::BaseJob* job);
+    void handleCommentJobFinished(Attica::BaseJob* job);
+    void slotAddCommentFinished(Attica::BaseJob* job);
+    void slotRatingFinished(Attica::BaseJob* job);
 
 };
 
--- appsformeego/src/configuration.cpp
+++ appsformeego/src/configuration.cpp
@@ -91,3 +91,12 @@
     // not saved in config
     emit valueChanged();
 }
+
+bool Configuration::haveTestingMode()
+{
+#if defined(FOR_HARMATTAN)
+    return true;
+#else
+    return false;
+#endif
+}
--- appsformeego/src/configuration.h
+++ appsformeego/src/configuration.h
@@ -15,6 +15,8 @@
 
     Q_PROPERTY(bool showTesting READ showTesting WRITE setShowTesting NOTIFY 
valueChanged);
 
+    Q_PROPERTY(bool haveTestingMode READ haveTestingMode);
+
 public:
     explicit Configuration(QObject *parent = 0);
     virtual ~Configuration();
@@ -30,6 +32,8 @@
     bool showTesting();
     void setShowTesting(bool value);
 
+    bool haveTestingMode();
+
 signals:
     void valueChanged();
 };
--- appsformeego/src/installer.cpp
+++ appsformeego/src/installer.cpp
@@ -82,11 +82,6 @@
                                               << "testing"
                                               << (enabled ? "yes" : "no"));
     myInstallers << installer;
-
-    // this is a blocking operation
-    qDebug() << "waiting for repository";
-    installer->waitForFinished();
-    qDebug() << "ready";
 }
 
 void Installer::install(QString appKey, QUrl url)
--- appsformeego/src/packagedb.cpp
+++ appsformeego/src/packagedb.cpp
@@ -19,6 +19,7 @@
     , myRefreshProcess(new QProcess)
     , myLastRefreshTime(0)
     , myCurrentMode("idle")
+    , myIsInstalling(false)
 {
     QHash<int, QByteArray> roles;
     roles[Qt::DisplayRole] = "appname";
@@ -180,6 +181,8 @@
 void PackageDB::enableTesting(bool enabled)
 {
     myInstaller.enableTesting(enabled);
+    myIsInstalling = true;
+    emit installingStatusChanged();
 }
 
 /* Installs the given application.
@@ -198,6 +201,8 @@
     emit progressChanged(appKey, 0, 0);
 
     myInstaller.install(appKey, uri);
+    myIsInstalling = true;
+    emit installingStatusChanged();
 
     myAppInfoQueue << appKey;
     fetchNextAppInfo();
@@ -213,6 +218,8 @@
     tryRefresh();
 
     myInstaller.installPackage(name);
+    myIsInstalling = true;
+    emit installingStatusChanged();
 }
 
 /* Removes the given application.
@@ -226,6 +233,7 @@
     emit progressChanged(appKey, 0, 0);
 
     myInstaller.remove(appKey);
+    myIsInstalling = true;
 
     // why did we fetch appInfo from OCS here? is this a copy&paste relic..?
     //myAppInfoQueue << appId;
@@ -404,6 +412,8 @@
     PackageStatus::Ptr status = packageStatus(myCurrentAppKey);
     updateStatus(status);
 
+    myIsInstalling = false;
+    emit installingStatusChanged();
     emit endOfTransaction(myCurrentAppKey);
 }
 
@@ -413,6 +423,8 @@
     updateStatus(status);
 
     myCurrentMessage = message;
+    myIsInstalling = false;
+    emit installingStatusChanged();
     emit endOfTransaction(myCurrentAppKey);
 }
 
--- appsformeego/src/packagedb.h
+++ appsformeego/src/packagedb.h
@@ -26,6 +26,8 @@
     Q_PROPERTY(int progress READ progress NOTIFY progressChanged);
     Q_PROPERTY(int subProgress READ subProgress NOTIFY progressChanged);
     Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY progressChanged);
+    Q_PROPERTY(bool installing READ installing NOTIFY installingStatusChanged);
+
 public:
     enum {
         SummaryRole = Qt::UserRole,
@@ -73,6 +75,7 @@
     int progress() { return myCurrentProgress; }
     int subProgress() { return myCurrentSubProgress; }
     QString errorMessage() { return myCurrentMessage; }
+    bool installing() { return myIsInstalling; }
 
     QList<PackageStatus::Ptr> myPackages;
     SchemeService* mySchemeService;
@@ -90,12 +93,14 @@
     uint myCurrentProgress;
     uint myCurrentSubProgress;
     QString myCurrentMessage;
+    bool myIsInstalling;
 
 signals:
     void modelChanged();
     void progressChanged(QString appKey, uint progress, uint subProgress);
     void endOfTransaction(QString appKey);
     void appPageRequested(QString appId);
+    void installingStatusChanged();
 
 
 private slots:
--- appsformeego/src/provider.cpp
+++ appsformeego/src/provider.cpp
@@ -7,6 +7,7 @@
 
 Provider::Provider(QObject *parent)
     : QObject(parent)
+    , myIsLoggedIn(false)
 {
     // TODO: check if we may load this already
     
//myManager.addProviderFromXml("<provider><id>MeeGo</id><location>http://apps-beta.meego.com/ocs/v1/</location><name>MeeGo.com
 Apps</name><icon/><termsofuse/><register/><services><content 
ocsversion='1.6'/><comments ocsversion='1.6'/></services></provider>");
@@ -15,10 +16,6 @@
     
myManager.addProviderFromXml("<providers><provider><id>opendesktop</id><location>https://api.opendesktop.org/v1/</location><name>openDesktop.org</name><icon/><termsofuse>https://opendesktop.org/terms/</termsofuse><register>https://opendesktop.org/usermanager/new.php</register><services><person
 ocsversion='1.3'/><friend ocsversion='1.3'/><message 
ocsversion='1.3'/><activity ocsversion='1.3'/><content ocsversion='1.3'/><fan 
ocsversion='1.3'/><knowledgebase ocsversion='1.3'/><event 
ocsversion='1.3'/></services></provider></providers>");
     
//myManager.addProviderFile(QUrl("http://download.kde.org/ocs/providers.xml";));
     
//myManager.addProviderFile(QUrl("http://apps.formeego.org/ocs/providers.xml";));
-
-
-
-
 }
 
 Provider::~Provider()
@@ -44,18 +41,37 @@
 }
 
 void Provider::login(QString user, QString password)
-{
-    myProvider.saveCredentials(user, password);
-    qDebug() << "Has Credentials" << myProvider.hasCredentials();
-    bool ok = myProvider.loadCredentials(user, password);
-    qDebug() << "logging in..." << ok;
+{   
+    if (user.isEmpty())
+    {
+        qDebug() << "logged out";
+        myProvider.saveCredentials(user, password);
+        myIsLoggedIn = false;
+        emit loginChanged();
+    }
+    else
+    {
+        qDebug() << "logging in...";
+        myProvider.saveCredentials(user, password);
+        Attica::PostJob* job = myProvider.checkLogin(user, password);
+        connect(job, SIGNAL(finished(Attica::BaseJob*)),
+                this, SLOT(slotLoginDone(Attica::BaseJob*)));
+        job->start();
+    }
 }
 
 void Provider::slotLoginDone(Attica::BaseJob *job)
 {
-
     if (job->metadata().error() == Attica::Metadata::NoError)
     {
-        qDebug() << "Logged In";
+        qDebug() << "login successful";
+        myIsLoggedIn = true;
+    }
+    else
+    {
+        qDebug() << "Error logging in:" << job->metadata().message();
+        myIsLoggedIn = false;
+        emit loginError(job->metadata().message());
     }
+    emit loginChanged();
 }
--- appsformeego/src/provider.h
+++ appsformeego/src/provider.h
@@ -14,6 +14,7 @@
     Q_DISABLE_COPY(Provider)
 
     Q_PROPERTY(QUrl url READ url WRITE setUrl);
+    Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loginChanged);
 
 public:
     Provider(QObject *parent = 0);
@@ -29,13 +30,20 @@
     Q_INVOKABLE void login(QString user, QString password);
 
 private:
+    bool loggedIn() { return myIsLoggedIn; }
+
     Attica::ProviderManager myManager;
     Attica::Provider myProvider;
     QUrl myUrl;
+    bool myIsLoggedIn;
 
 private slots:
     void slotLoginDone(Attica::BaseJob* job);
 
+signals:
+    void loginChanged();
+    void loginError(QString message);
+
 };
 
 QML_DECLARE_TYPE(Provider)

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



Reply via email to