Merge pull request #2895 from nextcloud/wizard_ui_improvements

Improve wizard ui
This commit is contained in:
Felix Weilbach 2021-03-10 12:54:43 +01:00 committed by GitHub
commit b5cf820b42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 2457 additions and 832 deletions

View File

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

View File

@ -25,6 +25,7 @@
#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@"

View File

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

View File

@ -338,9 +338,6 @@ Application::Application(int &argc, char **argv)
FolderMan::instance()->setupFolders();
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
// Enable word wrapping of QInputDialog (#4197)
setStyleSheet("QInputDialog QLabel { qproperty-wordWrap:1; }");
connect(AccountManager::instance(), &AccountManager::accountAdded,
this, &Application::slotAccountStateAdded);
connect(AccountManager::instance(), &AccountManager::accountRemoved,

View File

@ -116,7 +116,7 @@ void OwncloudSetupWizard::startWizard()
// if its a relative path, prepend with users home dir, otherwise use as absolute path
if (!QDir(localFolder).isAbsolute()) {
localFolder = QDir::homePath() + QDir::separator() + localFolder;
localFolder = QDir::homePath() + QLatin1Char('/') + localFolder;
}
_ocWizard->setProperty("localFolder", localFolder);
@ -131,7 +131,12 @@ void OwncloudSetupWizard::startWizard()
_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();

View File

@ -33,9 +33,6 @@ Flow2AuthCredsPage::Flow2AuthCredsPage()
{
_layout = new QVBoxLayout(this);
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(Theme::instance()->appNameGUI())));
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Login in your browser (Login Flow v2)")));
_flow2AuthWidget = new Flow2AuthWidget();
_layout->addWidget(_flow2AuthWidget);
@ -59,6 +56,8 @@ void Flow2AuthCredsPage::initializePage()
// Don't hide the wizard (avoid user confusion)!
//wizard()->hide();
_flow2AuthWidget->slotStyleChanged();
}
void OCC::Flow2AuthCredsPage::cleanupPage()

View File

@ -17,6 +17,8 @@
#include "common/utility.h"
#include "account.h"
#include "wizard/owncloudwizardcommon.h"
#include "theme.h"
#include "linklabel.h"
#include "QProgressIndicator.h"
@ -34,13 +36,23 @@ Flow2AuthWidget::Flow2AuthWidget(QWidget *parent)
WizardCommon::initErrorLabel(_ui.errorLabel);
_ui.errorLabel->setTextFormat(Qt::RichText);
connect(_ui.openLinkButton, &QCommandLinkButton::clicked, this, &Flow2AuthWidget::slotOpenBrowser);
connect(_ui.copyLinkButton, &QCommandLinkButton::clicked, this, &Flow2AuthWidget::slotCopyLinkToClipboard);
connect(_ui.openLinkLabel, &LinkLabel::clicked, this, &Flow2AuthWidget::slotOpenBrowser);
connect(_ui.copyLinkLabel, &LinkLabel::clicked, this, &Flow2AuthWidget::slotCopyLinkToClipboard);
_ui.horizontalLayout->addWidget(_progressIndi);
auto sizePolicy = _progressIndi->sizePolicy();
sizePolicy.setRetainSizeWhenHidden(true);
_progressIndi->setSizePolicy(sizePolicy);
_ui.progressLayout->addWidget(_progressIndi);
stopSpinner(false);
}
customizeStyle();
void Flow2AuthWidget::setLogo()
{
const auto backgroundColor = palette().window().color();
const auto logoIconFileName = Theme::instance()->isBranded() ? Theme::hidpiFileName("external.png", backgroundColor)
: Theme::hidpiFileName(":/client/theme/colored/external.png");
_ui.logoLabel->setPixmap(logoIconFileName);
}
void Flow2AuthWidget::startAuth(Account *account)
@ -160,24 +172,24 @@ void Flow2AuthWidget::slotStatusChanged(Flow2Auth::PollStatus status, int second
void Flow2AuthWidget::startSpinner()
{
_ui.horizontalLayout->setEnabled(true);
_ui.progressLayout->setEnabled(true);
_ui.statusLabel->setVisible(true);
_progressIndi->setVisible(true);
_progressIndi->startAnimation();
_ui.openLinkButton->setEnabled(false);
_ui.copyLinkButton->setEnabled(false);
_ui.openLinkLabel->setEnabled(false);
_ui.copyLinkLabel->setEnabled(false);
}
void Flow2AuthWidget::stopSpinner(bool showStatusLabel)
{
_ui.horizontalLayout->setEnabled(false);
_ui.progressLayout->setEnabled(false);
_ui.statusLabel->setVisible(showStatusLabel);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
_ui.openLinkButton->setEnabled(_statusUpdateSkipCount == 0);
_ui.copyLinkButton->setEnabled(_statusUpdateSkipCount == 0);
_ui.openLinkLabel->setEnabled(_statusUpdateSkipCount == 0);
_ui.copyLinkLabel->setEnabled(_statusUpdateSkipCount == 0);
}
void Flow2AuthWidget::slotStyleChanged()
@ -187,8 +199,24 @@ void Flow2AuthWidget::slotStyleChanged()
void Flow2AuthWidget::customizeStyle()
{
if(_progressIndi)
_progressIndi->setColor(QGuiApplication::palette().color(QPalette::Text));
setLogo();
if (_progressIndi) {
const auto isDarkBackground = Theme::isDarkColor(palette().window().color());
if (isDarkBackground) {
_progressIndi->setColor(Qt::white);
} else {
_progressIndi->setColor(Qt::black);
}
}
_ui.openLinkLabel->setText(tr("Reopen Browser"));
_ui.openLinkLabel->setAlignment(Qt::AlignCenter);
_ui.copyLinkLabel->setText(tr("Copy Link"));
_ui.copyLinkLabel->setAlignment(Qt::AlignCenter);
WizardCommon::customizeHintLabel(_ui.statusLabel);
}
} // namespace OCC

View File

@ -60,6 +60,7 @@ private:
void startSpinner();
void stopSpinner(bool showStatusLabel);
void customizeStyle();
void setLogo();
QProgressIndicator *_progressIndi;
int _statusUpdateSkipCount = 0;

View File

@ -27,44 +27,138 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Please switch to your browser to proceed.</string>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
</widget>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>80</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="text">
<string>An error occurred while connecting. Please try again.</string>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
<property name="bottomMargin">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QCommandLinkButton" name="openLinkButton">
<property name="text">
<string>Re-open Browser</string>
</property>
</widget>
</item>
<item>
<widget class="QCommandLinkButton" name="copyLinkButton">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Copy link</string>
</property>
</widget>
<item>
<widget class="QLabel" name="logoLabel">
<property name="text">
<string>Logo</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Switch to your browser to connect your account</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string notr="true">Status</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="margin">
<number>0</number>
</property>
</widget>
</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_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>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="OCC::LinkLabel" name="copyLinkLabel" native="true"/>
</item>
<item>
<widget class="OCC::LinkLabel" name="openLinkLabel" native="true"/>
</item>
</layout>
</item>
<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>
</layout>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="text">
<string>An error occurred while connecting. Please try again.</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="progressLayout"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
@ -79,19 +173,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout"/>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@ -100,13 +181,21 @@
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>107</height>
<height>80</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>OCC::LinkLabel</class>
<extends>QWidget</extends>
<header>wizard/linklabel.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

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

