diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fcc6e8d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: cpp -compiler: gcc -sudo: require -dist: trusty -before_install: -- sudo add-apt-repository ppa:beineri/opt-qt58-trusty -y -- sudo apt-get update -qq -install: -- sudo apt-get -y install qt58base qt58webengine qt58quickcontrols -- source /opt/qt58/bin/qt58-env.sh -script: -- qmake PREFIX=/usr -- make -j4 -- sudo make INSTALL_ROOT=appdir install ; sudo chown -R $USER appdir ; find appdir/ -- wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" -- chmod a+x linuxdeployqt*.AppImage -- unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH -- "./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -qmldir=./qml/ - -bundle-non-qt-libs" -- "./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -qmldir=./qml/ - -appimage" -- find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " - -f 2-3 | sort | uniq -- mv FeedTheMonkey*.AppImage FeedTheMonkey.AppImage -deploy: - provider: releases - api_key: - secure: d+hHwOnmeLPVvuue6VDCs2LwLS+BFzJF/BB5iObtkCYBwQ8ybnVzUcgnjJKOt37SHI0T9kLegI+Lq/843ECYiGiDjQg4PvCF69V8ODgHv3v1qiN5oG/eroBXd83a0+xhi4BuJt0SwcV9mcv4uD9bCPhj944rmMLH+3qD4ysgImBmbYSbbLecE9+QAs7bfrCwQRfdCePBORX3FHa/p12NEtln7xv6ZRyku9LdJSzAcdgm4zc95ggTAVC1+aQB6J0q2QzWPlQcOkLx+ZYmOqClhbSMFpIyPXP8UpXjYyvUlTAd0+wH8BGf0O3lpOqACc7IKIbj9d5oPmghVZo55SyW+RR77G+az+IbGJ7iXZsMfQZsMvtB7hNYhNvUUxQrAau7Y/ve+6sMQmvA7aMHV8kDUvnNW/c2r2jAWwk+N8QzGcP/rclDCKeOWZqZABmrzTViXZVAeXh4hJ8r6mbq8iwagBUPCsVYhVuerQt/KIoWxyn6/1GmMfKGi3dA/v3u1qU61vzrz3yLlJBmUAVPxZdVmqfRweh4BXjImxFMFmf5PYm5FnDg1gmw8rWsgii7+IPYw7DjTAHpjYbtXvDwDgG1nRXiRp2TGtPPgKW1/Uk8r/j5vfB5WcEZ7exLUgsPPjny5MGvzjqOxeLvwK1Pg9jFBFXIx7l1tNMJQxQU0r3DmBg= - file: FeedTheMonkey.AppImage - on: - repo: jeena/FeedTheMonkey - skip_cleanup: true - draft: true diff --git a/README.md b/README.md index 155358a..d26e967 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # FeedTheMonkey -Icon +Icon FeedTheMonkey is a desktop client for [TinyTinyRSS](http://tt-rss.org). That means that it doesn't work as a standalone feed reader but only as a client for the TinyTinyRSS API @@ -11,12 +11,10 @@ to have Qt 5.6 installed to be able to compile and have a account on a TinyTinyR ## Installation -If you run Linux then there is an AppImage on the [Latest release](https://github.com/jeena/FeedTheMonkey/releases/latest) page. You download it, make executable and are able to run, it should work on most of the distributions out there. - -For ArchLinux I package it and it's available on https://aur.archlinux.org/packages/feedthemonkey/ +Download the latest release code from: https://github.com/jeena/FeedTheMonkey/releases/latest You can compile and install it everywhere Qt is suported, this means on macOS, Windows -and Linux. +and Linux. For ArchLinux I package it and it's available on https://aur.archlinux.org/packages/feedthemonkey/ ## Keyboard shortcuts @@ -43,13 +41,13 @@ the use on a desktop computer but I'd like to see it on a mobile device too. ## Screenshot -![Feed the Monkey screenshot](http://jeena.net/feedthemonkey/feedthemonkey-dark.png) +![Feed the Monkey screenshot](http://jabs.nu/feedthemonkey/screenshot.png) ## License This file is part of FeedTheMonkey. -Copyright 2015-2017 Jeena +Copyright 2015 Jeena FeedTheMonkey is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/html/content.css b/html/content.css index 2b1d0b3..1b3eda8 100644 --- a/html/content.css +++ b/html/content.css @@ -25,12 +25,13 @@ html, body { body { background: #eee; font-family: sans-serif; - word-wrap: break-word; + padding: 2em; + font-weight: lighter; } .nightmode { - background: #353535; - color: #ddd; + background: #111; + color: #aaa; } .nightmode::-webkit-scrollbar { @@ -49,28 +50,32 @@ body { } h1 { + font-weight: lighter; font-size: 1.4em; margin: 0; padding: 0; } +#date { + border-bottom: 1px solid #aaa; + margin-bottom: 1em; + padding-bottom: 1em; + display: block; +} + +.nightmode #date { + border-bottom-color: #333; +} + .starred:after { content: "*"; } -header { - padding: 2em; - border-bottom: 1px solid #aaa; -} - -.nightmode header { - border-bottom-color: #222; -} - header p { - color: #666; + color: #aaa; margin: 0; padding: 0; + font-size: 0.8em; } .nightmode header p { @@ -84,7 +89,6 @@ a { article { line-height: 1.6; - margin: 2em; } article a { diff --git a/html/content.html b/html/content.html index 87d53aa..bbcd5f5 100644 --- a/html/content.html +++ b/html/content.html @@ -4,96 +4,7 @@ TTRSS - + diff --git a/html/content.js b/html/content.js new file mode 100644 index 0000000..cbc29b2 --- /dev/null +++ b/html/content.js @@ -0,0 +1,73 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +function $(id) { + return document.getElementById(id); +} + +function setArticle(article) { + window.scrollTo(0, 0); + + $("date").innerHTML = ""; + $("title").innerHTML = ""; + $("title").href = ""; + $("title").title = ""; + $("feed_title").innerHTML = ""; + $("author").innerHTML = ""; + $("article").innerHTML = ""; + + if(article === "empty") { + + $("article").innerHTML = "No unread articles to display."; + + } else if(article === "loading") { + + $("article").innerHTML = "Loading "; + + } else if (article === "logout") { + + } else if(article) { + + $("date").innerHTML = (new Date(parseInt(article.updated, 10) * 1000)); + $("title").innerHTML = article.title; + $("title").href = article.link; + $("title").title = article.link; + $("feed_title").innerHTML = article.feed_title; + $("title").className = article.marked ? "starred" : ""; + $("author").innerHTML = ""; + if(article.author && article.author.length > 0) + $("author").innerHTML = "– " + article.author + $("article").innerHTML = article.content; + + var as = $("article").getElementsByTagName("a"); + for(var i = 0; i < as.length; i++) { + as[i].target = ""; + } + } +} + +function setFont(font, size) { + document.body.style.fontFamily = font; + document.body.style.fontSize = size + "pt"; +} + +function setNightmode(nightmode) { + if(nightmode) document.body.className = "nightmode"; + else document.body.className = ""; +} diff --git a/html/html.qrc b/html/html.qrc index c6cf166..90d8b19 100644 --- a/html/html.qrc +++ b/html/html.qrc @@ -2,5 +2,6 @@ content.css content.html + content.js diff --git a/misc/feedthemonkey.desktop b/misc/feedthemonkey.desktop index c302345..a9d950f 100644 --- a/misc/feedthemonkey.desktop +++ b/misc/feedthemonkey.desktop @@ -1,4 +1,5 @@ [Desktop Entry] +Version=2.0.0 Comment=A desktop client for the TinyTinyRSS feed reader. Exec=feedthemonkey GenericName=Feed Reader @@ -8,4 +9,4 @@ NoDisplay=false StartupNotify=true Terminal=false Type=Application -Categories=Network;Qt; +Categories=Network;Qt diff --git a/qml/Content.qml b/qml/Content.qml index 07440be..b00764a 100644 --- a/qml/Content.qml +++ b/qml/Content.qml @@ -17,11 +17,12 @@ * along with FeedTheMonkey. If not, see . */ -import QtWebEngine 1.8 +import QtWebEngine 1.0 import QtQuick 2.0 import QtQuick.Controls 1.3 import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.3 +import QtQuick.Controls 1.3 import TTRSS 1.0 Item { @@ -84,17 +85,9 @@ Item { webView.runJavaScript("if(typeof setNightmode == \"function\") setNightmode(" + (content.nightmode ? "true" : "false") + ")") } + onNavigationRequested: { - if (request.url == "feedthemonkey:previous") { - request.action = WebEngineView.IgnoreRequest; - app.showPreviousPost(); - } else if (request.url == "feedthemonkey:next") { - request.action = WebEngineView.IgnoreRequest; - app.showNextPost(); - } else if (request.url == "feedthemonkey:open") { - request.action = WebEngineView.IgnoreRequest; - Qt.openUrlExternally(post.link) - } else if (request.navigationType !== WebEngineNavigationRequest.LinkClickedNavigation) { + if (request.navigationType != WebEngineView.LinkClickedNavigation) { request.action = WebEngineView.AcceptRequest; } else { request.action = WebEngineView.IgnoreRequest; diff --git a/qml/PostListItem.qml b/qml/PostListItem.qml index 63bf813..e0c3d20 100644 --- a/qml/PostListItem.qml +++ b/qml/PostListItem.qml @@ -33,7 +33,7 @@ Item { } id: item - height: d.height + t.height + e.height + 2 + height: d.height + t.height + e.height + 20 Item { anchors.fill: parent @@ -81,7 +81,7 @@ Item { Label { id: t text: title - color: nightmode ? (read ? "#888" : "#ddd") : (read ? "gray" : "black") + color: nightmode ? (read ? "#555" : "#aaa") : (read ? "gray" : "black") font.pointSize: textFontSize textFormat: Text.PlainText wrapMode: Text.WrapAnywhere diff --git a/qml/Sidebar.qml b/qml/Sidebar.qml index 84de4cb..bcb70ee 100644 --- a/qml/Sidebar.qml +++ b/qml/Sidebar.qml @@ -48,21 +48,6 @@ ScrollView { } } - onWidthChanged: { - // Hide sidebar if smaller than 200px wide - if(width < 200) { - width = 0; - } - } - - Rectangle { - width: 1 - color: app.nightmode ? "#111" : "lightgray" - anchors.right: parent.right - anchors.top: parent.top - height: parent.height - } - ListView { id: listView @@ -82,12 +67,12 @@ ScrollView { highlightFollowsCurrentItem: false highlight: Component { Rectangle { - width: listView.currentItem.width -1 + width: listView.currentItem.width height: listView.currentItem.height - color: nightmode ? "#15539e" : "lightblue" + color: nightmode ? "#444" : "lightblue" + opacity: 0.5 y: listView.currentItem.y } - } onCurrentItemChanged: { @@ -100,6 +85,8 @@ ScrollView { } item.content.post = server.posts[currentIndex] + //content.flickableItem.contentY = 0 + previousPost = item.content.post } } diff --git a/qml/TheMenuBar.qml b/qml/TheMenuBar.qml index 34c0310..ae2eb70 100644 --- a/qml/TheMenuBar.qml +++ b/qml/TheMenuBar.qml @@ -35,11 +35,6 @@ MenuBar { Menu { visible: menuBar.visible title: qsTr("File") - MenuItem { - text: qsTr("Close &Window") - shortcut: "Ctrl+W" - onTriggered: Qt.quit() - } MenuItem { text: qsTr("Exit") shortcut: "Ctrl+Q" @@ -137,7 +132,7 @@ MenuBar { title: qsTr("Help") MenuItem { text: qsTr("About") - onTriggered: Qt.openUrlExternally("http://jeena.net/feedthemonkey/index.html"); + onTriggered: Qt.openUrlExternally("http://jabs.nu/feedthemonkey"); } } diff --git a/qml/main.qml b/qml/main.qml index 0b6074b..0a6288a 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -21,7 +21,6 @@ import QtQuick 2.3 import QtQuick.Controls 1.3 import QtQuick.Window 2.0 import QtQuick.Layouts 1.1 -import QtQuick.Dialogs 1.1 import Qt.labs.settings 1.0 import TTRSS 1.0 @@ -29,7 +28,7 @@ ApplicationWindow { id: app title: "FeedTheMonkey" visible: true - color: nightmode ? "#2d2d2d" : "#eee" + color: nightmode ? "#111" : "#eee" minimumWidth: 480 minimumHeight: 320 @@ -48,17 +47,6 @@ ApplicationWindow { property int textFontSizeIndex: defaultTextFontSizeIndex property int textFontSize: fontSizes[textFontSizeIndex] property bool nightmode: false - property bool showMenuBar: false - - menuBar: TheMenuBar { - id: menu - serverLogin: serverLogin - server: server - sidebar: sidebar - content: content - visible: app.showMenuBar - __contentItem.visible: visible - } Settings { id: settings @@ -72,6 +60,14 @@ ApplicationWindow { property alias nightmode: app.nightmode } + property TheMenuBar menu: TheMenuBar { + id: menu + serverLogin: serverLogin + server: server + sidebar: sidebar + content: content + } + function loggedIn() { if(serverLogin.loggedIn()) { menu.loggedIn = true; @@ -113,14 +109,6 @@ ApplicationWindow { return forEscapingHTML.getText(0, forEscapingHTML.length) } - function showNextPost() { - sidebar.next() - } - - function showPreviousPost() { - sidebar.previous() - } - function keyPressed(event) { switch (event.key) { case Qt.Key_Right: @@ -159,6 +147,10 @@ ApplicationWindow { case Qt.Key_Return: Qt.openUrlExternally(content.post.link) break + case Qt.Key_S: { + console.log(Qt.openUrlExternally("speaker:"+ removeHTML(content.post.content))) + break + } default: break } @@ -180,6 +172,7 @@ ApplicationWindow { content: content server: server + Layout.minimumWidth: 200 implicitWidth: 300 textFontSize: app.textFontSize nightmode: app.nightmode @@ -199,7 +192,7 @@ ApplicationWindow { Keys.onReleased: { switch (event.key) { case Qt.Key_Alt: - app.showMenuBar = !app.showMenuBar + app.menuBar = menu break default: break @@ -213,27 +206,14 @@ ApplicationWindow { visible: !serverLogin.loggedIn() function login() { + console.log("FOO") serverLogin.login(serverUrl, userName, password) } - - } - - MessageDialog { - id: loginErrorAlert - title: "A login error occured" - text: serverLogin.loginError - onAccepted: visible = false } ServerLogin { id: serverLogin onSessionIdChanged: app.loggedIn() - onLoginErrorChanged: { - console.log("loginError:", loginError) - if(loginError.length > 0) { - loginErrorAlert.visible = true - } - } } Server { diff --git a/src/main.cpp b/src/main.cpp index 95f351e..48475bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,6 @@ int main(int argc, char *argv[]) { - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); app.setOrganizationName("Jeena"); app.setOrganizationDomain("jeena.net"); diff --git a/src/post.cpp b/src/post.cpp index 2d3179b..3a20840 100644 --- a/src/post.cpp +++ b/src/post.cpp @@ -28,6 +28,33 @@ Post::Post(QObject *parent) : QObject(parent) } Post::Post(QJsonObject post, QObject *parent) : QObject(parent) +{ + populateFromJson(post); +} + +Post::Post(QJsonObject post, QNetworkAccessManager *networkManager, QObject *parent) : QObject(parent) +{ + mNetworkManager = networkManager; + populateFromJson(post); + + QObject::connect(this, &Post::contentChanged, [this]() { + QJsonObject obj = QJsonDocument::fromJson(mJsonString.toUtf8()).object(); + obj["content"] = QJsonValue(mContent); + QJsonDocument doc(obj); + QString result(doc.toJson(QJsonDocument::Indented)); + mJsonString = result; + emit jsonStringChanged(mJsonString); + }); + + cacheImgs(); +} + +Post::~Post() +{ + +} + +void Post::populateFromJson(QJsonObject post) { mTitle = html2text(post.value("title").toString().trimmed()); mFeedTitle = html2text(post.value("feed_title").toString().trimmed()); @@ -50,11 +77,6 @@ Post::Post(QJsonObject post, QObject *parent) : QObject(parent) mJsonString = result; } -Post::~Post() -{ - -} - void Post::setRead(bool r) { if(mRead == r) return; @@ -77,3 +99,42 @@ QString Post::html2text(const QString htmlString) doc.setHtml(htmlString); return doc.toPlainText(); } + +void Post::cacheImgs() +{ + QRegExp imgTagRegex("\\]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive); + imgTagRegex.setMinimal(true); + QStringList urlmatches; + int offset = 0; + while( (offset = imgTagRegex.indexIn(mContent, offset)) != -1){ + offset += imgTagRegex.matchedLength(); + urlmatches.append(imgTagRegex.cap(1)); // Should hold only src property + } + + for(QString url : urlmatches) { + + if(url.startsWith("http")) { + QNetworkRequest request(url); + QNetworkReply *reply = mNetworkManager->get(request); + + connect(reply, &QNetworkReply::finished, [url, this, reply] () { + if (reply) { + if (reply->error() == QNetworkReply::NoError) { + QVariant mimeType(reply->header(QNetworkRequest::ContentTypeHeader)); + QString imgString = QString("data:") + mimeType.toString() + QString(";base64,") + QString(reply->readAll().toBase64()); + if(mimeType == "image/jpeg" || mimeType == "image/gif" || mimeType == "image/png") + { + mContent = mContent.replace(url, imgString); + emit contentChanged(mContent); + } + } else { + int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + //do some error management + qWarning() << "HTTP error: " << httpStatus; + } + reply->deleteLater(); + } + }); + } + } +} diff --git a/src/post.h b/src/post.h index 56ab9ff..ad1649d 100644 --- a/src/post.h +++ b/src/post.h @@ -24,6 +24,7 @@ #include #include #include +#include class Post : public QObject { @@ -35,16 +36,17 @@ class Post : public QObject Q_PROPERTY(QString author READ author CONSTANT) Q_PROPERTY(QUrl link READ link CONSTANT) Q_PROPERTY(QDateTime date READ date CONSTANT) - Q_PROPERTY(QString content READ content CONSTANT) + Q_PROPERTY(QString content READ content NOTIFY contentChanged) Q_PROPERTY(QString excerpt READ excerpt CONSTANT) Q_PROPERTY(bool starred READ starred NOTIFY starredChanged) Q_PROPERTY(bool read READ read WRITE setRead NOTIFY readChanged) Q_PROPERTY(bool dontChangeRead READ dontChangeRead WRITE setDontChangeRead NOTIFY dontChangeReadChanged) - Q_PROPERTY(QString jsonString READ jsonString CONSTANT) + Q_PROPERTY(QString jsonString READ jsonString NOTIFY jsonStringChanged) public: Post(QObject *parent = 0); Post(QJsonObject post, QObject *parent = 0); + Post(QJsonObject post, QNetworkAccessManager *networkManager, QObject *parent = 0); ~Post(); QString title() const { return mTitle; } QString feedTitle() const { return mFeedTitle; } @@ -63,9 +65,11 @@ public: QString jsonString() const { return mJsonString; } signals: + void contentChanged(QString); void starredChanged(bool); void readChanged(bool); void dontChangeReadChanged(bool); + void jsonStringChanged(QString); public slots: @@ -83,7 +87,11 @@ private: bool mRead; bool mDontChangeRead; QString mJsonString; + QString html2text(const QString htmlString); + void cacheImgs(); + void populateFromJson(QJsonObject post); + QNetworkAccessManager *mNetworkManager; }; #endif // POST_H diff --git a/src/tinytinyrss.cpp b/src/tinytinyrss.cpp index 4806c04..3cc5ae0 100644 --- a/src/tinytinyrss.cpp +++ b/src/tinytinyrss.cpp @@ -62,7 +62,7 @@ void TinyTinyRSS::reload() for(int i = 0; i < posts.count(); i++) { QJsonObject postJson = posts.at(i).toObject(); - Post *post = new Post(postJson, this); + Post *post = new Post(postJson, mNetworkManager, this); connect(post, SIGNAL(readChanged(bool)), this, SLOT(onPostReadChanged(bool))); mPosts.append(post); } diff --git a/src/tinytinyrsslogin.cpp b/src/tinytinyrsslogin.cpp index 2648e7a..f0536f2 100644 --- a/src/tinytinyrsslogin.cpp +++ b/src/tinytinyrsslogin.cpp @@ -88,47 +88,23 @@ void TinyTinyRSSLogin::reply() QNetworkReply *reply = qobject_cast(sender()); if (reply) { - if (reply->error() == QNetworkReply::NoError) { QString jsonString = QString(reply->readAll()); QJsonDocument json = QJsonDocument::fromJson(jsonString.toUtf8()); - if(json.object().value("content").toObject().value("error").toString().length() > 0) { + mSessionId = json.object().value("content").toObject().value("session_id").toString(); - mLoginError = json.object().value("content").toObject().value("error").toString(); - qWarning() << mLoginError; - emit loginErrorChanged(mLoginError); + emit sessionIdChanged(mSessionId); - if(mLoginError == "NOT_LOGGED_IN") { - mSessionId = nullptr; - mServerUrl = nullptr; + QSettings settings; + settings.setValue("sessionId", mSessionId); + settings.setValue("serverUrl", mServerUrl); + settings.sync(); - QSettings settings; - settings.remove("sessionId"); - settings.remove("serverUrl"); - settings.sync(); - - emit sessionIdChanged(mSessionId); - } - - } else { - mSessionId = json.object().value("content").toObject().value("session_id").toString(); - - emit sessionIdChanged(mSessionId); - - QSettings settings; - settings.setValue("sessionId", mSessionId); - settings.setValue("serverUrl", mServerUrl); - settings.sync(); - } } else { - mLoginError = "HTTP error: " - + reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString() - + " :: " - + reply->errorString(); - qWarning() << mLoginError; - - emit loginErrorChanged(mLoginError); + int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + //do some error management + qWarning() << "HTTP error: " << httpStatus << " :: " << reply->error(); } reply->deleteLater(); } diff --git a/src/tinytinyrsslogin.h b/src/tinytinyrsslogin.h index 5c21887..8971f2a 100644 --- a/src/tinytinyrsslogin.h +++ b/src/tinytinyrsslogin.h @@ -30,14 +30,12 @@ class TinyTinyRSSLogin : public QObject Q_OBJECT Q_PROPERTY(QString sessionId READ sessionId NOTIFY sessionIdChanged) Q_PROPERTY(QUrl serverUrl READ serverUrl) - Q_PROPERTY(QString loginError READ loginError NOTIFY loginErrorChanged) public: TinyTinyRSSLogin(QObject *parent = 0); ~TinyTinyRSSLogin(); QString sessionId() const { return mSessionId; } QUrl serverUrl() const { return mServerUrl; } - QString loginError() const { return mLoginError; } Q_INVOKABLE bool loggedIn(); Q_INVOKABLE void login(const QString serverUrl, const QString user, const QString password); @@ -45,7 +43,6 @@ public: signals: void sessionIdChanged(QString); - void loginErrorChanged(QString); private slots: void reply(); @@ -53,7 +50,6 @@ private slots: private: QString mSessionId; QUrl mServerUrl; - QString mLoginError; QNetworkAccessManager *mNetworkManager; };