Split out wizard welcome page

Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
This commit is contained in:
Felix Weilbach 2021-02-16 10:20:04 +01:00
parent 05d2a87840
commit 9185956069
19 changed files with 809 additions and 5 deletions

View file

@ -34,7 +34,8 @@ option( WITH_PROVIDERS "Build with providers list" ON )
## Theming options ## 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") 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 ) 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 )

View file

@ -25,6 +25,7 @@
#cmakedefine APPLICATION_SERVER_URL_ENFORCE "@APPLICATION_SERVER_URL_ENFORCE@" #cmakedefine APPLICATION_SERVER_URL_ENFORCE "@APPLICATION_SERVER_URL_ENFORCE@"
#cmakedefine LINUX_APPLICATION_ID "@LINUX_APPLICATION_ID@" #cmakedefine LINUX_APPLICATION_ID "@LINUX_APPLICATION_ID@"
#cmakedefine APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR "@APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR@" #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_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@"
#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@" #cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@"
#cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@" #cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@"

View file

@ -51,6 +51,7 @@ set(client_UI_SRCS
wizard/owncloudsetupnocredspage.ui wizard/owncloudsetupnocredspage.ui
wizard/owncloudwizardresultpage.ui wizard/owncloudwizardresultpage.ui
wizard/webview.ui wizard/webview.ui
wizard/welcomepage.ui
) )
set(client_SRCS set(client_SRCS
@ -134,6 +135,8 @@ set(client_SRCS
wizard/webviewpage.cpp wizard/webviewpage.cpp
wizard/webview.cpp wizard/webview.cpp
wizard/slideshow.cpp wizard/slideshow.cpp
wizard/welcomepage.cpp
wizard/linklabel.cpp
) )
IF(BUILD_UPDATER) IF(BUILD_UPDATER)

View file

@ -131,7 +131,12 @@ void OwncloudSetupWizard::startWizard()
_ocWizard->setRemoteFolder(_remoteFolder); _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(); _ocWizard->restart();

View file

@ -0,0 +1,58 @@
/*
* 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);
}
}

View file

@ -0,0 +1,46 @@
/*
* 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;
};
}

View file

@ -20,6 +20,7 @@
#include "owncloudgui.h" #include "owncloudgui.h"
#include "wizard/owncloudwizard.h" #include "wizard/owncloudwizard.h"
#include "wizard/welcomepage.h"
#include "wizard/owncloudsetuppage.h" #include "wizard/owncloudsetuppage.h"
#include "wizard/owncloudhttpcredspage.h" #include "wizard/owncloudhttpcredspage.h"
#include "wizard/owncloudoauthcredspage.h" #include "wizard/owncloudoauthcredspage.h"
@ -46,6 +47,9 @@ Q_LOGGING_CATEGORY(lcWizard, "nextcloud.gui.wizard", QtInfoMsg)
OwncloudWizard::OwncloudWizard(QWidget *parent) OwncloudWizard::OwncloudWizard(QWidget *parent)
: QWizard(parent) : QWizard(parent)
, _account(nullptr) , _account(nullptr)
#ifdef WITH_PROVIDERS
, _welcomePage(new WelcomePage(this))
#endif // WITH_PROVIDERS
, _setupPage(new OwncloudSetupPage(this)) , _setupPage(new OwncloudSetupPage(this))
, _httpCredsPage(new OwncloudHttpCredsPage(this)) , _httpCredsPage(new OwncloudHttpCredsPage(this))
, _browserCredsPage(new OwncloudOAuthCredsPage) , _browserCredsPage(new OwncloudOAuthCredsPage)
@ -57,6 +61,9 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
setObjectName("owncloudWizard"); setObjectName("owncloudWizard");
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
#ifdef WITH_PROVIDERS
setPage(WizardCommon::Page_Welcome, _welcomePage);
#endif // WITH_PROVIDERS
setPage(WizardCommon::Page_ServerSetup, _setupPage); setPage(WizardCommon::Page_ServerSetup, _setupPage);
setPage(WizardCommon::Page_HttpCreds, _httpCredsPage); setPage(WizardCommon::Page_HttpCreds, _httpCredsPage);
setPage(WizardCommon::Page_OAuthCreds, _browserCredsPage); setPage(WizardCommon::Page_OAuthCreds, _browserCredsPage);
@ -94,6 +101,12 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
setSubTitleFormat(Qt::RichText); setSubTitleFormat(Qt::RichText);
setButtonText(QWizard::CustomButton1, tr("Skip folders configuration")); 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 styleChanged events to our widgets, so they can adapt (Dark-/Light-Mode switching)
connect(this, &OwncloudWizard::styleChanged, _setupPage, &OwncloudSetupPage::slotStyleChanged); connect(this, &OwncloudWizard::styleChanged, _setupPage, &OwncloudSetupPage::slotStyleChanged);
@ -220,6 +233,29 @@ void OwncloudWizard::slotCurrentPageChanged(int id)
{ {
qCDebug(lcWizard) << "Current Wizard page changed to " << id; 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) { if (id == WizardCommon::Page_ServerSetup) {
emit clearPendingRequests(); emit clearPendingRequests();
} }
@ -232,7 +268,6 @@ void OwncloudWizard::slotCurrentPageChanged(int id)
done(Accepted); done(Accepted);
} }
setOption(QWizard::HaveCustomButton1, id == WizardCommon::Page_AdvancedSetup);
if (id == WizardCommon::Page_AdvancedSetup && (_credentialsPage == _browserCredsPage || _credentialsPage == _flow2CredsPage)) { if (id == WizardCommon::Page_AdvancedSetup && (_credentialsPage == _browserCredsPage || _credentialsPage == _flow2CredsPage)) {
// For OAuth, disable the back button in the Page_AdvancedSetup because we don't want // For OAuth, disable the back button in the Page_AdvancedSetup because we don't want
// to re-open the browser. // to re-open the browser.

View file

@ -29,6 +29,7 @@ namespace OCC {
Q_DECLARE_LOGGING_CATEGORY(lcWizard) Q_DECLARE_LOGGING_CATEGORY(lcWizard)
class WelcomePage;
class OwncloudSetupPage; class OwncloudSetupPage;
class OwncloudHttpCredsPage; class OwncloudHttpCredsPage;
class OwncloudOAuthCredsPage; class OwncloudOAuthCredsPage;
@ -115,6 +116,7 @@ private:
void customizeStyle(); void customizeStyle();
AccountPtr _account; AccountPtr _account;
WelcomePage *_welcomePage;
OwncloudSetupPage *_setupPage; OwncloudSetupPage *_setupPage;
OwncloudHttpCredsPage *_httpCredsPage; OwncloudHttpCredsPage *_httpCredsPage;
OwncloudOAuthCredsPage *_browserCredsPage; OwncloudOAuthCredsPage *_browserCredsPage;

View file

@ -16,6 +16,10 @@
#include <QLabel> #include <QLabel>
#include <QPixmap> #include <QPixmap>
#include <QVariant> #include <QVariant>
#include <QRadioButton>
#include <QAbstractButton>
#include <QCheckBox>
#include <QSpinBox>
#include "wizard/owncloudwizardcommon.h" #include "wizard/owncloudwizardcommon.h"
#include "theme.h" #include "theme.h"
@ -68,6 +72,15 @@ namespace WizardCommon {
errorLabel->setVisible(false); 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 } // ns WizardCommon
} // namespace OCC } // namespace OCC

View file

@ -18,6 +18,10 @@
class QVariant; class QVariant;
class QLabel; class QLabel;
class QRadioButton;
class QSpinBox;
class QCheckBox;
class QAbstractButton;
namespace OCC { namespace OCC {
@ -27,6 +31,7 @@ namespace WizardCommon {
QString titleTemplate(); QString titleTemplate();
QString subTitleTemplate(); QString subTitleTemplate();
void initErrorLabel(QLabel *errorLabel); void initErrorLabel(QLabel *errorLabel);
void customizeHintLabel(QLabel *label);
enum SyncMode { enum SyncMode {
SelectiveMode, SelectiveMode,
@ -34,6 +39,7 @@ namespace WizardCommon {
}; };
enum Pages { enum Pages {
Page_Welcome,
Page_ServerSetup, Page_ServerSetup,
Page_HttpCreds, Page_HttpCreds,
Page_ShibbolethCreds, Page_ShibbolethCreds,

View file

@ -0,0 +1,120 @@
/*
* 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();
}
}

View file

@ -0,0 +1,54 @@
/*
* 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;
};
}

View file

@ -0,0 +1,229 @@
<?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>

View file

@ -246,6 +246,12 @@ QString Theme::themeImagePath(const QString &name, int size, bool sysTray) const
} }
} }
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 QIcon Theme::uiThemeIcon(const QString &iconName, bool uiHasDarkBg) const
{ {
QString themeResBasePath = ":/client/theme/"; QString themeResBasePath = ":/client/theme/";
@ -256,8 +262,7 @@ QIcon Theme::uiThemeIcon(const QString &iconName, bool uiHasDarkBg) const
QString Theme::hidpiFileName(const QString &fileName, QPaintDevice *dev) QString Theme::hidpiFileName(const QString &fileName, QPaintDevice *dev)
{ {
qreal devicePixelRatio = dev ? dev->devicePixelRatio() : qApp->primaryScreen()->devicePixelRatio(); if (!Theme::isHidpi(dev)) {
if (devicePixelRatio <= 1.0) {
return fileName; return fileName;
} }
// try to find a 2x version // try to find a 2x version
@ -274,6 +279,16 @@ QString Theme::hidpiFileName(const QString &fileName, QPaintDevice *dev)
return fileName; 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 #endif
@ -541,6 +556,29 @@ QColor Theme::wizardHeaderBackgroundColor() const
return {APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR}; 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 QPixmap Theme::wizardHeaderLogo() const
{ {
#ifdef APPLICATION_WIZARD_USE_CUSTOM_LOGO #ifdef APPLICATION_WIZARD_USE_CUSTOM_LOGO

View file

@ -132,6 +132,10 @@ public:
#ifndef TOKEN_AUTH_ONLY #ifndef TOKEN_AUTH_ONLY
static QString hidpiFileName(const QString &fileName, QPaintDevice *dev = nullptr); 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 * get an sync state icon
*/ */
@ -231,6 +235,8 @@ public:
/** @return color for the setup wizard. */ /** @return color for the setup wizard. */
virtual QColor wizardHeaderBackgroundColor() const; virtual QColor wizardHeaderBackgroundColor() const;
virtual QPixmap wizardApplicationLogo() const;
/** @return logo for the setup wizard. */ /** @return logo for the setup wizard. */
virtual QPixmap wizardHeaderLogo() const; virtual QPixmap wizardHeaderLogo() const;

View file

@ -9,6 +9,7 @@ add_library(testutils
STATIC STATIC
syncenginetestutils.cpp syncenginetestutils.cpp
pushnotificationstestutils.cpp pushnotificationstestutils.cpp
themeutils.cpp
) )
target_link_libraries(testutils PUBLIC ${APPLICATION_EXECUTABLE}sync Qt5::Test) target_link_libraries(testutils PUBLIC ${APPLICATION_EXECUTABLE}sync Qt5::Test)
@ -54,6 +55,7 @@ nextcloud_add_test(LockedFiles)
nextcloud_add_test(FolderWatcher) nextcloud_add_test(FolderWatcher)
nextcloud_add_test(Capabilities) nextcloud_add_test(Capabilities)
nextcloud_add_test(PushNotifications) nextcloud_add_test(PushNotifications)
nextcloud_add_test(Theme)
if( UNIX AND NOT APPLE ) if( UNIX AND NOT APPLE )
nextcloud_add_test(InotifyWatcher) nextcloud_add_test(InotifyWatcher)

111
test/testtheme.cpp Normal file
View file

@ -0,0 +1,111 @@
/*
* 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"

40
test/themeutils.cpp Normal file
View file

@ -0,0 +1,40 @@
/*
* 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);
}
}

34
test/themeutils.h Normal file
View file

@ -0,0 +1,34 @@
/*
* 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;
};