diff --git a/Changelog b/Changelog index 9de698be0..dd3242cc3 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,7 @@ - FEATURE: Display more infos about the torrent in its properties - FEATURE: Allow the user to edit torrents' trackers - FEATURE: Allow user to change qBT's style (Plastique, Cleanlooks, Motif, CDE, MacOSX, WinXP) + - FEATURE: Allow the user to disable system tray integration - COSMETIC: Redesigned torrent properties a little - COSMETIC: Redesigned options a little - COSMETIC: Display more logs messages concerning features diff --git a/src/GUI.cpp b/src/GUI.cpp index ccbd6cc36..d0cc45301 100644 --- a/src/GUI.cpp +++ b/src/GUI.cpp @@ -156,10 +156,16 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){ connect(actionPreview_file, SIGNAL(triggered()), this, SLOT(previewFileSelection())); connect(infoBar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoBarMenu(const QPoint&))); // Create tray icon - if (!QSystemTrayIcon::isSystemTrayAvailable()){ - std::cerr << "Error: System tray unavailable\n"; + if (QSystemTrayIcon::isSystemTrayAvailable()){ + QSettings settings("qBittorrent", "qBittorrent"); + systrayIntegration = settings.value("Options/Misc/Behaviour/SystrayIntegration", true).toBool(); + if(systrayIntegration){ + createTrayIcon(); + } + }else{ + systrayIntegration = false; + qDebug("Info: System tray unavailable\n"); } - myTrayIcon = new QSystemTrayIcon(QIcon(":/Icons/qbittorrent22.png"), this); // Search engine tab searchEngine = new SearchEngine(&BTSession, myTrayIcon); tabs->addTab(searchEngine, tr("Search")); @@ -172,20 +178,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent){ refresher = new QTimer(this); connect(refresher, SIGNAL(timeout()), this, SLOT(updateDlList())); refresher->start(2000); - // Tray icon Menu - myTrayIconMenu = new QMenu(this); - myTrayIconMenu->addAction(actionOpen); - myTrayIconMenu->addAction(actionDownload_from_URL); - myTrayIconMenu->addSeparator(); - myTrayIconMenu->addAction(actionStart_All); - myTrayIconMenu->addAction(actionPause_All); - myTrayIconMenu->addSeparator(); - myTrayIconMenu->addAction(actionExit); - myTrayIcon->setContextMenu(myTrayIconMenu); - connect(myTrayIcon, SIGNAL(messageClicked()), this, SLOT(balloonClicked())); - // End of Icon Menu - connect(myTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason))); - myTrayIcon->show(); // Use a tcp server to allow only one instance of qBittorrent tcpServer = new QTcpServer(); if (!tcpServer->listen(QHostAddress::LocalHost, 1666)) { @@ -211,8 +203,10 @@ GUI::~GUI(){ delete searchEngine; delete checkConnect; delete refresher; - delete myTrayIcon; - delete myTrayIconMenu; + if(systrayIntegration){ + delete myTrayIcon; + delete myTrayIconMenu; + } delete DLDelegate; delete DLListModel; delete tcpServer; @@ -420,7 +414,9 @@ void GUI::updateDlList(bool force){ // update global informations snprintf(tmp, MAX_CHAR_TMP, "%.1f", BTSession.getPayloadUploadRate()/1024.); snprintf(tmp2, MAX_CHAR_TMP, "%.1f", BTSession.getPayloadDownloadRate()/1024.); - myTrayIcon->setToolTip(""+tr("qBittorrent")+"
"+tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString(tmp2))+"
"+tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString(tmp))); // tray icon + if(systrayIntegration){ + myTrayIcon->setToolTip(""+tr("qBittorrent")+"
"+tr("DL speed: %1 KiB/s", "e.g: Download speed: 10 KiB/s").arg(QString(tmp2))+"
"+tr("UP speed: %1 KiB/s", "e.g: Upload speed: 10 KiB/s").arg(QString(tmp))); // tray icon + } if( !force && (isMinimized() || isHidden() || tabs->currentIndex())){ // No need to update if qBittorrent DL list is hidden return; @@ -650,7 +646,7 @@ void GUI::showAbout(){ void GUI::closeEvent(QCloseEvent *e){ QSettings settings("qBittorrent", "qBittorrent"); bool goToSystrayOnExit = settings.value("Options/Misc/Behaviour/GoToSystrayOnExit", false).toBool(); - if(goToSystrayOnExit && !this->isHidden()){ + if(systrayIntegration && goToSystrayOnExit && !this->isHidden()){ hide(); e->ignore(); return; @@ -688,8 +684,10 @@ void GUI::closeEvent(QCloseEvent *e){ saveColWidthDLList(); // Create fast resume data BTSession.saveFastResumeData(); - // Hide tray icon - myTrayIcon->hide(); + if(systrayIntegration){ + // Hide tray icon + myTrayIcon->hide(); + } // Accept exit e->accept(); } @@ -702,7 +700,7 @@ void GUI::showCreateWindow(){ // Called when we minimize the program void GUI::hideEvent(QHideEvent *e){ QSettings settings("qBittorrent", "qBittorrent"); - if(settings.value("Options/Misc/Behaviour/GoToSystray", true).toBool()){ + if(systrayIntegration && settings.value("Options/Misc/Behaviour/GoToSystray", true).toBool()){ // Hide window hide(); } @@ -1021,7 +1019,7 @@ void GUI::configureSession(bool deleteOptions){ // PeX if(!options->isPeXDisabled()){ qDebug("Enabling Peer eXchange (PeX)"); - setInfoBar(tr("PeX support [OFF]"), "blue"); + setInfoBar(tr("PeX support [ON]"), "blue"); BTSession.enablePeerExchange(); }else{ setInfoBar(tr("PeX support [OFF]"), "blue"); @@ -1172,7 +1170,7 @@ void GUI::finishedTorrent(torrent_handle& h){ QString fileName = QString(h.name().c_str()); setInfoBar(tr("%1 has finished downloading.", "e.g: xxx.avi has finished downloading.").arg(fileName)); int useOSD = settings.value("Options/OSDEnabled", 1).toInt(); - if(useOSD == 1 || (useOSD == 2 && (isMinimized() || isHidden()))) { + if(systrayIntegration && (useOSD == 1 || (useOSD == 2 && (isMinimized() || isHidden())))) { myTrayIcon->showMessage(tr("Download finished"), tr("%1 has finished downloading.", "e.g: xxx.avi has finished downloading.").arg(fileName), QSystemTrayIcon::Information, TIME_TRAY_BALLOON); } } @@ -1181,7 +1179,7 @@ void GUI::finishedTorrent(torrent_handle& h){ void GUI::fullDiskError(torrent_handle& h){ QSettings settings("qBittorrent", "qBittorrent"); int useOSD = settings.value("Options/OSDEnabled", 1).toInt(); - if(useOSD == 1 || (useOSD == 2 && (isMinimized() || isHidden()))) { + if(systrayIntegration && (useOSD == 1 || (useOSD == 2 && (isMinimized() || isHidden())))){ myTrayIcon->showMessage(tr("I/O Error", "i.e: Input/Output Error"), tr("An error occured when trying to read or write %1. The disk is probably full, download has been paused", "e.g: An error occured when trying to read or write xxx.avi. The disk is probably full, download has been paused").arg(QString(h.name().c_str())), QSystemTrayIcon::Critical, TIME_TRAY_BALLOON); } // Download will be paused by libtorrent. Updating GUI information accordingly @@ -1300,6 +1298,25 @@ void GUI::displayDownloadingUrlInfos(const QString& url){ * * *****************************************************/ +void GUI::createTrayIcon(){ + // Tray icon + myTrayIcon = new QSystemTrayIcon(QIcon(":/Icons/qbittorrent22.png"), this); + // Tray icon Menu + myTrayIconMenu = new QMenu(this); + myTrayIconMenu->addAction(actionOpen); + myTrayIconMenu->addAction(actionDownload_from_URL); + myTrayIconMenu->addSeparator(); + myTrayIconMenu->addAction(actionStart_All); + myTrayIconMenu->addAction(actionPause_All); + myTrayIconMenu->addSeparator(); + myTrayIconMenu->addAction(actionExit); + myTrayIcon->setContextMenu(myTrayIconMenu); + connect(myTrayIcon, SIGNAL(messageClicked()), this, SLOT(balloonClicked())); + // End of Icon Menu + connect(myTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason))); + myTrayIcon->show(); +} + // Display Program Options void GUI::showOptions(){ options = new options_imp(this); @@ -1309,6 +1326,17 @@ void GUI::showOptions(){ // Is executed each time options are saved void GUI::OptionsSaved(const QString& info, bool deleteOptions){ + bool newSystrayIntegration = options->useSystrayIntegration(); + if(newSystrayIntegration && !systrayIntegration){ + // create the trayicon + createTrayIcon(); + } + if(!newSystrayIntegration && systrayIntegration){ + // Destroy trayicon + delete myTrayIcon; + delete myTrayIconMenu; + } + systrayIntegration = newSystrayIntegration; // Update info bar setInfoBar(info); // Update session diff --git a/src/GUI.h b/src/GUI.h index 085bb5139..5e9603a3e 100644 --- a/src/GUI.h +++ b/src/GUI.h @@ -76,6 +76,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{ DLListDelegate *DLDelegate; unsigned int nbTorrents; QLabel *connecStatusLblIcon; + bool systrayIntegration; // Preview previewSelect *previewSelection; QProcess *previewProcess; @@ -118,6 +119,7 @@ class GUI : public QMainWindow, private Ui::MainWindow{ void writeSettings(); void readSettings(); void forceExit(); + void createTrayIcon(); // Torrent actions void showProperties(const QModelIndex &index); void propertiesSelection(); diff --git a/src/options.ui b/src/options.ui index 723d3ea32..fba9c4141 100644 --- a/src/options.ui +++ b/src/options.ui @@ -870,6 +870,13 @@ + + + + Disable systray integration + + + diff --git a/src/options_imp.cpp b/src/options_imp.cpp index 6a0ae12b2..2a3a25c8d 100644 --- a/src/options_imp.cpp +++ b/src/options_imp.cpp @@ -124,6 +124,11 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){ txt_savePath->setText(home+"qBT_dir"); // Load options loadOptions(); + // Disable systray integration if it is not supported by the system + if(!QSystemTrayIcon::isSystemTrayAvailable()){ + systrayDisabled(true); + check_disableSystray->setEnabled(false); + } // Connect signals / slots connect(disableUPLimit, SIGNAL(stateChanged(int)), this, SLOT(disableUpload(int))); connect(disableDLLimit, SIGNAL(stateChanged(int)), this, SLOT(disableDownload(int))); @@ -131,6 +136,7 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){ #ifndef NO_UPNP connect(disableUPnP, SIGNAL(stateChanged(int)), this, SLOT(disableUPnPGroup(int))); #endif + connect(check_disableSystray, SIGNAL(stateChanged(int)), this, SLOT(systrayDisabled(int))); connect(disableRatio, SIGNAL(stateChanged(int)), this, SLOT(disableShareRatio(int))); connect(activateFilter, SIGNAL(stateChanged(int)), this, SLOT(enableFilter(int))); connect(enableProxy_checkBox, SIGNAL(stateChanged(int)), this, SLOT(enableProxy(int))); @@ -185,6 +191,7 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){ connect(radioCleanlooksStyle, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); connect(radioMotifStyle, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); connect(radioCDEStyle, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); + connect(check_disableSystray, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton())); #ifdef Q_WS_WIN connect(radioWinXPStyle, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton())); #endif @@ -253,7 +260,7 @@ void options_imp::saveOptions(){ #ifndef NO_UPNP settings.setValue("UPnPPort", getUPnPPort()); #endif - settings.setValue("PeXState", isPeXDisabled()); + settings.setValue("PeXState", !isPeXDisabled()); settings.setValue("ScanDir", getScanDir()); // End Main options settings.endGroup(); @@ -302,6 +309,7 @@ void options_imp::saveOptions(){ settings.setValue("ConfirmOnExit", getConfirmOnExit()); settings.setValue("GoToSystray", getGoToSysTrayOnMinimizingWindow()); settings.setValue("GoToSystrayOnExit", getGoToSysTrayOnExitingWindow()); + settings.setValue("SystrayIntegration", useSystrayIntegration()); // End Behaviour group settings.endGroup(); settings.setValue("PreviewProgram", getPreviewProgram()); @@ -442,13 +450,13 @@ void options_imp::loadOptions(){ spin_upnp_port->setValue(value); } #endif - boolValue = settings.value("PeXState", 0).toBool(); + boolValue = settings.value("PeXState", true).toBool(); if(boolValue){ // Pex disabled - disablePeX->setChecked(true); + disablePeX->setChecked(false); }else{ // PeX enabled - disablePeX->setChecked(false); + disablePeX->setChecked(true); } strValue = settings.value("ScanDir", QString()).toString(); if(!strValue.isEmpty()){ @@ -536,6 +544,9 @@ void options_imp::loadOptions(){ confirmExit_checkBox->setChecked(settings.value("ConfirmOnExit", true).toBool()); check_goToSysTray->setChecked(settings.value("GoToSystray", true).toBool()); check_closeToSysTray->setChecked(settings.value("GoToSystrayOnExit", false).toBool()); + boolValue = settings.value("SystrayIntegration", true).toBool(); + check_disableSystray->setChecked(!boolValue); + systrayDisabled(!boolValue); // End Behaviour group settings.endGroup(); preview_program->setText(settings.value("PreviewProgram", QString()).toString()); @@ -558,6 +569,22 @@ void options_imp::loadOptions(){ applyButton->setEnabled(false); } +void options_imp::systrayDisabled(int val){ + if(val){ + // No SystrayIntegration + check_closeToSysTray->setChecked(false); + check_closeToSysTray->setEnabled(false); + check_goToSysTray->setChecked(false); + check_goToSysTray->setEnabled(false); + neverOSD->setChecked(true); + groupOSD->setEnabled(false); + }else{ + check_closeToSysTray->setEnabled(true); + check_goToSysTray->setEnabled(true); + groupOSD->setEnabled(true); + } +} + // return min & max ports // [min, max] std::pair options_imp::getPorts() const{ @@ -642,6 +669,11 @@ bool options_imp::getUseOSDWhenHiddenOnly() const{ return someOSD->isChecked(); } +bool options_imp::useSystrayIntegration() const{ + if (!QSystemTrayIcon::isSystemTrayAvailable()) return false; + return (!check_disableSystray->isChecked()); +} + // Return Share ratio float options_imp::getRatio() const{ if(!disableRatio->isChecked()){ diff --git a/src/options_imp.h b/src/options_imp.h index aefebd638..1e05403ce 100644 --- a/src/options_imp.h +++ b/src/options_imp.h @@ -80,7 +80,7 @@ class options_imp : public QDialog, private Ui::Dialog{ bool getUseOSDAlways() const; bool getUseOSDWhenHiddenOnly() const; QString getStyle() const; - void setStyle(QString style); + bool useSystrayIntegration() const; protected slots: void on_okButton_clicked(); @@ -109,6 +109,8 @@ class options_imp : public QDialog, private Ui::Dialog{ void enableApplyButton(); void checkPortsLogic(); void enableSavePath(int checkBoxValue); + void setStyle(QString style); + void systrayDisabled(int val); public slots: void setLocale(QString locale);