# 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..")
add_subdirectory(./dbus)
add_subdirectory(./src/client)
add_subdirectory(./src/server)
+add_subdirectory(./src/qml-client)
#add_subdirectory(./src/utest)
-CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
-
-set(QT_USE_QTDECLARATIVE 1)
-
-FIND_PACKAGE(Qt4 REQUIRED)
-
INCLUDE(${QT_USE_FILE})
-INCLUDE_DIRECTORIES(${qtrapids_SOURCE_DIR}/src/include ${qtrapids_SOURCE_DIR}/src/plugins)
+INCLUDE_DIRECTORIES(../include ../plugins)
FIND_LIBRARY(BOOST_SYSTEM boost_system-mt)
IF(${BOOST_SYSTEM} STREQUAL BOOST_SYSTEM-NOTFOUND)
${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
- ./models/QDeclarativeDownloadListModel.h
- ./models/QDeclarativeDownloadListModel_p.h
-# ./DownloadView.h
-# ./models/Plugin.h
-# ./MainWindow.h
-# ./PreferencesDialog.h
-# ./proxy.h
-# ./SeedView.h
-# ./ColumnSelectorDialog.h
+ ./DownloadView.h
+ ./MainWindow.h
+ ./PreferencesDialog.h
+ ./proxy.h
+ ./SeedView.h
+ ./ColumnSelectorDialog.h
)
SET(SRC
-# ./DownloadView.cpp
- ./main.cpp
- ./models/QDeclarativeDownloadListModel.cpp
-# ./MainWindow.cpp
-# ./PreferencesDialog.cpp
-# ./proxy.cpp
-# ./SeedView.cpp
-# ./ColumnSelectorDialog.cpp
+ ./DownloadView.cpp
+ ./main.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})
-# Build the executable from these files:
-ADD_EXECUTABLE(qml-client ${SRC} ${MOC_HEADERS} ${RCC_SRC})
-INSTALL(TARGETS qml-client DESTINATION bin)
+ADD_EXECUTABLE(qtrapids-gui ${SRC} ${MOC_HEADERS})
+INSTALL(TARGETS qtrapids-gui DESTINATION bin)
ADD_DEFINITIONS(-DQT_SHARED)
endif(NOT QT_QTMAEMO5_LIBRARY)
-TARGET_LINK_LIBRARIES(qml-client
+TARGET_LINK_LIBRARIES(qtrapids-gui
${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..")
+++ /dev/null
-#include <QObject>
-#include <QtDeclarative/qdeclarativeextensionplugin.h>
-#include <QtDeclarative/qdeclarative.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<qtrapids::QDeclarativeDownloadListModel>(uri, 1, 0, "DownloadListModel");
- }
-};
-
-#include "moc_Plugin.cxx"
-
-Q_EXPORT_PLUGIN2(downloadlistmodelplugin, QT_PREPEND_NAMESPACE(QmlDownloadListModelPlugin));
\ No newline at end of file
+++ /dev/null
-#include <QtDeclarative/qdeclarativeextensionplugin.h>
-#include <QtDeclarative/qdeclarative.h>
-
-#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<qtrapids::QDeclarativeDownloadListModel>(uri, 1, 0, "DownloadListModel");
- }
-};
-
-Q_EXPORT_PLUGIN2(downloadlistmodelplugin, QT_PREPEND_NAMESPACE(QmlDownloadListModelPlugin));
\ No newline at end of file
+++ /dev/null
-/***************************************************************************
- * 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 <QtCore/QVariant>
-#include <QtCore/QDebug>
-
-#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<int, QByteArray> 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
+++ /dev/null
-/***************************************************************************
- * 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 <QDeclarativeParserStatus>
-#include <QAbstractListModel>
-#include <QtDeclarative>
-#include <QModelIndex>
-
-#include "qtrapids/dbus.hpp"
-#include "qtrapids/info.hpp"
-
-//#include "../DownloadView.h"
-
-QT_MODULE(Declarative);
-
-namespace qtrapids
-{
-
-typedef QHash<QString, TorrentState> DownloadItems_t;
-typedef QMap<int, QString> 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
+++ /dev/null
-#ifndef QDECLARATIVEDOWNLOADLISTMODELPRIVATE_H
-#define QDECLARATIVEDOWNLOADLISTMODELPRIVATE_H
-
-#include <QModelIndex>
-
-#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
+++ /dev/null
-plugin qmlfolderlistmodelplugin
\ No newline at end of file
+++ /dev/null
-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
+++ /dev/null
-
-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()}
- }
- }
-}
-
+++ /dev/null
- <!DOCTYPE RCC>
- <RCC version="1.0">
-
- <qresource prefix="/">
- <file>main.qml</file>
- <file>MainPage.qml</file>
- </qresource>
-
- </RCC>
\ No newline at end of file
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+set(QT_USE_QTDECLARATIVE 1)
+
+FIND_PACKAGE(Qt4 REQUIRED)
+
+INCLUDE(${QT_USE_FILE})
+
+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)
+ MESSAGE(SEND_ERROR ${BOOST_SYSTEM})
+ENDIF(${BOOST_SYSTEM} STREQUAL BOOST_SYSTEM-NOTFOUND)
+
+INCLUDE_DIRECTORIES(
+ ${QT_INCLUDE_DIR}
+ ${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
+ ./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
+ ./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})
+# 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)
+
+set(QT_QTMAEMO5_LIBRARY -lQtMaemo5 -L${QT_LIBRARY_DIR})
+
+# QT_QTMAEMO5_* variables are not defined by CMake
+if(NOT QT_QTMAEMO5_INCLUDE_DIR)
+ FIND_PATH(QT_QTMAEMO5_INCLUDE_DIR QtMaemo5
+ PATHS ${QT_HEADERS_DIR}/QtMaemo5 NO_DEFAULT_PATH)
+endif(NOT QT_QTMAEMO5_INCLUDE_DIR)
+if(NOT QT_QTMAEMO5_LIBRARY)
+ FIND_LIBRARY(QT_QTMAEMO5_LIBRARY QtMaemo5
+ PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH)
+endif(NOT QT_QTMAEMO5_LIBRARY)
+
+
+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})
+
+if (SCRATCHBOX_UNAME)
+ MESSAGE("Configuring for building under Scratchbox..")
+ TARGET_LINK_LIBRARIES(qtrapids-gui ${QT_QTMAEMO5_LIBRARY})
+endif (SCRATCHBOX_UNAME)
+
+#MESSAGE(${CMAKE_HOST_SYSTEM_PROCESSOR})
+#CHECK_LIBRARY_EXISTS(QT_QTMAEMO5_LIBRARY)
+
+
+
+ADD_DEPENDENCIES(qtrapids-gui dbusapi)
--- /dev/null
+/***************************************************************************
+ * 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 <QScrollArea>
+#include <QGroupBox>
+#include <QGridLayout>
+#include <QTreeWidgetItem>
+#include <QCheckBox>
+#include <QDialogButtonBox>
+#include <QAbstractButton>
+
+#ifdef Q_WS_MAEMO_5
+ #include <QAbstractKineticScroller>
+#endif
+
+#include "ColumnSelectorDialog.h"
+
+
+ColumnSelectorDialog::ColumnSelectorDialog(QTreeWidget *treewidget, QWidget* parent, Qt::WindowFlags f) :
+ QDialog(parent, f), // Superclass construct
+ dialogButtons_(NULL),
+ grid_(NULL),
+ treeWidget_(treewidget),
+ scroller_(NULL),
+ checkBoxes_()
+{
+ QScrollArea *scrollArea = new QScrollArea(this);
+
+#ifdef Q_WS_MAEMO_5
+ /// @todo Kineticscrolling (property "FingerScrollable" does not work in Qt 4.6, only in 4.5)
+ scroller_ = scrollArea->property("kineticScroller").value<QAbstractKineticScroller*>();
+
+ if (!scroller_)
+ qFatal("This example only works with QMaemo5Style as the default style for all QAbstractScrollAreas");
+#endif
+
+ scrollArea->setWidgetResizable(true);
+ //scrollArea->setProperty("FingerScrollable", false);
+ QBoxLayout *verticalBox = new QBoxLayout(QBoxLayout::TopToBottom);
+ grid_ = new QGridLayout;
+ QCheckBox *cbox = NULL;
+
+
+
+ // Create scrollable checkbox dialog to allow proper viewing on Maemo:
+ verticalBox->addWidget(scrollArea);
+ // A "temporary" widget for containing QScrollArea stuff
+ QWidget* scrollAreaWidgetContents = new QWidget();
+ scrollAreaWidgetContents->setLayout(grid_);
+ scrollArea->setWidget(scrollAreaWidgetContents);
+ setLayout(verticalBox);
+
+ if (treeWidget_ != NULL) {
+ QTreeWidgetItem *item = treeWidget_->headerItem();
+
+ for (unsigned i = 0; i < item->columnCount(); ++i) {
+ cbox = new QCheckBox(item->text(i));
+ grid_->addWidget(cbox, i, 0);
+ treeWidget_->isColumnHidden(i) ? cbox->setCheckState(Qt::Unchecked) : cbox->setCheckState(Qt::Checked);
+ checkBoxes_.push_back(cbox);
+ cbox = NULL;
+ }
+ }
+
+ dialogButtons_ = new QDialogButtonBox(this);
+ dialogButtons_->setStandardButtons(QDialogButtonBox::Ok
+ | QDialogButtonBox::Cancel);
+
+ verticalBox->addWidget(dialogButtons_);
+
+ connect(dialogButtons_, SIGNAL(clicked(QAbstractButton*)),
+ this, SLOT(on_buttonClicked(QAbstractButton*)));
+}
+
+
+ColumnSelectorDialog::~ColumnSelectorDialog()
+{
+}
+
+
+void ColumnSelectorDialog::on_buttonClicked(QAbstractButton *button)
+{
+ switch (dialogButtons_->buttonRole ( button ) ) {
+ case QDialogButtonBox::AcceptRole :
+ ApplySettings();
+ done(QDialog::Accepted);
+ break;
+ case QDialogButtonBox::ApplyRole :
+ ApplySettings();
+ done(QDialog::Accepted);
+ break;
+ case QDialogButtonBox::RejectRole :
+ done(QDialog::Rejected);
+ break;
+ default:
+ return;
+ }
+}
+
+
+void ColumnSelectorDialog::ApplySettings()
+{
+ if (treeWidget_ != NULL) {
+ QTreeWidgetItem *item = treeWidget_->headerItem();
+ QCheckBox *cbox = NULL;
+
+ for (unsigned i = 0; i < checkBoxes_.size(); ++i) {
+ cbox = checkBoxes_.at(i);
+ cbox->isChecked() ? treeWidget_->showColumn(i) : treeWidget_->hideColumn(i);
+ cbox = NULL;
+ }
+ }
+}
+
--- /dev/null
+/***************************************************************************
+ * 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 COLUMNSELECTORDIALOG_H
+#define COLUMNSELECTORDIALOG_H
+
+#include <vector>
+#include <QDialog>
+#include <QSettings>
+
+class QTreeWidget;
+class QDialogButtonBox;
+class QGridLayout;
+class QTreeWidget;
+class QCheckBox;
+class QAbstractButton;
+class QAbstractKineticScroller;
+
+
+/**
+ @author Lassi Väätämöinen <lassi.vaatamoinen@ixonos.com>
+ @brief Dialog for selecting columns in QTreeViewWidget
+*/
+class ColumnSelectorDialog : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ ColumnSelectorDialog(QTreeWidget *treewidget, QWidget* parent = 0, Qt::WindowFlags f = 0);
+ virtual ~ColumnSelectorDialog();
+
+ private slots:
+ void on_buttonClicked(QAbstractButton *button);
+
+ private:
+ QDialogButtonBox *dialogButtons_;
+ QGridLayout *grid_;
+ QTreeWidget *treeWidget_;
+ QAbstractKineticScroller *scroller_;
+ std::vector<QCheckBox*> checkBoxes_;
+
+ private:
+ void ApplySettings();
+
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * 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 <qtrapids/format.hpp>
+
+#include "DownloadView.h"
+
+#include <QDebug>
+#include <QVariant>
+#include <QColor>
+
+namespace qtrapids
+{
+
+DownloadView::DownloadView(QWidget* parent) :
+ QTreeWidget(parent),
+ items_(),
+ settings_()
+{
+ setRootIsDecorated(false); // Hide branch lines, making one-level treeview (similar to list)
+ setHeaderItem(DownloadViewItem::getHeaderItem());
+
+ connect(this, SIGNAL(itemPressed(QTreeWidgetItem*, int)),
+ this, SLOT(on_itemClicked(QTreeWidgetItem*, int)));
+
+}
+
+
+DownloadView::~DownloadView()
+{
+}
+
+void DownloadView::updateItem(TorrentState const& info, ParamsMap_t other_info)
+{
+ DownloadItems_t::iterator p = items_.find(info.hash);
+ switch (info.action) {
+ case TorrentState::action_add :
+ if (p == items_.end()) {
+ addItem_(info, other_info);
+ } else {
+ qWarning() << "item with similar info hash marked as added";
+ updateItem_(p.value(), info, other_info);
+ }
+ break;
+ case TorrentState::action_update :
+ if (p != items_.end()) {
+ updateItem_(p.value(), info, other_info);
+ } else {
+ qWarning() << "item does not exist in list but information update arrived";
+ }
+ break;
+ case TorrentState::action_remove :
+ if (p != items_.end()) {
+ removeItem_(p.value(), info);
+ } else {
+ qWarning() << "item removal request arrived but there is no such item";
+ }
+ break;
+ default:
+ qWarning() << "unknown action requested: " << info.action;
+ break;
+ }
+}
+
+void DownloadView::removeItem_(DownloadViewItem *item, TorrentState const& info)
+{
+ QString hash = item->getHash();
+
+ int removed = items_.remove(hash);
+ if (!removed)
+ qDebug() << "Inconsistent download view state on item removal";
+
+ int index = indexOfTopLevelItem(item);
+ if (index >= 0) {
+ takeTopLevelItem(index);
+ }
+}
+
+void DownloadView::addItem_(TorrentState const& info, ParamsMap_t)
+{
+ 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);
+ items_[info.hash] = item;
+}
+
+
+void DownloadView::updateItem_(DownloadViewItem *item
+ , TorrentState const& info, ParamsMap_t)
+{
+ 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");
+ }
+
+ // Set color for status text
+ QBrush brushTmp(GetStatusColor((TorrentStatus::Id)info.state));
+ item->setForeground(2, brushTmp);
+}
+
+
+QString DownloadView::prepareRemoveSelected()
+{
+ qDebug() << "DownloadView::removeSelected() " << topLevelItemCount() ;
+
+ DownloadViewItem *item = dynamic_cast<DownloadViewItem*> (currentItem());
+ QString hash = item->getHash();
+
+ item->setDisabled(true);
+
+ qDebug() << "DownloadView::removeSelected() " << topLevelItemCount() ;
+
+ return hash;
+}
+
+
+void DownloadView::on_itemClicked(QTreeWidgetItem * , int)
+{
+ /*
+ qDebug() << "DownloadView::on_itemClicked(()" << item << "," << column;
+ qDebug() << "current item" << currentItem();
+
+ if (item == currentItem() && item->isSelected()) {
+ item->setSelected(false);
+ }
+ */
+}
+
+
+void DownloadView::saveView()
+{
+ QTreeWidgetItem *item = headerItem();
+ QList<QVariant> columns;
+
+ for (int i = 0; i < item->columnCount(); ++i) {
+ isColumnHidden(i) ? columns.push_back(QVariant(false)) : columns.push_back(QVariant(true));
+ }
+
+ settings_.setValue("downloadview_columns", QVariant(columns));
+}
+
+
+void DownloadView::restoreView()
+{
+ QTreeWidgetItem *item = headerItem();
+ QVariant columns(settings_.value("downloadview_columns"));
+ QList<QVariant> columnList = columns.toList();
+
+ for (int i = 0; i < columnList.size(); ++i) {
+ columnList.at(i).toBool() ? setColumnHidden(i, false) : setColumnHidden(i, true);
+ }
+}
+
+
+QString DownloadView::GetStatusString(TorrentStatus::Id status)
+{
+ 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");
+ }
+}
+
+
+QColor DownloadView::GetStatusColor(TorrentStatus::Id status)
+{
+ QColor green(40,205,40);
+ QColor yellow(255,174,0);
+
+ switch (status) {
+ case TorrentStatus::QUEUED_FOR_CHECKING :
+ case TorrentStatus::CHECKING_FILES :
+ case TorrentStatus::DOWNLOADING_METADATA :
+ case TorrentStatus::ALLOCATING :
+ case TorrentStatus::CHECKING_RESUME_DATA:
+ return yellow;
+ case TorrentStatus::DOWNLOADING :
+ case TorrentStatus::FINISHED :
+ case TorrentStatus::SEEDING :
+ return green;
+ default:
+ return QColor();
+ }
+}
+
+} // namespace qtrapids
--- /dev/null
+/***************************************************************************
+ * 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 DOWNLOADVIEW_H
+#define DOWNLOADVIEW_H
+
+#include <map>
+#include <qtrapids/info.hpp>
+#include <qtrapids/dbus.hpp>
+
+#include <QTreeWidget>
+
+
+namespace qtrapids
+{
+
+class DownloadViewItem;
+
+typedef QHash<QString, DownloadViewItem*> DownloadItems_t;
+
+/**
+ @class DownloadView
+ @brief A view showing all downloaded torrents
+ @author Lassi Väätämöinen <lassi.vaatamoinen@ixonos.com>
+*/
+class DownloadView : public QTreeWidget
+{
+ Q_OBJECT
+
+public:
+ DownloadView(QWidget* parent);
+
+ ~DownloadView();
+
+ void updateItem(TorrentState const& info, ParamsMap_t other_info);
+ QString prepareRemoveSelected();
+
+ /// Saves current view settings via QSettings
+ void saveView();
+ /// Reads view settigns via QSettings
+ void restoreView();
+
+private slots:
+ void on_itemClicked(QTreeWidgetItem * item, int column);
+
+private:
+
+ // Maps torrent to downloadview item.
+ // Key: SHA1 info hash of torrent. Data: View item corresponding to torrent.
+ DownloadItems_t items_;
+ // Used for saving view settings
+ QSettings settings_;
+
+private:
+ // Private functions.
+ void addItem_(TorrentState const& info, ParamsMap_t other_info);
+ void updateItem_(DownloadViewItem *item
+ , TorrentState const& info, ParamsMap_t other_info);
+ void removeItem_(DownloadViewItem *item, TorrentState const& info);
+
+
+ static QString GetStatusString(TorrentStatus::Id status);
+ static QColor GetStatusColor(TorrentStatus::Id status);
+
+};
+
+
+/**
+ @class DownloadViewItem
+ @brief Represents one item row of DownloadView
+*/
+class DownloadViewItem : public QTreeWidgetItem
+{
+
+public:
+ DownloadViewItem(QTreeWidget* parent, int type) :
+ QTreeWidgetItem(parent, type = QTreeWidgetItem::UserType) {};
+
+ DownloadViewItem(QString hash, const QStringList& strings,
+ int type = QTreeWidgetItem::UserType) :
+ QTreeWidgetItem (strings, type = Type),
+ hash_(hash) {}
+
+
+ /// @return An item comprising of string list, suitable for QTableView
+ /// header.
+ static DownloadViewItem *getHeaderItem() {
+ DownloadViewItem *item
+ = new DownloadViewItem("", QStringList()
+ << "Name"
+ << "Size" << "Status"
+ << "Progress" << "DL speed"
+ << "UL speed" << "Seeds/Leechers"
+ << "Ratio" << "ETA");
+
+ return item;
+ }
+
+ /// @todo QTorrentHandle as one hidden column
+
+ QString getHash() const {
+ return hash_;
+ }
+
+private:
+ QString hash_;
+};
+
+} // namespace qtrapids
+
+#endif // DOWNLOADVIEW_H
+
--- /dev/null
+/***************************************************************************
+ * 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 <qtrapids/dbus.hpp>
+
+#include <QDebug>
+#include <QtGui/QMenuBar>
+#include <QtGui/QToolBar>
+#include <QAction>
+#include <QFileDialog>
+#include <QMessageBox>
+//#include <QTreeWidgetItem>
+#include <QApplication>
+#include <QPluginLoader>
+
+#include "DownloadView.h"
+#include "SeedView.h"
+#include "PreferencesDialog.h"
+#include "ColumnSelectorDialog.h"
+
+#include "MainWindow.h"
+
+namespace qtrapids
+{
+
+const QString ABOUT_TEXT
+= QString(QObject::trUtf8("QtRapids, a simple BitTorrent client based on"
+ "\nQt and Libtorrent."
+ "\n\nURL: http://qtrapids.garage.maemo.org/"
+ "\n\nAuthors:\nLassi Väätämöinen, lassi.vaatamoinen@ixonos.com"
+ "\nDenis Zalevskiy, denis.zalewsky@gmail.com"
+ "\n\nIxonos Plc, Finland\n"));
+
+const QString PLUGINS_DIR = "plugins";
+
+// Consturctor
+MainWindow::MainWindow() :
+ QMainWindow(), // Superclass
+ tabWidget_(NULL),
+ dlView_(NULL),
+ seedView_(NULL),
+ searchWidget_(NULL),
+ startDaemonAction_(NULL),
+ stopDaemonAction_(NULL),
+ preferencesDialog_(NULL),
+ settings_(QCoreApplication::organizationName()
+ , QCoreApplication::applicationName()),
+ pluginDirs_(),
+ server_(QtRapidsServer::staticInterfaceName()
+ , "/qtrapids", QDBusConnection::sessionBus())
+ // torrentHandles_(),
+{
+
+ setWindowTitle("QtRapids");
+
+ // MENUBAR
+ QMenuBar *menuBar = new QMenuBar();
+ QMenu *tempMenu = NULL;
+
+ tempMenu = menuBar->addMenu(tr("&File"));
+ QAction *openAction = tempMenu->addAction(tr("&Open"));
+ QAction *removeAction = tempMenu->addAction(tr("&Remove"));
+ removeAction->setEnabled(false);
+
+ startDaemonAction_ = tempMenu->addAction(tr("S&tart daemon"));
+ stopDaemonAction_ = tempMenu->addAction(tr("Sto&p daemon"));
+ startDaemonAction_->setEnabled(false);
+
+ QAction *quitAction = tempMenu->addAction(tr("&Quit"));
+
+ tempMenu = menuBar->addMenu(tr("&View"));
+ QAction *columnsAction = tempMenu->addAction(tr("&Columns"));
+
+ tempMenu = menuBar->addMenu(tr("&Settings"));
+ QAction *preferencesAction = tempMenu->addAction(tr("&Preferences"));
+
+ tempMenu = menuBar->addMenu(tr("&Help"));
+ QAction *aboutAction = tempMenu->addAction(tr("&About"));
+ QAction *aboutQtAction = tempMenu->addAction(tr("About &Qt"));
+
+ setMenuBar(menuBar);
+ connect(openAction, SIGNAL(triggered()), this, SLOT(on_openAction_clicked()));
+ connect(removeAction, SIGNAL(triggered()), this, SLOT(on_removeAction_clicked()));
+ connect(this, SIGNAL(itemSelected(bool)), removeAction, SLOT(setEnabled(bool)));
+ connect(quitAction, SIGNAL(triggered()), this, SLOT(on_quitAction_clicked()));
+ connect(startDaemonAction_, SIGNAL(triggered()), this, SLOT(on_startDaemonAction_clicked()));
+ connect(stopDaemonAction_, SIGNAL(triggered()), this, SLOT(on_stopDaemonAction_clicked()));
+ connect(columnsAction, SIGNAL(triggered()), this, SLOT(on_columnsAction_clicked()));
+ connect(preferencesAction, SIGNAL(triggered()), this, SLOT(on_preferencesAction_clicked()));
+ connect(aboutAction, SIGNAL(triggered()), this, SLOT(on_aboutAction_clicked()));
+ connect(aboutQtAction, SIGNAL(triggered()), this, SLOT(on_aboutQtAction_clicked()));
+
+ // TABWIDGET (central widget)
+ tabWidget_ = new QTabWidget();
+ tabWidget_->setTabsClosable(true);
+
+ /// @todo Exception handling
+ dlView_ = new DownloadView(this);
+ //seedView_ = new SeedView(this);
+ tabWidget_->addTab(dlView_, tr("Downloads"));
+ //tabWidget_->addTab(seedView_, tr("Seeds"));
+ connect(dlView_, SIGNAL(itemSelectionChanged()), this,
+ SLOT(on_downloadItemSelectionChanged()));
+
+ //connect(seedView_, SIGNAL(itemSelectionChanged()), this,
+ // SLOT(on_seedItemSelectionChanged()));
+
+ // Tab widget as central widget.
+ setCentralWidget(tabWidget_);
+
+ // TOOLBAR
+ QToolBar *toolBar = new QToolBar();
+ toolBar->addAction(tr("Open"));
+ removeAction = toolBar->addAction(tr("Remove"));
+ removeAction->setEnabled(false);
+ addToolBar(Qt::BottomToolBarArea, toolBar);
+
+ connect(this, SIGNAL(itemSelected(bool)), removeAction,
+ SLOT(setEnabled(bool)));
+ connect(toolBar, SIGNAL(actionTriggered(QAction*)), this,
+ SLOT(handleToolBarAction(QAction*)));
+ connect (tabWidget_, SIGNAL(tabCloseRequested(int)), this, SLOT(on_tabWidget_tabCloseRequested(int)));
+
+ connect(&server_, SIGNAL(alert(qtrapids::TorrentState, qtrapids::ParamsMap_t)),
+ this, SLOT(on_alert(qtrapids::TorrentState, qtrapids::ParamsMap_t)));
+
+ connect(&server_, SIGNAL(sessionTerminated()), this, SLOT(on_serverTerminated()));
+
+// connect(&btSession_, SIGNAL(alert(std::auto_ptr<Alert>)),
+// this, SLOT(on_alert(std::auto_ptr<Alert>)));
+
+
+ LoadPlugins();
+
+}
+
+
+MainWindow::~MainWindow()
+{
+ settings_.setValue("geometry", saveGeometry());
+}
+
+// ===================== Implements PluginInterface =========================
+/// @todo add PluginInterface parameter to request plugin name
+bool MainWindow::setGui(QWidget* widget, PluginWidgetType type, qtrapids::PluginInterface* plugin)
+{
+#ifdef QTRAPIDS_DEBUG
+ qDebug() << "MainWindow::setGui():" << dlView_->currentItem();
+#endif
+
+ if (plugin && plugin->identifier() == "SearchPlugin") {
+ searchWidget_ = widget;
+ } else {
+ return false;
+ }
+
+ tabWidget_->addTab(widget, tr("Search"));
+ return true;
+}
+
+/// @todo Add PluginInterface parameter to check which plugin gives the widget, to handle appropriately
+void MainWindow::addPluginWidget(QWidget* widget, PluginWidgetType type)
+{
+#ifdef QTRAPIDS_DEBUG
+ qDebug() << "MainWindow::addPluginWidget():" << dlView_->currentItem();
+#endif
+
+ if (type == qtrapids::PluginHostInterface::TAB_PAGE) {
+ int index = tabWidget_->addTab(widget, tr("Results"));
+ tabWidget_->setCurrentIndex(index);
+ //layout_->addWidget(widget);
+ }
+}
+void MainWindow::addToolbar(QWidget* widget, PluginWidgetType type)
+{
+}
+
+void MainWindow::addToolItem(QWidget* widget, PluginWidgetType type)
+{
+}
+
+void MainWindow::addMenu(QWidget* widget, PluginWidgetType type)
+{
+}
+
+void MainWindow::addMenuItem(QWidget* widget, PluginWidgetType type)
+{
+}
+
+bool MainWindow::eventRequest(QVariant param, PluginRequest req)
+{
+ if (req == qtrapids::PluginHostInterface::OPEN_FILE) {
+ QString sourceFile = param.toString();
+
+ // Get the source files name from the full path:
+ QFileInfo fInfo(sourceFile);
+ QString targetFile = fInfo.fileName();
+ targetFile = settings_.value("download/directory").toString() + "/" + targetFile;
+
+ // Copy temoporary file to Downloads directory...
+ if (!QFile::copy(sourceFile, targetFile)) {
+ qDebug() << "File copying failed";
+ return false;
+ } else {
+ // If copying was successful, remove the original temporary file.
+ QFile::remove(sourceFile);
+ }
+
+ /// @todo Torrent bencoding validity should be checked before starting(?)
+ // ...and start the torrent:
+ on_torrentFileSelected(targetFile);
+
+ } else if (req == qtrapids::PluginHostInterface::READ_BUFFER) {
+ // Create torrent information from char* buffer and start.
+ StartTorrentFromBufferData(param.toByteArray().constData(), param.toByteArray().size());
+ }
+
+ return true;
+}
+
+
+//=========================== PRIVATE ================================
+
+void MainWindow::LoadPlugins()
+{
+ // Get plugin directories from
+ QStringList pluginDirsTmp = settings_.value("plugins/path").toStringList();
+ QStringList nameFilters("*.so");
+
+ /// @todo enable "application directory" for plugin search in development/debug mode only. In release version
+ /// search plugins directory under $HOME/.qtrapids or system library paths
+ pluginDirsTmp << qApp->applicationDirPath();
+ pluginDirsTmp.removeDuplicates();
+
+ foreach (QString dir, pluginDirsTmp) {
+ pluginDirs_.append(QDir(dir));
+ }
+
+ foreach (QDir dir, pluginDirs_) {
+
+ if (dir.cd(PLUGINS_DIR)) {
+
+ foreach (QString fileName, dir.entryList(nameFilters, QDir::Files)) {
+ QPluginLoader pluginLoader(dir.absoluteFilePath(fileName));
+
+ // If plugin not loaded from another directory, then load
+ if (!pluginFileNames_.contains(fileName) && QLibrary::isLibrary(fileName)) {
+
+ if (pluginLoader.load()) {
+ qDebug() << "Plugin loaded: " << fileName;
+ } else {
+ qWarning() << "Plugin load failed: " << pluginLoader.errorString();
+ }
+
+ QObject *baseInstance = pluginLoader.instance();
+ if (!baseInstance) {
+ qDebug() << "Base instance = NULL.";
+ }
+
+ qtrapids::PluginInterface *plugin = qobject_cast<qtrapids::PluginInterface*>(baseInstance);
+
+ if (!plugin) {
+ qDebug() << "Cast failed.";
+ } else {
+ qtrapids::PluginInterface::Info info;
+ info.directory = dir.path();
+ qDebug() << dir.path();
+ plugin->initialize(this, info);
+ pluginFileNames_ += fileName;
+ }
+ } else {
+ qWarning() << "Plugin "
+ << fileName
+ << " already loaded from another directory, or not a valid library file";
+ }
+ }
+
+ } else {
+ qWarning() << PLUGINS_DIR << "directory not accessible or does not exist in " << dir.path();
+ }
+ }
+}
+
+
+void MainWindow::RestoreSettings()
+{
+
+ // Restore previous main window geometry:
+ QVariant geometry(settings_.value("geometry"));
+ if (!geometry.isNull()) {
+ qDebug() << "restoring geometry";
+ restoreGeometry(geometry.toByteArray());
+ }
+
+ // Restore DownloadView columns:
+ dlView_->restoreView();
+
+ // Restore torrent session settings to server:
+ qtrapids::ParamsMap_t options;
+ options["net/downloadRate"] = settings_.value("net/downloadRate").toString();
+ options["net/uploadRate"] = settings_.value("net/uploadRate").toString();
+ server_.setOptions(options);
+}
+
+
+// Opens torrent information from buffer data and adds torrent to session
+void MainWindow::StartTorrentFromBufferData(char const* data, int size)
+{
+
+}
+
+// =========================== PRIVATE SLOTS =================================
+void MainWindow::on_openAction_clicked()
+{
+ QString filename = QFileDialog::getOpenFileName( this, tr("Open torrent file"), QString(), tr("Torrent files (*.torrent)") );
+ on_torrentFileSelected(filename);
+ /*
+ QFileDialog *dialog = new QFileDialog( this, "Open torrent file", QString(), tr("Torrent files (*.torrent)"));
+ dialog->setFileMode(QFileDialog::ExistingFile);
+ connect(dialog, SIGNAL(fileSelected(const QString&)), this, SLOT(on_torrentFileSelected(const QString&)));
+ dialog->show();
+ */
+}
+
+void MainWindow::on_removeAction_clicked()
+{
+ QString hash = dlView_->prepareRemoveSelected();
+ try {
+ server_.removeTorrent(hash);
+ } catch (...) {
+ qDebug() << "Exception while removing torrent";
+ }
+}
+
+
+void MainWindow::on_quitAction_clicked()
+{
+ close();
+}
+
+
+void MainWindow::on_startDaemonAction_clicked()
+{
+ server_.getState();
+ /// @todo create signal that signals server startup and
+ /// enable controls in the handler slot
+ stopDaemonAction_->setEnabled(true);
+ startDaemonAction_->setEnabled(false);
+}
+
+
+void MainWindow::on_stopDaemonAction_clicked()
+{
+ server_.terminateSession();
+}
+
+
+void MainWindow::on_serverTerminated()
+{
+ stopDaemonAction_->setEnabled(false);
+ startDaemonAction_->setEnabled(true);
+}
+
+void MainWindow::on_columnsAction_clicked()
+{
+ ColumnSelectorDialog *dialog = new ColumnSelectorDialog(dlView_);
+ dialog->show();
+ dialog->exec();
+// dialog->raise();
+// dialog->activateWindow();
+ qDebug() << "dialog exit";
+
+ if (dialog->result() == QDialog::Accepted) {
+ qDebug() << "saved";
+ dlView_->saveView();
+ }
+}
+
+
+void MainWindow::on_preferencesAction_clicked()
+{
+ if (!preferencesDialog_) {
+ preferencesDialog_ = new PreferencesDialog(this, 0, &server_);
+ }
+
+ preferencesDialog_->show();
+ preferencesDialog_->raise();
+ preferencesDialog_->activateWindow();
+}
+
+
+void MainWindow::on_aboutAction_clicked()
+{
+ QMessageBox::about(this, tr("About QtRapids"), ABOUT_TEXT);
+}
+
+
+void MainWindow::on_aboutQtAction_clicked()
+{
+ QMessageBox::aboutQt (this, tr("About Qt"));
+}
+
+
+void MainWindow::on_tabWidget_tabCloseRequested(int index)
+{
+
+ int searchWidgetIndex = tabWidget_->indexOf(searchWidget_);
+
+ // Allow closing other tabs than the first two
+ // TODO The first two may well be closable, just add "show tabs" action for these in the menu
+ if (index != 0 && index != 1 && index != searchWidgetIndex) {
+ QWidget *remove = tabWidget_->widget(index);
+ tabWidget_->removeTab(index);
+ delete remove;
+ remove = NULL;
+ }
+}
+
+
+void MainWindow::on_downloadItemSelectionChanged()
+{
+#ifdef QTRAPIDS_DEBUG
+ qDebug() << "MainWindow::on_seedItemSelectionChanged():" << dlView_->currentItem();
+#endif
+ if (dlView_->currentItem() != NULL) {
+ emit(itemSelected(true));
+ } else {
+ emit(itemSelected(false));
+ }
+}
+
+
+void MainWindow::on_seedItemSelectionChanged()
+{
+#ifdef QTRAPIDS_DEBUG
+ qDebug() << "MainWindow::on_seedItemSelectionChanged():" << seedView_->currentItem();
+#endif
+ if (seedView_->currentItem() != NULL) {
+ emit(itemSelected(true));
+ } else {
+ emit(itemSelected(false));
+ }
+}
+
+
+void MainWindow::handleToolBarAction(QAction* action)
+{
+ if (action->text() == "Open") {
+ on_openAction_clicked();
+ } else if (action->text() == "Remove") {
+ on_removeAction_clicked();
+ }
+}
+
+
+void MainWindow::on_torrentFileSelected(QString file)
+{
+#ifdef QTRAPIDS_DEBUG
+ qDebug() << " MainWindow::on_torrentFileSelected(): " << file;
+#endif
+ // Torrent filename empty, do nothing.
+ if (file == "") {
+ return;
+ }
+
+ // Otherwise add torrent
+ // For params, see: http://www.rasterbar.com/products/libtorrent/manual.html#add-torrent
+ // save_path is the only mandatory parameter, rest are optional.
+ //addParams.storage_mode = libtorrent::storage_mode_allocate;
+ try {
+ server_.addTorrent(file, settings_.value("download/directory").toString()
+ , ParamsMap_t());
+ } catch (...) {
+ qDebug() << "Exception adding torrent";
+ }
+}
+
+
+void MainWindow::on_alert(qtrapids::TorrentState info, qtrapids::ParamsMap_t other_info)
+{
+#ifdef QTRAPIDS_DEBUG
+ qDebug() << "got alert";
+#endif
+ dlView_->updateItem(info, other_info);
+}
+
+} // namespace qtrapids
--- /dev/null
+/***************************************************************************
+ * 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 MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QSettings>
+
+#include "PluginInterface.h"
+#include "proxy.h"
+
+class QTabWidget;
+class DownloadView;
+class PreferencesDialog;
+
+namespace qtrapids
+{
+
+class SeedView;
+
+/**
+ @author Lassi Väätämöinen <lassi.vaatamoinen@ixonos.com>
+*/
+class MainWindow : public QMainWindow, public PluginHostInterface
+{
+
+ Q_OBJECT;
+
+public:
+
+ MainWindow();
+ virtual ~MainWindow();
+
+ // Implemented from PluginHostInterface
+ virtual bool setGui(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE, qtrapids::PluginInterface* plugin = NULL);
+ virtual void addPluginWidget(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE);
+ virtual void addToolbar(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE);
+ virtual void addToolItem(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE);
+ virtual void addMenu(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE);
+ virtual void addMenuItem(QWidget* widget, PluginWidgetType type = UNKNOWN_TYPE);
+ virtual bool eventRequest(QVariant param, PluginRequest req = UNKNOWN_REQUEST);
+
+ void RestoreSettings();
+
+ void connectToServer() {
+ qDBusRegisterMetaType<qtrapids::TorrentState>();
+ qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
+
+ connect(&server_
+ , SIGNAL(alert(qtrapids::TorrentState
+ , qtrapids::ParamsMap_t))
+ , this
+ , SLOT(on_alert(qtrapids::TorrentState
+ , qtrapids::ParamsMap_t)));
+ // Request server state.
+ // NOTE: This call starts qtrapids-server automatically with the GUI,
+ // if the .service file is in /usr/share/dbus-1/services/
+ server_.getState();
+ }
+
+signals:
+ void itemSelected(bool enabled);
+
+public slots:
+private slots:
+ void on_openAction_clicked();
+ void on_removeAction_clicked();
+ void on_quitAction_clicked();
+ void on_startDaemonAction_clicked();
+ void on_stopDaemonAction_clicked();
+ void on_serverTerminated();
+ void on_columnsAction_clicked();
+ void on_preferencesAction_clicked();
+ void on_aboutAction_clicked();
+ void on_aboutQtAction_clicked();
+ void on_tabWidget_tabCloseRequested(int index);
+ void on_downloadItemSelectionChanged();
+ void on_seedItemSelectionChanged();
+ void handleToolBarAction(QAction* action);
+ void on_torrentFileSelected(QString file);
+ void on_alert(qtrapids::TorrentState, qtrapids::ParamsMap_t);
+
+
+private:
+ void LoadPlugins();
+ void StartTorrentFromBufferData(char const* data, int size);
+
+private:
+ QTabWidget *tabWidget_;
+ DownloadView *dlView_;
+ SeedView *seedView_;
+ QWidget *searchWidget_;
+ QAction *startDaemonAction_, *stopDaemonAction_;
+ PreferencesDialog *preferencesDialog_;
+ QSettings settings_;
+ QList<QDir> pluginDirs_;
+ QStringList pluginFileNames_;
+
+
+ //std::vector< std::auto_ptr<QTorrentHandle> const > torrentHandles_;
+
+ QtRapidsServer server_;
+
+
+ //bool IsNewTorrent(std::auto_ptr<QTorrentHandle> handlePtr);
+};
+
+} // namespace qtrapids
+
+#endif
--- /dev/null
+/***************************************************************************
+ * 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 <QDebug>
+#include <QBoxLayout>
+#include <QLineEdit>
+#include <QLabel>
+#include <QPushButton>
+#include <QSpinBox>
+#include <QDialogButtonBox>
+#include <QAbstractButton>
+#include <QFileDialog>
+
+#include "qtrapids/dbus.hpp"
+#include "proxy.h"
+#include "PreferencesDialog.h"
+
+
+
+PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags f, QtRapidsServer *server) :
+ QDialog(parent, f), // Superclass
+ dirLineEdit_(NULL),
+ dialogButtons_(NULL),
+ uploadRateSpinBox_(NULL),
+ downloadRateSpinBox_(NULL),
+ server_(server),
+ settings_()
+{
+ setWindowTitle("Preferences");
+
+ QBoxLayout *verticalBox = new QBoxLayout(QBoxLayout::TopToBottom);
+ //QBoxLayout *horizontalBox1 = new QBoxLayout(QBoxLayout::LeftToRight);
+ QGridLayout *grid = new QGridLayout;
+ setLayout(verticalBox);
+ verticalBox->addLayout(grid);
+
+ QLabel *dirLabel = new QLabel(tr("Download directory: "));
+ dirLineEdit_ = new QLineEdit(this);
+ QPushButton *browseDirButton = new QPushButton(tr("Browse.."));
+
+ QLabel *uploadLabel = new QLabel(tr("Max. upload rate: "));
+ QLabel *downloadLabel = new QLabel(tr("Max. download rate: "));
+ uploadRateSpinBox_ = new QSpinBox(this);
+ downloadRateSpinBox_ = new QSpinBox(this);
+
+ grid->addWidget(dirLabel, 0, 0);
+ grid->addWidget(dirLineEdit_, 0, 1);
+ grid->addWidget(browseDirButton, 0, 2);
+
+ grid->addWidget(uploadLabel, 1, 0);
+ grid->addWidget(uploadRateSpinBox_, 1, 1);
+ grid->addWidget(downloadLabel, 2, 0);
+ grid->addWidget(downloadRateSpinBox_, 2, 1);
+
+ uploadRateSpinBox_->setRange(0, 1000);
+ uploadRateSpinBox_->setSuffix(" kB/s");
+ downloadRateSpinBox_->setRange(0, 1000);
+ downloadRateSpinBox_->setSuffix(" kB/s");
+
+// horizontalBox1->addWidget(dirLabel);
+// horizontalBox1->addWidget(dirLineEdit_);
+// horizontalBox1->addWidget(browseDirButton);
+
+ connect(browseDirButton, SIGNAL(clicked()),
+ this, SLOT(on_browseDirButtonClicked()));
+
+
+ dialogButtons_ = new QDialogButtonBox(this);
+ dialogButtons_->setStandardButtons(QDialogButtonBox::Ok
+ | QDialogButtonBox::Apply
+ | QDialogButtonBox::Cancel);
+
+ verticalBox->addWidget(dialogButtons_);
+
+ connect(dialogButtons_, SIGNAL(clicked(QAbstractButton*)),
+ this, SLOT(on_buttonClicked(QAbstractButton*)));
+
+ // Set saved preference values to fields.
+ ReadSettings();
+
+}
+
+
+PreferencesDialog::~PreferencesDialog()
+{
+}
+
+// ======================== SLOTS ========================
+void PreferencesDialog::on_browseDirButtonClicked()
+{
+ QString dir = QFileDialog::getExistingDirectory(this, tr("Download directory"), QString(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+ on_downloadDirectorySelected(dir);
+
+ /*
+ QFileDialog *dialog
+ = new QFileDialog(this, "Download directory",
+ QString(), tr("Torrent files (*.torrent)"));
+
+ dialog->setFileMode(QFileDialog::Directory);
+ dialog->setOption(QFileDialog::ShowDirsOnly, true);
+
+ connect(dialog, SIGNAL(fileSelected(const QString&)),
+ this, SLOT(on_downloadDirectorySelected(const QString&)));
+
+ dialog->show();
+ */
+}
+
+void PreferencesDialog::on_buttonClicked(QAbstractButton* button)
+{
+ switch (dialogButtons_->buttonRole ( button ) ) {
+ case QDialogButtonBox::AcceptRole :
+ qDebug() << "PreferencesDialog: OK";
+ WriteSettings();
+ done(QDialog::Accepted);
+ break;
+ case QDialogButtonBox::ApplyRole :
+ qDebug() << "PreferencesDialog: APPLY";
+ WriteSettings();
+ break;
+ case QDialogButtonBox::RejectRole :
+ qDebug() << "PreferencesDialog: CANCEL";
+ done(QDialog::Rejected);
+ break;
+ default:
+ return;
+ }
+}
+
+void PreferencesDialog::on_downloadDirectorySelected(QString directory)
+{
+ qDebug() << "PreferencesDialog::on_downloadDirectorySelected(): " << directory;
+ // Torrent filename empty, do nothing.
+ if (directory == "")
+ return;
+
+ dirLineEdit_->clear();
+ dirLineEdit_->insert(directory);
+
+ /// @todo check that user has privileges to write to this directory.
+}
+
+
+// ========================= Private functions ==========================
+void PreferencesDialog::WriteSettings()
+{
+ int ulRate = 1000*uploadRateSpinBox_->value();
+ int dlRate = 1000*downloadRateSpinBox_->value();
+
+ settings_.setValue("download/directory", dirLineEdit_->text());
+ //settings_.setValue("net/uploadRate", ulRate);
+ //settings_.setValue("net/downloadRate", dlRate);
+
+ // NOTE: We might need to call QSettigns::sync() here to instantly write settings.
+ // settings are written also by QSettings() destructor and by event loop at regular interval.
+
+ // If server pointer was given, apply settings immediately.
+ if (server_) {
+ /// @todo Use DBus interface
+ /// @todo Set parameters for server
+ /// @todo Add speedlimit functionality to Server.
+ qtrapids::ParamsMap_t options;
+ options["net/downloadRate"] = QString::number(dlRate);
+ options["net/uploadRate"] = QString::number(ulRate);
+ server_->setOptions(options);
+// btSession_->setUploadRateLimit(ulRate);
+// btSession_->setDownloadRateLimit(dlRate);
+ }
+
+}
+
+void PreferencesDialog::ReadSettings()
+{
+ dirLineEdit_->insert(settings_.value("download/directory").toString());
+ uploadRateSpinBox_->setValue(settings_.value("net/uploadRate").toInt()/1000);
+ downloadRateSpinBox_->setValue(settings_.value("net/downloadRate").toInt()/1000);
+
+ // NOTE: We might need to call QSettigns::sync() here to instantly write settings.
+ // settings are written also by QSettings() destructor and by event loop at regular interval.
+}
+
--- /dev/null
+/***************************************************************************
+ * 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 PREFERENCESDIALOG_H
+#define PREFERENCESDIALOG_H
+
+#include <QDialog>
+#include <QSettings>
+
+
+class QAbstractButton;
+class QLineEdit;
+class QSpinBox;
+class QDialogButtonBox;
+
+class QtRapidsServer;
+
+
+/**
+ @author Lassi Väätämöinen <lassi.vaatamoinen@ixonos.com>
+*/
+class PreferencesDialog : public QDialog
+{
+
+ Q_OBJECT
+
+public:
+ PreferencesDialog(QWidget* parent = 0, Qt::WindowFlags f = 0, QtRapidsServer *server = 0);
+
+ ~PreferencesDialog();
+
+private slots:
+ void on_browseDirButtonClicked();
+ void on_buttonClicked(QAbstractButton* button);
+ void on_downloadDirectorySelected(QString directory);
+
+private:
+ QLineEdit *dirLineEdit_;
+ QDialogButtonBox *dialogButtons_;
+ QSpinBox *uploadRateSpinBox_, *downloadRateSpinBox_;
+
+ QtRapidsServer *server_;
+
+ QSettings settings_;
+
+private:
+ // Private functions:
+ void WriteSettings();
+ void ReadSettings();
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * 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 "SeedView.h"
+
+#include <QDebug>
+
+namespace qtrapids
+{
+
+SeedView::SeedView(QWidget* parent):
+ QTreeWidget(parent)
+{
+ setRootIsDecorated(false); // Hide branch lines, making one-level treeview (similar to list)
+ setHeaderItem(SeedViewItem::getHeaderItem());
+
+ connect(this, SIGNAL(itemPressed(QTreeWidgetItem*, int)),
+ this, SLOT(on_itemPressed(QTreeWidgetItem*, int)));
+}
+
+
+SeedView::~SeedView()
+{
+}
+
+void SeedView::on_itemPressed(QTreeWidgetItem * item, int column)
+{
+ qDebug() << "SeedView::on_itemPressed() " << item << "," << column;
+}
+
+} // namespace qtrapids
--- /dev/null
+/***************************************************************************
+ * 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 SEEDVIEW_H
+#define SEEDVIEW_H
+
+#include <QTreeWidget>
+
+namespace qtrapids
+{
+
+class TorrentHandle;
+class SeedViewItem;
+
+/**
+ @author Lassi Väätämöinen <lassi.vaatamoinen@ixonos.com>
+*/
+class SeedView : public QTreeWidget
+{
+ Q_OBJECT
+public:
+ SeedView(QWidget* parent);
+
+ ~SeedView();
+
+private slots:
+ void on_itemPressed(QTreeWidgetItem *item, int column);
+
+private:
+
+ // Name
+ // Size
+ // Status
+ // UP speed
+ // Seeds/Leechers
+ // Connected peers
+ // total uploaded
+ // ratio
+};
+
+/**
+ @class DownloadViewItem
+ @brief Represents one item row of DownloadView
+*/
+class SeedViewItem : public QTreeWidgetItem
+{
+
+public:
+
+ SeedViewItem(QTreeWidget* parent, int type) :
+ QTreeWidgetItem(parent, type = QTreeWidgetItem::UserType) {};
+
+ SeedViewItem(const QStringList& strings, int type = QTreeWidgetItem::UserType ) :
+ QTreeWidgetItem (strings, type = Type) {};
+
+
+ /// @return An item comprising of string list, suitable for QTableView
+ /// header.
+ static SeedViewItem *getHeaderItem() {
+ SeedViewItem *item
+ = new SeedViewItem(QStringList()
+ << "Name"
+ << "Size" << "Status"
+ << "Progress" << "UL speed" << "Seeds/Leechers"
+ << "Conn. peers"
+ << "Ratio");
+
+ return item;
+ }
+
+ /// @todo TorrentHandle as one hidden column
+};
+
+} // namespace qtrapids
+
+#endif
--- /dev/null
+/***************************************************************************
+ * 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 <QApplication>
+#include <QtDeclarative>
+#include <QDeclarativeContext>
+#include <QTest>
+#include <QDebug>
+//#include <QDesktopWidget>
+//#include "DownloadView.h"
+#include <QtDeclarative/qdeclarative.h>
+#include "models/QDeclarativeDownloadListModel.h"
+
+#include "MainWindow.h"
+#include "../include/qtrapids/dbus.hpp"
+
+using qtrapids::MainWindow;
+
+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;
+ app.setProperty("NoMStyle", true);
+
+ // Register our types:
+ qmlRegisterType<qtrapids::QDeclarativeDownloadListModel>("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<DownloadViewItem*>
+ (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();
+}
--- /dev/null
+#include <QObject>
+#include <QtDeclarative/qdeclarativeextensionplugin.h>
+#include <QtDeclarative/qdeclarative.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<qtrapids::QDeclarativeDownloadListModel>(uri, 1, 0, "DownloadListModel");
+ }
+};
+
+#include "moc_Plugin.cxx"
+
+Q_EXPORT_PLUGIN2(downloadlistmodelplugin, QT_PREPEND_NAMESPACE(QmlDownloadListModelPlugin));
\ No newline at end of file
--- /dev/null
+#include <QtDeclarative/qdeclarativeextensionplugin.h>
+#include <QtDeclarative/qdeclarative.h>
+
+#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<qtrapids::QDeclarativeDownloadListModel>(uri, 1, 0, "DownloadListModel");
+ }
+};
+
+Q_EXPORT_PLUGIN2(downloadlistmodelplugin, QT_PREPEND_NAMESPACE(QmlDownloadListModelPlugin));
\ No newline at end of file
--- /dev/null
+/***************************************************************************
+ * 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 <QtCore/QVariant>
+#include <QtCore/QDebug>
+
+#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<int, QByteArray> 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
--- /dev/null
+/***************************************************************************
+ * 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 <QDeclarativeParserStatus>
+#include <QAbstractListModel>
+#include <QtDeclarative>
+#include <QModelIndex>
+
+#include "qtrapids/dbus.hpp"
+#include "qtrapids/info.hpp"
+
+//#include "../DownloadView.h"
+
+QT_MODULE(Declarative);
+
+namespace qtrapids
+{
+
+typedef QHash<QString, TorrentState> DownloadItems_t;
+typedef QMap<int, QString> 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
--- /dev/null
+#ifndef QDECLARATIVEDOWNLOADLISTMODELPRIVATE_H
+#define QDECLARATIVEDOWNLOADLISTMODELPRIVATE_H
+
+#include <QModelIndex>
+
+#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
--- /dev/null
+plugin qmlfolderlistmodelplugin
\ No newline at end of file
--- /dev/null
+/*
+ * 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()
+{
+}
+
--- /dev/null
+/*
+ * 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 <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+#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<QVariant> argumentList;
+ argumentList << qVariantFromValue(path) << qVariantFromValue(save_path) << qVariantFromValue(other_params);
+ return asyncCallWithArgumentList(QLatin1String("addTorrent"), argumentList);
+ }
+
+ inline QDBusPendingReply<qtrapids::ParamsMap_t> getOptions()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QLatin1String("getOptions"), argumentList);
+ }
+
+ inline QDBusPendingReply<> getState()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QLatin1String("getState"), argumentList);
+ }
+
+ inline QDBusPendingReply<> removeTorrent(const QString &hash)
+ {
+ QList<QVariant> argumentList;
+ argumentList << qVariantFromValue(hash);
+ return asyncCallWithArgumentList(QLatin1String("removeTorrent"), argumentList);
+ }
+
+ inline QDBusPendingReply<> setOptions(qtrapids::ParamsMap_t options)
+ {
+ QList<QVariant> argumentList;
+ argumentList << qVariantFromValue(options);
+ return asyncCallWithArgumentList(QLatin1String("setOptions"), argumentList);
+ }
+
+ inline QDBusPendingReply<> terminateSession()
+ {
+ QList<QVariant> 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
--- /dev/null
+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
--- /dev/null
+
+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()}
+ }
+ }
+}
+
--- /dev/null
+ <!DOCTYPE RCC>
+ <RCC version="1.0">
+
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>MainPage.qml</file>
+ </qresource>
+
+ </RCC>
\ No newline at end of file