@ -19,6 +19,7 @@
#include <QTimer>
#include <QStorageInfo>
#include <QMessageBox>
#include <QJsonObject>
#include "QProgressIndicator.h"
@ -32,27 +33,31 @@
#include <folderman.h>
#include "creds/abstractcredentials.h"
#include "networkjobs.h"
#include "wizard/owncloudwizard.h"
namespace OCC {
OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage()
OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage(OwncloudWizard *wizard)
: QWizardPage()
, _progressIndi(new QProgressIndicator(this))
, _ocWizard(wizard)
{
_ui.setupUi(this);
Theme *theme = Theme::instance();
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(theme->appNameGUI())));
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Setup local folder options")));
setupResoultionWidget();
registerField(QLatin1String("OCSyncFromScratch"), _ui.cbSyncFromScratch);
auto sizePolicy = _progressIndi->sizePolicy();
sizePolicy.setRetainSizeWhenHidden(true);
_progressIndi->setSizePolicy(sizePolicy);
_ui.resultLayout->addWidget(_progressIndi);
stopSpinner();
setupCustomization();
connect(_ui.pbSelectLocalFolder, &QAbstractButton::clicked, this, &OwncloudAdvancedSetupPage::slotSelectFolder);
setButtonText(QWizard::NextButton, tr("Connect"));
setButtonText(QWizard::NextButton, tr("Connect"));
connect(_ui.rSyncEverything, &QAbstractButton::clicked, this, &OwncloudAdvancedSetupPage::slotSyncEverythingClicked);
connect(_ui.rSelectiveSync, &QAbstractButton::clicked, this, &OwncloudAdvancedSetupPage::slotSelectiveSyncClicked);
@ -65,13 +70,11 @@ OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage()
});
connect(_ui.bSelectiveSync, &QAbstractButton::clicked, this, &OwncloudAdvancedSetupPage::slotSelectiveSyncClicked);
QIcon appIcon = theme->applicationIcon();
_ui.lServerIcon->setText(QString());
_ui.lServerIcon->setPixmap(appIcon.pixmap(48));
_ui.lLocalIcon->setText(QString());
// TO DO: File doesn't exist anymore - unneccessary or replacement needed?
_ui.lLocalIcon->setPixmap(QPixmap(Theme::hidpiFileName(":/client/theme/folder-sync.png")));
const auto theme = Theme::instance();
const auto appIcon = theme->applicationIcon();
const auto appIconSize = Theme::isHidpi() ? 128 : 64;
_ui.lServerIcon->setPixmap(appIcon.pixmap(appIconSize));
if (theme->wizardHideExternalStorageConfirmationCheckbox()) {
_ui.confCheckBoxExternal->hide();
@ -106,6 +109,11 @@ void OwncloudAdvancedSetupPage::setupCustomization()
variant = theme->customMedia(Theme::oCSetupBottom);
WizardCommon::setupCustomMedia(variant, _ui.bottomLabel);
WizardCommon::customizeHintLabel(_ui.lFreeSpace);
WizardCommon::customizeHintLabel(_ui.lSyncEverythingSizeLabel);
WizardCommon::customizeHintLabel(_ui.lSelectiveSyncSizeLabel);
WizardCommon::customizeHintLabel(_ui.serverAddressLabel);
}
bool OwncloudAdvancedSetupPage::isComplete() const
@ -158,6 +166,69 @@ void OwncloudAdvancedSetupPage::initializePage()
_ui.confCheckBoxSize->setChecked(newFolderLimit.first);
_ui.confSpinBox->setValue(newFolderLimit.second);
_ui.confCheckBoxExternal->setChecked(cfgFile.confirmExternalStorage());
fetchUserAvatar();
fetchUserData();
customizeStyle();
auto nextButton = qobject_cast<QPushButton *>(_ocWizard->button(QWizard::NextButton));
if (nextButton) {
nextButton->setDefault(true);
}
}
void OwncloudAdvancedSetupPage::fetchUserAvatar()
{
// Reset user avatar
const auto appIcon = Theme::instance()->applicationIcon();
_ui.lServerIcon->setPixmap(appIcon.pixmap(48));
// Fetch user avatar
const auto account = _ocWizard->account();
auto avatarSize = 64;
if (Theme::isHidpi()) {
avatarSize *= 2;
}
const auto avatarJob = new AvatarJob(account, account->davUser(), avatarSize, this);
avatarJob->setTimeout(20 * 1000);
QObject::connect(avatarJob, &AvatarJob::avatarPixmap, this, [this](const QImage &avatarImage) {
if (avatarImage.isNull()) {
return;
}
const auto avatarPixmap = QPixmap::fromImage(AvatarJob::makeCircularAvatar(avatarImage));
_ui.lServerIcon->setPixmap(avatarPixmap);
});
avatarJob->start();
}
void OwncloudAdvancedSetupPage::fetchUserData()
{
const auto account = _ocWizard->account();
// Fetch user data
const auto userJob = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/user"), this);
userJob->setTimeout(20 * 1000);
connect(userJob, &JsonApiJob::jsonReceived, this, [this](const QJsonDocument &json) {
const auto objData = json.object().value("ocs").toObject().value("data").toObject();
const auto displayName = objData.value("display-name").toString();
_ui.userNameLabel->setText(displayName);
});
userJob->start();
const auto serverUrl = account->url().toString();
setServerAddressLabelUrl(serverUrl);
const auto userName = account->davDisplayName();
_ui.userNameLabel->setText(userName);
}
void OwncloudAdvancedSetupPage::setServerAddressLabelUrl(const QUrl &url)
{
if (!url.isValid()) {
return;
}
const auto prettyUrl = url.toString().mid(url.scheme().size() + 3); // + 3 because we need to remove ://
_ui.serverAddressLabel->setText(prettyUrl);
}
// Called if the user changes the user- or url field. Adjust the texts and
@ -172,7 +243,8 @@ void OwncloudAdvancedSetupPage::updateStatus()
QString t;
_ui.pbSelectLocalFolder->setText(QDir::toNativeSeparators(locFolder));
setLocalFolderPushButtonPath(locFolder);
if (dataChanged()) {
if (_remoteFolder.isEmpty() || _remoteFolder == QLatin1String("/")) {
t = "";
@ -185,20 +257,18 @@ void OwncloudAdvancedSetupPage::updateStatus()
const bool dirNotEmpty(QDir(locFolder).entryList(QDir::AllEntries | QDir::NoDotAndDotDot).count() > 0);
if (dirNotEmpty) {
t += tr("<p><small><strong>Warning:</strong> The local folder is not empty. "
"Pick a resolution!</small></p>");
t += tr("Warning: The local folder is not empty. Pick a resolution!");
}
_ui.resolutionWidget->setVisible(dirNotEmpty);
setResolutionGuiVisible(dirNotEmpty);
} else {
_ui.resolutionWidget->setVisible(false);
setResolutionGuiVisible(false);
}
QString lfreeSpaceStr = Utility::octetsToString(availableLocalSpace());
_ui.lFreeSpace->setText(QString(tr("Free space: %1")).arg(lfreeSpaceStr));
_ui.lFreeSpace->setText(QString(tr("%1 free space", "%1 gets replaced with the size and a matching unit. Example: 3 MB or 5 GB")).arg(lfreeSpaceStr));
_ui.syncModeLabel->setText(t);
_ui.syncModeLabel->setFixedHeight(_ui.syncModeLabel->sizeHint().height());
wizard()->resize(wizard()->sizeHint());
qint64 rSpace = _ui.rSyncEverything->isChecked() ? _rSize : _rSelectedSize;
@ -211,6 +281,13 @@ void OwncloudAdvancedSetupPage::updateStatus()
emit completeChanged();
}
void OwncloudAdvancedSetupPage::setResolutionGuiVisible(bool value)
{
_ui.syncModeLabel->setVisible(value);
_ui.rKeepLocal->setVisible(value);
_ui.cbSyncFromScratch->setVisible(value);
}
/* obsolete */
bool OwncloudAdvancedSetupPage::dataChanged()
{
@ -334,7 +411,7 @@ void OwncloudAdvancedSetupPage::slotSelectFolder()
{
QString dir = QFileDialog::getExistingDirectory(nullptr, tr("Local Sync Folder"), QDir::homePath());
if (!dir.isEmpty()) {
_ui.pbSelectLocalFolder->setText(dir);
setLocalFolderPushButtonPath(dir);
wizard()->setProperty("localFolder", dir);
updateStatus();
}
@ -344,6 +421,22 @@ void OwncloudAdvancedSetupPage::slotSelectFolder()
setErrorString(errorStr);
}
void OwncloudAdvancedSetupPage::setLocalFolderPushButtonPath(const QString &path)
{
const auto homeDir = QDir::homePath().endsWith('/') ? QDir::homePath() : QDir::homePath() + QLatin1Char('/');
if (!path.startsWith(homeDir)) {
_ui.pbSelectLocalFolder->setText(QDir::toNativeSeparators(path));
return;
}
auto prettyPath = path;
prettyPath.remove(0, homeDir.size());
_ui.pbSelectLocalFolder->setText(QDir::toNativeSeparators(prettyPath));
}
void OwncloudAdvancedSetupPage::slotSelectiveSyncClicked()
{
AccountPtr acc = static_cast<OwncloudWizard *>(wizard())->account();
@ -384,6 +477,8 @@ void OwncloudAdvancedSetupPage::slotSelectiveSyncClicked()
wizard()->setProperty("blacklist", _selectiveSyncBlacklist);
}
updateStatus();
});
dlg->open();
}
@ -439,8 +534,25 @@ void OwncloudAdvancedSetupPage::slotStyleChanged()
void OwncloudAdvancedSetupPage::customizeStyle()
{
if(_progressIndi)
_progressIndi->setColor(QGuiApplication::palette().color(QPalette::Text));
if (_progressIndi) {
const auto isDarkBackground = Theme::isDarkColor(palette().window().color());
if (isDarkBackground) {
_progressIndi->setColor(Qt::white);
} else {
_progressIndi->setColor(Qt::black);
}
}
styleSyncLogo();
styleLocalFolderLabel();
}
void OwncloudAdvancedSetupPage::styleLocalFolderLabel()
{
const auto backgroundColor = palette().window().color();
const auto folderIconFileName = Theme::instance()->isBranded() ? Theme::hidpiFileName("folder.png", backgroundColor)
: Theme::hidpiFileName(":/client/theme/colored/folder.png");
_ui.lLocal->setPixmap(folderIconFileName);
}
void OwncloudAdvancedSetupPage::setRadioChecked(QRadioButton *radio)
@ -457,4 +569,24 @@ void OwncloudAdvancedSetupPage::setRadioChecked(QRadioButton *radio)
_ui.rVirtualFileSync->setCheckable(false);
}
void OwncloudAdvancedSetupPage::styleSyncLogo()
{
const auto syncArrowIcon = Theme::createColorAwareIcon(QLatin1String(":/client/theme/sync-arrow.svg"), palette());
_ui.syncLogoLabel->setPixmap(syncArrowIcon.pixmap(QSize(50, 50)));
}
void OwncloudAdvancedSetupPage::setupResoultionWidget()
{
for (int i = 0; i < _ui.resolutionWidgetLayout->count(); ++i) {
auto widget = _ui.resolutionWidgetLayout->itemAt(i)->widget();
if (!widget) {
continue;
}
auto sizePolicy = widget->sizePolicy();
sizePolicy.setRetainSizeWhenHidden(true);
widget->setSizePolicy(sizePolicy);
}
}
} // namespace OCC

