[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet.spec
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -6,7 +6,7 @@
<service name="tar_git">
<param name="url">https://github.com/SfietKonstantin/harbour-twablet.git</param>
<param name="branch">master</param>
- <param name="revision">1a86de5d22d112c1f74fe5a93a0f8ea066f93b9f</param>
+ <param name="revision">387ccb363c0f690d33d80ea566ecff2e568c409d</param>
<param name="token"/>
<param name="debian">N</param>
<param name="dumb">N</param>
|
[-]
[+]
|
Deleted |
_service:tar_git:harbour-twablet-0.6.1.tar.bz2/src/bin/qml/pages/AccountsPage.qml
^
|
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2015 Lucien XU <sfietkonstantin@free.fr>
- *
- * You may use this file under the terms of the BSD license as follows:
- *
- * "Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * The names of its contributors may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- */
-
-import QtQuick 2.0
-import Sailfish.Silica 1.0
-import harbour.twablet 1.0
-
-Page {
- id: container
- allowedOrientations: app.defaultAllowedOrientations
- property bool initial: false
- onStatusChanged: {
- if (container.status === PageStatus.Active) {
- if (container.initial && accountModel.count > 0) {
- pageStack.replace(Qt.resolvedUrl("MainPage.qml"))
- }
- }
- }
-
- SilicaListView {
- id: view
- anchors.fill: parent
- model: accountModel
- header: PageHeader { title: qsTr("Accounts") }
- delegate: ListItem {
- id: item
- function remove() {
- remorseAction(qsTr("Removing account"), function() {
- Repository.removeAccount(index)
-
- if (!container.initial && accountModel.count === 0) {
- pageStack.clear()
- pageStack.push(Qt.resolvedUrl("AccountsPage.qml"), {initial: true})
- }
- })
- }
- menu: contextMenu
- contentHeight: Theme.itemSizeMedium
- ListView.onRemove: animateRemoval(item)
- onClicked: pageStack.push(Qt.resolvedUrl("AccountPage.qml"),
- {
- index: model.index,
- screenName: model.screenName,
- initialName: model.name
- })
-
- Column {
- spacing: Theme.paddingSmall
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin
- anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin
-
- Label {
- anchors.left: parent.left; anchors.right: parent.right
- text: model.name
- color: item.pressed ? Theme.highlightColor : Theme.primaryColor
- }
- Label {
- color: item.pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor
- text: model.screenName
- font.pixelSize: Theme.fontSizeSmall
- }
- }
-
- Component {
- id: contextMenu
- ContextMenu {
- MenuItem {
- text: qsTr("Remove")
- onClicked: remove()
- }
- }
- }
- }
-
-
- ViewPlaceholder {
- enabled: view.count === 0
- text: qsTr("There is no account defined. Pull down to add one account")
- }
-
- PullDownMenu {
- MenuItem {
- text: qsTr("Add account")
- onClicked: {
- var page = pageStack.push(Qt.resolvedUrl("AuthentificationPage.qml"))
- page.load()
- }
- }
- }
- }
-}
|
[-]
[+]
|
Deleted |
_service:tar_git:harbour-twablet-0.6.1.tar.bz2/src/lib/qml/querylistmodel.cpp
^
|
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2014 Lucien XU <sfietkonstantin@free.fr>
- *
- * You may use this file under the terms of the BSD license as follows:
- *
- * "Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * The names of its contributors may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- */
-
-#include "querylistmodel.h"
-#include "querytypeobject.h"
-
-namespace qml
-{
-
-QueryListModel::QueryListModel(QObject *parent) :
- QAbstractListModel(parent)
-{
- m_data.emplace_back(new Data {tr("Home"), QueryTypeObject::Home});
- m_data.emplace_back(new Data {tr("Mentions"), QueryTypeObject::Mentions});
- m_data.emplace_back(new Data {tr("Search"), QueryTypeObject::Search});
-}
-
-void QueryListModel::classBegin()
-{
-}
-
-void QueryListModel::componentComplete()
-{
-}
-
-int QueryListModel::rowCount(const QModelIndex &index) const
-{
- Q_UNUSED(index)
- return m_data.size();
-}
-
-QVariant QueryListModel::data(const QModelIndex &index, int role) const
-{
- int row = index.row();
- if (row < 0 || row >= rowCount()) {
- return QVariant();
- }
- const std::unique_ptr<Data> &data = m_data[row];
- switch (role) {
- case NameRole:
- return data->name;
- break;
- case QueryTypeRole:
- return data->type;
- break;
- default:
- return QVariant();
- break;
- }
-}
-
-int QueryListModel::count() const
-{
- return rowCount();
-}
-
-int QueryListModel::getType(int index)
-{
- if (index < 0 || index >= rowCount()) {
- return QueryTypeObject::InvalidTweetList;
- }
- return m_data[index]->type;
-}
-
-QHash<int, QByteArray> QueryListModel::roleNames() const
-{
- return {{NameRole, "name"}, {QueryTypeRole, "type"}};
-}
-
-}
|
[-]
[+]
|
Deleted |
_service:tar_git:harbour-twablet-0.6.1.tar.bz2/src/lib/qml/querylistmodel.h
^
|
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2014 Lucien XU <sfietkonstantin@free.fr>
- *
- * You may use this file under the terms of the BSD license as follows:
- *
- * "Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * The names of its contributors may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- */
-
-#ifndef QUERYLISTMODEL_H
-#define QUERYLISTMODEL_H
-
-#include <memory>
-#include <QtCore/QAbstractListModel>
-#include <QtQml/QQmlParserStatus>
-#include "querytypeobject.h"
-
-namespace qml
-{
-
-class QueryListModel : public QAbstractListModel, public QQmlParserStatus
-{
- Q_OBJECT
- Q_INTERFACES(QQmlParserStatus)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-public:
- enum Roles {
- NameRole = Qt::UserRole + 1,
- QueryTypeRole
- };
- explicit QueryListModel(QObject *parent = 0);
- void classBegin() override;
- void componentComplete() override;
- int rowCount(const QModelIndex &index = QModelIndex()) const override final;
- QVariant data(const QModelIndex &index, int role) const override final;
- int count() const;
-public slots:
- int getType(int index);
-signals:
- void countChanged();
-private:
- QHash<int, QByteArray> roleNames() const override final;
- struct Data
- {
- QString name;
- QueryTypeObject::TweetListType type;
- };
- std::vector<std::unique_ptr<Data>> m_data {};
-};
-
-}
-
-#endif // QUERYLISTMODEL_H
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/CMakeLists.txt
^
|
@@ -37,8 +37,8 @@
set(${PROJECT_NAME}_Qml_SRCS
qml/harbour-twablet.qml
qml/pages/MainPage.qml
- qml/pages/AccountsPage.qml
qml/pages/AuthentificationPage.qml
+ qml/pages/AccountPage.qml
qml/pages/ColumnLayout.qml
qml/pages/AddColumnPage.qml
qml/pages/Toolbar.qml
@@ -50,6 +50,7 @@
qml/pages/ToolbarButton.qml
qml/pages/RightPanel.qml
qml/pages/UserPage.qml
+ qml/pages/UserPageButton.qml
qml/pages/MiniButton.qml
qml/pages/UsersPage.qml
qml/pages/TweetsPage.qml
@@ -61,6 +62,9 @@
qml/pages/TweetHeader.qml
qml/pages/TweetText.qml
qml/pages/TweetFooter.qml
+ qml/pages/SettingsPage.qml
+ qml/pages/AccountDelegate.qml
+ qml/pages/LayoutItemDelegate.qml
qml/pages/LinkHandler.js
)
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/main.cpp
^
|
@@ -47,7 +47,7 @@
#include "qml/accountselectionmodel.h"
#include "qml/layoutmodel.h"
#include "qml/querytypeobject.h"
-#include "qml/querylistmodel.h"
+#include "qml/querytypemodel.h"
#include "qml/tweetmodel.h"
#include "qml/descriptionformatter.h"
#include "qml/tweetformatter.h"
@@ -120,7 +120,7 @@
qmlRegisterType<qml::AccountSelectionModel>("harbour.twablet", 1, 0, "AccountSelectionModel");
qmlRegisterType<qml::LayoutModel>("harbour.twablet", 1, 0, "LayoutModel");
qmlRegisterType<qml::TweetModel>("harbour.twablet", 1, 0, "TweetModel");
- qmlRegisterType<qml::QueryListModel>("harbour.twablet", 1, 0, "QueryListModel");
+ qmlRegisterType<qml::QueryTypeModel>("harbour.twablet", 1, 0, "QueryTypeModel");
qmlRegisterType<qml::DescriptionFormatter>("harbour.twablet", 1, 0, "DescriptionFormatter");
qmlRegisterType<qml::TweetFormatter>("harbour.twablet", 1, 0, "TweetFormatter");
qmlRegisterType<qml::QuotedTweetFormatter>("harbour.twablet", 1, 0, "QuotedTweetFormatter");
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/harbour-twablet.qml
^
|
@@ -44,7 +44,7 @@
Component.onCompleted: {
if (accountModel.count === 0) {
- pageStack.push(Qt.resolvedUrl("pages/AccountsPage.qml"), {initial: true})
+ pageStack.push(Qt.resolvedUrl("pages/SettingsPage.qml"), {initial: true})
} else {
pageStack.push(Qt.resolvedUrl("pages/MainPage.qml"))
}
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/AccountDelegate.qml
^
|
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+import harbour.twablet 1.0
+
+ListItem {
+ id: container
+ property int index
+ property alias name: name.text
+ property alias screenName: screenName.text
+ menu: contextMenu
+ contentHeight: Theme.itemSizeMedium
+ ListView.onRemove: animateRemoval(container)
+ signal removed()
+
+ Column {
+ spacing: Theme.paddingSmall
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin
+ anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin
+
+ Label {
+ id: name
+ anchors.left: parent.left; anchors.right: parent.right
+ color: container.pressed ? Theme.highlightColor : Theme.primaryColor
+ }
+ Label {
+ id: screenName
+ anchors.left: parent.left; anchors.right: parent.right
+ color: container.pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor
+ font.pixelSize: Theme.fontSizeSmall
+ }
+ }
+
+ Component {
+ id: contextMenu
+ ContextMenu {
+ MenuItem {
+ text: qsTr("Remove")
+ onClicked: container.removed()
+ }
+ }
+ }
+}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/AccountPage.qml
^
|
@@ -35,16 +35,19 @@
Dialog {
id: container
- canAccept: nameField.text.length > 0
- allowedOrientations: app.defaultAllowedOrientations
+ property SettingsPage parentPage: null
property int index: -1
property string userId
property string screenName
property string token
property string tokenSecret
property string initialName
+ readonly property bool editing: index != -1
+ canAccept: nameField.text.length > 0
+ allowedOrientations: app.defaultAllowedOrientations
+
onAccepted: {
- if (container.index == -1) {
+ if (!container.editing) {
var index = Repository.addAccount(nameField.text, container.userId, container.screenName,
container.token, container.tokenSecret)
Repository.addDefaultLayouts(index, qsTr("Home"), homeTl.checked,
@@ -62,7 +65,7 @@
anchors.left: parent.left; anchors.right: parent.right
DialogHeader {
id: header
- acceptText: qsTr("Add account")
+ acceptText: container.editing ? qsTr("Edit account") : qsTr("Add account")
}
Item {
@@ -94,16 +97,27 @@
}
TextSwitch {
id: homeTl
- visible: container.index === -1
+ visible: !container.editing
text: qsTr("Add home timeline")
checked: true
}
TextSwitch {
id: mentionsTl
- visible: container.index === -1
+ visible: !container.editing
text: qsTr("Add mentions timeline")
checked: true
}
}
+
+ PullDownMenu {
+ visible: container.editing
+ MenuItem {
+ text: qsTr("Remove")
+ onClicked: {
+ container.parentPage.removeAccount(container.index)
+ pageStack.pop()
+ }
+ }
+ }
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/AddColumnPage.qml
^
|
@@ -35,36 +35,50 @@
Dialog {
id: container
- property AccountModel accountModel
+ property SettingsPage parentPage: null
+ property int index: -1
+ property string initialName
+ property string initialAccountUserId
+ property int initialType: -1
+ property var initialParameters
+ readonly property bool editing: index != -1
canAccept: nameField.text.length > 0 && searchQuery.isSearchOk
allowedOrientations: app.defaultAllowedOrientations
onAccepted: {
var accountIndex = accountCombo.currentIndex
- var queryType = queryListModel.getType(queryCombo.currentIndex)
+ var queryType = queryTypeModel.getType(queryCombo.currentIndex)
var args = new Object
if (searchQuery.isSearch) {
args.q = searchQuery.text.trim()
args.result_type = resultTypeModel.get(resultTypeCombo.currentIndex).value
}
- Repository.addLayout(nameField.text, accountIndex, queryType, args)
+ if (!container.editing) {
+ Repository.addLayout(nameField.text, accountIndex, queryType, args)
+ } else {
+ Repository.updateLayout(container.index, nameField.text, accountIndex, queryType, args)
+ }
}
SilicaFlickable {
id: flickable
anchors.fill: parent
+ property bool editable: (container.initialAccountUserId.length == 0 && container.initialType == -1)
+ || ((container.initialAccountUserId.length > 0 && container.initialType != -1)
+ && accountCombo.currentIndex != -1 && queryCombo.currentIndex != -1)
Column {
anchors.left: parent.left; anchors.right: parent.right
DialogHeader {
id: header
- acceptText: qsTr("Add tab")
+ acceptText: container.editing ? qsTr("Edit column") : qsTr("Add column")
}
TextField {
id: nameField
+ text: initialName
anchors.left: parent.left; anchors.right: parent.right
placeholderText: qsTr("Name of the column")
label: qsTr("Name of the column")
@@ -72,10 +86,19 @@
ComboBox {
id: accountCombo
+ visible: flickable.editable
label: qsTr("Account")
menu: ContextMenu {
Repeater {
- model: container.accountModel
+ model: AccountModel {
+ id: accountModel
+ repository: Repository
+ Component.onCompleted: {
+ if (container.editing) {
+ accountCombo.currentIndex = accountModel.getIndex(container.initialAccountUserId)
+ }
+ }
+ }
delegate: MenuItem {
text: model.name
}
@@ -85,10 +108,18 @@
ComboBox {
id: queryCombo
+ visible: flickable.editable
label: qsTr("Column type")
menu: ContextMenu {
Repeater {
- model: QueryListModel {id: queryListModel}
+ model: QueryTypeModel {
+ id: queryTypeModel
+ Component.onCompleted: {
+ if (container.editing) {
+ queryCombo.currentIndex = queryTypeModel.getIndex(container.initialType)
+ }
+ }
+ }
delegate: MenuItem {
text: model.name
}
@@ -98,12 +129,18 @@
TextField {
id: searchQuery
- property bool isSearch: (queryListModel.getType(queryCombo.currentIndex) === QueryType.Search)
+ property bool isSearch: (queryTypeModel.getType(queryCombo.currentIndex) === QueryType.Search)
property bool isSearchOk: (isSearch && searchQuery.text.length > 0 || !isSearch)
anchors.left: parent.left; anchors.right: parent.right
visible: isSearch
placeholderText: qsTr("Search query")
label: qsTr("Search query")
+
+ Component.onCompleted: {
+ if (container.editing && container.initialType == QueryType.Search) {
+ searchQuery.text = container.initialParameters.q
+ }
+ }
}
ComboBox {
@@ -133,6 +170,31 @@
}
}
}
+ Component.onCompleted: {
+ if (container.editing && container.initialType == QueryType.Search) {
+ var resultType = container.initialParameters.result_type
+ if (resultType === "recent") {
+ resultTypeCombo.currentIndex = 0
+ } else if (resultType === "popular") {
+ resultTypeCombo.currentIndex = 1
+ } else if (resultType === "mixed") {
+ resultTypeCombo.currentIndex = 2
+ } else {
+ resultTypeCombo.currentIndex = -1
+ }
+ }
+ }
+ }
+ }
+
+ PullDownMenu {
+ visible: container.editing
+ MenuItem {
+ text: qsTr("Remove")
+ onClicked: {
+ container.parentPage.removeLayout(container.index)
+ pageStack.pop()
+ }
}
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/AuthentificationPage.qml
^
|
@@ -35,6 +35,7 @@
Dialog {
id: container
+ property bool initial: false
canAccept: false
allowedOrientations: app.defaultAllowedOrientations
Component.onCompleted: state = "initial"
@@ -54,13 +55,19 @@
error.text = errorMessage
}
onDone: {
- pageStack.replace(Qt.resolvedUrl("AccountPage.qml"),
- {
- userId: authentification.userId,
- screenName: authentification.screenName,
- token: authentification.token,
- tokenSecret: authentification.tokenSecret
- })
+ var args = {
+ userId: authentification.userId,
+ screenName: authentification.screenName,
+ token: authentification.token,
+ tokenSecret: authentification.tokenSecret
+ }
+ if (container.initial) {
+ args.acceptDestination = Qt.resolvedUrl("MainPage.qml")
+ args.acceptDestinationAction = PageStackAction.Replace
+ args.acceptDestinationReplaceTarget = null
+ }
+
+ pageStack.replace(Qt.resolvedUrl("AccountPage.qml"), args)
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/ColumnLayout.qml
^
|
@@ -36,6 +36,7 @@
Item {
id: container
property string title
+ property SilicaListView flickable: view
property alias query: twitterModel.query
signal handleLink(string url)
signal openTweet(string tweetId, string retweetId)
@@ -115,67 +116,18 @@
header: Column {
width: container.width
- ListItem {
+ PageHeader {
id: header
anchors.left: parent.left; anchors.right: parent.right
- onClicked: header.state = "visible"
- contentHeight: pageHeader.height
- enabled: !container.temporary
-
- PageHeader {
- id: pageHeader
- anchors.left: headerRemove.right; anchors.right: parent.right
- title: container.title
- height: Theme.itemSizeLarge
- _titleItem.color: header.pressed || container.temporary ? Theme.highlightColor: Theme.primaryColor
- }
+ title: container.title
+ height: Theme.itemSizeLarge
BusyIndicator {
- id: headerIndicator
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left; anchors.leftMargin: Theme.paddingMedium
- running: model.status === Model.Loading
+ running: twitterModel.status === Model.Loading
size: BusyIndicatorSize.Small
}
-
- IconButton {
- id: headerRemove
- anchors.left: headerIndicator.right; anchors.leftMargin: Theme.paddingMedium
- anchors.verticalCenter: parent.verticalCenter
- icon.source: "image://theme/icon-m-remove"
- enabled: !container.temporary
- opacity: 0
- onClicked: {
- headerTimer.stop()
- header.state = ""
- header.remorseAction(qsTr("Removing column"), function() {
- container.removed()
- })
- }
-
- Behavior on opacity { NumberAnimation { duration: 200 } }
- }
-
- Timer {
- id: headerTimer
- interval: 5000
- repeat: false
- onTriggered: header.state = ""
- }
-
- states: [
- State {
- name: "visible"
- PropertyChanges {
- target: headerRemove
- opacity: 1
- }
- PropertyChanges {
- target: headerTimer
- running: true
- }
- }
- ]
}
StatusHeader {
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/LayoutItemDelegate.qml
^
|
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+import harbour.twablet 1.0
+
+ListItem {
+ id: container
+ property Page page
+ property int index
+ property alias name: name.text
+ signal startMove(int index)
+ signal endMove()
+ signal dragEntered(int dragIndex, int dropIndex)
+ highlighted: down && !content.held
+ onPressAndHold: content.held = true
+ onReleased: content.held = false
+ drag.target: content.held ? content : undefined
+ drag.axis: Drag.YAxis
+ anchors.left: parent.left; anchors.right: parent.right
+ contentHeight: content.height
+
+ Item {
+ id: content
+ property bool held: false
+ width: container.width
+ height: Theme.itemSizeMedium
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ Drag.active: content.held
+ Drag.source: container
+ Drag.hotSpot.x: width / 2
+ Drag.hotSpot.y: height / 2
+
+ Label {
+ id: name
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin
+ anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin
+ color: container.pressed ? Theme.highlightColor : Theme.primaryColor
+ }
+
+ states: State {
+ name: "held"
+ when: content.held
+ ParentChange { target: content; parent: container.page }
+ AnchorChanges {
+ target: content
+ anchors { horizontalCenter: undefined; verticalCenter: undefined }
+ }
+ }
+ transitions: [
+ Transition {
+ from: ""
+ to: "held"
+ ScriptAction {
+ script: {
+ container.startMove(container.index)
+ }
+ }
+ },
+ Transition {
+ from: "held"
+ to: ""
+ ScriptAction {
+ script: {
+ container.endMove()
+ }
+ }
+ }
+ ]
+ }
+
+ DropArea {
+ anchors.fill: parent
+ onEntered: container.dragEntered(drag.source.index, container.index)
+ }
+}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/MainPage.qml
^
|
@@ -41,7 +41,7 @@
onStatusChanged: {
if (container.status === PageStatus.Active) {
if (accountModel.count === 0) {
- pageStack.replace(Qt.resolvedUrl("AccountsPage.qml"), {initial: true})
+ pageStack.replace(Qt.resolvedUrl("SettingsPage.qml"), {initial: true})
}
}
}
@@ -90,15 +90,13 @@
enabled: layoutModel.count > 0
onClicked: Repository.refresh()
}
-
MenuItem {
- text: qsTr("Accounts")
- onClicked: pageStack.push(Qt.resolvedUrl("AccountsPage.qml"))
+ text: qsTr("Search")
+ enabled: false
}
-
MenuItem {
- text: qsTr("About")
- onClicked: pageStack.push(Qt.resolvedUrl("AboutPage.qml"), {rightPanel: panel})
+ text: qsTr("Settings")
+ onClicked: pageStack.push(Qt.resolvedUrl("SettingsPage.qml"), {rightPanel: panel})
}
}
@@ -106,7 +104,7 @@
anchors.centerIn: parent
visible: layoutModel.count === 0
text: qsTr("Add column")
- onClicked: pageStack.push(Qt.resolvedUrl("AddColumnPage.qml"), {accountModel: accountModel})
+ onClicked: pageStack.push(Qt.resolvedUrl("AddColumnPage.qml"))
}
Item {
@@ -177,7 +175,7 @@
Button {
anchors.centerIn: parent
text: qsTr("Add column")
- onClicked: pageStack.push(Qt.resolvedUrl("AddColumnPage.qml"), {accountModel: accountModel})
+ onClicked: pageStack.push(Qt.resolvedUrl("AddColumnPage.qml"))
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/MiniButton.qml
^
|
@@ -35,12 +35,12 @@
BackgroundItem {
id: container
property alias text: text.text
- height: Theme.itemSizeMedium
+ height: Theme.itemSizeSmall
Label {
id: text
- anchors.left: parent.left; anchors.leftMargin: Theme.paddingMedium
- anchors.right: parent.right; anchors.rightMargin: Theme.paddingMedium
+ anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin
+ anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin
anchors.verticalCenter: parent.verticalCenter
truncationMode: TruncationMode.Fade
color: container.pressed ? Theme.highlightColor : Theme.primaryColor
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/RightPanel.qml
^
|
@@ -149,7 +149,7 @@
args.orientation = Orientation.Portrait
args.allowedOrientations = Orientation.Portrait
if (pushMode === Info.Replace) {
- pageStack.pop()
+ pageStack.pop(mainPage)
}
return panelPageStack.push(page, args)
} else {
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/SettingsPage.qml
^
|
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+import harbour.twablet 1.0
+
+Page {
+ id: container
+ property RightPanel rightPanel
+ property bool initial: false
+ function removeAccount(index) {
+ accounts.remove(index)
+ }
+ function removeLayout(index) {
+ layouts.remove(index)
+ }
+ allowedOrientations: app.defaultAllowedOrientations
+
+ Connections {
+ target: accountModel
+ onCountChanged: {
+ if (!container.initial && accountModel.count === 0) {
+ pageStack.clear()
+ pageStack.push(Qt.resolvedUrl("SettingsPage.qml"), {initial: true})
+ }
+ }
+ }
+
+ SilicaFlickable {
+ id: view
+ anchors.fill: parent
+ contentHeight: column.height
+
+ Column {
+ id: column
+ anchors.left: parent.left; anchors.right: parent.right
+
+ PageHeader {
+ anchors.left: parent.left; anchors.right: parent.right
+ title: qsTr("Settings")
+ }
+
+ Column {
+ id: accounts
+ signal remove(int index)
+ anchors.left: parent.left; anchors.right: parent.right
+ height: header.height + accountModel.count * Theme.itemSizeMedium
+ SectionHeader {
+ text: qsTr("Accounts")
+ }
+
+ Repeater {
+ model: accountModel
+ delegate: AccountDelegate {
+ id: accountDelegate
+ function remove() {
+ remorseAction(qsTr("Removing account"), function() {
+ Repository.removeAccount(accountDelegate.index)
+ })
+ }
+ index: model.index
+ name: model.name
+ screenName: model.screenName
+ onClicked: {
+ var args = {
+ index: model.index,
+ screenName: model.screenName,
+ initialName: model.name,
+ parentPage: container
+ }
+ pageStack.push(Qt.resolvedUrl("AccountPage.qml"), args)
+ }
+ onRemoved: remove()
+
+ Connections {
+ target: accounts
+ onRemove: {
+ if (model.index === index) {
+ accountDelegate.remove()
+ }
+ }
+ }
+ }
+ }
+
+ MiniButton {
+ height: Theme.itemSizeMedium
+ text: qsTr("Add account")
+ onClicked: {
+ var args = {
+ initial: container.initial
+ }
+ var page = pageStack.push(Qt.resolvedUrl("AuthentificationPage.qml"), args)
+ page.load()
+ }
+ }
+ }
+
+ Column {
+ id: layouts
+ signal remove(int index)
+ property int from: -1
+ property int to: -1
+ anchors.left: parent.left; anchors.right: parent.right
+ height: contentHeight
+ move: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ duration: 300
+ easing.type: Easing.OutQuad
+ }
+ }
+
+ SectionHeader {
+ text: qsTr("Columns")
+ visible: !container.initial || accountModel.count > 0
+ }
+
+ Repeater {
+ model: LayoutModel {
+ id: layoutModel
+ repository: Repository
+ }
+ delegate: LayoutItemDelegate {
+ id: layoutItemDelegate
+ function remove() {
+ layoutItemDelegate.remorseAction(qsTr("Removing column"), function() {
+ Repository.removeLayout(model.index)
+ })
+ }
+ page: container
+ index: model.index
+ name: model.name
+ onClicked: {
+ var args = {
+ index: model.index,
+ initialName: model.name,
+ initialAccountUserId: model.layout.accountUserId,
+ initialType: model.queryType,
+ initialParameters: model.layout.parameters,
+ parentPage: container
+ }
+ pageStack.push(Qt.resolvedUrl("AddColumnPage.qml"), args)
+ }
+ onStartMove: {
+ layoutModel.startMove()
+ layouts.from = index
+ }
+ onEndMove: {
+ Repository.moveLayout(layouts.from, layouts.to)
+ layoutModel.endMove()
+ layouts.from = -1
+ layouts.to = -1
+ }
+ onDragEntered: {
+ layoutModel.move(dragIndex, dropIndex)
+ layouts.to = dropIndex
+ }
+
+ Connections {
+ target: layouts
+ onRemove: {
+ if (model.index === index) {
+ layoutItemDelegate.remove()
+ }
+ }
+ }
+ }
+ }
+
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/Toolbar.qml
^
|
@@ -125,7 +125,7 @@
width: view.cellWidth
height: view.height
source: "image://theme/icon-m-add"
- onClicked: pageStack.push(Qt.resolvedUrl("AddColumnPage.qml"), {accountModel: accountModel})
+ onClicked: pageStack.push(Qt.resolvedUrl("AddColumnPage.qml"))
}
Rectangle {
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/UserPage.qml
^
|
@@ -168,19 +168,19 @@
Row {
anchors.left: parent.left; anchors.right: parent.right
- MiniButton {
+ UserPageButton {
width: parent.width / 3
text: queryItem.item ? qsTr("%n\ntweets", "", queryItem.item.statusesCount) : ""
onClicked: container.panel.openUserTimeline(container.userId, queryItem.item.screenName,
container.accountUserId, false)
}
- MiniButton {
+ UserPageButton {
width: parent.width / 3
text: queryItem.item ? qsTr("%n\nfollowing", "", queryItem.item.friendsCount) : ""
onClicked: container.panel.openFriends(container.userId, queryItem.item.screenName,
container.accountUserId, false)
}
- MiniButton {
+ UserPageButton {
width: parent.width / 3
text: queryItem.item ? qsTr("%n\nfollowers", "", queryItem.item.followersCount) : ""
onClicked: container.panel.openFollowers(container.userId, queryItem.item.screenName,
@@ -202,23 +202,23 @@
}
}
- MiniButton {
+ UserPageButton {
visible: queryItem.item && queryItem.item.displayUrl !== ""
text: queryItem.item ? queryItem.item.displayUrl : ""
onClicked: Qt.openUrlExternally(queryItem.item.url)
}
- MiniButton {
+ UserPageButton {
text: queryItem.item ? qsTr("%n favourites", "", queryItem.item.favouritesCount) : ""
onClicked: container.panel.openFavorites(container.userId, queryItem.item.screenName,
container.accountUserId, false)
}
- MiniButton {
+ UserPageButton {
text: qsTr("Subscribed lists")
}
- MiniButton {
+ UserPageButton {
text: queryItem.item ? qsTr("Listed in %n lists", "", queryItem.item.listedCount) : ""
}
}
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/qml/pages/UserPageButton.qml
^
|
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+
+BackgroundItem {
+ id: container
+ property alias text: text.text
+ height: Theme.itemSizeMedium
+
+ Label {
+ id: text
+ anchors.left: parent.left; anchors.leftMargin: Theme.paddingMedium
+ anchors.right: parent.right; anchors.rightMargin: Theme.paddingMedium
+ anchors.verticalCenter: parent.verticalCenter
+ truncationMode: TruncationMode.Fade
+ color: container.pressed ? Theme.highlightColor : Theme.primaryColor
+ }
+}
+
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/bin/res.qrc
^
|
@@ -1,7 +1,6 @@
<RCC>
<qresource prefix="/">
<file>qml/harbour-twablet.qml</file>
- <file>qml/pages/AccountsPage.qml</file>
<file>qml/pages/AccountPage.qml</file>
<file>qml/pages/AddColumnPage.qml</file>
<file>qml/pages/AuthentificationPage.qml</file>
@@ -36,5 +35,9 @@
<file>qml/pages/TweetHeader.qml</file>
<file>qml/pages/TweetText.qml</file>
<file>qml/pages/TweetFooter.qml</file>
+ <file>qml/pages/SettingsPage.qml</file>
+ <file>qml/pages/UserPageButton.qml</file>
+ <file>qml/pages/AccountDelegate.qml</file>
+ <file>qml/pages/LayoutItemDelegate.qml</file>
</qresource>
</RCC>
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/CMakeLists.txt
^
|
@@ -83,7 +83,7 @@
qml/tweetmodel.cpp
qml/usermodel.cpp
qml/mediamodel.cpp
- qml/querylistmodel.cpp
+ qml/querytypemodel.cpp
qml/accountselectionmodel.cpp
qml/iaccountrepositorycontainerobject.h
qml/ilayoutcontainerobject.h
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/irepositorylistener.h
^
|
@@ -82,6 +82,12 @@
*/
virtual void doRemove(int index) = 0;
/**
+ * @brief Notify that an item has moved
+ * @param from index of the item to move.
+ * @param to the item's new index.
+ */
+ virtual void doMove(int from, int to) = 0;
+ /**
* @brief Notify that the listened object is now invalid
*
* When called on this method, the listener should stop
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/private/conversionutil.cpp
^
|
@@ -46,5 +46,14 @@
return returned;
}
+QVariantMap convertParametersBack(const Query::Parameters ¶meters)
+{
+ QVariantMap returned {};
+ for (auto it = std::begin(parameters); it != std::end(parameters); ++it) {
+ returned.insert(QUrl::fromPercentEncoding(it->first), QUrl::fromPercentEncoding(it->second));
+ }
+ return returned;
+}
+
}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/private/conversionutil.h
^
|
@@ -39,6 +39,7 @@
{
Query::Parameters convertParameters(const QVariantMap ¶meters);
+QVariantMap convertParametersBack(const Query::Parameters ¶meters);
}
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/accountmodel.cpp
^
|
@@ -70,6 +70,16 @@
return it == std::end(m_items) ? nullptr : it->get();
}
+int AccountModel::getIndex(const QString &userId) const
+{
+ for (size_t i = 0; i < m_items.size(); ++i) {
+ if (m_items[i]->userId() == userId) {
+ return i;
+ }
+ }
+ return -1;
+}
+
QHash<int, QByteArray> AccountModel::roleNames() const
{
return {{NameRole, "name"}, {ScreenNameRole, "screenName"}, {AccountRole, "account"}};
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/accountmodel.h
^
|
@@ -51,6 +51,7 @@
QVariant data(const QModelIndex &index, int role) const override final;
public slots:
qml::AccountObject * get(const QString &userId) const;
+ int getIndex(const QString &userId) const;
private:
QHash<int, QByteArray> roleNames() const override final;
};
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/datarepositoryobject.cpp
^
|
@@ -178,22 +178,29 @@
void DataRepositoryObject::addLayout(const QString &name, int accountIndex, int queryType,
const QVariantMap ¶meters)
{
- QString userId {};
- if (!addLayoutCheckAccount(accountIndex, userId)) {
+ QString accountUserId {};
+ if (!addLayoutCheckAccount(accountIndex, accountUserId)) {
return;
}
- addLayout(name, userId, queryType, parameters);
+ addLayout(name, accountUserId, queryType, parameters);
}
-void DataRepositoryObject::addLayout(const QString &name, AccountObject *account, int queryType,
- const QVariantMap ¶meters)
+void DataRepositoryObject::addLayout(const QString &name, const QString &accountUserId,
+ int queryType, const QVariantMap ¶meters)
{
- if (account == nullptr) {
+ TweetListQuery query {
+ static_cast<TweetListQuery::Type>(queryType),
+ std::move(private_util::convertParameters(parameters))
+ };
+ if (!query.isValid()) {
return;
}
- addLayout(name, account->userId(), queryType, parameters);
+ m_tweetRepositoryContainer.referenceQuery(account(accountUserId), query);
+ m_layouts.append(std::move(Layout(name, accountUserId, std::move(query))));
+ m_loadSaveManager.save(m_layouts);
+ refresh();
}
void DataRepositoryObject::addDefaultLayouts(int accountIndex, const QString &homeName,
@@ -206,25 +213,45 @@
}
if (enableHomeTimeline) {
- m_layouts.append(Layout(homeName, userId, TweetListQuery(TweetListQuery::Home, TweetListQuery::Parameters())));
- referenceLastLayoutTweetList();
+ TweetListQuery query {TweetListQuery::Home, TweetListQuery::Parameters()};
+ m_tweetRepositoryContainer.referenceQuery(account(userId), query);
+ m_layouts.append(Layout{homeName, userId, std::move(query)});
}
if (enableMentionsTimeline) {
- m_layouts.append(Layout(mentionsName, userId, TweetListQuery(TweetListQuery::Mentions, TweetListQuery::Parameters())));
- referenceLastLayoutTweetList();
+ TweetListQuery query {TweetListQuery::Mentions, TweetListQuery::Parameters()};
+ m_tweetRepositoryContainer.referenceQuery(account(userId), query);
+ m_layouts.append(Layout{mentionsName, userId, std::move(query)});
}
m_loadSaveManager.save(m_layouts);
+ refresh();
}
-void DataRepositoryObject::updateLayoutName(int index, const QString &name)
+void DataRepositoryObject::updateLayout(int index, const QString &name, int accountIndex,
+ int queryType, const QVariantMap ¶meters)
{
if (index < 0 || index >= m_layouts.size()) {
return;
}
- Layout layout {*(std::begin(m_layouts) + index)};
- layout.setName(name);
+
+ QString accountUserId {};
+ if (!addLayoutCheckAccount(accountIndex, accountUserId)) {
+ return;
+ }
+
+ TweetListQuery query {
+ static_cast<TweetListQuery::Type>(queryType),
+ std::move(private_util::convertParameters(parameters))
+ };
+
+ const Layout &oldLayout {*(std::begin(m_layouts) + index)};
+ m_tweetRepositoryContainer.dereferenceQuery(account(oldLayout.accountUserId()), oldLayout.query());
+
+ Layout layout {name, accountUserId, std::move(query)};
+ m_tweetRepositoryContainer.referenceQuery(account(layout.accountUserId()), layout.query());
+
m_layouts.update(index, std::move(layout));
m_loadSaveManager.save(m_layouts);
+ refresh();
}
void DataRepositoryObject::updateLayoutUnread(int index, int unread)
@@ -247,6 +274,11 @@
m_loadSaveManager.save(m_layouts);
}
+void DataRepositoryObject::moveLayout(int from, int to)
+{
+ m_layouts.move(from, to);
+}
+
void DataRepositoryObject::refresh()
{
m_tweetRepositoryContainer.refresh();
@@ -342,23 +374,6 @@
}
}
-void DataRepositoryObject::addLayout(const QString &name, const QString &userId, int queryType,
- const QVariantMap ¶meters)
-{
- TweetListQuery query {
- static_cast<TweetListQuery::Type>(queryType),
- std::move(private_util::convertParameters(parameters))
- };
- if (!query.isValid()) {
- return;
- }
-
- m_layouts.append(std::move(Layout(name, userId, std::move(query))));
- referenceLastLayoutTweetList();
- m_loadSaveManager.save(m_layouts);
- refresh();
-}
-
bool DataRepositoryObject::addLayoutCheckAccount(int accountIndex, QString &userId)
{
if (accountIndex < 0 || accountIndex >= m_accounts.size()) {
@@ -369,12 +384,6 @@
return true;
}
-void DataRepositoryObject::referenceLastLayoutTweetList()
-{
- const Layout &layout {*(std::end(m_layouts) - 1)};
- m_tweetRepositoryContainer.referenceQuery(account(layout.accountUserId()), layout.query());
-}
-
void DataRepositoryObject::dereferenceLayoutTweetList(int index)
{
const Layout &layout {*(std::begin(m_layouts) + index)};
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/datarepositoryobject.h
^
|
@@ -89,13 +89,15 @@
// Layouts
void addLayout(const QString &name, int accountIndex, int queryType,
const QVariantMap ¶meters);
- void addLayout(const QString &name, AccountObject *account, int queryType,
+ void addLayout(const QString &name, const QString &accountUserId, int queryType,
const QVariantMap ¶meters);
void addDefaultLayouts(int accountIndex, const QString &homeName, bool enableHomeTimeline,
const QString &mentionsName, bool enableMentionsTimeline);
- void updateLayoutName(int index, const QString &name);
+ void updateLayout(int index, const QString &name, int accountIndex, int queryType,
+ const QVariantMap ¶meters);
void updateLayoutUnread(int index, int unread);
void removeLayout(int index);
+ void moveLayout(int from, int to);
void refresh();
void refresh(QObject *query);
void loadMore(QObject *query);
@@ -103,10 +105,7 @@
void setTweetRetweeted(const QString &tweetId);
void setTweetFavorited(const QString &tweetId, bool favorited);
private:
- void addLayout(const QString &name, const QString &userId, int queryType,
- const QVariantMap ¶meters);
bool addLayoutCheckAccount(int accountIndex, QString &userId);
- void referenceLastLayoutTweetList();
void dereferenceLayoutTweetList(int index);
QObjectPtr<QNetworkAccessManager> m_network {nullptr};
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/imodel.h
^
|
@@ -47,7 +47,7 @@
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
- Q_PROPERTY(qml::DataRepositoryObject * repository READ repository WRITE setRepository
+ Q_PROPERTY(QObject * repository READ repository WRITE setRepository
NOTIFY repositoryChanged)
Q_PROPERTY(QObject * query READ query WRITE setQuery NOTIFY queryChanged)
Q_ENUMS(Status)
@@ -63,10 +63,33 @@
virtual int count() const = 0;
virtual Status status() const = 0;
virtual QString errorMessage() const = 0;
- virtual DataRepositoryObject * repository() const = 0;
- virtual void setRepository(DataRepositoryObject *repository) = 0;
+ virtual QObject * repository() const = 0;
+ virtual void setRepository(QObject *repository) = 0;
virtual QObject * query() const = 0;
virtual void setQuery(QObject *query) = 0;
+public slots:
+ /**
+ * @brief Start a local move for this model
+ *
+ * Starting a local move will enable the model to move
+ * it's items without impacting the repository. This
+ * is done for following user input.
+ *
+ * When in a local move mode, the model stop listening
+ * about the move message from the repository.
+ */
+ virtual void startMove() = 0;
+ /**
+ * @brief Locally move an item
+ *
+ * @param from index of the item to move.
+ * @param to the item's new index.
+ */
+ virtual void move(int from, int to) = 0;
+ /**
+ * @brief Stop the local move for this model
+ */
+ virtual void endMove() = 0;
signals:
void countChanged();
void prependPre();
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/layoutobject.cpp
^
|
@@ -30,6 +30,7 @@
*/
#include "layoutobject.h"
+#include "private/conversionutil.h"
namespace qml
{
@@ -37,6 +38,7 @@
LayoutObject::LayoutObject(const Layout &data, QObject *parent)
: QObject(parent), m_data{data}
, m_query{new TweetListQueryWrapperObject(data.accountUserId(), data.query())}
+ , m_parameters{private_util::convertParametersBack(data.query().parameters())}
{
}
@@ -50,7 +52,7 @@
return m_data.name();
}
-QString LayoutObject::userId() const
+QString LayoutObject::accountUserId() const
{
return m_data.accountUserId();
}
@@ -70,6 +72,11 @@
return m_query.get();
}
+QVariantMap LayoutObject::parameters() const
+{
+ return m_parameters;
+}
+
void LayoutObject::update(const Layout &other)
{
if (m_data.name() != other.name()) {
@@ -77,9 +84,12 @@
emit nameChanged();
}
+ bool hasQueryChanged {false};
+
if (m_data.accountUserId() != other.accountUserId()) {
m_data.setAccountUserId(other.accountUserId());
- emit userIdChanged();
+ hasQueryChanged = true;
+ emit accountUserIdChanged();
}
if (m_data.query() != other.query()) {
@@ -89,6 +99,17 @@
if (m_data.query().type() != oldType) {
emit queryTypeChanged();
}
+ QVariantMap parameters = private_util::convertParametersBack(m_data.query().parameters());
+ if (m_parameters != parameters) {
+ m_parameters = parameters;
+ emit parametersChanged();
+ }
+ hasQueryChanged = true;
+ }
+
+ if (hasQueryChanged) {
+ m_query.reset(new TweetListQueryWrapperObject(m_data.accountUserId(), m_data.query()));
+ emit queryChanged();
}
if (m_data.unread() != other.unread()) {
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/layoutobject.h
^
|
@@ -46,27 +46,32 @@
{
Q_OBJECT
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
- Q_PROPERTY(QString userId READ userId NOTIFY userIdChanged)
+ Q_PROPERTY(QString accountUserId READ accountUserId NOTIFY accountUserIdChanged)
Q_PROPERTY(qml::QueryTypeObject::TweetListType queryType READ queryType NOTIFY queryTypeChanged)
- Q_PROPERTY(QObject * query READ query CONSTANT)
+ Q_PROPERTY(QObject * query READ query NOTIFY queryChanged)
+ Q_PROPERTY(QVariantMap parameters READ parameters NOTIFY parametersChanged)
public:
DISABLE_COPY_DISABLE_MOVE(LayoutObject);
static LayoutObject * create(const Layout &data, QObject *parent = 0);
QString name() const;
- QString userId() const;
+ QString accountUserId() const;
int unread() const;
QueryTypeObject::TweetListType queryType() const;
QObject * query() const;
+ QVariantMap parameters() const;
signals:
void nameChanged();
- void userIdChanged();
+ void accountUserIdChanged();
void queryTypeChanged();
void unreadChanged();
+ void queryChanged();
+ void parametersChanged();
private:
explicit LayoutObject(const Layout &data, QObject *parent = 0);
void update(const Layout &other);
Layout m_data {};
QObjectPtr<TweetListQueryWrapperObject> m_query {};
+ QVariantMap m_parameters {};
friend class Model<Layout, LayoutObject>;
};
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/model.h
^
|
@@ -80,11 +80,11 @@
{
return m_errorMessage;
}
- DataRepositoryObject * repository() const override
+ QObject * repository() const override
{
return m_repository;
}
- void setRepository(DataRepositoryObject *repository) override
+ void setRepository(QObject *repository) override
{
if (m_repository != repository) {
m_repository = repository;
@@ -104,6 +104,21 @@
emit queryChanged();
}
}
+public slots:
+ void startMove() override
+ {
+ m_localMove = true;
+ }
+ void move(int from, int to) override
+ {
+ if (m_localMove) {
+ performMove(from, to);
+ }
+ }
+ void endMove()
+ {
+ m_localMove = false;
+ }
protected:
explicit Model(QObject *parent = 0)
: IModel(parent) , IRepositoryListener<T>()
@@ -158,6 +173,12 @@
emit countChanged();
endRemoveRows();
}
+ void doMove(int from, int to) override
+ {
+ if (!m_localMove) {
+ performMove(from, to);
+ }
+ }
void doInvalidate() override
{
m_internalRepository = nullptr;
@@ -192,6 +213,9 @@
int oldSize = m_items.size();
int newSize = newItems.size();
int delta = newSize - oldSize;
+
+ qCDebug(mLogging) << "Refreshing data. Item delta:" << delta;
+
if (delta < 0) {
beginRemoveRows(QModelIndex(), newSize, oldSize - 1);
} else if (delta > 0) {
@@ -253,11 +277,30 @@
refreshData();
}
}
+ void performMove(int from, int to)
+ {
+ if (from < 0 || static_cast<std::size_t>(from) >= m_items.size()
+ || to < 0 || static_cast<std::size_t>(to) > m_items.size()) {
+ return;
+ }
+
+ if (!beginMoveRows(QModelIndex(), from, from, QModelIndex(), to)) {
+ return;
+ }
+
+ int toIndex = (to < from) ? to : to - 1;
+
+ QObjectPtr<O> item = std::move(*(std::begin(m_items) + from));
+ m_items.erase(std::begin(m_items) + from);
+ m_items.insert(std::begin(m_items) + toIndex, std::move(item));
+ endMoveRows();
+ }
bool m_complete {false};
+ bool m_localMove {false};
Status m_status {Idle};
QString m_errorMessage {};
- DataRepositoryObject *m_repository {nullptr};
+ QObject *m_repository {nullptr};
QObject *m_query {nullptr};
QString m_internalAccountUserId {};
Query m_internalQuery {};
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/querytypemodel.cpp
^
|
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#include "querytypemodel.h"
+#include "querytypeobject.h"
+
+namespace qml
+{
+
+QueryTypeModel::QueryTypeModel(QObject *parent) :
+ QAbstractListModel(parent)
+{
+ m_items.emplace_back(new Data {tr("Home"), QueryTypeObject::Home});
+ m_items.emplace_back(new Data {tr("Mentions"), QueryTypeObject::Mentions});
+ m_items.emplace_back(new Data {tr("Search"), QueryTypeObject::Search});
+}
+
+void QueryTypeModel::classBegin()
+{
+}
+
+void QueryTypeModel::componentComplete()
+{
+}
+
+int QueryTypeModel::rowCount(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ return m_items.size();
+}
+
+QVariant QueryTypeModel::data(const QModelIndex &index, int role) const
+{
+ int row = index.row();
+ if (row < 0 || row >= rowCount()) {
+ return QVariant();
+ }
+ const std::unique_ptr<Data> &data = m_items[row];
+ switch (role) {
+ case NameRole:
+ return data->name;
+ break;
+ case QueryTypeRole:
+ return data->type;
+ break;
+ default:
+ return QVariant();
+ break;
+ }
+}
+
+int QueryTypeModel::count() const
+{
+ return rowCount();
+}
+
+int QueryTypeModel::getType(int index)
+{
+ if (index < 0 || index >= rowCount()) {
+ return QueryTypeObject::InvalidTweetList;
+ }
+ return m_items[index]->type;
+}
+
+int QueryTypeModel::getIndex(int type)
+{
+ for (size_t i = 0; i < m_items.size(); ++i) {
+ if (m_items[i]->type == type) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+QHash<int, QByteArray> QueryTypeModel::roleNames() const
+{
+ return {{NameRole, "name"}, {QueryTypeRole, "type"}};
+}
+
+}
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/qml/querytypemodel.h
^
|
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef QUERYTYPEMODEL_H
+#define QUERYTYPEMODEL_H
+
+#include <memory>
+#include <QtCore/QAbstractListModel>
+#include <QtQml/QQmlParserStatus>
+#include "querytypeobject.h"
+
+namespace qml
+{
+
+class QueryTypeModel : public QAbstractListModel, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+public:
+ enum Roles {
+ NameRole = Qt::UserRole + 1,
+ QueryTypeRole
+ };
+ explicit QueryTypeModel(QObject *parent = 0);
+ void classBegin() override final;
+ void componentComplete() override final;
+ int rowCount(const QModelIndex &index = QModelIndex()) const override final;
+ QVariant data(const QModelIndex &index, int role) const override final;
+ int count() const;
+public slots:
+ int getType(int index);
+ int getIndex(int type);
+signals:
+ void countChanged();
+private:
+ QHash<int, QByteArray> roleNames() const override final;
+ struct Data
+ {
+ QString name;
+ QueryTypeObject::TweetListType type;
+ };
+ std::vector<std::unique_ptr<Data>> m_items {};
+};
+
+}
+
+#endif // QUERYTYPEMODEL_H
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/lib/repository.h
^
|
@@ -97,7 +97,6 @@
listener->doPrepend(data);
}
}
-
void update(int index, T &&data)
{
if (index < 0 || static_cast<std::size_t>(index) >= m_data.size()) {
@@ -118,6 +117,26 @@
listener->doRemove(index);
}
}
+ void move(int from, int to)
+ {
+ if (from < 0 || static_cast<std::size_t>(from) >= m_data.size()
+ || to < 0 || static_cast<std::size_t>(to) > m_data.size()) {
+ return;
+ }
+
+ if (to == from || to == from + 1) {
+ return;
+ }
+
+ int toIndex = (to < from) ? to : to - 1;
+
+ T data {*(std::begin(m_data) + from)};
+ m_data.erase(std::begin(m_data) + from);
+ m_data.insert(std::begin(m_data) + toIndex, data);
+ for (IRepositoryListener<T> *listener : m_listeners) {
+ listener->doMove(from, to);
+ }
+ }
void start()
{
m_status = Loading;
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/tests/CMakeLists.txt
^
|
@@ -27,7 +27,9 @@
set(${PROJECT_NAME}_SRCS
testrepositorylistener.h
+ testmodel.cpp
tst_main.cpp
+ tst_model.cpp
tst_account.cpp
tst_layout.cpp
tst_loadsavemanager.cpp
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/tests/testmodel.cpp
^
|
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2014 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#include "testmodel.h"
+
+TestData::TestData(int value)
+ : m_value{value}
+{
+}
+
+int TestData::value() const
+{
+ return m_value;
+}
+
+TestDataObject::TestDataObject(const TestData &data, QObject *parent)
+ : QObject(parent), m_data{data}
+{
+}
+
+TestDataObject * TestDataObject::create(const TestData &data, QObject *parent)
+{
+ return new TestDataObject{data, parent};
+}
+
+int TestDataObject::value() const
+{
+ return m_data.value();
+}
+
+void TestDataObject::update(const TestData &data)
+{
+ Q_UNUSED(data)
+}
+
+TestRepositoryContainer::TestRepositoryContainer(QObject *parent)
+ : QObject(parent)
+{
+}
+
+TestRepository & TestRepositoryContainer::repository()
+{
+ return m_repository;
+}
+
+TestModel::TestModel(QObject *parent)
+ : Model<TestData, TestDataObject>(parent)
+{
+}
+
+QVariant TestModel::data(const QModelIndex &index, int role) const
+{
+ int row = index.row();
+ if (row < 0 || row >= rowCount()) {
+ return QVariant();
+ }
+ const QObjectPtr<TestDataObject> &data = m_items[row];
+ switch (role) {
+ case ValueRole:
+ return data->value();
+ break;
+ case ItemRole:
+ return QVariant::fromValue(data.get());
+ break;
+ default:
+ return QVariant();
+ break;
+ }
+}
+
+QHash<int, QByteArray> TestModel::roleNames() const
+{
+ return {{ValueRole, "value"}, {ItemRole, "item"}};
+}
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/tests/testmodel.h
^
|
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2014 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef TESTMODEL_H
+#define TESTMODEL_H
+
+#include <repository.h>
+#include <qml/model.h>
+
+class TestData
+{
+public:
+ explicit TestData() = default;
+ DEFAULT_COPY_DEFAULT_MOVE(TestData);
+ explicit TestData(int value);
+ int value() const;
+private:
+ int m_value {-1};
+};
+
+class TestDataObject: public QObject
+{
+ Q_OBJECT
+public:
+ static TestDataObject * create(const TestData &data, QObject *parent = 0);
+ int value() const;
+ void update(const TestData &data);
+private:
+ explicit TestDataObject(const TestData &data, QObject *parent = 0);
+ TestData m_data {};
+};
+
+Q_DECLARE_METATYPE(TestDataObject *)
+
+using TestRepository = Repository<TestData>;
+
+class TestRepositoryContainer: public QObject
+{
+ Q_OBJECT
+public:
+ explicit TestRepositoryContainer(QObject *parent = 0);
+ TestRepository & repository();
+private:
+ TestRepository m_repository {};
+};
+
+namespace qml
+{
+
+template<> class DataRepositoryObjectMap<TestData>
+{
+public:
+ static void getQueryInfo(QObject *queryWrapper, QString &accountUserId, Query &query)
+ {
+ Q_UNUSED(queryWrapper)
+ Q_UNUSED(accountUserId)
+ Q_UNUSED(query)
+ }
+ static Repository<TestData> * get(QObject &object, const QString &accountUserId, const Query &query)
+ {
+ Q_UNUSED(accountUserId)
+ Q_UNUSED(query)
+ TestRepositoryContainer *container = qobject_cast<TestRepositoryContainer *>(&object);
+ return container != nullptr ? &(container->repository()) : nullptr;
+ }
+ static void addListener(Repository<TestData> &repository, IRepositoryListener<TestData> &listener,
+ QObject *object, const QString &accountUserId, const Query &query)
+ {
+ Q_UNUSED(object)
+ Q_UNUSED(accountUserId)
+ Q_UNUSED(query)
+ repository.addListener(listener);
+ }
+ static void removeListener(Repository<TestData> &repository, IRepositoryListener<TestData> &listener,
+ QObject *object, const QString &accountUserId, const Query &query)
+ {
+ Q_UNUSED(object)
+ Q_UNUSED(accountUserId)
+ Q_UNUSED(query)
+ repository.removeListener(listener);
+ }
+};
+
+}
+
+class TestModel: public qml::Model<TestData, TestDataObject>
+{
+ Q_OBJECT
+public:
+ enum Roles {
+ ValueRole = Qt::UserRole + 1,
+ ItemRole
+ };
+ explicit TestModel(QObject *parent = 0);
+ QVariant data(const QModelIndex &index, int role) const override final;
+private:
+ QHash<int, QByteArray> roleNames() const override final;
+
+};
+
+#endif // TESTMODEL_H
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/tests/testrepositorylistener.h
^
|
@@ -58,59 +58,65 @@
Prepend,
Append,
Update,
- Remove
+ Remove,
+ Move
};
explicit Data() = default;
explicit Data(Status status, InsertionType insertionType,
const std::vector<QString> &insertedIds, const QString &updatedId,
- int index)
+ int index1, int index2)
: status{status}, insertionType{insertionType}, insertedIds{insertedIds}
- , updatedId{updatedId}, index{index}
+ , updatedId{updatedId}, index1{index1}, index2{index2}
{
}
static Data createAppend(const std::vector<QString> &itemsIds)
{
- return Data(NoChangeStatus, Append, itemsIds, QString{}, -1);
+ return Data(NoChangeStatus, Append, itemsIds, QString{}, -1, -1);
}
static Data createPrepend(const std::vector<QString> &itemsIds)
{
- return Data(NoChangeStatus, Prepend, itemsIds, QString{}, -1);
+ return Data(NoChangeStatus, Prepend, itemsIds, QString{}, -1, -1);
}
static Data createUpdate(int index, const QString &itemId)
{
- return Data(NoChangeStatus, Update, std::vector<QString>{}, itemId, index);
+ return Data(NoChangeStatus, Update, std::vector<QString>{}, itemId, index, -1);
}
static Data createRemove(int index)
{
- return Data(NoChangeStatus, Prepend, std::vector<QString>{}, QString{}, index);
+ return Data(NoChangeStatus, Prepend, std::vector<QString>{}, QString{}, index, -1);
+ }
+ static Data createMove(int start, int end)
+ {
+ return Data(NoChangeStatus, Move, std::vector<QString>{}, QString{}, start, end);
}
static Data createInvalidate()
{
- return Data(Invalidated, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1);
+ return Data(Invalidated, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1, -1);
}
static Data createIdle()
{
- return Data(Idle, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1);
+ return Data(Idle, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1, -1);
}
static Data createLoading()
{
- return Data(Loading, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1);
+ return Data(Loading, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1, -1);
}
static Data createError()
{
- return Data(Error, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1);
+ return Data(Error, NoChangeInsertionType, std::vector<QString>{}, QString{}, -1, -1);
}
bool operator==(const Data &other) const
{
return status == other.status && insertionType == other.insertionType
&& insertedIds == other.insertedIds && updatedId == other.updatedId
- && index == other.index;
+ && index1 == other.index1 && index2 == other.index2;
}
Status status {InvalidStatus};
InsertionType insertionType {InvalidInsertionType};
std::vector<QString> insertedIds{};
QString updatedId {};
- int index {-1};
+ int index1 {-1};
+ int index2 {-1};
};
std::vector<Data> data {};
private:
@@ -142,6 +148,10 @@
{
data.emplace_back(Data::createRemove(index));
}
+ void doMove(int start, int end) override
+ {
+ data.emplace_back(Data::createMove(start, end));
+ }
void doInvalidate() override
{
data.emplace_back(Data::createInvalidate());
|
[-]
[+]
|
Changed |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/tests/tst_loadsavemanager.cpp
^
|
@@ -29,7 +29,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
-
#include <gtest/gtest.h>
#include <memory>
#include <QtCore/QCoreApplication>
|
[-]
[+]
|
Added |
_service:tar_git:harbour-twablet-0.6.2.tar.bz2/src/tests/tst_model.cpp
^
|
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 Lucien XU <sfietkonstantin@free.fr>
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * The names of its contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#include <gtest/gtest.h>
+#include "testmodel.h"
+
+TEST(repository, Move)
+{
+ TestRepositoryContainer container {};
+ container.repository().append(TestData(0));
+ container.repository().append(TestData(1));
+ container.repository().append(TestData(2));
+ container.repository().append(TestData(3));
+
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 0);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 3);
+
+ container.repository().move(1, 0);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 0);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 3);
+
+ container.repository().move(0, 2);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 0);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 3);
+
+ container.repository().move(0, 3);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 0);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 3);
+
+ container.repository().move(2, 4);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 3);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 0);
+
+ container.repository().move(1, 3);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 3);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 0);
+
+ // Invalid move
+ container.repository().move(0, 5);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 3);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 0);
+
+ container.repository().move(4, 0);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 3);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 0);
+
+ container.repository().move(0, 1);
+ EXPECT_EQ((std::begin(container.repository()) + 0)->value(), 1);
+ EXPECT_EQ((std::begin(container.repository()) + 1)->value(), 3);
+ EXPECT_EQ((std::begin(container.repository()) + 2)->value(), 2);
+ EXPECT_EQ((std::begin(container.repository()) + 3)->value(), 0);
+}
+
+static int getValue(TestModel &model, int index)
+{
+ return model.data(model.index(index), TestModel::ValueRole).toInt();
+}
+
+TEST(model, LocalMove)
+{
+ TestRepositoryContainer container {};
+ container.repository().append(TestData(0));
+ container.repository().append(TestData(1));
+ container.repository().append(TestData(2));
+ container.repository().append(TestData(3));
+
+ TestModel model {};
+ model.classBegin();
+ model.setRepository(&container);
+ model.componentComplete();
+
+ EXPECT_EQ(model.count(), 4);
+ EXPECT_EQ(getValue(model, 0), 0);
+ EXPECT_EQ(getValue(model, 1), 1);
+ EXPECT_EQ(getValue(model, 2), 2);
+ EXPECT_EQ(getValue(model, 3), 3);
+
+ model.startMove();
+ model.move(1, 0);
+ EXPECT_EQ(getValue(model, 0), 1);
+ EXPECT_EQ(getValue(model, 1), 0);
+ EXPECT_EQ(getValue(model, 2), 2);
+ EXPECT_EQ(getValue(model, 3), 3);
+
+ model.move(0, 2);
+ EXPECT_EQ(getValue(model, 0), 0);
+ EXPECT_EQ(getValue(model, 1), 1);
+ EXPECT_EQ(getValue(model, 2), 2);
+ EXPECT_EQ(getValue(model, 3), 3);
+
+ model.move(0, 3);
+ EXPECT_EQ(getValue(model, 0), 1);
+ EXPECT_EQ(getValue(model, 1), 2);
+ EXPECT_EQ(getValue(model, 2), 0);
+ EXPECT_EQ(getValue(model, 3), 3);
+
+ model.move(2, 4);
+ EXPECT_EQ(getValue(model, 0), 1);
+ EXPECT_EQ(getValue(model, 1), 2);
+ EXPECT_EQ(getValue(model, 2), 3);
+ EXPECT_EQ(getValue(model, 3), 0);
+
+ model.move(1, 3);
+ EXPECT_EQ(getValue(model, 0), 1);
+ EXPECT_EQ(getValue(model, 1), 3);
+ EXPECT_EQ(getValue(model, 2), 2);
+ EXPECT_EQ(getValue(model, 3), 0);
+
+ // Invalid move
+ model.move(0, 5);
+ EXPECT_EQ(getValue(model, 0), 1);
+ EXPECT_EQ(getValue(model, 1), 3);
+ EXPECT_EQ(getValue(model, 2), 2);
+ EXPECT_EQ(getValue(model, 3), 0);
+
+ model.move(4, 0);
+ EXPECT_EQ(getValue(model, 0), 1);
+ EXPECT_EQ(getValue(model, 1), 3);
+ EXPECT_EQ(getValue(model, 2), 2);
+ EXPECT_EQ(getValue(model, 3), 0);
+
+ model.move(0, 1);
+ EXPECT_EQ(getValue(model, 0), 1);
+ EXPECT_EQ(getValue(model, 1), 3);
+ EXPECT_EQ(getValue(model, 2), 2);
+ EXPECT_EQ(getValue(model, 3), 0);
+ model.endMove();
+}
|