Show main dialog as normal window if tray icons not available

Fixes #3307

Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
This commit is contained in:
Felix Weilbach 2021-06-21 13:33:22 +02:00 committed by Felix Weilbach (Rebase PR Action)
parent bffcf8e482
commit efaccbd6fd
10 changed files with 98 additions and 43 deletions

View file

@ -33,33 +33,35 @@ Some interesting values that can be set on the configuration file are:
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+ +---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``[General]`` section | | ``[General]`` section |
+=================================+===============+=================================================================================================================+ +==================================+===============+=================================================================================================================+
| Variable | Default | Meaning | | Variable | Default | Meaning |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``chunkSize`` | ``10000000`` (10 MB) | Specifies the chunk size of uploaded files in bytes. | | ``chunkSize`` | ``10000000`` (10 MB) | Specifies the chunk size of uploaded files in bytes. |
| | | The client will dynamically adjust this size within the maximum and minimum bounds (see below). | | | | The client will dynamically adjust this size within the maximum and minimum bounds (see below). |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``maxChunkSize`` | ``100000000`` (100 MB) | Specifies the maximum chunk size of uploaded files in bytes. | | ``maxChunkSize`` | ``100000000`` (100 MB) | Specifies the maximum chunk size of uploaded files in bytes. |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``minChunkSize`` | ``1000000`` (1 MB) | Specifies the minimum chunk size of uploaded files in bytes. | | ``minChunkSize`` | ``1000000`` (1 MB) | Specifies the minimum chunk size of uploaded files in bytes. |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``targetChunkUploadDuration`` | ``6000`` (1 minute) | Target duration in milliseconds for chunk uploads. | | ``targetChunkUploadDuration`` | ``6000`` (1 minute) | Target duration in milliseconds for chunk uploads. |
| | | The client adjusts the chunk size until each chunk upload takes approximately this long. | | | | The client adjusts the chunk size until each chunk upload takes approximately this long. |
| | | Set to 0 to disable dynamic chunk sizing. | | | | Set to 0 to disable dynamic chunk sizing. |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``promptDeleteAllFiles`` | ``true`` | If a UI prompt should ask for confirmation if it was detected that all files and folders were deleted. | | ``promptDeleteAllFiles`` | ``true`` | If a UI prompt should ask for confirmation if it was detected that all files and folders were deleted. |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``timeout`` | ``300`` | The timeout for network connections in seconds. | | ``timeout`` | ``300`` | The timeout for network connections in seconds. |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``moveToTrash`` | ``false`` | If non-locally deleted files should be moved to trash instead of deleting them completely. | | ``moveToTrash`` | ``false`` | If non-locally deleted files should be moved to trash instead of deleting them completely. |
| | | This option only works on linux | | | | This option only works on linux |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``showExperimentalOptions`` | ``false`` | Whether to show experimental options that are still undergoing testing in the user interface. | | ``showExperimentalOptions`` | ``false`` | Whether to show experimental options that are still undergoing testing in the user interface. |
| | | Turning this on does not enable experimental behavior on its own. It does enable user inferface | | | | Turning this on does not enable experimental behavior on its own. It does enable user inferface |
| | | options that can be used to opt in to experimental features. | | | | options that can be used to opt in to experimental features. |
+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``showMainDialogAsNormalWindow`` | ``false`` | Whether the main dialog should be shown as a normal window even if tray icons are available. |
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
+----------------------------------------------------------------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------------------------------------------------------------------------+

View file

@ -555,7 +555,13 @@ void Application::slotParseMessage(const QString &msg, QObject *)
qCWarning(lcApplication) << "Ignoring MSG_SHOWMAINDIALOG, possibly double-invocation of client via session restore and auto start"; qCWarning(lcApplication) << "Ignoring MSG_SHOWMAINDIALOG, possibly double-invocation of client via session restore and auto start";
return; return;
} }
showMainDialog();
// Show the main dialog only if there is at least one account configured
if (!AccountManager::instance()->accounts().isEmpty()) {
showMainDialog();
} else {
_gui->slotNewAccountWizard();
}
} }
} }

View file

@ -176,7 +176,7 @@ int main(int argc, char **argv)
if (QSystemTrayIcon::isSystemTrayAvailable()) { if (QSystemTrayIcon::isSystemTrayAvailable()) {
app.tryTrayAgain(); app.tryTrayAgain();
} else if (!app.backgroundMode()) { } else if (!app.backgroundMode() && !AccountManager::instance()->accounts().isEmpty()) {
if (desktopSession != "ubuntu") { if (desktopSession != "ubuntu") {
qCInfo(lcApplication) << "System tray still not available, showing window and trying again later"; qCInfo(lcApplication) << "System tray still not available, showing window and trying again later";
app.showMainDialog(); app.showMainDialog();

View file

@ -107,10 +107,11 @@ public slots:
void slotRemoveDestroyedShareDialogs(); void slotRemoveDestroyedShareDialogs();
void slotNewAccountWizard();
private slots: private slots:
void slotLogin(); void slotLogin();
void slotLogout(); void slotLogout();
void slotNewAccountWizard();
private: private:
QPointer<Systray> _tray; QPointer<Systray> _tray;

View file

@ -18,6 +18,7 @@
#include "config.h" #include "config.h"
#include "common/utility.h" #include "common/utility.h"
#include "tray/UserModel.h" #include "tray/UserModel.h"
#include "configfile.h"
#include <QCursor> #include <QCursor>
#include <QGuiApplication> #include <QGuiApplication>
@ -197,6 +198,21 @@ bool Systray::isOpen()
return _isOpen; return _isOpen;
} }
QString Systray::windowTitle() const
{
return Theme::instance()->appNameGUI();
}
bool Systray::useNormalWindow() const
{
if (!isSystemTrayAvailable()) {
return true;
}
ConfigFile cfg;
return cfg.showMainDialogAsNormalWindow();
}
Q_INVOKABLE void Systray::setOpened() Q_INVOKABLE void Systray::setOpened()
{ {
_isOpen = true; _isOpen = true;
@ -258,8 +274,10 @@ void Systray::positionWindow(QQuickWindow *window) const
{ {
window->setScreen(currentScreen()); window->setScreen(currentScreen());
const auto position = computeWindowPosition(window->width(), window->height()); if (useNormalWindow()) {
window->setPosition(position); const auto position = computeWindowPosition(window->width(), window->height());
window->setPosition(position);
}
} }
void Systray::forceWindowInit(QQuickWindow *window) const void Systray::forceWindowInit(QQuickWindow *window) const

View file

@ -24,6 +24,7 @@ class QScreen;
class QQmlApplicationEngine; class QQmlApplicationEngine;
class QQuickWindow; class QQuickWindow;
class QWindow; class QWindow;
class QQuickWindow;
namespace OCC { namespace OCC {
@ -41,6 +42,10 @@ class Systray
: public QSystemTrayIcon : public QSystemTrayIcon
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString windowTitle READ windowTitle CONSTANT)
Q_PROPERTY(bool useNormalWindow READ useNormalWindow CONSTANT)
public: public:
static Systray *instance(); static Systray *instance();
virtual ~Systray() = default; virtual ~Systray() = default;
@ -53,6 +58,8 @@ public:
void showMessage(const QString &title, const QString &message, MessageIcon icon = Information); void showMessage(const QString &title, const QString &message, MessageIcon icon = Information);
void setToolTip(const QString &tip); void setToolTip(const QString &tip);
bool isOpen(); bool isOpen();
QString windowTitle() const;
bool useNormalWindow() const;
Q_INVOKABLE void pauseResumeSync(); Q_INVOKABLE void pauseResumeSync();
Q_INVOKABLE bool syncIsPaused(); Q_INVOKABLE bool syncIsPaused();

View file

@ -25,7 +25,7 @@ class User : public QObject
Q_PROPERTY(QUrl statusIcon READ statusIcon NOTIFY statusChanged) Q_PROPERTY(QUrl statusIcon READ statusIcon NOTIFY statusChanged)
Q_PROPERTY(QString statusEmoji READ statusEmoji NOTIFY statusChanged) Q_PROPERTY(QString statusEmoji READ statusEmoji NOTIFY statusChanged)
Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY statusChanged) Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY statusChanged)
Q_PROPERTY(QString desktopNotificationsAllowed READ isDesktopNotificationsAllowed NOTIFY desktopNotificationsAllowedChanged) Q_PROPERTY(bool desktopNotificationsAllowed READ isDesktopNotificationsAllowed NOTIFY desktopNotificationsAllowedChanged)
Q_PROPERTY(bool hasLocalFolder READ hasLocalFolder NOTIFY hasLocalFolderChanged) Q_PROPERTY(bool hasLocalFolder READ hasLocalFolder NOTIFY hasLocalFolderChanged)
Q_PROPERTY(bool serverHasTalk READ serverHasTalk NOTIFY serverHasTalkChanged) Q_PROPERTY(bool serverHasTalk READ serverHasTalk NOTIFY serverHasTalkChanged)
Q_PROPERTY(QString avatar READ avatarUrl NOTIFY avatarChanged) Q_PROPERTY(QString avatar READ avatarUrl NOTIFY avatarChanged)
@ -67,7 +67,7 @@ signals:
void hasLocalFolderChanged(); void hasLocalFolderChanged();
void serverHasTalkChanged(); void serverHasTalkChanged();
void avatarChanged(); void avatarChanged();
void accountStateChanged(int state); void accountStateChanged();
void statusChanged(); void statusChanged();
void desktopNotificationsAllowedChanged(); void desktopNotificationsAllowedChanged();

View file

@ -14,10 +14,13 @@ import com.nextcloud.desktopclient 1.0
Window { Window {
id: trayWindow id: trayWindow
width: Style.trayWindowWidth title: Systray.windowTitle
// If the main dialog is displayed as a regular window we want it to be quadratic
width: Systray.useNormalWindow ? Style.trayWindowHeight : Style.trayWindowWidth
height: Style.trayWindowHeight height: Style.trayWindowHeight
color: "transparent" color: "transparent"
flags: Qt.Dialog | Qt.FramelessWindowHint flags: Qt.WindowTitleHint | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | (Systray.useNormalWindow ? Qt.Dialog : Qt.Dialog | Qt.FramelessWindowHint)
readonly property int maxMenuHeight: Style.trayWindowHeight - Style.trayWindowHeaderHeight - 2 * Style.trayWindowBorderWidth readonly property int maxMenuHeight: Style.trayWindowHeight - Style.trayWindowHeaderHeight - 2 * Style.trayWindowBorderWidth
@ -25,10 +28,14 @@ Window {
// Close tray window when focus is lost (e.g. click somewhere else on the screen) // Close tray window when focus is lost (e.g. click somewhere else on the screen)
onActiveChanged: { onActiveChanged: {
if(!active) { if (!Systray.useNormalWindow && !active) {
trayWindow.hide(); hide();
Systray.setClosed(); setClosed();
} }
}
onClosing: {
Systray.setClosed()
} }
onVisibleChanged: { onVisibleChanged: {
@ -51,7 +58,9 @@ Window {
accountMenu.close(); accountMenu.close();
appsMenu.close(); appsMenu.close();
Systray.positionWindow(trayWindow); if (!Systray.useNormalWindow) {
Systray.positionWindow(trayWindow);
}
trayWindow.show(); trayWindow.show();
trayWindow.raise(); trayWindow.raise();
@ -75,7 +84,7 @@ Window {
maskSource: Rectangle { maskSource: Rectangle {
width: trayWindowBackground.width width: trayWindowBackground.width
height: trayWindowBackground.height height: trayWindowBackground.height
radius: trayWindowBackground.radius radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius
} }
} }
@ -83,7 +92,7 @@ Window {
id: trayWindowBackground id: trayWindowBackground
anchors.fill: parent anchors.fill: parent
radius: Style.trayWindowRadius radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius
border.width: Style.trayWindowBorderWidth border.width: Style.trayWindowBorderWidth
border.color: Style.menuBorder border.color: Style.menuBorder
@ -411,6 +420,11 @@ Window {
} }
} }
// Add space between items
Item {
Layout.fillWidth: true
}
RowLayout { RowLayout {
id: openLocalFolderRowLayout id: openLocalFolderRowLayout
spacing: 0 spacing: 0

View file

@ -50,7 +50,8 @@
#define DEFAULT_MAX_LOG_LINES 20000 #define DEFAULT_MAX_LOG_LINES 20000
namespace { namespace {
static constexpr char allowChecksumValidationFailC[] = "allowChecksumValidationFail"; static constexpr char allowChecksumValidationFailC[] = "allowChecksumValidationFail";
static constexpr char showMainDialogAsNormalWindowC[] = "showMainDialogAsNormalWindow";
} }
namespace OCC { namespace OCC {
@ -896,6 +897,10 @@ bool ConfigFile::allowChecksumValidationFail() const
return getValue(allowChecksumValidationFailC, {}, false).toBool(); return getValue(allowChecksumValidationFailC, {}, false).toBool();
} }
bool ConfigFile::showMainDialogAsNormalWindow() const {
return getValue(showMainDialogAsNormalWindowC, {}, false).toBool();
}
bool ConfigFile::promptDeleteFiles() const bool ConfigFile::promptDeleteFiles() const
{ {
QSettings settings(configFile(), QSettings::IniFormat); QSettings settings(configFile(), QSettings::IniFormat);

View file

@ -148,6 +148,8 @@ public:
/** should we allow checksum validation to fail? set to true to workaround corrupted checksums **/ /** should we allow checksum validation to fail? set to true to workaround corrupted checksums **/
bool allowChecksumValidationFail() const; bool allowChecksumValidationFail() const;
bool showMainDialogAsNormalWindow() const;
static bool setConfDir(const QString &value); static bool setConfDir(const QString &value);
bool optionalServerNotifications() const; bool optionalServerNotifications() const;