diff --git a/src/ui/dnattributeorderconfigwidget.cpp b/src/ui/dnattributeorderconfigwidget.cpp index afd39610b..2f7f0d45e 100644 --- a/src/ui/dnattributeorderconfigwidget.cpp +++ b/src/ui/dnattributeorderconfigwidget.cpp @@ -1,363 +1,369 @@ /* -*- 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 #include "dnattributeorderconfigwidget.h" #include #include #include #include #include #include #include #include #include #include class Kleo::DNAttributeOrderConfigWidget::DNAttributeOrderConfigWidgetPrivate { public: enum { Right = 0, Left = 1, UUp = 2, Up = 3, Down = 4, DDown = 5 }; QTreeWidget *availableLV = nullptr; QTreeWidget *currentLV = nullptr; std::vector navTB; QTreeWidgetItem *placeHolderItem = nullptr; }; static void prepare(QTreeWidget *lv) { lv->setAllColumnsShowFocus(true); lv->header()->setStretchLastSection(true); lv->setHeaderLabels(QStringList() << QString() << i18n("Description")); } Kleo::DNAttributeOrderConfigWidget::DNAttributeOrderConfigWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) , d(new DNAttributeOrderConfigWidgetPrivate) { 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); d->availableLV = new QTreeWidget(this); d->availableLV->setAccessibleName(i18n("available attributes")); prepare(d->availableLV); d->availableLV->sortItems(0, Qt::AscendingOrder); glay->addWidget(d->availableLV, row, 0); d->placeHolderItem = new QTreeWidgetItem(d->availableLV); d->placeHolderItem->setText(0, QStringLiteral("_X_")); d->placeHolderItem->setText(1, i18n("All others")); + d->placeHolderItem->setData(0, Qt::AccessibleTextRole, i18n("All others")); struct NavButtonInfo { const char *icon; const KLazyLocalizedString accessibleName; const KLazyLocalizedString tooltip; void (DNAttributeOrderConfigWidget::*slot)(); bool autorepeat; }; static const std::vector navButtons = { {"go-next", kli18nc("@action:button accessible name for 'Add to list'", "add"), kli18n("Add to current attribute order"), &DNAttributeOrderConfigWidget::slotRightButtonClicked, false}, {"go-previous", kli18nc("@action:button accessible name for 'Remove from list'", "remove"), kli18n("Remove from current attribute order"), &DNAttributeOrderConfigWidget::slotLeftButtonClicked, false}, {"go-top", kli18nc("@action:button accessible name for 'Move to top'", "top"), kli18n("Move to top"), &DNAttributeOrderConfigWidget::slotDoubleUpButtonClicked, false}, {"go-up", kli18nc("@action:button accessible name for 'Move up'", "up"), kli18n("Move one up"), &DNAttributeOrderConfigWidget::slotUpButtonClicked, true}, {"go-down", kli18nc("@action:button accessible name for 'Move down'", "down"), kli18n("Move one down"), &DNAttributeOrderConfigWidget::slotDownButtonClicked, true}, {"go-bottom", kli18nc("@action:button accessible name for 'Move to bottom'", "bottom"), kli18n("Move to bottom"), &DNAttributeOrderConfigWidget::slotDoubleDownButtonClicked, false}, }; const auto createToolButton = [this](const NavButtonInfo &navButton) { auto tb = new QToolButton{this}; tb->setIcon(QIcon::fromTheme(QLatin1String(navButton.icon))); tb->setEnabled(false); tb->setAccessibleName(KLocalizedString{navButton.accessibleName}.toString()); tb->setToolTip(KLocalizedString(navButton.tooltip).toString()); tb->setAutoRepeat(navButton.autorepeat); connect(tb, &QToolButton::clicked, this, navButton.slot); d->navTB.push_back(tb); return tb; }; { auto buttonCol = new QVBoxLayout; buttonCol->addStretch(); buttonCol->addWidget(createToolButton(navButtons[DNAttributeOrderConfigWidgetPrivate::Right])); buttonCol->addWidget(createToolButton(navButtons[DNAttributeOrderConfigWidgetPrivate::Left])); buttonCol->addStretch(); glay->addLayout(buttonCol, row, 1); } d->currentLV = new QTreeWidget(this); d->currentLV->setAccessibleName(i18n("current attribute order")); prepare(d->currentLV); glay->addWidget(d->currentLV, row, 2); { auto buttonCol = new QVBoxLayout; buttonCol->addStretch(); buttonCol->addWidget(createToolButton(navButtons[DNAttributeOrderConfigWidgetPrivate::UUp])); buttonCol->addWidget(createToolButton(navButtons[DNAttributeOrderConfigWidgetPrivate::Up])); buttonCol->addWidget(createToolButton(navButtons[DNAttributeOrderConfigWidgetPrivate::Down])); buttonCol->addWidget(createToolButton(navButtons[DNAttributeOrderConfigWidgetPrivate::DDown])); buttonCol->addStretch(); glay->addLayout(buttonCol, row, 3); } #ifndef NDEBUG Q_ASSERT(d->navTB.size() == navButtons.size()); for (uint i = 0; i < navButtons.size(); ++i) { Q_ASSERT(d->navTB[i]->accessibleName() == KLocalizedString{navButtons[i].accessibleName}.toString()); } #endif connect(d->availableLV, &QTreeWidget::itemSelectionChanged, this, &DNAttributeOrderConfigWidget::slotAvailableSelectionChanged); connect(d->currentLV, &QTreeWidget::itemSelectionChanged, this, &DNAttributeOrderConfigWidget::slotCurrentOrderSelectionChanged); } Kleo::DNAttributeOrderConfigWidget::~DNAttributeOrderConfigWidget() = default; void Kleo::DNAttributeOrderConfigWidget::setAttributeOrder(const QStringList &order) { // save the _X_ item: takePlaceHolderItem(); // clear the rest: d->availableLV->clear(); d->currentLV->clear(); // fill the RHS listview: QTreeWidgetItem *last = nullptr; - for (QStringList::const_iterator it = order.begin(); it != order.end(); ++it) { - const QString attr = (*it).toUpper(); + for (const auto &entry : order) { + const QString attr = entry.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, DN::attributeNameToLabel(attr)); + const auto label = DN::attributeNameToLabel(attr); + last->setText(1, label); + const QString accessibleName = label + QLatin1String(", ") + attr; + last->setData(0, Qt::AccessibleTextRole, accessibleName); } } d->currentLV->setCurrentItem(d->currentLV->topLevelItem(0)); // fill the LHS listview with what's left: 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)) { + for (const auto &attr : all) { + if (!order.contains(attr, Qt::CaseInsensitive)) { auto item = new QTreeWidgetItem(d->availableLV); - item->setText(0, *it); - item->setText(1, DN::attributeNameToLabel(*it)); + item->setText(0, attr); + const auto label = DN::attributeNameToLabel(attr); + item->setText(1, label); + const QString accessibleName = label + QLatin1String(", ") + attr; + item->setData(0, Qt::AccessibleTextRole, accessibleName); } } if (!d->placeHolderItem->treeWidget()) { d->availableLV->addTopLevelItem(d->placeHolderItem); } d->availableLV->setCurrentItem(d->availableLV->topLevelItem(0)); } void Kleo::DNAttributeOrderConfigWidget::takePlaceHolderItem() { if (QTreeWidget *lv = d->placeHolderItem->treeWidget()) { lv->takeTopLevelItem(lv->indexOfTopLevelItem(d->placeHolderItem)); } } QStringList Kleo::DNAttributeOrderConfigWidget::attributeOrder() const { QStringList order; for (QTreeWidgetItemIterator it(d->currentLV); (*it); ++it) { order.push_back((*it)->text(0)); } return order; } void Kleo::DNAttributeOrderConfigWidget::slotAvailableSelectionChanged() { d->navTB[DNAttributeOrderConfigWidgetPrivate::Right]->setEnabled(!d->availableLV->selectedItems().empty()); } void Kleo::DNAttributeOrderConfigWidget::slotCurrentOrderSelectionChanged() { const auto selectedItems = d->currentLV->selectedItems(); auto selectedItem = selectedItems.empty() ? nullptr : selectedItems.front(); enableDisableButtons(selectedItem); } void Kleo::DNAttributeOrderConfigWidget::enableDisableButtons(QTreeWidgetItem *item) { 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)); } void Kleo::DNAttributeOrderConfigWidget::slotUpButtonClicked() { 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->setCurrentItem(item); enableDisableButtons(item); Q_EMIT changed(); } void Kleo::DNAttributeOrderConfigWidget::slotDoubleUpButtonClicked() { 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->setCurrentItem(item); enableDisableButtons(item); Q_EMIT changed(); } void Kleo::DNAttributeOrderConfigWidget::slotDownButtonClicked() { 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->setCurrentItem(item); enableDisableButtons(item); Q_EMIT changed(); } void Kleo::DNAttributeOrderConfigWidget::slotDoubleDownButtonClicked() { 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->setCurrentItem(item); enableDisableButtons(item); Q_EMIT changed(); } void Kleo::DNAttributeOrderConfigWidget::slotLeftButtonClicked() { 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); d->availableLV->setCurrentItem(right); if (next) { d->currentLV->setCurrentItem(next); } enableDisableButtons(next); Q_EMIT changed(); } void Kleo::DNAttributeOrderConfigWidget::slotRightButtonClicked() { 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); } d->currentLV->insertTopLevelItem(newRightIndex, left); d->currentLV->setCurrentItem(left); enableDisableButtons(left); d->navTB[DNAttributeOrderConfigWidgetPrivate::Right]->setEnabled(next); if (next) { d->availableLV->setCurrentItem(next); } Q_EMIT changed(); } void Kleo::DNAttributeOrderConfigWidget::virtual_hook(int, void *) { }