Merge pull request #6952 from vit9696/master

Various macOS UI improvements
This commit is contained in:
sledgehammer999 2017-07-15 20:51:45 +03:00 committed by GitHub
commit c964f0c490
20 changed files with 358 additions and 90 deletions

View file

@ -17,12 +17,21 @@ if (GUI)
if (WIN32) if (WIN32)
list (APPEND QBT_QT_COMPONENTS WinExtras) list (APPEND QBT_QT_COMPONENTS WinExtras)
endif(WIN32) endif(WIN32)
if (APPLE)
list (APPEND QBT_GUI_OPTIONAL_LINK_LIBRARIES objc)
list (APPEND QBT_QT_COMPONENTS MacExtras)
endif (APPLE)
endif (GUI) endif (GUI)
if (DBUS) if (DBUS)
list (APPEND QBT_QT_COMPONENTS DBus) list (APPEND QBT_QT_COMPONENTS DBus)
endif (DBUS) endif (DBUS)
find_package(Qt5 5.5.1 COMPONENTS ${QBT_QT_COMPONENTS} REQUIRED) find_package(Qt5 5.5.1 COMPONENTS ${QBT_QT_COMPONENTS} REQUIRED)
if (GUI AND APPLE)
# Fix MOC inability to detect macOS. This seems to only affect cmake.
# Relevant issue: https://bugreports.qt.io/browse/QTBUG-58325
set(CMAKE_AUTOMOC_MOC_OPTIONS ${CMAKE_AUTOMOC_MOC_OPTIONS} -DQ_OS_MAC)
endif ()
set(CMAKE_AUTOMOC True) set(CMAKE_AUTOMOC True)
list(APPEND CMAKE_AUTORCC_OPTIONS -compress 9 -threshold 5) list(APPEND CMAKE_AUTORCC_OPTIONS -compress 9 -threshold 5)

View file

@ -208,14 +208,15 @@ int main(int argc, char *argv[])
#endif #endif
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
{ // Since Apple made difficult for users to set PATH, we set here for convenience.
// Since Apple made difficult for users to set PATH, we set here for convenience. // Users are supposed to install Homebrew Python for search function.
// Users are supposed to install Homebrew Python for search function. // For more info see issue #5571.
// For more info see issue #5571. QByteArray path = "/usr/local/bin:";
QByteArray path = "/usr/local/bin:"; path += qgetenv("PATH");
path += qgetenv("PATH"); qputenv("PATH", path.constData());
qputenv("PATH", path.constData());
} // On OS X the standard is to not show icons in the menus
app->setAttribute(Qt::AA_DontShowIconsInMenus);
#endif #endif
#ifndef DISABLE_GUI #ifndef DISABLE_GUI

View file

