mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-25 00:50:04 -05: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()
|
endif()
|
||||||
|
|
||||||
if (NOT HAIKU)
|
if (NOT HAIKU)
|
||||||
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8.999) OR CMAKE_COMPILER_IS_CLANGXX)
|
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")
|
add_gcc_compiler_flags("-fstack-protector-strong")
|
||||||
else()
|
else()
|
||||||
add_gcc_compiler_flags("-fstack-protector --param=ssp-buffer-size=4")
|
add_gcc_compiler_flags("-fstack-protector --param=ssp-buffer-size=4")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual")
|
add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual")
|
||||||
@ -466,7 +466,7 @@ elseif(WIN32)
|
|||||||
message(STATUS "Using windeployqt: ${WINDEPLOYQT_EXE}")
|
message(STATUS "Using windeployqt: ${WINDEPLOYQT_EXE}")
|
||||||
endif()
|
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.
|
# Make sure we don't enable asserts there.
|
||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
|
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ set(keepassx_SOURCES
|
|||||||
core/Config.cpp
|
core/Config.cpp
|
||||||
core/CustomData.cpp
|
core/CustomData.cpp
|
||||||
core/Database.cpp
|
core/Database.cpp
|
||||||
core/DatabaseIcons.cpp
|
|
||||||
core/Entry.cpp
|
core/Entry.cpp
|
||||||
core/EntryAttachments.cpp
|
core/EntryAttachments.cpp
|
||||||
core/EntryAttributes.cpp
|
core/EntryAttributes.cpp
|
||||||
@ -71,7 +70,6 @@ set(keepassx_SOURCES
|
|||||||
crypto/kdf/Argon2Kdf.cpp
|
crypto/kdf/Argon2Kdf.cpp
|
||||||
format/CsvExporter.cpp
|
format/CsvExporter.cpp
|
||||||
format/CsvParser.cpp
|
format/CsvParser.cpp
|
||||||
format/HtmlExporter.cpp
|
|
||||||
format/KeePass1Reader.cpp
|
format/KeePass1Reader.cpp
|
||||||
format/KeePass2.cpp
|
format/KeePass2.cpp
|
||||||
format/KeePass2RandomStream.cpp
|
format/KeePass2RandomStream.cpp
|
||||||
@ -101,6 +99,7 @@ set(keepassx_SOURCES
|
|||||||
gui/CategoryListWidget.cpp
|
gui/CategoryListWidget.cpp
|
||||||
gui/Clipboard.cpp
|
gui/Clipboard.cpp
|
||||||
gui/CloneDialog.cpp
|
gui/CloneDialog.cpp
|
||||||
|
gui/DatabaseIcons.cpp
|
||||||
gui/DatabaseOpenWidget.cpp
|
gui/DatabaseOpenWidget.cpp
|
||||||
gui/DatabaseTabWidget.cpp
|
gui/DatabaseTabWidget.cpp
|
||||||
gui/DatabaseWidget.cpp
|
gui/DatabaseWidget.cpp
|
||||||
@ -114,6 +113,7 @@ set(keepassx_SOURCES
|
|||||||
gui/FileDialog.cpp
|
gui/FileDialog.cpp
|
||||||
gui/Font.cpp
|
gui/Font.cpp
|
||||||
gui/GuiTools.cpp
|
gui/GuiTools.cpp
|
||||||
|
gui/HtmlExporter.cpp
|
||||||
gui/IconModels.cpp
|
gui/IconModels.cpp
|
||||||
gui/KeePass1OpenWidget.cpp
|
gui/KeePass1OpenWidget.cpp
|
||||||
gui/KMessageWidget.cpp
|
gui/KMessageWidget.cpp
|
||||||
|
@ -20,8 +20,12 @@
|
|||||||
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
|
|
||||||
|
#include "core/Entry.h"
|
||||||
|
#include "core/Global.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
|
#include "gui/DatabaseIcons.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
|
|
||||||
AutoTypeMatchModel::AutoTypeMatchModel(QObject* parent)
|
AutoTypeMatchModel::AutoTypeMatchModel(QObject* parent)
|
||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
@ -114,11 +118,11 @@ QVariant AutoTypeMatchModel::data(const QModelIndex& index, int role) const
|
|||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case ParentGroup:
|
case ParentGroup:
|
||||||
if (match.first->group()) {
|
if (match.first->group()) {
|
||||||
return match.first->group()->iconPixmap();
|
return Icons::groupIconPixmap(match.first->group());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Title:
|
case Title:
|
||||||
return match.first->iconPixmap();
|
return Icons::entryIconPixmap(match.first);
|
||||||
}
|
}
|
||||||
} else if (role == Qt::FontRole) {
|
} else if (role == Qt::FontRole) {
|
||||||
QFont font;
|
QFont font;
|
||||||
|
@ -44,7 +44,7 @@ set(cli_SOURCES
|
|||||||
Show.cpp)
|
Show.cpp)
|
||||||
|
|
||||||
add_library(cli STATIC ${cli_SOURCES})
|
add_library(cli STATIC ${cli_SOURCES})
|
||||||
target_link_libraries(cli Qt5::Core Qt5::Widgets)
|
target_link_libraries(cli Qt5::Core)
|
||||||
|
|
||||||
find_package(Readline)
|
find_package(Readline)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "Entry.h"
|
#include "Entry.h"
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include "core/DatabaseIcons.h"
|
#include "core/Database.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "core/PasswordHealth.h"
|
#include "core/PasswordHealth.h"
|
||||||
@ -159,40 +159,6 @@ const QString Entry::uuidToHex() const
|
|||||||
return Tools::uuidToHex(m_uuid);
|
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
|
int Entry::iconNumber() const
|
||||||
{
|
{
|
||||||
return m_data.iconNumber;
|
return m_data.iconNumber;
|
||||||
@ -1217,7 +1183,8 @@ void Entry::setGroup(Group* group)
|
|||||||
// copy custom icon to the new database
|
// copy custom icon to the new database
|
||||||
if (!iconUuid().isNull() && group->database() && m_group->database()->metadata()->hasCustomIcon(iconUuid())
|
if (!iconUuid().isNull() && group->database() && m_group->database()->metadata()->hasCustomIcon(iconUuid())
|
||||||
&& !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
|
#ifndef KEEPASSX_ENTRY_H
|
||||||
#define KEEPASSX_ENTRY_H
|
#define KEEPASSX_ENTRY_H
|
||||||
|
|
||||||
#include <QImage>
|
#include <QMap>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
@ -80,8 +80,6 @@ public:
|
|||||||
~Entry();
|
~Entry();
|
||||||
const QUuid& uuid() const;
|
const QUuid& uuid() const;
|
||||||
const QString uuidToHex() const;
|
const QString uuidToHex() const;
|
||||||
QImage icon() const;
|
|
||||||
QPixmap iconPixmap(IconSize size = IconSize::Default) const;
|
|
||||||
int iconNumber() const;
|
int iconNumber() const;
|
||||||
const QUuid& iconUuid() const;
|
const QUuid& iconUuid() const;
|
||||||
QString foregroundColor() const;
|
QString foregroundColor() const;
|
||||||
|
@ -45,13 +45,6 @@
|
|||||||
static const auto TRUE_STR = QStringLiteral("true");
|
static const auto TRUE_STR = QStringLiteral("true");
|
||||||
static const auto FALSE_STR = QStringLiteral("false");
|
static const auto FALSE_STR = QStringLiteral("false");
|
||||||
|
|
||||||
enum IconSize
|
|
||||||
{
|
|
||||||
Default,
|
|
||||||
Medium,
|
|
||||||
Large
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class AuthDecision
|
enum class AuthDecision
|
||||||
{
|
{
|
||||||
Undecided,
|
Undecided,
|
||||||
|
@ -20,14 +20,16 @@
|
|||||||
#include "config-keepassx.h"
|
#include "config-keepassx.h"
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include "core/DatabaseIcons.h"
|
|
||||||
#include "core/Metadata.h"
|
|
||||||
#include "core/Tools.h"
|
|
||||||
|
|
||||||
#ifdef WITH_XC_KEESHARE
|
#ifdef WITH_XC_KEESHARE
|
||||||
#include "keeshare/KeeShare.h"
|
#include "keeshare/KeeShare.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "core/Global.h"
|
||||||
|
#include "core/Metadata.h"
|
||||||
|
#include "core/Tools.h"
|
||||||
|
|
||||||
|
#include <QtConcurrent>
|
||||||
#include <QtConcurrentFilter>
|
#include <QtConcurrentFilter>
|
||||||
|
|
||||||
const int Group::DefaultIconNumber = 48;
|
const int Group::DefaultIconNumber = 48;
|
||||||
@ -123,44 +125,6 @@ QString Group::notes() const
|
|||||||
return m_data.notes;
|
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
|
int Group::iconNumber() const
|
||||||
{
|
{
|
||||||
return m_data.iconNumber;
|
return m_data.iconNumber;
|
||||||
@ -469,7 +433,7 @@ void Group::setParent(Group* parent, int index)
|
|||||||
// copy custom icon to the new database
|
// copy custom icon to the new database
|
||||||
if (!iconUuid().isNull() && parent->m_db && m_db->metadata()->hasCustomIcon(iconUuid())
|
if (!iconUuid().isNull() && parent->m_db && m_db->metadata()->hasCustomIcon(iconUuid())
|
||||||
&& !parent->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) {
|
if (m_db != parent->m_db) {
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#ifndef KEEPASSX_GROUP_H
|
#ifndef KEEPASSX_GROUP_H
|
||||||
#define KEEPASSX_GROUP_H
|
#define KEEPASSX_GROUP_H
|
||||||
|
|
||||||
#include <QImage>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "core/CustomData.h"
|
#include "core/CustomData.h"
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
@ -82,8 +82,6 @@ public:
|
|||||||
const QString uuidToHex() const;
|
const QString uuidToHex() const;
|
||||||
QString name() const;
|
QString name() const;
|
||||||
QString notes() const;
|
QString notes() const;
|
||||||
QImage icon() const;
|
|
||||||
QPixmap iconPixmap(IconSize size = IconSize::Default) const;
|
|
||||||
int iconNumber() const;
|
int iconNumber() const;
|
||||||
const QUuid& iconUuid() const;
|
const QUuid& iconUuid() const;
|
||||||
const TimeInfo& timeInfo() const;
|
const TimeInfo& timeInfo() const;
|
||||||
|
@ -611,8 +611,7 @@ Merger::ChangeList Merger::mergeMetadata(const MergeContext& context)
|
|||||||
|
|
||||||
for (const auto& iconUuid : sourceMetadata->customIconsOrder()) {
|
for (const auto& iconUuid : sourceMetadata->customIconsOrder()) {
|
||||||
if (!targetMetadata->hasCustomIcon(iconUuid)) {
|
if (!targetMetadata->hasCustomIcon(iconUuid)) {
|
||||||
QImage customIcon = sourceMetadata->customIcon(iconUuid);
|
targetMetadata->addCustomIcon(iconUuid, sourceMetadata->customIcon(iconUuid));
|
||||||
targetMetadata->addCustomIcon(iconUuid, customIcon);
|
|
||||||
changes << tr("Adding missing icon %1").arg(QString::fromLatin1(iconUuid.toRfc4122().toHex()));
|
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) 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -17,7 +18,8 @@
|
|||||||
|
|
||||||
#include "Metadata.h"
|
#include "Metadata.h"
|
||||||
|
|
||||||
#include "core/DatabaseIcons.h"
|
#include "core/Clock.h"
|
||||||
|
#include "core/Entry.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -64,7 +66,6 @@ void Metadata::clear()
|
|||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
m_customIcons.clear();
|
m_customIcons.clear();
|
||||||
m_customIconsRaw.clear();
|
|
||||||
m_customIconsOrder.clear();
|
m_customIconsOrder.clear();
|
||||||
m_customIconsHashes.clear();
|
m_customIconsHashes.clear();
|
||||||
m_customData->clear();
|
m_customData->clear();
|
||||||
@ -175,33 +176,14 @@ bool Metadata::protectNotes() const
|
|||||||
return m_data.protectNotes;
|
return m_data.protectNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage Metadata::customIcon(const QUuid& uuid) const
|
QByteArray Metadata::customIcon(const QUuid& uuid) const
|
||||||
{
|
{
|
||||||
return m_customIconsRaw.value(uuid);
|
return m_customIcons.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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Metadata::hasCustomIcon(const QUuid& uuid) const
|
bool Metadata::hasCustomIcon(const QUuid& uuid) const
|
||||||
{
|
{
|
||||||
return m_customIconsRaw.contains(uuid);
|
return m_customIcons.contains(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QUuid> Metadata::customIconsOrder() const
|
QList<QUuid> Metadata::customIconsOrder() const
|
||||||
@ -357,32 +339,19 @@ void Metadata::setProtectNotes(bool value)
|
|||||||
set(m_data.protectNotes, 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(!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
|
// remove all uuids to prevent duplicates in release mode
|
||||||
m_customIconsOrder.removeAll(uuid);
|
m_customIconsOrder.removeAll(uuid);
|
||||||
m_customIconsOrder.append(uuid);
|
m_customIconsOrder.append(uuid);
|
||||||
// Associate image hash to uuid
|
// Associate image hash to uuid
|
||||||
QByteArray hash = hashImage(image);
|
QByteArray hash = hashIcon(iconData);
|
||||||
m_customIconsHashes[hash] = uuid;
|
m_customIconsHashes[hash] = uuid;
|
||||||
Q_ASSERT(m_customIconsRaw.count() == m_customIconsOrder.count());
|
Q_ASSERT(m_customIcons.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());
|
|
||||||
}
|
|
||||||
|
|
||||||
emitModified();
|
emitModified();
|
||||||
}
|
}
|
||||||
@ -390,24 +359,23 @@ void Metadata::addCustomIcon(const QUuid& uuid, const QImage& image)
|
|||||||
void Metadata::removeCustomIcon(const QUuid& uuid)
|
void Metadata::removeCustomIcon(const QUuid& uuid)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!uuid.isNull());
|
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
|
// 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) {
|
if (m_customIconsHashes.contains(hash) && m_customIconsHashes[hash] == uuid) {
|
||||||
m_customIconsHashes.remove(hash);
|
m_customIconsHashes.remove(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_customIcons.remove(uuid);
|
m_customIcons.remove(uuid);
|
||||||
m_customIconsRaw.remove(uuid);
|
|
||||||
m_customIconsOrder.removeAll(uuid);
|
m_customIconsOrder.removeAll(uuid);
|
||||||
Q_ASSERT(m_customIconsRaw.count() == m_customIconsOrder.count());
|
Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count());
|
||||||
emitModified();
|
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());
|
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)
|
return QCryptographicHash::hash(iconData, QCryptographicHash::Md5);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setRecycleBinEnabled(bool value)
|
void Metadata::setRecycleBinEnabled(bool value)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -19,7 +20,7 @@
|
|||||||
#define KEEPASSX_METADATA_H
|
#define KEEPASSX_METADATA_H
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QIcon>
|
#include <QHash>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
@ -78,10 +79,8 @@ public:
|
|||||||
bool protectPassword() const;
|
bool protectPassword() const;
|
||||||
bool protectUrl() const;
|
bool protectUrl() const;
|
||||||
bool protectNotes() const;
|
bool protectNotes() const;
|
||||||
QImage customIcon(const QUuid& uuid) const;
|
QByteArray customIcon(const QUuid& uuid) const;
|
||||||
bool hasCustomIcon(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;
|
QList<QUuid> customIconsOrder() const;
|
||||||
bool recycleBinEnabled() const;
|
bool recycleBinEnabled() const;
|
||||||
Group* recycleBin();
|
Group* recycleBin();
|
||||||
@ -117,10 +116,10 @@ public:
|
|||||||
void setProtectPassword(bool value);
|
void setProtectPassword(bool value);
|
||||||
void setProtectUrl(bool value);
|
void setProtectUrl(bool value);
|
||||||
void setProtectNotes(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 removeCustomIcon(const QUuid& uuid);
|
||||||
void copyCustomIcons(const QSet<QUuid>& iconList, const Metadata* otherMetadata);
|
void copyCustomIcons(const QSet<QUuid>& iconList, const Metadata* otherMetadata);
|
||||||
QUuid findCustomIcon(const QImage& candidate);
|
QUuid findCustomIcon(const QByteArray& candidate);
|
||||||
void setRecycleBinEnabled(bool value);
|
void setRecycleBinEnabled(bool value);
|
||||||
void setRecycleBin(Group* group);
|
void setRecycleBin(Group* group);
|
||||||
void setRecycleBinChanged(const QDateTime& value);
|
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);
|
||||||
template <class P, class V> bool set(P& property, const V& value, QDateTime& dateTime);
|
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;
|
MetadataData m_data;
|
||||||
|
|
||||||
QHash<QUuid, QIcon> m_customIcons;
|
|
||||||
QHash<QUuid, QImage> m_customIconsRaw;
|
|
||||||
QList<QUuid> m_customIconsOrder;
|
QList<QUuid> m_customIconsOrder;
|
||||||
|
QHash<QUuid, QByteArray> m_customIcons;
|
||||||
QHash<QByteArray, QUuid> m_customIconsHashes;
|
QHash<QByteArray, QUuid> m_customIconsHashes;
|
||||||
|
|
||||||
QPointer<Group> m_recycleBin;
|
QPointer<Group> m_recycleBin;
|
||||||
|
@ -24,9 +24,11 @@
|
|||||||
|
|
||||||
#include "core/Clock.h"
|
#include "core/Clock.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
#include <QEventLoop>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QImageReader>
|
#include <QIODevice>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QMetaProperty>
|
#include <QMetaProperty>
|
||||||
#include <QRegularExpression>
|
#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)
|
bool isHex(const QByteArray& ba)
|
||||||
{
|
{
|
||||||
for (const uchar c : ba) {
|
for (const uchar c : ba) {
|
||||||
|
@ -32,7 +32,6 @@ namespace Tools
|
|||||||
QString humanReadableFileSize(qint64 bytes, quint32 precision = 2);
|
QString humanReadableFileSize(qint64 bytes, quint32 precision = 2);
|
||||||
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
|
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
|
||||||
bool readAllFromDevice(QIODevice* device, QByteArray& data);
|
bool readAllFromDevice(QIODevice* device, QByteArray& data);
|
||||||
QString imageReaderFilter();
|
|
||||||
bool isHex(const QByteArray& ba);
|
bool isHex(const QByteArray& ba);
|
||||||
bool isBase64(const QByteArray& ba);
|
bool isBase64(const QByteArray& ba);
|
||||||
void sleep(int ms);
|
void sleep(int ms);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "fdosecrets/widgets/RowButtonHelper.h"
|
#include "fdosecrets/widgets/RowButtonHelper.h"
|
||||||
|
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
|
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
@ -250,7 +251,7 @@ QVariant AccessControlDialog::EntryModel::data(const QModelIndex& index, int rol
|
|||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
return entry->title();
|
return entry->title();
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
return entry->icon();
|
return Icons::entryIconPixmap(entry);
|
||||||
case Qt::CheckStateRole:
|
case Qt::CheckStateRole:
|
||||||
return QVariant::fromValue(m_selected.contains(entry) ? Qt::Checked : Qt::Unchecked);
|
return QVariant::fromValue(m_selected.contains(entry) ? Qt::Checked : Qt::Unchecked);
|
||||||
default:
|
default:
|
||||||
|
@ -147,7 +147,7 @@ namespace FdoSecrets
|
|||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
return group->name();
|
return group->name();
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
return group->iconPixmap();
|
return Icons::groupIconPixmap(group);
|
||||||
case Qt::FontRole:
|
case Qt::FontRole:
|
||||||
if (group->isExpired()) {
|
if (group->isExpired()) {
|
||||||
QFont font;
|
QFont font;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "KdbxXmlReader.h"
|
#include "KdbxXmlReader.h"
|
||||||
#include "KeePass2RandomStream.h"
|
#include "KeePass2RandomStream.h"
|
||||||
#include "core/DatabaseIcons.h"
|
#include "core/Clock.h"
|
||||||
#include "core/Endian.h"
|
#include "core/Endian.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Tools.h"
|
#include "core/Tools.h"
|
||||||
@ -346,7 +346,7 @@ void KdbxXmlReader::parseIcon()
|
|||||||
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Icon");
|
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Icon");
|
||||||
|
|
||||||
QUuid uuid;
|
QUuid uuid;
|
||||||
QImage icon;
|
QByteArray iconData;
|
||||||
bool uuidSet = false;
|
bool uuidSet = false;
|
||||||
bool iconSet = false;
|
bool iconSet = false;
|
||||||
|
|
||||||
@ -355,7 +355,7 @@ void KdbxXmlReader::parseIcon()
|
|||||||
uuid = readUuid();
|
uuid = readUuid();
|
||||||
uuidSet = !uuid.isNull();
|
uuidSet = !uuid.isNull();
|
||||||
} else if (m_xml.name() == "Data") {
|
} else if (m_xml.name() == "Data") {
|
||||||
icon.loadFromData(readBinary());
|
iconData = readBinary();
|
||||||
iconSet = true;
|
iconSet = true;
|
||||||
} else {
|
} else {
|
||||||
skipCurrentElement();
|
skipCurrentElement();
|
||||||
@ -367,7 +367,7 @@ void KdbxXmlReader::parseIcon()
|
|||||||
if (m_meta->hasCustomIcon(uuid)) {
|
if (m_meta->hasCustomIcon(uuid)) {
|
||||||
uuid = QUuid::createUuid();
|
uuid = QUuid::createUuid();
|
||||||
}
|
}
|
||||||
m_meta->addCustomIcon(uuid, icon);
|
m_meta->addCustomIcon(uuid, iconData);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,9 +509,6 @@ Group* KdbxXmlReader::parseGroup()
|
|||||||
raiseError(tr("Invalid group icon number"));
|
raiseError(tr("Invalid group icon number"));
|
||||||
}
|
}
|
||||||
iconId = 0;
|
iconId = 0;
|
||||||
} else if (iconId >= databaseIcons()->count()) {
|
|
||||||
qWarning("KdbxXmlReader::parseGroup: icon id \"%d\" not supported", iconId);
|
|
||||||
iconId = databaseIcons()->count() - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
group->setIcon(iconId);
|
group->setIcon(iconId);
|
||||||
|
@ -162,19 +162,12 @@ void KdbxXmlWriter::writeCustomIcons()
|
|||||||
m_xml.writeEndElement();
|
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");
|
m_xml.writeStartElement("Icon");
|
||||||
|
|
||||||
writeUuid("UUID", uuid);
|
writeUuid("UUID", uuid);
|
||||||
|
writeBinary("Data", iconData);
|
||||||
QByteArray ba;
|
|
||||||
QBuffer buffer(&ba);
|
|
||||||
buffer.open(QIODevice::WriteOnly);
|
|
||||||
// TODO: check !icon.save()
|
|
||||||
icon.save(&buffer, "PNG");
|
|
||||||
buffer.close();
|
|
||||||
writeBinary("Data", ba);
|
|
||||||
|
|
||||||
m_xml.writeEndElement();
|
m_xml.writeEndElement();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#ifndef KEEPASSX_KDBXXMLWRITER_H
|
#ifndef KEEPASSX_KDBXXMLWRITER_H
|
||||||
#define KEEPASSX_KDBXXMLWRITER_H
|
#define KEEPASSX_KDBXXMLWRITER_H
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
|
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
@ -46,7 +47,7 @@ private:
|
|||||||
void writeMetadata();
|
void writeMetadata();
|
||||||
void writeMemoryProtection();
|
void writeMemoryProtection();
|
||||||
void writeCustomIcons();
|
void writeCustomIcons();
|
||||||
void writeIcon(const QUuid& uuid, const QImage& icon);
|
void writeIcon(const QUuid& uuid, const QByteArray& iconData);
|
||||||
void writeBinaries();
|
void writeBinaries();
|
||||||
void writeCustomData(const CustomData* customData);
|
void writeCustomData(const CustomData* customData);
|
||||||
void writeCustomDataItem(const QString& key, const QString& value);
|
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)) {
|
if (static_cast<quint32>(data.size()) < (pos + iconSize)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QImage icon = QImage::fromData(data.mid(pos, iconSize));
|
QByteArray icon = data.mid(pos, iconSize);
|
||||||
pos += iconSize;
|
pos += iconSize;
|
||||||
|
|
||||||
if (icon.width() != 16 || icon.height() != 16) {
|
|
||||||
icon = icon.scaled(16, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
QUuid uuid = QUuid::createUuid();
|
QUuid uuid = QUuid::createUuid();
|
||||||
iconUuids.append(uuid);
|
iconUuids.append(uuid);
|
||||||
m_db->metadata()->addCustomIcon(uuid, icon);
|
m_db->metadata()->addCustomIcon(uuid, icon);
|
||||||
|
@ -57,8 +57,9 @@ DatabaseIcons* DatabaseIcons::instance()
|
|||||||
QPixmap DatabaseIcons::icon(int index, IconSize size)
|
QPixmap DatabaseIcons::icon(int index, IconSize size)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= count()) {
|
if (index < 0 || index >= count()) {
|
||||||
qWarning("DatabaseIcons::icon: invalid icon index %d", index);
|
qWarning("DatabaseIcons::icon: invalid icon index %d, using 0 instead", index);
|
||||||
return {};
|
index = 0;
|
||||||
|
Q_ASSERT_X(false, "DatabaseIcons::icon", "invalid icon index %d");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cacheKey = QString::number(index);
|
auto cacheKey = QString::number(index);
|
@ -18,9 +18,15 @@
|
|||||||
#ifndef KEEPASSX_DATABASEICONS_H
|
#ifndef KEEPASSX_DATABASEICONS_H
|
||||||
#define KEEPASSX_DATABASEICONS_H
|
#define KEEPASSX_DATABASEICONS_H
|
||||||
|
|
||||||
#include "core/Global.h"
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
|
enum IconSize
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
Medium,
|
||||||
|
Large
|
||||||
|
};
|
||||||
|
|
||||||
class DatabaseIcons
|
class DatabaseIcons
|
||||||
{
|
{
|
||||||
public:
|
public:
|
@ -22,10 +22,13 @@
|
|||||||
#include "autotype/AutoType.h"
|
#include "autotype/AutoType.h"
|
||||||
#include "core/Tools.h"
|
#include "core/Tools.h"
|
||||||
#include "format/CsvExporter.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/DatabaseWidgetStateSync.h"
|
||||||
#include "gui/DragTabBar.h"
|
#include "gui/DragTabBar.h"
|
||||||
#include "gui/FileDialog.h"
|
#include "gui/FileDialog.h"
|
||||||
|
#include "gui/HtmlExporter.h"
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
#include "gui/osutils/macutils/MacUtils.h"
|
#include "gui/osutils/macutils/MacUtils.h"
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "core/Tools.h"
|
#include "core/Tools.h"
|
||||||
#include "gui/FileDialog.h"
|
#include "gui/FileDialog.h"
|
||||||
#include "gui/IconModels.h"
|
#include "gui/IconModels.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
|
#include "gui/MessageBox.h"
|
||||||
#ifdef WITH_XC_NETWORKING
|
#ifdef WITH_XC_NETWORKING
|
||||||
#include "gui/IconDownloader.h"
|
#include "gui/IconDownloader.h"
|
||||||
#endif
|
#endif
|
||||||
@ -128,7 +130,7 @@ void EditWidgetIcons::load(const QUuid& currentUuid,
|
|||||||
m_currentUuid = currentUuid;
|
m_currentUuid = currentUuid;
|
||||||
setUrl(url);
|
setUrl(url);
|
||||||
|
|
||||||
m_customIconModel->setIcons(database->metadata()->customIconsPixmaps(IconSize::Default),
|
m_customIconModel->setIcons(Icons::customIconsPixmaps(database.data(), IconSize::Default),
|
||||||
database->metadata()->customIconsOrder());
|
database->metadata()->customIconsOrder());
|
||||||
|
|
||||||
QUuid iconUuid = iconStruct.uuid;
|
QUuid iconUuid = iconStruct.uuid;
|
||||||
@ -231,7 +233,7 @@ void EditWidgetIcons::addCustomIconFromFile()
|
|||||||
return;
|
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 =
|
auto filenames =
|
||||||
fileDialog()->getOpenFileNames(this, tr("Select Image(s)"), FileDialog::getLastDir("icons"), filter);
|
fileDialog()->getOpenFileNames(this, tr("Select Image(s)"), FileDialog::getLastDir("icons"), filter);
|
||||||
if (!filenames.empty()) {
|
if (!filenames.empty()) {
|
||||||
@ -284,16 +286,17 @@ bool EditWidgetIcons::addCustomIcon(const QImage& icon)
|
|||||||
bool added = false;
|
bool added = false;
|
||||||
if (m_db) {
|
if (m_db) {
|
||||||
// Don't add an icon larger than 128x128, but retain original size if smaller
|
// 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) {
|
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()) {
|
if (uuid.isNull()) {
|
||||||
uuid = QUuid::createUuid();
|
uuid = QUuid::createUuid();
|
||||||
m_db->metadata()->addCustomIcon(uuid, scaledicon);
|
m_db->metadata()->addCustomIcon(uuid, serializedIcon);
|
||||||
m_customIconModel->setIcons(m_db->metadata()->customIconsPixmaps(IconSize::Default),
|
m_customIconModel->setIcons(Icons::customIconsPixmaps(m_db.data(), IconSize::Default),
|
||||||
m_db->metadata()->customIconsOrder());
|
m_db->metadata()->customIconsOrder());
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ void EntryPreviewWidget::updateEntryHeaderLine()
|
|||||||
Q_ASSERT(m_currentEntry);
|
Q_ASSERT(m_currentEntry);
|
||||||
const QString title = m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->title());
|
const QString title = m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->title());
|
||||||
m_ui->entryTitleLabel->setRawText(hierarchy(m_currentEntry->group(), 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()
|
void EntryPreviewWidget::updateEntryTotp()
|
||||||
@ -377,7 +377,7 @@ void EntryPreviewWidget::updateGroupHeaderLine()
|
|||||||
{
|
{
|
||||||
Q_ASSERT(m_currentGroup);
|
Q_ASSERT(m_currentGroup);
|
||||||
m_ui->groupTitleLabel->setRawText(hierarchy(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()
|
void EntryPreviewWidget::updateGroupGeneralTab()
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -204,7 +205,7 @@ bool HtmlExporter::writeGroup(QIODevice& device, const Group& group, QString pat
|
|||||||
|
|
||||||
// Header line
|
// Header line
|
||||||
auto header = QString("<hr><h2>");
|
auto header = QString("<hr><h2>");
|
||||||
header.append(PixmapToHTML(group.iconPixmap(IconSize::Medium)));
|
header.append(PixmapToHTML(Icons::groupIconPixmap(&group, IconSize::Medium)));
|
||||||
header.append(" ");
|
header.append(" ");
|
||||||
header.append(path);
|
header.append(path);
|
||||||
header.append("</h2>\n");
|
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
|
// Output it into our table. First the left side with
|
||||||
// icon and entry title ...
|
// icon and entry title ...
|
||||||
table += "<tr>";
|
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>";
|
table += "<td width=\"19%\" valign=\"top\"><h3>" + entry->title().toHtmlEscaped() + "</h3></td>";
|
||||||
|
|
||||||
// ... then the right side with the data fields
|
// ... then the right side with the data fields
|
@ -24,7 +24,12 @@
|
|||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "core/Tools.h"
|
#include "core/Tools.h"
|
||||||
#include "gui/IconDownloader.h"
|
#include "gui/IconDownloader.h"
|
||||||
|
#include "gui/IconModels.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
#include "osutils/OSUtils.h"
|
#include "osutils/OSUtils.h"
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
#include "gui/osutils/macutils/MacUtils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
@ -126,15 +131,16 @@ void IconDownloaderDialog::downloadFinished(const QString& url, const QImage& ic
|
|||||||
|
|
||||||
if (m_db && !icon.isNull()) {
|
if (m_db && !icon.isNull()) {
|
||||||
// Don't add an icon larger than 128x128, but retain original size if smaller
|
// 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) {
|
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()) {
|
if (uuid.isNull()) {
|
||||||
uuid = QUuid::createUuid();
|
uuid = QUuid::createUuid();
|
||||||
m_db->metadata()->addCustomIcon(uuid, scaledicon);
|
m_db->metadata()->addCustomIcon(uuid, serializedIcon);
|
||||||
updateTable(url, tr("Ok"));
|
updateTable(url, tr("Ok"));
|
||||||
} else {
|
} else {
|
||||||
updateTable(url, tr("Already Exists"));
|
updateTable(url, tr("Already Exists"));
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include "core/DatabaseIcons.h"
|
#include "gui/DatabaseIcons.h"
|
||||||
|
|
||||||
DefaultIconModel::DefaultIconModel(QObject* parent)
|
DefaultIconModel::DefaultIconModel(QObject* parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
|
@ -19,11 +19,20 @@
|
|||||||
#include "Icons.h"
|
#include "Icons.h"
|
||||||
|
|
||||||
#include <QIconEngine>
|
#include <QIconEngine>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QPaintDevice>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "config-keepassx.h"
|
||||||
|
#include "core/Config.h"
|
||||||
|
#include "gui/DatabaseIcons.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
#include "gui/osutils/OSUtils.h"
|
#include "gui/osutils/OSUtils.h"
|
||||||
|
|
||||||
|
#ifdef WITH_XC_KEESHARE
|
||||||
|
#include "keeshare/KeeShare.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class AdaptiveIconEngine : public QIconEngine
|
class AdaptiveIconEngine : public QIconEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -206,3 +215,97 @@ Icons* Icons::instance()
|
|||||||
|
|
||||||
return m_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 <QIcon>
|
||||||
|
|
||||||
|
#include <core/Database.h>
|
||||||
|
#include <gui/DatabaseIcons.h>
|
||||||
|
|
||||||
class Icons
|
class Icons
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -32,6 +35,14 @@ public:
|
|||||||
QIcon icon(const QString& name, bool recolor = true, const QColor& overrideColor = QColor::Invalid);
|
QIcon icon(const QString& name, bool recolor = true, const QColor& overrideColor = QColor::Invalid);
|
||||||
QIcon onOffIcon(const QString& name, bool on, bool recolor = true);
|
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();
|
static Icons* instance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "gui/IconModels.h"
|
#include "gui/IconModels.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
|
|
||||||
DatabaseSettingsWidgetMaintenance::DatabaseSettingsWidgetMaintenance(QWidget* parent)
|
DatabaseSettingsWidgetMaintenance::DatabaseSettingsWidgetMaintenance(QWidget* parent)
|
||||||
@ -47,7 +48,7 @@ DatabaseSettingsWidgetMaintenance::~DatabaseSettingsWidgetMaintenance()
|
|||||||
|
|
||||||
void DatabaseSettingsWidgetMaintenance::populateIcons(QSharedPointer<Database> db)
|
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());
|
db->metadata()->customIconsOrder());
|
||||||
m_ui->deleteButton->setEnabled(false);
|
m_ui->deleteButton->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,11 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
|
|
||||||
|
#include "core/Entry.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "core/PasswordHealth.h"
|
#include "core/PasswordHealth.h"
|
||||||
|
#include "gui/DatabaseIcons.h"
|
||||||
#include "gui/Icons.h"
|
#include "gui/Icons.h"
|
||||||
#include "gui/styles/StateColorPalette.h"
|
#include "gui/styles/StateColorPalette.h"
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
@ -277,11 +279,11 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
|
|||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case ParentGroup:
|
case ParentGroup:
|
||||||
if (entry->group()) {
|
if (entry->group()) {
|
||||||
return entry->group()->iconPixmap();
|
return Icons::groupIconPixmap(entry->group());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Title:
|
case Title:
|
||||||
return entry->iconPixmap();
|
return Icons::entryIconPixmap(entry);
|
||||||
case Paperclip:
|
case Paperclip:
|
||||||
if (!entry->attachments()->isEmpty()) {
|
if (!entry->attachments()->isEmpty()) {
|
||||||
return icons()->icon("paperclip");
|
return icons()->icon("paperclip");
|
||||||
|
@ -19,8 +19,12 @@
|
|||||||
|
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
|
|
||||||
|
#include "core/Database.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
|
#include "core/Tools.h"
|
||||||
|
#include "gui/DatabaseIcons.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
#include "keeshare/KeeShare.h"
|
#include "keeshare/KeeShare.h"
|
||||||
|
|
||||||
GroupModel::GroupModel(Database* db, QObject* parent)
|
GroupModel::GroupModel(Database* db, QObject* parent)
|
||||||
@ -126,7 +130,7 @@ QVariant GroupModel::data(const QModelIndex& index, int role) const
|
|||||||
#endif
|
#endif
|
||||||
return nameTemplate.arg(group->name());
|
return nameTemplate.arg(group->name());
|
||||||
} else if (role == Qt::DecorationRole) {
|
} else if (role == Qt::DecorationRole) {
|
||||||
return group->iconPixmap();
|
return Icons::groupIconPixmap(group);
|
||||||
} else if (role == Qt::FontRole) {
|
} else if (role == Qt::FontRole) {
|
||||||
QFont font;
|
QFont font;
|
||||||
if (group->isExpired()) {
|
if (group->isExpired()) {
|
||||||
|
@ -203,8 +203,8 @@ void ReportsWidgetHealthcheck::addHealthRow(QSharedPointer<PasswordHealth> healt
|
|||||||
|
|
||||||
auto row = QList<QStandardItem*>();
|
auto row = QList<QStandardItem*>();
|
||||||
row << new QStandardItem(descr);
|
row << new QStandardItem(descr);
|
||||||
row << new QStandardItem(entry->iconPixmap(), title);
|
row << new QStandardItem(Icons::entryIconPixmap(entry), title);
|
||||||
row << new QStandardItem(group->iconPixmap(), group->hierarchy().join("/"));
|
row << new QStandardItem(Icons::groupIconPixmap(group), group->hierarchy().join("/"));
|
||||||
row << new QStandardItem(QString::number(health->score()));
|
row << new QStandardItem(QString::number(health->score()));
|
||||||
row << new QStandardItem(health->scoreReason());
|
row << new QStandardItem(health->scoreReason());
|
||||||
|
|
||||||
|
@ -163,8 +163,8 @@ void ReportsWidgetHibp::makeHibpTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto row = QList<QStandardItem*>();
|
auto row = QList<QStandardItem*>();
|
||||||
row << new QStandardItem(entry->iconPixmap(), title)
|
row << new QStandardItem(Icons::entryIconPixmap(entry), title)
|
||||||
<< new QStandardItem(group->iconPixmap(), group->hierarchy().join("/"))
|
<< new QStandardItem(Icons::groupIconPixmap(group), group->hierarchy().join("/"))
|
||||||
<< new QStandardItem(countToText(count));
|
<< new QStandardItem(countToText(count));
|
||||||
|
|
||||||
if (entry->excludeFromReports()) {
|
if (entry->excludeFromReports()) {
|
||||||
|
@ -16,8 +16,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "KeeShare.h"
|
#include "KeeShare.h"
|
||||||
#include "core/DatabaseIcons.h"
|
#include "core/CustomData.h"
|
||||||
|
#include "core/Database.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
|
#include "core/Metadata.h"
|
||||||
|
#include "gui/DatabaseIcons.h"
|
||||||
#include "keeshare/ShareObserver.h"
|
#include "keeshare/ShareObserver.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -17,7 +17,13 @@
|
|||||||
|
|
||||||
#include "KeeShareSettings.h"
|
#include "KeeShareSettings.h"
|
||||||
|
|
||||||
|
#include "core/CustomData.h"
|
||||||
|
#include "core/Database.h"
|
||||||
|
#include "core/Group.h"
|
||||||
|
#include "core/Metadata.h"
|
||||||
#include "crypto/Random.h"
|
#include "crypto/Random.h"
|
||||||
|
#include "gui/DatabaseIcons.h"
|
||||||
|
#include "keeshare/Signature.h"
|
||||||
|
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "format/KeePass2Writer.h"
|
#include "format/KeePass2Writer.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
#include "keeshare/KeeShare.h"
|
#include "keeshare/KeeShare.h"
|
||||||
#include "keeshare/Signature.h"
|
#include "keeshare/Signature.h"
|
||||||
#include "keys/PasswordKey.h"
|
#include "keys/PasswordKey.h"
|
||||||
@ -81,7 +82,7 @@ namespace
|
|||||||
targetEntry->setUpdateTimeinfo(updateTimeinfoEntry);
|
targetEntry->setUpdateTimeinfo(updateTimeinfoEntry);
|
||||||
const auto iconUuid = targetEntry->iconUuid();
|
const auto iconUuid = targetEntry->iconUuid();
|
||||||
if (!iconUuid.isNull() && !targetMetadata->hasCustomIcon(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})
|
add_library(qrcode STATIC ${qrcode_SOURCES})
|
||||||
target_include_directories(qrcode PRIVATE ${QRENCODE_INCLUDE_DIR})
|
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 <QSignalSpy>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
#include "core/DatabaseIcons.h"
|
#include "core/Entry.h"
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
|
#include "gui/DatabaseIcons.h"
|
||||||
#include "gui/IconModels.h"
|
#include "gui/IconModels.h"
|
||||||
#include "gui/SortFilterHideProxyModel.h"
|
#include "gui/SortFilterHideProxyModel.h"
|
||||||
#include "gui/entry/AutoTypeAssociationsModel.h"
|
#include "gui/entry/AutoTypeAssociationsModel.h"
|
||||||
|
@ -315,36 +315,34 @@ void TestGroup::testCopyCustomIcon()
|
|||||||
QScopedPointer<Database> dbSource(new Database());
|
QScopedPointer<Database> dbSource(new Database());
|
||||||
|
|
||||||
QUuid groupIconUuid = QUuid::createUuid();
|
QUuid groupIconUuid = QUuid::createUuid();
|
||||||
QImage groupIcon(16, 16, QImage::Format_RGB32);
|
QByteArray groupIcon("group icon");
|
||||||
groupIcon.setPixel(0, 0, qRgb(255, 0, 0));
|
|
||||||
dbSource->metadata()->addCustomIcon(groupIconUuid, groupIcon);
|
dbSource->metadata()->addCustomIcon(groupIconUuid, groupIcon);
|
||||||
|
|
||||||
QUuid entryIconUuid = QUuid::createUuid();
|
QUuid entryIconUuid = QUuid::createUuid();
|
||||||
QImage entryIcon(16, 16, QImage::Format_RGB32);
|
QByteArray entryIcon("entry icon");
|
||||||
entryIcon.setPixel(0, 0, qRgb(255, 0, 0));
|
|
||||||
dbSource->metadata()->addCustomIcon(entryIconUuid, entryIcon);
|
dbSource->metadata()->addCustomIcon(entryIconUuid, entryIcon);
|
||||||
|
|
||||||
Group* group = new Group();
|
Group* group = new Group();
|
||||||
group->setParent(dbSource->rootGroup());
|
group->setParent(dbSource->rootGroup());
|
||||||
group->setIcon(groupIconUuid);
|
group->setIcon(groupIconUuid);
|
||||||
QCOMPARE(group->icon(), groupIcon);
|
QCOMPARE(group->database()->metadata()->customIcon(groupIconUuid), groupIcon);
|
||||||
|
|
||||||
Entry* entry = new Entry();
|
Entry* entry = new Entry();
|
||||||
entry->setGroup(dbSource->rootGroup());
|
entry->setGroup(dbSource->rootGroup());
|
||||||
entry->setIcon(entryIconUuid);
|
entry->setIcon(entryIconUuid);
|
||||||
QCOMPARE(entry->icon(), entryIcon);
|
QCOMPARE(entry->database()->metadata()->customIcon(entryIconUuid), entryIcon);
|
||||||
|
|
||||||
QScopedPointer<Database> dbTarget(new Database());
|
QScopedPointer<Database> dbTarget(new Database());
|
||||||
|
|
||||||
group->setParent(dbTarget->rootGroup());
|
group->setParent(dbTarget->rootGroup());
|
||||||
QVERIFY(dbTarget->metadata()->hasCustomIcon(groupIconUuid));
|
QVERIFY(dbTarget->metadata()->hasCustomIcon(groupIconUuid));
|
||||||
QCOMPARE(dbTarget->metadata()->customIcon(groupIconUuid), groupIcon);
|
QCOMPARE(dbTarget->metadata()->customIcon(groupIconUuid), groupIcon);
|
||||||
QCOMPARE(group->icon(), groupIcon);
|
QCOMPARE(group->database()->metadata()->customIcon(groupIconUuid), groupIcon);
|
||||||
|
|
||||||
entry->setGroup(dbTarget->rootGroup());
|
entry->setGroup(dbTarget->rootGroup());
|
||||||
QVERIFY(dbTarget->metadata()->hasCustomIcon(entryIconUuid));
|
QVERIFY(dbTarget->metadata()->hasCustomIcon(entryIconUuid));
|
||||||
QCOMPARE(dbTarget->metadata()->customIcon(entryIconUuid), entryIcon);
|
QCOMPARE(dbTarget->metadata()->customIcon(entryIconUuid), entryIcon);
|
||||||
QCOMPARE(entry->icon(), entryIcon);
|
QCOMPARE(entry->database()->metadata()->customIcon(entryIconUuid), entryIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGroup::testClone()
|
void TestGroup::testClone()
|
||||||
@ -425,11 +423,9 @@ void TestGroup::testCopyCustomIcons()
|
|||||||
QScopedPointer<Database> dbSource(new Database());
|
QScopedPointer<Database> dbSource(new Database());
|
||||||
QScopedPointer<Database> dbTarget(new Database());
|
QScopedPointer<Database> dbTarget(new Database());
|
||||||
|
|
||||||
QImage iconImage1(1, 1, QImage::Format_RGB32);
|
QByteArray iconImage1("icon 1");
|
||||||
iconImage1.setPixel(0, 0, qRgb(1, 2, 3));
|
|
||||||
|
|
||||||
QImage iconImage2(1, 1, QImage::Format_RGB32);
|
QByteArray iconImage2("icon 2");
|
||||||
iconImage2.setPixel(0, 0, qRgb(4, 5, 6));
|
|
||||||
|
|
||||||
QScopedPointer<Group> group1(new Group());
|
QScopedPointer<Group> group1(new Group());
|
||||||
group1->setParent(dbSource->rootGroup());
|
group1->setParent(dbSource->rootGroup());
|
||||||
@ -469,8 +465,8 @@ void TestGroup::testCopyCustomIcons()
|
|||||||
QVERIFY(metaTarget->hasCustomIcon(entry1IconOld));
|
QVERIFY(metaTarget->hasCustomIcon(entry1IconOld));
|
||||||
QVERIFY(metaTarget->hasCustomIcon(entry1IconNew));
|
QVERIFY(metaTarget->hasCustomIcon(entry1IconNew));
|
||||||
|
|
||||||
QCOMPARE(metaTarget->customIcon(group1Icon).pixel(0, 0), qRgb(1, 2, 3));
|
QCOMPARE(metaTarget->customIcon(group1Icon), iconImage1);
|
||||||
QCOMPARE(metaTarget->customIcon(group2Icon).pixel(0, 0), qRgb(4, 5, 6));
|
QCOMPARE(metaTarget->customIcon(group2Icon), iconImage2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGroup::testFindEntry()
|
void TestGroup::testFindEntry()
|
||||||
@ -1075,21 +1071,18 @@ void TestGroup::testApplyGroupIconRecursively()
|
|||||||
// Set an icon per UUID to the subgroup and apply recursively
|
// Set an icon per UUID to the subgroup and apply recursively
|
||||||
// -> all groups and entries except the root group have the same icon
|
// -> all groups and entries except the root group have the same icon
|
||||||
const QUuid subgroupIconUuid = QUuid::createUuid();
|
const QUuid subgroupIconUuid = QUuid::createUuid();
|
||||||
QImage subgroupIcon(16, 16, QImage::Format_RGB32);
|
QByteArray subgroupIcon("subgroup icon");
|
||||||
subgroupIcon.setPixel(0, 0, qRgb(255, 0, 0));
|
|
||||||
database.metadata()->addCustomIcon(subgroupIconUuid, subgroupIcon);
|
database.metadata()->addCustomIcon(subgroupIconUuid, subgroupIcon);
|
||||||
subgroup->setIcon(subgroupIconUuid);
|
subgroup->setIcon(subgroupIconUuid);
|
||||||
subgroup->applyGroupIconToChildGroups();
|
subgroup->applyGroupIconToChildGroups();
|
||||||
subgroup->applyGroupIconToChildEntries();
|
subgroup->applyGroupIconToChildEntries();
|
||||||
QVERIFY(database.rootGroup()->iconNumber() == rootIconNumber);
|
QVERIFY(database.rootGroup()->iconNumber() == rootIconNumber);
|
||||||
QCOMPARE(subgroup->iconUuid(), subgroupIconUuid);
|
QCOMPARE(subgroup->iconUuid(), subgroupIconUuid);
|
||||||
QCOMPARE(subgroup->icon(), subgroupIcon);
|
|
||||||
QCOMPARE(subgroupEntry->iconUuid(), subgroupIconUuid);
|
QCOMPARE(subgroupEntry->iconUuid(), subgroupIconUuid);
|
||||||
QCOMPARE(subgroupEntry->icon(), subgroupIcon);
|
|
||||||
QCOMPARE(subsubgroup->iconUuid(), subgroupIconUuid);
|
QCOMPARE(subsubgroup->iconUuid(), subgroupIconUuid);
|
||||||
QCOMPARE(subsubgroup->icon(), subgroupIcon);
|
|
||||||
QCOMPARE(subsubgroupEntry->iconUuid(), subgroupIconUuid);
|
QCOMPARE(subsubgroupEntry->iconUuid(), subgroupIconUuid);
|
||||||
QCOMPARE(subsubgroupEntry->icon(), subgroupIcon);
|
QCOMPARE(subgroup->database()->metadata()->customIcon(subgroupIconUuid), subgroupIcon);
|
||||||
|
|
||||||
// Reset all icons to root icon
|
// Reset all icons to root icon
|
||||||
database.rootGroup()->setIcon(rootIconNumber);
|
database.rootGroup()->setIcon(rootIconNumber);
|
||||||
|
@ -114,20 +114,12 @@ void TestKeePass1Reader::testMasterKey()
|
|||||||
void TestKeePass1Reader::testCustomIcons()
|
void TestKeePass1Reader::testCustomIcons()
|
||||||
{
|
{
|
||||||
QCOMPARE(m_db->metadata()->customIconsOrder().size(), 1);
|
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);
|
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"));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKeePass1Reader::testGroupExpanded()
|
void TestKeePass1Reader::testGroupExpanded()
|
||||||
|
@ -113,18 +113,10 @@ void TestKeePass2Format::testXmlCustomIcons()
|
|||||||
QCOMPARE(m_xmlDb->metadata()->customIconsOrder().size(), 1);
|
QCOMPARE(m_xmlDb->metadata()->customIconsOrder().size(), 1);
|
||||||
QUuid uuid = QUuid::fromRfc4122(QByteArray::fromBase64("++vyI+daLk6omox4a6kQGA=="));
|
QUuid uuid = QUuid::fromRfc4122(QByteArray::fromBase64("++vyI+daLk6omox4a6kQGA=="));
|
||||||
QVERIFY(m_xmlDb->metadata()->hasCustomIcon(uuid));
|
QVERIFY(m_xmlDb->metadata()->hasCustomIcon(uuid));
|
||||||
QImage icon = m_xmlDb->metadata()->customIcon(uuid);
|
QByteArray icon = m_xmlDb->metadata()->customIcon(uuid);
|
||||||
QCOMPARE(icon.width(), 16);
|
|
||||||
QCOMPARE(icon.height(), 16);
|
|
||||||
|
|
||||||
for (int x = 0; x < 16; x++) {
|
QVERIFY(icon.startsWith(
|
||||||
for (int y = 0; y < 16; y++) {
|
"\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"));
|
||||||
QRgb rgb = icon.pixel(x, y);
|
|
||||||
QCOMPARE(qRed(rgb), 128);
|
|
||||||
QCOMPARE(qGreen(rgb), 0);
|
|
||||||
QCOMPARE(qBlue(rgb), 128);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKeePass2Format::testXmlGroupRoot()
|
void TestKeePass2Format::testXmlGroupRoot()
|
||||||
|
@ -998,8 +998,7 @@ void TestMerge::testUpdateGroup()
|
|||||||
groupSourceInitial->setName("group2 renamed");
|
groupSourceInitial->setName("group2 renamed");
|
||||||
groupSourceInitial->setNotes("updated notes");
|
groupSourceInitial->setNotes("updated notes");
|
||||||
QUuid customIconId = QUuid::createUuid();
|
QUuid customIconId = QUuid::createUuid();
|
||||||
QImage customIcon;
|
dbSource->metadata()->addCustomIcon(customIconId, QString("custom icon").toLocal8Bit());
|
||||||
dbSource->metadata()->addCustomIcon(customIconId, customIcon);
|
|
||||||
groupSourceInitial->setIcon(customIconId);
|
groupSourceInitial->setIcon(customIconId);
|
||||||
|
|
||||||
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
QPointer<Entry> entrySourceInitial = dbSource->rootGroup()->findEntryByPath("entry1");
|
||||||
@ -1113,9 +1112,8 @@ void TestMerge::testMergeCustomIcons()
|
|||||||
m_clock->advanceSecond(1);
|
m_clock->advanceSecond(1);
|
||||||
|
|
||||||
QUuid customIconId = QUuid::createUuid();
|
QUuid customIconId = QUuid::createUuid();
|
||||||
QImage customIcon;
|
|
||||||
|
|
||||||
dbSource->metadata()->addCustomIcon(customIconId, customIcon);
|
dbSource->metadata()->addCustomIcon(customIconId, QString("custom icon").toLocal8Bit());
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
QVERIFY(dbSource->metadata()->hasCustomIcon(customIconId));
|
QVERIFY(dbSource->metadata()->hasCustomIcon(customIconId));
|
||||||
|
|
||||||
@ -1138,10 +1136,12 @@ void TestMerge::testMergeDuplicateCustomIcons()
|
|||||||
m_clock->advanceSecond(1);
|
m_clock->advanceSecond(1);
|
||||||
|
|
||||||
QUuid customIconId = QUuid::createUuid();
|
QUuid customIconId = QUuid::createUuid();
|
||||||
QImage customIcon;
|
|
||||||
|
|
||||||
dbSource->metadata()->addCustomIcon(customIconId, customIcon);
|
QByteArray customIcon1 = QString("custom icon 1").toLocal8Bit();
|
||||||
dbDestination->metadata()->addCustomIcon(customIconId, customIcon);
|
QByteArray customIcon2 = QString("custom icon 2").toLocal8Bit();
|
||||||
|
|
||||||
|
dbSource->metadata()->addCustomIcon(customIconId, customIcon1);
|
||||||
|
dbDestination->metadata()->addCustomIcon(customIconId, customIcon2);
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
QVERIFY(dbSource->metadata()->hasCustomIcon(customIconId));
|
QVERIFY(dbSource->metadata()->hasCustomIcon(customIconId));
|
||||||
QVERIFY(dbDestination->metadata()->hasCustomIcon(customIconId));
|
QVERIFY(dbDestination->metadata()->hasCustomIcon(customIconId));
|
||||||
@ -1153,6 +1153,7 @@ void TestMerge::testMergeDuplicateCustomIcons()
|
|||||||
|
|
||||||
QVERIFY(dbDestination->metadata()->hasCustomIcon(customIconId));
|
QVERIFY(dbDestination->metadata()->hasCustomIcon(customIconId));
|
||||||
QCOMPARE(dbDestination->metadata()->customIconsOrder().count(), 1);
|
QCOMPARE(dbDestination->metadata()->customIconsOrder().count(), 1);
|
||||||
|
QCOMPARE(dbDestination->metadata()->customIcon(customIconId), customIcon2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestMerge::testMetadata()
|
void TestMerge::testMetadata()
|
||||||
|
@ -16,12 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "TestGuiPixmaps.h"
|
#include "TestGuiPixmaps.h"
|
||||||
#include "core/DatabaseIcons.h"
|
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
|
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
#include <QTest>
|
#include "gui/DatabaseIcons.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
|
|
||||||
void TestGuiPixmaps::initTestCase()
|
void TestGuiPixmaps::initTestCase()
|
||||||
{
|
{
|
||||||
@ -30,55 +32,53 @@ void TestGuiPixmaps::initTestCase()
|
|||||||
|
|
||||||
void TestGuiPixmaps::testDatabaseIcons()
|
void TestGuiPixmaps::testDatabaseIcons()
|
||||||
{
|
{
|
||||||
// check if the cache works correctly
|
QVERIFY(!databaseIcons()->icon(0).isNull());
|
||||||
auto pixmap = databaseIcons()->icon(0);
|
|
||||||
auto pixmapCached = databaseIcons()->icon(0);
|
|
||||||
QCOMPARE(pixmapCached.cacheKey(), pixmap.cacheKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGuiPixmaps::testEntryIcons()
|
void TestGuiPixmaps::testEntryIcons()
|
||||||
{
|
{
|
||||||
QScopedPointer<Database> db(new Database());
|
QScopedPointer<Database> db(new Database());
|
||||||
Entry* entry = new Entry();
|
auto entry = new Entry();
|
||||||
entry->setGroup(db->rootGroup());
|
entry->setGroup(db->rootGroup());
|
||||||
|
|
||||||
// Test setting standard icon
|
// Test setting standard icon
|
||||||
entry->setIcon(10);
|
entry->setIcon(10);
|
||||||
auto pixmap = entry->iconPixmap();
|
auto pixmap = Icons::entryIconPixmap(entry);
|
||||||
QCOMPARE(pixmap.cacheKey(), databaseIcons()->icon(10).cacheKey());
|
QVERIFY(pixmap.toImage() == databaseIcons()->icon(10).toImage());
|
||||||
|
|
||||||
// Test setting custom icon
|
// Test setting custom icon
|
||||||
QUuid iconUuid = QUuid::createUuid();
|
QUuid iconUuid = QUuid::createUuid();
|
||||||
QImage icon(2, 1, QImage::Format_RGB32);
|
QImage icon(2, 1, QImage::Format_RGB32);
|
||||||
icon.setPixel(0, 0, qRgb(0, 0, 0));
|
icon.setPixel(0, 0, qRgb(0, 0, 0));
|
||||||
icon.setPixel(1, 0, qRgb(0, 0, 50));
|
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);
|
entry->setIcon(iconUuid);
|
||||||
pixmap = entry->iconPixmap();
|
// Confirm the icon is the same as that stored in the database
|
||||||
QCOMPARE(pixmap.cacheKey(), db->metadata()->customIconPixmap(iconUuid).cacheKey());
|
QVERIFY(Icons::entryIconPixmap(entry).toImage() == Icons::customIconPixmap(db.data(), iconUuid).toImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGuiPixmaps::testGroupIcons()
|
void TestGuiPixmaps::testGroupIcons()
|
||||||
{
|
{
|
||||||
QScopedPointer<Database> db(new Database());
|
QScopedPointer<Database> db(new Database());
|
||||||
Group* group = db->rootGroup();
|
auto group = db->rootGroup();
|
||||||
|
|
||||||
// Test setting standard icon
|
// Test setting standard icon
|
||||||
group->setIcon(10);
|
group->setIcon(10);
|
||||||
auto pixmap = group->iconPixmap();
|
auto pixmap = Icons::groupIconPixmap(group);
|
||||||
QCOMPARE(pixmap.cacheKey(), databaseIcons()->icon(10).cacheKey());
|
QVERIFY(pixmap.toImage() == databaseIcons()->icon(10).toImage());
|
||||||
|
|
||||||
// Test setting custom icon
|
// Test setting custom icon
|
||||||
QUuid iconUuid = QUuid::createUuid();
|
QUuid iconUuid = QUuid::createUuid();
|
||||||
QImage icon(2, 1, QImage::Format_RGB32);
|
QImage icon(2, 1, QImage::Format_RGB32);
|
||||||
icon.setPixel(0, 0, qRgb(0, 0, 0));
|
icon.setPixel(0, 0, qRgb(0, 0, 0));
|
||||||
icon.setPixel(1, 0, qRgb(0, 0, 50));
|
icon.setPixel(1, 0, qRgb(0, 0, 50));
|
||||||
db->metadata()->addCustomIcon(iconUuid, icon);
|
db->metadata()->addCustomIcon(iconUuid, Icons::saveToBytes(icon));
|
||||||
|
|
||||||
group->setIcon(iconUuid);
|
group->setIcon(iconUuid);
|
||||||
pixmap = group->iconPixmap();
|
// Confirm the icon is the same as that stored in the database
|
||||||
QCOMPARE(pixmap.cacheKey(), db->metadata()->customIconPixmap(iconUuid).cacheKey());
|
QVERIFY(Icons::groupIconPixmap(group).toImage() == Icons::customIconPixmap(db.data(), iconUuid).toImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestGuiPixmaps)
|
QTEST_MAIN(TestGuiPixmaps)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user