mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-21 12:35:52 +03:00
Enable share to Talk and Email. Display correct icon. Added unit tests.
Signed-off-by: allexzander <blackslayer4@gmail.com>
This commit is contained in:
parent
3f6defe594
commit
a3fc812539
16 changed files with 306 additions and 67 deletions
|
@ -149,4 +149,4 @@ trigger:
|
|||
- master
|
||||
event:
|
||||
- pull_request
|
||||
- push
|
||||
- push
|
|
@ -104,6 +104,7 @@ set(client_SRCS
|
|||
elidedlabel.cpp
|
||||
headerbanner.cpp
|
||||
iconjob.cpp
|
||||
iconutils.cpp
|
||||
remotewipe.cpp
|
||||
tray/ActivityData.cpp
|
||||
tray/ActivityListModel.cpp
|
||||
|
|
92
src/gui/iconutils.cpp
Normal file
92
src/gui/iconutils.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "iconutils.h"
|
||||
|
||||
#include <theme.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QPainter>
|
||||
#include <QPixmapCache>
|
||||
#include <QSvgRenderer>
|
||||
|
||||
namespace OCC {
|
||||
namespace Ui {
|
||||
namespace IconUtils {
|
||||
QPixmap pixmapForBackground(const QString &fileName, const QColor &backgroundColor)
|
||||
{
|
||||
Q_ASSERT(!fileName.isEmpty());
|
||||
|
||||
// some icons are present in white or black only, so, we need to check both when needed
|
||||
const auto iconBaseColors = QStringList({ QStringLiteral("black"), QStringLiteral("white") });
|
||||
|
||||
const QString pixmapColor = backgroundColor.isValid() && !Theme::isDarkColor(backgroundColor) ? "black" : "white";
|
||||
|
||||
const QString cacheKey = fileName + QLatin1Char(',') + pixmapColor;
|
||||
|
||||
QPixmap cachedPixmap;
|
||||
|
||||
if (!QPixmapCache::find(cacheKey, &cachedPixmap)) {
|
||||
if (iconBaseColors.contains(pixmapColor)) {
|
||||
cachedPixmap = QPixmap::fromImage(QImage(QString(Theme::themePrefix) + pixmapColor + QLatin1Char('/') + fileName));
|
||||
QPixmapCache::insert(cacheKey, cachedPixmap);
|
||||
return cachedPixmap;
|
||||
}
|
||||
|
||||
const auto drawSvgWithCustomFillColor = [](const QString &sourceSvgPath, const QString &fillColor) {
|
||||
QSvgRenderer svgRenderer;
|
||||
|
||||
if (!svgRenderer.load(sourceSvgPath)) {
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
// render source image
|
||||
QImage svgImage(svgRenderer.defaultSize(), QImage::Format_ARGB32);
|
||||
{
|
||||
QPainter svgImagePainter(&svgImage);
|
||||
svgImage.fill(Qt::GlobalColor::transparent);
|
||||
svgRenderer.render(&svgImagePainter);
|
||||
}
|
||||
|
||||
// draw target image with custom fillColor
|
||||
QImage image(svgRenderer.defaultSize(), QImage::Format_ARGB32);
|
||||
image.fill(QColor(fillColor));
|
||||
{
|
||||
QPainter imagePainter(&image);
|
||||
imagePainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
imagePainter.drawImage(0, 0, svgImage);
|
||||
}
|
||||
|
||||
return QPixmap::fromImage(image);
|
||||
};
|
||||
|
||||
// find the first matching svg among base colors, if any
|
||||
const QString sourceSvg = [&]() {
|
||||
for (const auto &color : iconBaseColors) {
|
||||
const QString baseSVG(QString(Theme::themePrefix) + color + QLatin1Char('/') + fileName);
|
||||
|
||||
if (QFile(baseSVG).exists()) {
|
||||
return baseSVG;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}();
|
||||
|
||||
Q_ASSERT(!sourceSvg.isEmpty());
|
||||
if (sourceSvg.isEmpty()) {
|
||||
qWarning("Failed to find base svg for %s", qPrintable(cacheKey));
|
||||
return {};
|
||||
}
|
||||
|
||||
cachedPixmap = drawSvgWithCustomFillColor(sourceSvg, pixmapColor);
|
||||
QPixmapCache::insert(cacheKey, cachedPixmap);
|
||||
|
||||
Q_ASSERT(!cachedPixmap.isNull());
|
||||
if (cachedPixmap.isNull()) {
|
||||
qWarning("Failed to load pixmap for %s", qPrintable(cacheKey));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return cachedPixmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
src/gui/iconutils.h
Normal file
28
src/gui/iconutils.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) by Oleksandr Zolotov <alex@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.
|
||||
*/
|
||||
|
||||
#ifndef ICONUTILS_H
|
||||
#define ICONUTILS_H
|
||||
|
||||
#include <QColor>
|
||||
#include <QPixmap>
|
||||
|
||||
namespace OCC {
|
||||
namespace Ui {
|
||||
namespace IconUtils {
|
||||
QPixmap pixmapForBackground(const QString &fileName, const QColor &backgroundColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ICONUTILS_H
|
|
@ -296,7 +296,7 @@ UserGroupShare::UserGroupShare(AccountPtr account,
|
|||
, _note(note)
|
||||
, _expireDate(expireDate)
|
||||
{
|
||||
Q_ASSERT(shareType == TypeUser || shareType == TypeGroup || shareType == TypeEmail);
|
||||
Q_ASSERT(shareType == TypeUser || shareType == TypeGroup || shareType == TypeEmail || shareType == TypeRoom);
|
||||
Q_ASSERT(shareWith);
|
||||
}
|
||||
|
||||
|
@ -326,6 +326,11 @@ QDate UserGroupShare::getExpireDate() const
|
|||
|
||||
void UserGroupShare::setExpireDate(const QDate &date)
|
||||
{
|
||||
if (_expireDate == date) {
|
||||
emit expireDateSet();
|
||||
return;
|
||||
}
|
||||
|
||||
auto *job = new OcsShareJob(_account);
|
||||
connect(job, &OcsShareJob::shareJobFinished, this, &UserGroupShare::slotExpireDateSet);
|
||||
connect(job, &OcsJob::ocsError, this, &UserGroupShare::slotOcsError);
|
||||
|
@ -461,7 +466,7 @@ void ShareManager::slotSharesFetched(const QJsonDocument &reply)
|
|||
|
||||
if (shareType == Share::TypeLink) {
|
||||
newShare = parseLinkShare(data);
|
||||
} else if (shareType == Share::TypeGroup || shareType == Share::TypeUser || shareType == Share::TypeEmail) {
|
||||
} else if (shareType == Share::TypeGroup || shareType == Share::TypeUser || shareType == Share::TypeEmail || shareType == Share::TypeRoom) {
|
||||
newShare = parseUserGroupShare(data);
|
||||
} else {
|
||||
newShare = parseShare(data);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "thumbnailjob.h"
|
||||
#include "sharemanager.h"
|
||||
#include "theme.h"
|
||||
#include "iconutils.h"
|
||||
|
||||
#include "QProgressIndicator.h"
|
||||
#include <QBuffer>
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include <QColor>
|
||||
#include <QPainter>
|
||||
#include <QListWidget>
|
||||
#include <QSvgRenderer>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
@ -247,7 +249,7 @@ void ShareUserGroupWidget::slotSharesFetched(const QList<QSharedPointer<Share>>
|
|||
}
|
||||
|
||||
|
||||
Q_ASSERT(share->getShareType() == Share::TypeUser || share->getShareType() == Share::TypeGroup || share->getShareType() == Share::TypeEmail);
|
||||
Q_ASSERT(share->getShareType() == Share::TypeUser || share->getShareType() == Share::TypeGroup || share->getShareType() == Share::TypeEmail || share->getShareType() == Share::TypeRoom);
|
||||
auto userGroupShare = qSharedPointerDynamicCast<UserGroupShare>(share);
|
||||
auto *s = new ShareUserLine(_account, userGroupShare, _maxSharingPermissions, _isFile, _parentScrollArea);
|
||||
connect(s, &ShareUserLine::resizeRequested, this, &ShareUserGroupWidget::slotAdjustScrollWidgetSize);
|
||||
|
@ -501,7 +503,6 @@ ShareUserLine::ShareUserLine(AccountPtr account,
|
|||
_ui->permissionsEdit->setEnabled(enabled);
|
||||
connect(_ui->permissionsEdit, &QAbstractButton::clicked, this, &ShareUserLine::slotEditPermissionsChanged);
|
||||
connect(_ui->noteConfirmButton, &QAbstractButton::clicked, this, &ShareUserLine::onNoteConfirmButtonClicked);
|
||||
connect(_ui->confirmExpirationDate, &QAbstractButton::clicked, this, &ShareUserLine::setExpireDate);
|
||||
connect(_ui->calendar, &QDateTimeEdit::dateChanged, this, &ShareUserLine::setExpireDate);
|
||||
|
||||
connect(_share.data(), &UserGroupShare::noteSet, this, &ShareUserLine::disableProgessIndicatorAnimation);
|
||||
|
@ -521,10 +522,9 @@ ShareUserLine::ShareUserLine(AccountPtr account,
|
|||
|
||||
showNoteOptions(false);
|
||||
|
||||
// email shares do not support notes and expiration dates
|
||||
const bool isNoteAndExpirationDateSupported = _share->getShareType() != Share::ShareType::TypeEmail;
|
||||
const bool isNoteSupported = _share->getShareType() != Share::ShareType::TypeEmail && _share->getShareType() != Share::ShareType::TypeRoom;
|
||||
|
||||
if (isNoteAndExpirationDateSupported) {
|
||||
if (isNoteSupported) {
|
||||
_noteLinkAction = new QAction(tr("Note to recipient"));
|
||||
_noteLinkAction->setCheckable(true);
|
||||
menu->addAction(_noteLinkAction);
|
||||
|
@ -537,7 +537,9 @@ ShareUserLine::ShareUserLine(AccountPtr account,
|
|||
|
||||
showExpireDateOptions(false);
|
||||
|
||||
if (isNoteAndExpirationDateSupported) {
|
||||
const bool isExpirationDateSupported = _share->getShareType() != Share::ShareType::TypeEmail;
|
||||
|
||||
if (isExpirationDateSupported) {
|
||||
// email shares do not support expiration dates
|
||||
_expirationDateLinkAction = new QAction(tr("Set expiration date"));
|
||||
_expirationDateLinkAction->setCheckable(true);
|
||||
|
@ -545,9 +547,8 @@ ShareUserLine::ShareUserLine(AccountPtr account,
|
|||
connect(_expirationDateLinkAction, &QAction::triggered, this, &ShareUserLine::toggleExpireDateOptions);
|
||||
const auto expireDate = _share->getExpireDate().isValid() ? share.data()->getExpireDate() : QDate();
|
||||
if (!expireDate.isNull()) {
|
||||
_ui->calendar->setDate(expireDate);
|
||||
_expirationDateLinkAction->setChecked(true);
|
||||
showExpireDateOptions(true);
|
||||
showExpireDateOptions(true, expireDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -646,28 +647,7 @@ void ShareUserLine::loadAvatar()
|
|||
_ui->avatar->setMaximumWidth(avatarSize);
|
||||
_ui->avatar->setAlignment(Qt::AlignCenter);
|
||||
|
||||
/* Create the fallback avatar.
|
||||
*
|
||||
* This will be shown until the avatar image data arrives.
|
||||
*/
|
||||
const QByteArray hash = QCryptographicHash::hash(_ui->sharedWith->text().toUtf8(), QCryptographicHash::Md5);
|
||||
double hue = static_cast<quint8>(hash[0]) / 255.;
|
||||
|
||||
// See core/js/placeholder.js for details on colors and styling
|
||||
const QColor bg = QColor::fromHslF(hue, 0.7, 0.68);
|
||||
const QString style = QString(R"(* {
|
||||
color: #fff;
|
||||
background-color: %1;
|
||||
border-radius: %2px;
|
||||
text-align: center;
|
||||
line-height: %2px;
|
||||
font-size: %2px;
|
||||
})").arg(bg.name(), QString::number(avatarSize / 2));
|
||||
_ui->avatar->setStyleSheet(style);
|
||||
|
||||
// The avatar label is the first character of the user name.
|
||||
const QString text = _share->getShareWith()->displayName();
|
||||
_ui->avatar->setText(text.at(0).toUpper());
|
||||
setDefaultAvatar(avatarSize);
|
||||
|
||||
/* Start the network job to fetch the avatar data.
|
||||
*
|
||||
|
@ -680,6 +660,38 @@ void ShareUserLine::loadAvatar()
|
|||
}
|
||||
}
|
||||
|
||||
void ShareUserLine::setDefaultAvatar(int avatarSize)
|
||||
{
|
||||
/* Create the fallback avatar.
|
||||
*
|
||||
* This will be shown until the avatar image data arrives.
|
||||
*/
|
||||
|
||||
// See core/js/placeholder.js for details on colors and styling
|
||||
const auto backgroundColor = backgroundColorForShareeType(_share->getShareWith()->type());
|
||||
const QString style = QString(R"(* {
|
||||
color: #fff;
|
||||
background-color: %1;
|
||||
border-radius: %2px;
|
||||
text-align: center;
|
||||
line-height: %2px;
|
||||
font-size: %2px;
|
||||
})").arg(backgroundColor.name(), QString::number(avatarSize / 2));
|
||||
_ui->avatar->setStyleSheet(style);
|
||||
|
||||
const auto pixmap = pixmapForShareeType(_share->getShareWith()->type(), backgroundColor);
|
||||
|
||||
if (!pixmap.isNull()) {
|
||||
_ui->avatar->setPixmap(pixmap);
|
||||
} else {
|
||||
qCDebug(lcSharing) << "pixmap is null for share type: " << _share->getShareWith()->type();
|
||||
|
||||
// The avatar label is the first character of the user name.
|
||||
const auto text = _share->getShareWith()->displayName();
|
||||
_ui->avatar->setText(text.at(0).toUpper());
|
||||
}
|
||||
}
|
||||
|
||||
void ShareUserLine::slotAvatarLoaded(QImage avatar)
|
||||
{
|
||||
if (avatar.isNull())
|
||||
|
@ -926,13 +938,57 @@ void ShareUserLine::customizeStyle()
|
|||
_deleteShareButton->setIcon(deleteicon);
|
||||
|
||||
_ui->noteConfirmButton->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg"));
|
||||
_ui->confirmExpirationDate->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg"));
|
||||
_ui->progressIndicator->setColor(QGuiApplication::palette().color(QPalette::WindowText));
|
||||
|
||||
// make sure to force BackgroundRole to QPalette::WindowText for a lable, because it's parent always has a different role set that applies to children unless customized
|
||||
_ui->errorLabel->setBackgroundRole(QPalette::WindowText);
|
||||
}
|
||||
|
||||
QPixmap ShareUserLine::pixmapForShareeType(Sharee::Type type, const QColor &backgroundColor) const
|
||||
{
|
||||
switch (type) {
|
||||
case Sharee::Room:
|
||||
return Ui::IconUtils::pixmapForBackground(QStringLiteral("talk-app.svg"), backgroundColor);
|
||||
case Sharee::Email:
|
||||
return Ui::IconUtils::pixmapForBackground(QStringLiteral("email.svg"), backgroundColor);
|
||||
case Sharee::Group:
|
||||
case Sharee::Federated:
|
||||
case Sharee::Circle:
|
||||
case Sharee::User:
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QColor ShareUserLine::backgroundColorForShareeType(Sharee::Type type) const
|
||||
{
|
||||
switch (type) {
|
||||
case Sharee::Room:
|
||||
return Theme::instance()->wizardHeaderBackgroundColor();
|
||||
case Sharee::Email:
|
||||
return Theme::instance()->wizardHeaderTitleColor();
|
||||
case Sharee::Group:
|
||||
case Sharee::Federated:
|
||||
case Sharee::Circle:
|
||||
case Sharee::User:
|
||||
break;
|
||||
}
|
||||
|
||||
const auto calculateBackgroundBasedOnText = [this]() {
|
||||
const auto hash = QCryptographicHash::hash(_ui->sharedWith->text().toUtf8(), QCryptographicHash::Md5);
|
||||
Q_ASSERT(hash.size() > 0);
|
||||
if (hash.size() == 0) {
|
||||
qCWarning(lcSharing) << "Failed to calculate hash color for share:" << _share->path();
|
||||
return QColor{};
|
||||
}
|
||||
const double hue = static_cast<quint8>(hash[0]) / 255.;
|
||||
return QColor::fromHslF(hue, 0.7, 0.68);
|
||||
};
|
||||
|
||||
return calculateBackgroundBasedOnText();
|
||||
}
|
||||
|
||||
void ShareUserLine::showNoteOptions(bool show)
|
||||
{
|
||||
_ui->noteLabel->setVisible(show);
|
||||
|
@ -979,16 +1035,14 @@ void ShareUserLine::toggleExpireDateOptions(bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
void ShareUserLine::showExpireDateOptions(bool show)
|
||||
void ShareUserLine::showExpireDateOptions(bool show, const QDate &initialDate)
|
||||
{
|
||||
_ui->expirationLabel->setVisible(show);
|
||||
_ui->calendar->setVisible(show);
|
||||
_ui->confirmExpirationDate->setVisible(show);
|
||||
|
||||
if (show) {
|
||||
const QDate date = QDate::currentDate().addDays(1);
|
||||
_ui->calendar->setDate(date);
|
||||
_ui->calendar->setMinimumDate(date);
|
||||
_ui->calendar->setMinimumDate(QDate::currentDate().addDays(1));
|
||||
_ui->calendar->setDate(initialDate.isValid() ? initialDate : _ui->calendar->minimumDate());
|
||||
_ui->calendar->setFocus();
|
||||
}
|
||||
|
||||
|
|
|
@ -169,15 +169,19 @@ private slots:
|
|||
private:
|
||||
void displayPermissions();
|
||||
void loadAvatar();
|
||||
void setDefaultAvatar(int avatarSize);
|
||||
void customizeStyle();
|
||||
|
||||
QPixmap pixmapForShareeType(Sharee::Type type, const QColor &backgroundColor = QColor()) const;
|
||||
QColor backgroundColorForShareeType(Sharee::Type type) const;
|
||||
|
||||
void showNoteOptions(bool show);
|
||||
void toggleNoteOptions(bool enable);
|
||||
void onNoteConfirmButtonClicked();
|
||||
void setNote(const QString ¬e);
|
||||
|
||||
void toggleExpireDateOptions(bool enable);
|
||||
void showExpireDateOptions(bool show);
|
||||
void showExpireDateOptions(bool show, const QDate &initialDate = QDate());
|
||||
void setExpireDate();
|
||||
|
||||
void togglePasswordSetProgressAnimation(bool show);
|
||||
|
|
|
@ -273,20 +273,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="confirmExpirationDate">
|
||||
<property name="text">
|
||||
<string notr="true">…</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../theme.qrc">
|
||||
<normaloff>:/client/theme/confirm.svg</normaloff>:/client/theme/confirm.svg</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -197,7 +197,7 @@ QIcon Theme::themeIcon(const QString &name, bool sysTray) const
|
|||
return cached = QIcon::fromTheme(name);
|
||||
}
|
||||
|
||||
const auto svgName = QString::fromLatin1(":/client/theme/%1/%2.svg").arg(flavor).arg(name);
|
||||
const QString svgName = QString(Theme::themePrefix) + QString::fromLatin1("%1/%2.svg").arg(flavor).arg(name);
|
||||
QSvgRenderer renderer(svgName);
|
||||
const auto createPixmapFromSvg = [&renderer] (int size) {
|
||||
QImage img(size, size, QImage::Format_ARGB32);
|
||||
|
@ -208,7 +208,7 @@ QIcon Theme::themeIcon(const QString &name, bool sysTray) const
|
|||
};
|
||||
|
||||
const auto loadPixmap = [flavor, name] (int size) {
|
||||
const auto pixmapName = QString::fromLatin1(":/client/theme/%1/%2-%3.png").arg(flavor).arg(name).arg(size);
|
||||
const QString pixmapName = QString(Theme::themePrefix) + QString::fromLatin1("%1/%2-%3.png").arg(flavor).arg(name).arg(size);
|
||||
return QPixmap(pixmapName);
|
||||
};
|
||||
|
||||
|
@ -249,8 +249,8 @@ QString Theme::themeImagePath(const QString &name, int size, bool sysTray) const
|
|||
|
||||
// branded client may have several sizes of the same icon
|
||||
const QString filePath = (useSvg || size <= 0)
|
||||
? QString::fromLatin1(":/client/theme/%1/%2").arg(flavor).arg(name)
|
||||
: QString::fromLatin1(":/client/theme/%1/%2-%3").arg(flavor).arg(name).arg(size);
|
||||
? QString(Theme::themePrefix) + QString::fromLatin1("%1/%2").arg(flavor).arg(name)
|
||||
: QString(Theme::themePrefix) + QString::fromLatin1("%1/%2-%3").arg(flavor).arg(name).arg(size);
|
||||
|
||||
const QString svgPath = filePath + ".svg";
|
||||
if (useSvg) {
|
||||
|
@ -274,8 +274,7 @@ bool Theme::isHidpi(QPaintDevice *dev)
|
|||
|
||||
QIcon Theme::uiThemeIcon(const QString &iconName, bool uiHasDarkBg) const
|
||||
{
|
||||
QString themeResBasePath = ":/client/theme/";
|
||||
QString iconPath = themeResBasePath + (uiHasDarkBg?"white/":"black/") + iconName;
|
||||
QString iconPath = QString(Theme::themePrefix) + (uiHasDarkBg ? "white/" : "black/") + iconName;
|
||||
std::string icnPath = iconPath.toUtf8().constData();
|
||||
return QIcon(QPixmap(iconPath));
|
||||
}
|
||||
|
@ -303,8 +302,7 @@ QString Theme::hidpiFileName(const QString &iconName, const QColor &backgroundCo
|
|||
{
|
||||
const auto isDarkBackground = Theme::isDarkColor(backgroundColor);
|
||||
|
||||
const QString themeResBasePath = ":/client/theme/";
|
||||
const QString iconPath = themeResBasePath + (isDarkBackground ? "white/" : "black/") + iconName;
|
||||
const QString iconPath = QString(Theme::themePrefix) + (isDarkBackground ? "white/" : "black/") + iconName;
|
||||
|
||||
return Theme::hidpiFileName(iconPath, dev);
|
||||
}
|
||||
|
@ -406,7 +404,7 @@ bool Theme::systrayUseMonoIcons() const
|
|||
|
||||
bool Theme::monoIconsAvailable() const
|
||||
{
|
||||
QString themeDir = QString::fromLatin1(":/client/theme/%1/").arg(Theme::instance()->systrayIconFlavor(true));
|
||||
QString themeDir = QString(Theme::themePrefix) + QString::fromLatin1("%1/").arg(Theme::instance()->systrayIconFlavor(true));
|
||||
return QDir(themeDir).exists();
|
||||
}
|
||||
|
||||
|
@ -510,7 +508,7 @@ QVariant Theme::customMedia(CustomMediaType type)
|
|||
break;
|
||||
}
|
||||
|
||||
QString imgPath = QString::fromLatin1(":/client/theme/colored/%1.png").arg(key);
|
||||
QString imgPath = QString(Theme::themePrefix) + QString::fromLatin1("colored/%1.png").arg(key);
|
||||
if (QFile::exists(imgPath)) {
|
||||
QPixmap pix(imgPath);
|
||||
if (pix.isNull()) {
|
||||
|
@ -581,11 +579,11 @@ QColor Theme::wizardHeaderBackgroundColor() const
|
|||
QPixmap Theme::wizardApplicationLogo() const
|
||||
{
|
||||
if (!Theme::isBranded()) {
|
||||
return QPixmap(Theme::hidpiFileName(":/client/theme/colored/wizard-nextcloud.png"));
|
||||
return QPixmap(Theme::hidpiFileName(QString(Theme::themePrefix) + "colored/wizard-nextcloud.png"));
|
||||
}
|
||||
#ifdef APPLICATION_WIZARD_USE_CUSTOM_LOGO
|
||||
const auto useSvg = shouldPreferSvg();
|
||||
const auto logoBasePath = QStringLiteral(":/client/theme/colored/wizard_logo");
|
||||
const QString logoBasePath = QString(Theme::themePrefix) + QStringLiteral("colored/wizard_logo");
|
||||
if (useSvg) {
|
||||
const auto maxHeight = Theme::isHidpi() ? 200 : 100;
|
||||
const auto maxWidth = 2 * maxHeight;
|
||||
|
@ -605,7 +603,7 @@ QPixmap Theme::wizardHeaderLogo() const
|
|||
{
|
||||
#ifdef APPLICATION_WIZARD_USE_CUSTOM_LOGO
|
||||
const auto useSvg = shouldPreferSvg();
|
||||
const auto logoBasePath = QStringLiteral(":/client/theme/colored/wizard_logo");
|
||||
const QString logoBasePath = QString(Theme::themePrefix) + QStringLiteral("colored/wizard_logo");
|
||||
if (useSvg) {
|
||||
const auto maxHeight = 64;
|
||||
const auto maxWidth = 2 * maxHeight;
|
||||
|
|
|
@ -535,6 +535,8 @@ public:
|
|||
*/
|
||||
virtual bool showVirtualFilesOption() const;
|
||||
|
||||
static constexpr const char *themePrefix = ":/client/theme/";
|
||||
|
||||
protected:
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
QIcon themeIcon(const QString &name, bool sysTray = false) const;
|
||||
|
|
|
@ -57,6 +57,7 @@ nextcloud_add_test(FolderWatcher)
|
|||
nextcloud_add_test(Capabilities)
|
||||
nextcloud_add_test(PushNotifications)
|
||||
nextcloud_add_test(Theme)
|
||||
nextcloud_add_test(IconUtils)
|
||||
nextcloud_add_test(NotificationCache)
|
||||
|
||||
if( UNIX AND NOT APPLE )
|
||||
|
|
64
test/testiconutils.cpp
Normal file
64
test/testiconutils.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) by Oleksandr Zolotov <alex@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 "iconutils.h"
|
||||
|
||||
class TestIconUtils : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TestIconUtils()
|
||||
{
|
||||
Q_INIT_RESOURCE(resources);
|
||||
Q_INIT_RESOURCE(theme);
|
||||
}
|
||||
|
||||
private slots:
|
||||
void testPixmapForBackground()
|
||||
{
|
||||
const QDir blackSvgDir(QString(OCC::Theme::themePrefix) + QStringLiteral("black"));
|
||||
const QStringList blackImages = blackSvgDir.entryList(QStringList("*.svg"));
|
||||
|
||||
const QDir whiteSvgDir(QString(OCC::Theme::themePrefix) + QStringLiteral("white"));
|
||||
const QStringList whiteImages = whiteSvgDir.entryList(QStringList("*.svg"));
|
||||
|
||||
if (blackImages.size() > 0) {
|
||||
// white pixmap for dark background - should not fail
|
||||
QVERIFY(!OCC::Ui::IconUtils::pixmapForBackground(whiteImages.at(0), QColor("blue")).isNull());
|
||||
}
|
||||
|
||||
if (whiteImages.size() > 0) {
|
||||
// black pixmap for bright background - should not fail
|
||||
QVERIFY(!OCC::Ui::IconUtils::pixmapForBackground(blackImages.at(0), QColor("yellow")).isNull());
|
||||
}
|
||||
|
||||
const auto blackImagesExclusive = QSet<QString>(blackImages.begin(), blackImages.end()).subtract(QSet<QString>(whiteImages.begin(), whiteImages.end()));
|
||||
const auto whiteImagesExclusive = QSet<QString>(whiteImages.begin(), whiteImages.end()).subtract(QSet<QString>(blackImages.begin(), blackImages.end()));
|
||||
|
||||
if (blackImagesExclusive != whiteImagesExclusive) {
|
||||
// black pixmap for dark background - should fail as we don't have this image in black
|
||||
QVERIFY(OCC::Ui::IconUtils::pixmapForBackground(blackImagesExclusive.values().at(0), QColor("blue")).isNull());
|
||||
|
||||
// white pixmap for bright background - should fail as we don't have this image in white
|
||||
QVERIFY(OCC::Ui::IconUtils::pixmapForBackground(whiteImagesExclusive.values().at(0), QColor("yellow")).isNull());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN(TestIconUtils)
|
||||
#include "testiconutils.moc"
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "theme.h"
|
||||
#include "themeutils.h"
|
||||
#include "iconutils.h"
|
||||
|
||||
class TestTheme : public QObject
|
||||
{
|
||||
|
|
|
@ -198,5 +198,6 @@
|
|||
<file>theme/colored/user-status-invisible.svg</file>
|
||||
<file>theme/colored/user-status-away.svg</file>
|
||||
<file>theme/colored/user-status-dnd.svg</file>
|
||||
<file>theme/black/email.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -198,5 +198,6 @@
|
|||
<file>theme/colored/user-status-invisible.svg</file>
|
||||
<file>theme/colored/user-status-away.svg</file>
|
||||
<file>theme/colored/user-status-dnd.svg</file>
|
||||
<file>theme/black/email.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
1
theme/black/email.svg
Normal file
1
theme/black/email.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 24 24" width="16px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>
|
After Width: | Height: | Size: 267 B |
Loading…
Reference in a new issue