@ -161,6 +161,9 @@ void Preferences::setHideZeroComboValues(int n)
setValue("Preferences/General/HideZeroComboValues", n); setValue("Preferences/General/HideZeroComboValues", n);
} }
// In Mac OS X the dock is sufficient for our needs so we disable the sys tray functionality.
// See extensive discussion in https://github.com/qbittorrent/qBittorrent/pull/3018
#ifndef Q_OS_MAC
bool Preferences::systrayIntegration() const bool Preferences::systrayIntegration() const
{ {
return value("Preferences/General/SystrayEnabled", true).toBool(); return value("Preferences/General/SystrayEnabled", true).toBool();
@ -171,26 +174,6 @@ void Preferences::setSystrayIntegration(bool enabled)
setValue("Preferences/General/SystrayEnabled", enabled); setValue("Preferences/General/SystrayEnabled", enabled);
} }
bool Preferences::isToolbarDisplayed() const
{
return value("Preferences/General/ToolbarDisplayed", true).toBool();
}
void Preferences::setToolbarDisplayed(bool displayed)
{
setValue("Preferences/General/ToolbarDisplayed", displayed);
}
bool Preferences::isStatusbarDisplayed() const
{
return value("Preferences/General/StatusbarDisplayed", true).toBool();
}
void Preferences::setStatusbarDisplayed(bool displayed)
{
setValue("Preferences/General/StatusbarDisplayed", displayed);
}
bool Preferences::minimizeToTray() const bool Preferences::minimizeToTray() const
{ {
return value("Preferences/General/MinimizeToTray", false).toBool(); return value("Preferences/General/MinimizeToTray", false).toBool();
@ -210,6 +193,27 @@ void Preferences::setCloseToTray(bool b)
{ {
setValue("Preferences/General/CloseToTray", b); setValue("Preferences/General/CloseToTray", b);
} }
#endif
bool Preferences::isToolbarDisplayed() const
{
return value("Preferences/General/ToolbarDisplayed", true).toBool();
}
void Preferences::setToolbarDisplayed(bool displayed)
{
setValue("Preferences/General/ToolbarDisplayed", displayed);
}
bool Preferences::isStatusbarDisplayed() const
{
return value("Preferences/General/StatusbarDisplayed", true).toBool();
}
void Preferences::setStatusbarDisplayed(bool displayed)
{
setValue("Preferences/General/StatusbarDisplayed", displayed);
}
bool Preferences::startMinimized() const bool Preferences::startMinimized() const
{ {
@ -1084,6 +1088,7 @@ void Preferences::setConfirmRemoveAllTags(bool enabled)
setValue("Preferences/Advanced/confirmRemoveAllTags", enabled); setValue("Preferences/Advanced/confirmRemoveAllTags", enabled);
} }
#ifndef Q_OS_MAC
TrayIcon::Style Preferences::trayIconStyle() const TrayIcon::Style Preferences::trayIconStyle() const
{ {
return TrayIcon::Style(value("Preferences/Advanced/TrayIconStyle", TrayIcon::NORMAL).toInt()); return TrayIcon::Style(value("Preferences/Advanced/TrayIconStyle", TrayIcon::NORMAL).toInt());
@ -1093,6 +1098,7 @@ void Preferences::setTrayIconStyle(TrayIcon::Style style)
{ {
setValue("Preferences/Advanced/TrayIconStyle", style); setValue("Preferences/Advanced/TrayIconStyle", style);
} }
#endif
// Stuff that don't appear in the Options GUI but are saved // Stuff that don't appear in the Options GUI but are saved
// in the same file. // in the same file.

View file

@ -115,16 +115,10 @@ public:
void setHideZeroValues(bool b); void setHideZeroValues(bool b);
int getHideZeroComboValues() const; int getHideZeroComboValues() const;
void setHideZeroComboValues(int n); void setHideZeroComboValues(int n);
bool systrayIntegration() const;
void setSystrayIntegration(bool enabled);
bool isToolbarDisplayed() const;
void setToolbarDisplayed(bool displayed);
bool isStatusbarDisplayed() const; bool isStatusbarDisplayed() const;
void setStatusbarDisplayed(bool displayed); void setStatusbarDisplayed(bool displayed);
bool minimizeToTray() const; bool isToolbarDisplayed() const;
void setMinimizeToTray(bool b); void setToolbarDisplayed(bool displayed);
bool closeToTray() const;
void setCloseToTray(bool b);
bool startMinimized() const; bool startMinimized() const;
void setStartMinimized(bool b); void setStartMinimized(bool b);
bool isSplashScreenDisabled() const; bool isSplashScreenDisabled() const;
@ -264,8 +258,16 @@ public:
void setConfirmTorrentRecheck(bool enabled); void setConfirmTorrentRecheck(bool enabled);
bool confirmRemoveAllTags() const; bool confirmRemoveAllTags() const;
void setConfirmRemoveAllTags(bool enabled); void setConfirmRemoveAllTags(bool enabled);
#ifndef Q_OS_MAC
bool systrayIntegration() const;
void setSystrayIntegration(bool enabled);
bool minimizeToTray() const;
void setMinimizeToTray(bool b);
bool closeToTray() const;
void setCloseToTray(bool b);
TrayIcon::Style trayIconStyle() const; TrayIcon::Style trayIconStyle() const;
void setTrayIconStyle(TrayIcon::Style style); void setTrayIconStyle(TrayIcon::Style style);
#endif
// Stuff that don't appear in the Options GUI but are saved // Stuff that don't appear in the Options GUI but are saved
// in the same file. // in the same file.

View file

@ -153,3 +153,7 @@ target_link_libraries(qbt_gui qbt_lineedit qbt_powermanagement qbt_rss qbt_prope
if(WIN32) if(WIN32)
target_link_libraries(qbt_gui Qt5::WinExtras) target_link_libraries(qbt_gui Qt5::WinExtras)
endif(WIN32) endif(WIN32)
if (APPLE)
target_link_libraries(qbt_gui Qt5::MacExtras)
endif()

View file

@ -214,7 +214,11 @@ void AddNewTorrentDialog::show(QString source, const BitTorrent::AddTorrentParam
ok = dlg->loadTorrent(source); ok = dlg->loadTorrent(source);
if (ok) if (ok)
#ifdef Q_OS_MAC
dlg->exec();
#else
dlg->open(); dlg->open();
#endif
else else
delete dlg; delete dlg;
} }

View file

@ -71,8 +71,11 @@ CategoryFilterWidget::CategoryFilterWidget(QWidget *parent)
setUniformRowHeights(true); setUniformRowHeights(true);
setHeaderHidden(true); setHeaderHidden(true);
setIconSize(Utils::Misc::smallIconSize()); setIconSize(Utils::Misc::smallIconSize());
#if defined(Q_OS_MAC) #ifdef Q_OS_MAC
setAttribute(Qt::WA_MacShowFocusRect, false); setAttribute(Qt::WA_MacShowFocusRect, false);
m_defaultIndentation = indentation();
if (!BitTorrent::Session::instance()->isSubcategoriesEnabled())
setIndentation(0);
#endif #endif
setContextMenuPolicy(Qt::CustomContextMenu); setContextMenuPolicy(Qt::CustomContextMenu);
sortByColumn(0, Qt::AscendingOrder); sortByColumn(0, Qt::AscendingOrder);
@ -154,6 +157,12 @@ void CategoryFilterWidget::showMenu(QPoint)
void CategoryFilterWidget::callUpdateGeometry() void CategoryFilterWidget::callUpdateGeometry()
{ {
#ifdef Q_OS_MAC
if (!BitTorrent::Session::instance()->isSubcategoriesEnabled())
setIndentation(0);
else
setIndentation(m_defaultIndentation);
#endif
updateGeometry(); updateGeometry();
} }

View file

@ -57,4 +57,8 @@ private:
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
void rowsInserted(const QModelIndex &parent, int start, int end) override; void rowsInserted(const QModelIndex &parent, int start, int end) override;
QString askCategoryName(); QString askCategoryName();
#ifdef Q_OS_MAC
int m_defaultIndentation;
#endif
}; };

View file

@ -47,8 +47,10 @@ ExecutionLog::ExecutionLog(QWidget *parent, const Log::MsgTypes &types)
m_msgList = new LogListWidget(MAX_LOG_MESSAGES, Log::MsgTypes(types)); m_msgList = new LogListWidget(MAX_LOG_MESSAGES, Log::MsgTypes(types));
#ifndef Q_OS_MAC
ui->tabConsole->setTabIcon(0, GuiIconProvider::instance()->getIcon("view-calendar-journal")); ui->tabConsole->setTabIcon(0, GuiIconProvider::instance()->getIcon("view-calendar-journal"));
ui->tabConsole->setTabIcon(1, GuiIconProvider::instance()->getIcon("view-filter")); ui->tabConsole->setTabIcon(1, GuiIconProvider::instance()->getIcon("view-filter"));
#endif
ui->tabGeneral->layout()->addWidget(m_msgList); ui->tabGeneral->layout()->addWidget(m_msgList);
ui->tabBan->layout()->addWidget(m_peerList); ui->tabBan->layout()->addWidget(m_peerList);

View file

@ -43,13 +43,22 @@ public:
} }
protected: protected:
void tabInserted(int index) #ifdef Q_OS_MAC
void paintEvent(QPaintEvent* event) override
{
// Hide the pane for macintosh style
if (!style()->inherits("QMacStyle"))
QTabWidget::paintEvent(event);
}
#endif
void tabInserted(int index) override
{ {
QTabWidget::tabInserted(index); QTabWidget::tabInserted(index);
tabBar()->setVisible(count() != 1); tabBar()->setVisible(count() != 1);
} }
void tabRemoved(int index) void tabRemoved(int index) override
{ {
//QTabWidget::tabInserted(index); //QTabWidget::tabInserted(index);
QTabWidget::tabRemoved(index); QTabWidget::tabRemoved(index);

View file

@ -30,6 +30,13 @@
#include "mainwindow.h" #include "mainwindow.h"
#ifdef Q_OS_MAC
#include <objc/objc.h>
#include <objc/message.h>
#include <QtMacExtras>
#include <QtMac>
#endif
#include <QtGlobal> #include <QtGlobal>
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) #if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB)
#include <QDBusConnection> #include <QDBusConnection>
@ -149,12 +156,18 @@ MainWindow::MainWindow(QWidget *parent)
setWindowTitle("qBittorrent " QBT_VERSION); setWindowTitle("qBittorrent " QBT_VERSION);
m_displaySpeedInTitle = pref->speedInTitleBar(); m_displaySpeedInTitle = pref->speedInTitleBar();
// Setting icons // Setting icons
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) #ifndef Q_OS_MAC
#ifdef Q_OS_UNIX
if (Preferences::instance()->useSystemIconTheme()) if (Preferences::instance()->useSystemIconTheme())
setWindowIcon(QIcon::fromTheme("qbittorrent", QIcon(":/icons/skin/qbittorrent32.png"))); setWindowIcon(QIcon::fromTheme("qbittorrent", QIcon(":/icons/skin/qbittorrent32.png")));
else else
#endif #endif // Q_OS_UNIX
setWindowIcon(QIcon(":/icons/skin/qbittorrent32.png")); setWindowIcon(QIcon(":/icons/skin/qbittorrent32.png"));
#endif // Q_OS_MAC
#if (defined(Q_OS_UNIX))
m_ui->actionOptions->setText(tr("Preferences"));
#endif
addToolbarContextMenu(); addToolbarContextMenu();
@ -234,7 +247,11 @@ MainWindow::MainWindow(QWidget *parent)
m_splitter->addWidget(hSplitter); m_splitter->addWidget(hSplitter);
m_splitter->setCollapsible(0, true); m_splitter->setCollapsible(0, true);
m_splitter->setCollapsible(1, false); m_splitter->setCollapsible(1, false);
m_tabs->addTab(m_splitter, GuiIconProvider::instance()->getIcon("folder-remote"), tr("Transfers")); m_tabs->addTab(m_splitter,
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("folder-remote"),
#endif
tr("Transfers"));
connect(m_searchFilter, SIGNAL(textChanged(QString)), m_transferListWidget, SLOT(applyNameFilter(QString))); connect(m_searchFilter, SIGNAL(textChanged(QString)), m_transferListWidget, SLOT(applyNameFilter(QString)));
connect(hSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(writeSettings())); connect(hSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(writeSettings()));
@ -247,10 +264,39 @@ MainWindow::MainWindow(QWidget *parent)
connect(BitTorrent::Session::instance(), SIGNAL(trackerError(BitTorrent::TorrentHandle * const,const QString&)), m_transferListFiltersWidget, SLOT(trackerError(BitTorrent::TorrentHandle * const,const QString&))); connect(BitTorrent::Session::instance(), SIGNAL(trackerError(BitTorrent::TorrentHandle * const,const QString&)), m_transferListFiltersWidget, SLOT(trackerError(BitTorrent::TorrentHandle * const,const QString&)));
connect(BitTorrent::Session::instance(), SIGNAL(trackerWarning(BitTorrent::TorrentHandle * const,const QString&)), m_transferListFiltersWidget, SLOT(trackerWarning(BitTorrent::TorrentHandle * const,const QString&))); connect(BitTorrent::Session::instance(), SIGNAL(trackerWarning(BitTorrent::TorrentHandle * const,const QString&)), m_transferListFiltersWidget, SLOT(trackerWarning(BitTorrent::TorrentHandle * const,const QString&)));
#ifdef Q_OS_MAC
// Increase top spacing to avoid tab overlapping
m_ui->centralWidgetLayout->addSpacing(8);
#endif
m_ui->centralWidgetLayout->addWidget(m_tabs); m_ui->centralWidgetLayout->addWidget(m_tabs);
m_prioSeparator = m_ui->toolBar->insertSeparator(m_ui->actionTopPriority); m_prioSeparator = m_ui->toolBar->insertSeparator(m_ui->actionTopPriority);
m_prioSeparatorMenu = m_ui->menuEdit->insertSeparator(m_ui->actionTopPriority); m_prioSeparatorMenu = m_ui->menuEdit->insertSeparator(m_ui->actionTopPriority);
#ifdef Q_OS_MAC
foreach (QAction *action, m_ui->toolBar->actions()) {
if (action->isSeparator()) {
QWidget *spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
spacer->setMinimumWidth(16);
m_ui->toolBar->insertWidget(action, spacer);
m_ui->toolBar->removeAction(action);
}
}
{
QWidget *spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
spacer->setMinimumWidth(8);
m_ui->toolBar->insertWidget(m_ui->actionDownloadFromURL, spacer);
}
{
QWidget *spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
spacer->setMinimumWidth(8);
m_ui->toolBar->addWidget(spacer);
}
#endif
// Transfer list slots // Transfer list slots
connect(m_ui->actionStart, SIGNAL(triggered()), m_transferListWidget, SLOT(startSelectedTorrents())); connect(m_ui->actionStart, SIGNAL(triggered()), m_transferListWidget, SLOT(startSelectedTorrents()));
@ -262,7 +308,9 @@ MainWindow::MainWindow(QWidget *parent)
connect(m_ui->actionIncreasePriority, SIGNAL(triggered()), m_transferListWidget, SLOT(increasePrioSelectedTorrents())); connect(m_ui->actionIncreasePriority, SIGNAL(triggered()), m_transferListWidget, SLOT(increasePrioSelectedTorrents()));
connect(m_ui->actionDecreasePriority, SIGNAL(triggered()), m_transferListWidget, SLOT(decreasePrioSelectedTorrents())); connect(m_ui->actionDecreasePriority, SIGNAL(triggered()), m_transferListWidget, SLOT(decreasePrioSelectedTorrents()));
connect(m_ui->actionBottomPriority, SIGNAL(triggered()), m_transferListWidget, SLOT(bottomPrioSelectedTorrents())); connect(m_ui->actionBottomPriority, SIGNAL(triggered()), m_transferListWidget, SLOT(bottomPrioSelectedTorrents()));
#ifndef Q_OS_MAC
connect(m_ui->actionToggleVisibility, SIGNAL(triggered()), this, SLOT(toggleVisibility())); connect(m_ui->actionToggleVisibility, SIGNAL(triggered()), this, SLOT(toggleVisibility()));
#endif
connect(m_ui->actionMinimize, SIGNAL(triggered()), SLOT(minimizeWindow())); connect(m_ui->actionMinimize, SIGNAL(triggered()), SLOT(minimizeWindow()));
connect(m_ui->actionUseAlternativeSpeedLimits, &QAction::triggered, this, &MainWindow::toggleAlternativeSpeeds); connect(m_ui->actionUseAlternativeSpeedLimits, &QAction::triggered, this, &MainWindow::toggleAlternativeSpeeds);
@ -343,6 +391,7 @@ MainWindow::MainWindow(QWidget *parent)
// Load Window state and sizes // Load Window state and sizes
readSettings(); readSettings();
#ifndef Q_OS_MAC
if (m_systrayIcon) { if (m_systrayIcon) {
if (!(pref->startMinimized() || m_uiLocked)) { if (!(pref->startMinimized() || m_uiLocked)) {
show(); show();
@ -356,6 +405,7 @@ MainWindow::MainWindow(QWidget *parent)
} }
} }
else { else {
#endif
// Make sure the Window is visible if we don't have a tray icon // Make sure the Window is visible if we don't have a tray icon
if (pref->startMinimized()) { if (pref->startMinimized()) {
showMinimized(); showMinimized();
@ -365,7 +415,9 @@ MainWindow::MainWindow(QWidget *parent)
activateWindow(); activateWindow();
raise(); raise();
} }
#ifndef Q_OS_MAC
} }
#endif
m_propertiesWidget->readSettings(); m_propertiesWidget->readSettings();
@ -398,6 +450,7 @@ MainWindow::MainWindow(QWidget *parent)
} }
#endif #endif
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
setupDockClickHandler();
qt_mac_set_dock_menu(trayIconMenu()); qt_mac_set_dock_menu(trayIconMenu());
#endif #endif
} }
@ -616,7 +669,9 @@ void MainWindow::displayRSSTab(bool enable)
m_rssWidget = new RSSWidget(m_tabs); m_rssWidget = new RSSWidget(m_tabs);
connect(m_rssWidget.data(), &RSSWidget::unreadCountUpdated, this, &MainWindow::handleRSSUnreadCountUpdated); connect(m_rssWidget.data(), &RSSWidget::unreadCountUpdated, this, &MainWindow::handleRSSUnreadCountUpdated);
int indexTab = m_tabs->addTab(m_rssWidget, tr("RSS (%1)").arg(RSS::Session::instance()->rootFolder()->unreadCount())); int indexTab = m_tabs->addTab(m_rssWidget, tr("RSS (%1)").arg(RSS::Session::instance()->rootFolder()->unreadCount()));
#ifndef Q_OS_MAC
m_tabs->setTabIcon(indexTab, GuiIconProvider::instance()->getIcon("application-rss+xml")); m_tabs->setTabIcon(indexTab, GuiIconProvider::instance()->getIcon("application-rss+xml"));
#endif
} }
} }
else if (m_rssWidget) { else if (m_rssWidget) {
@ -631,7 +686,11 @@ void MainWindow::displaySearchTab(bool enable)
// RSS tab // RSS tab
if (!m_searchWidget) { if (!m_searchWidget) {
m_searchWidget = new SearchWidget(this); m_searchWidget = new SearchWidget(this);
m_tabs->insertTab(1, m_searchWidget, GuiIconProvider::instance()->getIcon("edit-find"), tr("Search")); m_tabs->insertTab(1, m_searchWidget,
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("edit-find"),
#endif
tr("Search"));
} }
} }
else if (m_searchWidget) { else if (m_searchWidget) {
@ -693,8 +752,10 @@ void MainWindow::cleanup()
delete m_rssWidget; delete m_rssWidget;
delete m_executableWatcher; delete m_executableWatcher;
#ifndef Q_OS_MAC
if (m_systrayCreator) if (m_systrayCreator)
m_systrayCreator->stop(); m_systrayCreator->stop();
#endif
if (m_preventTimer) if (m_preventTimer)
m_preventTimer->stop(); m_preventTimer->stop();
#if (defined(Q_OS_WIN) || defined(Q_OS_MAC)) #if (defined(Q_OS_WIN) || defined(Q_OS_MAC))
@ -955,6 +1016,7 @@ void MainWindow::notifyOfUpdate(QString)
m_executableWatcher = 0; m_executableWatcher = 0;
} }
#ifndef Q_OS_MAC
// Toggle Main window visibility // Toggle Main window visibility
void MainWindow::toggleVisibility(const QSystemTrayIcon::ActivationReason reason) void MainWindow::toggleVisibility(const QSystemTrayIcon::ActivationReason reason)
{ {
@ -983,6 +1045,7 @@ void MainWindow::toggleVisibility(const QSystemTrayIcon::ActivationReason reason
break; break;
} }
} }
#endif
// Display About Dialog // Display About Dialog
void MainWindow::on_actionAbout_triggered() void MainWindow::on_actionAbout_triggered()
@ -1022,12 +1085,20 @@ void MainWindow::showEvent(QShowEvent *e)
void MainWindow::closeEvent(QCloseEvent *e) void MainWindow::closeEvent(QCloseEvent *e)
{ {
Preferences *const pref = Preferences::instance(); Preferences *const pref = Preferences::instance();
#ifdef Q_OS_MAC
if (!m_forceExit) {
hide();
e->accept();
return;
}
#else
const bool goToSystrayOnExit = pref->closeToTray(); const bool goToSystrayOnExit = pref->closeToTray();
if (!m_forceExit && m_systrayIcon && goToSystrayOnExit && !this->isHidden()) { if (!m_forceExit && m_systrayIcon && goToSystrayOnExit && !this->isHidden()) {
hide(); hide();
e->accept(); e->accept();
return; return;
} }
#endif
if (pref->confirmOnExit() && BitTorrent::Session::instance()->hasActiveTorrents()) { if (pref->confirmOnExit() && BitTorrent::Session::instance()->hasActiveTorrents()) {
if (e->spontaneous() || m_forceExit) { if (e->spontaneous() || m_forceExit) {
@ -1059,9 +1130,11 @@ void MainWindow::closeEvent(QCloseEvent *e)
delete m_searchWidget; delete m_searchWidget;
hide(); hide();
#ifndef Q_OS_MAC
// Hide tray icon // Hide tray icon
if (m_systrayIcon) if (m_systrayIcon)
m_systrayIcon->hide(); m_systrayIcon->hide();
#endif
// Accept exit // Accept exit
e->accept(); e->accept();
qApp->exit(); qApp->exit();
@ -1085,6 +1158,7 @@ void MainWindow::createTorrentTriggered(const QString &path)
bool MainWindow::event(QEvent *e) bool MainWindow::event(QEvent *e)
{ {
#ifndef Q_OS_MAC
switch (e->type()) { switch (e->type()) {
case QEvent::WindowStateChange: { case QEvent::WindowStateChange: {
qDebug("Window change event"); qDebug("Window change event");
@ -1112,7 +1186,6 @@ bool MainWindow::event(QEvent *e)
} }
break; break;
} }
#ifdef Q_OS_MAC
case QEvent::ToolBarChange: { case QEvent::ToolBarChange: {
qDebug("MAC: Received a toolbar change event!"); qDebug("MAC: Received a toolbar change event!");
bool ret = QMainWindow::event(e); bool ret = QMainWindow::event(e);
@ -1122,10 +1195,10 @@ bool MainWindow::event(QEvent *e)
Preferences::instance()->setToolbarDisplayed(m_ui->actionTopToolBar->isChecked()); Preferences::instance()->setToolbarDisplayed(m_ui->actionTopToolBar->isChecked());
return ret; return ret;
} }
#endif
default: default:
break; break;
} }
#endif
return QMainWindow::event(e); return QMainWindow::event(e);
} }
@ -1191,6 +1264,53 @@ void MainWindow::dragEnterEvent(QDragEnterEvent *event)
event->acceptProposedAction(); event->acceptProposedAction();
} }
#ifdef Q_OS_MAC
static MainWindow *dockMainWindowHandle;
static bool dockClickHandler(id self, SEL cmd, ...)
{
Q_UNUSED(self)
Q_UNUSED(cmd)
qDebug("Dock icon clicked!");
if (dockMainWindowHandle && !dockMainWindowHandle->isVisible()) {
dockMainWindowHandle->activate();
}
// Return NO (false) to suppress the default OS X actions
return false;
}
void MainWindow::setupDockClickHandler()
{
Class cls = objc_getClass("NSApplication");
objc_object *appInst = objc_msgSend(reinterpret_cast<objc_object *>(cls), sel_registerName("sharedApplication"));
if (!appInst)
return;
dockMainWindowHandle = this;
objc_object* delegate = objc_msgSend(appInst, sel_registerName("delegate"));
Class delClass = reinterpret_cast<Class>(objc_msgSend(delegate, sel_registerName("class")));
SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
if (class_getInstanceMethod(delClass, shouldHandle)) {
if (class_replaceMethod(delClass, shouldHandle, reinterpret_cast<IMP>(dockClickHandler), "B@:"))
qDebug("Registered dock click handler (replaced original method)");
else
qWarning("Failed to replace method for dock click handler");
}
else {
if (class_addMethod(delClass, shouldHandle, reinterpret_cast<IMP>(dockClickHandler), "B@:"))
qDebug("Registered dock click handler");
else
qWarning("Failed to register dock click handler");
}
}
#endif
/***************************************************** /*****************************************************
* * * *
* Torrent * * Torrent *
@ -1258,6 +1378,7 @@ void MainWindow::loadPreferences(bool configureSession)
{ {
Logger::instance()->addMessage(tr("Options were saved successfully.")); Logger::instance()->addMessage(tr("Options were saved successfully."));
const Preferences *const pref = Preferences::instance(); const Preferences *const pref = Preferences::instance();
#ifndef Q_OS_MAC
const bool newSystrayIntegration = pref->systrayIntegration(); const bool newSystrayIntegration = pref->systrayIntegration();
m_ui->actionLock->setVisible(newSystrayIntegration); m_ui->actionLock->setVisible(newSystrayIntegration);
if (newSystrayIntegration != (m_systrayIcon != 0)) { if (newSystrayIntegration != (m_systrayIcon != 0)) {
@ -1288,6 +1409,7 @@ void MainWindow::loadPreferences(bool configureSession)
// Reload systray icon // Reload systray icon
if (newSystrayIntegration && m_systrayIcon) if (newSystrayIntegration && m_systrayIcon)
m_systrayIcon->setIcon(getSystrayIcon()); m_systrayIcon->setIcon(getSystrayIcon());
#endif
// General // General
if (pref->isToolbarDisplayed()) { if (pref->isToolbarDisplayed()) {
m_ui->toolBar->setVisible(true); m_ui->toolBar->setVisible(true);
@ -1321,7 +1443,9 @@ void MainWindow::loadPreferences(bool configureSession)
m_ui->actionIncreasePriority->setVisible(true); m_ui->actionIncreasePriority->setVisible(true);
m_ui->actionTopPriority->setVisible(true); m_ui->actionTopPriority->setVisible(true);
m_ui->actionBottomPriority->setVisible(true); m_ui->actionBottomPriority->setVisible(true);
#ifndef Q_OS_MAC
m_prioSeparator->setVisible(true); m_prioSeparator->setVisible(true);
#endif
m_prioSeparatorMenu->setVisible(true); m_prioSeparatorMenu->setVisible(true);
} }
} }
@ -1332,7 +1456,9 @@ void MainWindow::loadPreferences(bool configureSession)
m_ui->actionIncreasePriority->setVisible(false); m_ui->actionIncreasePriority->setVisible(false);
m_ui->actionTopPriority->setVisible(false); m_ui->actionTopPriority->setVisible(false);
m_ui->actionBottomPriority->setVisible(false); m_ui->actionBottomPriority->setVisible(false);
#ifndef Q_OS_MAC
m_prioSeparator->setVisible(false); m_prioSeparator->setVisible(false);
#endif
m_prioSeparatorMenu->setVisible(false); m_prioSeparatorMenu->setVisible(false);
} }
} }
@ -1379,8 +1505,9 @@ void MainWindow::updateGUI()
const BitTorrent::SessionStatus &status = BitTorrent::Session::instance()->status(); const BitTorrent::SessionStatus &status = BitTorrent::Session::instance()->status();
// update global informations // update global informations
#ifndef Q_OS_MAC
if (m_systrayIcon) { if (m_systrayIcon) {
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) #ifdef Q_OS_UNIX
QString html = "<div style='background-color: #678db2; color: #fff;height: 18px; font-weight: bold; margin-bottom: 5px;'>"; QString html = "<div style='background-color: #678db2; color: #fff;height: 18px; font-weight: bold; margin-bottom: 5px;'>";
html += "qBittorrent"; html += "qBittorrent";
html += "</div>"; html += "</div>";
@ -1395,9 +1522,16 @@ void MainWindow::updateGUI()
QString html = tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate, true)); QString html = tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate, true));
html += "\n"; html += "\n";
html += tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadUploadRate, true)); html += tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadUploadRate, true));
#endif #endif // Q_OS_UNIX
m_systrayIcon->setToolTip(html); // tray icon m_systrayIcon->setToolTip(html); // tray icon
} }
#else
if (status.payloadDownloadRate > 0)
QtMac::setBadgeLabelText(tr("%1/s", "s is a shorthand for seconds")
.arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate)));
else if (!QtMac::badgeLabelText().isEmpty())
QtMac::setBadgeLabelText("");
#endif // Q_OS_MAC
if (m_displaySpeedInTitle) { if (m_displaySpeedInTitle) {
setWindowTitle(tr("[D: %1, U: %2] qBittorrent %3", "D = Download; U = Upload; %3 is qBittorrent version") setWindowTitle(tr("[D: %1, U: %2] qBittorrent %3", "D = Download; U = Upload; %3 is qBittorrent version")
@ -1430,9 +1564,10 @@ void MainWindow::showNotificationBaloon(QString title, QString msg) const
reply.waitForFinished(); reply.waitForFinished();
if (!reply.isError()) if (!reply.isError())
return; return;
#endif #elif (!defined(Q_OS_MAC))
if (m_systrayIcon && QSystemTrayIcon::supportsMessages()) if (m_systrayIcon && QSystemTrayIcon::supportsMessages())
m_systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON); m_systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON);
#endif
} }
/***************************************************** /*****************************************************
@ -1462,6 +1597,7 @@ void MainWindow::downloadFromURLList(const QStringList &urlList)
* * * *
*****************************************************/ *****************************************************/
#ifndef Q_OS_MAC
void MainWindow::createSystrayDelayed() void MainWindow::createSystrayDelayed()
{ {
static int timeout = 20; static int timeout = 20;
@ -1488,24 +1624,34 @@ void MainWindow::createSystrayDelayed()
} }
} }
void MainWindow::updateAltSpeedsBtn(bool alternative)
{
m_ui->actionUseAlternativeSpeedLimits->setChecked(alternative);
}
void MainWindow::updateTrayIconMenu() void MainWindow::updateTrayIconMenu()
{ {
m_ui->actionToggleVisibility->setText(isVisible() ? tr("Hide") : tr("Show")); m_ui->actionToggleVisibility->setText(isVisible() ? tr("Hide") : tr("Show"));
} }
void MainWindow::createTrayIcon()
{
// Tray icon
m_systrayIcon = new QSystemTrayIcon(getSystrayIcon(), this);
m_systrayIcon->setContextMenu(trayIconMenu());
connect(m_systrayIcon, SIGNAL(messageClicked()), this, SLOT(balloonClicked()));
// End of Icon Menu
connect(m_systrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason)));
m_systrayIcon->show();
}
#endif
QMenu *MainWindow::trayIconMenu() QMenu *MainWindow::trayIconMenu()
{ {
if (m_trayIconMenu) return m_trayIconMenu; if (m_trayIconMenu) return m_trayIconMenu;
m_trayIconMenu = new QMenu(this); m_trayIconMenu = new QMenu(this);
#ifndef Q_OS_MAC
connect(m_trayIconMenu, SIGNAL(aboutToShow()), SLOT(updateTrayIconMenu())); connect(m_trayIconMenu, SIGNAL(aboutToShow()), SLOT(updateTrayIconMenu()));
m_trayIconMenu->addAction(m_ui->actionToggleVisibility); m_trayIconMenu->addAction(m_ui->actionToggleVisibility);
m_trayIconMenu->addSeparator(); m_trayIconMenu->addSeparator();
#endif
m_trayIconMenu->addAction(m_ui->actionOpen); m_trayIconMenu->addAction(m_ui->actionOpen);
m_trayIconMenu->addAction(m_ui->actionDownloadFromURL); m_trayIconMenu->addAction(m_ui->actionDownloadFromURL);
m_trayIconMenu->addSeparator(); m_trayIconMenu->addSeparator();
@ -1518,31 +1664,26 @@ QMenu *MainWindow::trayIconMenu()
m_trayIconMenu->addSeparator(); m_trayIconMenu->addSeparator();
m_trayIconMenu->addAction(m_ui->actionStartAll); m_trayIconMenu->addAction(m_ui->actionStartAll);
m_trayIconMenu->addAction(m_ui->actionPauseAll); m_trayIconMenu->addAction(m_ui->actionPauseAll);
#ifndef Q_OS_MAC
m_trayIconMenu->addSeparator(); m_trayIconMenu->addSeparator();
m_trayIconMenu->addAction(m_ui->actionExit); m_trayIconMenu->addAction(m_ui->actionExit);
#endif
if (m_uiLocked) if (m_uiLocked)
m_trayIconMenu->setEnabled(false); m_trayIconMenu->setEnabled(false);
return m_trayIconMenu; return m_trayIconMenu;
} }
void MainWindow::updateAltSpeedsBtn(bool alternative)
{
m_ui->actionUseAlternativeSpeedLimits->setChecked(alternative);
}
PropertiesWidget *MainWindow::propertiesWidget() const PropertiesWidget *MainWindow::propertiesWidget() const
{ {
return m_propertiesWidget; return m_propertiesWidget;
} }
void MainWindow::createTrayIcon()
{
// Tray icon
m_systrayIcon = new QSystemTrayIcon(getSystrayIcon(), this);
m_systrayIcon->setContextMenu(trayIconMenu());
connect(m_systrayIcon, SIGNAL(messageClicked()), this, SLOT(balloonClicked()));
// End of Icon Menu
connect(m_systrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason)));
m_systrayIcon->show();
}
// Display Program Options // Display Program Options
void MainWindow::on_actionOptions_triggered() void MainWindow::on_actionOptions_triggered()
{ {
@ -1726,7 +1867,9 @@ void MainWindow::on_actionExecutionLogs_triggered(bool checked)
Q_ASSERT(!m_executionLog); Q_ASSERT(!m_executionLog);
m_executionLog = new ExecutionLog(m_tabs, static_cast<Log::MsgType>(executionLogMsgTypes())); m_executionLog = new ExecutionLog(m_tabs, static_cast<Log::MsgType>(executionLogMsgTypes()));
int indexTab = m_tabs->addTab(m_executionLog, tr("Execution Log")); int indexTab = m_tabs->addTab(m_executionLog, tr("Execution Log"));
#ifndef Q_OS_MAC
m_tabs->setTabIcon(indexTab, GuiIconProvider::instance()->getIcon("view-calendar-journal")); m_tabs->setTabIcon(indexTab, GuiIconProvider::instance()->getIcon("view-calendar-journal"));
#endif
} }
else if (m_executionLog) { else if (m_executionLog) {
delete m_executionLog; delete m_executionLog;
@ -1808,6 +1951,7 @@ void MainWindow::checkForActiveTorrents()
m_pwr->setActivityState(BitTorrent::Session::instance()->hasActiveTorrents()); m_pwr->setActivityState(BitTorrent::Session::instance()->hasActiveTorrents());
} }
#ifndef Q_OS_MAC
QIcon MainWindow::getSystrayIcon() const QIcon MainWindow::getSystrayIcon() const
{ {
#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) #if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
@ -1843,6 +1987,7 @@ QIcon MainWindow::getSystrayIcon() const
icon.addFile(":/icons/skin/qbittorrent32.png", QSize(32, 32)); icon.addFile(":/icons/skin/qbittorrent32.png", QSize(32, 32));
return icon; return icon;
} }
#endif
#if defined(Q_OS_WIN) || defined(Q_OS_MAC) #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
void MainWindow::checkProgramUpdate() void MainWindow::checkProgramUpdate()