View File

@ -25,6 +25,8 @@ class QProgressIndicator;
namespace OCC {
class OwncloudWizard;
/**
* @brief The OwncloudAdvancedSetupPage class
* @ingroup gui
@ -33,7 +35,7 @@ class OwncloudAdvancedSetupPage : public QWizardPage
{
Q_OBJECT
public:
OwncloudAdvancedSetupPage();
OwncloudAdvancedSetupPage(OwncloudWizard *wizard);
bool isComplete() const override;
void initializePage() override;
@ -73,6 +75,14 @@ private:
qint64 availableLocalSpace() const;
QString checkLocalSpace(qint64 remoteSize) const;
void customizeStyle();
void setServerAddressLabelUrl(const QUrl &url);
void setLocalFolderPushButtonPath(const QString &path);
void styleSyncLogo();
void styleLocalFolderLabel();
void setResolutionGuiVisible(bool value);
void setupResoultionWidget();
void fetchUserAvatar();
void fetchUserData();
Ui_OwncloudAdvancedSetupPage _ui;
bool _checking = false;
@ -83,6 +93,7 @@ private:
QStringList _selectiveSyncBlacklist;
qint64 _rSize = -1;
qint64 _rSelectedSize = -1;
OwncloudWizard *_ocWizard;
};
} // namespace OCC

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,12 @@
<rect>
<x>0</x>
<y>0</y>
<width>802</width>
<height>629</height>
<width>556</width>
<height>489</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -27,102 +27,84 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<spacer name="verticalSpacer_5">
<widget class="QLabel" name="topLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
<height>80</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="topLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin">
<number>0</number>
</property>
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QPushButton" name="prevButton">
<property name="minimumSize">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>16777215</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="logoLabel">
<property name="text">
<string/>
</property>
<property name="flat">
<bool>true</bool>
<string>Logo</string>
</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>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="nextButton">
<property name="minimumSize">
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="login" native="true">
<property name="sizePolicy">
@ -143,38 +125,28 @@
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QHBoxLayout" name="serverBox">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<width>0</width>
<height>0</height>
</size>
</property>
@ -182,72 +154,137 @@
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="text">
<string>Server Address</string>
</property>
<property name="buddy">
<cstring>leUrl</cstring>
</property>
</widget>
</item>
<item>
<widget class="OCC::PostfixLineEdit" name="leUrl">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="placeholderText">
<string notr="true"/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="resultLayout">
<property name="spacing">
<number>0</number>
</property>
</layout>
</item>
<item>
<widget class="QLabel" name="urlLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<property name="sizeHint" stdset="0">
<size>
<width>24</width>
<height>24</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="serverAddressLabel">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
<string>Server address</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="addressDescriptionLabel">
<property name="text">
<string>This is the link to your %1 web interface when you open it in the browser.&lt;br/&gt;It looks like https://cloud.example.com or https://example.com/cloud</string>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="topMargin">
<number>0</number>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="OCC::PostfixLineEdit" name="leUrl">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string notr="true">https://try.nextcloud.com</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="serverAddressDescriptionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>This is the link to your %1 web interface when you open it in the browser.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="errorLabel">
@ -268,6 +305,9 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="progressLayout"/>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
@ -278,7 +318,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<width>0</width>
<height>0</height>
</size>
</property>
@ -286,22 +326,6 @@
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
@ -317,163 +341,26 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="buttons" stretch="0,0,0,0">
<property name="spacing">
<number>6</number>
<widget class="QLabel" name="bottomLabel">
<property name="text">
<string>TextLabel</string>
</property>
<property name="topMargin">
<number>20</number>
</property>
<item>
<spacer name="horizontalSpacer_3">
<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>
<widget class="QPushButton" name="createAccountButton">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string>Sign up with a provider</string>
</property>
<property name="default">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="loginButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Log in to your %1</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<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>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer_6">
<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>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="installLink">
<property name="text">
<string notr="true">&lt;a href=&quot;https://docs.nextcloud.com/server/latest/admin_manual/installation/#installation&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#7a7a7a;&quot;&gt;Host your own server&lt;/span&gt;&lt;/a&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<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>
<widget class="QLabel" name="bottomLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
@ -482,11 +369,6 @@
<extends>QLineEdit</extends>
<header>wizard/postfixlineedit.h</header>
</customwidget>
<customwidget>
<class>OCC::SlideShow</class>
<extends>QWidget</extends>
<header>wizard/slideshow.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -45,10 +45,9 @@ OwncloudSetupPage::OwncloudSetupPage(QWidget *parent)
{
_ui.setupUi(this);
Theme *theme = Theme::instance();
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(theme->appNameGUI())));
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Setup %1 server").arg(theme->appNameGUI())));
setupServerAddressDescriptionLabel();
Theme *theme = Theme::instance();
if (theme->overrideServerUrl().isEmpty()) {
_ui.leUrl->setPostfix(theme->wizardUrlPostfix());
_ui.leUrl->setPlaceholderText(theme->wizardUrlHint());
@ -59,7 +58,11 @@ OwncloudSetupPage::OwncloudSetupPage(QWidget *parent)
registerField(QLatin1String("OCUrl*"), _ui.leUrl);
_ui.resultLayout->addWidget(_progressIndi);
auto sizePolicy = _progressIndi->sizePolicy();
sizePolicy.setRetainSizeWhenHidden(true);
_progressIndi->setSizePolicy(sizePolicy);
_ui.progressLayout->addWidget(_progressIndi);
stopSpinner();
setupCustomization();
@ -70,35 +73,17 @@ OwncloudSetupPage::OwncloudSetupPage(QWidget *parent)
addCertDial = new AddCertificateDialog(this);
connect(addCertDial, &QDialog::accepted, this, &OwncloudSetupPage::slotCertificateAccepted);
}
#ifdef WITH_PROVIDERS
connect(_ui.loginButton, &QPushButton::clicked, this, &OwncloudSetupPage::slotLogin);
connect(_ui.createAccountButton, &QPushButton::clicked, this, &OwncloudSetupPage::slotGotoProviderList);
_ui.login->hide();
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-nextcloud.png"), tr("Keep your data secure and under your control"));
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-files.png"), tr("Secure collaboration & file exchange"));
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-groupware.png"), tr("Easy-to-use web mail, calendaring & contacts"));
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-talk.png"), tr("Screensharing, online meetings & web conferences"));
connect(_ui.slideShow, &SlideShow::clicked, _ui.slideShow, &SlideShow::stopShow);
connect(_ui.nextButton, &QPushButton::clicked, _ui.slideShow, &SlideShow::nextSlide);
connect(_ui.prevButton, &QPushButton::clicked, _ui.slideShow, &SlideShow::prevSlide);
_ui.slideShow->startShow();
#else
_ui.createAccountButton->hide();
_ui.loginButton->hide();
_ui.installLink->hide();
_ui.slideShow->hide();
#endif
void OwncloudSetupPage::setLogo()
{
_ui.logoLabel->setPixmap(Theme::instance()->wizardApplicationLogo());
}
void OwncloudSetupPage::setupServerAddressDescriptionLabel()
{
const auto appName = Theme::instance()->appNameGUI();
_ui.loginButton->setText(tr("Log in to your %1").arg(appName));
_ui.addressDescriptionLabel->setText(tr("This is the link to your %1 web interface when you open it in the browser.<br/>"
"It looks like https://cloud.example.com or https://example.com/cloud").arg(appName));
customizeStyle();
_ui.serverAddressDescriptionLabel->setText(tr("The link to your %1 web interface when you open it in the browser.", "%1 will be replaced with the application name").arg(appName));
}
void OwncloudSetupPage::setServerUrl(const QString &newUrl)
@ -127,25 +112,17 @@ void OwncloudSetupPage::setupCustomization()
variant = theme->customMedia(Theme::oCSetupBottom);
WizardCommon::setupCustomMedia(variant, _ui.bottomLabel);
auto leUrlPalette = _ui.leUrl->palette();
leUrlPalette.setColor(QPalette::Text, Qt::black);
leUrlPalette.setColor(QPalette::Base, Qt::white);
_ui.leUrl->setPalette(leUrlPalette);
}
#ifdef WITH_PROVIDERS
void OwncloudSetupPage::slotLogin()
{
_ui.slideShow->hide();
_ui.nextButton->hide();
_ui.prevButton->hide();
_ocWizard->setRegistration(false);
_ui.login->setMaximumHeight(0);
auto *animation = new QPropertyAnimation(_ui.login, "maximumHeight");
animation->setDuration(0);
animation->setStartValue(500);
animation->setEndValue(500);
_ui.login->show();
_ui.loginButton->hide();
wizard()->resize(wizard()->sizeHint());
animation->start();
}
void OwncloudSetupPage::slotGotoProviderList()
{
@ -160,6 +137,14 @@ void OwncloudSetupPage::slotGotoProviderList()
// slot hit from textChanged of the url entry field.
void OwncloudSetupPage::slotUrlChanged(const QString &url)
{
// Need to set next button as default button here because
// otherwise the on OSX the next button does not stay the default
// button
auto nextButton = qobject_cast<QPushButton *>(_ocWizard->button(QWizard::NextButton));
if (nextButton) {
nextButton->setDefault(true);
}
_authTypeKnown = false;
QString newUrl = url;
@ -181,16 +166,6 @@ void OwncloudSetupPage::slotUrlChanged(const QString &url)
if (newUrl != url) {
_ui.leUrl->setText(newUrl);
}
const auto isSecure = url.startsWith(QLatin1String("https://"));
const auto toolTip = isSecure ? tr("This URL is secure. You can use it.")
: tr("This URL is NOT secure as it is not encrypted.\n"
"It is not advisable to use it.");
const auto pixmap = isSecure ? QPixmap(Theme::hidpiFileName(":/client/theme/lock-https.svg"))
: QPixmap(Theme::hidpiFileName(":/client/theme/lock-http.svg"));
_ui.urlLabel->setToolTip(toolTip);
_ui.urlLabel->setPixmap(pixmap.scaled(_ui.urlLabel->size(), Qt::KeepAspectRatio));
}
void OwncloudSetupPage::slotUrlEditFinished()
@ -210,6 +185,8 @@ bool OwncloudSetupPage::isComplete() const
void OwncloudSetupPage::initializePage()
{
customizeStyle();
WizardCommon::initErrorLabel(_ui.errorLabel);
_authTypeKnown = false;
@ -217,26 +194,29 @@ void OwncloudSetupPage::initializePage()
QAbstractButton *nextButton = wizard()->button(QWizard::NextButton);
auto *pushButton = qobject_cast<QPushButton *>(nextButton);
if (pushButton)
if (pushButton) {
pushButton->setDefault(true);
}
// If url is overriden by theme, it's already set and
// we just check the server type and switch to second page
// immediately.
if (Theme::instance()->overrideServerUrl().isEmpty()) {
_ui.leUrl->setFocus();
} else if (!Theme::instance()->forceOverrideServerUrl()) {
_ui.leUrl->setFocus();
const auto isServerUrlOverridden = !Theme::instance()->overrideServerUrl().isEmpty();
if (isServerUrlOverridden && !Theme::instance()->forceOverrideServerUrl()) {
// If the url is overwritten but we don't force to use that url
// Just focus the next button to let the user navigate quicker
if (nextButton) {
nextButton->setFocus();
}
} else {
} else if (isServerUrlOverridden) {
// If the overwritten url is not empty and we force this overwritten url
// we just check the server type and switch to next page
// immediately.
setCommitPage(true);
// Hack: setCommitPage() changes caption, but after an error this page could still be visible
setButtonText(QWizard::CommitButton, tr("&Next >"));
validatePage();
setVisible(false);
}
wizard()->resize(wizard()->sizeHint());
}
int OwncloudSetupPage::nextId() const
@ -269,7 +249,7 @@ bool OwncloudSetupPage::validatePage()
QString u = url();
QUrl qurl(u);
if (!qurl.isValid() || qurl.host().isEmpty()) {
setErrorString(tr("Invalid URL"), false);
setErrorString(tr("Server address does not seem to be valid"), false);
return false;
}
@ -338,21 +318,18 @@ void OwncloudSetupPage::setErrorString(const QString &err, bool retryHTTPonly)
_checking = false;
emit completeChanged();
stopSpinner();
wizard()->resize(wizard()->sizeHint());
}
void OwncloudSetupPage::startSpinner()
{
_ui.resultLayout->setEnabled(true);
_ui.urlLabel->setVisible(false);
_ui.progressLayout->setEnabled(true);
_progressIndi->setVisible(true);
_progressIndi->startAnimation();
}
void OwncloudSetupPage::stopSpinner()
{
_ui.resultLayout->setEnabled(false);
_ui.urlLabel->setVisible(true);
_ui.progressLayout->setEnabled(false);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
@ -397,24 +374,19 @@ void OwncloudSetupPage::slotStyleChanged()
void OwncloudSetupPage::customizeStyle()
{
#ifdef WITH_PROVIDERS
Theme *theme = Theme::instance();
setLogo();
bool widgetHasDarkBg = Theme::isDarkColor(QGuiApplication::palette().base().color());
_ui.nextButton->setIcon(theme->uiThemeIcon(QString("control-next.svg"), widgetHasDarkBg));
_ui.prevButton->setIcon(theme->uiThemeIcon(QString("control-prev.svg"), widgetHasDarkBg));
if (_progressIndi) {
const auto isDarkBackground = Theme::isDarkColor(palette().window().color());
if (isDarkBackground) {
_progressIndi->setColor(Qt::white);
} else {
_progressIndi->setColor(Qt::black);
}
}
// QPushButtons are a mess when it comes to consistent background coloring without stylesheets,
// so we do it here even though this is an exceptional styling method here
_ui.createAccountButton->setStyleSheet("QPushButton {background-color: #0082C9; color: white}");
QPalette pal = _ui.slideShow->palette();
pal.setColor(QPalette::WindowText, theme->wizardHeaderBackgroundColor());
_ui.slideShow->setPalette(pal);
#endif
if(_progressIndi)
_progressIndi->setColor(QGuiApplication::palette().color(QPalette::Text));
WizardCommon::customizeHintLabel(_ui.serverAddressDescriptionLabel);
}
} // namespace OCC

View File

@ -78,7 +78,9 @@ signals:
void determineAuthType(const QString &);
private:
void setLogo();
void customizeStyle();
void setupServerAddressDescriptionLabel();
Ui_OwncloudSetupPage _ui;

View File

@ -20,6 +20,7 @@
#include "owncloudgui.h"
#include "wizard/owncloudwizard.h"
#include "wizard/welcomepage.h"
#include "wizard/owncloudsetuppage.h"
#include "wizard/owncloudhttpcredspage.h"
#include "wizard/owncloudoauthcredspage.h"
@ -46,17 +47,19 @@ Q_LOGGING_CATEGORY(lcWizard, "nextcloud.gui.wizard", QtInfoMsg)
OwncloudWizard::OwncloudWizard(QWidget *parent)
: QWizard(parent)
, _account(nullptr)
, _welcomePage(new WelcomePage(this))
, _setupPage(new OwncloudSetupPage(this))
, _httpCredsPage(new OwncloudHttpCredsPage(this))
, _browserCredsPage(new OwncloudOAuthCredsPage)
, _flow2CredsPage(new Flow2AuthCredsPage)
, _advancedSetupPage(new OwncloudAdvancedSetupPage)
, _advancedSetupPage(new OwncloudAdvancedSetupPage(this))
, _resultPage(new OwncloudWizardResultPage)
, _webViewPage(new WebViewPage(this))
{
setObjectName("owncloudWizard");
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setPage(WizardCommon::Page_Welcome, _welcomePage);
setPage(WizardCommon::Page_ServerSetup, _setupPage);
setPage(WizardCommon::Page_HttpCreds, _httpCredsPage);
setPage(WizardCommon::Page_OAuthCreds, _browserCredsPage);
@ -69,7 +72,6 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
// note: start Id is set by the calling class depending on if the
// welcome text is to be shown or not.
setWizardStyle(QWizard::ModernStyle);
connect(this, &QWizard::currentIdChanged, this, &OwncloudWizard::slotCurrentPageChanged);
connect(_setupPage, &OwncloudSetupPage::determineAuthType, this, &OwncloudWizard::determineAuthType);
@ -83,17 +85,19 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
Theme *theme = Theme::instance();
setWindowTitle(tr("%1 Connection Wizard").arg(theme->appNameGUI()));
setWindowTitle(tr("Add %1 account").arg(theme->appNameGUI()));
setWizardStyle(QWizard::ModernStyle);
setPixmap(QWizard::BannerPixmap, theme->wizardHeaderBanner());
setPixmap(QWizard::LogoPixmap, theme->wizardHeaderLogo());
setOption(QWizard::NoBackButtonOnStartPage);
setOption(QWizard::NoBackButtonOnLastPage);
setOption(QWizard::NoCancelButton);
setTitleFormat(Qt::RichText);
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);
@ -104,6 +108,48 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
// allow Flow2 page to poll on window activation
connect(this, &OwncloudWizard::onActivate, _flow2CredsPage, &Flow2AuthCredsPage::slotPollNow);
adjustWizardSize();
centerWindow();
}
void OwncloudWizard::centerWindow()
{
const auto wizardWindow = window();
const auto screenGeometry = QGuiApplication::screenAt(wizardWindow->pos())->geometry();
const auto windowGeometry = wizardWindow->geometry();
const auto newWindowPosition = screenGeometry.center() - QPoint(windowGeometry.width() / 2, windowGeometry.height() / 2);
wizardWindow->move(newWindowPosition);
}
void OwncloudWizard::adjustWizardSize()
{
const auto pageSizes = calculateWizardPageSizes();
const auto longestSide = calculateLongestSideOfWizardPages(pageSizes);
resize(QSize(longestSide, longestSide));
}
QList<QSize> OwncloudWizard::calculateWizardPageSizes() const
{
QList<QSize> pageSizes;
const auto pIds = pageIds();
std::transform(pIds.cbegin(), pIds.cend(), std::back_inserter(pageSizes), [this](int pageId) {
auto p = page(pageId);
p->adjustSize();
return p->sizeHint();
});
return pageSizes;
}
int OwncloudWizard::calculateLongestSideOfWizardPages(const QList<QSize> &pageSizes) const
{
return std::accumulate(std::cbegin(pageSizes), std::cend(pageSizes), 0, [](int current, const QSize &size) {
return std::max({ current, size.width(), size.height() });
});
}
void OwncloudWizard::setAccount(AccountPtr account)
@ -220,6 +266,28 @@ void OwncloudWizard::slotCurrentPageChanged(int 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);
}
};
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();
}
@ -232,7 +300,6 @@ void OwncloudWizard::slotCurrentPageChanged(int id)
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.
@ -302,6 +369,15 @@ void OwncloudWizard::changeEvent(QEvent *e)
void OwncloudWizard::customizeStyle()
{
// HINT: Customize wizard's own style here, if necessary in the future (Dark-/Light-Mode switching)
// Set background colors
auto wizardPalette = palette();
const auto backgroundColor = wizardPalette.color(QPalette::Window);
wizardPalette.setColor(QPalette::Base, backgroundColor);
// Set separator color
wizardPalette.setColor(QPalette::Mid, backgroundColor);
setPalette(wizardPalette);
}
void OwncloudWizard::bringToTop()

View File

@ -29,6 +29,7 @@ namespace OCC {
Q_DECLARE_LOGGING_CATEGORY(lcWizard)
class WelcomePage;
class OwncloudSetupPage;
class OwncloudHttpCredsPage;
class OwncloudOAuthCredsPage;
@ -73,6 +74,7 @@ public:
AbstractCredentials *getCredentials() const;
void bringToTop();
void centerWindow();
/**
* Shows a dialog explaining the virtual files mode and warning about it
@ -113,8 +115,12 @@ protected:
private:
void customizeStyle();
void adjustWizardSize();
int calculateLongestSideOfWizardPages(const QList<QSize> &pageSizes) const;
QList<QSize> calculateWizardPageSizes() const;
AccountPtr _account;
WelcomePage *_welcomePage;
OwncloudSetupPage *_setupPage;
OwncloudHttpCredsPage *_httpCredsPage;
OwncloudOAuthCredsPage *_browserCredsPage;

View File

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

View File

@ -16,8 +16,14 @@
#ifndef MIRALL_OWNCLOUD_WIZARD_COMMON_H
#define MIRALL_OWNCLOUD_WIZARD_COMMON_H
#include <QString>
class QVariant;
class QLabel;
class QRadioButton;
class QSpinBox;
class QCheckBox;
class QAbstractButton;
namespace OCC {
@ -27,6 +33,7 @@ namespace WizardCommon {
QString titleTemplate();
QString subTitleTemplate();
void initErrorLabel(QLabel *errorLabel);
void customizeHintLabel(QLabel *label);
enum SyncMode {
SelectiveMode,
@ -34,6 +41,7 @@ namespace WizardCommon {
};
enum Pages {
Page_Welcome,
Page_ServerSetup,
Page_HttpCreds,
Page_ShibbolethCreds,

View File

@ -11,15 +11,15 @@
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>650</height>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">

View File

@ -4,6 +4,7 @@
#include <QProgressBar>
#include <QVBoxLayout>
#include <QNetworkProxyFactory>
#include <QScreen>
#include "owncloudwizard.h"
#include "creds/webflowcredentials.h"
@ -24,6 +25,7 @@ WebViewPage::WebViewPage(QWidget *parent)
_webView = new WebView(this);
auto *layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->addWidget(_webView);
setLayout(layout);
@ -52,6 +54,44 @@ void WebViewPage::initializePage() {
}
qCInfo(lcWizardWebiewPage()) << "Url to auth at: " << url;
_webView->setUrl(QUrl(url));
_originalWizardSize = _ocWizard->size();
resizeWizard();
}
void WebViewPage::resizeWizard()
{
// The webview needs a little bit more space
auto wizardSizeChanged = tryToSetWizardSize(_originalWizardSize.width() * 2, _originalWizardSize.height() * 2);
if (!wizardSizeChanged) {
wizardSizeChanged = tryToSetWizardSize(static_cast<int>(_originalWizardSize.width() * 1.5), static_cast<int>(_originalWizardSize.height() * 1.5));
}
if (wizardSizeChanged) {
_ocWizard->centerWindow();
}
}
bool WebViewPage::tryToSetWizardSize(int width, int height)
{
const auto window = _ocWizard->window();
const auto screenGeometry = QGuiApplication::screenAt(window->pos())->geometry();
const auto windowWidth = screenGeometry.width();
const auto windowHeight = screenGeometry.height();
if (width < windowWidth && height < windowHeight) {
_ocWizard->resize(width, height);
return true;
}
return false;
}
void WebViewPage::cleanupPage()
{
_ocWizard->resize(_originalWizardSize);
_ocWizard->centerWindow();
}
int WebViewPage::nextId() const {

View File

@ -17,6 +17,7 @@ public:
~WebViewPage();
void initializePage() override;
void cleanupPage() override;
int nextId() const override;
bool isComplete() const override;
@ -30,6 +31,9 @@ private slots:
void urlCatched(QString user, QString pass, QString host);
private:
void resizeWizard();
bool tryToSetWizardSize(int width, int height);
OwncloudWizard *_ocWizard;
WebView *_webView;
@ -37,6 +41,8 @@ private:
QString _pass;
bool _useSystemProxy;
QSize _originalWizardSize;
};
}

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

@ -35,7 +35,7 @@ NextcloudTheme::NextcloudTheme()
QString NextcloudTheme::wizardUrlHint() const
{
return QString("https://host:port");
return QString("https://try.nextcloud.com");
}
}

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
{
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)
{
qreal devicePixelRatio = dev ? dev->devicePixelRatio() : qApp->primaryScreen()->devicePixelRatio();
if (devicePixelRatio <= 1.0) {
if (!Theme::isHidpi(dev)) {
return fileName;
}
// try to find a 2x version
@ -274,6 +279,16 @@ QString Theme::hidpiFileName(const QString &fileName, QPaintDevice *dev)
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
@ -541,6 +556,29 @@ QColor Theme::wizardHeaderBackgroundColor() const
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

View File

@ -132,6 +132,10 @@ public:
#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
*/
@ -231,6 +235,8 @@ public:
/** @return color for the setup wizard. */
virtual QColor wizardHeaderBackgroundColor() const;
virtual QPixmap wizardApplicationLogo() const;
/** @return logo for the setup wizard. */
virtual QPixmap wizardHeaderLogo() const;

View File

@ -9,6 +9,7 @@ add_library(testutils
STATIC
syncenginetestutils.cpp
pushnotificationstestutils.cpp
themeutils.cpp
)
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(Capabilities)
nextcloud_add_test(PushNotifications)
nextcloud_add_test(Theme)
if( UNIX AND NOT APPLE )
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;
};

