diff --git a/doc/conffile.rst b/doc/conffile.rst index b5fa66157..6fa99e33c 100644 --- a/doc/conffile.rst +++ b/doc/conffile.rst @@ -33,33 +33,35 @@ Some interesting values that can be set on the configuration file are: +---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``[General]`` section | -+=================================+===============+=================================================================================================================+ -| Variable | Default | Meaning | -+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ -| ``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). | -+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ -| ``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. | -+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ -| ``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. | -| | | 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. | -+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ -| ``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. | -| | | This option only works on linux | -+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ -| ``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 | -| | | options that can be used to opt in to experimental features. | -+---------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``[General]`` section | ++==================================+===============+=================================================================================================================+ +| Variable | Default | Meaning | ++----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +| ``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). | ++----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +| ``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. | ++----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +| ``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. | +| | | 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. | ++----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +| ``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. | +| | | This option only works on linux | ++----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +| ``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 | +| | | 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. | ++----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/src/gui/application.cpp b/src/gui/application.cpp index d23be5c14..bce4e9afe 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -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"; return; } - showMainDialog(); + + // Show the main dialog only if there is at least one account configured + if (!AccountManager::instance()->accounts().isEmpty()) { + showMainDialog(); + } else { + _gui->slotNewAccountWizard(); + } } } diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 8246528cd..a7a47e16e 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -176,7 +176,7 @@ int main(int argc, char **argv) if (QSystemTrayIcon::isSystemTrayAvailable()) { app.tryTrayAgain(); - } else if (!app.backgroundMode()) { + } else if (!app.backgroundMode() && !AccountManager::instance()->accounts().isEmpty()) { if (desktopSession != "ubuntu") { qCInfo(lcApplication) << "System tray still not available, showing window and trying again later"; app.showMainDialog(); diff --git a/src/gui/owncloudgui.h b/src/gui/owncloudgui.h index cd664e0a8..312c43748 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/owncloudgui.h @@ -107,10 +107,11 @@ public slots: void slotRemoveDestroyedShareDialogs(); + void slotNewAccountWizard(); + private slots: void slotLogin(); void slotLogout(); - void slotNewAccountWizard(); private: QPointer _tray; diff --git a/src/gui/systray.cpp b/src/gui/systray.cpp index c8d33f982..6b9f46ee2 100644 --- a/src/gui/systray.cpp +++ b/src/gui/systray.cpp @@ -18,6 +18,7 @@ #include "config.h" #include "common/utility.h" #include "tray/UserModel.h" +#include "configfile.h" #include #include @@ -197,6 +198,21 @@ bool Systray::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() { _isOpen = true; @@ -258,8 +274,10 @@ void Systray::positionWindow(QQuickWindow *window) const { window->setScreen(currentScreen()); - const auto position = computeWindowPosition(window->width(), window->height()); - window->setPosition(position); + if (useNormalWindow()) { + const auto position = computeWindowPosition(window->width(), window->height()); + window->setPosition(position); + } } void Systray::forceWindowInit(QQuickWindow *window) const diff --git a/src/gui/systray.h b/src/gui/systray.h index df15154ba..a55977f7c 100644 --- a/src/gui/systray.h +++ b/src/gui/systray.h @@ -24,6 +24,7 @@ class QScreen; class QQmlApplicationEngine; class QQuickWindow; class QWindow; +class QQuickWindow; namespace OCC { @@ -41,6 +42,10 @@ class Systray : public QSystemTrayIcon { Q_OBJECT + + Q_PROPERTY(QString windowTitle READ windowTitle CONSTANT) + Q_PROPERTY(bool useNormalWindow READ useNormalWindow CONSTANT) + public: static Systray *instance(); virtual ~Systray() = default; @@ -53,6 +58,8 @@ public: void showMessage(const QString &title, const QString &message, MessageIcon icon = Information); void setToolTip(const QString &tip); bool isOpen(); + QString windowTitle() const; + bool useNormalWindow() const; Q_INVOKABLE void pauseResumeSync(); Q_INVOKABLE bool syncIsPaused(); diff --git a/src/gui/tray/UserModel.h b/src/gui/tray/UserModel.h index 2e57d0844..b1a97da2a 100644 --- a/src/gui/tray/UserModel.h +++ b/src/gui/tray/UserModel.h @@ -25,7 +25,7 @@ class User : public QObject Q_PROPERTY(QUrl statusIcon READ statusIcon NOTIFY statusChanged) Q_PROPERTY(QString statusEmoji READ statusEmoji 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 serverHasTalk READ serverHasTalk NOTIFY serverHasTalkChanged) Q_PROPERTY(QString avatar READ avatarUrl NOTIFY avatarChanged) @@ -67,7 +67,7 @@ signals: void hasLocalFolderChanged(); void serverHasTalkChanged(); void avatarChanged(); - void accountStateChanged(int state); + void accountStateChanged(); void statusChanged(); void desktopNotificationsAllowedChanged(); diff --git a/src/gui/tray/Window.qml b/src/gui/tray/Window.qml index 6bfe020fa..48e188db2 100644 --- a/src/gui/tray/Window.qml +++ b/src/gui/tray/Window.qml @@ -14,10 +14,13 @@ import com.nextcloud.desktopclient 1.0 Window { 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 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 @@ -25,10 +28,14 @@ Window { // Close tray window when focus is lost (e.g. click somewhere else on the screen) onActiveChanged: { - if(!active) { - trayWindow.hide(); - Systray.setClosed(); + if (!Systray.useNormalWindow && !active) { + hide(); + setClosed(); } + } + + onClosing: { + Systray.setClosed() } onVisibleChanged: { @@ -51,7 +58,9 @@ Window { accountMenu.close(); appsMenu.close(); - Systray.positionWindow(trayWindow); + if (!Systray.useNormalWindow) { + Systray.positionWindow(trayWindow); + } trayWindow.show(); trayWindow.raise(); @@ -75,7 +84,7 @@ Window { maskSource: Rectangle { width: trayWindowBackground.width height: trayWindowBackground.height - radius: trayWindowBackground.radius + radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius } } @@ -83,7 +92,7 @@ Window { id: trayWindowBackground anchors.fill: parent - radius: Style.trayWindowRadius + radius: Systray.useNormalWindow ? 0.0 : Style.trayWindowRadius border.width: Style.trayWindowBorderWidth border.color: Style.menuBorder @@ -411,6 +420,11 @@ Window { } } + // Add space between items + Item { + Layout.fillWidth: true + } + RowLayout { id: openLocalFolderRowLayout spacing: 0 diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index 954018a19..24986f3cb 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -50,7 +50,8 @@ #define DEFAULT_MAX_LOG_LINES 20000 namespace { - static constexpr char allowChecksumValidationFailC[] = "allowChecksumValidationFail"; +static constexpr char allowChecksumValidationFailC[] = "allowChecksumValidationFail"; +static constexpr char showMainDialogAsNormalWindowC[] = "showMainDialogAsNormalWindow"; } namespace OCC { @@ -896,6 +897,10 @@ bool ConfigFile::allowChecksumValidationFail() const return getValue(allowChecksumValidationFailC, {}, false).toBool(); } +bool ConfigFile::showMainDialogAsNormalWindow() const { + return getValue(showMainDialogAsNormalWindowC, {}, false).toBool(); +} + bool ConfigFile::promptDeleteFiles() const { QSettings settings(configFile(), QSettings::IniFormat); diff --git a/src/libsync/configfile.h b/src/libsync/configfile.h index 537bfec0c..5f288bede 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -148,6 +148,8 @@ public: /** should we allow checksum validation to fail? set to true to workaround corrupted checksums **/ bool allowChecksumValidationFail() const; + bool showMainDialogAsNormalWindow() const; + static bool setConfDir(const QString &value); bool optionalServerNotifications() const;