View file

@ -32,9 +32,12 @@
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon>
#include <QPointer> #include <QPointer>
#ifndef Q_OS_MAC
#include <QSystemTrayIcon>
#endif
class QCloseEvent; class QCloseEvent;
class QFileSystemWatcher; class QFileSystemWatcher;
class QShortcut; class QShortcut;
@ -102,15 +105,11 @@ public:
void showNotificationBaloon(QString title, QString msg) const; void showNotificationBaloon(QString title, QString msg) const;
private slots: private slots:
void toggleVisibility(const QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Trigger);
void balloonClicked(); void balloonClicked();
void writeSettings(); void writeSettings();
void readSettings(); void readSettings();
void createTrayIcon();
void fullDiskError(BitTorrent::TorrentHandle *const torrent, QString msg) const; void fullDiskError(BitTorrent::TorrentHandle *const torrent, QString msg) const;
void handleDownloadFromUrlFailure(QString, QString) const; void handleDownloadFromUrlFailure(QString, QString) const;
void createSystrayDelayed();
void tabChanged(int newTab); void tabChanged(int newTab);
void defineUILockPassword(); void defineUILockPassword();
void clearUILockPassword(); void clearUILockPassword();
@ -118,7 +117,6 @@ private slots:
void notifyOfUpdate(QString); void notifyOfUpdate(QString);
void showConnectionSettings(); void showConnectionSettings();
void minimizeWindow(); void minimizeWindow();
void updateTrayIconMenu();
// Keyboard shortcuts // Keyboard shortcuts
void createKeyboardShortcuts(); void createKeyboardShortcuts();
void displayTransferTab() const; void displayTransferTab() const;
@ -191,7 +189,15 @@ private slots:
void toolbarFollowSystem(); void toolbarFollowSystem();
private: private:
#ifdef Q_OS_MAC
void setupDockClickHandler();
#else
void toggleVisibility(const QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Trigger);
void createTrayIcon();
void createSystrayDelayed();
void updateTrayIconMenu();
QIcon getSystrayIcon() const; QIcon getSystrayIcon() const;
#endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
bool addPythonPathToEnv(); bool addPythonPathToEnv();
void installPython(); void installPython();
@ -221,8 +227,10 @@ private:
QPointer<StatsDialog> m_statsDlg; QPointer<StatsDialog> m_statsDlg;
QPointer<TorrentCreatorDlg> m_createTorrentDlg; QPointer<TorrentCreatorDlg> m_createTorrentDlg;
QPointer<downloadFromURL> m_downloadFromURLDialog; QPointer<downloadFromURL> m_downloadFromURLDialog;
#ifndef Q_OS_MAC
QPointer<QSystemTrayIcon> m_systrayIcon; QPointer<QSystemTrayIcon> m_systrayIcon;
QPointer<QTimer> m_systrayCreator; QPointer<QTimer> m_systrayCreator;
#endif
QPointer<QMenu> m_trayIconMenu; QPointer<QMenu> m_trayIconMenu;
TransferListWidget *m_transferListWidget; TransferListWidget *m_transferListWidget;
TransferListFiltersWidget *m_transferListFiltersWidget; TransferListFiltersWidget *m_transferListFiltersWidget;