View File

@ -80,6 +80,12 @@
<file>theme/colored/state-warning-64.png</file>
<file>theme/colored/state-warning-128.png</file>
<file>theme/colored/state-warning-256.png</file>
<file>theme/black/folder.png</file>
<file>theme/black/folder@2x.png</file>
<file>theme/white/folder.png</file>
<file>theme/white/folder@2x.png</file>
<file>theme/colored/folder.png</file>
<file>theme/colored/folder@2x.png</file>
<file>theme/black/control-next.svg</file>
<file>theme/black/control-prev.svg</file>
<file>theme/black/state-error.svg</file>
@ -124,6 +130,23 @@
<file>theme/white/state-warning-64.png</file>
<file>theme/white/state-warning-128.png</file>
<file>theme/white/state-warning-256.png</file>
<file>theme/white/wizard-files.png</file>
<file>theme/white/wizard-files@2x.png</file>
<file>theme/white/wizard-groupware.png</file>
<file>theme/white/wizard-groupware@2x.png</file>
<file>theme/white/wizard-nextcloud.png</file>
<file>theme/white/wizard-nextcloud@2x.png</file>
<file>theme/white/wizard-talk.png</file>
<file>theme/white/wizard-talk@2x.png</file>
<file>theme/black/wizard-files.png</file>
<file>theme/black/wizard-files@2x.png</file>
<file>theme/black/wizard-groupware.png</file>
<file>theme/black/wizard-groupware@2x.png</file>
<file>theme/black/wizard-nextcloud.png</file>
<file>theme/black/wizard-nextcloud@2x.png</file>
<file>theme/black/wizard-talk.png</file>
<file>theme/black/wizard-talk@2x.png</file>
<file>theme/black/wizard-files.png</file>
<file>theme/colored/wizard-files.png</file>
<file>theme/colored/wizard-files@2x.png</file>
<file>theme/colored/wizard-groupware.png</file>
@ -132,6 +155,13 @@
<file>theme/colored/wizard-nextcloud@2x.png</file>
<file>theme/colored/wizard-talk.png</file>
<file>theme/colored/wizard-talk@2x.png</file>
<file>theme/sync-arrow.svg</file>
<file>theme/white/external.png</file>
<file>theme/white/external@2x.png</file>
<file>theme/black/external.png</file>
<file>theme/black/external@2x.png</file>
<file>theme/colored/external.png</file>
<file>theme/colored/external@2x.png</file>
<file>theme/white/folder.svg</file>
<file>theme/white/more-apps.svg</file>
<file>theme/white/talk-app.svg</file>

