X-Git-Url: http://git.maemo.org/git/?p=qtrapids;a=blobdiff_plain;f=src%2Fclient%2FMainWindow.cpp;h=551197a4255d1cdd47c646a68d4de1a6dca02b46;hp=e2008651558a494489ca250ce7396b2e799faf35;hb=711f20225524f059da9296f814a06ab9332bb324;hpb=06410091b1e07c443849f0fe71050654c6fb9710 diff --git a/src/client/MainWindow.cpp b/src/client/MainWindow.cpp index e200865..551197a 100644 --- a/src/client/MainWindow.cpp +++ b/src/client/MainWindow.cpp @@ -1,11 +1,9 @@ /*************************************************************************** - * Copyright (C) 2009 by Lassi Väätämöinen * - * lassi.vaatamoinen@ixonos.com * + * 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; either version 2 of the License, or * - * (at your option) any later version. * + * 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 * @@ -25,210 +23,481 @@ #include #include #include -#include -#include -#include +#include +#include +//#include +#include +#include #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\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); - } +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)), +// this, SLOT(on_alert(std::auto_ptr))); + + + 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; - 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)); - } - } + // 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); + } - 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); - } + /// @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(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