View file

@ -81,6 +81,10 @@ OptionsDialog::OptionsDialog(QWidget *parent)
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setModal(true); setModal(true);
#if (defined(Q_OS_UNIX))
setWindowTitle(tr("Preferences"));
#endif
// Icons // Icons
m_ui->tabSelection->item(TAB_UI)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop")); m_ui->tabSelection->item(TAB_UI)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop"));
m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network")); m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network"));
@ -95,7 +99,8 @@ OptionsDialog::OptionsDialog(QWidget *parent)
#endif #endif
m_ui->tabSelection->item(TAB_ADVANCED)->setIcon(GuiIconProvider::instance()->getIcon("preferences-other")); m_ui->tabSelection->item(TAB_ADVANCED)->setIcon(GuiIconProvider::instance()->getIcon("preferences-other"));
for (int i = 0; i < m_ui->tabSelection->count(); ++i) { for (int i = 0; i < m_ui->tabSelection->count(); ++i) {
m_ui->tabSelection->item(i)->setSizeHint(QSize(std::numeric_limits<int>::max(), 64)); // uniform size for all icons // uniform size for all icons
m_ui->tabSelection->item(i)->setSizeHint(QSize(std::numeric_limits<int>::max(), 62));
} }
m_ui->IpFilterRefreshBtn->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); m_ui->IpFilterRefreshBtn->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
@ -143,6 +148,9 @@ OptionsDialog::OptionsDialog(QWidget *parent)
// Load options // Load options
loadOptions(); loadOptions();
#ifdef Q_OS_MAC
m_ui->checkShowSystray->setVisible(false);
#else
// Disable systray integration if it is not supported by the system // Disable systray integration if it is not supported by the system
if (!QSystemTrayIcon::isSystemTrayAvailable()) { if (!QSystemTrayIcon::isSystemTrayAvailable()) {
m_ui->checkShowSystray->setChecked(false); m_ui->checkShowSystray->setChecked(false);
@ -150,6 +158,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
m_ui->label_trayIconStyle->setVisible(false); m_ui->label_trayIconStyle->setVisible(false);
m_ui->comboTrayIcon->setVisible(false); m_ui->comboTrayIcon->setVisible(false);
} }
#endif
#if defined(QT_NO_OPENSSL) #if defined(QT_NO_OPENSSL)
m_ui->checkWebUiHttps->setVisible(false); m_ui->checkWebUiHttps->setVisible(false);
@ -479,11 +488,13 @@ void OptionsDialog::saveOptions()
pref->setAlternatingRowColors(m_ui->checkAltRowColors->isChecked()); pref->setAlternatingRowColors(m_ui->checkAltRowColors->isChecked());
pref->setHideZeroValues(m_ui->checkHideZero->isChecked()); pref->setHideZeroValues(m_ui->checkHideZero->isChecked());
pref->setHideZeroComboValues(m_ui->comboHideZero->currentIndex()); pref->setHideZeroComboValues(m_ui->comboHideZero->currentIndex());
#ifndef Q_OS_MAC
pref->setSystrayIntegration(systrayIntegration()); pref->setSystrayIntegration(systrayIntegration());
pref->setTrayIconStyle(TrayIcon::Style(m_ui->comboTrayIcon->currentIndex())); pref->setTrayIconStyle(TrayIcon::Style(m_ui->comboTrayIcon->currentIndex()));
pref->setCloseToTray(closeToTray()); pref->setCloseToTray(closeToTray());
pref->setMinimizeToTray(minimizeToTray()); pref->setMinimizeToTray(minimizeToTray());
pref->setStartMinimized(startMinimized()); pref->setStartMinimized(startMinimized());
#endif
pref->setSplashScreenDisabled(isSlashScreenDisabled()); pref->setSplashScreenDisabled(isSlashScreenDisabled());
pref->setConfirmOnExit(m_ui->checkProgramExitConfirm->isChecked()); pref->setConfirmOnExit(m_ui->checkProgramExitConfirm->isChecked());
pref->setDontConfirmAutoExit(!m_ui->checkProgramAutoExitConfirm->isChecked()); pref->setDontConfirmAutoExit(!m_ui->checkProgramAutoExitConfirm->isChecked());
@ -699,12 +710,14 @@ void OptionsDialog::loadOptions()
m_ui->checkProgramExitConfirm->setChecked(pref->confirmOnExit()); m_ui->checkProgramExitConfirm->setChecked(pref->confirmOnExit());
m_ui->checkProgramAutoExitConfirm->setChecked(!pref->dontConfirmAutoExit()); m_ui->checkProgramAutoExitConfirm->setChecked(!pref->dontConfirmAutoExit());
#ifndef Q_OS_MAC
m_ui->checkShowSystray->setChecked(pref->systrayIntegration()); m_ui->checkShowSystray->setChecked(pref->systrayIntegration());
if (m_ui->checkShowSystray->isChecked()) { if (m_ui->checkShowSystray->isChecked()) {
m_ui->checkMinimizeToSysTray->setChecked(pref->minimizeToTray()); m_ui->checkMinimizeToSysTray->setChecked(pref->minimizeToTray());
m_ui->checkCloseToSystray->setChecked(pref->closeToTray()); m_ui->checkCloseToSystray->setChecked(pref->closeToTray());
m_ui->comboTrayIcon->setCurrentIndex(pref->trayIconStyle()); m_ui->comboTrayIcon->setCurrentIndex(pref->trayIconStyle());
} }
#endif
m_ui->checkPreventFromSuspend->setChecked(pref->preventFromSuspend()); m_ui->checkPreventFromSuspend->setChecked(pref->preventFromSuspend());
@ -1067,18 +1080,6 @@ int OptionsDialog::getMaxActiveTorrents() const
return m_ui->spinMaxActiveTorrents->value(); return m_ui->spinMaxActiveTorrents->value();
} }
bool OptionsDialog::minimizeToTray() const
{
if (!m_ui->checkShowSystray->isChecked()) return false;
return m_ui->checkMinimizeToSysTray->isChecked();
}
bool OptionsDialog::closeToTray() const
{
if (!m_ui->checkShowSystray->isChecked()) return false;
return m_ui->checkCloseToSystray->isChecked();
}
bool OptionsDialog::isQueueingSystemEnabled() const bool OptionsDialog::isQueueingSystemEnabled() const
{ {
return m_ui->checkEnableQueueing->isChecked(); return m_ui->checkEnableQueueing->isChecked();
@ -1128,12 +1129,26 @@ bool OptionsDialog::startMinimized() const
return m_ui->checkStartMinimized->isChecked(); return m_ui->checkStartMinimized->isChecked();
} }
#ifndef Q_OS_MAC
bool OptionsDialog::systrayIntegration() const bool OptionsDialog::systrayIntegration() const
{ {
if (!QSystemTrayIcon::isSystemTrayAvailable()) return false; if (!QSystemTrayIcon::isSystemTrayAvailable()) return false;
return m_ui->checkShowSystray->isChecked(); return m_ui->checkShowSystray->isChecked();
} }
bool OptionsDialog::minimizeToTray() const
{
if (!m_ui->checkShowSystray->isChecked()) return false;
return m_ui->checkMinimizeToSysTray->isChecked();
}
bool OptionsDialog::closeToTray() const
{
if (!m_ui->checkShowSystray->isChecked()) return false;
return m_ui->checkCloseToSystray->isChecked();
}
#endif
// Return Share ratio // Return Share ratio
qreal OptionsDialog::getMaxRatio() const qreal OptionsDialog::getMaxRatio() const
{ {

View file

@ -114,9 +114,11 @@ private:
static QString languageToLocalizedString(const QLocale &locale); static QString languageToLocalizedString(const QLocale &locale);
// General options // General options
QString getLocale() const; QString getLocale() const;
#ifndef Q_OS_MAC
bool systrayIntegration() const; bool systrayIntegration() const;
bool minimizeToTray() const; bool minimizeToTray() const;
bool closeToTray() const; bool closeToTray() const;
#endif
bool startMinimized() const; bool startMinimized() const;
bool isSlashScreenDisabled() const; bool isSlashScreenDisabled() const;
bool preventFromSuspend() const; bool preventFromSuspend() const;

View file

@ -43,34 +43,58 @@ PropTabBar::PropTabBar(QWidget *parent) :
setSpacing(3); setSpacing(3);
m_btnGroup = new QButtonGroup(this); m_btnGroup = new QButtonGroup(this);
// General tab // General tab
QPushButton *main_infos_button = new QPushButton(GuiIconProvider::instance()->getIcon("document-properties"), tr("General"), parent); QPushButton *main_infos_button = new QPushButton(
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("document-properties"),
#endif
tr("General"), parent);
main_infos_button->setShortcut(Qt::ALT + Qt::Key_G); main_infos_button->setShortcut(Qt::ALT + Qt::Key_G);
addWidget(main_infos_button); addWidget(main_infos_button);
m_btnGroup->addButton(main_infos_button, MAIN_TAB); m_btnGroup->addButton(main_infos_button, MAIN_TAB);
// Trackers tab // Trackers tab
QPushButton *trackers_button = new QPushButton(GuiIconProvider::instance()->getIcon("network-server"), tr("Trackers"), parent); QPushButton *trackers_button = new QPushButton(
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("network-server"),
#endif
tr("Trackers"), parent);
trackers_button->setShortcut(Qt::ALT + Qt::Key_C); trackers_button->setShortcut(Qt::ALT + Qt::Key_C);
addWidget(trackers_button); addWidget(trackers_button);
m_btnGroup->addButton(trackers_button, TRACKERS_TAB); m_btnGroup->addButton(trackers_button, TRACKERS_TAB);
// Peers tab // Peers tab
QPushButton *peers_button = new QPushButton(GuiIconProvider::instance()->getIcon("edit-find-user"), tr("Peers"), parent); QPushButton *peers_button = new QPushButton(
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("edit-find-user"),
#endif
tr("Peers"), parent);
peers_button->setShortcut(Qt::ALT + Qt::Key_R); peers_button->setShortcut(Qt::ALT + Qt::Key_R);
addWidget(peers_button); addWidget(peers_button);
m_btnGroup->addButton(peers_button, PEERS_TAB); m_btnGroup->addButton(peers_button, PEERS_TAB);
// URL seeds tab // URL seeds tab
QPushButton *urlseeds_button = new QPushButton(GuiIconProvider::instance()->getIcon("network-server"), tr("HTTP Sources"), parent); QPushButton *urlseeds_button = new QPushButton(
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("network-server"),
#endif
tr("HTTP Sources"), parent);
urlseeds_button->setShortcut(Qt::ALT + Qt::Key_B); urlseeds_button->setShortcut(Qt::ALT + Qt::Key_B);
addWidget(urlseeds_button); addWidget(urlseeds_button);
m_btnGroup->addButton(urlseeds_button, URLSEEDS_TAB); m_btnGroup->addButton(urlseeds_button, URLSEEDS_TAB);
// Files tab // Files tab
QPushButton *files_button = new QPushButton(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Content"), parent); QPushButton *files_button = new QPushButton(
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("inode-directory"),
#endif
tr("Content"), parent);
files_button->setShortcut(Qt::ALT + Qt::Key_Z); files_button->setShortcut(Qt::ALT + Qt::Key_Z);
addWidget(files_button); addWidget(files_button);
m_btnGroup->addButton(files_button, FILES_TAB); m_btnGroup->addButton(files_button, FILES_TAB);
// Spacer // Spacer
addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed)); addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
// Speed tab // Speed tab
QPushButton *speed_button = new QPushButton(GuiIconProvider::instance()->getIcon("office-chart-line"), tr("Speed"), parent); QPushButton *speed_button = new QPushButton(
#ifndef Q_OS_MAC
GuiIconProvider::instance()->getIcon("office-chart-line"),
#endif
tr("Speed"), parent);
speed_button->setShortcut(Qt::ALT + Qt::Key_D); speed_button->setShortcut(Qt::ALT + Qt::Key_D);
addWidget(speed_button); addWidget(speed_button);
m_btnGroup->addButton(speed_button, SPEED_TAB); m_btnGroup->addButton(speed_button, SPEED_TAB);