BIN
theme/black/external.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

1
theme/black/external.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M3.2 2C2.53 2 2 2.54 2 3.2v9.6c0 .67.53 1.2 1.2 1.2h9.6c.67 0 1.2-.53 1.2-1.2V8.98l-1.2-1.2v5.02H3.2V3.2h5.02L7.08 2.06 7.02 2H3.2z"/><path d="M8.14 1l2.29 2.29L7 6.7 9.29 9l3.42-3.43L15 7.86V1z"/></svg>

After

Width:  |  Height:  |  Size: 275 B

BIN
theme/black/external@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
theme/black/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

1
theme/black/folder.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" width="32" version="1.1"><path fill="#000000" d="m3 4c-0.5 0-1 0.5-1 1v22c0 0.52 0.48 1 1 1h26c0.52 0 1-0.482 1-1v-18c0-0.5-0.5-1-1-1h-13l-4-4z"/></svg>

After

Width:  |  Height:  |  Size: 225 B

BIN
theme/black/folder@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" viewBox="0 0 16 16" width="16" version="1.1"><path fill="#000000" d="m1.5 2c-0.25 0-0.5 0.25-0.5 0.5v11c0 0.26 0.24 0.5 0.5 0.5h13c0.26 0 0.5-0.241 0.5-0.5v-9c0-0.25-0.25-0.5-0.5-0.5h-6.5l-2-2h-4.5zm8.75 3.5a1.25 1.25 0 0 1 1.25 1.25 1.25 1.25 0 0 1 -1.25 1.25 1.25 1.25 0 0 1 -0.8008 -0.291l-2.4512 1.2265a1.25 1.25 0 0 1 0.002 0.0645 1.25 1.25 0 0 1 -0.0039 0.0645l2.4531 1.2265a1.25 1.25 0 0 1 0.8008 -0.291 1.25 1.25 0 0 1 1.25 1.25 1.25 1.25 0 0 1 -1.25 1.25 1.25 1.25 0 0 1 -1.25 -1.25 1.25 1.25 0 0 1 0.0039 -0.064l-2.4531-1.227a1.25 1.25 0 0 1 -0.8008 0.291 1.25 1.25 0 0 1 -1.25 -1.25 1.25 1.25 0 0 1 1.25 -1.25 1.25 1.25 0 0 1 0.8008 0.291l2.4512-1.2265a1.25 1.25 0 0 1 -0.002 -0.0645 1.25 1.25 0 0 1 1.25 -1.25z"/></svg>

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 16 16" height="16" width="16" version="1.1"><path fill="#000000" d="m9 1c-1.746 0-3 1.43-3 2.8 0 1.4 0.1 2.4 0.8 3.5 0.224 0.29 0.485 0.35 0.7 0.6 0.135 0.5 0.24 1 0.1 1.5-0.436 0.153-0.85 0.332-1.27 0.5-0.51-0.273-1.1-0.5-1.61-0.7-0.07-0.28-0.02-0.487 0.05-0.75 0.12-0.125 0.23-0.18 0.36-0.3 0.37-0.45 0.39-1.21 0.39-1.75 0-0.8-0.72-1.4-1.5-1.4-0.87 0-1.5 0.72-1.5 1.4h-0.02c0 0.7 0.05 1.2 0.4 1.75 0.1 0.15 0.242 0.175 0.35 0.3 0.0674 0.25 0.121 0.5 0.05 0.75-0.64 0.223-1.244 0.5-1.8 0.8-0.42 0.3-0.233 0.182-0.5 1.15-0.124 0.5 1.3 0.73 2.32 0.81-0.05 0.275-0.12 0.64-0.32 1.34-0.32 1.25 4.353 1.7 6 1.7 2.43 0 6.313-0.456 5.98-1.7-0.52-1.94-0.208-1.71-0.98-2.3-1.09-0.654-2.452-1.167-3.6-1.6-0.15-0.557-0.04-0.97 0.1-1.5 0.235-0.25 0.5-0.36 0.72-0.6 0.69-0.884 0.78-2.424 0.78-3.5 0-1.586-1.43-2.8-3-2.8z"/></svg>

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="100"
width="200"
viewBox="0 0 200 100"
id="svg10"
sodipodi:docname="wizard-nextcloud.svg"
inkscape:export-filename="/home/felix/workspace/work/nextcloud-desktop/theme/white/wizard-nextcloud.png"
inkscape:export-xdpi="37.5"
inkscape:export-ydpi="37.5"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#808080"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3440"
inkscape:window-height="1440"
id="namedview12"
showgrid="false"
inkscape:zoom="5.0976562"
inkscape:cx="63.321716"
inkscape:cy="64.000003"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10"
inkscape:document-rotation="0" />
<g
stroke="#000000"
stroke-width="22"
fill="none"
id="g8"
style="fill:#000000;fill-opacity:0"
transform="matrix(0.80267111,0,0,0.80443207,-2.7419032,-5.2833187)">
<circle
cy="64"
cx="40"
r="26"
id="circle2"
style="fill:#000000;fill-opacity:0" />
<circle
cy="64"
cx="216"
r="26"
id="circle4"
style="fill:#000000;fill-opacity:0" />
<circle
cy="64"
cx="128"
r="46"
id="circle6"
style="fill:#000000;fill-opacity:0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
theme/black/wizard-talk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16"><path fill="#000000" d="m7.9992 0.999a6.9993 6.9994 0 0 0 -6.9992 6.9996 6.9993 6.9994 0 0 0 6.9992 6.9994 6.9993 6.9994 0 0 0 3.6308 -1.024c0.86024 0.34184 2.7871 1.356 3.2457 0.91794 0.47922-0.45765-0.56261-2.6116-0.81238-3.412a6.9993 6.9994 0 0 0 0.935 -3.4814 6.9993 6.9994 0 0 0 -6.9991 -6.9993zm0.0008 2.6611a4.34 4.3401 0 0 1 4.34 4.3401 4.34 4.3401 0 0 1 -4.34 4.3398 4.34 4.3401 0 0 1 -4.34 -4.3398 4.34 4.3401 0 0 1 4.34 -4.3401z" stroke-width="0.14"/></svg>

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
theme/colored/external.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#0082c9" d="M3.2 2C2.53 2 2 2.54 2 3.2v9.6c0 .67.53 1.2 1.2 1.2h9.6c.67 0 1.2-.53 1.2-1.2V8.98l-1.2-1.2v5.02H3.2V3.2h5.02L7.08 2.06 7.02 2H3.2z"/><path fill="#0082c9" d="M8.14 1l2.29 2.29L7 6.7 9.29 9l3.42-3.43L15 7.86V1z"/></svg>

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
theme/colored/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" version="1.1" height="16"><path fill="#0082c9" d="m1.5 2c-0.25 0-0.5 0.25-0.5 0.5v11c0 0.26 0.24 0.5 0.5 0.5h13c0.26 0 0.5-0.241 0.5-0.5v-9c0-0.25-0.25-0.5-0.5-0.5h-6.5l-2-2z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" width="32" version="1.1"><path fill="#0082c9" d="m3 4c-0.5 0-1 0.5-1 1v22c0 0.52 0.48 1 1 1h26c0.52 0 1-0.482 1-1v-18c0-0.5-0.5-1-1-1h-13l-4-4z"/></svg>

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 225 B

