--- /dev/null
+project(qtrapids)
+cmake_minimum_required(VERSION 2.6)
+set(CMAKE_VERBOSE_MAKEFILE ON)
+
+add_definitions(-Wall -g)
+
+find_package(Qt4 REQUIRED)
+
+add_subdirectory(./dbus)
+add_subdirectory(./src/client)
+add_subdirectory(./src/server)
+
--- /dev/null
+SET(SOURCES com.ixonos.qtrapids.xml)
+SET(PROXY_SRC proxy.h proxy.cpp)
+SET(SERVER_SRC server.h server.cpp)
+
+SET(PROXY_TARGET
+ ${CMAKE_HOME_DIRECTORY}/src/client/proxy.h
+ ${CMAKE_HOME_DIRECTORY}/src/client/proxy.cpp)
+
+SET(SERVER_TARGET
+ ${CMAKE_HOME_DIRECTORY}/src/server/server.h
+ ${CMAKE_HOME_DIRECTORY}/src/server/server.cpp)
+
+SET(GENERATED_FILES ${PROXY_SRC} ${SERVER_SRC})
+
+ADD_CUSTOM_COMMAND(OUTPUT ${GENERATED_FILES}
+ COMMAND qdbusxml2cpp -a server -c QtRapidsServer -i "qtrapids/dbus.hpp" -p proxy ${SOURCES}
+ COMMAND cp ${PROXY_SRC} ${CMAKE_HOME_DIRECTORY}/src/client
+ COMMAND cp ${SERVER_SRC} ${CMAKE_HOME_DIRECTORY}/src/server
+ DEPENDS ${SOURCES}
+ COMMENT "DBus API sources")
+
+
+ADD_CUSTOM_TARGET(dbusapi ALL DEPENDS ${GENERATED_FILES})
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/com/ixonos/qtrapids">
+
+ <interface name="com.ixonos.qtrapids">
+
+ <method name="getState">
+ </method>
+
+ <method name="addTorrent">
+ <arg type="s" name="path" direction="in"/>
+ <arg type="s" name="save_path" direction="in"/>
+ <arg type="a{ss}" name="other_params" direction="in"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In2"
+ value="qtrapids::ParamsMap_t"/>
+ </method>
+
+ <method name="removeTorrent">
+ <arg type="s" name="hash" direction="in"/>
+ </method>
+
+ <signal name="alert">
+ <arg type="(ssuuuuuuut)" name="info" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In0"
+ value="qtrapids::TorrentState"/>
+ <arg type="a{ss}" name="other_info" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In1"
+ value="qtrapids::ParamsMap_t"/>
+ </signal>
+
+ </interface>
+
+</node>
INCLUDEPATH = /usr/local/include/libtorrent \
- /usr/local/include/boost-1_38
+ /usr/local/include/boost-1_38 \
+ ../include
CONFIG -= debug
--- /dev/null
+INCLUDE(${QT_USE_FILE})
+
+INCLUDE_DIRECTORIES(../include)
+
+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}
+)
+
+SET_SOURCE_FILES_PROPERTIES(./proxy.cpp ./proxy.h PROPERTIES GENERATED 1)
+
+SET(MOC_HEADERS
+ ./DownloadView.h
+ ./MainWindow.h
+ ./PreferencesDialog.h
+ ./proxy.h
+ ./SeedView.h
+)
+
+SET(SRC
+ ./DownloadView.cpp
+ ./main.cpp
+ ./MainWindow.cpp
+ ./PreferencesDialog.cpp
+ ./proxy.cpp
+ ./SeedView.cpp
+)
+
+QT4_WRAP_CPP(SRC ${MOC_HEADERS})
+ADD_EXECUTABLE(qtrapids ${SRC} ${MOC_HEADERS})
+
+ADD_DEFINITIONS(-DQT_SHARED)
+TARGET_LINK_LIBRARIES(qtrapids
+ ${QT_QTGUI_LIBRARY}
+ ${QT_QTCORE_LIBRARY}
+ ${QT_QTDBUS_LIBRARY}
+ ${QT_QTTEST_LIBRARY}
+ -lboost_system-mt
+)
+
+ADD_DEPENDENCIES(qtrapids dbusapi)
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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_()
+ {
+ 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);
+ if (p != items_.end()) {
+ updateItem_(p.value(), info, other_info);
+ } else {
+ addItem_(info, other_info);
+ }
+ }
+
+ 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)
+ << QString::number(info.down_rate, 'f', 2)
+ << QString::number(info.up_rate, 'f', 2)
+ << 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(QString::number(info.down_rate)));
+ item->setData(5, Qt::DisplayRole,
+ QVariant(QString::number(info.up_rate)));
+ item->setData(6, Qt::DisplayRole,
+ QString::number(info.seeds) + "/" + QString::number(info.leeches));
+
+ QBrush brushTmp(GetStatusColor((TorrentStatus::Id)info.state));
+ item->setForeground(2, brushTmp);
+ }
+
+
+ QString DownloadView::removeSelected()
+ {
+ qDebug() << "DownloadView::removeSelected() " << topLevelItemCount() ;
+
+ DownloadViewItem *item = dynamic_cast<DownloadViewItem*> (currentItem());
+ QString hash = item->getHash();
+
+ int removed = items_.remove(hash);
+ if (!removed)
+ qDebug() << "Inconsistent download view state on item removal";
+
+ int index = indexOfTopLevelItem(currentItem());
+ if (index >= 0) {
+ takeTopLevelItem(index);
+ }
+
+ 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);
+ }
+ */
+ }
+
+
+ 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) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 removeSelected();
+
+ private slots:
+ void on_itemClicked(QTreeWidgetItem * item, int column);
+ private:
+
+ void addItem_(TorrentState const& info, ParamsMap_t other_info);
+ void updateItem_(DownloadViewItem *item
+ , TorrentState const& info, ParamsMap_t other_info);
+
+ // Maps torrent to downloadview item.
+ // Key: SHA1 info hash of torrent. Data: View item corresponding to torrent.
+ DownloadItems_t items_;
+
+ // Private functions.
+ 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) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QTabWidget>
+
+#include "DownloadView.h"
+#include "SeedView.h"
+#include "PreferencesDialog.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\nAuthor(s):\nLassi Väätämöinen, lassi.vaatamoinen@ixonos.com"
+ "\nDenis Zalevskiy, denis.zalewsky@ixonos.com"
+ "\n\nIxonos Plc, Finland\n"));
+
+
+ // Consturctor
+ MainWindow::MainWindow() :
+ QMainWindow(), // Superclass
+ tabWidget_(NULL),
+ dlView_(NULL),
+ seedView_(NULL),
+ preferencesDialog_(NULL),
+ settings_(QCoreApplication::organizationName()
+ , QCoreApplication::applicationName()),
+ server_(QtRapidsServer::staticInterfaceName()
+ , "/qtrapids", QDBusConnection::sessionBus())
+ // torrentHandles_(),
+ {
+ // 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);
+ QAction *quitAction = tempMenu->addAction(tr("&Quit"));
+
+ 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(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();
+
+ /// @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::TopToolBarArea, toolBar);
+
+ connect(this, SIGNAL(itemSelected(bool)), removeAction,
+ SLOT(setEnabled(bool)));
+ connect(toolBar, SIGNAL(actionTriggered(QAction*)), this,
+ SLOT(handleToolBarAction(QAction*)));
+
+ QVariant geometry(settings_.value("geometry"));
+ if (!geometry.isNull()) {
+ qDebug() << "restoring geometry";
+ restoreGeometry(geometry.toByteArray());
+ }
+ }
+
+
+ MainWindow::~MainWindow()
+ {
+ settings_.setValue("geometry", saveGeometry());
+ }
+
+ // =========================== SLOTS =================================
+ void MainWindow::on_openAction_clicked()
+ {
+ 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_->removeSelected();
+ try {
+ server_.removeTorrent(hash);
+ } catch (...) {
+ qDebug() << "Exception removing torrent";
+ }
+ }
+
+ void MainWindow::on_quitAction_clicked()
+ {
+ close();
+ }
+
+ void MainWindow::on_preferencesAction_clicked()
+ {
+ if (!preferencesDialog_) {
+ preferencesDialog_ = new PreferencesDialog(this);
+ }
+ 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_downloadItemSelectionChanged()
+ {
+ qDebug() << "MainWindow::on_seedItemSelectionChanged():" << dlView_->currentItem();
+ if (dlView_->currentItem() != NULL) {
+ emit(itemSelected(true));
+ } else {
+ emit(itemSelected(false));
+ }
+ }
+
+ void MainWindow::on_seedItemSelectionChanged()
+ {
+ qDebug() << "MainWindow::on_seedItemSelectionChanged():" << seedView_->currentItem();
+ 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(const QString& file)
+ {
+ qDebug() << " MainWindow::on_torrentFileSelected(): " << file;
+ // 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::alert(qtrapids::TorrentState info, qtrapids::ParamsMap_t other_info)
+ {
+ std::cerr << "got alert" << std::endl;
+ dlView_->updateItem(info, other_info);
+ }
+
+} // namespace qtrapids
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 "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 {
+ Q_OBJECT;
+
+ public:
+
+ MainWindow();
+ ~MainWindow();
+
+ void connectToServer()
+ {
+ qDBusRegisterMetaType<qtrapids::TorrentState>();
+ qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
+
+ connect(&server_
+ , SIGNAL(alert(qtrapids::TorrentState
+ , qtrapids::ParamsMap_t))
+ , this
+ , SLOT(alert(qtrapids::TorrentState
+ , qtrapids::ParamsMap_t)));
+ 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_preferencesAction_clicked();
+ void on_aboutAction_clicked();
+ void on_aboutQtAction_clicked();
+ void on_downloadItemSelectionChanged();
+ void on_seedItemSelectionChanged();
+ void handleToolBarAction(QAction* action);
+ void on_torrentFileSelected(const QString& file);
+ void alert(qtrapids::TorrentState, qtrapids::ParamsMap_t);
+
+ private:
+ QTabWidget *tabWidget_;
+ DownloadView *dlView_;
+ SeedView *seedView_;
+ PreferencesDialog *preferencesDialog_;
+ QSettings settings_;
+
+ //std::vector< std::auto_ptr<QTorrentHandle> const > torrentHandles_;
+
+ QtRapidsServer server_;
+
+
+ //bool IsNewTorrent(std::auto_ptr<QTorrentHandle> handlePtr);
+ };
+
+} // namespace qtrapids
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 <QDialogButtonBox>
+#include <QAbstractButton>
+#include <QFileDialog>
+
+#include "PreferencesDialog.h"
+
+PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags f) :
+ QDialog(parent, f), // Superclass
+ dirLineEdit_(NULL),
+ dialogButtons_(NULL),
+ settings_()
+{
+ setWindowTitle("Preferences");
+
+ QBoxLayout *verticalBox = new QBoxLayout(QBoxLayout::TopToBottom);
+ QBoxLayout *horizontalBox1 = new QBoxLayout(QBoxLayout::LeftToRight);
+ setLayout(verticalBox);
+ verticalBox->addLayout(horizontalBox1);
+
+ QLabel *dirLabel = new QLabel(tr("Download directory: "));
+ dirLineEdit_ = new QLineEdit(this);
+ QPushButton *browseDirButton = new QPushButton(tr("Browse.."));
+
+ 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()
+{
+ 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();
+ close();
+ break;
+ case QDialogButtonBox::ApplyRole :
+ qDebug() << "PreferencesDialog: APPLY";
+ WriteSettings();
+ break;
+ case QDialogButtonBox::RejectRole :
+ qDebug() << "PreferencesDialog: CANCEL";
+ close();
+ break;
+ default:
+ return;
+ }
+}
+
+void PreferencesDialog::on_downloadDirectorySelected(const QString& directory)
+{
+ qDebug() << "PreferencesDialog::on_downloadDirectorySelected(): " << directory;
+ // Torrent filename empty, do nothing.
+ if (directory == "")
+ return;
+
+ dirLineEdit_->insert(directory);
+
+ /// @todo check that user has privileges to write to this directory.
+}
+
+
+// ========================= Private functions ==========================
+void PreferencesDialog::WriteSettings()
+{
+ settings_.setValue("download/directory", dirLineEdit_->text());
+
+ // 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.
+}
+
+void PreferencesDialog::ReadSettings()
+{
+ dirLineEdit_->insert(settings_.value("download/directory").toString());
+
+ // 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) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 QDialogButtonBox;
+
+/**
+ @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);
+
+ ~PreferencesDialog();
+
+ private slots:
+ void on_browseDirButtonClicked();
+ void on_buttonClicked(QAbstractButton* button);
+ void on_downloadDirectorySelected(const QString& directory);
+
+ private:
+ QLineEdit *dirLineEdit_;
+ QDialogButtonBox *dialogButtons_;
+ QSettings settings_;
+
+ // Private functions:
+ void WriteSettings();
+ void ReadSettings();
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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
+include (../../includes.pri)
+
+SOURCES += DownloadView.cpp \
+ SeedView.cpp \
+ MainWindow.cpp \
+ main.cpp \
+ PreferencesDialog.cpp \
+ proxy.cpp
+
+
+HEADERS += DownloadView.h \
+ SeedView.h \
+ MainWindow.h \
+ PreferencesDialog.h \
+ proxy.h \
+ ../include/qtrapids/dbus.hpp \
+ ../include/qtrapids/info.hpp
+
+
+TEMPLATE = app
+
+TARGET = qtrapids
+
+CONFIG -= release
+
+CONFIG += debug \
+ qtestlib
+
+QT += dbus
+
+DESTDIR = ../../bin
+
+INCLUDEPATH += ../include
+
+LIBS += -L../../bin \
+ -L../engine
+
+QMAKE_LFLAGS_DEBUG += -L.
+
+LIBS += -lboost_system-mt
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 <QTest>
+#include <QDebug>
+//#include <QDesktopWidget>
+//#include "DownloadView.h"
+
+#include "MainWindow.h"
+
+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;
+ mainWindow.connectToServer();
+ // 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);
+ }
+ */
+
+
+ return app.exec();
+}
--- /dev/null
+#ifndef _QTRAPIDS_DBUS_HPP_
+#define _QTRAPIDS_DBUS_HPP_
+
+#include <QtDBus/QtDBus>
+#include <QtCore/QString>
+#include <QtCore/QHash>
+
+// TMP TODO
+#include <iostream>
+
+namespace qtrapids
+{
+
+ struct TorrentState
+ {
+ TorrentState()
+ : hash("")
+ , name("")
+ , state(0)
+ , progress(0)
+ , down_rate(0)
+ , up_rate(0)
+ , seeds(0)
+ , leeches(0)
+ , ratio(0)
+ , total_size(0)
+ { }
+
+ QString hash;
+ QString name;
+ uint state;
+ uint progress;
+ uint down_rate;
+ uint up_rate;
+ uint seeds;
+ uint leeches;
+ uint ratio;
+ qulonglong total_size;
+ };
+
+ typedef QHash<QString, QString> ParamsMap_t;
+ typedef QHash<QString, QString> const ParamsMapConst_t;
+ typedef QHash<QString, QString>::iterator ParamsMapIterator_t;
+ typedef QHash<QString, QString>::const_iterator ParamsMapConstIterator_t;
+
+ static inline QDBusArgument& operator << (QDBusArgument& argument
+ , TorrentState const& state)
+ {
+ std::cout << "serialize" << std::endl;
+ argument.beginStructure();
+ argument << state.hash << state.name << state.state << state.progress
+ << state.down_rate << state.up_rate << state.seeds
+ << state.leeches << state.ratio << state.total_size;
+ argument.endStructure();
+ return argument;
+ }
+
+ static inline QDBusArgument const& operator >> (QDBusArgument const& argument
+ , TorrentState& state)
+ {
+ std::cout << "deserialize" << std::endl;
+ argument.beginStructure();
+ argument >> state.hash >> state.name >> state.state >> state.progress
+ >> state.down_rate >> state.up_rate >> state.seeds
+ >> state.leeches >> state.ratio >> state.total_size;
+ argument.endStructure();
+ return argument;
+ }
+
+ static inline QDBusArgument& operator << (QDBusArgument& argument
+ , ParamsMapConst_t& params)
+ {
+ ParamsMapConstIterator_t p;
+ std::cout << "serialize params" << std::endl;
+ argument.beginMap();
+ for (p = params.constBegin(); p != params.constEnd(); ++p) {
+ argument.beginMapEntry();
+ argument << p.key() << p.value();
+ argument.endMapEntry();
+ }
+ argument.endMap();
+ return argument;
+ }
+
+ static inline QDBusArgument const& operator >> (QDBusArgument const& argument
+ , ParamsMap_t& params)
+ {
+ ParamsMapConstIterator_t p;
+ QString key, value;
+ std::cout << "deserialize params" << std::endl;
+ argument.beginMap();
+ for (p = params.constBegin(); p != params.constEnd(); ++p) {
+ argument.beginMapEntry();
+ argument >> key >> value;
+ params[key] = value;
+ argument.endMapEntry();
+ }
+ argument.endMap();
+ return argument;
+ }
+
+
+ // class DBusConnector
+ // {
+ // public:
+ // DBusConnector()
+ // : connection_()
+ // {
+ // }
+ // private:
+ // QDBusConnection connection_;
+ // };
+
+}
+
+Q_DECLARE_METATYPE(qtrapids::TorrentState);
+Q_DECLARE_METATYPE(qtrapids::ParamsMap_t);
+
+#endif // _QTRAPIDS_DBUS_HPP_
+
--- /dev/null
+#ifndef _QTRAPIDS_ERROR_HPP_
+#define _QTRAPIDS_ERROR_HPP_
+
+#include <QString>
+
+namespace qtrapids
+{
+
+ class Error
+ {
+ public:
+
+ Error()
+ : msg_("")
+ { }
+
+ Error(char const *msg)
+ : msg_(msg)
+ {}
+
+ template <typename T>
+ void append_to_msg(T val)
+ {
+ msg_ << val;
+ }
+
+ private:
+ QString msg_;
+
+ };
+
+ template <typename T>
+ Error& operator << (Error &self, T val)
+ {
+ self.append_to_msg(val);
+ return self;
+ }
+
+ class InvalidArgument : public Error
+ {
+ };
+
+ template <typename T>
+ InvalidArgument& operator << (InvalidArgument &self, T val)
+ {
+ self.append_to_msg(val);
+ return self;
+ }
+
+}
+
+#endif // _QTRAPIDS_ERROR_HPP_
+
--- /dev/null
+#ifndef _QTRAPIDS_FORMAT_HPP_
+#define _QTRAPIDS_FORMAT_HPP_
+
+#include <qtrapids/info.hpp>
+#include <QtCore/QString>
+
+
+
+namespace qtrapids
+{
+
+
+ static inline QString formatProgress(uint progress)
+ {
+ return QString::number(((double)progress) / torrent_progress_max * 100);
+ }
+
+ namespace
+ {
+
+ static const qulonglong size_KB = 1024;
+ static const qulonglong size_MB = size_KB << 10;
+ static const qulonglong size_GB = size_MB << 10;
+
+ static char const* size_names[] = {
+ "GB",
+ "MB",
+ "KB",
+ "B"
+ };
+ }
+
+ static inline QString formatSize(qulonglong size)
+ {
+ qulonglong unit = size_GB;
+ char const ** unit_name = &size_names[0];
+ QString ret("");
+ for (unit = size_GB; unit > 0; unit >>= 10, ++unit_name) {
+ if (size & (~(unit - 1))) {
+ ret += (QString::number(size / unit) + *unit_name);
+ return ret;
+ }
+ }
+ ret += (QString::number(size / unit) + "B");
+ return ret;
+ }
+
+
+} // namespace qtrapids
+
+#endif // _QTRAPIDS_FORMAT_HPP_
+
--- /dev/null
+#ifndef _QTRAPIDS_INFO_HPP_
+#define _QTRAPIDS_INFO_HPP_
+
+#include <libtorrent/torrent_handle.hpp>
+
+#include <limits>
+#include <stdint.h>
+
+namespace qtrapids
+{
+
+ static const uint32_t torrent_progress_max = std::numeric_limits<uint32_t>::max();
+
+ typedef libtorrent::torrent_status TorrentStatus_t;
+ typedef libtorrent::torrent_status::state_t TorrentStatusIds_t;
+
+ struct TorrentStatus
+ {
+ enum Id {
+ QUEUED_FOR_CHECKING = TorrentStatus_t::queued_for_checking,
+ CHECKING_FILES = TorrentStatus_t::checking_files,
+ DOWNLOADING_METADATA = TorrentStatus_t::downloading_metadata,
+ DOWNLOADING = TorrentStatus_t::downloading,
+ FINISHED = TorrentStatus_t::finished,
+ SEEDING = TorrentStatus_t::seeding,
+ ALLOCATING = TorrentStatus_t::allocating,
+ CHECKING_RESUME_DATA = TorrentStatus_t::checking_resume_data,
+ UNSPECIFIED
+ };
+ };
+
+}
+
+#endif // _QTRAPIDS_INFO_HPP_
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 "AlertWaiterThread.hpp"
+#include <QDebug>
+
+
+namespace qtrapids
+{
+
+ // Constants:
+ // Timeout for waiting alerts
+ const libtorrent::time_duration ALERT_WAIT_TIMEOUT
+ = libtorrent::time_duration(libtorrent::seconds(15));
+
+
+ AlertWaiterThread::AlertWaiterThread(session_t *session, QObject* parent) :
+ QThread(parent),
+ btSession_(session)
+ {
+ }
+
+
+ AlertWaiterThread::~AlertWaiterThread()
+ {
+ }
+
+
+ void AlertWaiterThread::allAlerts(bool enable)
+ {
+ // If all enabled, set all alert cateogries:
+ if (enable) {
+ btSession_->set_alert_mask(libtorrent::alert::all_categories);
+ } else {
+ // Otherwise set to default, which is only error notifications.
+ btSession_->set_alert_mask(libtorrent::alert::error_notification);
+ }
+ }
+
+
+ void AlertWaiterThread::run()
+ {
+ alert_t const *alertTemp = NULL;
+ while (true) {
+ // wait_for_alert() call blocks. Returns libtorrent alert.
+ // Returns NULL, if no alerts in timeout period.
+ alertTemp = btSession_->wait_for_alert(ALERT_WAIT_TIMEOUT);
+ emit alert();
+ // 2000 us = 2ms. Gives main thread time to handle alert signal.
+ usleep(2000);
+ }
+ }
+
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 ALERTWAITERTHREAD_H
+#define ALERTWAITERTHREAD_H
+
+#include <QThread>
+#include "TorrentSession.hpp"
+
+namespace qtrapids
+{
+
+ /**
+ @author Lassi Väätämöinen <lassi.vaatamoinen@ixonos.com>
+ */
+ class AlertWaiterThread : public QThread
+ {
+ Q_OBJECT
+
+ public:
+ AlertWaiterThread(session_t *session, QObject *parent = 0);
+
+ virtual ~AlertWaiterThread();
+
+ void allAlerts(bool enable = true);
+
+ virtual void run(); // Overridden from QThread
+
+ signals:
+ void alert();
+
+ private:
+ session_t *const btSession_;
+
+ };
+
+} // namespace qtrapids
+
+#endif
--- /dev/null
+INCLUDE(${QT_USE_FILE})
+
+FIND_LIBRARY(TORRENT_RASTERBAR torrent-rasterbar)
+IF(${TORRENT_RASTERBAR} STREQUAL TORRENT_RASTERBAR-NOTFOUND)
+ MESSAGE(SEND_ERROR ${TORRENT_RASTERBAR})
+ENDIF(${TORRENT_RASTERBAR} STREQUAL TORRENT_RASTERBAR-NOTFOUND)
+
+INCLUDE_DIRECTORIES(../include)
+
+INCLUDE_DIRECTORIES(
+ ${QT_INCLUDE_DIR}
+ ${QT_QTDBUS_INCLUDE_DIR}
+ ${QT_QTSQL_INCLUDE_DIR}
+)
+
+SET_SOURCE_FILES_PROPERTIES(./server.cpp ./server.h PROPERTIES GENERATED 1)
+
+SET(MOC_HEADERS
+ ./AlertWaiterThread.hpp
+ ./TorrentHandle.hpp
+ ./TorrentSession.hpp
+ ./server.h
+)
+
+SET(SRC
+ ./AlertWaiterThread.cpp
+ ./main.cpp
+ ./server.cpp
+ ./TorrentHandle.cpp
+ ./TorrentSession.cpp
+)
+
+QT4_WRAP_CPP(SRC ${MOC_HEADERS} )
+
+ADD_EXECUTABLE(qtrapids-server ${SRC} ${MOC_HEADERS})
+
+ADD_DEFINITIONS(-DQT_SHARED)
+TARGET_LINK_LIBRARIES(qtrapids-server
+ ${QT_QTCORE_LIBRARY}
+ ${QT_QTDBUS_LIBRARY}
+ ${QT_QTSQL_LIBRARY}
+ -ltorrent-rasterbar
+)
+
+ADD_DEPENDENCIES(qtrapids-server dbusapi)
--- /dev/null
+#ifndef _SERVERDB_HPP_
+#define _SERVERDB_HPP_
+
+#include <QSettings>
+#include <QtSql>
+#include <QDir>
+
+namespace qtrapids
+{
+
+ class ServerSettings
+ {
+
+ public:
+ ServerSettings(QSettings *settings)
+ : settings_(settings)
+ { }
+
+ ~ServerSettings()
+ {
+
+ }
+
+ QString getDbEngine() const
+ {
+ return getParamAndStore("db_engine", getDefaultDbEngine()).toString();
+ }
+
+ QString getDbName() const
+ {
+ QString default_db_path(QDir::home().filePath(appName() + ".sqlite"));
+ return getParamAndStore("db", default_db_path).toString();
+ }
+
+ QString getTorrentsDir() const
+ {
+ QString default_dir(QDir::home().filePath(QString(".") + appName()));
+ return getParamAndStore("db", default_dir).toString();
+
+ }
+
+ private:
+
+ ServerSettings(ServerSettings const&);
+ ServerSettings& operator= (ServerSettings const&);
+
+ static inline QString appName()
+ {
+ return QCoreApplication::applicationName();
+ }
+
+ static QString getDefaultDbEngine()
+ {
+ // for (QStringListIterator p = QSqlDatabase::drivers(); p.hasNext();) {
+ // return p.next();
+ // }
+ return "QSQLITE";
+ }
+
+ QVariant getParamAndStore(QString const& name, QVariant default_value) const
+ {
+ QVariant v(settings_->value(name));
+ if (!v.isNull()) {
+ return v;
+ }
+
+ settings_->setValue(name, default_value);
+ return default_value;
+ }
+
+ mutable QSettings *settings_;
+ };
+
+ class ServerDb
+ {
+
+ public:
+ ServerDb(ServerSettings *settings)
+ : db_(QSqlDatabase::addDatabase(settings->getDbEngine()))
+ {
+ QString db_name(settings->getDbName());
+ db_.setDatabaseName(db_name);
+
+ if (!db_.open()) {
+ qDebug() << "cant open db";
+ return;
+ }
+ qDebug() << "opened " << db_name;
+
+ QSqlQuery q;
+ if (!q.exec("create table torrents (hash varchar primary key, path varchar, savepath varchar);\n")) {
+ qDebug() << "cant create table: " << q.lastError().text();
+ }
+ }
+
+ ~ServerDb()
+ {
+ db_.close();
+ }
+
+ void addTorrent(const QString &hash, const QString &path, const QString &save_path)
+ {
+ if (!db_.open()) {
+ qDebug() << "cant open db";
+ }
+ QSqlQuery query_add_;
+ query_add_.prepare("INSERT INTO torrents (hash, path, savepath) VALUES (?, ?, ?)");
+ query_add_.bindValue(0, hash);
+ query_add_.bindValue(1, path);
+ query_add_.bindValue(2, save_path);
+ if (!query_add_.exec()) {
+ qDebug() << "cant add torrent info into db: "
+ << query_add_.lastError().text();
+ }
+ db_.close();
+ }
+
+ private:
+
+ ServerDb(ServerDb const&);
+ ServerDb& operator= (ServerDb const&);
+
+ QSqlDatabase db_;
+ };
+
+} // namespace qtrapids
+
+#endif // _SERVERDB_HPP_
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 "TorrentHandle.hpp"
+#include <QDebug>
+
+
+namespace qtrapids
+{
+
+ TorrentHandle::TorrentHandle(libtorrent::torrent_handle handle) :
+ torrentHandle_(handle)
+ {
+ }
+
+
+ TorrentHandle::~TorrentHandle()
+ {
+ }
+
+
+ TorrentStatus_t TorrentHandle::status() const
+ {
+ return torrentHandle_.status();
+ }
+
+
+ torrent_info_cref TorrentHandle::getTorrentInfo() const
+ {
+ return torrentHandle_.get_torrent_info();
+ }
+
+
+ bool TorrentHandle::isValid() const
+ {
+ return torrentHandle_.is_valid();
+ }
+
+
+ QString TorrentHandle::name() const
+ {
+ return QString::fromStdString(torrentHandle_.name());
+ }
+
+ size_t TorrentHandle::getTotalSize() const
+ {
+ torrent_info_cref info = getTorrentInfo();
+ return static_cast<size_t> (info.total_size());
+ }
+
+
+ TorrentStatus::Id TorrentHandle::state() const
+ {
+ TorrentStatus::Id s = (TorrentStatus::Id)(status().state);
+ return ( (s < TorrentStatus::UNSPECIFIED)
+ ? s : TorrentStatus::UNSPECIFIED );
+ }
+
+
+ float TorrentHandle::progress() const
+ {
+ TorrentStatus_t statusTmp = status();
+ return statusTmp.progress;
+ }
+
+ float TorrentHandle::uploadRate() const
+ {
+ TorrentStatus_t statusTmp = status();
+ return statusTmp.upload_rate;
+ }
+
+
+ float TorrentHandle::downloadRate() const
+ {
+ TorrentStatus_t statusTmp = status();
+ return statusTmp.download_rate;
+ }
+
+
+ qint32 TorrentHandle::numSeeds() const
+ {
+ TorrentStatus_t statusTmp = status();
+ return statusTmp.list_seeds;
+ }
+
+
+ qint32 TorrentHandle::numLeeches() const
+ {
+ TorrentStatus_t statusTmp = status();
+ return (statusTmp.list_peers - statusTmp.list_seeds);
+ }
+
+
+ qint32 TorrentHandle::ratio() const
+ {
+ TorrentStatus_t statusTmp = status();
+ size_t ratio;
+ if (statusTmp.total_payload_download == 0) {
+ ratio = 0;
+ } else {
+ ratio = static_cast<size_t> (statusTmp.total_payload_upload / statusTmp.total_payload_download);
+ }
+
+ return ratio;
+ }
+
+
+ torrent_handle_t TorrentHandle::getHandle() const
+ {
+ return torrentHandle_;
+ }
+
+
+ bool TorrentHandle::operator==(TorrentHandle const& h) const
+ {
+ return torrentHandle_ == h.torrentHandle_;
+ }
+
+
+ bool TorrentHandle::operator<(TorrentHandle const& h) const
+ {
+ return torrentHandle_ < h.torrentHandle_;
+ }
+
+
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Lassi Väätämöinen *
+ * lassi.vaatamoinen@ixonos.com *
+ * *
+ * 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; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU 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 QTORRENTHANDLE_H
+#define QTORRENTHANDLE_H
+
+#include <QtGlobal>
+#include <QString>
+
+#include <qtrapids/info.hpp>
+#include <libtorrent/torrent_handle.hpp>
+
+namespace qtrapids
+{
+
+ typedef libtorrent::torrent_info const& torrent_info_cref;
+ typedef libtorrent::torrent_handle torrent_handle_t;
+ typedef libtorrent::sha1_hash Sha1Hash;
+
+
+ inline QString Hash2QStr(Sha1Hash const& hash)
+ {
+ return QString(hash.to_string().c_str());
+ }
+
+ /**
+ @author Lassi Väätämöinen <lassi.vaatamoinen@ixonos.com>
+ */
+ class TorrentHandle
+ {
+ public:
+
+ TorrentHandle(libtorrent::torrent_handle handle);
+ ~TorrentHandle();
+
+
+
+ torrent_info_cref getTorrentInfo() const;
+
+ bool isValid() const;
+
+ Sha1Hash hash() const
+ {
+ return torrentHandle_.info_hash();
+ }
+
+ QString name() const;
+ size_t getTotalSize() const;
+ TorrentStatus::Id state() const;
+ float progress() const;
+ float uploadRate() const;
+ float downloadRate() const;
+ qint32 numSeeds() const;
+ qint32 numLeeches() const;
+ qint32 ratio() const;
+
+ torrent_handle_t getHandle() const;
+ bool operator==(TorrentHandle const& h) const;
+ bool operator<(TorrentHandle const& h) const;
+
+ private:
+ TorrentHandle(); // Prevent default construct.
+ torrent_handle_t torrentHandle_;
+
+ TorrentStatus_t status() const;
+
+ };
+
+}
+
+#endif
--- /dev/null
+#include "TorrentSession.hpp"
+#include "TorrentHandle.hpp"
+#include "AlertWaiterThread.hpp"
+
+
+namespace qtrapids
+{
+
+
+
+ TorrentSession::TorrentSession(QObject *parent, QSettings *settings)
+ : QObject(parent)
+ , btSession_()
+ , alertWaiter_(new AlertWaiterThread(&btSession_, this))
+ {
+ qDBusRegisterMetaType<qtrapids::TorrentState>();
+ qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
+ new QtRapidsServer(this);
+
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ dbus.registerObject("/qtrapids", this);
+ dbus.registerService("com.ixonos.qtrapids");
+
+ alertWaiter_->allAlerts();
+ connect(alertWaiter_, SIGNAL(alert()), this, SLOT(on_alert()));
+ alertWaiter_->start();
+
+
+ }
+
+ void TorrentSession::on_alert()
+ //NOTE: al parameter not necessarily needed here, as we pop_alert() now!
+ {
+
+ //qDebug() << "QBittorrentSession:on_alert(" << al << ")";
+ // if (al)
+ // qDebug() << "on_alert():" << QString::fromStdString(al->message());
+
+ std::auto_ptr<alert_t> alertPtr = btSession_.pop_alert();
+
+ if (alertPtr.get() != NULL) {
+
+ torrent_alert_t *ta = dynamic_cast<torrent_alert_t*> (alertPtr.get());
+
+ qDebug()
+ << "QBittorrentSession::on_alert(): "
+ << QString::fromStdString(alertPtr->message());
+
+
+ if (ta) {
+ TorrentHandle handle(ta->handle);
+ TorrentState state;
+
+ state.hash = Hash2QStr(handle.hash());
+ state.state = handle.state();
+ state.progress = handle.progress() * torrent_progress_max;
+ state.down_rate = handle.downloadRate();
+ state.up_rate = handle.uploadRate();
+ state.seeds = handle.numSeeds();
+ state.leeches = handle.numLeeches();
+
+ ParamsMap_t params;
+ emit alert(state, params);
+ }
+
+ }
+ }
+
+ void TorrentSession::getState()
+ {
+ torrents_t::const_iterator p;
+ for (p = torrents_.constBegin(); p != torrents_.constEnd(); ++p) {
+ TorrentHandlePtr handle = *p;
+ TorrentState state;
+ QString hash = Hash2QStr(handle->hash());
+
+ state.hash = hash;
+ state.name = handle->name();
+ state.state = handle->state();
+ state.progress = handle->progress() * torrent_progress_max;
+ state.down_rate = handle->downloadRate();
+ state.up_rate = handle->uploadRate();
+ state.seeds = handle->numSeeds();
+ state.leeches = handle->numLeeches();
+ state.total_size = handle->getTotalSize();
+
+ emit alert(state, ParamsMap_t());
+ }
+ }
+
+ void TorrentSession::addTorrent(const QString &path, const QString &save_path
+ , qtrapids::ParamsMap_t other_params)
+ {
+ add_torrent_params_t addParams;
+ QFile torrent_file(path);
+ if (!torrent_file.exists()) {
+ qWarning() << "Torrent file " << path << "doesn't exist";
+ return;
+ }
+
+ qDebug() << "addTorrent: " << path << " save to " << save_path;
+ boost::intrusive_ptr<libtorrent::torrent_info> tiTmp
+ = new libtorrent::torrent_info(path.toStdString());
+ addParams.ti = tiTmp;
+
+ // save_path is the only mandatory parameter, rest are optional.
+ addParams.save_path = save_path.toStdString();
+ //addParams.storage_mode = libtorrent::storage_mode_allocate;
+
+ TorrentHandlePtr handle(new TorrentHandle(btSession_.add_torrent(addParams)));
+ QString hash = Hash2QStr(handle->hash());
+
+ TorrentState state;
+
+ state.hash = hash;
+ state.name = handle->name();
+ state.state = handle->state();
+ state.progress = handle->progress() * torrent_progress_max;
+ state.down_rate = handle->downloadRate();
+ state.up_rate = handle->uploadRate();
+ state.seeds = handle->numSeeds();
+ state.leeches = handle->numLeeches();
+ state.total_size = handle->getTotalSize();
+
+ torrents_[hash] = handle;
+
+ emit alert(state, ParamsMap_t());
+ }
+
+ void TorrentSession::removeTorrent(const QString &hash)
+ {
+ torrents_t::iterator p = torrents_.find(hash);
+ if (p == torrents_.end()) {
+ qDebug() << "Invalid request to remove torrent with hash " << hash;
+ return;
+ }
+ try {
+ btSession_.remove_torrent(p.value()->getHandle());
+ } catch (torrent_exception_t e) {
+ qDebug() << // e.what()
+ "exception catched"
+ ;
+ }
+ }
+
+
+} // namespace qtrapids
--- /dev/null
+#ifndef _TEST_HPP_
+#define _TEST_HPP_
+
+#include "TorrentHandle.hpp"
+#include "server.h"
+
+#include <QObject>
+#include <QString>
+#include <QSharedPointer>
+#include <QWeakPointer>
+
+#include <qtrapids/dbus.hpp>
+
+#include <libtorrent/session.hpp>
+#include <libtorrent/torrent_info.hpp>
+#include <libtorrent/alert_types.hpp>
+#include <libtorrent/error_code.hpp>
+
+class QSettings;
+
+namespace qtrapids
+{
+
+ typedef QWeakPointer<QSettings> settings_weak_ptr;
+
+ class AlertWaiterThread;
+ typedef libtorrent::session session_t;
+ typedef libtorrent::session const* session_cptr;
+
+ typedef libtorrent::add_torrent_params add_torrent_params_t;
+ typedef libtorrent::alert alert_t;
+ // typedef libtorrent::alert const* alert_cptr;
+ typedef libtorrent::torrent_alert torrent_alert_t;
+ typedef libtorrent::libtorrent_exception torrent_exception_t;
+
+ typedef QSharedPointer<TorrentHandle> TorrentHandlePtr;
+ typedef QHash<QString, TorrentHandlePtr > torrents_t;
+
+ class ServerDb;
+ class ServerSettings;
+
+ class TorrentSession : public QObject
+ {
+
+ Q_OBJECT;
+ Q_CLASSINFO("D-Bus Interface", "com.ixonos.qtrapids");
+
+ public:
+
+ TorrentSession(QObject *parent, QSettings *);
+
+ public slots:
+
+ void getState();
+ void addTorrent(const QString &path, const QString &save_path
+ , qtrapids::ParamsMap_t other_params);
+ void removeTorrent(const QString &hash);
+
+ signals:
+ void alert(qtrapids::TorrentState info, qtrapids::ParamsMap_t other_info);
+
+ private slots:
+ void on_alert();
+
+ private:
+ session_t btSession_;
+ AlertWaiterThread *alertWaiter_;
+ torrents_t torrents_;
+ };
+
+} // namespace qtrapids
+
+#endif // _TEST_HPP_
--- /dev/null
+drop table torrents;
+create table torrents(path varchar, savepath varchar);
--- /dev/null
+#include <QtCore/QCoreApplication>
+//#include "server.h"
+#include "TorrentSession.hpp"
+
+using qtrapids::TorrentSession;
+using qtrapids::settings_weak_ptr;
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setOrganizationName("Ixonos");
+ QCoreApplication::setOrganizationDomain("ixonos.com");
+ QCoreApplication::setApplicationName("QtRapids");
+ QSettings settings(QCoreApplication::organizationName()
+ , QCoreApplication::applicationName());
+
+ QCoreApplication app(argc, argv);
+ TorrentSession server(&app, &settings);
+ return app.exec();
+}
--- /dev/null
+include (../../includes.pri)
+
+TEMPLATE = app
+
+CONFIG += console debug
+CONFIG -= app_bundle
+
+VERSION = 0.2
+
+HEADERS += \
+TorrentSession.hpp \
+AlertWaiterThread.hpp \
+TorrentHandle.hpp \
+server.h \
+../include/qtrapids/dbus.hpp \
+../include/qtrapids/status.hpp
+
+SOURCES += \
+ main.cpp \
+ server.cpp \
+ TorrentSession.cpp \
+ TorrentHandle.cpp \
+ AlertWaiterThread.cpp
+
+QT += dbus sql
+
+QT -= gui
+
+CONFIG -= release
+
+TARGET = qtrapids-server
+
+DESTDIR = ../../bin
+
+LIBS += -ltorrent-rasterbar
+
SUBDIRS += engine \
gui
-
CONFIG += ordered \
warn_on \
thread \