View file

@ -72,10 +72,12 @@ RSSWidget::RSSWidget(QWidget *parent)
m_ui->actionRename->setIcon(GuiIconProvider::instance()->getIcon("edit-rename")); m_ui->actionRename->setIcon(GuiIconProvider::instance()->getIcon("edit-rename"));
m_ui->actionUpdate->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); m_ui->actionUpdate->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
m_ui->actionUpdateAllFeeds->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); m_ui->actionUpdateAllFeeds->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
#ifndef Q_OS_MAC
m_ui->newFeedButton->setIcon(GuiIconProvider::instance()->getIcon("list-add")); m_ui->newFeedButton->setIcon(GuiIconProvider::instance()->getIcon("list-add"));
m_ui->markReadButton->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read")); m_ui->markReadButton->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read"));
m_ui->updateAllButton->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); m_ui->updateAllButton->setIcon(GuiIconProvider::instance()->getIcon("view-refresh"));
m_ui->rssDownloaderBtn->setIcon(GuiIconProvider::instance()->getIcon("download")); m_ui->rssDownloaderBtn->setIcon(GuiIconProvider::instance()->getIcon("download"));
#endif
m_articleListWidget = new ArticleListWidget(m_ui->splitterMain); m_articleListWidget = new ArticleListWidget(m_ui->splitterMain);
m_ui->splitterMain->insertWidget(0, m_articleListWidget); m_ui->splitterMain->insertWidget(0, m_articleListWidget);