BIN
theme/colored/folder@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1 +1,81 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="128" width="256" viewBox="0 0 256 128" ><g stroke="#0082c9" stroke-width="22" fill="none"><circle cy="64" cx="40" r="26"/><circle cy="64" cx="216" r="26"/><circle cy="64" cx="128" r="46"/></g></svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="100"
width="200"
viewBox="0 0 200 100"
id="svg10"
sodipodi:docname="wizard-nextcloud.svg"
inkscape:export-filename="/home/felix/workspace/work/nextcloud-desktop/theme/white/wizard-nextcloud.png"
inkscape:export-xdpi="37.5"
inkscape:export-ydpi="37.5"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#808080"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3440"
inkscape:window-height="1440"
id="namedview12"
showgrid="false"
inkscape:zoom="5.0976562"
inkscape:cx="63.321716"
inkscape:cy="64.000003"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10"
inkscape:document-rotation="0" />
<g
stroke="#0082c9"
stroke-width="22"
fill="none"
id="g8"
style="fill:#000000;fill-opacity:0"
transform="matrix(0.80267111,0,0,0.80443207,-2.7419032,-5.2833187)">
<circle
cy="64"
cx="40"
r="26"
id="circle2"
style="fill:#000000;fill-opacity:0" />
<circle
cy="64"
cx="216"
r="26"
id="circle4"
style="fill:#000000;fill-opacity:0" />
<circle
cy="64"
cx="128"
r="46"
id="circle6"
style="fill:#000000;fill-opacity:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 261 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="126" viewBox="0 0 266.00001 126.0018" width="266" version="1.1" y="0px" x="0px" enable-background="new 0 0 196.6 72"><path style="color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;image-rendering:auto;white-space:normal;text-indent:0;enable-background:accumulate;text-transform:none;text-decoration-style:solid" fill="#fff" d="m134.19 6.1907c-26.05 0.0025-47.917 17.835-54.6 41.827-5.832-12.832-18.671-21.926-33.588-21.927-20.305 0.002-37 16.697-37.002 37.002-0.00364 20.309 16.693 37.008 37.002 37.01 14.918-0.002 27.748-9.1014 33.58-21.935 6.6801 23.995 28.558 41.832 54.608 41.834 25.904 0.002 47.668-17.641 54.486-41.43 5.9271 12.596 18.568 21.529 33.314 21.531 20.313 0.004 37.013-16.697 37.01-37.01-0.002-20.309-16.701-37.006-37.01-37.002-14.746 0.0017-27.395 8.933-33.321 21.531-6.81-23.79-28.57-41.433-54.47-41.431zm0 21.721c19.561-0.0013 35.186 15.62 35.188 35.181 0.001 19.563-15.625 35.19-35.188 35.188-19.56-0.001-35.182-15.627-35.18-35.188 0.002-19.559 15.62-35.179 35.18-35.181zm-88.188 19.9c8.5689 0.00099 15.28 6.7122 15.281 15.281 0.0015 8.5707-6.7103 15.288-15.281 15.289-8.5707-0.001-15.283-6.718-15.281-15.289 0.001-8.5689 6.7122-15.28 15.281-15.281zm175.99 0c8.5705-0.0015 15.288 6.7103 15.289 15.281 0.002 8.5726-6.7159 15.29-15.289 15.289-8.5708-0.001-15.283-6.718-15.281-15.289 0.00097-8.5689 6.7124-15.28 15.281-15.281z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="126" viewBox="0 0 266.00001 126.0018" width="266" version="1.1" y="0px" x="0px" enable-background="new 0 0 196.6 72"><path style="color-rendering:auto;text-decoration-color:#000000;color:#000000;isolation:auto;mix-blend-mode:normal;shape-rendering:auto;solid-color:#000000;block-progression:tb;text-decoration-line:none;image-rendering:auto;white-space:normal;text-indent:0;enable-background:accumulate;text-transform:none;text-decoration-style:solid" fill="#0082c9" d="m134.19 6.1907c-26.05 0.0025-47.917 17.835-54.6 41.827-5.832-12.832-18.671-21.926-33.588-21.927-20.305 0.002-37 16.697-37.002 37.002-0.00364 20.309 16.693 37.008 37.002 37.01 14.918-0.002 27.748-9.1014 33.58-21.935 6.6801 23.995 28.558 41.832 54.608 41.834 25.904 0.002 47.668-17.641 54.486-41.43 5.9271 12.596 18.568 21.529 33.314 21.531 20.313 0.004 37.013-16.697 37.01-37.01-0.002-20.309-16.701-37.006-37.01-37.002-14.746 0.0017-27.395 8.933-33.321 21.531-6.81-23.79-28.57-41.433-54.47-41.431zm0 21.721c19.561-0.0013 35.186 15.62 35.188 35.181 0.001 19.563-15.625 35.19-35.188 35.188-19.56-0.001-35.182-15.627-35.18-35.188 0.002-19.559 15.62-35.179 35.18-35.181zm-88.188 19.9c8.5689 0.00099 15.28 6.7122 15.281 15.281 0.0015 8.5707-6.7103 15.288-15.281 15.289-8.5707-0.001-15.283-6.718-15.281-15.289 0.001-8.5689 6.7122-15.28 15.281-15.281zm175.99 0c8.5705-0.0015 15.288 6.7103 15.289 15.281 0.002 8.5726-6.7159 15.29-15.289 15.289-8.5708-0.001-15.283-6.718-15.281-15.289 0.00097-8.5689 6.7124-15.28 15.281-15.281z"/></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

