Page MenuHome GnuPG

No OneTemporary

diff --git a/src/conf/CMakeLists.txt b/src/conf/CMakeLists.txt
index 618d09fc6..fdde1771a 100644
--- a/src/conf/CMakeLists.txt
+++ b/src/conf/CMakeLists.txt
@@ -1,88 +1,91 @@
include_directories(${kleopatra_SOURCE_DIR}/src)
if(BUILD_libkleopatraclient)
set(_kcm_kleopatra_libkleopatraclient_extra_SRCS
smimevalidationconfigurationwidget.cpp
smimevalidationconfigurationpage.cpp
cryptooperationsconfigwidget.cpp
cryptooperationsconfigpage.cpp
)
ki18n_wrap_ui(_kcm_kleopatra_libkleopatraclient_extra_SRCS
smimevalidationconfigurationwidget.ui
)
kconfig_add_kcfg_files(_kcm_kleopatra_libkleopatraclient_extra_SRCS
${kleopatra_SOURCE_DIR}/src/kcfg/smimevalidationpreferences.kcfgc
)
set(_kcm_kleopatra_libkleopatraclient_extra_LIBS kleopatraclientgui)
set(_kcm_kleopatra_libkleopatraclient_extra_install_FILES
kleopatra_config_smimevalidation.desktop
kleopatra_config_cryptooperations.desktop
)
else()
set(_kcm_kleopatra_libkleopatraclient_extra_SRCS)
set(_kcm_kleopatra_libkleopatraclient_extra_LIBS)
set(_kcm_kleopatra_libkleopatraclient_extra_install_FILES)
endif()
set(kcm_kleopatra_PART_SRCS
dirservconfigpage.cpp
appearanceconfigpage.cpp
appearanceconfigwidget.cpp
gnupgsystemconfigurationpage.cpp
+ groupsconfigpage.cpp
+ groupsconfigwidget.cpp
+ ${kleopatra_SOURCE_DIR}/src/dialogs/editgroupdialog.cpp
${kleopatra_BINARY_DIR}/src/kleopatra_debug.cpp
${_kcm_kleopatra_libkleopatraclient_extra_SRCS}
)
ki18n_wrap_ui(kcm_kleopatra_PART_SRCS
appearanceconfigwidget.ui
smimevalidationconfigurationwidget.ui
)
kconfig_add_kcfg_files(kcm_kleopatra_PART_SRCS
${kleopatra_SOURCE_DIR}/src/kcfg/tooltippreferences.kcfgc
${kleopatra_SOURCE_DIR}/src/kcfg/emailoperationspreferences.kcfgc
${kleopatra_SOURCE_DIR}/src/kcfg/fileoperationspreferences.kcfgc
${kleopatra_SOURCE_DIR}/src/kcfg/tagspreferences.kcfgc
${kleopatra_SOURCE_DIR}/src/kcfg/settings.kcfgc
)
add_library(kcm_kleopatra MODULE ${kcm_kleopatra_PART_SRCS})
if(HAVE_KCMUTILS)
set (_kcm_kleopatra_extra_libs KF5::KCMUtils)
endif()
target_link_libraries(kcm_kleopatra
KF5::Libkleo
KF5::IconThemes
KF5::I18n
KF5::WidgetsAddons
KF5::ConfigWidgets
${_kcm_kleopatra_extra_libs}
${_kleopatra_dbusaddons_libs}
${_kcm_kleopatra_libkleopatraclient_extra_LIBS}
)
if (COMPILE_WITH_UNITY_CMAKE_SUPPORT)
set_target_properties(kcm_kleopatra PROPERTIES UNITY_BUILD ON)
endif()
install(TARGETS kcm_kleopatra DESTINATION ${KDE_INSTALL_PLUGINDIR})
########### install files ###############
install(FILES
kleopatra_config_dirserv.desktop
kleopatra_config_appear.desktop
kleopatra_config_gnupgsystem.desktop
+ kleopatra_config_groups.desktop
${_kcm_kleopatra_libkleopatraclient_extra_install_FILES}
DESTINATION ${KDE_INSTALL_KSERVICES5DIR}
)
-
diff --git a/src/conf/configuredialog.cpp b/src/conf/configuredialog.cpp
index 63b5bd7aa..086d0643f 100644
--- a/src/conf/configuredialog.cpp
+++ b/src/conf/configuredialog.cpp
@@ -1,70 +1,71 @@
/*
configuredialog.cpp
This file is part of kleopatra
SPDX-FileCopyrightText: 2000 Espen Sand <espen@kde.org>
SPDX-FileCopyrightText: 2001-2002 Marc Mutz <mutz@kde.org>
SPDX-FileCopyrightText: 2004, 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-only
*/
#include "configuredialog.h"
#include <KConfig>
#include <KLocalizedString>
#include <KConfigGroup>
#include <KSharedConfig>
#if HAVE_KCMUTILS
# include <KCMultiDialog>
#else
# include "kleopageconfigdialog.h"
#endif
ConfigureDialog::ConfigureDialog(QWidget *parent)
#if HAVE_KCMUTILS
: KCMultiDialog(parent)
#else
: KleoPageConfigDialog(parent)
#endif
{
setFaceType(KPageDialog::List);
setWindowTitle(i18nc("@title:window", "Configure"));
+ addModule(QStringLiteral("kleopatra_config_groups"));
addModule(QStringLiteral("kleopatra_config_dirserv"));
addModule(QStringLiteral("kleopatra_config_appear"));
addModule(QStringLiteral("kleopatra_config_cryptooperations"));
addModule(QStringLiteral("kleopatra_config_smimevalidation"));
addModule(QStringLiteral("kleopatra_config_gnupgsystem"));
// We store the minimum size of the dialog on hide, because otherwise
// the KCMultiDialog starts with the size of the first kcm, not
// the largest one. This way at least after the first showing of
// the largest kcm the size is kept.
const KConfigGroup geometry(KSharedConfig::openConfig(), "Geometry");
const int width = geometry.readEntry("ConfigureDialogWidth", 0);
const int height = geometry.readEntry("ConfigureDialogHeight", 0);
if (width != 0 && height != 0) {
setMinimumSize(width, height);
}
}
void ConfigureDialog::hideEvent(QHideEvent *e)
{
const QSize minSize = minimumSizeHint();
KConfigGroup geometry(KSharedConfig::openConfig(), "Geometry");
geometry.writeEntry("ConfigureDialogWidth", minSize.width());
geometry.writeEntry("ConfigureDialogHeight", minSize.height());
#if HAVE_KCMUTILS
KCMultiDialog::hideEvent(e);
#else
KleoPageConfigDialog::hideEvent(e);
#endif
}
ConfigureDialog::~ConfigureDialog()
{
}
diff --git a/src/conf/groupsconfigpage.cpp b/src/conf/groupsconfigpage.cpp
new file mode 100644
index 000000000..e89179855
--- /dev/null
+++ b/src/conf/groupsconfigpage.cpp
@@ -0,0 +1,89 @@
+/*
+ conf/groupsconfigpage.cpp
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include <config-kleopatra.h>
+
+#include "groupsconfigpage.h"
+
+#include "groupsconfigwidget.h"
+
+#include <Libkleo/Debug>
+#include <Libkleo/KeyCache>
+#include <Libkleo/KeyGroup>
+
+#include <QVBoxLayout>
+
+#include "kleopatra_debug.h"
+
+using namespace Kleo;
+
+class GroupsConfigPage::Private
+{
+ friend class ::GroupsConfigPage;
+ GroupsConfigPage *const q;
+
+ Private(GroupsConfigPage *qq);
+public:
+ ~Private() = default;
+
+private:
+ GroupsConfigWidget *widget = nullptr;
+};
+
+GroupsConfigPage::Private::Private(GroupsConfigPage *qq)
+ : q(qq)
+{
+}
+
+GroupsConfigPage::GroupsConfigPage(QWidget *parent, const QVariantList &args)
+ : KCModule(parent, args)
+ , d(new Private(this))
+{
+ // do not show the Defaults button; it has no effect
+ setButtons(buttons() & ~KCModule::Default);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+
+ d->widget = new Kleo::GroupsConfigWidget(this);
+ if (QLayout *l = d->widget->layout()) {
+ l->setContentsMargins(0, 0, 0, 0);
+ }
+
+ layout->addWidget(d->widget);
+
+ connect(d->widget, &GroupsConfigWidget::changed, this, &GroupsConfigPage::markAsChanged);
+}
+
+GroupsConfigPage::~GroupsConfigPage() = default;
+
+void GroupsConfigPage::load()
+{
+ qCDebug(KLEOPATRA_LOG) << "GroupsConfigPage::load()";
+ d->widget->setGroups(KeyCache::instance()->configurableGroups());
+}
+
+void GroupsConfigPage::save()
+{
+ KeyCache::mutableInstance()->saveConfigurableGroups(d->widget->groups());
+
+ // reload after saving to ensure that the groups reflect the saved groups (e.g. in case of immutable entries)
+ load();
+}
+
+extern "C"
+{
+ Q_DECL_EXPORT KCModule *create_kleopatra_config_groups(QWidget *parent = nullptr, const QVariantList &args = QVariantList())
+ {
+ GroupsConfigPage *page = new GroupsConfigPage(parent, args);
+ page->setObjectName(QStringLiteral("kleopatra_config_groups"));
+ return page;
+ }
+}
diff --git a/src/conf/groupsconfigpage.h b/src/conf/groupsconfigpage.h
new file mode 100644
index 000000000..b4b3432a4
--- /dev/null
+++ b/src/conf/groupsconfigpage.h
@@ -0,0 +1,31 @@
+/*
+ conf/groupsconfigpage.h
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef __KLEOPATRA_CONF_GROUPSCONFIGPAGE_H__
+#define __KLEOPATRA_CONF_GROUPSCONFIGPAGE_H__
+
+#include <KCModule>
+
+class GroupsConfigPage : public KCModule
+{
+ Q_OBJECT
+public:
+ explicit GroupsConfigPage(QWidget *parent = nullptr, const QVariantList &args = QVariantList());
+ ~GroupsConfigPage() override;
+
+ void load() override;
+ void save() override;
+
+private:
+ class Private;
+ const std::unique_ptr<Private> d;
+};
+
+#endif // __KLEOPATRA_CONF_GROUPSCONFIGPAGE_H__
diff --git a/src/conf/groupsconfigwidget.cpp b/src/conf/groupsconfigwidget.cpp
new file mode 100644
index 000000000..eaf98df3b
--- /dev/null
+++ b/src/conf/groupsconfigwidget.cpp
@@ -0,0 +1,278 @@
+/*
+ conf/groupsconfigwidget.cpp
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "groupsconfigwidget.h"
+
+#include "dialogs/editgroupdialog.h"
+
+#include <Libkleo/KeyCache>
+#include <Libkleo/KeyGroup>
+#include <Libkleo/KeyListModel>
+#include <Libkleo/KeyListSortFilterProxyModel>
+
+#include <KLocalizedString>
+#include <KRandom>
+
+#include <QLabel>
+#include <QLineEdit>
+#include <QListView>
+#include <QPointer>
+#include <QPushButton>
+#include <QVBoxLayout>
+
+#include "kleopatra_debug.h"
+
+using namespace Kleo;
+using namespace Kleo::Dialogs;
+
+Q_DECLARE_METATYPE(KeyGroup)
+
+namespace
+{
+
+class ProxyModel : public AbstractKeyListSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ ProxyModel(QObject *parent = nullptr)
+ : AbstractKeyListSortFilterProxyModel(parent)
+ {
+ }
+
+ ~ProxyModel() override = default;
+
+ ProxyModel *clone() const override
+ {
+ // compiler-generated copy ctor is fine!
+ return new ProxyModel(*this);
+ }
+};
+
+}
+
+class GroupsConfigWidget::Private
+{
+ friend class ::Kleo::GroupsConfigWidget;
+ GroupsConfigWidget *const q;
+
+ struct {
+ QLineEdit *groupsFilter = nullptr;
+ QListView *groupsList = nullptr;
+ QPushButton *newButton = nullptr;
+ QPushButton *editButton = nullptr;
+ QPushButton *deleteButton = nullptr;
+ } ui;
+ AbstractKeyListModel *groupsModel = nullptr;
+ ProxyModel *groupsFilterModel = nullptr;
+
+public:
+ Private(GroupsConfigWidget *qq)
+ : q(qq)
+ {
+ auto mainLayout = new QVBoxLayout(q);
+
+ auto groupsLayout = new QGridLayout();
+ groupsLayout->setColumnStretch(0, 1);
+ groupsLayout->setRowStretch(1, 1);
+
+ ui.groupsFilter = new QLineEdit();
+ ui.groupsFilter->setClearButtonEnabled(true);
+ ui.groupsFilter->setPlaceholderText(i18nc("Placeholder text", "Search..."));
+ groupsLayout->addWidget(ui.groupsFilter, 0, 0);
+
+ groupsModel = AbstractKeyListModel::createFlatKeyListModel(q);
+ groupsFilterModel = new ProxyModel(q);
+ groupsFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ groupsFilterModel->setFilterKeyColumn(KeyList::Summary);
+ groupsFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+ groupsFilterModel->setSourceModel(groupsModel);
+ groupsFilterModel->sort(KeyList::Summary, Qt::AscendingOrder);
+ ui.groupsList = new QListView();
+ ui.groupsList->setModel(groupsFilterModel);
+ ui.groupsList->setModelColumn(KeyList::Summary);
+ ui.groupsList->setSelectionBehavior(QAbstractItemView::SelectRows);
+ ui.groupsList->setSelectionMode(QAbstractItemView::SingleSelection);
+
+ groupsLayout->addWidget(ui.groupsList, 1, 0);
+
+ auto groupsButtonLayout = new QVBoxLayout();
+
+ ui.newButton = new QPushButton(i18n("New"));
+ groupsButtonLayout->addWidget(ui.newButton);
+
+ ui.editButton = new QPushButton(i18n("Edit"));
+ ui.editButton->setEnabled(false);
+ groupsButtonLayout->addWidget(ui.editButton);
+
+ ui.deleteButton = new QPushButton(i18n("Delete"));
+ ui.deleteButton->setEnabled(false);
+ groupsButtonLayout->addWidget(ui.deleteButton);
+
+ groupsButtonLayout->addStretch(1);
+
+ groupsLayout->addLayout(groupsButtonLayout, 1, 1);
+
+ mainLayout->addLayout(groupsLayout, /*stretch=*/ 1);
+
+ connect(ui.groupsFilter, &QLineEdit::textChanged, groupsFilterModel, &QSortFilterProxyModel::setFilterFixedString);
+ connect(ui.groupsList->selectionModel(), &QItemSelectionModel::selectionChanged,
+ q, [this] () { selectionChanged(); });
+ connect(ui.groupsList, &QListView::doubleClicked,
+ q, [this] (const QModelIndex &index) { editGroup(index); });
+ connect(ui.newButton, &QPushButton::clicked, q, [this] () { addGroup(); });
+ connect(ui.editButton, &QPushButton::clicked, q, [this] () { editGroup(); });
+ connect(ui.deleteButton, &QPushButton::clicked, q, [this] () { deleteGroup(); });
+ }
+
+ ~Private()
+ {
+ }
+
+private:
+ QModelIndex selectedIndex()
+ {
+ const QModelIndexList selected = ui.groupsList->selectionModel()->selectedRows();
+ return selected.empty() ? QModelIndex() : selected[0];
+ }
+
+ KeyGroup getGroup(const QModelIndex &index)
+ {
+ return index.isValid() ? ui.groupsList->model()->data(index, KeyList::GroupRole).value<KeyGroup>() : KeyGroup();
+ }
+
+ void selectionChanged()
+ {
+ const KeyGroup selectedGroup = getGroup(selectedIndex());
+ const bool selectedGroupIsEditable = !selectedGroup.isNull() && !selectedGroup.isImmutable();
+ ui.editButton->setEnabled(selectedGroupIsEditable);
+ ui.deleteButton->setEnabled(selectedGroupIsEditable);
+ }
+
+ KeyGroup showEditGroupDialog(KeyGroup group, const QString &windowTitle, EditGroupDialog::FocusWidget focusWidget)
+ {
+ auto dialog = std::make_unique<EditGroupDialog>(q);
+ dialog->setWindowTitle(windowTitle);
+ dialog->setGroupName(group.name());
+ const KeyGroup::Keys &keys = group.keys();
+ dialog->setGroupKeys(std::vector<GpgME::Key>(keys.cbegin(), keys.cend()));
+ dialog->setInitialFocus(focusWidget);
+
+ const int result = dialog->exec();
+ if (result == QDialog::Rejected) {
+ return KeyGroup();
+ }
+
+ group.setName(dialog->groupName());
+ group.setKeys(dialog->groupKeys());
+
+ return group;
+ }
+
+ void addGroup()
+ {
+ const KeyGroup::Id newId = KRandom::randomString(8);
+ KeyGroup group = KeyGroup(newId, i18nc("default name for new group of keys", "New Group"), {}, KeyGroup::ApplicationConfig);
+ group.setIsImmutable(false);
+
+ const KeyGroup newGroup = showEditGroupDialog(
+ group, i18nc("@title:window a group of keys", "New Group"), EditGroupDialog::GroupName);
+ if (newGroup.isNull()) {
+ return;
+ }
+
+ const QModelIndex newIndex = groupsModel->addGroup(newGroup);
+ if (!newIndex.isValid()) {
+ qCDebug(KLEOPATRA_LOG) << "Adding group to model failed";
+ return;
+ }
+
+ Q_EMIT q->changed();
+ }
+
+ void editGroup(const QModelIndex &index = QModelIndex())
+ {
+ const QModelIndex groupIndex = index.isValid() ? index : selectedIndex();
+ if (!groupIndex.isValid()) {
+ qCDebug(KLEOPATRA_LOG) << "selection is empty";
+ return;
+ }
+ const KeyGroup group = getGroup(groupIndex);
+ if (group.isNull()) {
+ qCDebug(KLEOPATRA_LOG) << "selected group is null";
+ return;
+ }
+ if (group.isImmutable()) {
+ qCDebug(KLEOPATRA_LOG) << "selected group is immutable";
+ return;
+ }
+
+ const KeyGroup updatedGroup = showEditGroupDialog(
+ group, i18nc("@title:window a group of keys", "Edit Group"), EditGroupDialog::KeysFilter);
+ if (updatedGroup.isNull()) {
+ return;
+ }
+
+ const bool success = ui.groupsList->model()->setData(groupIndex, QVariant::fromValue(updatedGroup));
+ if (!success) {
+ qCDebug(KLEOPATRA_LOG) << "Updating group in model failed";
+ return;
+ }
+
+ Q_EMIT q->changed();
+ }
+
+ void deleteGroup()
+ {
+ const QModelIndex groupIndex = selectedIndex();
+ if (!groupIndex.isValid()) {
+ qCDebug(KLEOPATRA_LOG) << "selection is empty";
+ return;
+ }
+ const KeyGroup group = getGroup(groupIndex);
+ if (group.isNull()) {
+ qCDebug(KLEOPATRA_LOG) << "selected group is null";
+ return;
+ }
+
+ const bool success = groupsModel->removeGroup(group);
+ if (!success) {
+ qCDebug(KLEOPATRA_LOG) << "Removing group from model failed";
+ return;
+ }
+
+ Q_EMIT q->changed();
+ }
+};
+
+GroupsConfigWidget::GroupsConfigWidget(QWidget *parent)
+ : QWidget(parent)
+ , d(new Private(this))
+{
+}
+
+GroupsConfigWidget::~GroupsConfigWidget() = default;
+
+void GroupsConfigWidget::setGroups(const std::vector<KeyGroup> &groups)
+{
+ d->groupsModel->setGroups(groups);
+}
+
+std::vector<KeyGroup> GroupsConfigWidget::groups() const
+{
+ std::vector<KeyGroup> result;
+ result.reserve(d->groupsModel->rowCount());
+ for (int row = 0; row < d->groupsModel->rowCount(); ++row) {
+ const QModelIndex index = d->groupsModel->index(row, 0);
+ result.push_back(d->groupsModel->group(index));
+ }
+ return result;
+}
+
+#include "groupsconfigwidget.moc"
diff --git a/src/conf/groupsconfigwidget.h b/src/conf/groupsconfigwidget.h
new file mode 100644
index 000000000..ceb66a050
--- /dev/null
+++ b/src/conf/groupsconfigwidget.h
@@ -0,0 +1,42 @@
+/*
+ conf/groupsconfigwidget.h
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2021 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef __KLEOPATRA_CONF_GROUPSCONFIGWIDGET_H__
+#define __KLEOPATRA_CONF_GROUPSCONFIGWIDGET_H__
+
+#include <QWidget>
+
+#include <vector>
+
+namespace Kleo
+{
+class KeyGroup;
+
+class GroupsConfigWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit GroupsConfigWidget(QWidget *parent = nullptr);
+ ~GroupsConfigWidget() override;
+
+ void setGroups(const std::vector<KeyGroup> &groups);
+ std::vector<KeyGroup> groups() const;
+
+Q_SIGNALS:
+ void changed();
+
+private:
+ class Private;
+ const std::unique_ptr<Private> d;
+};
+
+}
+
+#endif // __KLEOPATRA_CONF_GROUPSCONFIGWIDGET_H__
diff --git a/src/conf/kleopatra_config_groups.desktop b/src/conf/kleopatra_config_groups.desktop
new file mode 100644
index 000000000..44bf87dc2
--- /dev/null
+++ b/src/conf/kleopatra_config_groups.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Icon=group
+Type=Service
+X-KDE-ServiceTypes=KCModule
+X-DocPath=kleopatra/configuration.html
+
+X-KDE-ModuleType=Library
+X-KDE-Library=kcm_kleopatra
+X-KDE-FactoryName=kleopatra_config_groups
+X-KDE-HasReadOnlyMode=false
+X-KDE-ParentApp=kleopatra
+X-KDE-ParentComponents=kleopatra
+X-KDE-CfgDlgHierarchy=Kleopatra
+
+Name=Groups
+Comment=Configuration of groups of keys
+X-KDE-Keywords=groups,keys,certificates,configuration

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 18, 4:30 PM (13 h, 36 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
7a/fe/8e05c32c60d60ba377219a8c5936

Event Timeline