[kde-doc-english] [calligra] kexi/main: GUI: prototype of welcome status bar

Jaroslaw Staniek staniek at kde.org
Sat Feb 18 23:02:42 UTC 2012


Git commit 59036e061ab35277fe7c0254234ec8f1374a3517 by Jaroslaw Staniek.
Committed on 23/01/2012 at 23:43.
Pushed by staniek into branch 'master'.

GUI: prototype of welcome status bar

feedback format++: added JSON-compatible character escaping; added uid

M  +1    -0    kexi/main/CMakeLists.txt
M  +47   -4    kexi/main/KexiUserFeedbackAgent.cpp
M  +11   -2    kexi/main/startup/KexiWelcomeAssistant.cpp
M  +2    -0    kexi/main/startup/KexiWelcomeAssistant.h
A  +200  -0    kexi/main/startup/KexiWelcomeStatusBar.cpp     [License: LGPL (v2+)]
A  +48   -0    kexi/main/startup/KexiWelcomeStatusBar.h     [License: LGPL (v2+)]

http://commits.kde.org/calligra/59036e061ab35277fe7c0254234ec8f1374a3517

diff --git a/kexi/main/CMakeLists.txt b/kexi/main/CMakeLists.txt
index 40e883b..1c1f3d6 100644
--- a/kexi/main/CMakeLists.txt
+++ b/kexi/main/CMakeLists.txt
@@ -26,6 +26,7 @@ KexiUserFeedbackAgent.cpp
 startup/KexiNewProjectAssistant.cpp
 startup/KexiOpenProjectAssistant.cpp
 startup/KexiWelcomeAssistant.cpp
+startup/KexiWelcomeStatusBar.cpp
 startup/KexiImportExportAssistant.cpp
 startup/KexiStartupFileHandler.cpp
 startup/KexiStartupDialog.cpp
diff --git a/kexi/main/KexiUserFeedbackAgent.cpp b/kexi/main/KexiUserFeedbackAgent.cpp
index 083f748..2ecee1d 100644
--- a/kexi/main/KexiUserFeedbackAgent.cpp
+++ b/kexi/main/KexiUserFeedbackAgent.cpp
@@ -25,13 +25,21 @@
 #include <KIO/Job>
 #include <KLocale>
 #include <KDebug>
+#include <KConfigGroup>
 
 #include <QPair>
 #include <QApplication>
 #include <QDesktopWidget>
 #include <QProcess>
+#include <QUuid>
 
-static const char userFeedbackUrl[] = "http://www.kexi-project.org/feedback/send";
+//! Version of feedback data format.
+//! Changelog:
+//! *1.0: initial version
+//! *1.1: added JSON-compatible character escaping; added uid
+static const char KexiUserFeedbackAgent_VERSION[] = "1.1";
+
+static const char KexiUserFeedbackAgent_URL[] = "http://www.kexi-project.org/feedback/send";
 
 typedef QPair<QByteArray, QVariant> DataPair;
 
@@ -44,13 +52,27 @@ public:
     }
     bool enabled;
     QList<DataPair> data;
+    //! Unique user ID handy if used does not want to disclose username
+    //! but agrees to be identified as unique user of the application.
+    QUuid uid;
 };
 
 KexiUserFeedbackAgent::KexiUserFeedbackAgent(QObject* parent)
  : QObject(parent), d(new Private)
 {
+    KConfigGroup configGroup(KGlobal::config()->group("User Feedback"));
+    
+    // load or create uid
+    QString uidString = configGroup.readEntry("uid", QString());
+    d->uid = QUuid(uidString);
+    if (d->uid.isNull()) {
+        d->uid = QUuid::createUuid();
+        configGroup.writeEntry("uid", d->uid.toString());
+    }
+    
     #define ADD(a, b) d->data.append(qMakePair(QByteArray(a), QVariant(b)))
-    ADD("ver", "1.0");
+    ADD("ver", KexiUserFeedbackAgent_VERSION);
+    ADD("uid", d->uid.toString());
     ADD("app_ver", Kexi::versionString());
     ADD("app_ver_major", Kexi::versionMajor());
     ADD("app_ver_minor", Kexi::versionMinor());
@@ -116,6 +138,26 @@ void KexiUserFeedbackAgent::setEnabled(bool enabled)
     d->enabled = enabled;
 }
 
+//! Escapes string for json format (see http://json.org/string.gif).
+inline QString escapeJson(const QString& s)
+{
+    QString res;
+    for (int i=0; i<s.length(); i++) {
+        switch (s[i].toLatin1()) {
+        case '\\': res += QLatin1String("\\\\"); break;
+        case '/': res += QLatin1String("\\/"); break;
+        case '"': res += QLatin1String("\\\""); break;
+        case '\b': res += QLatin1String("\\b"); break;
+        case '\f': res += QLatin1String("\\f"); break;
+        case '\n': res += QLatin1String("\\n"); break;
+        case '\r': res += QLatin1String("\\r"); break;
+        case '\t': res += QLatin1String("\\t"); break;
+        default: res += s[i];
+        }
+    }
+    return res;
+}
+
 void KexiUserFeedbackAgent::sendData()
 {
     QByteArray postData;
@@ -124,11 +166,12 @@ void KexiUserFeedbackAgent::sendData()
             postData += ',';
         }
         postData += (QByteArray("\"") + item.first + "\":\""
-                     + item.second.toString().toUtf8() + '"');
+                     + escapeJson(item.second.toString()).toUtf8() + '"');
     }
+    kDebug() << postData;
     
     KIO::Job* sendJob = KIO::storedHttpPost(
-        postData, KUrl(userFeedbackUrl), KIO::HideProgressInfo);
+        postData, KUrl(KexiUserFeedbackAgent_URL), KIO::HideProgressInfo);
     connect(sendJob, SIGNAL(finished(KJob*)), this, SLOT(sendJobFinished(KJob*)));
     sendJob->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded");
 }