View file

@ -99,12 +99,19 @@ SearchWidget::SearchWidget(MainWindow *mainWindow)
<< "</p></body></html>" << flush; << "</p></body></html>" << flush;
m_ui->m_searchPattern->setToolTip(searchPatternHint); m_ui->m_searchPattern->setToolTip(searchPatternHint);
#ifndef Q_OS_MAC
// Icons // Icons
m_ui->searchButton->setIcon(GuiIconProvider::instance()->getIcon("edit-find")); m_ui->searchButton->setIcon(GuiIconProvider::instance()->getIcon("edit-find"));
m_ui->downloadButton->setIcon(GuiIconProvider::instance()->getIcon("download")); m_ui->downloadButton->setIcon(GuiIconProvider::instance()->getIcon("download"));
m_ui->goToDescBtn->setIcon(GuiIconProvider::instance()->getIcon("application-x-mswinurl")); m_ui->goToDescBtn->setIcon(GuiIconProvider::instance()->getIcon("application-x-mswinurl"));
m_ui->pluginsButton->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network")); m_ui->pluginsButton->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network"));
m_ui->copyURLBtn->setIcon(GuiIconProvider::instance()->getIcon("edit-copy")); m_ui->copyURLBtn->setIcon(GuiIconProvider::instance()->getIcon("edit-copy"));
#else
// On macOS the icons overlap the text otherwise
QSize iconSize = m_ui->tabWidget->iconSize();
iconSize.setWidth(iconSize.width() + 16);
m_ui->tabWidget->setIconSize(iconSize);
#endif
connect(m_ui->tabWidget, &QTabWidget::tabCloseRequested, this, &SearchWidget::closeTab); connect(m_ui->tabWidget, &QTabWidget::tabCloseRequested, this, &SearchWidget::closeTab);
m_searchEngine = new SearchEngine; m_searchEngine = new SearchEngine;

