Removing QWidget dependency from src/core.

This commit is contained in:
louib 2021-03-13 14:07:49 -05:00 committed by Jonathan White
parent 6f5bbf7ad1
commit 004f2b6801
46 changed files with 298 additions and 313 deletions

View File

@ -266,11 +266,11 @@ if(CMAKE_BUILD_TYPE_LOWER STREQUAL "debug")
endif()
if (NOT HAIKU)
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8.999) OR CMAKE_COMPILER_IS_CLANGXX)
add_gcc_compiler_flags("-fstack-protector-strong")
else()
add_gcc_compiler_flags("-fstack-protector --param=ssp-buffer-size=4")
endif()
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8.999) OR CMAKE_COMPILER_IS_CLANGXX)
add_gcc_compiler_flags("-fstack-protector-strong")
else()
add_gcc_compiler_flags("-fstack-protector --param=ssp-buffer-size=4")
endif()
endif()
add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual")
@ -466,7 +466,7 @@ elseif(WIN32)
message(STATUS "Using windeployqt: ${WINDEPLOYQT_EXE}")
endif()
# Debian sets the the build type to None for package builds.
# Debian sets the build type to None for package builds.
# Make sure we don't enable asserts there.
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)

View File

@ -39,7 +39,6 @@ set(keepassx_SOURCES
core/Config.cpp
core/CustomData.cpp
core/Database.cpp
core/DatabaseIcons.cpp
core/Entry.cpp
core/EntryAttachments.cpp
core/EntryAttributes.cpp
@ -71,7 +70,6 @@ set(keepassx_SOURCES
crypto/kdf/Argon2Kdf.cpp
format/CsvExporter.cpp
format/CsvParser.cpp
format/HtmlExporter.cpp
format/KeePass1Reader.cpp
format/KeePass2.cpp
format/KeePass2RandomStream.cpp
@ -101,6 +99,7 @@ set(keepassx_SOURCES
gui/CategoryListWidget.cpp
gui/Clipboard.cpp
gui/CloneDialog.cpp
gui/DatabaseIcons.cpp
gui/DatabaseOpenWidget.cpp
gui/DatabaseTabWidget.cpp
gui/DatabaseWidget.cpp
@ -114,6 +113,7 @@ set(keepassx_SOURCES
gui/FileDialog.cpp
gui/Font.cpp
gui/GuiTools.cpp
gui/HtmlExporter.cpp
gui/IconModels.cpp
gui/KeePass1OpenWidget.cpp
gui/KMessageWidget.cpp

View File

@ -20,8 +20,12 @@
#include <QFont>
#include "core/Entry.h"
#include "core/Global.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "gui/DatabaseIcons.h"
#include "gui/Icons.h"
AutoTypeMatchModel::AutoTypeMatchModel(QObject* parent)
: QAbstractTableModel(parent)
@ -114,11 +118,11 @@ QVariant AutoTypeMatchModel::data(const QModelIndex& index, int role) const
switch (index.column()) {
case ParentGroup:
if (match.first->group()) {
return match.first->group()->iconPixmap();
return Icons::groupIconPixmap(match.first->group());
}
break;
case Title:
return match.first->iconPixmap();
return Icons::entryIconPixmap(match.first);
}
} else if (role == Qt::FontRole) {
QFont font;

View File

@ -44,7 +44,7 @@ set(cli_SOURCES
Show.cpp)
add_library(cli STATIC ${cli_SOURCES})
target_link_libraries(cli Qt5::Core Qt5::Widgets)
target_link_libraries(cli Qt5::Core)
find_package(Readline)

View File

@ -19,7 +19,7 @@
#include "Entry.h"
#include "core/Config.h"
#include "core/DatabaseIcons.h"
#include "core/Database.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "core/PasswordHealth.h"
@ -159,40 +159,6 @@ const QString Entry::uuidToHex() const
return Tools::uuidToHex(m_uuid);
}
QImage Entry::icon() const
{
if (m_data.customIcon.isNull()) {
return databaseIcons()->icon(m_data.iconNumber).toImage();
} else {
Q_ASSERT(database());
if (database()) {
return database()->metadata()->customIcon(m_data.customIcon);
} else {
return QImage();
}
}
}
QPixmap Entry::iconPixmap(IconSize size) const
{
QPixmap icon(size, size);
if (m_data.customIcon.isNull()) {
icon = databaseIcons()->icon(m_data.iconNumber, size);
} else {
Q_ASSERT(database());
if (database()) {
icon = database()->metadata()->customIconPixmap(m_data.customIcon, size);
}
}
if (isExpired()) {
icon = databaseIcons()->applyBadge(icon, DatabaseIcons::Badges::Expired);
}
return icon;
}
int Entry::iconNumber() const
{
return m_data.iconNumber;
@ -1217,7 +1183,8 @@ void Entry::setGroup(Group* group)
// copy custom icon to the new database
if (!iconUuid().isNull() && group->database() && m_group->database()->metadata()->hasCustomIcon(iconUuid())
&& !group->database()->metadata()->hasCustomIcon(iconUuid())) {
group->database()->metadata()->addCustomIcon(iconUuid(), icon());
group->database()->metadata()->addCustomIcon(iconUuid(),
m_group->database()->metadata()->customIcon(iconUuid()));
}
}
}

View File

@ -19,7 +19,7 @@
#ifndef KEEPASSX_ENTRY_H
#define KEEPASSX_ENTRY_H
#include <QImage>
#include <QMap>
#include <QPointer>
#include <QUuid>
@ -80,8 +80,6 @@ public:
~Entry();
const QUuid& uuid() const;
const QString uuidToHex() const;
QImage icon() const;
QPixmap iconPixmap(IconSize size = IconSize::Default) const;
int iconNumber() const;
const QUuid& iconUuid() const;
QString foregroundColor() const;

View File

@ -45,13 +45,6 @@
static const auto TRUE_STR = QStringLiteral("true");
static const auto FALSE_STR = QStringLiteral("false");
enum IconSize
{
Default,
Medium,
Large
};
enum class AuthDecision
{
Undecided,

View File

@ -20,14 +20,16 @@
#include "config-keepassx.h"
#include "core/Config.h"
#include "core/DatabaseIcons.h"
#include "core/Metadata.h"
#include "core/Tools.h"
#ifdef WITH_XC_KEESHARE
#include "keeshare/KeeShare.h"
#endif
#include "core/Global.h"
#include "core/Metadata.h"
#include "core/Tools.h"
#include <QtConcurrent>
#include <QtConcurrentFilter>
const int Group::DefaultIconNumber = 48;
@ -123,44 +125,6 @@ QString Group::notes() const
return m_data.notes;
}
QImage Group::icon() const
{
if (m_data.customIcon.isNull()) {
return databaseIcons()->icon(m_data.iconNumber).toImage();
} else {
Q_ASSERT(m_db);
if (m_db) {
return m_db->metadata()->customIcon(m_data.customIcon);
} else {
return QImage();
}
}
}
QPixmap Group::iconPixmap(IconSize size) const
{
QPixmap icon(size, size);
if (m_data.customIcon.isNull()) {
icon = databaseIcons()->icon(m_data.iconNumber, size);
} else {
Q_ASSERT(m_db);
if (m_db) {
icon = m_db->metadata()->customIconPixmap(m_data.customIcon, size);
}
}
if (isExpired()) {
icon = databaseIcons()->applyBadge(icon, DatabaseIcons::Badges::Expired);
}
#ifdef WITH_XC_KEESHARE
else if (KeeShare::isShared(this)) {
icon = KeeShare::indicatorBadge(this, icon);
}
#endif
return icon;
}
int Group::iconNumber() const
{
return m_data.iconNumber;
@ -469,7 +433,7 @@ void Group::setParent(Group* parent, int index)
// copy custom icon to the new database
if (!iconUuid().isNull() && parent->m_db && m_db->metadata()->hasCustomIcon(iconUuid())
&& !parent->m_db->metadata()->hasCustomIcon(iconUuid())) {
parent->m_db->metadata()->addCustomIcon(iconUuid(), icon());
parent->m_db->metadata()->addCustomIcon(iconUuid(), m_db->metadata()->customIcon(iconUuid()));
}
}
if (m_db != parent->m_db) {

View File

@ -19,7 +19,7 @@
#ifndef KEEPASSX_GROUP_H
#define KEEPASSX_GROUP_H
#include <QImage>
#include <QPointer>
#include "core/CustomData.h"
#include "core/Database.h"
@ -82,8 +82,6 @@ public:
const QString uuidToHex() const;
QString name() const;
QString notes() const;
QImage icon() const;
QPixmap iconPixmap(IconSize size = IconSize::Default) const;
int iconNumber() const;
const QUuid& iconUuid() const;
const TimeInfo& timeInfo() const;

View File

@ -611,8 +611,7 @@ Merger::ChangeList Merger::mergeMetadata(const MergeContext& context)
for (const auto& iconUuid : sourceMetadata->customIconsOrder()) {
if (!targetMetadata->hasCustomIcon(iconUuid)) {
QImage customIcon = sourceMetadata->customIcon(iconUuid);
targetMetadata->addCustomIcon(iconUuid, customIcon);
targetMetadata->addCustomIcon(iconUuid, sourceMetadata->customIcon(iconUuid));
changes << tr("Adding missing icon %1").arg(QString::fromLatin1(iconUuid.toRfc4122().toHex()));
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
*
* 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
@ -17,7 +18,8 @@
#include "Metadata.h"
#include "core/DatabaseIcons.h"
#include "core/Clock.h"
#include "core/Entry.h"
#include "core/Group.h"
#include <QApplication>
@ -64,7 +66,6 @@ void Metadata::clear()
{
init();
m_customIcons.clear();
m_customIconsRaw.clear();
m_customIconsOrder.clear();
m_customIconsHashes.clear();
m_customData->clear();
@ -175,33 +176,14 @@ bool Metadata::protectNotes() const
return m_data.protectNotes;
}
QImage Metadata::customIcon(const QUuid& uuid) const
QByteArray Metadata::customIcon(const QUuid& uuid) const
{
return m_customIconsRaw.value(uuid);
}
QPixmap Metadata::customIconPixmap(const QUuid& uuid, IconSize size) const
{
if (!hasCustomIcon(uuid)) {
return {};
}
return m_customIcons.value(uuid).pixmap(databaseIcons()->iconSize(size));
}
QHash<QUuid, QPixmap> Metadata::customIconsPixmaps(IconSize size) const
{
QHash<QUuid, QPixmap> result;
for (const QUuid& uuid : m_customIconsOrder) {
result.insert(uuid, customIconPixmap(uuid, size));
}
return result;
return m_customIcons.value(uuid);
}
bool Metadata::hasCustomIcon(const QUuid& uuid) const
{
return m_customIconsRaw.contains(uuid);
return m_customIcons.contains(uuid);
}
QList<QUuid> Metadata::customIconsOrder() const
@ -357,32 +339,19 @@ void Metadata::setProtectNotes(bool value)
set(m_data.protectNotes, value);
}
void Metadata::addCustomIcon(const QUuid& uuid, const QImage& image)
void Metadata::addCustomIcon(const QUuid& uuid, const QByteArray& iconData)
{
Q_ASSERT(!uuid.isNull());
Q_ASSERT(!m_customIconsRaw.contains(uuid));
Q_ASSERT(!m_customIcons.contains(uuid));
m_customIconsRaw[uuid] = image;
m_customIcons[uuid] = iconData;
// remove all uuids to prevent duplicates in release mode
m_customIconsOrder.removeAll(uuid);
m_customIconsOrder.append(uuid);
// Associate image hash to uuid
QByteArray hash = hashImage(image);
QByteArray hash = hashIcon(iconData);
m_customIconsHashes[hash] = uuid;
Q_ASSERT(m_customIconsRaw.count() == m_customIconsOrder.count());
// TODO: This check can go away when we move all QIcon handling outside of core
// On older versions of Qt, loading a QPixmap from QImage outside of a GUI
// environment causes ASAN to fail and crash on nullptr violation
static bool isGui = qApp->inherits("QGuiApplication");
if (isGui) {
// Generate QIcon with pre-baked resolutions
auto basePixmap = QPixmap::fromImage(image.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
QIcon icon(basePixmap);
m_customIcons.insert(uuid, icon);
} else {
m_customIcons.insert(uuid, QIcon());
}
Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count());
emitModified();
}
@ -390,24 +359,23 @@ void Metadata::addCustomIcon(const QUuid& uuid, const QImage& image)
void Metadata::removeCustomIcon(const QUuid& uuid)
{
Q_ASSERT(!uuid.isNull());
Q_ASSERT(m_customIconsRaw.contains(uuid));
Q_ASSERT(m_customIcons.contains(uuid));
// Remove hash record only if this is the same uuid
QByteArray hash = hashImage(m_customIconsRaw[uuid]);
QByteArray hash = hashIcon(m_customIcons[uuid]);
if (m_customIconsHashes.contains(hash) && m_customIconsHashes[hash] == uuid) {
m_customIconsHashes.remove(hash);
}
m_customIcons.remove(uuid);
m_customIconsRaw.remove(uuid);
m_customIconsOrder.removeAll(uuid);
Q_ASSERT(m_customIconsRaw.count() == m_customIconsOrder.count());
Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count());
emitModified();
}
QUuid Metadata::findCustomIcon(const QImage& candidate)
QUuid Metadata::findCustomIcon(const QByteArray& candidate)
{
QByteArray hash = hashImage(candidate);
QByteArray hash = hashIcon(candidate);
return m_customIconsHashes.value(hash, QUuid());
}
@ -422,14 +390,9 @@ void Metadata::copyCustomIcons(const QSet<QUuid>& iconList, const Metadata* othe
}
}
QByteArray Metadata::hashImage(const QImage& image)
QByteArray Metadata::hashIcon(const QByteArray& iconData)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
auto data = QByteArray(reinterpret_cast<const char*>(image.bits()), static_cast<int>(image.sizeInBytes()));
#else
auto data = QByteArray(reinterpret_cast<const char*>(image.bits()), image.byteCount());
#endif
return QCryptographicHash::hash(data, QCryptographicHash::Md5);
return QCryptographicHash::hash(iconData, QCryptographicHash::Md5);
}
void Metadata::setRecycleBinEnabled(bool value)

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
*
* 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
@ -19,7 +20,7 @@
#define KEEPASSX_METADATA_H
#include <QDateTime>
#include <QIcon>
#include <QHash>
#include <QPointer>
#include <QUuid>
@ -78,10 +79,8 @@ public:
bool protectPassword() const;
bool protectUrl() const;
bool protectNotes() const;
QImage customIcon(const QUuid& uuid) const;
QByteArray customIcon(const QUuid& uuid) const;
bool hasCustomIcon(const QUuid& uuid) const;
QPixmap customIconPixmap(const QUuid& uuid, IconSize size = IconSize::Default) const;
QHash<QUuid, QPixmap> customIconsPixmaps(IconSize size = IconSize::Default) const;
QList<QUuid> customIconsOrder() const;
bool recycleBinEnabled() const;
Group* recycleBin();
@ -117,10 +116,10 @@ public:
void setProtectPassword(bool value);
void setProtectUrl(bool value);
void setProtectNotes(bool value);
void addCustomIcon(const QUuid& uuid, const QImage& image);
void addCustomIcon(const QUuid& uuid, const QByteArray& iconData);
void removeCustomIcon(const QUuid& uuid);
void copyCustomIcons(const QSet<QUuid>& iconList, const Metadata* otherMetadata);
QUuid findCustomIcon(const QImage& candidate);
QUuid findCustomIcon(const QByteArray& candidate);
void setRecycleBinEnabled(bool value);
void setRecycleBin(Group* group);
void setRecycleBinChanged(const QDateTime& value);
@ -148,13 +147,12 @@ private:
template <class P, class V> bool set(P& property, const V& value);
template <class P, class V> bool set(P& property, const V& value, QDateTime& dateTime);
QByteArray hashImage(const QImage& image);
QByteArray hashIcon(const QByteArray& iconData);
MetadataData m_data;
QHash<QUuid, QIcon> m_customIcons;
QHash<QUuid, QImage> m_customIconsRaw;
QList<QUuid> m_customIconsOrder;
QHash<QUuid, QByteArray> m_customIcons;
QHash<QByteArray, QUuid> m_customIconsHashes;
QPointer<Group> m_recycleBin;

View File

@ -24,9 +24,11 @@
#include "core/Clock.h"
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QEventLoop>
#include <QFileInfo>
#include <QImageReader>
#include <QIODevice>
#include <QLocale>
#include <QMetaProperty>
#include <QRegularExpression>
@ -172,24 +174,6 @@ namespace Tools
}
}
QString imageReaderFilter()
{
const QList<QByteArray> formats = QImageReader::supportedImageFormats();
QStringList formatsStringList;
for (const QByteArray& format : formats) {
for (char codePoint : format) {
if (!QChar(codePoint).isLetterOrNumber()) {
continue;
}
}
formatsStringList.append("*." + QString::fromLatin1(format).toLower());
}
return formatsStringList.join(" ");
}
bool isHex(const QByteArray& ba)
{
for (const uchar c : ba) {

View File

@ -32,7 +32,6 @@ namespace Tools
QString humanReadableFileSize(qint64 bytes, quint32 precision = 2);
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
bool readAllFromDevice(QIODevice* device, QByteArray& data);
QString imageReaderFilter();
bool isHex(const QByteArray& ba);
bool isBase64(const QByteArray& ba);
void sleep(int ms);

View File

@ -24,6 +24,7 @@
#include "fdosecrets/widgets/RowButtonHelper.h"
#include "core/Entry.h"
#include "gui/Icons.h"
#include <QWindow>
@ -250,7 +251,7 @@ QVariant AccessControlDialog::EntryModel::data(const QModelIndex& index, int rol
case Qt::DisplayRole:
return entry->title();
case Qt::DecorationRole:
return entry->icon();
return Icons::entryIconPixmap(entry);
case Qt::CheckStateRole:
return QVariant::fromValue(m_selected.contains(entry) ? Qt::Checked : Qt::Unchecked);
default:

View File

@ -147,7 +147,7 @@ namespace FdoSecrets
case Qt::DisplayRole:
return group->name();
case Qt::DecorationRole:
return group->iconPixmap();
return Icons::groupIconPixmap(group);
case Qt::FontRole:
if (group->isExpired()) {
QFont font;

View File

@ -17,7 +17,7 @@
#include "KdbxXmlReader.h"
#include "KeePass2RandomStream.h"
#include "core/DatabaseIcons.h"
#include "core/Clock.h"
#include "core/Endian.h"
#include "core/Group.h"
#include "core/Tools.h"
@ -346,7 +346,7 @@ void KdbxXmlReader::parseIcon()
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Icon");
QUuid uuid;
QImage icon;
QByteArray iconData;
bool uuidSet = false;
bool iconSet = false;
@ -355,7 +355,7 @@ void KdbxXmlReader::parseIcon()
uuid = readUuid();
uuidSet = !uuid.isNull();
} else if (m_xml.name() == "Data") {
icon.loadFromData(readBinary());
iconData = readBinary();
iconSet = true;
} else {
skipCurrentElement();
@ -367,7 +367,7 @@ void KdbxXmlReader::parseIcon()
if (m_meta->hasCustomIcon(uuid)) {
uuid = QUuid::createUuid();
}
m_meta->addCustomIcon(uuid, icon);
m_meta->addCustomIcon(uuid, iconData);
return;
}
@ -509,9 +509,6 @@ Group* KdbxXmlReader::parseGroup()
raiseError(tr("Invalid group icon number"));
}
iconId = 0;
} else if (iconId >= databaseIcons()->count()) {
qWarning("KdbxXmlReader::parseGroup: icon id \"%d\" not supported", iconId);
iconId = databaseIcons()->count() - 1;
}
group->setIcon(iconId);

View File

@ -162,19 +162,12 @@ void KdbxXmlWriter::writeCustomIcons()
m_xml.writeEndElement();
}
void KdbxXmlWriter::writeIcon(const QUuid& uuid, const QImage& icon)
void KdbxXmlWriter::writeIcon(const QUuid& uuid, const QByteArray& iconData)
{
m_xml.writeStartElement("Icon");
writeUuid("UUID", uuid);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
// TODO: check !icon.save()
icon.save(&buffer, "PNG");
buffer.close();
writeBinary("Data", ba);
writeBinary("Data", iconData);
m_xml.writeEndElement();
}