1
theme/sync-arrow.svg Normal file
View File

@ -0,0 +1 @@
<svg width="16" height="16" version="1.1" viewbox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m4.0293 4.0003a1 1 0 0 0-0.73633 0.29297l-3 3a1.0001 1.0001 0 0 0 0 1.4141l3 3a1 1 0 0 0 1.4141 0 1 1 0 0 0 0-1.4141l-1.293-1.293h9.1719l-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l3-3a1.0001 1.0001 0 0 0 0-1.4141l-3-3a1 1 0 0 0-0.67773-0.29297 1 1 0 0 0-0.73633 0.29297 1 1 0 0 0 0 1.4141l1.293 1.293h-9.1719l1.293-1.293a1 1 0 0 0 0-1.4141 1 1 0 0 0-0.67773-0.29297z" fill="#969696"/></svg>

After

Width:  |  Height:  |  Size: 505 B

BIN
theme/white/external.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

1
theme/white/external.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#ffffff" d="M3.2 2C2.53 2 2 2.54 2 3.2v9.6c0 .67.53 1.2 1.2 1.2h9.6c.67 0 1.2-.53 1.2-1.2V8.98l-1.2-1.2v5.02H3.2V3.2h5.02L7.08 2.06 7.02 2H3.2z"/><path fill="#ffffff" d="M8.14 1l2.29 2.29L7 6.7 9.29 9l3.42-3.43L15 7.86V1z"/></svg>