View file

@ -45,7 +45,11 @@
StatusBar::StatusBar(QWidget *parent) StatusBar::StatusBar(QWidget *parent)
: QStatusBar(parent) : QStatusBar(parent)
{ {
#ifndef Q_OS_MAC
// Redefining global stylesheet breaks certain elements on mac like tabs.
// Qt checks whether the stylesheet class inherts("QMacStyle") and this becomes false.
qApp->setStyleSheet("QStatusBar::item { border-width: 0; }"); qApp->setStyleSheet("QStatusBar::item { border-width: 0; }");
#endif
BitTorrent::Session *const session = BitTorrent::Session::instance(); BitTorrent::Session *const session = BitTorrent::Session::instance();
connect(session, &BitTorrent::Session::speedLimitModeChanged, this, &StatusBar::updateAltSpeedsBtn); connect(session, &BitTorrent::Session::speedLimitModeChanged, this, &StatusBar::updateAltSpeedsBtn);
@ -108,16 +112,24 @@ StatusBar::StatusBar(QWidget *parent)
QFrame *statusSep1 = new QFrame(this); QFrame *statusSep1 = new QFrame(this);
statusSep1->setFrameStyle(QFrame::VLine); statusSep1->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MAC
statusSep1->setFrameShadow(QFrame::Raised); statusSep1->setFrameShadow(QFrame::Raised);
#endif
QFrame *statusSep2 = new QFrame(this); QFrame *statusSep2 = new QFrame(this);
statusSep2->setFrameStyle(QFrame::VLine); statusSep2->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MAC
statusSep2->setFrameShadow(QFrame::Raised); statusSep2->setFrameShadow(QFrame::Raised);
#endif
QFrame *statusSep3 = new QFrame(this); QFrame *statusSep3 = new QFrame(this);
statusSep3->setFrameStyle(QFrame::VLine); statusSep3->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MAC
statusSep3->setFrameShadow(QFrame::Raised); statusSep3->setFrameShadow(QFrame::Raised);
#endif
QFrame *statusSep4 = new QFrame(this); QFrame *statusSep4 = new QFrame(this);
statusSep4->setFrameStyle(QFrame::VLine); statusSep4->setFrameStyle(QFrame::VLine);
#ifndef Q_OS_MAC
statusSep4->setFrameShadow(QFrame::Raised); statusSep4->setFrameShadow(QFrame::Raised);
#endif
layout->addWidget(m_DHTLbl); layout->addWidget(m_DHTLbl);
layout->addWidget(statusSep1); layout->addWidget(statusSep1);
layout->addWidget(m_connecStatusLblIcon); layout->addWidget(m_connecStatusLblIcon);

View file

@ -73,6 +73,7 @@ TagFilterWidget::TagFilterWidget(QWidget *parent)
setIconSize(Utils::Misc::smallIconSize()); setIconSize(Utils::Misc::smallIconSize());
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
setAttribute(Qt::WA_MacShowFocusRect, false); setAttribute(Qt::WA_MacShowFocusRect, false);
setIndentation(0);
#endif #endif
setContextMenuPolicy(Qt::CustomContextMenu); setContextMenuPolicy(Qt::CustomContextMenu);
sortByColumn(0, Qt::AscendingOrder); sortByColumn(0, Qt::AscendingOrder);

View file

@ -23,6 +23,8 @@ nogui {
DEFINES += DISABLE_GUI DEFINES += DISABLE_GUI
TARGET = qbittorrent-nox TARGET = qbittorrent-nox
} else { } else {
macx: QT += macextras
macx: LIBS += -lobjc
QT += xml concurrent svg widgets QT += xml concurrent svg widgets
CONFIG(static) { CONFIG(static) {
DEFINES += QBT_STATIC_QT DEFINES += QBT_STATIC_QT