View File

@ -18,6 +18,7 @@
#ifndef KEEPASSX_KDBXXMLWRITER_H
#define KEEPASSX_KDBXXMLWRITER_H
#include <QDateTime>
#include <QXmlStreamWriter>
#include "core/Group.h"
@ -46,7 +47,7 @@ private:
void writeMetadata();
void writeMemoryProtection();
void writeCustomIcons();
void writeIcon(const QUuid& uuid, const QImage& icon);
void writeIcon(const QUuid& uuid, const QByteArray& iconData);
void writeBinaries();
void writeCustomData(const CustomData* customData);
void writeCustomDataItem(const QString& key, const QString& value);

View File

@ -857,13 +857,9 @@ bool KeePass1Reader::parseCustomIcons4(const QByteArray& data)
if (static_cast<quint32>(data.size()) < (pos + iconSize)) {
return false;
}
QImage icon = QImage::fromData(data.mid(pos, iconSize));
QByteArray icon = data.mid(pos, iconSize);
pos += iconSize;
if (icon.width() != 16 || icon.height() != 16) {
icon = icon.scaled(16, 16);
}
QUuid uuid = QUuid::createUuid();
iconUuids.append(uuid);
m_db->metadata()->addCustomIcon(uuid, icon);

View File

@ -57,8 +57,9 @@ DatabaseIcons* DatabaseIcons::instance()
QPixmap DatabaseIcons::icon(int index, IconSize size)
{
if (index < 0 || index >= count()) {
qWarning("DatabaseIcons::icon: invalid icon index %d", index);
return {};
qWarning("DatabaseIcons::icon: invalid icon index %d, using 0 instead", index);
index = 0;
Q_ASSERT_X(false, "DatabaseIcons::icon", "invalid icon index %d");
}
auto cacheKey = QString::number(index);

View File

@ -18,9 +18,15 @@
#ifndef KEEPASSX_DATABASEICONS_H
#define KEEPASSX_DATABASEICONS_H
#include "core/Global.h"
#include <QIcon>
enum IconSize
{
Default,
Medium,
Large
};
class DatabaseIcons
{
public:

View File

@ -22,10 +22,13 @@
#include "autotype/AutoType.h"
#include "core/Tools.h"
#include "format/CsvExporter.h"
#include "format/HtmlExporter.h"
#include "gui/Clipboard.h"
#include "gui/DatabaseOpenDialog.h"
#include "gui/DatabaseWidget.h"
#include "gui/DatabaseWidgetStateSync.h"
#include "gui/DragTabBar.h"
#include "gui/FileDialog.h"
#include "gui/HtmlExporter.h"
#include "gui/MessageBox.h"
#ifdef Q_OS_MACOS
#include "gui/osutils/macutils/MacUtils.h"

View File

@ -25,6 +25,8 @@
#include "core/Tools.h"
#include "gui/FileDialog.h"
#include "gui/IconModels.h"
#include "gui/Icons.h"
#include "gui/MessageBox.h"
#ifdef WITH_XC_NETWORKING
#include "gui/IconDownloader.h"
#endif
@ -128,7 +130,7 @@ void EditWidgetIcons::load(const QUuid& currentUuid,
m_currentUuid = currentUuid;
setUrl(url);
m_customIconModel->setIcons(database->metadata()->customIconsPixmaps(IconSize::Default),
m_customIconModel->setIcons(Icons::customIconsPixmaps(database.data(), IconSize::Default),
database->metadata()->customIconsOrder());
QUuid iconUuid = iconStruct.uuid;
@ -231,7 +233,7 @@ void EditWidgetIcons::addCustomIconFromFile()
return;
}
auto filter = QString("%1 (%2);;%3 (*)").arg(tr("Images"), Tools::imageReaderFilter(), tr("All files"));
auto filter = QString("%1 (%2);;%3 (*)").arg(tr("Images"), Icons::imageFormatsFilter(), tr("All files"));
auto filenames =
fileDialog()->getOpenFileNames(this, tr("Select Image(s)"), FileDialog::getLastDir("icons"), filter);
if (!filenames.empty()) {
@ -284,16 +286,17 @@ bool EditWidgetIcons::addCustomIcon(const QImage& icon)
bool added = false;
if (m_db) {
// Don't add an icon larger than 128x128, but retain original size if smaller
auto scaledicon = icon;
auto scaledIcon = icon;
if (icon.width() > 128 || icon.height() > 128) {
scaledicon = icon.scaled(128, 128);
scaledIcon = icon.scaled(128, 128);
}
QUuid uuid = m_db->metadata()->findCustomIcon(scaledicon);
QByteArray serializedIcon = Icons::saveToBytes(scaledIcon);
QUuid uuid = m_db->metadata()->findCustomIcon(serializedIcon);
if (uuid.isNull()) {
uuid = QUuid::createUuid();
m_db->metadata()->addCustomIcon(uuid, scaledicon);
m_customIconModel->setIcons(m_db->metadata()->customIconsPixmaps(IconSize::Default),
m_db->metadata()->addCustomIcon(uuid, serializedIcon);
m_customIconModel->setIcons(Icons::customIconsPixmaps(m_db.data(), IconSize::Default),
m_db->metadata()->customIconsOrder());
added = true;
}

View File

@ -173,7 +173,7 @@ void EntryPreviewWidget::updateEntryHeaderLine()
Q_ASSERT(m_currentEntry);
const QString title = m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->title());
m_ui->entryTitleLabel->setRawText(hierarchy(m_currentEntry->group(), title));
m_ui->entryIcon->setPixmap(m_currentEntry->iconPixmap(IconSize::Large));
m_ui->entryIcon->setPixmap(Icons::entryIconPixmap(m_currentEntry, IconSize::Large));
}
void EntryPreviewWidget::updateEntryTotp()
@ -377,7 +377,7 @@ void EntryPreviewWidget::updateGroupHeaderLine()
{
Q_ASSERT(m_currentGroup);
m_ui->groupTitleLabel->setRawText(hierarchy(m_currentGroup, {}));
m_ui->groupIcon->setPixmap(m_currentGroup->iconPixmap(IconSize::Large));
m_ui->groupIcon->setPixmap(Icons::groupIconPixmap(m_currentGroup, IconSize::Large));
}
void EntryPreviewWidget::updateGroupGeneralTab()

View File

@ -22,6 +22,7 @@
#include "core/Group.h"
#include "core/Metadata.h"
#include "gui/Icons.h"
namespace
{
@ -204,7 +205,7 @@ bool HtmlExporter::writeGroup(QIODevice& device, const Group& group, QString pat
// Header line
auto header = QString("<hr><h2>");
header.append(PixmapToHTML(group.iconPixmap(IconSize::Medium)));
header.append(PixmapToHTML(Icons::groupIconPixmap(&group, IconSize::Medium)));
header.append("&nbsp;");
header.append(path);
header.append("</h2>\n");
@ -236,7 +237,7 @@ bool HtmlExporter::writeGroup(QIODevice& device, const Group& group, QString pat
// Output it into our table. First the left side with
// icon and entry title ...
table += "<tr>";
table += "<td width=\"1%\">" + PixmapToHTML(entry->iconPixmap(IconSize::Medium)) + "</td>";
table += "<td width=\"1%\">" + PixmapToHTML(Icons::entryIconPixmap(entry, IconSize::Medium)) + "</td>";
table += "<td width=\"19%\" valign=\"top\"><h3>" + entry->title().toHtmlEscaped() + "</h3></td>";
// ... then the right side with the data fields

View File

@ -24,7 +24,12 @@
#include "core/Metadata.h"
#include "core/Tools.h"
#include "gui/IconDownloader.h"
#include "gui/IconModels.h"
#include "gui/Icons.h"
#include "osutils/OSUtils.h"
#ifdef Q_OS_MACOS
#include "gui/osutils/macutils/MacUtils.h"
#endif
#include <QStandardItemModel>
@ -126,15 +131,16 @@ void IconDownloaderDialog::downloadFinished(const QString& url, const QImage& ic
if (m_db && !icon.isNull()) {
// Don't add an icon larger than 128x128, but retain original size if smaller
auto scaledicon = icon;
auto scaledIcon = icon;
if (icon.width() > 128 || icon.height() > 128) {
scaledicon = icon.scaled(128, 128);
scaledIcon = icon.scaled(128, 128);
}
QUuid uuid = m_db->metadata()->findCustomIcon(scaledicon);
QByteArray serializedIcon = Icons::saveToBytes(scaledIcon);
QUuid uuid = m_db->metadata()->findCustomIcon(serializedIcon);
if (uuid.isNull()) {
uuid = QUuid::createUuid();
m_db->metadata()->addCustomIcon(uuid, scaledicon);
m_db->metadata()->addCustomIcon(uuid, serializedIcon);
updateTable(url, tr("Ok"));
} else {
updateTable(url, tr("Already Exists"));

View File

@ -19,7 +19,7 @@
#include <QUuid>
#include "core/DatabaseIcons.h"
#include "gui/DatabaseIcons.h"
DefaultIconModel::DefaultIconModel(QObject* parent)
: QAbstractListModel(parent)

View File

@ -19,11 +19,20 @@
#include "Icons.h"
#include <QIconEngine>
#include <QImageReader>
#include <QPaintDevice>
#include <QPainter>
#include "config-keepassx.h"
#include "core/Config.h"
#include "gui/DatabaseIcons.h"
#include "gui/MainWindow.h"
#include "gui/osutils/OSUtils.h"
#ifdef WITH_XC_KEESHARE
#include "keeshare/KeeShare.h"
#endif
class AdaptiveIconEngine : public QIconEngine
{
public:
@ -206,3 +215,97 @@ Icons* Icons::instance()
return m_instance;
}
QPixmap Icons::customIconPixmap(const Database* db, const QUuid& uuid, IconSize size)
{
if (!db->metadata()->hasCustomIcon(uuid)) {
return {};
}
// Generate QIcon with pre-baked resolutions
auto icon = QImage::fromData(db->metadata()->customIcon(uuid));
auto basePixmap = QPixmap::fromImage(icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
return QIcon(basePixmap).pixmap(databaseIcons()->iconSize(size));
}
QHash<QUuid, QPixmap> Icons::customIconsPixmaps(const Database* db, IconSize size)
{
QHash<QUuid, QPixmap> result;
for (const QUuid& uuid : db->metadata()->customIconsOrder()) {
result.insert(uuid, Icons::customIconPixmap(db, uuid, size));
}
return result;
}
QPixmap Icons::entryIconPixmap(const Entry* entry, IconSize size)
{
QPixmap icon(size, size);
if (entry->iconUuid().isNull()) {
icon = databaseIcons()->icon(entry->iconNumber(), size);
} else {
Q_ASSERT(entry->database());
if (entry->database()) {
icon = Icons::customIconPixmap(entry->database(), entry->iconUuid(), size);
}
}
if (entry->isExpired()) {
icon = databaseIcons()->applyBadge(icon, DatabaseIcons::Badges::Expired);
}
return icon;
}
QPixmap Icons::groupIconPixmap(const Group* group, IconSize size)
{
QPixmap icon(size, size);
if (group->iconUuid().isNull()) {
icon = databaseIcons()->icon(group->iconNumber(), size);
} else {
Q_ASSERT(group->database());
if (group->database()) {
icon = Icons::customIconPixmap(group->database(), group->iconUuid(), size);
}
}
if (group->isExpired()) {
icon = databaseIcons()->applyBadge(icon, DatabaseIcons::Badges::Expired);
}
#ifdef WITH_XC_KEESHARE
else if (KeeShare::isShared(group)) {
icon = KeeShare::indicatorBadge(group, icon);
}
#endif
return icon;
}
QString Icons::imageFormatsFilter()
{
const QList<QByteArray> formats = QImageReader::supportedImageFormats();
QStringList formatsStringList;
for (const QByteArray& format : formats) {
for (char codePoint : format) {
if (!QChar(codePoint).isLetterOrNumber()) {
continue;
}
}
formatsStringList.append("*." + QString::fromLatin1(format).toLower());
}
return formatsStringList.join(" ");
}
QByteArray Icons::saveToBytes(const QImage& image)
{
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
// TODO: check !icon.save()
image.save(&buffer, "PNG");
buffer.close();
return ba;
}

View File

@ -21,6 +21,9 @@
#include <QIcon>
#include <core/Database.h>
#include <gui/DatabaseIcons.h>
class Icons
{
public:
@ -32,6 +35,14 @@ public:
QIcon icon(const QString& name, bool recolor = true, const QColor& overrideColor = QColor::Invalid);
QIcon onOffIcon(const QString& name, bool on, bool recolor = true);
static QPixmap customIconPixmap(const Database* db, const QUuid& uuid, IconSize size = IconSize::Default);
static QHash<QUuid, QPixmap> customIconsPixmaps(const Database* db, IconSize size = IconSize::Default);
static QPixmap entryIconPixmap(const Entry* entry, IconSize size = IconSize::Default);
static QPixmap groupIconPixmap(const Group* group, IconSize size = IconSize::Default);
static QByteArray saveToBytes(const QImage& image);
static QString imageFormatsFilter();
static Icons* instance();
private:

View File

@ -21,6 +21,7 @@
#include "core/Group.h"
#include "core/Metadata.h"
#include "gui/IconModels.h"
#include "gui/Icons.h"
#include "gui/MessageBox.h"
DatabaseSettingsWidgetMaintenance::DatabaseSettingsWidgetMaintenance(QWidget* parent)
@ -47,7 +48,7 @@ DatabaseSettingsWidgetMaintenance::~DatabaseSettingsWidgetMaintenance()
void DatabaseSettingsWidgetMaintenance::populateIcons(QSharedPointer<Database> db)
{
m_customIconModel->setIcons(db->metadata()->customIconsPixmaps(IconSize::Default),
m_customIconModel->setIcons(Icons::customIconsPixmaps(db.data(), IconSize::Default),
db->metadata()->customIconsOrder());
m_ui->deleteButton->setEnabled(false);
}

View File

@ -21,9 +21,11 @@
#include <QMimeData>
#include <QPalette>
#include "core/Entry.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "core/PasswordHealth.h"
#include "gui/DatabaseIcons.h"
#include "gui/Icons.h"
#include "gui/styles/StateColorPalette.h"
#ifdef Q_OS_MACOS
@ -277,11 +279,11 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
switch (index.column()) {
case ParentGroup:
if (entry->group()) {
return entry->group()->iconPixmap();
return Icons::groupIconPixmap(entry->group());
}
break;
case Title:
return entry->iconPixmap();
return Icons::entryIconPixmap(entry);
case Paperclip:
if (!entry->attachments()->isEmpty()) {
return icons()->icon("paperclip");

View File

@ -19,8 +19,12 @@
#include <QMimeData>
#include "core/Database.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "core/Tools.h"
#include "gui/DatabaseIcons.h"
#include "gui/Icons.h"
#include "keeshare/KeeShare.h"
GroupModel::GroupModel(Database* db, QObject* parent)
@ -126,7 +130,7 @@ QVariant GroupModel::data(const QModelIndex& index, int role) const
#endif
return nameTemplate.arg(group->name());
} else if (role == Qt::DecorationRole) {
return group->iconPixmap();
return Icons::groupIconPixmap(group);
} else if (role == Qt::FontRole) {
QFont font;
if (group->isExpired()) {

View File

@ -203,8 +203,8 @@ void ReportsWidgetHealthcheck::addHealthRow(QSharedPointer<PasswordHealth> healt
auto row = QList<QStandardItem*>();
row << new QStandardItem(descr);
row << new QStandardItem(entry->iconPixmap(), title);
row << new QStandardItem(group->iconPixmap(), group->hierarchy().join("/"));
row << new QStandardItem(Icons::entryIconPixmap(entry), title);
row << new QStandardItem(Icons::groupIconPixmap(group), group->hierarchy().join("/"));
row << new QStandardItem(QString::number(health->score()));
row << new QStandardItem(health->scoreReason());

View File

@ -163,8 +163,8 @@ void ReportsWidgetHibp::makeHibpTable()
}
auto row = QList<QStandardItem*>();
row << new QStandardItem(entry->iconPixmap(), title)
<< new QStandardItem(group->iconPixmap(), group->hierarchy().join("/"))
row << new QStandardItem(Icons::entryIconPixmap(entry), title)
<< new QStandardItem(Icons::groupIconPixmap(group), group->hierarchy().join("/"))
<< new QStandardItem(countToText(count));
if (entry->excludeFromReports()) {

View File

@ -16,8 +16,11 @@
*/
#include "KeeShare.h"
#include "core/DatabaseIcons.h"
#include "core/CustomData.h"
#include "core/Database.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "gui/DatabaseIcons.h"
#include "keeshare/ShareObserver.h"
namespace

View File

@ -17,7 +17,13 @@
#include "KeeShareSettings.h"
#include "core/CustomData.h"
#include "core/Database.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "crypto/Random.h"
#include "gui/DatabaseIcons.h"
#include "keeshare/Signature.h"
#include <QTextCodec>
#include <QXmlStreamWriter>

View File

@ -19,6 +19,7 @@
#include "core/Group.h"
#include "core/Metadata.h"
#include "format/KeePass2Writer.h"
#include "gui/Icons.h"
#include "keeshare/KeeShare.h"
#include "keeshare/Signature.h"
#include "keys/PasswordKey.h"
@ -81,7 +82,7 @@ namespace
targetEntry->setUpdateTimeinfo(updateTimeinfoEntry);
const auto iconUuid = targetEntry->iconUuid();
if (!iconUuid.isNull() && !targetMetadata->hasCustomIcon(iconUuid)) {
targetMetadata->addCustomIcon(iconUuid, sourceEntry->icon());
targetMetadata->addCustomIcon(iconUuid, sourceEntry->database()->metadata()->customIcon(iconUuid));
}
}

View File

@ -21,4 +21,4 @@ find_package(QREncode REQUIRED)
add_library(qrcode STATIC ${qrcode_SOURCES})
target_include_directories(qrcode PRIVATE ${QRENCODE_INCLUDE_DIR})
target_link_libraries(qrcode PUBLIC Qt5::Core Qt5::Widgets Qt5::Svg ${QRENCODE_LIBRARY})
target_link_libraries(qrcode PUBLIC Qt5::Core Qt5::Svg ${QRENCODE_LIBRARY})

View File

@ -20,9 +20,10 @@
#include <QSignalSpy>
#include <QTest>
#include "core/DatabaseIcons.h"
#include "core/Entry.h"
#include "core/Group.h"
#include "crypto/Crypto.h"
#include "gui/DatabaseIcons.h"
#include "gui/IconModels.h"
#include "gui/SortFilterHideProxyModel.h"
#include "gui/entry/AutoTypeAssociationsModel.h"

View File

@ -315,36 +315,34 @@ void TestGroup::testCopyCustomIcon()
QScopedPointer<Database> dbSource(new Database());
QUuid groupIconUuid = QUuid::createUuid();
QImage groupIcon(16, 16, QImage::Format_RGB32);
groupIcon.setPixel(0, 0, qRgb(255, 0, 0));
QByteArray groupIcon("group icon");
dbSource->metadata()->addCustomIcon(groupIconUuid, groupIcon);
QUuid entryIconUuid = QUuid::createUuid();
QImage entryIcon(16, 16, QImage::Format_RGB32);
entryIcon.setPixel(0, 0, qRgb(255, 0, 0));
QByteArray entryIcon("entry icon");
dbSource->metadata()->addCustomIcon(entryIconUuid, entryIcon);
Group* group = new Group();
group->setParent(dbSource->rootGroup());
group->setIcon(groupIconUuid);
QCOMPARE(group->icon(), groupIcon);
QCOMPARE(group->database()->metadata()->customIcon(groupIconUuid), groupIcon);
Entry* entry = new Entry();
entry->setGroup(dbSource->rootGroup());
entry->setIcon(entryIconUuid);
QCOMPARE(entry->icon(), entryIcon);
QCOMPARE(entry->database()->metadata()->customIcon(entryIconUuid), entryIcon);
QScopedPointer<Database> dbTarget(new Database());
group->setParent(dbTarget->rootGroup());
QVERIFY(dbTarget->metadata()->hasCustomIcon(groupIconUuid));
QCOMPARE(dbTarget->metadata()->customIcon(groupIconUuid), groupIcon);
QCOMPARE(group->icon(), groupIcon);
QCOMPARE(group->database()->metadata()->customIcon(groupIconUuid), groupIcon);
entry->setGroup(dbTarget->rootGroup());
QVERIFY(dbTarget->metadata()->hasCustomIcon(entryIconUuid));
QCOMPARE(dbTarget->metadata()->customIcon(entryIconUuid), entryIcon);
QCOMPARE(entry->icon(), entryIcon);
QCOMPARE(entry->database()->metadata()->customIcon(entryIconUuid), entryIcon);
}
void TestGroup::testClone()
@ -425,11 +423,9 @@ void TestGroup::testCopyCustomIcons()
QScopedPointer<Database> dbSource(new Database());
QScopedPointer<Database> dbTarget(new Database());
QImage iconImage1(1, 1, QImage::Format_RGB32);
iconImage1.setPixel(0, 0, qRgb(1, 2, 3));
QByteArray iconImage1("icon 1");
QImage iconImage2(1, 1, QImage::Format_RGB32);
iconImage2.setPixel(0, 0, qRgb(4, 5, 6));
QByteArray iconImage2("icon 2");
QScopedPointer<Group> group1(new Group());
group1->setParent(dbSource->rootGroup());
@ -469,8 +465,8 @@ void TestGroup::testCopyCustomIcons()
QVERIFY(metaTarget->hasCustomIcon(entry1IconOld));
QVERIFY(metaTarget->hasCustomIcon(entry1IconNew));
QCOMPARE(metaTarget->customIcon(group1Icon).pixel(0, 0), qRgb(1, 2, 3));
QCOMPARE(metaTarget->customIcon(group2Icon).pixel(0, 0), qRgb(4, 5, 6));
QCOMPARE(metaTarget->customIcon(group1Icon), iconImage1);
QCOMPARE(metaTarget->customIcon(group2Icon), iconImage2);
}
void TestGroup::testFindEntry()
@ -1075,21 +1071,18 @@ void TestGroup::testApplyGroupIconRecursively()
// Set an icon per UUID to the subgroup and apply recursively
// -> all groups and entries except the root group have the same icon
const QUuid subgroupIconUuid = QUuid::createUuid();
QImage subgroupIcon(16, 16, QImage::Format_RGB32);
subgroupIcon.setPixel(0, 0, qRgb(255, 0, 0));
QByteArray subgroupIcon("subgroup icon");
database.metadata()->addCustomIcon(subgroupIconUuid, subgroupIcon);
subgroup->setIcon(subgroupIconUuid);
subgroup->applyGroupIconToChildGroups();
subgroup->applyGroupIconToChildEntries();
QVERIFY(database.rootGroup()->iconNumber() == rootIconNumber);
QCOMPARE(subgroup->iconUuid(), subgroupIconUuid);
QCOMPARE(subgroup->icon(), subgroupIcon);
QCOMPARE(subgroupEntry->iconUuid(), subgroupIconUuid);
QCOMPARE(subgroupEntry->icon(), subgroupIcon);
QCOMPARE(subsubgroup->iconUuid(), subgroupIconUuid);
QCOMPARE(subsubgroup->icon(), subgroupIcon);
QCOMPARE(subsubgroupEntry->iconUuid(), subgroupIconUuid);
QCOMPARE(subsubgroupEntry->icon(), subgroupIcon);
QCOMPARE(subgroup->database()->metadata()->customIcon(subgroupIconUuid), subgroupIcon);
// Reset all icons to root icon
database.rootGroup()->setIcon(rootIconNumber);

View File

@ -114,20 +114,12 @@ void TestKeePass1Reader::testMasterKey()
void TestKeePass1Reader::testCustomIcons()
{
QCOMPARE(m_db->metadata()->customIconsOrder().size(), 1);
QUuid uuid = m_db->metadata()->customIconsOrder().at(0);
QVERIFY(m_db->metadata()->hasCustomIcon(uuid));
QByteArray icon = m_db->metadata()->customIcon(uuid);
Entry* entry = m_db->rootGroup()->children().at(1)->entries().at(0);
QCOMPARE(entry->icon().width(), 16);
QCOMPARE(entry->icon().height(), 16);
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
QRgb rgb = entry->icon().pixel(x, y);
QCOMPARE(qRed(rgb), 8);
QCOMPARE(qGreen(rgb), 160);
QCOMPARE(qBlue(rgb), 60);
}
}
QVERIFY(icon.startsWith(
"\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\b\x06\x00\x00\x00\x1F\xF3\xFF"));
}
void TestKeePass1Reader::testGroupExpanded()

View File

@ -113,18 +113,10 @@ void TestKeePass2Format::testXmlCustomIcons()
QCOMPARE(m_xmlDb->metadata()->customIconsOrder().size(), 1);
QUuid uuid = QUuid::fromRfc4122(QByteArray::fromBase64("++vyI+daLk6omox4a6kQGA=="));
QVERIFY(m_xmlDb->metadata()->hasCustomIcon(uuid));
QImage icon = m_xmlDb->metadata()->customIcon(uuid);
QCOMPARE(icon.width(), 16);
QCOMPARE(icon.height(), 16);
QByteArray icon = m_xmlDb->metadata()->customIcon(uuid);
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
QRgb rgb = icon.pixel(x, y);
QCOMPARE(qRed(rgb), 128);
QCOMPARE(qGreen(rgb), 0);
QCOMPARE(qBlue(rgb), 128);
}
}
QVERIFY(icon.startsWith(
"\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\b\x06\x00\x00\x00\x1F\xF3\xFF"));
}
void TestKeePass2Format::testXmlGroupRoot()

View File

@ -998,8 +998,7 @@ void TestMerge::testUpdateGroup()
groupSourceInitial->setName("group2 renamed");
groupSourceInitial->setNotes("updated notes");
QUuid customIconId = QUuid::createUuid();
QImage customIcon;
dbSource->metadata()->addCustomIcon(customIconId, customIcon);
dbSource->metadata()->addCustomIcon(customIconId, QString("custom icon").toLocal8Bit());
groupSourceInitial->setIcon(customIconId);
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
@ -1113,9 +1112,8 @@ void TestMerge::testMergeCustomIcons()
m_clock->advanceSecond(1);
QUuid customIconId = QUuid::createUuid();
QImage customIcon;
dbSource->metadata()->addCustomIcon(customIconId, customIcon);
dbSource->metadata()->addCustomIcon(customIconId, QString("custom icon").toLocal8Bit());
// Sanity check.
QVERIFY(dbSource->metadata()->hasCustomIcon(customIconId));
@ -1138,10 +1136,12 @@ void TestMerge::testMergeDuplicateCustomIcons()
m_clock->advanceSecond(1);
QUuid customIconId = QUuid::createUuid();
QImage customIcon;
dbSource->metadata()->addCustomIcon(customIconId, customIcon);
dbDestination->metadata()->addCustomIcon(customIconId, customIcon);
QByteArray customIcon1 = QString("custom icon 1").toLocal8Bit();
QByteArray customIcon2 = QString("custom icon 2").toLocal8Bit();
dbSource->metadata()->addCustomIcon(customIconId, customIcon1);
dbDestination->metadata()->addCustomIcon(customIconId, customIcon2);
// Sanity check.
QVERIFY(dbSource->metadata()->hasCustomIcon(customIconId));
QVERIFY(dbDestination->metadata()->hasCustomIcon(customIconId));
@ -1153,6 +1153,7 @@ void TestMerge::testMergeDuplicateCustomIcons()
QVERIFY(dbDestination->metadata()->hasCustomIcon(customIconId));
QCOMPARE(dbDestination->metadata()->customIconsOrder().count(), 1);
QCOMPARE(dbDestination->metadata()->customIcon(customIconId), customIcon2);
}
void TestMerge::testMetadata()

View File

@ -16,12 +16,14 @@
*/
#include "TestGuiPixmaps.h"
#include "core/DatabaseIcons.h"
#include "core/Metadata.h"
#include <QTest>
#include "core/Group.h"
#include "crypto/Crypto.h"
#include <QTest>
#include "gui/DatabaseIcons.h"
#include "gui/Icons.h"
void TestGuiPixmaps::initTestCase()
{
@ -30,55 +32,53 @@ void TestGuiPixmaps::initTestCase()
void TestGuiPixmaps::testDatabaseIcons()
{
// check if the cache works correctly
auto pixmap = databaseIcons()->icon(0);
auto pixmapCached = databaseIcons()->icon(0);
QCOMPARE(pixmapCached.cacheKey(), pixmap.cacheKey());
QVERIFY(!databaseIcons()->icon(0).isNull());
}
void TestGuiPixmaps::testEntryIcons()
{
QScopedPointer<Database> db(new Database());
Entry* entry = new Entry();
auto entry = new Entry();
entry->setGroup(db->rootGroup());
// Test setting standard icon
entry->setIcon(10);
auto pixmap = entry->iconPixmap();
QCOMPARE(pixmap.cacheKey(), databaseIcons()->icon(10).cacheKey());
auto pixmap = Icons::entryIconPixmap(entry);
QVERIFY(pixmap.toImage() == databaseIcons()->icon(10).toImage());
// Test setting custom icon
QUuid iconUuid = QUuid::createUuid();
QImage icon(2, 1, QImage::Format_RGB32);
icon.setPixel(0, 0, qRgb(0, 0, 0));
icon.setPixel(1, 0, qRgb(0, 0, 50));
db->metadata()->addCustomIcon(iconUuid, icon);
db->metadata()->addCustomIcon(iconUuid, Icons::saveToBytes(icon));
QCOMPARE(db->metadata()->customIconsOrder().count(), 1);
entry->setIcon(iconUuid);
pixmap = entry->iconPixmap();
QCOMPARE(pixmap.cacheKey(), db->metadata()->customIconPixmap(iconUuid).cacheKey());
// Confirm the icon is the same as that stored in the database
QVERIFY(Icons::entryIconPixmap(entry).toImage() == Icons::customIconPixmap(db.data(), iconUuid).toImage());
}
void TestGuiPixmaps::testGroupIcons()
{
QScopedPointer<Database> db(new Database());
Group* group = db->rootGroup();
auto group = db->rootGroup();
// Test setting standard icon
group->setIcon(10);
auto pixmap = group->iconPixmap();
QCOMPARE(pixmap.cacheKey(), databaseIcons()->icon(10).cacheKey());
auto pixmap = Icons::groupIconPixmap(group);
QVERIFY(pixmap.toImage() == databaseIcons()->icon(10).toImage());
// Test setting custom icon
QUuid iconUuid = QUuid::createUuid();
QImage icon(2, 1, QImage::Format_RGB32);
icon.setPixel(0, 0, qRgb(0, 0, 0));
icon.setPixel(1, 0, qRgb(0, 0, 50));
db->metadata()->addCustomIcon(iconUuid, icon);
db->metadata()->addCustomIcon(iconUuid, Icons::saveToBytes(icon));
group->setIcon(iconUuid);
pixmap = group->iconPixmap();
QCOMPARE(pixmap.cacheKey(), db->metadata()->customIconPixmap(iconUuid).cacheKey());
// Confirm the icon is the same as that stored in the database
QVERIFY(Icons::groupIconPixmap(group).toImage() == Icons::customIconPixmap(db.data(), iconUuid).toImage());
}
QTEST_MAIN(TestGuiPixmaps)