After

Width:  |  Height:  |  Size: 306 B

BIN
theme/white/external@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
theme/white/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" version="1.1" height="16"><path fill="#fff" d="m1.5 2c-0.25 0-0.5 0.25-0.5 0.5v11c0 0.26 0.24 0.5 0.5 0.5h13c0.26 0 0.5-0.241 0.5-0.5v-9c0-0.25-0.25-0.5-0.5-0.5h-6.5l-2-2z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 32 32" width="32" version="1.1"><path fill="#ffffff" d="m3 4c-0.5 0-1 0.5-1 1v22c0 0.52 0.48 1 1 1h26c0.52 0 1-0.482 1-1v-18c0-0.5-0.5-1-1-1h-13l-4-4z"/></svg>

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 225 B

BIN
theme/white/folder@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" viewBox="0 0 16 16" width="16" version="1.1"><path fill="#ffffff" d="m1.5 2c-0.25 0-0.5 0.25-0.5 0.5v11c0 0.26 0.24 0.5 0.5 0.5h13c0.26 0 0.5-0.241 0.5-0.5v-9c0-0.25-0.25-0.5-0.5-0.5h-6.5l-2-2h-4.5zm8.75 3.5a1.25 1.25 0 0 1 1.25 1.25 1.25 1.25 0 0 1 -1.25 1.25 1.25 1.25 0 0 1 -0.8008 -0.291l-2.4512 1.2265a1.25 1.25 0 0 1 0.002 0.0645 1.25 1.25 0 0 1 -0.0039 0.0645l2.4531 1.2265a1.25 1.25 0 0 1 0.8008 -0.291 1.25 1.25 0 0 1 1.25 1.25 1.25 1.25 0 0 1 -1.25 1.25 1.25 1.25 0 0 1 -1.25 -1.25 1.25 1.25 0 0 1 0.0039 -0.064l-2.4531-1.227a1.25 1.25 0 0 1 -0.8008 0.291 1.25 1.25 0 0 1 -1.25 -1.25 1.25 1.25 0 0 1 1.25 -1.25 1.25 1.25 0 0 1 0.8008 0.291l2.4512-1.2265a1.25 1.25 0 0 1 -0.002 -0.0645 1.25 1.25 0 0 1 1.25 -1.25z"/></svg>

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 16 16" height="16" width="16" version="1.1"><path fill="#ffffff" d="m9 1c-1.746 0-3 1.43-3 2.8 0 1.4 0.1 2.4 0.8 3.5 0.224 0.29 0.485 0.35 0.7 0.6 0.135 0.5 0.24 1 0.1 1.5-0.436 0.153-0.85 0.332-1.27 0.5-0.51-0.273-1.1-0.5-1.61-0.7-0.07-0.28-0.02-0.487 0.05-0.75 0.12-0.125 0.23-0.18 0.36-0.3 0.37-0.45 0.39-1.21 0.39-1.75 0-0.8-0.72-1.4-1.5-1.4-0.87 0-1.5 0.72-1.5 1.4h-0.02c0 0.7 0.05 1.2 0.4 1.75 0.1 0.15 0.242 0.175 0.35 0.3 0.0674 0.25 0.121 0.5 0.05 0.75-0.64 0.223-1.244 0.5-1.8 0.8-0.42 0.3-0.233 0.182-0.5 1.15-0.124 0.5 1.3 0.73 2.32 0.81-0.05 0.275-0.12 0.64-0.32 1.34-0.32 1.25 4.353 1.7 6 1.7 2.43 0 6.313-0.456 5.98-1.7-0.52-1.94-0.208-1.71-0.98-2.3-1.09-0.654-2.452-1.167-3.6-1.6-0.15-0.557-0.04-0.97 0.1-1.5 0.235-0.25 0.5-0.36 0.72-0.6 0.69-0.884 0.78-2.424 0.78-3.5 0-1.586-1.43-2.8-3-2.8z"/></svg>

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="100"
width="200"
viewBox="0 0 200 100"
id="svg10"
sodipodi:docname="wizard-nextcloud.svg"
inkscape:export-filename="/home/felix/workspace/work/nextcloud-desktop/theme/white/wizard-nextcloud.png"
inkscape:export-xdpi="37.5"
inkscape:export-ydpi="37.5"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#808080"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3440"
inkscape:window-height="1440"
id="namedview12"
showgrid="false"
inkscape:zoom="5.0976562"
inkscape:cx="63.321716"
inkscape:cy="64.000003"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg10"
inkscape:document-rotation="0" />
<g
stroke="#ffffff"
stroke-width="22"
fill="none"
id="g8"
style="fill:#000000;fill-opacity:0"
transform="matrix(0.80267111,0,0,0.80443207,-2.7419032,-5.2833187)">
<circle
cy="64"
cx="40"
r="26"
id="circle2"
style="fill:#000000;fill-opacity:0" />
<circle
cy="64"
cx="216"
r="26"
id="circle4"
style="fill:#000000;fill-opacity:0" />
<circle
cy="64"
cx="128"
r="46"
id="circle6"
style="fill:#000000;fill-opacity:0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
theme/white/wizard-talk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16"><path fill="#ffffff" d="m7.9992 0.999a6.9993 6.9994 0 0 0 -6.9992 6.9996 6.9993 6.9994 0 0 0 6.9992 6.9994 6.9993 6.9994 0 0 0 3.6308 -1.024c0.86024 0.34184 2.7871 1.356 3.2457 0.91794 0.47922-0.45765-0.56261-2.6116-0.81238-3.412a6.9993 6.9994 0 0 0 0.935 -3.4814 6.9993 6.9994 0 0 0 -6.9991 -6.9993zm0.0008 2.6611a4.34 4.3401 0 0 1 4.34 4.3401 4.34 4.3401 0 0 1 -4.34 4.3398 4.34 4.3401 0 0 1 -4.34 -4.3398 4.34 4.3401 0 0 1 4.34 -4.3401z" stroke-width="0.14"/></svg>

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB