## Theming options
-set( APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR "#0082c9" CACHE STRING "Hex color of the wizard header background")
+set(NEXTCLOUD_BACKGROUND_COLOR "#0082c9" CACHE STRING "Default Nextcloud background color")
+set( APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR ${NEXTCLOUD_BACKGROUND_COLOR} CACHE STRING "Hex color of the wizard header background")
set( APPLICATION_WIZARD_HEADER_TITLE_COLOR "#ffffff" CACHE STRING "Hex color of the text in the wizard header")
option( APPLICATION_WIZARD_USE_CUSTOM_LOGO "Use the logo from ':/client/theme/colored/wizard_logo.(png|svg)' else the default application icon is used" ON )
#cmakedefine APPLICATION_SERVER_URL_ENFORCE "@APPLICATION_SERVER_URL_ENFORCE@"
#cmakedefine LINUX_APPLICATION_ID "@LINUX_APPLICATION_ID@"
#cmakedefine APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR "@APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR@"
+#cmakedefine NEXTCLOUD_BACKGROUND_COLOR "@NEXTCLOUD_BACKGROUND_COLOR@"
#cmakedefine APPLICATION_WIZARD_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@"
#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@"
#cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@"
wizard/owncloudsetupnocredspage.ui
wizard/owncloudwizardresultpage.ui
wizard/webview.ui
+ wizard/welcomepage.ui
)
set(client_SRCS
wizard/webviewpage.cpp
wizard/webview.cpp
wizard/slideshow.cpp
+ wizard/welcomepage.cpp
+ wizard/linklabel.cpp
)
IF(BUILD_UPDATER)
_ocWizard->setRemoteFolder(_remoteFolder);
- _ocWizard->setStartId(WizardCommon::Page_ServerSetup);
+#ifdef WITH_PROVIDERS
+ const auto startPage = WizardCommon::Page_Welcome;
+#else // WITH_PROVIDERS
+ const auto startPage = WizardCommon::Page_ServerSetup;
+#endif // WITH_PROVIDERS
+ _ocWizard->setStartId(startPage);
_ocWizard->restart();
--- /dev/null
+/*
+ * Copyright (C) 2021 by Felix Weilbach <felix.weilbach@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "linklabel.h"
+#include "guiutility.h"
+
+namespace OCC {
+
+LinkLabel::LinkLabel(QWidget *parent) : QLabel(parent)
+{
+
+}
+
+void LinkLabel::setUrl(const QUrl &url)
+{
+ this->url = url;
+}
+
+void LinkLabel::enterEvent(QEvent * /*event*/)
+{
+ setFontUnderline(true);
+ setCursor(Qt::PointingHandCursor);
+}
+
+void LinkLabel::leaveEvent(QEvent * /*event*/)
+{
+ setFontUnderline(false);
+ setCursor(Qt::ArrowCursor);
+}
+
+void LinkLabel::mouseReleaseEvent(QMouseEvent * /*event*/)
+{
+ if (url.isValid()) {
+ Utility::openBrowser(url);
+ }
+
+ emit clicked();
+}
+
+void LinkLabel::setFontUnderline(bool value)
+{
+ auto labelFont = font();
+ labelFont.setUnderline(value);
+ setFont(labelFont);
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2021 by Felix Weilbach <felix.weilbach@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#pragma once
+
+#include <QLabel>
+#include <QUrl>
+
+namespace OCC {
+
+class LinkLabel : public QLabel
+{
+ Q_OBJECT
+public:
+ explicit LinkLabel(QWidget *parent = nullptr);
+
+ void setUrl(const QUrl &url);
+
+signals:
+ void clicked();
+
+protected:
+ void enterEvent(QEvent *event) override;
+
+ void leaveEvent(QEvent *event) override;
+
+ void mouseReleaseEvent(QMouseEvent *event) override;
+
+private:
+ void setFontUnderline(bool value);
+
+ QUrl url;
+};
+
+}
#include "owncloudgui.h"
#include "wizard/owncloudwizard.h"
+#include "wizard/welcomepage.h"
#include "wizard/owncloudsetuppage.h"
#include "wizard/owncloudhttpcredspage.h"
#include "wizard/owncloudoauthcredspage.h"
OwncloudWizard::OwncloudWizard(QWidget *parent)
: QWizard(parent)
, _account(nullptr)
+#ifdef WITH_PROVIDERS
+ , _welcomePage(new WelcomePage(this))
+#endif // WITH_PROVIDERS
, _setupPage(new OwncloudSetupPage(this))
, _httpCredsPage(new OwncloudHttpCredsPage(this))
, _browserCredsPage(new OwncloudOAuthCredsPage)
setObjectName("owncloudWizard");
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+#ifdef WITH_PROVIDERS
+ setPage(WizardCommon::Page_Welcome, _welcomePage);
+#endif // WITH_PROVIDERS
setPage(WizardCommon::Page_ServerSetup, _setupPage);
setPage(WizardCommon::Page_HttpCreds, _httpCredsPage);
setPage(WizardCommon::Page_OAuthCreds, _browserCredsPage);
setSubTitleFormat(Qt::RichText);
setButtonText(QWizard::CustomButton1, tr("Skip folders configuration"));
+ // Change the next buttons size policy since we hide it on the
+ // welcome page but want it to fill it's space that we don't get
+ // flickering when the page changes
+ auto nextButtonSizePolicy = button(QWizard::NextButton)->sizePolicy();
+ nextButtonSizePolicy.setRetainSizeWhenHidden(true);
+ button(QWizard::NextButton)->setSizePolicy(nextButtonSizePolicy);
// Connect styleChanged events to our widgets, so they can adapt (Dark-/Light-Mode switching)
connect(this, &OwncloudWizard::styleChanged, _setupPage, &OwncloudSetupPage::slotStyleChanged);
{
qCDebug(lcWizard) << "Current Wizard page changed to " << id;
+ const auto setNextButtonAsDefault = [this]() {
+ auto nextButton = qobject_cast<QPushButton *>(button(QWizard::NextButton));
+ if (nextButton) {
+ nextButton->setDefault(true);
+ nextButton->setFocus();
+ }
+ };
+
+ if (id == WizardCommon::Page_Welcome) {
+ // Set next button to just hidden so it retains it's layout
+ button(QWizard::NextButton)->setHidden(true);
+ // Need to set it from here, otherwise it has no effect
+ _welcomePage->setLoginButtonDefault();
+ } else if (id == WizardCommon::Page_WebView || id == WizardCommon::Page_Flow2AuthCreds) {
+ setButtonLayout({ QWizard::Stretch, QWizard::BackButton });
+ } else if (id == WizardCommon::Page_AdvancedSetup) {
+ setButtonLayout({ QWizard::Stretch, QWizard::CustomButton1, QWizard::BackButton, QWizard::NextButton });
+ setNextButtonAsDefault();
+ } else {
+ setButtonLayout({ QWizard::Stretch, QWizard::BackButton, QWizard::NextButton });
+ setNextButtonAsDefault();
+ }
+
if (id == WizardCommon::Page_ServerSetup) {
emit clearPendingRequests();
}
done(Accepted);
}
- setOption(QWizard::HaveCustomButton1, id == WizardCommon::Page_AdvancedSetup);
if (id == WizardCommon::Page_AdvancedSetup && (_credentialsPage == _browserCredsPage || _credentialsPage == _flow2CredsPage)) {
// For OAuth, disable the back button in the Page_AdvancedSetup because we don't want
// to re-open the browser.
Q_DECLARE_LOGGING_CATEGORY(lcWizard)
+class WelcomePage;
class OwncloudSetupPage;
class OwncloudHttpCredsPage;
class OwncloudOAuthCredsPage;
void customizeStyle();
AccountPtr _account;
+ WelcomePage *_welcomePage;
OwncloudSetupPage *_setupPage;
OwncloudHttpCredsPage *_httpCredsPage;
OwncloudOAuthCredsPage *_browserCredsPage;
#include <QLabel>
#include <QPixmap>
#include <QVariant>
+#include <QRadioButton>
+#include <QAbstractButton>
+#include <QCheckBox>
+#include <QSpinBox>
#include "wizard/owncloudwizardcommon.h"
#include "theme.h"
errorLabel->setVisible(false);
}
+ void customizeHintLabel(QLabel *label)
+ {
+ auto palette = label->palette();
+ QColor textColor = palette.color(QPalette::Text);
+ textColor.setAlpha(128);
+ palette.setColor(QPalette::Text, textColor);
+ label->setPalette(palette);
+ }
+
} // ns WizardCommon
} // namespace OCC
class QVariant;
class QLabel;
+class QRadioButton;
+class QSpinBox;
+class QCheckBox;
+class QAbstractButton;
namespace OCC {
QString titleTemplate();
QString subTitleTemplate();
void initErrorLabel(QLabel *errorLabel);
+ void customizeHintLabel(QLabel *label);
enum SyncMode {
SelectiveMode,
};
enum Pages {
+ Page_Welcome,
Page_ServerSetup,
Page_HttpCreds,
Page_ShibbolethCreds,
--- /dev/null
+/*
+ * Copyright (C) 2021 by Felix Weilbach <felix.weilbach@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "welcomepage.h"
+#include "theme.h"
+#include "wizard/owncloudwizard.h"
+#include "wizard/slideshow.h"
+#include "ui_welcomepage.h"
+
+namespace OCC {
+
+WelcomePage::WelcomePage(OwncloudWizard *ocWizard)
+ : QWizardPage()
+ , _ui(new Ui::WelcomePage)
+ , _ocWizard(ocWizard)
+{
+ setupUi();
+}
+
+WelcomePage::~WelcomePage() = default;
+
+void WelcomePage::setupUi()
+{
+ _ui->setupUi(this);
+ setupSlideShow();
+ setupLoginButton();
+ setupCreateAccountButton();
+ setupHostYourOwnServerLabel();
+}
+
+void WelcomePage::initializePage()
+{
+ customizeStyle();
+}
+
+void WelcomePage::setLoginButtonDefault()
+{
+ _ui->loginButton->setDefault(true);
+ _ui->loginButton->setFocus();
+}
+
+void WelcomePage::styleSlideShow()
+{
+ const auto theme = Theme::instance();
+ const auto backgroundColor = palette().window().color();
+
+ const auto wizardNextcloudIconFileName = theme->isBranded() ? Theme::hidpiFileName("wizard-nextcloud.png", backgroundColor)
+ : Theme::hidpiFileName(":/client/theme/colored/wizard-nextcloud.png");
+ const auto wizardFilesIconFileName = theme->isBranded() ? Theme::hidpiFileName("wizard-files.png", backgroundColor)
+ : Theme::hidpiFileName(":/client/theme/colored/wizard-files.png");
+ const auto wizardGroupwareIconFileName = theme->isBranded() ? Theme::hidpiFileName("wizard-groupware.png", backgroundColor)
+ : Theme::hidpiFileName(":/client/theme/colored/wizard-groupware.png");
+ const auto wizardTalkIconFileName = theme->isBranded() ? Theme::hidpiFileName("wizard-talk.png", backgroundColor)
+ : Theme::hidpiFileName(":/client/theme/colored/wizard-talk.png");
+
+ _ui->slideShow->addSlide(wizardNextcloudIconFileName, tr("Keep your data secure and under your control"));
+ _ui->slideShow->addSlide(wizardFilesIconFileName, tr("Secure collaboration & file exchange"));
+ _ui->slideShow->addSlide(wizardGroupwareIconFileName, tr("Easy-to-use web mail, calendaring & contacts"));
+ _ui->slideShow->addSlide(wizardTalkIconFileName, tr("Screensharing, online meetings & web conferences"));
+
+ const auto isDarkBackground = Theme::isDarkColor(backgroundColor);
+ _ui->slideShowNextButton->setIcon(theme->uiThemeIcon(QString("control-next.svg"), isDarkBackground));
+ _ui->slideShowPreviousButton->setIcon(theme->uiThemeIcon(QString("control-prev.svg"), isDarkBackground));
+}
+
+void WelcomePage::setupSlideShow()
+{
+ connect(_ui->slideShow, &SlideShow::clicked, _ui->slideShow, &SlideShow::stopShow);
+ connect(_ui->slideShowNextButton, &QPushButton::clicked, _ui->slideShow, &SlideShow::nextSlide);
+ connect(_ui->slideShowPreviousButton, &QPushButton::clicked, _ui->slideShow, &SlideShow::prevSlide);
+}
+
+void WelcomePage::setupLoginButton()
+{
+ const auto appName = Theme::instance()->appNameGUI();
+
+ _ui->loginButton->setText(tr("Log in to your %1").arg(appName));
+ connect(_ui->loginButton, &QPushButton::clicked, this, [this](bool /*checked*/) {
+ _nextPage = WizardCommon::Page_ServerSetup;
+ _ocWizard->next();
+ });
+}
+
+void WelcomePage::setupCreateAccountButton()
+{
+ connect(_ui->createAccountButton, &QPushButton::clicked, this, [this](bool /*checked*/) {
+ _ocWizard->setRegistration(true);
+ _nextPage = WizardCommon::Page_WebView;
+ _ocWizard->next();
+ });
+}
+
+void WelcomePage::setupHostYourOwnServerLabel()
+{
+ _ui->hostYourOwnServerLabel->setText(tr("Host your own server"));
+ _ui->hostYourOwnServerLabel->setAlignment(Qt::AlignCenter);
+ _ui->hostYourOwnServerLabel->setUrl(QUrl("https://docs.nextcloud.com/server/latest/admin_manual/installation/#installation"));
+}
+
+int WelcomePage::nextId() const
+{
+ return _nextPage;
+}
+
+void WelcomePage::customizeStyle()
+{
+ styleSlideShow();
+}
+}
--- /dev/null
+/*
+ * Copyright (C) 2021 by Felix Weilbach <felix.weilbach@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#pragma once
+
+#include <QWizardPage>
+
+#include "wizard/owncloudwizardcommon.h"
+
+namespace OCC {
+
+class OwncloudWizard;
+
+namespace Ui {
+ class WelcomePage;
+}
+
+class WelcomePage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ explicit WelcomePage(OwncloudWizard *ocWizard);
+ ~WelcomePage() override;
+ int nextId() const override;
+ void initializePage() override;
+ void setLoginButtonDefault();
+
+private:
+ void setupUi();
+ void customizeStyle();
+ void styleSlideShow();
+ void setupSlideShow();
+ void setupLoginButton();
+ void setupCreateAccountButton();
+ void setupHostYourOwnServerLabel();
+
+ QScopedPointer<Ui::WelcomePage> _ui;
+
+ OwncloudWizard *_ocWizard;
+ WizardCommon::Pages _nextPage = WizardCommon::Page_ServerSetup;
+};
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OCC::WelcomePage</class>
+ <widget class="QWidget" name="OCC::WelcomePage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>500</width>
+ <height>500</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>80</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="slideShowPreviousButton">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="OCC::SlideShow" name="slideShow" native="true">
+ <property name="font">
+ <font>
+ <pointsize>12</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="slideShowNextButton">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="loginButton">
+ <property name="text">
+ <string>Log in to your %1</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="createAccountButton">
+ <property name="text">
+ <string>Create account with Provider</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="OCC::LinkLabel" name="hostYourOwnServerLabel" native="true"/>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>OCC::SlideShow</class>
+ <extends>QWidget</extends>
+ <header>wizard/slideshow.h</header>
+ </customwidget>
+ <customwidget>
+ <class>OCC::LinkLabel</class>
+ <extends>QWidget</extends>
+ <header>wizard/linklabel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
}
}
+bool Theme::isHidpi(QPaintDevice *dev)
+{
+ const auto devicePixelRatio = dev ? dev->devicePixelRatio() : qApp->primaryScreen()->devicePixelRatio();
+ return devicePixelRatio > 1;
+}
+
QIcon Theme::uiThemeIcon(const QString &iconName, bool uiHasDarkBg) const
{
QString themeResBasePath = ":/client/theme/";
QString Theme::hidpiFileName(const QString &fileName, QPaintDevice *dev)
{
- qreal devicePixelRatio = dev ? dev->devicePixelRatio() : qApp->primaryScreen()->devicePixelRatio();
- if (devicePixelRatio <= 1.0) {
+ if (!Theme::isHidpi(dev)) {
return fileName;
}
// try to find a 2x version
return fileName;
}
+QString Theme::hidpiFileName(const QString &iconName, const QColor &backgroundColor, QPaintDevice *dev)
+{
+ const auto isDarkBackground = Theme::isDarkColor(backgroundColor);
+
+ const QString themeResBasePath = ":/client/theme/";
+ const QString iconPath = themeResBasePath + (isDarkBackground ? "white/" : "black/") + iconName;
+
+ return Theme::hidpiFileName(iconPath, dev);
+}
+
#endif
return {APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR};
}
+QPixmap Theme::wizardApplicationLogo() const
+{
+ if (!Theme::isBranded()) {
+ return QPixmap(Theme::hidpiFileName(":/client/theme/colored/wizard-nextcloud.png"));
+ }
+#ifdef APPLICATION_WIZARD_USE_CUSTOM_LOGO
+ const auto useSvg = shouldPreferSvg();
+ const auto logoBasePath = QStringLiteral(":/client/theme/colored/wizard_logo");
+ if (useSvg) {
+ const auto maxHeight = Theme::isHidpi() ? 200 : 100;
+ const auto maxWidth = 2 * maxHeight;
+ const auto icon = QIcon(logoBasePath + ".svg");
+ const auto size = icon.actualSize(QSize(maxWidth, maxHeight));
+ return icon.pixmap(size);
+ } else {
+ return QPixmap(hidpiFileName(logoBasePath + ".png"));
+ }
+#else
+ const auto size = Theme::isHidpi() ?: 200 : 100;
+ return applicationIcon().pixmap(size);
+#endif
+}
+
QPixmap Theme::wizardHeaderLogo() const
{
#ifdef APPLICATION_WIZARD_USE_CUSTOM_LOGO
#ifndef TOKEN_AUTH_ONLY
static QString hidpiFileName(const QString &fileName, QPaintDevice *dev = nullptr);
+ static QString hidpiFileName(const QString &iconName, const QColor &backgroundColor, QPaintDevice *dev = nullptr);
+
+ static bool isHidpi(QPaintDevice *dev = nullptr);
+
/**
* get an sync state icon
*/
/** @return color for the setup wizard. */
virtual QColor wizardHeaderBackgroundColor() const;
+ virtual QPixmap wizardApplicationLogo() const;
+
/** @return logo for the setup wizard. */
virtual QPixmap wizardHeaderLogo() const;
STATIC
syncenginetestutils.cpp
pushnotificationstestutils.cpp
+ themeutils.cpp
)
target_link_libraries(testutils PUBLIC ${APPLICATION_EXECUTABLE}sync Qt5::Test)
nextcloud_add_test(FolderWatcher)
nextcloud_add_test(Capabilities)
nextcloud_add_test(PushNotifications)
+nextcloud_add_test(Theme)
if( UNIX AND NOT APPLE )
nextcloud_add_test(InotifyWatcher)
--- /dev/null
+/*
+ * Copyright (C) 2021 by Felix Weilbach <felix.weilbach@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <QTest>
+
+#include "theme.h"
+#include "themeutils.h"
+
+class TestTheme : public QObject
+{
+ Q_OBJECT
+
+public:
+ TestTheme()
+ {
+ Q_INIT_RESOURCE(resources);
+ Q_INIT_RESOURCE(theme);
+ }
+
+private slots:
+ void testHidpiFileName_darkBackground_returnPathToWhiteIcon()
+ {
+ FakePaintDevice paintDevice;
+ const QColor backgroundColor("#000000");
+ const QString iconName("icon-name");
+
+ const auto iconPath = OCC::Theme::hidpiFileName(iconName + ".png", backgroundColor, &paintDevice);
+
+ QCOMPARE(iconPath, ":/client/theme/white/" + iconName + ".png");
+ }
+
+ void testHidpiFileName_lightBackground_returnPathToBlackIcon()
+ {
+ FakePaintDevice paintDevice;
+ const QColor backgroundColor("#ffffff");
+ const QString iconName("icon-name");
+
+ const auto iconPath = OCC::Theme::hidpiFileName(iconName + ".png", backgroundColor, &paintDevice);
+
+ QCOMPARE(iconPath, ":/client/theme/black/" + iconName + ".png");
+ }
+
+ void testHidpiFileName_hidpiDevice_returnHidpiIconPath()
+ {
+ FakePaintDevice paintDevice;
+ paintDevice.setHidpi(true);
+ const QColor backgroundColor("#000000");
+ const QString iconName("wizard-files");
+
+ const auto iconPath = OCC::Theme::hidpiFileName(iconName + ".png", backgroundColor, &paintDevice);
+
+ QCOMPARE(iconPath, ":/client/theme/white/" + iconName + "@2x.png");
+ }
+
+ void testIsDarkColor_nextcloudBlue_returnTrue()
+ {
+ const QColor color(0, 130, 201);
+
+ const auto result = OCC::Theme::isDarkColor(color);
+
+ QCOMPARE(result, true);
+ }
+
+ void testIsDarkColor_lightColor_returnFalse()
+ {
+ const QColor color(255, 255, 255);
+
+ const auto result = OCC::Theme::isDarkColor(color);
+
+ QCOMPARE(result, false);
+ }
+
+ void testIsDarkColor_darkColor_returnTrue()
+ {
+ const QColor color(0, 0, 0);
+
+ const auto result = OCC::Theme::isDarkColor(color);
+
+ QCOMPARE(result, true);
+ }
+
+ void testIsHidpi_hidpi_returnTrue()
+ {
+ FakePaintDevice paintDevice;
+ paintDevice.setHidpi(true);
+
+ QCOMPARE(OCC::Theme::isHidpi(&paintDevice), true);
+ }
+
+ void testIsHidpi_lowdpi_returnFalse()
+ {
+ FakePaintDevice paintDevice;
+ paintDevice.setHidpi(false);
+
+ QCOMPARE(OCC::Theme::isHidpi(&paintDevice), false);
+ }
+};
+
+QTEST_GUILESS_MAIN(TestTheme)
+#include "testtheme.moc"
--- /dev/null
+/*
+ * Copyright (C) 2021 by Felix Weilbach <felix.weilbach@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "themeutils.h"
+
+FakePaintDevice::FakePaintDevice() = default;
+
+QPaintEngine *FakePaintDevice::paintEngine() const
+{
+ return nullptr;
+}
+
+void FakePaintDevice::setHidpi(bool value)
+{
+ _hidpi = value;
+}
+
+int FakePaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ switch (metric) {
+ case QPaintDevice::PdmDevicePixelRatio:
+ if (_hidpi) {
+ return 2;
+ }
+ return 1;
+ default:
+ return QPaintDevice::metric(metric);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#pragma once
+
+#include <QPaintDevice>
+#include <QTest>
+
+class FakePaintDevice : public QPaintDevice
+{
+public:
+ FakePaintDevice();
+
+ QPaintEngine *paintEngine() const override;
+
+ void setHidpi(bool value);
+
+protected:
+ int metric(QPaintDevice::PaintDeviceMetric metric) const override;
+
+private:
+ bool _hidpi = false;
+};