Some work about adaptive color scheme for Web UI (PR #19901)
http://[316:c51a:62a3:8b9::4]/d4708/qBittorrent/src/branch/adaptive-webui
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1176 lines
44 KiB
1176 lines
44 KiB
/* |
|
* Bittorrent Client using Qt4 and libtorrent. |
|
* Copyright (C) 2006 Christophe Dumez |
|
* |
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
* |
|
* In addition, as a special exception, the copyright holders give permission to |
|
* link this program with the OpenSSL project's "OpenSSL" library (or with |
|
* modified versions of it that use the same license as the "OpenSSL" library), |
|
* and distribute the linked executables. You must obey the GNU General Public |
|
* License in all respects for all of the code used other than "OpenSSL". If you |
|
* modify file(s), you may extend this exception to your version of the file(s), |
|
* but you are not obligated to do so. If you do not wish to do so, delete this |
|
* exception statement from your version. |
|
* |
|
* Contact : chris@qbittorrent.org |
|
*/ |
|
#ifdef WITH_LIBNOTIFY |
|
#include <glib.h> |
|
#include <unistd.h> |
|
#include <libnotify/notify.h> |
|
#endif |
|
|
|
#include <QFileDialog> |
|
#include <QMessageBox> |
|
#include <QTimer> |
|
#include <QDesktopServices> |
|
#include <QStatusBar> |
|
#include <QClipboard> |
|
#include <QCloseEvent> |
|
#include <QShortcut> |
|
|
|
#include "GUI.h" |
|
#include "transferlistwidget.h" |
|
#include "misc.h" |
|
#include "createtorrent_imp.h" |
|
#include "downloadfromurldlg.h" |
|
#include "torrentadditiondlg.h" |
|
#include "searchengine.h" |
|
#include "rss_imp.h" |
|
#include "bittorrent.h" |
|
#include "about_imp.h" |
|
#include "trackerlogin.h" |
|
#include "options_imp.h" |
|
#include "speedlimitdlg.h" |
|
#include "preferences.h" |
|
#include "console_imp.h" |
|
#include "trackerlist.h" |
|
#include "peerlistwidget.h" |
|
#include "torrentpersistentdata.h" |
|
#include "transferlistfilterswidget.h" |
|
#include "propertieswidget.h" |
|
#include "statusbar.h" |
|
#include "hidabletabwidget.h" |
|
#include "qinisettings.h" |
|
#ifdef Q_WS_MAC |
|
#include "qmacapplication.h" |
|
void qt_mac_set_dock_menu(QMenu *menu); |
|
#endif |
|
#include "lineedit.h" |
|
|
|
using namespace libtorrent; |
|
|
|
#define TIME_TRAY_BALLOON 5000 |
|
|
|
/***************************************************** |
|
* * |
|
* GUI * |
|
* * |
|
*****************************************************/ |
|
|
|
// Constructor |
|
GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), force_exit(false) { |
|
setupUi(this); |
|
ui_locked = Preferences::isUILocked(); |
|
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent v0.x").arg(QString::fromUtf8(VERSION))); |
|
displaySpeedInTitle = Preferences::speedInTitleBar(); |
|
// Setting icons |
|
this->setWindowIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent32.png"))); |
|
actionOpen->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/open.png"))); |
|
actionExit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/exit.png"))); |
|
actionDownload_from_URL->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/url.png"))); |
|
actionOptions->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/settings.png"))); |
|
actionAbout->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/info.png"))); |
|
actionWebsite->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent32.png"))); |
|
actionBugReport->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/bug.png"))); |
|
actionStart->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play.png"))); |
|
actionPause->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause.png"))); |
|
actionDelete->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png"))); |
|
actionPause_All->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/pause_all.png"))); |
|
actionStart_All->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/play_all.png"))); |
|
actionClearLog->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/delete.png"))); |
|
actionPreview_file->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/preview.png"))); |
|
actionSet_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))); |
|
actionSet_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/download.png"))); |
|
actionSet_global_upload_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/seeding.png"))); |
|
actionSet_global_download_limit->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/download.png"))); |
|
actionDocumentation->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/qb_question.png"))); |
|
actionLock_qBittorrent->setIcon(QIcon(QString::fromUtf8(":/Icons/oxygen/encrypted32.png"))); |
|
QMenu *lockMenu = new QMenu(); |
|
QAction *defineUiLockPasswdAct = lockMenu->addAction(tr("Set the password...")); |
|
connect(defineUiLockPasswdAct, SIGNAL(triggered()), this, SLOT(defineUILockPassword())); |
|
actionLock_qBittorrent->setMenu(lockMenu); |
|
prioSeparator = toolBar->insertSeparator(actionDecreasePriority); |
|
prioSeparator2 = menu_Edit->insertSeparator(actionDecreasePriority); |
|
prioSeparator->setVisible(false); |
|
prioSeparator2->setVisible(false); |
|
actionCreate_torrent->setIcon(QIcon(QString::fromUtf8(":/Icons/skin/new.png"))); |
|
// Fix Tool bar layout |
|
toolBar->layout()->setSpacing(7); |
|
// Creating Bittorrent session |
|
BTSession = new Bittorrent(); |
|
connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&, QString)), this, SLOT(fullDiskError(QTorrentHandle&, QString))); |
|
connect(BTSession, SIGNAL(finishedTorrent(QTorrentHandle&)), this, SLOT(finishedTorrent(QTorrentHandle&))); |
|
connect(BTSession, SIGNAL(trackerAuthenticationRequired(QTorrentHandle&)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle&))); |
|
connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString))); |
|
connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString))); |
|
connect(BTSession, SIGNAL(alternativeSpeedsModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool))); |
|
connect(BTSession, SIGNAL(recursiveTorrentDownloadPossible(QTorrentHandle&)), this, SLOT(askRecursiveTorrentDownloadConfirmation(QTorrentHandle&))); |
|
#ifdef Q_WS_MAC |
|
connect(static_cast<QMacApplication*>(qApp), SIGNAL(newFileOpenMacEvent(QString)), this, SLOT(processParams(QString))); |
|
#endif |
|
|
|
qDebug("create tabWidget"); |
|
tabs = new HidableTabWidget(); |
|
connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tab_changed(int))); |
|
vSplitter = new QSplitter(Qt::Horizontal); |
|
//vSplitter->setChildrenCollapsible(false); |
|
hSplitter = new QSplitter(Qt::Vertical); |
|
hSplitter->setChildrenCollapsible(false); |
|
|
|
// Transfer List tab |
|
transferList = new TransferListWidget(hSplitter, this, BTSession); |
|
properties = new PropertiesWidget(hSplitter, this, transferList, BTSession); |
|
transferListFilters = new TransferListFiltersWidget(vSplitter, transferList); |
|
hSplitter->addWidget(transferList); |
|
hSplitter->addWidget(properties); |
|
vSplitter->addWidget(transferListFilters); |
|
vSplitter->addWidget(hSplitter); |
|
vSplitter->setCollapsible(0, true); |
|
vSplitter->setCollapsible(1, false); |
|
tabs->addTab(vSplitter, QIcon(QString::fromUtf8(":/Icons/oxygen/folder-remote.png")), tr("Transfers")); |
|
connect(transferList, SIGNAL(torrentStatusUpdate(uint,uint,uint,uint,uint)), this, SLOT(updateNbTorrents(uint,uint,uint,uint,uint))); |
|
vboxLayout->addWidget(tabs); |
|
|
|
// Name filter |
|
search_filter = new LineEdit(); |
|
toolBar->addWidget(search_filter); |
|
search_filter->setFixedWidth(200); |
|
connect(search_filter, SIGNAL(textChanged(QString)), transferList, SLOT(applyNameFilter(QString))); |
|
|
|
// Transfer list slots |
|
connect(actionStart, SIGNAL(triggered()), transferList, SLOT(startSelectedTorrents())); |
|
connect(actionStart_All, SIGNAL(triggered()), transferList, SLOT(startAllTorrents())); |
|
connect(actionPause, SIGNAL(triggered()), transferList, SLOT(pauseSelectedTorrents())); |
|
connect(actionPause_All, SIGNAL(triggered()), transferList, SLOT(pauseAllTorrents())); |
|
connect(actionDelete, SIGNAL(triggered()), transferList, SLOT(deleteSelectedTorrents())); |
|
connect(actionIncreasePriority, SIGNAL(triggered()), transferList, SLOT(increasePrioSelectedTorrents())); |
|
connect(actionDecreasePriority, SIGNAL(triggered()), transferList, SLOT(decreasePrioSelectedTorrents())); |
|
|
|
// Configure BT session according to options |
|
loadPreferences(false); |
|
|
|
// Start connection checking timer |
|
guiUpdater = new QTimer(this); |
|
connect(guiUpdater, SIGNAL(timeout()), this, SLOT(updateGUI())); |
|
guiUpdater->start(2000); |
|
// Accept drag 'n drops |
|
setAcceptDrops(true); |
|
createKeyboardShortcuts(); |
|
// Create status bar |
|
status_bar = new StatusBar(QMainWindow::statusBar(), BTSession); |
|
connect(actionUse_alternative_speed_limits, SIGNAL(triggered()), status_bar, SLOT(toggleAlternativeSpeeds())); |
|
|
|
#ifdef Q_WS_MAC |
|
setUnifiedTitleAndToolBarOnMac(true); |
|
#endif |
|
|
|
// View settings |
|
actionTop_tool_bar->setChecked(Preferences::isToolbarDisplayed()); |
|
actionSpeed_in_title_bar->setChecked(Preferences::speedInTitleBar()); |
|
actionRSS_Reader->setChecked(Preferences::isRSSEnabled()); |
|
actionSearch_engine->setChecked(Preferences::isSearchEnabled()); |
|
displaySearchTab(actionSearch_engine->isChecked()); |
|
displayRSSTab(actionRSS_Reader->isChecked()); |
|
actionShutdown_when_downloads_complete->setChecked(Preferences::shutdownWhenDownloadsComplete()); |
|
|
|
show(); |
|
|
|
// Load Window state and sizes |
|
readSettings(); |
|
properties->readSettings(); |
|
|
|
// Limit status filters list height |
|
int cur_height = 80; |
|
do { |
|
transferListFilters->getStatusFilters()->setFixedHeight(cur_height); |
|
cur_height += 10; |
|
transferListFilters->getStatusFilters()->scrollToBottom(); |
|
}while(transferListFilters->getStatusFilters()->verticalScrollBar()->sliderPosition() > 0); |
|
transferListFilters->getStatusFilters()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
|
|
if(ui_locked) { |
|
hide(); |
|
} else { |
|
if(Preferences::startMinimized()) |
|
showMinimized(); |
|
} |
|
|
|
// Resume unfinished torrents |
|
BTSession->startUpTorrents(); |
|
// Add torrent given on command line |
|
processParams(torrentCmdLine); |
|
|
|
qDebug("GUI Built"); |
|
#ifdef Q_WS_WIN |
|
if(!Preferences::neverCheckFileAssoc() && !Preferences::isFileAssocOk()) { |
|
if(QMessageBox::question(0, tr("Torrent file association"), |
|
tr("qBittorrent is not the default application to open torrent files or Magnet links.\nDo you want to associate qBittorrent to torrent files and Magnet links?"), |
|
QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { |
|
Preferences::setFileAssoc(); |
|
} else { |
|
Preferences::setNeverCheckFileAssoc(); |
|
} |
|
} |
|
#endif |
|
#ifdef Q_WS_MAC |
|
qt_mac_set_dock_menu(getTrayIconMenu()); |
|
#endif |
|
} |
|
|
|
// Destructor |
|
GUI::~GUI() { |
|
qDebug("GUI destruction"); |
|
hide(); |
|
#ifdef Q_WS_MAC |
|
// Workaround to avoid bug http://bugreports.qt.nokia.com/browse/QTBUG-7305 |
|
setUnifiedTitleAndToolBarOnMac(false); |
|
#endif |
|
// Async deletion of Bittorrent session as early as possible |
|
// in order to speed up exit |
|
session_proxy sp = BTSession->asyncDeletion(); |
|
// Some saving |
|
properties->saveSettings(); |
|
disconnect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tab_changed(int))); |
|
// Delete other GUI objects |
|
delete status_bar; |
|
delete search_filter; |
|
delete transferList; |
|
delete guiUpdater; |
|
if(createTorrentDlg) |
|
delete createTorrentDlg; |
|
if(console) |
|
delete console; |
|
if(aboutDlg) |
|
delete aboutDlg; |
|
if(options) |
|
delete options; |
|
if(downloadFromURLDialog) |
|
delete downloadFromURLDialog; |
|
if(rssWidget) |
|
delete rssWidget; |
|
if(searchEngine) |
|
delete searchEngine; |
|
delete transferListFilters; |
|
delete properties; |
|
delete hSplitter; |
|
delete vSplitter; |
|
if(systrayCreator) { |
|
delete systrayCreator; |
|
} |
|
if(systrayIcon) { |
|
delete systrayIcon; |
|
} |
|
if(myTrayIconMenu) { |
|
delete myTrayIconMenu; |
|
} |
|
delete tabs; |
|
// Keyboard shortcuts |
|
delete switchSearchShortcut; |
|
delete switchSearchShortcut2; |
|
delete switchTransferShortcut; |
|
delete switchRSSShortcut; |
|
// Delete BTSession objects |
|
qDebug("Deleting BTSession"); |
|
delete BTSession; |
|
// May freeze for a few seconds after the next line |
|
// because the Bittorrent session proxy will |
|
// actually be deleted now and destruction |
|
// becomes synchronous |
|
qDebug("Exiting GUI destructor..."); |
|
} |
|
|
|
void GUI::defineUILockPassword() { |
|
QString old_pass_md5 = Preferences::getUILockPasswordMD5(); |
|
if(old_pass_md5.isNull()) old_pass_md5 = ""; |
|
bool ok = false; |
|
QString new_clear_password = QInputDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, old_pass_md5, &ok); |
|
if(ok) { |
|
if(new_clear_password != old_pass_md5) { |
|
Preferences::setUILockPassword(new_clear_password); |
|
} |
|
QMessageBox::information(this, tr("Password update"), tr("The UI lock password has been successfully updated")); |
|
} |
|
} |
|
|
|
void GUI::on_actionLock_qBittorrent_triggered() { |
|
// Check if there is a password |
|
if(Preferences::getUILockPasswordMD5().isEmpty()) { |
|
// Ask for a password |
|
bool ok = false; |
|
QString clear_password = QInputDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok); |
|
if(!ok) return; |
|
Preferences::setUILockPassword(clear_password); |
|
} |
|
// Lock the interface |
|
ui_locked = true; |
|
Preferences::setUILocked(true); |
|
hide(); |
|
} |
|
|
|
void GUI::displayRSSTab(bool enable) { |
|
if(enable) { |
|
// RSS tab |
|
if(!rssWidget) { |
|
rssWidget = new RSSImp(BTSession); |
|
int index_tab = tabs->addTab(rssWidget, tr("RSS")); |
|
tabs->setTabIcon(index_tab, QIcon(QString::fromUtf8(":/Icons/rss32.png"))); |
|
} |
|
tabs->showTabBar(true); |
|
} else { |
|
if(rssWidget) { |
|
delete rssWidget; |
|
} |
|
if(!searchEngine) |
|
tabs->showTabBar(false); |
|
} |
|
} |
|
|
|
void GUI::displaySearchTab(bool enable) { |
|
if(enable) { |
|
// RSS tab |
|
if(!searchEngine) { |
|
searchEngine = new SearchEngine(this, BTSession); |
|
tabs->insertTab(1, searchEngine, QIcon(QString::fromUtf8(":/Icons/oxygen/edit-find.png")), tr("Search")); |
|
} |
|
tabs->showTabBar(true); |
|
} else { |
|
if(searchEngine) { |
|
delete searchEngine; |
|
} |
|
if(!rssWidget) |
|
tabs->showTabBar(false); |
|
} |
|
} |
|
|
|
void GUI::updateNbTorrents(unsigned int nb_downloading, unsigned int nb_seeding, unsigned int nb_active, unsigned int nb_inactive, unsigned int nb_paused) { |
|
Q_UNUSED(nb_downloading); |
|
Q_UNUSED(nb_seeding); |
|
Q_UNUSED(nb_paused); |
|
tabs->setTabText(0, tr("Transfers (%1)").arg(QString::number(nb_inactive+nb_active))); |
|
} |
|
|
|
void GUI::on_actionWebsite_triggered() const { |
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8("http://www.qbittorrent.org"))); |
|
} |
|
|
|
void GUI::on_actionDocumentation_triggered() const { |
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8("http://doc.qbittorrent.org"))); |
|
} |
|
|
|
void GUI::on_actionBugReport_triggered() const { |
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8("http://bugs.qbittorrent.org"))); |
|
} |
|
|
|
void GUI::tab_changed(int new_tab) { |
|
Q_UNUSED(new_tab); |
|
// We cannot rely on the index new_tab |
|
// because the tab order is undetermined now |
|
if(tabs->currentWidget() == vSplitter) { |
|
qDebug("Changed tab to transfer list, refreshing the list"); |
|
transferList->refreshList(); |
|
properties->loadDynamicData(); |
|
return; |
|
} |
|
if(tabs->currentWidget() == searchEngine) { |
|
qDebug("Changed tab to search engine, giving focus to search input"); |
|
searchEngine->giveFocusToSearchInput(); |
|
} |
|
} |
|
|
|
void GUI::writeSettings() { |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
settings.beginGroup(QString::fromUtf8("MainWindow")); |
|
settings.setValue("geometry", saveGeometry()); |
|
// Splitter size |
|
QStringList sizes_str; |
|
sizes_str << QString::number(vSplitter->sizes().first()); |
|
sizes_str << QString::number(vSplitter->sizes().last()); |
|
settings.setValue(QString::fromUtf8("vSplitterSizes"), sizes_str); |
|
settings.endGroup(); |
|
} |
|
|
|
// called when a torrent has finished |
|
void GUI::finishedTorrent(QTorrentHandle& h) const { |
|
if(!TorrentPersistentData::isSeed(h.hash())) |
|
showNotificationBaloon(tr("Download completion"), tr("%1 has finished downloading.", "e.g: xxx.avi has finished downloading.").arg(h.name())); |
|
} |
|
|
|
// Notification when disk is full |
|
void GUI::fullDiskError(QTorrentHandle& h, QString msg) const { |
|
if(!h.is_valid()) return; |
|
showNotificationBaloon(tr("I/O Error", "i.e: Input/Output Error"), tr("An I/O error occured for torrent %1.\n Reason: %2", "e.g: An error occured for torrent xxx.avi.\n Reason: disk is full.").arg(h.name()).arg(msg)); |
|
} |
|
|
|
void GUI::createKeyboardShortcuts() { |
|
actionCreate_torrent->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+N"))); |
|
actionOpen->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+O"))); |
|
actionExit->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+Q"))); |
|
switchTransferShortcut = new QShortcut(QKeySequence(tr("Alt+1", "shortcut to switch to first tab")), this); |
|
connect(switchTransferShortcut, SIGNAL(activated()), this, SLOT(displayTransferTab())); |
|
switchSearchShortcut = new QShortcut(QKeySequence(tr("Alt+2", "shortcut to switch to third tab")), this); |
|
connect(switchSearchShortcut, SIGNAL(activated()), this, SLOT(displaySearchTab())); |
|
switchSearchShortcut2 = new QShortcut(QKeySequence(tr("Ctrl+F", "shortcut to switch to search tab")), this); |
|
connect(switchSearchShortcut2, SIGNAL(activated()), this, SLOT(displaySearchTab())); |
|
switchRSSShortcut = new QShortcut(QKeySequence(tr("Alt+3", "shortcut to switch to fourth tab")), this); |
|
connect(switchRSSShortcut, SIGNAL(activated()), this, SLOT(displayRSSTab())); |
|
actionDocumentation->setShortcut(QKeySequence("F1")); |
|
actionOptions->setShortcut(QKeySequence(QString::fromUtf8("Alt+O"))); |
|
actionDelete->setShortcut(QKeySequence(QString::fromUtf8("Del"))); |
|
actionStart->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+S"))); |
|
actionStart_All->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+Shift+S"))); |
|
actionPause->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+P"))); |
|
actionPause_All->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+Shift+P"))); |
|
actionDecreasePriority->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+-"))); |
|
actionIncreasePriority->setShortcut(QKeySequence(QString::fromUtf8("Ctrl++"))); |
|
} |
|
|
|
// Keyboard shortcuts slots |
|
void GUI::displayTransferTab() const { |
|
tabs->setCurrentWidget(transferList); |
|
} |
|
|
|
void GUI::displaySearchTab() const { |
|
if(searchEngine) |
|
tabs->setCurrentWidget(searchEngine); |
|
} |
|
|
|
void GUI::displayRSSTab() const { |
|
if(rssWidget) |
|
tabs->setCurrentWidget(rssWidget); |
|
} |
|
|
|
// End of keyboard shortcuts slots |
|
|
|
void GUI::readSettings() { |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
settings.beginGroup(QString::fromUtf8("MainWindow")); |
|
restoreGeometry(settings.value("geometry").toByteArray()); |
|
const QStringList sizes_str = settings.value("vSplitterSizes", QStringList()).toStringList(); |
|
// Splitter size |
|
QList<int> sizes; |
|
if(sizes_str.size() == 2) { |
|
sizes << sizes_str.first().toInt(); |
|
sizes << sizes_str.last().toInt(); |
|
} else { |
|
qDebug("Default splitter size"); |
|
sizes << 120; |
|
sizes << vSplitter->width()-120; |
|
} |
|
vSplitter->setSizes(sizes); |
|
settings.endGroup(); |
|
} |
|
|
|
void GUI::balloonClicked() { |
|
if(isHidden()) { |
|
show(); |
|
if(isMinimized()) { |
|
showNormal(); |
|
} |
|
raise(); |
|
activateWindow(); |
|
} |
|
} |
|
|
|
void GUI::askRecursiveTorrentDownloadConfirmation(QTorrentHandle &h) { |
|
if(Preferences::recursiveDownloadDisabled()) return; |
|
QMessageBox confirmBox(QMessageBox::Question, tr("Recursive download confirmation"), tr("The torrent %1 contains torrent files, do you want to proceed with their download?").arg(h.name())); |
|
QPushButton *yes = confirmBox.addButton(tr("Yes"), QMessageBox::YesRole); |
|
/*QPushButton *no = */confirmBox.addButton(tr("No"), QMessageBox::NoRole); |
|
QPushButton *never = confirmBox.addButton(tr("Never"), QMessageBox::NoRole); |
|
confirmBox.exec(); |
|
if(confirmBox.clickedButton() == 0) return; |
|
if(confirmBox.clickedButton() == yes) { |
|
BTSession->recursiveTorrentDownload(h); |
|
return; |
|
} |
|
if(confirmBox.clickedButton() == never) { |
|
Preferences::disableRecursiveDownload(); |
|
} |
|
} |
|
|
|
void GUI::handleDownloadFromUrlFailure(QString url, QString reason) const{ |
|
// Display a message box |
|
QMessageBox::critical(0, tr("Url download error"), tr("Couldn't download file at url: %1, reason: %2.").arg(url).arg(reason)); |
|
} |
|
|
|
void GUI::on_actionSet_global_upload_limit_triggered() { |
|
qDebug("actionSet_global_upload_limit_triggered"); |
|
bool ok; |
|
const long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Global Upload Speed Limit"), BTSession->getSession()->upload_rate_limit()); |
|
if(ok) { |
|
qDebug("Setting global upload rate limit to %.1fKb/s", new_limit/1024.); |
|
BTSession->getSession()->set_upload_rate_limit(new_limit); |
|
if(new_limit <= 0) |
|
Preferences::setGlobalUploadLimit(-1); |
|
else |
|
Preferences::setGlobalUploadLimit(new_limit/1024.); |
|
} |
|
} |
|
|
|
void GUI::on_actionShow_console_triggered() { |
|
if(!console) { |
|
console = new consoleDlg(this, BTSession); |
|
} else { |
|
console->setFocus(); |
|
} |
|
} |
|
|
|
void GUI::on_actionSet_global_download_limit_triggered() { |
|
qDebug("actionSet_global_download_limit_triggered"); |
|
bool ok; |
|
const long new_limit = SpeedLimitDialog::askSpeedLimit(&ok, tr("Global Download Speed Limit"), BTSession->getSession()->download_rate_limit()); |
|
if(ok) { |
|
qDebug("Setting global download rate limit to %.1fKb/s", new_limit/1024.); |
|
BTSession->getSession()->set_download_rate_limit(new_limit); |
|
if(new_limit <= 0) |
|
Preferences::setGlobalDownloadLimit(-1); |
|
else |
|
Preferences::setGlobalDownloadLimit(new_limit/1024.); |
|
} |
|
} |
|
|
|
// Necessary if we want to close the window |
|
// in one time if "close to systray" is enabled |
|
void GUI::on_actionExit_triggered() { |
|
force_exit = true; |
|
close(); |
|
} |
|
|
|
QWidget* GUI::getCurrentTabWidget() const { |
|
if(isMinimized() || !isVisible()) |
|
return 0; |
|
if(tabs->currentIndex() == 0) |
|
return transferList; |
|
return tabs->currentWidget(); |
|
} |
|
|
|
void GUI::setTabText(int index, QString text) const { |
|
tabs->setTabText(index, text); |
|
} |
|
|
|
bool GUI::unlockUI() { |
|
bool ok = false; |
|
QString clear_password = QInputDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok); |
|
if(!ok) return false; |
|
QString real_pass_md5 = Preferences::getUILockPasswordMD5(); |
|
QCryptographicHash md5(QCryptographicHash::Md5); |
|
md5.addData(clear_password.toLocal8Bit()); |
|
QString password_md5 = md5.result().toHex(); |
|
if(real_pass_md5 == password_md5) { |
|
ui_locked = false; |
|
Preferences::setUILocked(false); |
|
return true; |
|
} |
|
QMessageBox::warning(this, tr("Invalid password"), tr("The password is invalid")); |
|
return false; |
|
} |
|
|
|
// Toggle Main window visibility |
|
void GUI::toggleVisibility(QSystemTrayIcon::ActivationReason e) { |
|
if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { |
|
if(isHidden()) { |
|
if(ui_locked) { |
|
// Ask for UI lock password |
|
if(!unlockUI()) |
|
return; |
|
} |
|
show(); |
|
if(isMinimized()) { |
|
if(isMaximized()) { |
|
showMaximized(); |
|
}else{ |
|
showNormal(); |
|
} |
|
} |
|
raise(); |
|
activateWindow(); |
|
}else{ |
|
hide(); |
|
} |
|
} |
|
} |
|
|
|
// Display About Dialog |
|
void GUI::on_actionAbout_triggered() { |
|
//About dialog |
|
if(aboutDlg) { |
|
aboutDlg->setFocus(); |
|
} else { |
|
aboutDlg = new about(this); |
|
} |
|
} |
|
|
|
void GUI::showEvent(QShowEvent *e) { |
|
qDebug("** Show Event **"); |
|
if(getCurrentTabWidget() == transferList) { |
|
qDebug("-> Refreshing transfer list"); |
|
transferList->refreshList(); |
|
properties->loadDynamicData(); |
|
} |
|
e->accept(); |
|
} |
|
|
|
// Called when we close the program |
|
void GUI::closeEvent(QCloseEvent *e) { |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
const bool goToSystrayOnExit = settings.value(QString::fromUtf8("Preferences/General/CloseToTray"), false).toBool(); |
|
if(!force_exit && systrayIcon && goToSystrayOnExit && !this->isHidden()) { |
|
hide(); |
|
e->accept(); |
|
return; |
|
} |
|
if(settings.value(QString::fromUtf8("Preferences/General/ExitConfirm"), true).toBool() && BTSession->hasActiveTorrents()) { |
|
if(e->spontaneous() || force_exit) { |
|
if(!isVisible()) |
|
show(); |
|
QMessageBox confirmBox(QMessageBox::Question, tr("Exiting qBittorrent"), |
|
tr("Some files are currently transferring.\nAre you sure you want to quit qBittorrent?"), |
|
QMessageBox::NoButton, this); |
|
QPushButton *noBtn = confirmBox.addButton(tr("No"), QMessageBox::NoRole); |
|
QPushButton *yesBtn = confirmBox.addButton(tr("Yes"), QMessageBox::YesRole); |
|
QPushButton *alwaysBtn = confirmBox.addButton(tr("Always"), QMessageBox::YesRole); |
|
confirmBox.setDefaultButton(yesBtn); |
|
confirmBox.exec(); |
|
if(!confirmBox.clickedButton() || confirmBox.clickedButton() == noBtn) { |
|
// Cancel exit |
|
e->ignore(); |
|
force_exit = false; |
|
return; |
|
} |
|
if(confirmBox.clickedButton() == alwaysBtn) { |
|
// Remember choice |
|
Preferences::setConfirmOnExit(false); |
|
} |
|
} |
|
} |
|
hide(); |
|
if(systrayIcon) { |
|
// Hide tray icon |
|
systrayIcon->hide(); |
|
} |
|
// Save window size, columns size |
|
writeSettings(); |
|
// Accept exit |
|
e->accept(); |
|
qApp->exit(); |
|
} |
|
|
|
// Display window to create a torrent |
|
void GUI::on_actionCreate_torrent_triggered() { |
|
if(createTorrentDlg) { |
|
createTorrentDlg->setFocus(); |
|
} else { |
|
createTorrentDlg = new createtorrent(this); |
|
connect(createTorrentDlg, SIGNAL(torrent_to_seed(QString)), this, SLOT(addTorrent(QString))); |
|
} |
|
} |
|
|
|
bool GUI::event(QEvent * e) { |
|
switch(e->type()) { |
|
case QEvent::WindowStateChange: { |
|
qDebug("Window change event"); |
|
//Now check to see if the window is minimised |
|
if(isMinimized()) { |
|
qDebug("minimisation"); |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
if(systrayIcon && settings.value(QString::fromUtf8("Preferences/General/MinimizeToTray"), false).toBool()) { |
|
qDebug("Has active window: %d", (int)(qApp->activeWindow() != 0)); |
|
// Check if there is a modal window |
|
bool has_modal_window = false; |
|
foreach (QWidget *widget, QApplication::allWidgets()) { |
|
if(widget->isModal()) { |
|
has_modal_window = true; |
|
break; |
|
} |
|
} |
|
// Iconify if there is no modal window |
|
if(!has_modal_window) { |
|
qDebug("Minimize to Tray enabled, hiding!"); |
|
e->accept(); |
|
QTimer::singleShot(0, this, SLOT(hide())); |
|
return true; |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
#ifdef Q_WS_MAC |
|
case QEvent::ToolBarChange: { |
|
qDebug("MAC: Received a toolbar change event!"); |
|
bool ret = QMainWindow::event(e); |
|
|
|
qDebug("MAC: new toolbar visibility is %d", !actionTop_tool_bar->isChecked()); |
|
actionTop_tool_bar->toggle(); |
|
Preferences::setToolbarDisplayed(actionTop_tool_bar->isChecked()); |
|
return ret; |
|
} |
|
#endif |
|
default: |
|
break; |
|
} |
|
return QMainWindow::event(e); |
|
} |
|
|
|
// Action executed when a file is dropped |
|
void GUI::dropEvent(QDropEvent *event) { |
|
event->acceptProposedAction(); |
|
QStringList files; |
|
if(event->mimeData()->hasUrls()) { |
|
const QList<QUrl> urls = event->mimeData()->urls(); |
|
foreach(const QUrl &url, urls) { |
|
const QString tmp = url.toString().trimmed(); |
|
if(!tmp.isEmpty()) |
|
files << url.toString(); |
|
} |
|
} else { |
|
files = event->mimeData()->text().split(QString::fromUtf8("\n")); |
|
} |
|
// Add file to download list |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); |
|
foreach(QString file, files) { |
|
#ifdef Q_WS_WIN |
|
file = file.trimmed().replace(QString::fromUtf8("file:///"), QString::fromUtf8(""), Qt::CaseInsensitive); |
|
#else |
|
file = file.trimmed().replace(QString::fromUtf8("file://"), QString::fromUtf8(""), Qt::CaseInsensitive); |
|
#endif |
|
qDebug("Dropped file %s on download list", file.toLocal8Bit().data()); |
|
if(file.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || file.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) { |
|
BTSession->downloadFromUrl(file); |
|
continue; |
|
} |
|
if(file.startsWith("bc://bt/", Qt::CaseInsensitive)) { |
|
qDebug("Converting bc link to magnet link"); |
|
file = misc::bcLinkToMagnet(file); |
|
} |
|
if(file.startsWith("magnet:", Qt::CaseInsensitive)) { |
|
// FIXME: Possibly skipped torrent addition dialog |
|
BTSession->addMagnetUri(file); |
|
continue; |
|
} |
|
if(useTorrentAdditionDialog) { |
|
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession); |
|
dialog->showLoad(file); |
|
}else{ |
|
BTSession->addTorrent(file); |
|
} |
|
} |
|
} |
|
|
|
// Decode if we accept drag 'n drop or not |
|
void GUI::dragEnterEvent(QDragEnterEvent *event) { |
|
foreach(const QString &mime, event->mimeData()->formats()){ |
|
qDebug("mimeData: %s", mime.toLocal8Bit().data()); |
|
} |
|
if (event->mimeData()->hasFormat(QString::fromUtf8("text/plain")) || event->mimeData()->hasFormat(QString::fromUtf8("text/uri-list"))) { |
|
event->acceptProposedAction(); |
|
} |
|
} |
|
|
|
/***************************************************** |
|
* * |
|
* Torrent * |
|
* * |
|
*****************************************************/ |
|
|
|
// Display a dialog to allow user to add |
|
// torrents to download list |
|
void GUI::on_actionOpen_triggered() { |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
// Open File Open Dialog |
|
// Note: it is possible to select more than one file |
|
const QStringList pathsList = QFileDialog::getOpenFileNames(0, |
|
tr("Open Torrent Files"), settings.value(QString::fromUtf8("MainWindowLastDir"), QDir::homePath()).toString(), |
|
tr("Torrent Files")+QString::fromUtf8(" (*.torrent)")); |
|
if(!pathsList.empty()) { |
|
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); |
|
const uint listSize = pathsList.size(); |
|
for(uint i=0; i<listSize; ++i) { |
|
if(useTorrentAdditionDialog) { |
|
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession); |
|
dialog->showLoad(pathsList.at(i)); |
|
}else{ |
|
BTSession->addTorrent(pathsList.at(i)); |
|
} |
|
} |
|
// Save last dir to remember it |
|
QStringList top_dir = pathsList.at(0).split(QDir::separator()); |
|
top_dir.removeLast(); |
|
settings.setValue(QString::fromUtf8("MainWindowLastDir"), top_dir.join(QDir::separator())); |
|
} |
|
} |
|
|
|
// As program parameters, we can get paths or urls. |
|
// This function parse the parameters and call |
|
// the right addTorrent function, considering |
|
// the parameter type. |
|
void GUI::processParams(const QString& params_str) { |
|
processParams(params_str.split("|", QString::SkipEmptyParts)); |
|
} |
|
|
|
void GUI::processParams(const QStringList& params) { |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); |
|
foreach(QString param, params) { |
|
param = param.trimmed(); |
|
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) { |
|
BTSession->downloadFromUrl(param); |
|
}else{ |
|
if(param.startsWith("bc://bt/", Qt::CaseInsensitive)) { |
|
qDebug("Converting bc link to magnet link"); |
|
param = misc::bcLinkToMagnet(param); |
|
} |
|
if(param.startsWith("magnet:", Qt::CaseInsensitive)) { |
|
if(useTorrentAdditionDialog) { |
|
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession); |
|
dialog->showLoadMagnetURI(param); |
|
} else { |
|
BTSession->addMagnetUri(param); |
|
} |
|
} else { |
|
if(useTorrentAdditionDialog) { |
|
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession); |
|
dialog->showLoad(param); |
|
}else{ |
|
BTSession->addTorrent(param); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void GUI::addTorrent(QString path) { |
|
BTSession->addTorrent(path); |
|
} |
|
|
|
void GUI::processDownloadedFiles(QString path, QString url) { |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); |
|
if(useTorrentAdditionDialog) { |
|
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession); |
|
dialog->showLoad(path, url); |
|
}else{ |
|
BTSession->addTorrent(path, false, url); |
|
} |
|
} |
|
|
|
void GUI::optionsSaved() { |
|
loadPreferences(); |
|
} |
|
|
|
// Load program preferences |
|
void GUI::loadPreferences(bool configure_session) { |
|
BTSession->addConsoleMessage(tr("Options were saved successfully.")); |
|
#ifndef Q_WS_MAC |
|
const bool newSystrayIntegration = Preferences::systrayIntegration(); |
|
actionLock_qBittorrent->setEnabled(newSystrayIntegration); |
|
if(newSystrayIntegration != (systrayIcon!=0)) { |
|
if(newSystrayIntegration) { |
|
// create the trayicon |
|
if(!QSystemTrayIcon::isSystemTrayAvailable()) { |
|
if(!configure_session) { // Program startup |
|
systrayCreator = new QTimer(this); |
|
connect(systrayCreator, SIGNAL(timeout()), this, SLOT(createSystrayDelayed())); |
|
systrayCreator->setSingleShot(true); |
|
systrayCreator->start(2000); |
|
qDebug("Info: System tray is unavailable, trying again later."); |
|
} else { |
|
qDebug("Warning: System tray is unavailable."); |
|
} |
|
} else { |
|
createTrayIcon(); |
|
} |
|
} else { |
|
// Destroy trayicon |
|
delete systrayIcon; |
|
delete myTrayIconMenu; |
|
} |
|
} |
|
#endif |
|
// General |
|
if(Preferences::isToolbarDisplayed()) { |
|
toolBar->setVisible(true); |
|
toolBar->layout()->setSpacing(7); |
|
} else { |
|
// Clear search filter before hiding the top toolbar |
|
search_filter->clear(); |
|
toolBar->setVisible(false); |
|
} |
|
const uint new_refreshInterval = Preferences::getRefreshInterval(); |
|
transferList->setRefreshInterval(new_refreshInterval); |
|
transferList->setAlternatingRowColors(Preferences::useAlternatingRowColors()); |
|
properties->getFilesList()->setAlternatingRowColors(Preferences::useAlternatingRowColors()); |
|
properties->getTrackerList()->setAlternatingRowColors(Preferences::useAlternatingRowColors()); |
|
properties->getPeerList()->setAlternatingRowColors(Preferences::useAlternatingRowColors()); |
|
// Queueing System |
|
if(Preferences::isQueueingSystemEnabled()) { |
|
if(!configure_session || !BTSession->isQueueingEnabled()) { |
|
transferList->hidePriorityColumn(false); |
|
actionDecreasePriority->setVisible(true); |
|
actionIncreasePriority->setVisible(true); |
|
prioSeparator->setVisible(true); |
|
prioSeparator2->setVisible(true); |
|
toolBar->layout()->setSpacing(7); |
|
} |
|
} else { |
|
if(BTSession->isQueueingEnabled()) { |
|
transferList->hidePriorityColumn(true); |
|
actionDecreasePriority->setVisible(false); |
|
actionIncreasePriority->setVisible(false); |
|
prioSeparator->setVisible(false); |
|
prioSeparator2->setVisible(false); |
|
toolBar->layout()->setSpacing(7); |
|
} |
|
} |
|
|
|
// Torrent properties |
|
properties->reloadPreferences(); |
|
|
|
if(configure_session) |
|
BTSession->configureSession(); |
|
|
|
qDebug("GUI settings loaded"); |
|
} |
|
|
|
void GUI::addUnauthenticatedTracker(const QPair<QTorrentHandle,QString> &tracker) { |
|
// Trackers whose authentication was cancelled |
|
if(unauthenticated_trackers.indexOf(tracker) < 0) { |
|
unauthenticated_trackers << tracker; |
|
} |
|
} |
|
|
|
// Called when a tracker requires authentication |
|
void GUI::trackerAuthenticationRequired(QTorrentHandle& h) { |
|
if(unauthenticated_trackers.indexOf(QPair<QTorrentHandle,QString>(h, h.current_tracker())) < 0) { |
|
// Tracker login |
|
new trackerLogin(this, h); |
|
} |
|
} |
|
|
|
// Check connection status and display right icon |
|
void GUI::updateGUI() { |
|
// update global informations |
|
#ifndef Q_WS_MAC |
|
if(systrayIcon) { |
|
#if defined(Q_WS_X11) |
|
QString html = "<div style='background-color: #678db2; color: #fff;height: 18px; font-weight: bold; margin-bottom: 5px;'>"; |
|
html += tr("qBittorrent"); |
|
html += "</div>"; |
|
html += "<div style='vertical-align: baseline; height: 18px;'>"; |
|
html += "<img src=':/Icons/skin/download.png'/> "+tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString::number(BTSession->getPayloadDownloadRate()/1024., 'f', 1)); |
|
html += "</div>"; |
|
html += "<div style='vertical-align: baseline; height: 18px;'>"; |
|
html += "<img src=':/Icons/skin/seeding.png'/> "+tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString::number(BTSession->getPayloadUploadRate()/1024., 'f', 1)); |
|
html += "</div>"; |
|
#else |
|
// OSes such as Windows do not support html here |
|
QString html =tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString::number(BTSession->getPayloadDownloadRate()/1024., 'f', 1)); |
|
html += "\n"; |
|
html += tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString::number(BTSession->getPayloadUploadRate()/1024., 'f', 1)); |
|
#endif |
|
systrayIcon->setToolTip(html); // tray icon |
|
} |
|
#endif |
|
if(displaySpeedInTitle) { |
|
setWindowTitle(tr("qBittorrent %1 (Down: %2/s, Up: %3/s)", "%1 is qBittorrent version").arg(QString::fromUtf8(VERSION)).arg(misc::friendlyUnit(BTSession->getSessionStatus().payload_download_rate)).arg(misc::friendlyUnit(BTSession->getSessionStatus().payload_upload_rate))); |
|
} |
|
} |
|
|
|
void GUI::showNotificationBaloon(QString title, QString msg) const { |
|
if(!Preferences::useProgramNotification()) return; |
|
#ifdef WITH_LIBNOTIFY |
|
if (notify_init ("summary-body")) { |
|
NotifyNotification* notification; |
|
notification = notify_notification_new (qPrintable(title), qPrintable(msg), "qbittorrent", 0); |
|
gboolean success = notify_notification_show (notification, NULL); |
|
g_object_unref(G_OBJECT(notification)); |
|
notify_uninit (); |
|
if(success) { |
|
return; |
|
} |
|
} |
|
#endif |
|
#ifndef Q_WS_MAC |
|
if(systrayIcon && QSystemTrayIcon::supportsMessages()) |
|
systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON); |
|
#endif |
|
} |
|
|
|
/***************************************************** |
|
* * |
|
* Utils * |
|
* * |
|
*****************************************************/ |
|
|
|
void GUI::downloadFromURLList(const QStringList& url_list) { |
|
QIniSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); |
|
const bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); |
|
foreach(QString url, url_list) { |
|
if(url.startsWith("bc://bt/", Qt::CaseInsensitive)) { |
|
qDebug("Converting bc link to magnet link"); |
|
url = misc::bcLinkToMagnet(url); |
|
} |
|
if(url.startsWith("magnet:", Qt::CaseInsensitive)) { |
|
if(useTorrentAdditionDialog) { |
|
torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession); |
|
dialog->showLoadMagnetURI(url); |
|
} else { |
|
BTSession->addMagnetUri(url); |
|
} |
|
} else { |
|
BTSession->downloadFromUrl(url); |
|
} |
|
} |
|
} |
|
|
|
/***************************************************** |
|
* * |
|
* Options * |
|
* * |
|
*****************************************************/ |
|
|
|
void GUI::createSystrayDelayed() { |
|
#ifndef Q_WS_MAC |
|
static int timeout = 20; |
|
if(QSystemTrayIcon::isSystemTrayAvailable()) { |
|
// Ok, systray integration is now supported |
|
// Create systray icon |
|
createTrayIcon(); |
|
delete systrayCreator; |
|
} else { |
|
if(timeout) { |
|
// Retry a bit later |
|
systrayCreator->start(2000); |
|
--timeout; |
|
} else { |
|
// Timed out, apparently system really does not |
|
// support systray icon |
|
delete systrayCreator; |
|
// Disable it in program preferences to |
|
// avoid trying at earch startup |
|
Preferences::setSystrayIntegration(false); |
|
} |
|
} |
|
#endif |
|
} |
|
|
|
void GUI::updateAltSpeedsBtn(bool alternative) { |
|
actionUse_alternative_speed_limits->setChecked(alternative); |
|
} |
|
|
|
QMenu* GUI::getTrayIconMenu() { |
|
if(myTrayIconMenu) |
|
return myTrayIconMenu; |
|
// Tray icon Menu |
|
myTrayIconMenu = new QMenu(this); |
|
myTrayIconMenu->addAction(actionOpen); |
|
myTrayIconMenu->addAction(actionDownload_from_URL); |
|
myTrayIconMenu->addSeparator(); |
|
updateAltSpeedsBtn(Preferences::isAltBandwidthEnabled()); |
|
actionUse_alternative_speed_limits->setChecked(Preferences::isAltBandwidthEnabled()); |
|
myTrayIconMenu->addAction(actionUse_alternative_speed_limits); |
|
myTrayIconMenu->addAction(actionSet_global_download_limit); |
|
myTrayIconMenu->addAction(actionSet_global_upload_limit); |
|
myTrayIconMenu->addSeparator(); |
|
myTrayIconMenu->addAction(actionStart_All); |
|
myTrayIconMenu->addAction(actionPause_All); |
|
myTrayIconMenu->addSeparator(); |
|
myTrayIconMenu->addAction(actionExit); |
|
return myTrayIconMenu; |
|
} |
|
|
|
void GUI::createTrayIcon() { |
|
// Tray icon |
|
#ifdef Q_WS_WIN |
|
systrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent16.png")), this); |
|
#else |
|
systrayIcon = new QSystemTrayIcon(QIcon(QString::fromUtf8(":/Icons/skin/qbittorrent22.png")), this); |
|
#endif |
|
|
|
systrayIcon->setContextMenu(getTrayIconMenu()); |
|
connect(systrayIcon, SIGNAL(messageClicked()), this, SLOT(balloonClicked())); |
|
// End of Icon Menu |
|
connect(systrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason))); |
|
systrayIcon->show(); |
|
} |
|
|
|
// Display Program Options |
|
void GUI::on_actionOptions_triggered() { |
|
if(options) { |
|
// Get focus |
|
options->setFocus(); |
|
} else { |
|
options = new options_imp(this); |
|
connect(options, SIGNAL(status_changed()), this, SLOT(optionsSaved())); |
|
} |
|
} |
|
|
|
void GUI::on_actionTop_tool_bar_triggered() { |
|
bool is_visible = static_cast<QAction*>(sender())->isChecked(); |
|
toolBar->setVisible(is_visible); |
|
Preferences::setToolbarDisplayed(is_visible); |
|
} |
|
|
|
void GUI::on_actionShutdown_when_downloads_complete_triggered() { |
|
bool is_checked = static_cast<QAction*>(sender())->isChecked(); |
|
Preferences::setShutdownWhenDownloadsComplete(is_checked); |
|
} |
|
|
|
void GUI::on_actionSpeed_in_title_bar_triggered() { |
|
displaySpeedInTitle = static_cast<QAction*>(sender())->isChecked(); |
|
Preferences::showSpeedInTitleBar(displaySpeedInTitle); |
|
if(displaySpeedInTitle) |
|
updateGUI(); |
|
else |
|
setWindowTitle(tr("qBittorrent %1", "e.g: qBittorrent v0.x").arg(QString::fromUtf8(VERSION))); |
|
} |
|
|
|
void GUI::on_actionRSS_Reader_triggered() { |
|
Preferences::setRSSEnabled(actionRSS_Reader->isChecked()); |
|
displayRSSTab(actionRSS_Reader->isChecked()); |
|
} |
|
|
|
void GUI::on_actionSearch_engine_triggered() { |
|
Preferences::setSearchEnabled(actionSearch_engine->isChecked()); |
|
displaySearchTab(actionSearch_engine->isChecked()); |
|
} |
|
|
|
/***************************************************** |
|
* * |
|
* HTTP Downloader * |
|
* * |
|
*****************************************************/ |
|
|
|
// Display an input dialog to prompt user for |
|
// an url |
|
void GUI::on_actionDownload_from_URL_triggered() { |
|
if(!downloadFromURLDialog) { |
|
downloadFromURLDialog = new downloadFromURL(this); |
|
connect(downloadFromURLDialog, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), this, SLOT(downloadFromURLList(const QStringList&))); |
|
} |
|
} |
|
|
|
|