diff --git a/kexi/main/startup/KexiWelcomeAssistant.cpp b/kexi/main/startup/KexiWelcomeAssistant.cpp
index 6f2a60f..9f0c9ed 100644
--- a/kexi/main/startup/KexiWelcomeAssistant.cpp
+++ b/kexi/main/startup/KexiWelcomeAssistant.cpp
@@ -1,5 +1,5 @@
 /* This file is part of the KDE project
-   Copyright (C) 2011 Jarosław Staniek <staniek at kde.org>
+   Copyright (C) 2011-2012 Jarosław Staniek <staniek at kde.org>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
@@ -20,6 +20,7 @@
 #include "KexiWelcomeAssistant.h"
 
 #include "KexiRecentProjectsModel.h"
+#include "KexiWelcomeStatusBar.h"
 
 #include <core/kexi.h>
 #include <core/KexiRecentProjects.h>
@@ -66,7 +67,11 @@ KexiMainWelcomePage::KexiMainWelcomePage(
 {
     connect(this, SIGNAL(openProject(KexiProjectData,QString,bool*)),
             assistant, SIGNAL(openProject(KexiProjectData,QString,bool*)));
+    QWidget* contents = new QWidget;
+    QHBoxLayout* contentsLyr = new QHBoxLayout(contents);
+    
     m_recentProjects = new KexiCategorizedView;
+    contentsLyr->addWidget(m_recentProjects, 1);
     //m_recentProjects->setItemDelegate(new KFileItemDelegate(this));
     setFocusWidget(m_recentProjects);
     m_recentProjects->setFrameShape(QFrame::NoFrame);
@@ -77,7 +82,11 @@ KexiMainWelcomePage::KexiMainWelcomePage(
     m_recentProjects->setSpacing(margin);
     m_recentProjects->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
     connect(m_recentProjects, SIGNAL(clicked(QModelIndex)), this, SLOT(slotItemClicked(QModelIndex)));
-    setContents(m_recentProjects);
+    
+    m_statusBar = new KexiWelcomeStatusBar;
+    contentsLyr->addWidget(m_statusBar);
+    
+    setContents(contents);
 
     QTimer::singleShot(100, this, SLOT(loadProjects()));
 }
diff --git a/kexi/main/startup/KexiWelcomeAssistant.h b/kexi/main/startup/KexiWelcomeAssistant.h
index 98319cc..a8d892d 100644
--- a/kexi/main/startup/KexiWelcomeAssistant.h
+++ b/kexi/main/startup/KexiWelcomeAssistant.h
@@ -34,6 +34,7 @@ class KexiProjectSelectorWidget;
 class KCategorizedView;
 class KexiWelcomeAssistant;
 class KexiRecentProjectsProxyModel;
+class KexiWelcomeStatusBar;
 
 class KexiMainWelcomePage : public KexiAssistantPage
 {
@@ -55,6 +56,7 @@ private:
     KexiCategorizedView* m_recentProjects;
     KexiRecentProjectsProxyModel* m_recentProjectsProxyModel;
     KexiWelcomeAssistant* m_assistant;
+    KexiWelcomeStatusBar* m_statusBar;
 };
 
 class KexiProjectData;
diff --git a/kexi/main/startup/KexiWelcomeStatusBar.cpp b/kexi/main/startup/KexiWelcomeStatusBar.cpp
new file mode 100644
index 0000000..384de2f
--- /dev/null
+++ b/kexi/main/startup/KexiWelcomeStatusBar.cpp
@@ -0,0 +1,200 @@
+/* This file is part of the KDE project
+   Copyright (C) 2011-2012 Jarosław Staniek <staniek at kde.org>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This program 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this program; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KexiWelcomeStatusBar.h"
+#include <kexiutils/utils.h>
+
+#include <KTextBrowser>
+#include <KGlobalSettings>
+#include <KIconLoader>
+#include <KColorUtils>
+#include <KColorScheme>
+#include <KStandardDirs>
+#include <KDebug>
+
+#include <QLayout>
+#include <QProgressBar>
+#include <QtCore/qmath.h>
+
+#define HEADER_SIZE 1.0
+
+class KexiStatusTextDocument : public QTextDocument
+{
+public:
+    KexiStatusTextDocument(KexiWelcomeStatusBar* parent) : QTextDocument(parent),
+        m_parent(parent)
+    {
+        // http://www.qtcentre.org/wiki/index.php?title=QTextBrowser_with_images_and_CSS
+        qreal fontSize = qFloor(
+            (KGlobalSettings::smallestReadableFont().pointSizeF()
+             + m_parent->font().pointSizeF())
+             / 2.0);
+        KColorScheme colorScheme(m_parent->palette().currentColorGroup());
+        QString css =
+            QString("* { font-size:%1pt; color:%2; } ")
+                .arg(fontSize).arg(m_parent->palette().color(QPalette::Text).name())
+            + QString(".gray, .gray * { color:%1; } ")
+                .arg(KColorUtils::mix(m_parent->palette().color(QPalette::Text),
+                                        m_parent->palette().color(QPalette::Base), 0.5).name())
+            + "img.icon { vertical-align:bottom; } "
+            //+ "body { background-color:yellow; } "
+            + "p { text-indent:0px; } "
+            + QString("*.head { text-indent:0px; font-size:%1pt; font-weight:bold; } ").arg(
+                m_parent->font().pointSizeF() * HEADER_SIZE)
+            + QString("a, a * { color:%1; } ")
+                .arg(colorScheme.foreground(KColorScheme::LinkText).color().name());
+        addResource(QTextDocument::StyleSheetResource, QUrl( "format.css" ), css);
+    }
+protected:
+    virtual QVariant loadResource(int type, const QUrl &name)
+    {
+        if (type == QTextDocument::ImageResource) {
+            if (name.scheme() == QLatin1String("kicon")) {
+                return KIconLoader::global()->loadIcon(name.host(), KIconLoader::NoGroup, 16);
+            }
+            else if (name.scheme() == "feedbackdata") {
+                if (name.host() == "progress") {
+                    return m_parent->userProgressPixmap();
+                }
+            }
+            else if (name.toString() == "ext") {
+                return m_parent->externalLinkPixmap();
+            }
+        }
+        return QTextDocument::loadResource(type, name);
+    }
+private:
+    KexiWelcomeStatusBar *m_parent;
+};
+
+//---
+
+class KexiWelcomeStatusBar::Private
+{
+public:
+    Private(KexiWelcomeStatusBar* _q)
+     : q(_q)
+    {
+    }
+
+    KTextBrowser *statusBrowser;
+    QProgressBar userProgressBar;
+    QVBoxLayout *lyr;
+    QPixmap externalLinkPixmap;
+private:
+    KexiWelcomeStatusBar *q;
+};
+    
+KexiWelcomeStatusBar::KexiWelcomeStatusBar(QWidget* parent)
+ : QWidget(parent), d(new Private(this))
+{
+    d->lyr = new QVBoxLayout(this);
+    d->userProgressBar.setTextVisible(false);
+    setUserProgress(5);
+
+    init();
+}
+
+KexiWelcomeStatusBar::~KexiWelcomeStatusBar()
+{
+    delete d;
+}
+
+void KexiWelcomeStatusBar::init()
+{
+    QString title("You in Kexi Project"); // Your Status in Kexi Project
+    QString html = QString(
+        "<p><span class=\"head\">%1</span> <a class='gray' href='feedback://help_your_status'>(?)</a></p>"
+        "<p><img src='feedbackdata://progress'> <b>%2%</b> involved</p>"
+        "<p><b>Contribute</b> <a class='gray' href='feedback://help_why_contribute'>(Why?)</a></p>"
+        "<p><img src=\"kicon://list-add\"> <a href='feedback://show_share_usage_info'>Share Usage Info</a> <span class='gray'>(+5%)</span></p>"
+        ).arg(title).arg(d->userProgressBar.value());
+
+    d->statusBrowser = new KTextBrowser;
+    d->statusBrowser->setFrameShape(QFrame::NoFrame);
+    d->statusBrowser->setTextInteractionFlags(Qt::LinksAccessibleByMouse|Qt::LinksAccessibleByKeyboard);
+    d->lyr->addWidget(d->statusBrowser);
+
+    KexiStatusTextDocument *doc = new KexiStatusTextDocument(this);
+    
+    QFont f(d->statusBrowser->font());
+    f.setBold(true);
+    f.setPointSizeF(f.pointSizeF() * HEADER_SIZE);
+    d->statusBrowser->setFixedWidth(QFontMetrics(f).width(title + "(?)_____"));
+    d->userProgressBar.setFixedSize(
+        d->statusBrowser->minimumWidth() - QFontMetrics(f).width("888% involved"),
+        fontMetrics().height());
+    //statusDoc->addResource(QTextDocument::ImageResource, QUrl( "bg.png" ), QPixmap(":bg"));
+
+    title = "What's New?";
+    // <img src='ext'>
+    html += QString(
+        "<br>"
+        "<p><b class=\"head\">%1</b></p>"
+        "<p><a href=\"newsdata://0\"> Fruits of CSS2: Office Forms</a></p>"
+        "<p align=\"right\"><a href=\"newsdata://show_all\">See all <b>News</b> »</a></p>"
+        ).arg(title);
+
+    title = "Recent Releases";
+    html += QString(
+        "<br>"
+        "<p><b class=\"head\">%1</b></p>"
+        "<p><table>"
+        "<tr><td><p>Stable release: </p></td><td><a href=\"http://www.koffice.org/news/announcements/koffice-2-3-3-update/\">2.3.3</a></td></tr>"
+        "<tr><td><p>Preview release: </p></td><td><a href=\"http://www.calligra.org/news/announcements/calligra-2-4-beta-6/\">2.4 Beta 6</a></td></tr>"
+        "</table></p>"
+        "<p align=\"right\"><a href=\"newsdata://show_all\">See more <b>Releases</b> »</a></p>"
+        ).arg(title);
+    
+    QString htmlHead(QLatin1String(
+        "<html><head>"
+        "<link rel='stylesheet' type='text/css' href='format.css'>"
+        "</head><body>"));
+    doc->setHtml(htmlHead + html + "</body></html>");
+    d->statusBrowser->setDocument(doc);
+    kDebug() << d->statusBrowser->toHtml();
+}
+
+void KexiWelcomeStatusBar::setUserProgress(int progress)
+{
+    d->userProgressBar.setValue(progress);
+}
+
+QPixmap KexiWelcomeStatusBar::userProgressPixmap()
+{
+    QPixmap px(d->userProgressBar.size());
+    px.fill(Qt::transparent);
+    QPainter p(&px);
+    p.setOpacity(0.5);
+    d->userProgressBar.render(&p);
+    return px;
+}
+
+QPixmap KexiWelcomeStatusBar::externalLinkPixmap()
+{
+    if (d->externalLinkPixmap.isNull()) {
+        d->externalLinkPixmap = QPixmap(
+            KStandardDirs::locate("data", "kexi/pics/external-link.png"));
+        KColorScheme colorScheme(palette().currentColorGroup());
+        QColor c(colorScheme.foreground(KColorScheme::LinkText).color());
+        c.setAlpha(100);
+        KexiUtils::replaceColors(&d->externalLinkPixmap, c);
+    }
+    return d->externalLinkPixmap;
+}
diff --git a/kexi/main/startup/KexiWelcomeStatusBar.h b/kexi/main/startup/KexiWelcomeStatusBar.h
new file mode 100644
index 0000000..f2fb1ab
--- /dev/null
+++ b/kexi/main/startup/KexiWelcomeStatusBar.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+   Copyright (C) 2012 Jarosław Staniek <staniek at kde.org>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This program 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this program; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KEXIWELCOMESTATUSBAR_H
+#define KEXIWELCOMESTATUSBAR_H
+
+#include <QWidget>
+
+//! Status sidebar for the welcome page
+class KexiWelcomeStatusBar : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit KexiWelcomeStatusBar(QWidget* parent = 0);
+    ~KexiWelcomeStatusBar();
+
+    QPixmap userProgressPixmap();
+    QPixmap externalLinkPixmap();
+
+signals:
+
+private slots:
+
+private:
+    void setUserProgress(int progress);
+    void init();
+
+    class Private;
+    Private * const d;
+};
+
+#endif



More information about the kde-doc-english mailing list