mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Removing QWidget dependency from src/core.
This commit is contained in:
parent
6f5bbf7ad1
commit
004f2b6801
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
@ -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:
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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(" ");
|
||||
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
|
@ -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"));
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include "core/DatabaseIcons.h"
|
||||
#include "gui/DatabaseIcons.h"
|
||||
|
||||
DefaultIconModel::DefaultIconModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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})
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user