From 711f20225524f059da9296f814a06ab9332bb324 Mon Sep 17 00:00:00 2001 From: lvaatamoinen Date: Sun, 29 Jan 2012 14:00:40 +0000 Subject: [PATCH 1/1] Initial commit for the QML client: Adding data to model works, currently testdata used. TODO: Make torrent adding work, use real data. TODO: Add real functionality: status update, torrent removal. git-svn-id: file:///svnroot/qtrapids/trunk@82 42ac0dd5-4c8c-4c71-bb3e-ecdfe252ffda --- src/client/CMakeLists.txt | 59 ++-- src/client/main.cpp | 137 +++++---- src/client/models/Plugin.cpp | 19 ++ src/client/models/Plugin.h | 18 ++ .../models/QDeclarativeDownloadListModel.cpp | 304 ++++++++++++++++++++ src/client/models/QDeclarativeDownloadListModel.h | 129 +++++++++ .../models/QDeclarativeDownloadListModel_p.h | 30 ++ src/client/models/qmldir | 1 + src/client/proxy.cpp | 26 ++ src/client/proxy.h | 90 ++++++ src/client/qml/MainPage.qml | 177 ++++++++++++ src/client/qml/main.qml | 36 +++ src/client/qml/qml.qrc | 9 + 13 files changed, 969 insertions(+), 66 deletions(-) create mode 100644 src/client/models/Plugin.cpp create mode 100644 src/client/models/Plugin.h create mode 100644 src/client/models/QDeclarativeDownloadListModel.cpp create mode 100644 src/client/models/QDeclarativeDownloadListModel.h create mode 100644 src/client/models/QDeclarativeDownloadListModel_p.h create mode 100644 src/client/models/qmldir create mode 100644 src/client/proxy.cpp create mode 100644 src/client/proxy.h create mode 100644 src/client/qml/DownloadView.qml create mode 100644 src/client/qml/MainPage.qml create mode 100644 src/client/qml/SeedView.qml create mode 100644 src/client/qml/main.qml create mode 100644 src/client/qml/qml.qrc diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index da3d8b5..873b699 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -1,6 +1,12 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +set(QT_USE_QTDECLARATIVE 1) + +FIND_PACKAGE(Qt4 REQUIRED) + INCLUDE(${QT_USE_FILE}) -INCLUDE_DIRECTORIES(../include ../plugins) +INCLUDE_DIRECTORIES(${qtrapids_SOURCE_DIR}/src/include ${qtrapids_SOURCE_DIR}/src/plugins) FIND_LIBRARY(BOOST_SYSTEM boost_system-mt) IF(${BOOST_SYSTEM} STREQUAL BOOST_SYSTEM-NOTFOUND) @@ -12,32 +18,48 @@ INCLUDE_DIRECTORIES( ${QT_QTTEST_INCLUDE_DIR} ${QT_QTDBUS} ${QT_QTGUI} + ${QT_QTDECLARATIVE_INCLUDE_DIR} ) SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/proxy.cpp ${CMAKE_CURRENT_SOURCE_DIR}/proxy.h PROPERTIES GENERATED 1) SET(MOC_HEADERS - ./DownloadView.h - ./MainWindow.h - ./PreferencesDialog.h - ./proxy.h - ./SeedView.h - ./ColumnSelectorDialog.h + ./models/QDeclarativeDownloadListModel.h + ./models/QDeclarativeDownloadListModel_p.h +# ./DownloadView.h +# ./models/Plugin.h +# ./MainWindow.h +# ./PreferencesDialog.h +# ./proxy.h +# ./SeedView.h +# ./ColumnSelectorDialog.h ) SET(SRC - ./DownloadView.cpp - ./main.cpp - ./MainWindow.cpp - ./PreferencesDialog.cpp - ./proxy.cpp - ./SeedView.cpp - ./ColumnSelectorDialog.cpp +# ./DownloadView.cpp + ./main.cpp + ./models/QDeclarativeDownloadListModel.cpp +# ./MainWindow.cpp +# ./PreferencesDialog.cpp +# ./proxy.cpp +# ./SeedView.cpp +# ./ColumnSelectorDialog.cpp ) + +# Set the resource files to be used. +# Add all .qrc files here, that are needed. +SET(RCCS qml/qml.qrc) + +# generate rules for building source files from the resources +QT4_ADD_RESOURCES(RCC_SRC ${RCCS}) +# generate rules for building source files that moc generates +QT4_WRAP_CPP(QtApp_MOC_SRCS ${QtApp_MOCS}) + QT4_WRAP_CPP(SRC ${MOC_HEADERS}) -ADD_EXECUTABLE(qtrapids-gui ${SRC} ${MOC_HEADERS}) -INSTALL(TARGETS qtrapids-gui DESTINATION bin) +# Build the executable from these files: +ADD_EXECUTABLE(qml-client ${SRC} ${MOC_HEADERS} ${RCC_SRC}) +INSTALL(TARGETS qml-client DESTINATION bin) ADD_DEFINITIONS(-DQT_SHARED) @@ -54,17 +76,18 @@ if(NOT QT_QTMAEMO5_LIBRARY) endif(NOT QT_QTMAEMO5_LIBRARY) -TARGET_LINK_LIBRARIES(qtrapids-gui +TARGET_LINK_LIBRARIES(qml-client ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTDBUS_LIBRARY} ${QT_QTTEST_LIBRARY} + ${QT_QTDECLARATIVE_LIBRARY} -lboost_system-mt ) # Check if we are building under scratchbox and link with QtMaemo5 only in that case. # Thus, we maintain desktop build-ability also -set (SCRATCHBOX_UNAME $ENV{SBOX_UNAME_MACHINE}) +#set (SCRATCHBOX_UNAME $ENV{SBOX_UNAME_MACHINE}) if (SCRATCHBOX_UNAME) MESSAGE("Configuring for building under Scratchbox..") diff --git a/src/client/main.cpp b/src/client/main.cpp index 524da17..9d992b8 100644 --- a/src/client/main.cpp +++ b/src/client/main.cpp @@ -16,13 +16,17 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include +#include +#include #include #include //#include //#include "DownloadView.h" - +#include +#include "models/QDeclarativeDownloadListModel.h" #include "MainWindow.h" +#include "../include/qtrapids/dbus.hpp" using qtrapids::MainWindow; @@ -30,51 +34,88 @@ int main(int argc, char *argv[]) { - - QCoreApplication::setOrganizationName("Ixonos"); - QCoreApplication::setOrganizationDomain("ixonos.com"); - QCoreApplication::setApplicationName("QtRapids"); - - // Q_INIT_RESOURCE(application); - QApplication app(argc, argv); - MainWindow mainWindow; - - QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/qtrapids_gui", &mainWindow); - dbus.registerService("com.ixonos.qtrapids_gui"); - - mainWindow.connectToServer(); - mainWindow.RestoreSettings(); - // mainWindow->setGeometry(QApplication::desktop()->screenGeometry()); - - mainWindow.show(); - - /* - DownloadView* dlw = new DownloadView(NULL); - //qtrapids * mw = new qtrapids(); - dlw->show(); - DownloadViewItem* dlwItem = new DownloadViewItem(QStringList() << "Name" - << "Size" << "Status" - << "Progress" << "DL speed" - << "UL speed" << "Seeds/Leechers" - << "ratio"); - DownloadViewItem* dlwItem2 = new DownloadViewItem(QStringList() << "Name" - << "1000" << "Downloading" - << "23%" << "11" - << "0.1" << "0/2" - << "1.10"); - //dlwItem->insertChild(0, new DownloadViewItem(QStringList() << "Name")); - dlw->insertTopLevelItem(0,dlwItem); - dlw->insertTopLevelItem(1,dlwItem2); - - for (unsigned i = 0; i < 10; ++i) - { - DownloadViewItem *editItem = dynamic_cast - (dlw->itemAt(QPoint(0,0))); - editItem->setData ( 8, Qt::DisplayRole, QVariant("EDITED" + QString::number(i, 'g', 2))); - QTest::qSleep(2000); - } - */ - - return app.exec(); + + QCoreApplication::setOrganizationName("Ixonos"); + QCoreApplication::setOrganizationDomain("ixonos.com"); + QCoreApplication::setApplicationName("QtRapids"); + + // Q_INIT_RESOURCE(application); + QApplication app(argc, argv); + //MainWindow mainWindow; + app.setProperty("NoMStyle", true); + + // Register our types: + qmlRegisterType("QtRapids", 1, 0, "DownloadListModel"); + + QDir::setCurrent(app.applicationDirPath()); + + QDeclarativeView window; + //QDeclarativeEngine engine; + qtrapids::QDeclarativeDownloadListModel downloadModel; + QDeclarativeContext *context = window.rootContext(); + context->setContextProperty("downloadModel", &downloadModel); + window.setSource(QUrl("qrc:/main.qml")); + + window.showFullScreen(); +// window.show(); + + + /* TODO: Enable this once we have the views up & running + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject("/qtrapids_gui", &mainWindow); + dbus.registerService("com.ixonos.qtrapids_gui"); + + mainWindow.connectToServer(); + mainWindow.RestoreSettings(); + + // mainWindow->setGeometry(QApplication::desktop()->screenGeometry()); + + mainWindow.show(); + */ + /* + DownloadView* dlw = new DownloadView(NULL); + //qtrapids * mw = new qtrapids(); + dlw->show(); + DownloadViewItem* dlwItem = new DownloadViewItem(QStringList() << "Name" + << "Size" << "Status" + << "Progress" << "DL speed" + << "UL speed" << "Seeds/Leechers" + << "ratio"); + DownloadViewItem* dlwItem2 = new DownloadViewItem(QStringList() << "Name" + << "1000" << "Downloading" + << "23%" << "11" + << "0.1" << "0/2" + << "1.10"); + //dlwItem->insertChild(0, new DownloadViewItem(QStringList() << "Name")); + dlw->insertTopLevelItem(0,dlwItem); + dlw->insertTopLevelItem(1,dlwItem2); + + for (unsigned i = 0; i < 10; ++i) + { + DownloadViewItem *editItem = dynamic_cast + (dlw->itemAt(QPoint(0,0))); + editItem->setData ( 8, Qt::DisplayRole, QVariant("EDITED" + QString::number(i, 'g', 2))); + QTest::qSleep(2000); + } + */ + + qtrapids::TorrentState editItem; + for (unsigned i = 0; i < 10; ++i) + { + editItem.hash = QString("asdfasdfasdfasdfasfsd-") + QString::number(i); + editItem.name = QString("Lassi-") + QString::number(i); + editItem.action = qtrapids::TorrentState::action_add; + editItem.state = 0; + editItem.progress = 10+i; + editItem.down_rate = 10+i; + editItem.up_rate = 10+i; + editItem.seeds = 10+i; + editItem.leeches = 10+i; + editItem.ratio = 10+i; + editItem.total_size = 100000+i; + editItem.total_done = 10000+i; + downloadModel.updateItem(editItem, qtrapids::ParamsMap_t()); + } + + return app.exec(); } diff --git a/src/client/models/Plugin.cpp b/src/client/models/Plugin.cpp new file mode 100644 index 0000000..a6c6165 --- /dev/null +++ b/src/client/models/Plugin.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +// This class is needed to make DownloadListModel class available to QML: +class QmlDownloadListModelPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + virtual void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.downloadlistmodel")); + qmlRegisterType(uri, 1, 0, "DownloadListModel"); + } +}; + +#include "moc_Plugin.cxx" + +Q_EXPORT_PLUGIN2(downloadlistmodelplugin, QT_PREPEND_NAMESPACE(QmlDownloadListModelPlugin)); \ No newline at end of file diff --git a/src/client/models/Plugin.h b/src/client/models/Plugin.h new file mode 100644 index 0000000..129970c --- /dev/null +++ b/src/client/models/Plugin.h @@ -0,0 +1,18 @@ +#include +#include + +#include "QDeclarativeDownloadListModel.h" + +// This class is needed to make DownloadListModel class available to QML: +class QmlDownloadListModelPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + virtual void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.downloadlistmodel")); + qmlRegisterType(uri, 1, 0, "DownloadListModel"); + } +}; + +Q_EXPORT_PLUGIN2(downloadlistmodelplugin, QT_PREPEND_NAMESPACE(QmlDownloadListModelPlugin)); \ No newline at end of file diff --git a/src/client/models/QDeclarativeDownloadListModel.cpp b/src/client/models/QDeclarativeDownloadListModel.cpp new file mode 100644 index 0000000..e990705 --- /dev/null +++ b/src/client/models/QDeclarativeDownloadListModel.cpp @@ -0,0 +1,304 @@ +/*************************************************************************** + * Copyright (C) 2010 by Ixonos Plc * + * * + * This program 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; version 2 of the License. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "QDeclarativeDownloadListModel.h" +#include "QDeclarativeDownloadListModel_p.h" +#include "qtrapids/format.hpp" + +namespace qtrapids +{ + +QDeclarativeDownloadListModel::QDeclarativeDownloadListModel(QObject *parent): + QAbstractListModel(parent) +{ + d = new QDeclarativeDownloadListModelPrivate; + + // These roles are the names that we use to access the model data on QML + // in the string format. So, use the value on the right-hand side of assignment operator in QML. + // The role enum value is passed from QML side to the C++ model for fetching the data. + QHash roles; + roles[DownloadRole] = "download"; + roles[SeedRole] = "seed"; + roles[HashRole] = "hash"; + roles[NameRole] = "name"; + roles[SizeRole] = "size"; + roles[StatusRole] = "status"; + roles[StateRole] = "state"; + roles[ProgressRole] = "progress"; + roles[DownRateRole] = "downRate"; + roles[UpRateRole] = "upRate"; + roles[SeedsRole] = "seeds"; + roles[LeechesRole] = "leeches"; + roles[RatioRole] = "ratio"; + roles[TotaSizeRole] = "totalSize"; + roles[TotalDoneRole] = "totalDone"; + setRoleNames(roles); +} + +QDeclarativeDownloadListModel::~QDeclarativeDownloadListModel() +{ +} + + +void +QDeclarativeDownloadListModel::updateItem(TorrentState const& info, + ParamsMap_t other_info) +{ + qDebug() << Q_FUNC_INFO << " enter"; + + DownloadItems_t::iterator p = d->items_.find(info.hash); + switch (info.action) { + case TorrentState::action_add : + if (p == d->items_.end()) { + addItem_(info, other_info); + } else { + qWarning() << "item with similar info hash marked as added"; + updateItem_(info, other_info); + } + break; + case TorrentState::action_update : + if (p != d->items_.end()) { + updateItem_(info, other_info); + } else { + qWarning() << "item does not exist in list but information update arrived"; + } + break; + case TorrentState::action_remove : + if (p != d->items_.end()) { + removeItem_(info); + } else { + qWarning() << "item removal request arrived but there is no such item"; + } + break; + default: + qWarning() << "unknown action requested: " << info.action; + break; + } +} + + + // Returns the hash of the torrent be removed. +QString QDeclarativeDownloadListModel::prepareRemoveSelected() +{ + return "DUMMY_HASH"; +} + +int QDeclarativeDownloadListModel::rowCount(const QModelIndex &parent) const +{ + return d->items_.count(); +} + +QVariant QDeclarativeDownloadListModel::data(const QModelIndex &index, int role) const +{ + + qDebug() << Q_FUNC_INFO << " enter"; + int rowIndex = index.row(); + QString hash; + TorrentState item; + + // Get the item hash corresponding to row number: + if (d->itemIndexes_.contains(rowIndex)) + hash = d->itemIndexes_[rowIndex]; + else + return QVariant(); + + // Get the torrent info for the hash: + if (d->items_.contains(hash)) + item = d->items_[hash]; + else + return QVariant(); + + switch (role) { +// case DownloadRole: +// // TODO: What to do here?? +// break; +// case SeedRole: +// // TODO: What to do here?? +// break; + case HashRole: + return QVariant(item.hash); + case NameRole: + return QVariant(item.name); +// case SizeRole: +// return QVariant(item.total_size); + case StatusRole: + return QVariant(); + case StateRole: + return QVariant(item.state); + case ProgressRole: + return QVariant(item.progress); + case DownRateRole: + return QVariant(item.down_rate); + case UpRateRole: + return QVariant(item.up_rate); + case SeedsRole: + return QVariant(item.seeds); + case LeechesRole: + return QVariant(item.leeches); + case RatioRole: + return QVariant(item.ratio); + case TotaSizeRole: + return QVariant(item.total_size); + case TotalDoneRole: + return QVariant(item.total_done); + default: + qWarning() << Q_FUNC_INFO << "Unknown role requested from model"; + return QVariant(); + } + return QVariant(); +} + +bool QDeclarativeDownloadListModel::insertRow(int row, const QModelIndex &parent) +{ + qDebug() << "QDeclarativeDownloadListModel::insertRow()"; + return false; +} + +bool QDeclarativeDownloadListModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + qDebug() << "QDeclarativeDownloadListModel::setData()"; + return false; +} + + +void QDeclarativeDownloadListModel::classBegin() +{ + qDebug() << "QDeclarativeDownloadListModel::classBegin()"; +} + +void QDeclarativeDownloadListModel::componentComplete() +{ + qDebug() << "QDeclarativeDownloadListModel::componentComplete()"; +} + + +void QDeclarativeDownloadListModel::removeItem_(TorrentState const& info) +{ + qDebug() << Q_FUNC_INFO << " enter"; + QString hash = info.hash; + + // TODO: Emit rows remove start + int removed = d->items_.remove(hash); + // TODO: Edit rows insert end + if (!removed) + qDebug() << "Inconsistent download view state on item removal"; + + /* + int index = indexOfTopLevelItem(item); + if (index >= 0) { + takeTopLevelItem(index); + } + */ +} + +void QDeclarativeDownloadListModel::addItem_(TorrentState const& info, + ParamsMap_t) +{ + qDebug() << Q_FUNC_INFO << " enter"; +/* + DownloadViewItem *item = new DownloadViewItem + ( info.hash, + QStringList() + << info.name + << formatSize(info.total_size) + << GetStatusString((TorrentStatus::Id)info.state) + << formatProgress(info.progress) + << formatSize(info.down_rate) + << formatSize(info.up_rate) + << QString::number(info.seeds) + "/" + QString::number(info.leeches) + << QString::number(info.ratio) + << "ETA" ); + + QBrush brushTmp(GetStatusColor((TorrentStatus::Id)info.state)); + item->setForeground(2, brushTmp); + + addTopLevelItem(item); + */ + + int itemsCount = d->items_.count(); + beginInsertRows(QModelIndex(), itemsCount, itemsCount+1); + d->items_[info.hash] = info; + d->itemIndexes_[itemsCount+1] = info.hash; + endInsertRows(); +} + + +void QDeclarativeDownloadListModel::updateItem_(TorrentState const& info, ParamsMap_t) +{ + qDebug() << Q_FUNC_INFO << " enter"; + /* + item->setData(2, Qt::DisplayRole, + QVariant(GetStatusString((TorrentStatus::Id)info.state))); + item->setData(3, Qt::DisplayRole, + QVariant(formatProgress(info.progress))); + item->setData(4, Qt::DisplayRole, + QVariant(formatSize(info.down_rate))); + item->setData(5, Qt::DisplayRole, + QVariant(formatSize(info.up_rate))); + item->setData(6, Qt::DisplayRole, + QString::number(info.seeds) + "/" + QString::number(info.leeches)); + item->setData(7, Qt::DisplayRole, QString::number(info.ratio)); + + // Calculate ETA + if (info.down_rate > 0) { + qulonglong eta = (info.total_size - info.total_done) / info.down_rate; + item->setData(8, Qt::DisplayRole, formatElapsedTime(eta)); + } else { + item->setData(8, Qt::DisplayRole, "N/A"); + } +*/ + // TODO: Update items data & Emit data changed. + +/* + // Set color for status text + QBrush brushTmp(GetStatusColor((TorrentStatus::Id)info.state)); + item->setForeground(2, brushTmp); + */ +} + + + +QString QDeclarativeDownloadListModel::GetStatusString(TorrentStatus::Id status) +{ + qDebug() << Q_FUNC_INFO << " enter"; + switch (status) { + case TorrentStatus::QUEUED_FOR_CHECKING : + return tr("Queued"); + case TorrentStatus::CHECKING_FILES : + return tr("Checking"); + case TorrentStatus::DOWNLOADING_METADATA : + return tr("DL meta"); + case TorrentStatus::DOWNLOADING : + return tr("Downloading"); + case TorrentStatus::FINISHED : + return tr("Finished"); + case TorrentStatus::SEEDING : + return tr("Seeding"); + case TorrentStatus::ALLOCATING : + return tr("Allocating"); + case TorrentStatus::CHECKING_RESUME_DATA : + return tr("Checking resume"); + default: + return tr("N/A"); + } +} + +} // namespace qtrapids diff --git a/src/client/models/QDeclarativeDownloadListModel.h b/src/client/models/QDeclarativeDownloadListModel.h new file mode 100644 index 0000000..ee9cadd --- /dev/null +++ b/src/client/models/QDeclarativeDownloadListModel.h @@ -0,0 +1,129 @@ +/*************************************************************************** + * Copyright (C) 2010 by Ixonos Plc * + * * + * This program 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; version 2 of the License. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef QDECLARATIVEDOWNLOADLISTMODEL_H +#define QDECLARATIVEDOWNLOADLISTMODEL_H + + +#include +#include +#include +#include + +#include "qtrapids/dbus.hpp" +#include "qtrapids/info.hpp" + +//#include "../DownloadView.h" + +QT_MODULE(Declarative); + +namespace qtrapids +{ + +typedef QHash DownloadItems_t; +typedef QMap ItemIndex_t; + +class QDeclarativeContext; +class QDeclarativeDownloadListModelPrivate; + +class QDeclarativeDownloadListModel : + public QAbstractListModel, public QDeclarativeParserStatus +{ + Q_OBJECT + Q_INTERFACES(QDeclarativeParserStatus); + + /* + Q_PROPERTY(QString hash READ hash); + Q_PROPERTY(QString name READ name WRITE setName); + Q_PROPERTY(QString size READ size); + Q_PROPERTY(QString status READ status); + Q_PROPERTY(uint state READ state); + Q_PROPERTY(uint progress READ progress); + Q_PROPERTY(uint downRate READ downRate); + Q_PROPERTY(uint upRate READ upRate); + Q_PROPERTY(uint seeds READ seeds); + Q_PROPERTY(uint leeches READ leeches); + Q_PROPERTY(qulonglong ratio READ ratio); + Q_PROPERTY(qulonglong totaSize READ totalDone); + Q_PROPERTY(qulonglong totalDone READ totalDone); +*/ + +public: + QDeclarativeDownloadListModel(QObject *parent = 0); + virtual ~QDeclarativeDownloadListModel(); + + // TODO: Learn to use roles.. + enum Roles { + DownloadRole = Qt::UserRole + 1, + SeedRole, + HashRole, + NameRole, + SizeRole, + StatusRole, + StateRole, + ProgressRole, + DownRateRole, + UpRateRole, + SeedsRole, + LeechesRole, + RatioRole, + TotaSizeRole, + TotalDoneRole + }; + + // Updates the torrent status in the model. + void updateItem(TorrentState const& info, ParamsMap_t other_info); + // Returns the hash of the torrent be removed. + QString prepareRemoveSelected(); + + // -- QAbstractListModel + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role) const; + virtual bool insertRow(int row, const QModelIndex &parent); + virtual bool setData (const QModelIndex & index, const QVariant &value, int role = Qt::EditRole); + // -- End QAbstractListModel + + // -- Overrides from QDeclarativeParserStatus + virtual void classBegin(); + virtual void componentComplete(); + // -- End QDeclarativeParserStatus + +Q_SIGNALS: + void downloadItemChanged(QString hash); + +// Private functions. +private: + Q_DISABLE_COPY(QDeclarativeDownloadListModel) + QDeclarativeDownloadListModelPrivate *d; + + void addItem_(TorrentState const& info, ParamsMap_t other_info); + void updateItem_(TorrentState const& info, ParamsMap_t other_info); + void removeItem_(TorrentState const& info); + QString GetStatusString(TorrentStatus::Id status); +private: + +}; + + +} // namespace qtrapids + +// We need to declare the type +QML_DECLARE_TYPE(qtrapids::QDeclarativeDownloadListModel); + + + +#endif diff --git a/src/client/models/QDeclarativeDownloadListModel_p.h b/src/client/models/QDeclarativeDownloadListModel_p.h new file mode 100644 index 0000000..6c4b699 --- /dev/null +++ b/src/client/models/QDeclarativeDownloadListModel_p.h @@ -0,0 +1,30 @@ +#ifndef QDECLARATIVEDOWNLOADLISTMODELPRIVATE_H +#define QDECLARATIVEDOWNLOADLISTMODELPRIVATE_H + +#include + +#include "QDeclarativeDownloadListModel.h" // TODO: For DownloadItems_t, move that to common place.. + +namespace qtrapids +{ + +class QDeclarativeDownloadListModelPrivate : QObject +{ + Q_OBJECT +public: + QDeclarativeDownloadListModelPrivate() + { + } + + DownloadItems_t items_; + ItemIndex_t itemIndexes_; + //QModelIndex downloadIndex_; + +signals: + void itemAdded(QString hash); + void itemRemoved(QString hash); + +}; +} // namespace qtrapids + +#endif diff --git a/src/client/models/qmldir b/src/client/models/qmldir new file mode 100644 index 0000000..9e05264 --- /dev/null +++ b/src/client/models/qmldir @@ -0,0 +1 @@ +plugin qmlfolderlistmodelplugin \ No newline at end of file diff --git a/src/client/proxy.cpp b/src/client/proxy.cpp new file mode 100644 index 0000000..2c0c20c --- /dev/null +++ b/src/client/proxy.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a server -c QtRapidsServer -i qtrapids/dbus.hpp -p proxy /home/lassi/Projects/qtrapids/trunk/dbus/com.ixonos.qtrapids.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "proxy.h" + +/* + * Implementation of interface class QtRapidsServer + */ + +QtRapidsServer::QtRapidsServer(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +QtRapidsServer::~QtRapidsServer() +{ +} + diff --git a/src/client/proxy.h b/src/client/proxy.h new file mode 100644 index 0000000..6690149 --- /dev/null +++ b/src/client/proxy.h @@ -0,0 +1,90 @@ +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -a server -c QtRapidsServer -i qtrapids/dbus.hpp -p proxy /home/lassi/Projects/qtrapids/trunk/dbus/com.ixonos.qtrapids.xml + * + * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef PROXY_H_1327258740 +#define PROXY_H_1327258740 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qtrapids/dbus.hpp" + +/* + * Proxy class for interface com.ixonos.qtrapids + */ +class QtRapidsServer: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "com.ixonos.qtrapids"; } + +public: + QtRapidsServer(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~QtRapidsServer(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<> addTorrent(const QString &path, const QString &save_path, qtrapids::ParamsMap_t other_params) + { + QList argumentList; + argumentList << qVariantFromValue(path) << qVariantFromValue(save_path) << qVariantFromValue(other_params); + return asyncCallWithArgumentList(QLatin1String("addTorrent"), argumentList); + } + + inline QDBusPendingReply getOptions() + { + QList argumentList; + return asyncCallWithArgumentList(QLatin1String("getOptions"), argumentList); + } + + inline QDBusPendingReply<> getState() + { + QList argumentList; + return asyncCallWithArgumentList(QLatin1String("getState"), argumentList); + } + + inline QDBusPendingReply<> removeTorrent(const QString &hash) + { + QList argumentList; + argumentList << qVariantFromValue(hash); + return asyncCallWithArgumentList(QLatin1String("removeTorrent"), argumentList); + } + + inline QDBusPendingReply<> setOptions(qtrapids::ParamsMap_t options) + { + QList argumentList; + argumentList << qVariantFromValue(options); + return asyncCallWithArgumentList(QLatin1String("setOptions"), argumentList); + } + + inline QDBusPendingReply<> terminateSession() + { + QList argumentList; + return asyncCallWithArgumentList(QLatin1String("terminateSession"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void alert(qtrapids::TorrentState info, qtrapids::ParamsMap_t other_info); + void sessionTerminated(); + void terminate(); +}; + +namespace com { + namespace ixonos { + typedef ::QtRapidsServer qtrapids; + } +} +#endif diff --git a/src/client/qml/DownloadView.qml b/src/client/qml/DownloadView.qml new file mode 100644 index 0000000..e69de29 diff --git a/src/client/qml/MainPage.qml b/src/client/qml/MainPage.qml new file mode 100644 index 0000000..a189bab --- /dev/null +++ b/src/client/qml/MainPage.qml @@ -0,0 +1,177 @@ +import QtQuick 1.1 +import Qt.labs.components 1.0 +import com.nokia.meego 1.0 +import com.meego 1.0 +import com.nokia.extras 1.0 + +import QtRapids 1.0 + +Page { + id: tabbarPage + + property bool busy: Boolean(tabGroup.currentTab.busy) + anchors.margins: rootWindow.pageMargin + + tools: ToolBarLayout { + ToolIcon { iconId: "toolbar-back"; onClicked: pageStack.pop(); } + ButtonRow { + platformStyle: TabButtonStyle { } + TabButton { + text: "Downloads" + tab: downloads + } + TabButton { + text: "Seeds" + tab: seeds + } + } + ToolIcon { iconId: "toolbar-view-menu"; onClicked: (myMenu.status == DialogStatus.Closed) ? myMenu.open() : myMenu.close() } + } +// Text { +// text: "Hello World!" +// font.family: "Helvetica" +// font.pointSize: 24 +// color: "red" +// anchors.fill: parent +// } + + ListView { + width: 200; height: 400 +/* + DownloadListModel { + id: downloadModel + // TODO: Does not work like this. Need properties to set from QML? + // Try setting test data from C++ side and view here.. + /* + ListElement { + Hash: "QMLHASH1" + Size: "Size1" + Status: "DONE1" + } + ListElement { + Hash: "QMLHASH2" + Size: "Size2" + Status: "DONE2" + } + ListElement { + Hash: "QMLHASH3" + Size: "Size3" + Status: "DONE3" + } + } +*/ + Component { + id: downloadDelegate + Item { + height: 40 + width: parent.width + Text { + id: hashText + text: hash + } + Text { + id: nameText + anchors.leftMargin: 10 + anchors.left: hashText.right + text: name + } + Text { + id: seedsText + anchors.leftMargin: 10 + anchors.left: nameText.right + text: seeds + } + Text { + id: leechesText + anchors.leftMargin: 10 + anchors.left: seedsText.right + text: leeches + } + } + } + + // downloadModel is from rootContext, set in main.cpp + model: downloadModel + delegate: downloadDelegate + } + + /* + ListModel { + id: pagesModel + ListElement { + page: "CountBubble.qml" + title: "CountBubble" + subtitle: "Indicates current count" + } + ListElement { + page: "NetPromoterScore.qml" + title: "NetPromoterScore" + subtitle: "Shows net promotion query page" + } + ListElement { + page: "PageIndicator.qml" + title: "PageIndicator" + subtitle: "Indicates total & current pages" + } + ListElement { + page: "RatingIndicator.qml" + title: "RatingIndicator" + subtitle: "Indicates ratings" + } + ListElement { + page: "ListDelegates.qml" + title: "List Delegates" + subtitle: "Various List Delegates" + } + ListElement { + page: "MoreIndicator.qml" + title: "MoreIndicator" + subtitle: "Indicates that there are more contents" + } + ListElement { + page: "StyledButtons.qml" + title: "StyledButtons" + subtitle: "Buttons with different styles" + } + } + ListView { + id: listview + anchors.fill: parent + model: pagesModel + + delegate: ListDelegate { + Image { + source: "image://theme/icon-m-common-drilldown-arrow" + (theme.inverted ? "-inverse" : "") + anchors.right: parent.right; + anchors.verticalCenter: parent.verticalCenter + } + + subtitleColor: "#cc6633" + onClicked: { openFile(model.page); } + } + } +*/ + TabGroup { + id: tabGroup + + currentTab: downloads + + PageStack { + id: downloads + } + PageStack { + id: seeds + } + Page { + id: tab3 + Column { + spacing: 10 + + Text { + text: "This is a single page" + } + } + } + } + +} \ No newline at end of file diff --git a/src/client/qml/SeedView.qml b/src/client/qml/SeedView.qml new file mode 100644 index 0000000..e69de29 diff --git a/src/client/qml/main.qml b/src/client/qml/main.qml new file mode 100644 index 0000000..67383aa --- /dev/null +++ b/src/client/qml/main.qml @@ -0,0 +1,36 @@ + +import QtQuick 1.1 +import com.meego 1.0 + +PageStackWindow { + id: rootWindow + property int pageMargin: 16 + + platformStyle: defaultStyle; + + PageStackWindowStyle { id: defaultStyle } + PageStackWindowStyle { id: customStyle; background: "image://theme/meegotouch-wallpaper-portrait"} + + // ListPage is what we see when the app starts, it links to the component specific pages + initialPage: MainPage { } + + // These tools are shared by most sub-pages by assigning the id to a page's tools property + ToolBarLayout { + id: commonTools + visible: false + ToolIcon { iconId: "toolbar-back"; onClicked: { myMenu.close(); pageStack.pop(); } } + ToolIcon { iconId: "toolbar-view-menu"; onClicked: (myMenu.status == DialogStatus.Closed) ? myMenu.open() : myMenu.close() } + } + + Menu { + id: myMenu + visualParent: pageStack + MenuLayout { + MenuItem {id: b1; text: "Landscape"; onClicked: screen.allowedOrientations = Screen.Landscape} + MenuItem {id: b2; text: "Portrait"; onClicked: screen.allowedOrientations = Screen.Portrait} + MenuItem {id: b3; text: "Item 3"; onClicked: myMenu.accept()} + MenuItem {id: b4; text: "Item 4"; onClicked: myMenu.accept()} + } + } +} + diff --git a/src/client/qml/qml.qrc b/src/client/qml/qml.qrc new file mode 100644 index 0000000..955eecb --- /dev/null +++ b/src/client/qml/qml.qrc @@ -0,0 +1,9 @@ + + + + + main.qml + MainPage.qml + + + \ No newline at end of file -- 1.7.9.5