Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/autotype/AutoTypeMatchModel.cpp8
-rw-r--r--src/cli/CMakeLists.txt2
-rw-r--r--src/core/Entry.cpp39
-rw-r--r--src/core/Entry.h4
-rw-r--r--src/core/Global.h7
-rw-r--r--src/core/Group.cpp48
-rw-r--r--src/core/Group.h4
-rw-r--r--src/core/Merger.cpp3
-rw-r--r--src/core/Metadata.cpp73
-rw-r--r--src/core/Metadata.h16
-rw-r--r--src/core/Tools.cpp22
-rw-r--r--src/core/Tools.h1
-rw-r--r--src/fdosecrets/widgets/AccessControlDialog.cpp3
-rw-r--r--src/fdosecrets/widgets/SettingsModels.cpp2
-rw-r--r--src/format/KdbxXmlReader.cpp11
-rw-r--r--src/format/KdbxXmlWriter.cpp11
-rw-r--r--src/format/KdbxXmlWriter.h3
-rw-r--r--src/format/KeePass1Reader.cpp6
-rw-r--r--src/gui/DatabaseIcons.cpp (renamed from src/core/DatabaseIcons.cpp)5
-rw-r--r--src/gui/DatabaseIcons.h (renamed from src/core/DatabaseIcons.h)8
-rw-r--r--src/gui/DatabaseTabWidget.cpp5
-rw-r--r--src/gui/EditWidgetIcons.cpp17
-rw-r--r--src/gui/EntryPreviewWidget.cpp4
-rw-r--r--src/gui/HtmlExporter.cpp (renamed from src/format/HtmlExporter.cpp)5
-rw-r--r--src/gui/HtmlExporter.h (renamed from src/format/HtmlExporter.h)0
-rw-r--r--src/gui/IconDownloaderDialog.cpp14
-rw-r--r--src/gui/IconModels.cpp2
-rw-r--r--src/gui/Icons.cpp103
-rw-r--r--src/gui/Icons.h11
-rw-r--r--src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp3
-rw-r--r--src/gui/entry/EntryModel.cpp6
-rw-r--r--src/gui/group/GroupModel.cpp6
-rw-r--r--src/gui/reports/ReportsWidgetHealthcheck.cpp4
-rw-r--r--src/gui/reports/ReportsWidgetHibp.cpp4
-rw-r--r--src/keeshare/KeeShare.cpp5
-rw-r--r--src/keeshare/KeeShareSettings.cpp6
-rw-r--r--src/keeshare/ShareExport.cpp3
-rw-r--r--src/qrcode/CMakeLists.txt2
-rw-r--r--tests/TestEntryModel.cpp3
-rw-r--r--tests/TestGroup.cpp33
-rw-r--r--tests/TestKeePass1Reader.cpp18
-rw-r--r--tests/TestKeePass2Format.cpp16
-rw-r--r--tests/TestMerge.cpp15
-rw-r--r--tests/gui/TestGuiPixmaps.cpp36
46 files changed, 299 insertions, 314 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d633396c4..3405f6ac6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fff80238f..430515185 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -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
diff --git a/src/autotype/AutoTypeMatchModel.cpp b/src/autotype/AutoTypeMatchModel.cpp
index 128015898..207d09b02 100644
--- a/src/autotype/AutoTypeMatchModel.cpp
+++ b/src/autotype/AutoTypeMatchModel.cpp
@@ -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;
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
index 470af6283..f0d6cbd46 100644
--- a/src/cli/CMakeLists.txt
+++ b/src/cli/CMakeLists.txt
@@ -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)
diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp
index e386a349d..e7e000c2d 100644
--- a/src/core/Entry.cpp
+++ b/src/core/Entry.cpp
@@ -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()));
}
}
}
diff --git a/src/core/Entry.h b/src/core/Entry.h
index 99c0e6024..1fcd09572 100644
--- a/src/core/Entry.h
+++ b/src/core/Entry.h
@@ -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;
diff --git a/src/core/Global.h b/src/core/Global.h
index fe51b9b5d..e9a4db739 100644
--- a/src/core/Global.h
+++ b/src/core/Global.h
@@ -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,
diff --git a/src/core/Group.cpp b/src/core/Group.cpp
index 196f230c1..6684d1ab9 100644
--- a/src/core/Group.cpp
+++ b/src/core/Group.cpp
@@ -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) {
diff --git a/src/core/Group.h b/src/core/Group.h
index c564d1609..c283a89a2 100644
--- a/src/core/Group.h
+++ b/src/core/Group.h
@@ -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;
diff --git a/src/core/Merger.cpp b/src/core/Merger.cpp
index a5f532af2..b7c832951 100644
--- a/src/core/Merger.cpp
+++ b/src/core/Merger.cpp
@@ -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()));
}
}
diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp
index f99f42499..8bb0b52e4 100644
--- a/src/core/Metadata.cpp
+++ b/src/core/Metadata.cpp
@@ -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)
diff --git a/src/core/Metadata.h b/src/core/Metadata.h
index 51276ec61..1b87ec2ad 100644
--- a/src/core/Metadata.h
+++ b/src/core/Metadata.h
@@ -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;
diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp
index 7c6d52a59..61c8cb6e2 100644
--- a/src/core/Tools.cpp
+++ b/src/core/Tools.cpp
@@ -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) {
diff --git a/src/core/Tools.h b/src/core/Tools.h
index cf3b3593d..2c22e7427 100644
--- a/src/core/Tools.h
+++ b/src/core/Tools.h
@@ -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);
diff --git a/src/fdosecrets/widgets/AccessControlDialog.cpp b/src/fdosecrets/widgets/AccessControlDialog.cpp
index af741ea0f..2c8fd696a 100644
--- a/src/fdosecrets/widgets/AccessControlDialog.cpp
+++ b/src/fdosecrets/widgets/AccessControlDialog.cpp
@@ -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:
diff --git a/src/fdosecrets/widgets/SettingsModels.cpp b/src/fdosecrets/widgets/SettingsModels.cpp
index 6f318b7bb..d68ee4b0c 100644
--- a/src/fdosecrets/widgets/SettingsModels.cpp
+++ b/src/fdosecrets/widgets/SettingsModels.cpp
@@ -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;
diff --git a/src/format/KdbxXmlReader.cpp b/src/format/KdbxXmlReader.cpp
index c802040c0..03a87ad5d 100644
--- a/src/format/KdbxXmlReader.cpp
+++ b/src/format/KdbxXmlReader.cpp
@@ -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);
diff --git a/src/format/KdbxXmlWriter.cpp b/src/format/KdbxXmlWriter.cpp
index 853a64e89..c71aa42b9 100644
--- a/src/format/KdbxXmlWriter.cpp
+++ b/src/format/KdbxXmlWriter.cpp
@@ -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();
}
diff --git a/src/format/KdbxXmlWriter.h b/src/format/KdbxXmlWriter.h
index c0774fc6c..e8dac5bee 100644
--- a/src/format/KdbxXmlWriter.h
+++ b/src/format/KdbxXmlWriter.h
@@ -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);
diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp
index e4415af93..0b7f168a4 100644
--- a/src/format/KeePass1Reader.cpp
+++ b/src/format/KeePass1Reader.cpp
@@ -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);
diff --git a/src/core/DatabaseIcons.cpp b/src/gui/DatabaseIcons.cpp
index a284d3842..f83ce9ac4 100644
--- a/src/core/DatabaseIcons.cpp
+++ b/src/gui/DatabaseIcons.cpp
@@ -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);
diff --git a/src/core/DatabaseIcons.h b/src/gui/DatabaseIcons.h
index 2abb8a485..38d1590c7 100644
--- a/src/core/DatabaseIcons.h
+++ b/src/gui/DatabaseIcons.h
@@ -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:
diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp
index 9aa58f556..40d42f4e1 100644
--- a/src/gui/DatabaseTabWidget.cpp
+++ b/src/gui/DatabaseTabWidget.cpp
@@ -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"
diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp
index 3158a6c9d..c301728b6 100644
--- a/src/gui/EditWidgetIcons.cpp
+++ b/src/gui/EditWidgetIcons.cpp
@@ -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;
}
diff --git a/src/gui/EntryPreviewWidget.cpp b/src/gui/EntryPreviewWidget.cpp
index 8b283d39a..7c3b8ffd2 100644
--- a/src/gui/EntryPreviewWidget.cpp
+++ b/src/gui/EntryPreviewWidget.cpp
@@ -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()
diff --git a/src/format/HtmlExporter.cpp b/src/gui/HtmlExporter.cpp
index 83a5b7345..c79681637 100644
--- a/src/format/HtmlExporter.cpp
+++ b/src/gui/HtmlExporter.cpp
@@ -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
diff --git a/src/format/HtmlExporter.h b/src/gui/HtmlExporter.h
index 3a592e54a..3a592e54a 100644
--- a/src/format/HtmlExporter.h
+++ b/src/gui/HtmlExporter.h
diff --git a/src/gui/IconDownloaderDialog.cpp b/src/gui/IconDownloaderDialog.cpp
index c2d5c8190..271a916f3 100644
--- a/src/gui/IconDownloaderDialog.cpp
+++ b/src/gui/IconDownloaderDialog.cpp
@@ -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"));
diff --git a/src/gui/IconModels.cpp b/src/gui/IconModels.cpp
index 3bdd9a5e6..ab435aedc 100644
--- a/src/gui/IconModels.cpp
+++ b/src/gui/IconModels.cpp
@@ -19,7 +19,7 @@
#include <QUuid>
-#include "core/DatabaseIcons.h"
+#include "gui/DatabaseIcons.h"
DefaultIconModel::DefaultIconModel(QObject* parent)
: QAbstractListModel(parent)
diff --git a/src/gui/Icons.cpp b/src/gui/Icons.cpp
index cdebdcc75..95e6aadc4 100644
--- a/src/gui/Icons.cpp
+++ b/src/gui/Icons.cpp
@@ -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;
+}
diff --git a/src/gui/Icons.h b/src/gui/Icons.h
index d02fd79c4..01af0b289 100644
--- a/src/gui/Icons.h
+++ b/src/gui/Icons.h
@@ -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:
diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp
index 12738a987..09650c6b0 100644
--- a/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp
+++ b/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp
@@ -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);
}
diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp
index 7b61da042..313b7ee50 100644
--- a/src/gui/entry/EntryModel.cpp
+++ b/src/gui/entry/EntryModel.cpp
@@ -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");
diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp
index 9a2b745ea..c21d1f911 100644
--- a/src/gui/group/GroupModel.cpp
+++ b/src/gui/group/GroupModel.cpp
@@ -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()) {
diff --git a/src/gui/reports/ReportsWidgetHealthcheck.cpp b/src/gui/reports/ReportsWidgetHealthcheck.cpp
index e6b441a4d..d23829031 100644
--- a/src/gui/reports/ReportsWidgetHealthcheck.cpp
+++ b/src/gui/reports/ReportsWidgetHealthcheck.cpp
@@ -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());
diff --git a/src/gui/reports/ReportsWidgetHibp.cpp b/src/gui/reports/ReportsWidgetHibp.cpp
index f84be1a18..86be3d92f 100644
--- a/src/gui/reports/ReportsWidgetHibp.cpp
+++ b/src/gui/reports/ReportsWidgetHibp.cpp
@@ -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()) {
diff --git a/src/keeshare/KeeShare.cpp b/src/keeshare/KeeShare.cpp
index 4287481d9..7f512c6d9 100644
--- a/src/keeshare/KeeShare.cpp
+++ b/src/keeshare/KeeShare.cpp
@@ -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
diff --git a/src/keeshare/KeeShareSettings.cpp b/src/keeshare/KeeShareSettings.cpp
index c2679feb7..601b05310 100644
--- a/src/keeshare/KeeShareSettings.cpp
+++ b/src/keeshare/KeeShareSettings.cpp
@@ -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>
diff --git a/src/keeshare/ShareExport.cpp b/src/keeshare/ShareExport.cpp
index ac1d4ddec..31f7fece3 100644
--- a/src/keeshare/ShareExport.cpp
+++ b/src/keeshare/ShareExport.cpp
@@ -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));
}
}
diff --git a/src/qrcode/CMakeLists.txt b/src/qrcode/CMakeLists.txt
index 5d01d07b7..10e368406 100644
--- a/src/qrcode/CMakeLists.txt
+++ b/src/qrcode/CMakeLists.txt
@@ -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})
diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp
index 724d3f5c1..ce4b66881 100644
--- a/tests/TestEntryModel.cpp
+++ b/tests/TestEntryModel.cpp
@@ -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"
diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp
index ccc94cc90..55c54d821 100644
--- a/tests/TestGroup.cpp
+++ b/tests/TestGroup.cpp
@@ -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);
diff --git a/tests/TestKeePass1Reader.cpp b/tests/TestKeePass1Reader.cpp
index 9983cf74c..d7a04bdbb 100644
--- a/tests/TestKeePass1Reader.cpp
+++ b/tests/TestKeePass1Reader.cpp
@@ -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()
diff --git a/tests/TestKeePass2Format.cpp b/tests/TestKeePass2Format.cpp
index bbe9f3c3e..397c8bd1c 100644
--- a/tests/TestKeePass2Format.cpp
+++ b/tests/TestKeePass2Format.cpp
@@ -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);
-
- 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);
- }
- }
+ QByteArray icon = m_xmlDb->metadata()->customIcon(uuid);
+
+ 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()
diff --git a/tests/TestMerge.cpp b/tests/TestMerge.cpp
index 8018861e8..7fc1d1dc8 100644
--- a/tests/TestMerge.cpp
+++ b/tests/TestMerge.cpp
@@ -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()
diff --git a/tests/gui/TestGuiPixmaps.cpp b/tests/gui/TestGuiPixmaps.cpp
index 1c78b8962..f18cba221 100644
--- a/tests/gui/TestGuiPixmaps.cpp
+++ b/tests/gui/TestGuiPixmaps.cpp
@@ -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)