diff --git a/src/kleo/dn.cpp b/src/kleo/dn.cpp index 053f2dc60..dc1ec252e 100644 --- a/src/kleo/dn.cpp +++ b/src/kleo/dn.cpp @@ -1,593 +1,560 @@ /* dn.cpp This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB + SPDX-FileCopyrightText: 2021 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker DN parsing: - SPDX-FileCopyrightText: 2002 g 10 Code GmbH + SPDX-FileCopyrightText: 2002 g10 Code GmbH SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include "dn.h" #include "oidmap.h" -#include "ui/dnattributeorderconfigwidget.h" - -#include -#include - +#include -#include -#include #include -#include - -#include -#include -#include -#include -#include -#include #ifdef _MSC_VER +#include #define strcasecmp _stricmp #endif +namespace { +static const QStringList defaultOrder = { + QStringLiteral("CN"), + QStringLiteral("L"), + QStringLiteral("_X_"), + QStringLiteral("OU"), + QStringLiteral("O"), + QStringLiteral("C"), +}; + +class DNAttributeOrderStore +{ + DNAttributeOrderStore() + : mAttributeOrder{defaultOrder} + { + } + +public: + static DNAttributeOrderStore *instance() + { + static DNAttributeOrderStore *self = new DNAttributeOrderStore(); + return self; + } + + const QStringList &attributeOrder() const + { + return mAttributeOrder.empty() ? defaultOrder : mAttributeOrder; + } + + void setAttributeOrder(const QStringList &order) + { + mAttributeOrder = order; + } + +private: + QStringList mAttributeOrder; +}; +} + class Kleo::DN::Private { public: Private() : mRefCount(0) {} Private(const Private &other) : attributes(other.attributes), reorderedAttributes(other.reorderedAttributes), mRefCount(0) { } int ref() { return ++mRefCount; } int unref() { if (--mRefCount <= 0) { delete this; return 0; } else { return mRefCount; } } int refCount() const { return mRefCount; } DN::Attribute::List attributes; DN::Attribute::List reorderedAttributes; private: int mRefCount; }; namespace { struct DnPair { char *key; char *value; }; } // copied from CryptPlug and adapted to work on DN::Attribute::List: #define digitp(p) (*(p) >= '0' && *(p) <= '9') #define hexdigitp(a) (digitp (a) \ || (*(a) >= 'A' && *(a) <= 'F') \ || (*(a) >= 'a' && *(a) <= 'f')) #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) static char * trim_trailing_spaces(char *string) { char *p; char *mark; for (mark = nullptr, p = string; *p; p++) { if (isspace(*p)) { if (!mark) { mark = p; } } else { mark = nullptr; } } if (mark) { *mark = '\0'; } return string; } /* Parse a DN and return an array-ized one. This is not a validating parser and it does not support any old-stylish syntax; gpgme is expected to return only rfc2253 compatible strings. */ static const unsigned char * parse_dn_part(DnPair *array, const unsigned char *string) { const unsigned char *s; const unsigned char *s1; size_t n; char *p; /* parse attributeType */ for (s = string + 1; *s && *s != '='; s++) { ; } if (!*s) { return nullptr; /* error */ } n = s - string; if (!n) { return nullptr; /* empty key */ } p = (char *)malloc(n + 1); memcpy(p, string, n); p[n] = 0; trim_trailing_spaces((char *)p); // map OIDs to their names: for (unsigned int i = 0; i < numOidMaps; ++i) { if (!strcasecmp((char *)p, oidmap[i].oid)) { free(p); p = strdup(oidmap[i].name); break; } } array->key = p; string = s + 1; if (*string == '#') { /* hexstring */ string++; for (s = string; hexdigitp(s); s++) { s++; } n = s - string; if (!n || (n & 1)) { return nullptr; /* empty or odd number of digits */ } n /= 2; array->value = p = (char *)malloc(n + 1); for (s1 = string; n; s1 += 2, n--) { *p++ = xtoi_2(s1); } *p = 0; } else { /* regular v3 quoted string */ for (n = 0, s = string; *s; s++) { if (*s == '\\') { /* pair */ s++; if (*s == ',' || *s == '=' || *s == '+' || *s == '<' || *s == '>' || *s == '#' || *s == ';' || *s == '\\' || *s == '\"' || *s == ' ') { n++; } else if (hexdigitp(s) && hexdigitp(s + 1)) { s++; n++; } else { return nullptr; /* invalid escape sequence */ } } else if (*s == '\"') { return nullptr; /* invalid encoding */ } else if (*s == ',' || *s == '=' || *s == '+' || *s == '<' || *s == '>' || *s == '#' || *s == ';') { break; } else { n++; } } array->value = p = (char *)malloc(n + 1); for (s = string; n; s++, n--) { if (*s == '\\') { s++; if (hexdigitp(s)) { *p++ = xtoi_2(s); s++; } else { *p++ = *s; } } else { *p++ = *s; } } *p = 0; } return s; } /* Parse a DN and return an array-ized one. This is not a validating parser and it does not support any old-stylish syntax; gpgme is expected to return only rfc2253 compatible strings. */ static Kleo::DN::Attribute::List parse_dn(const unsigned char *string) { if (!string) { return QVector(); } QVector result; while (*string) { while (*string == ' ') { string++; } if (!*string) { break; /* ready */ } DnPair pair = { nullptr, nullptr }; string = parse_dn_part(&pair, string); if (!string) { goto failure; } if (pair.key && pair.value) { result.push_back(Kleo::DN::Attribute(QString::fromUtf8(pair.key), QString::fromUtf8(pair.value))); } free(pair.key); free(pair.value); while (*string == ' ') { string++; } if (*string && *string != ',' && *string != ';' && *string != '+') { goto failure; /* invalid delimiter */ } if (*string) { string++; } } return result; failure: return QVector(); } static QVector parse_dn(const QString &dn) { return parse_dn((const unsigned char *)dn.toUtf8().data()); } static QString dn_escape(const QString &s) { QString result; for (int i = 0, end = s.length(); i != end; ++i) { const QChar ch = s[i]; switch (ch.unicode()) { case ',': case '+': case '"': case '\\': case '<': case '>': case ';': result += QLatin1Char('\\'); // fall through Q_FALLTHROUGH(); default: result += ch; } } return result; } static QString serialise(const QVector &dn, const QString &sep) { QStringList result; for (QVector::const_iterator it = dn.begin(); it != dn.end(); ++it) { if (!(*it).name().isEmpty() && !(*it).value().isEmpty()) { result.push_back((*it).name().trimmed() + QLatin1Char('=') + dn_escape((*it).value().trimmed())); } } return result.join(sep); } static Kleo::DN::Attribute::List reorder_dn(const Kleo::DN::Attribute::List &dn) { - const QStringList &attrOrder = Kleo::DNAttributeMapper::instance()->attributeOrder(); + const QStringList &attrOrder = Kleo::DN::attributeOrder(); Kleo::DN::Attribute::List unknownEntries; Kleo::DN::Attribute::List result; unknownEntries.reserve(dn.size()); result.reserve(dn.size()); // find all unknown entries in their order of appearance for (Kleo::DN::const_iterator it = dn.begin(); it != dn.end(); ++it) { if (!attrOrder.contains((*it).name())) { unknownEntries.push_back(*it); } } // process the known attrs in the desired order for (QStringList::const_iterator oit = attrOrder.begin(); oit != attrOrder.end(); ++oit) { if (*oit == QLatin1String("_X_")) { // insert the unknown attrs std::copy(unknownEntries.begin(), unknownEntries.end(), std::back_inserter(result)); unknownEntries.clear(); // don't produce dup's } else { for (Kleo::DN::const_iterator dnit = dn.begin(); dnit != dn.end(); ++dnit) { if ((*dnit).name() == *oit) { result.push_back(*dnit); } } } } return result; } // // // class DN // // Kleo::DN::DN() { d = new Private(); d->ref(); } Kleo::DN::DN(const QString &dn) { d = new Private(); d->ref(); d->attributes = parse_dn(dn); } Kleo::DN::DN(const char *utf8DN) { d = new Private(); d->ref(); if (utf8DN) { d->attributes = parse_dn((const unsigned char *)utf8DN); } } Kleo::DN::DN(const DN &other) : d(other.d) { if (d) { d->ref(); } } Kleo::DN::~DN() { if (d) { d->unref(); } } const Kleo::DN &Kleo::DN::operator=(const DN &that) { if (this->d == that.d) { return *this; } if (that.d) { that.d->ref(); } if (this->d) { this->d->unref(); } this->d = that.d; return *this; } +// static +QStringList Kleo::DN::attributeOrder() +{ + return DNAttributeOrderStore::instance()->attributeOrder(); +} + +// static +void Kleo::DN::setAttributeOrder(const QStringList &order) +{ + DNAttributeOrderStore::instance()->setAttributeOrder(order); +} + +// static +QStringList Kleo::DN::defaultAttributeOrder() +{ + return defaultOrder; +} + QString Kleo::DN::prettyDN() const { if (!d) { return QString(); } if (d->reorderedAttributes.empty()) { d->reorderedAttributes = reorder_dn(d->attributes); } return serialise(d->reorderedAttributes, QStringLiteral(",")); } QString Kleo::DN::dn() const { return d ? serialise(d->attributes, QStringLiteral(",")) : QString(); } QString Kleo::DN::dn(const QString &sep) const { return d ? serialise(d->attributes, sep) : QString(); } // static QString Kleo::DN::escape(const QString &value) { return dn_escape(value); } void Kleo::DN::detach() { if (!d) { d = new Kleo::DN::Private(); d->ref(); } else if (d->refCount() > 1) { Kleo::DN::Private *d_save = d; d = new Kleo::DN::Private(*d); d->ref(); d_save->unref(); } } void Kleo::DN::append(const Attribute &attr) { detach(); d->attributes.push_back(attr); d->reorderedAttributes.clear(); } QString Kleo::DN::operator[](const QString &attr) const { if (!d) { return QString(); } const QString attrUpper = attr.toUpper(); for (QVector::const_iterator it = d->attributes.constBegin(); it != d->attributes.constEnd(); ++it) { if ((*it).name() == attrUpper) { return (*it).value(); } } return QString(); } static QVector empty; Kleo::DN::const_iterator Kleo::DN::begin() const { return d ? d->attributes.constBegin() : empty.constBegin(); } Kleo::DN::const_iterator Kleo::DN::end() const { return d ? d->attributes.constEnd() : empty.constEnd(); } ///////////////////// namespace { -struct ltstr { - bool operator()(const char *s1, const char *s2) const - { - return qstrcmp(s1, s2) < 0; - } -}; -} - -static const QStringList defaultOrder = { - QStringLiteral("CN"), - QStringLiteral("L"), - QStringLiteral("_X_"), - QStringLiteral("OU"), - QStringLiteral("O"), - QStringLiteral("C"), +static const QMap attributeNamesAndLabels = { + { QStringLiteral("CN"), kli18n("Common name") }, + { QStringLiteral("SN"), kli18n("Surname") }, + { QStringLiteral("GN"), kli18n("Given name") }, + { QStringLiteral("L"), kli18n("Location") }, + { QStringLiteral("T"), kli18n("Title") }, + { QStringLiteral("OU"), kli18n("Organizational unit") }, + { QStringLiteral("O"), kli18n("Organization") }, + { QStringLiteral("PC"), kli18n("Postal code") }, + { QStringLiteral("C"), kli18n("Country code") }, + { QStringLiteral("SP"), kli18n("State or province") }, + { QStringLiteral("DC"), kli18n("Domain component") }, + { QStringLiteral("BC"), kli18n("Business category") }, + { QStringLiteral("EMAIL"), kli18n("Email address") }, + { QStringLiteral("MAIL"), kli18n("Mail address") }, + { QStringLiteral("MOBILE"), kli18n("Mobile phone number") }, + { QStringLiteral("TEL"), kli18n("Telephone number") }, + { QStringLiteral("FAX"), kli18n("Fax number") }, + { QStringLiteral("STREET"), kli18n("Street address") }, + { QStringLiteral("UID"), kli18n("Unique ID") } }; - -static std::pair const attributeLabels[] = { -#define MAKE_PAIR(x,y) std::pair( x, y ) - MAKE_PAIR("CN", kli18n("Common name")), - MAKE_PAIR("SN", kli18n("Surname")), - MAKE_PAIR("GN", kli18n("Given name")), - MAKE_PAIR("L", kli18n("Location")), - MAKE_PAIR("T", kli18n("Title")), - MAKE_PAIR("OU", kli18n("Organizational unit")), - MAKE_PAIR("O", kli18n("Organization")), - MAKE_PAIR("PC", kli18n("Postal code")), - MAKE_PAIR("C", kli18n("Country code")), - MAKE_PAIR("SP", kli18n("State or province")), - MAKE_PAIR("DC", kli18n("Domain component")), - MAKE_PAIR("BC", kli18n("Business category")), - MAKE_PAIR("EMAIL", kli18n("Email address")), - MAKE_PAIR("MAIL", kli18n("Mail address")), - MAKE_PAIR("MOBILE", kli18n("Mobile phone number")), - MAKE_PAIR("TEL", kli18n("Telephone number")), - MAKE_PAIR("FAX", kli18n("Fax number")), - MAKE_PAIR("STREET", kli18n("Street address")), - MAKE_PAIR("UID", kli18n("Unique ID")) -#undef MAKE_PAIR -}; -static const unsigned int numAttributeLabels = sizeof attributeLabels / sizeof * attributeLabels; - -class Kleo::DNAttributeMapper::Private -{ -public: - Private(); - std::map map; - QStringList attributeOrder; -}; - -Kleo::DNAttributeMapper::Private::Private() - : map(attributeLabels, attributeLabels + numAttributeLabels) {} - -Kleo::DNAttributeMapper::DNAttributeMapper() -{ - d = new Private(); - const KConfigGroup config(KSharedConfig::openConfig(), "DN"); - d->attributeOrder = config.readEntry("AttributeOrder", defaultOrder); - mSelf = this; -} - -Kleo::DNAttributeMapper::~DNAttributeMapper() -{ - mSelf = nullptr; - delete d; d = nullptr; -} - -Kleo::DNAttributeMapper *Kleo::DNAttributeMapper::mSelf = nullptr; - -const Kleo::DNAttributeMapper *Kleo::DNAttributeMapper::instance() -{ - if (!mSelf) { - (void)new DNAttributeMapper(); - } - return mSelf; } -QString Kleo::DNAttributeMapper::name2label(const QString &s) const -{ - const std::map::const_iterator it - = d->map.find(s.trimmed().toUpper().toLatin1().constData()); - if (it == d->map.end()) { - return QString(); - } - return KLocalizedString(it->second).toString(); -} - -QStringList Kleo::DNAttributeMapper::names() const -{ - QStringList result; - for (std::map::const_iterator it = d->map.begin(); it != d->map.end(); ++it) { - result.push_back(QLatin1String(it->first)); - } - return result; -} - -const QStringList &Kleo::DNAttributeMapper::attributeOrder() const -{ - return d->attributeOrder; -} - -void Kleo::DNAttributeMapper::setAttributeOrder(const QStringList &order) +// static +QStringList Kleo::DN::attributeNames() { - d->attributeOrder = order.empty() ? defaultOrder : order; - - KConfigGroup config(KSharedConfig::openConfig(), "DN"); - config.writeEntry("AttributeOrder", order); + return attributeNamesAndLabels.keys(); } -Kleo::DNAttributeOrderConfigWidget *Kleo::DNAttributeMapper::configWidget(QWidget *parent) const +// static +QString Kleo::DN::attributeNameToLabel(const QString &name) { - return new DNAttributeOrderConfigWidget(mSelf, parent); + return attributeNamesAndLabels.value(name.trimmed().toUpper()).toString(); } diff --git a/src/kleo/dn.h b/src/kleo/dn.h index 3f1f52bad..740d2debd 100644 --- a/src/kleo/dn.h +++ b/src/kleo/dn.h @@ -1,138 +1,118 @@ /* dn.h This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB + SPDX-FileCopyrightText: 2021 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "kleo_export.h" #include +#include #include -#include class QWidget; -namespace Kleo -{ -class DNAttributeOrderConfigWidget; -} - namespace Kleo { -/** - @short DN Attribute mapper -*/ -class KLEO_EXPORT DNAttributeMapper -{ - DNAttributeMapper(); - ~DNAttributeMapper(); -public: - static const DNAttributeMapper *instance(); - - QString name2label(const QString &s) const; - QStringList names() const; - - const QStringList &attributeOrder() const; - - void setAttributeOrder(const QStringList &order); - - DNAttributeOrderConfigWidget *configWidget(QWidget *parent = nullptr) const; - -private: - class Private; - Private *d; - static DNAttributeMapper *mSelf; -}; - /** @short DN parser and reorderer */ class KLEO_EXPORT DN { public: class Attribute; using AttributeList = QVector; using const_iterator = AttributeList::const_iterator; DN(); explicit DN(const QString &dn); explicit DN(const char *utf8DN); DN(const DN &other); ~DN(); const DN &operator=(const DN &other); + static QStringList attributeOrder(); + static void setAttributeOrder(const QStringList &order); + + static QStringList defaultAttributeOrder(); + + static QStringList attributeNames(); + static QString attributeNameToLabel(const QString &name); + /** @return the value in rfc-2253-escaped form */ static QString escape(const QString &value); /** @return the DN in a reordered form, according to the settings in the [DN] group of the application's config file */ QString prettyDN() const; /** @return the DN in the original form */ QString dn() const; /** \overload Uses \a sep as separator (default: ,) */ QString dn(const QString &sep) const; QString operator[](const QString &attr) const; void append(const Attribute &attr); const_iterator begin() const; const_iterator end() const; private: void detach(); private: class Private; Private *d; }; class KLEO_EXPORT DN::Attribute { public: using List = DN::AttributeList; explicit Attribute(const QString &name = QString(), const QString &value = QString()) : mName(name.toUpper()), mValue(value) {} Attribute(const Attribute &other) : mName(other.name()), mValue(other.value()) {} const Attribute &operator=(const Attribute &other) { if (this != &other) { mName = other.name(); mValue = other.value(); } return *this; } const QString &name() const { return mName; } const QString &value() const { return mValue; } void setValue(const QString &value) { mValue = value; } private: QString mName; QString mValue; }; } diff --git a/src/ui/dnattributeorderconfigwidget.cpp b/src/ui/dnattributeorderconfigwidget.cpp index d4804e684..24e4e3bbc 100644 --- a/src/ui/dnattributeorderconfigwidget.cpp +++ b/src/ui/dnattributeorderconfigwidget.cpp @@ -1,351 +1,339 @@ /* -*- c++ -*- dnattributeorderconfigwidget.cpp This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include "dnattributeorderconfigwidget.h" + #include "libkleo_debug.h" #include "libkleo/dn.h" #include #include #include #include #include #include #include #include class Kleo::DNAttributeOrderConfigWidget::DNAttributeOrderConfigWidgetPrivate { public: enum { UUp = 0, Up = 1, Left = 2, Right = 3, Down = 4, DDown = 5 }; #ifndef QT_NO_TREEWIDGET QTreeWidget *availableLV = nullptr; QTreeWidget *currentLV = nullptr; #endif QToolButton *navTB[6]; #ifndef QT_NO_TREEWIDGET QTreeWidgetItem *placeHolderItem = nullptr; #endif - - Kleo::DNAttributeMapper *mapper = nullptr; }; #ifndef QT_NO_TREEWIDGET static void prepare(QTreeWidget *lv) { lv->setAllColumnsShowFocus(true); lv->header()->setStretchLastSection(true); lv->setHeaderLabels(QStringList() << QString() << i18n("Description")); } #endif -Kleo::DNAttributeOrderConfigWidget::DNAttributeOrderConfigWidget(DNAttributeMapper *mapper, QWidget *parent, Qt::WindowFlags f) +Kleo::DNAttributeOrderConfigWidget::DNAttributeOrderConfigWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f), d(new DNAttributeOrderConfigWidgetPrivate) { - Q_ASSERT(mapper); - d->mapper = mapper; - auto glay = new QGridLayout(this); glay->setContentsMargins(0, 0, 0, 0); glay->setColumnStretch(0, 1); glay->setColumnStretch(2, 1); int row = -1; ++row; glay->addWidget(new QLabel(i18n("Available attributes:"), this), row, 0); glay->addWidget(new QLabel(i18n("Current attribute order:"), this), row, 2); ++row; glay->setRowStretch(row, 1); #ifndef QT_NO_TREEWIDGET d->availableLV = new QTreeWidget(this); prepare(d->availableLV); d->availableLV->sortItems(0, Qt::AscendingOrder); glay->addWidget(d->availableLV, row, 0); d->currentLV = new QTreeWidget(this); prepare(d->currentLV); glay->addWidget(d->currentLV, row, 2); connect(d->availableLV, &QTreeWidget::itemClicked, this, &DNAttributeOrderConfigWidget::slotAvailableSelectionChanged); connect(d->currentLV, &QTreeWidget::itemClicked, this, &DNAttributeOrderConfigWidget::slotCurrentOrderSelectionChanged); d->placeHolderItem = new QTreeWidgetItem(d->availableLV); d->placeHolderItem->setText(0, QStringLiteral("_X_")); d->placeHolderItem->setText(1, i18n("All others")); #endif // the up/down/left/right arrow cross: auto xlay = new QGridLayout(); xlay->setSpacing(0); xlay->setObjectName(QStringLiteral("xlay")); xlay->setAlignment(Qt::AlignCenter); static const struct { const char *icon; int row, col; const KLazyLocalizedString tooltip; void(DNAttributeOrderConfigWidget::*slot)(); bool autorepeat; } navButtons[] = { { "go-top", 0, 1, kli18n("Move to top"), &DNAttributeOrderConfigWidget::slotDoubleUpButtonClicked, false }, { "go-up", 1, 1, kli18n("Move one up"), &DNAttributeOrderConfigWidget::slotUpButtonClicked, true }, { "go-previous", 2, 0, kli18n("Remove from current attribute order"), &DNAttributeOrderConfigWidget::slotLeftButtonClicked, false }, { "go-next", 2, 2, kli18n("Add to current attribute order"), &DNAttributeOrderConfigWidget::slotRightButtonClicked, false }, { "go-down", 3, 1, kli18n("Move one down"), &DNAttributeOrderConfigWidget::slotDownButtonClicked, true }, { "go-bottom", 4, 1, kli18n("Move to bottom"), &DNAttributeOrderConfigWidget::slotDoubleDownButtonClicked, false } }; for (unsigned int i = 0; i < sizeof navButtons / sizeof * navButtons; ++i) { QToolButton *tb = d->navTB[i] = new QToolButton(this); tb->setIcon(QIcon::fromTheme(QLatin1String(navButtons[i].icon))); tb->setEnabled(false); tb->setToolTip(KLocalizedString(navButtons[i].tooltip).toString()); xlay->addWidget(tb, navButtons[i].row, navButtons[i].col); tb->setAutoRepeat(navButtons[i].autorepeat); connect(tb, &QToolButton::clicked, this, navButtons[i].slot); } glay->addLayout(xlay, row, 1); } Kleo::DNAttributeOrderConfigWidget::~DNAttributeOrderConfigWidget() = default; -void Kleo::DNAttributeOrderConfigWidget::load() +void Kleo::DNAttributeOrderConfigWidget::setAttributeOrder(const QStringList &order) { #ifndef QT_NO_TREEWIDGET // save the _X_ item: takePlaceHolderItem(); // clear the rest: d->availableLV->clear(); d->currentLV->clear(); - const QStringList order = d->mapper->attributeOrder(); - // fill the RHS listview: QTreeWidgetItem *last = nullptr; for (QStringList::const_iterator it = order.begin(); it != order.end(); ++it) { const QString attr = (*it).toUpper(); if (attr == QLatin1String("_X_")) { takePlaceHolderItem(); d->currentLV->insertTopLevelItem(d->currentLV->topLevelItemCount(), d->placeHolderItem); last = d->placeHolderItem; } else { last = new QTreeWidgetItem(d->currentLV, last); last->setText(0, attr); - last->setText(1, d->mapper->name2label(attr)); + last->setText(1, DN::attributeNameToLabel(attr)); } } // fill the LHS listview with what's left: - const QStringList all = Kleo::DNAttributeMapper::instance()->names(); + const QStringList all = DN::attributeNames(); const QStringList::const_iterator end(all.end()); for (QStringList::const_iterator it = all.begin(); it != end; ++it) { if (!order.contains(*it)) { auto item = new QTreeWidgetItem(d->availableLV); item->setText(0, *it); - item->setText(1, d->mapper->name2label(*it)); + item->setText(1, DN::attributeNameToLabel(*it)); } } if (!d->placeHolderItem->treeWidget()) { d->availableLV->addTopLevelItem(d->placeHolderItem); } #endif } void Kleo::DNAttributeOrderConfigWidget::takePlaceHolderItem() { #ifndef QT_NO_TREEWIDGET if (QTreeWidget *lv = d->placeHolderItem->treeWidget()) { lv->takeTopLevelItem(lv->indexOfTopLevelItem(d->placeHolderItem)); } #endif } -void Kleo::DNAttributeOrderConfigWidget::save() const +QStringList Kleo::DNAttributeOrderConfigWidget::attributeOrder() const { -#ifndef QT_NO_TREEWIDGET QStringList order; +#ifndef QT_NO_TREEWIDGET for (QTreeWidgetItemIterator it(d->currentLV); (*it); ++it) { order.push_back((*it)->text(0)); } - - d->mapper->setAttributeOrder(order); #endif -} - -void Kleo::DNAttributeOrderConfigWidget::defaults() -{ - qCDebug (LIBKLEO_LOG) << "Sorry, not implemented: Kleo::DNAttributeOrderConfigWidget::defaults()"; + return order; } void Kleo::DNAttributeOrderConfigWidget::slotAvailableSelectionChanged(QTreeWidgetItem *item) { d->navTB[DNAttributeOrderConfigWidgetPrivate::Right]->setEnabled(item); } void Kleo::DNAttributeOrderConfigWidget::slotCurrentOrderSelectionChanged(QTreeWidgetItem *item) { enableDisableButtons(item); } void Kleo::DNAttributeOrderConfigWidget::enableDisableButtons(QTreeWidgetItem *item) { #ifndef QT_NO_TREEWIDGET d->navTB[DNAttributeOrderConfigWidgetPrivate::UUp ]->setEnabled(item && d->currentLV->itemAbove(item)); d->navTB[DNAttributeOrderConfigWidgetPrivate::Up ]->setEnabled(item && d->currentLV->itemAbove(item)); d->navTB[DNAttributeOrderConfigWidgetPrivate::Left ]->setEnabled(item); d->navTB[DNAttributeOrderConfigWidgetPrivate::Down ]->setEnabled(item && d->currentLV->itemBelow(item)); d->navTB[DNAttributeOrderConfigWidgetPrivate::DDown]->setEnabled(item && d->currentLV->itemBelow(item)); #endif } void Kleo::DNAttributeOrderConfigWidget::slotUpButtonClicked() { #ifndef QT_NO_TREEWIDGET if (d->currentLV->selectedItems().isEmpty()) { return; } QTreeWidgetItem *item = d->currentLV->selectedItems().first(); int itemIndex = d->currentLV->indexOfTopLevelItem(item); if (itemIndex <= 0) { return; } d->currentLV->takeTopLevelItem(itemIndex); d->currentLV->insertTopLevelItem(itemIndex - 1, item); d->currentLV->clearSelection(); item->setSelected(true); enableDisableButtons(item); Q_EMIT changed(); #endif } void Kleo::DNAttributeOrderConfigWidget::slotDoubleUpButtonClicked() { #ifndef QT_NO_TREEWIDGET if (d->currentLV->selectedItems().isEmpty()) { return; } QTreeWidgetItem *item = d->currentLV->selectedItems().first(); int itemIndex = d->currentLV->indexOfTopLevelItem(item); if (itemIndex == 0) { return; } d->currentLV->takeTopLevelItem(itemIndex); d->currentLV->insertTopLevelItem(0, item); d->currentLV->clearSelection(); item->setSelected(true); enableDisableButtons(item); Q_EMIT changed(); #endif } void Kleo::DNAttributeOrderConfigWidget::slotDownButtonClicked() { #ifndef QT_NO_TREEWIDGET if (d->currentLV->selectedItems().isEmpty()) { return; } QTreeWidgetItem *item = d->currentLV->selectedItems().first(); int itemIndex = d->currentLV->indexOfTopLevelItem(item); if (itemIndex + 1 >= d->currentLV->topLevelItemCount()) { return; } d->currentLV->takeTopLevelItem(itemIndex); d->currentLV->insertTopLevelItem(itemIndex + 1, item); d->currentLV->clearSelection(); item->setSelected(true); enableDisableButtons(item); Q_EMIT changed(); #endif } void Kleo::DNAttributeOrderConfigWidget::slotDoubleDownButtonClicked() { #ifndef QT_NO_TREEWIDGET if (d->currentLV->selectedItems().isEmpty()) { return; } QTreeWidgetItem *item = d->currentLV->selectedItems().first(); const int itemIndex = d->currentLV->indexOfTopLevelItem(item); if (itemIndex + 1 >= d->currentLV->topLevelItemCount()) { return; } d->currentLV->takeTopLevelItem(itemIndex); d->currentLV->addTopLevelItem(item); d->currentLV->clearSelection(); item->setSelected(true); enableDisableButtons(item); Q_EMIT changed(); #endif } void Kleo::DNAttributeOrderConfigWidget::slotLeftButtonClicked() { #ifndef QT_NO_TREEWIDGET if (d->currentLV->selectedItems().isEmpty()) { return; } QTreeWidgetItem *right = d->currentLV->selectedItems().first(); QTreeWidgetItem *next = d->currentLV->itemBelow(right); if (!next) { next = d->currentLV->itemAbove(right); } d->currentLV->takeTopLevelItem(d->currentLV->indexOfTopLevelItem(right)); d->availableLV->addTopLevelItem(right); d->availableLV->sortItems(0, Qt::AscendingOrder); if (next) { next->setSelected(true); } enableDisableButtons(next); Q_EMIT changed(); #endif } void Kleo::DNAttributeOrderConfigWidget::slotRightButtonClicked() { #ifndef QT_NO_TREEWIDGET if (d->availableLV->selectedItems().isEmpty()) { return; } QTreeWidgetItem *left = d->availableLV->selectedItems().first(); QTreeWidgetItem *next = d->availableLV->itemBelow(left); if (!next) { next = d->availableLV->itemAbove(left); } d->availableLV->takeTopLevelItem(d->availableLV->indexOfTopLevelItem(left)); int newRightIndex = d->currentLV->topLevelItemCount(); if (!d->currentLV->selectedItems().isEmpty()) { QTreeWidgetItem *right = d->currentLV->selectedItems().first(); newRightIndex = d->currentLV->indexOfTopLevelItem(right); right->setSelected(false); } d->currentLV->insertTopLevelItem(newRightIndex, left); left->setSelected(true); enableDisableButtons(left); d->navTB[DNAttributeOrderConfigWidgetPrivate::Right]->setEnabled(next); if (next) { next->setSelected(true); } Q_EMIT changed(); #endif } void Kleo::DNAttributeOrderConfigWidget::virtual_hook(int, void *) {} diff --git a/src/ui/dnattributeorderconfigwidget.h b/src/ui/dnattributeorderconfigwidget.h index 56afb507a..89c3d64e0 100644 --- a/src/ui/dnattributeorderconfigwidget.h +++ b/src/ui/dnattributeorderconfigwidget.h @@ -1,67 +1,59 @@ /* -*- c++ -*- dnattributeorderconfigwidget.h This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "kleo_export.h" #include -namespace Kleo -{ -class DNAttributeMapper; -} - class QTreeWidgetItem; namespace Kleo { class KLEO_EXPORT DNAttributeOrderConfigWidget : public QWidget { Q_OBJECT public: - /*! Use Kleo::DNAttributeMapper::instance()->configWidget( parent, name ) instead. */ - explicit DNAttributeOrderConfigWidget(DNAttributeMapper *mapper, QWidget *parent = nullptr, Qt::WindowFlags f = {}); + explicit DNAttributeOrderConfigWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {}); ~DNAttributeOrderConfigWidget() override; - void load(); - void save() const; - void defaults(); + QStringList attributeOrder() const; + void setAttributeOrder(const QStringList &order); Q_SIGNALS: void changed(); // // only boring stuff below... // private Q_SLOTS: void slotAvailableSelectionChanged(QTreeWidgetItem *); void slotCurrentOrderSelectionChanged(QTreeWidgetItem *); void slotDoubleUpButtonClicked(); void slotUpButtonClicked(); void slotDownButtonClicked(); void slotDoubleDownButtonClicked(); void slotLeftButtonClicked(); void slotRightButtonClicked(); private: void takePlaceHolderItem(); void enableDisableButtons(QTreeWidgetItem *); private: class DNAttributeOrderConfigWidgetPrivate; std::unique_ptr const d; protected: virtual void virtual_hook(int, void *); }; } -