DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
ChoiceListDialog.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "moc_ChoiceListDialog.cpp"
5#include "ui_ChoiceListDialog.h"
6#include "ChoiceListDialog.h"
7
9 std::string_view ParamName, bool IsOptional, std::string_view IconResourcePath, const std::vector<DynExp::ItemIDType>& Values)
10 : QDialog(parent, Qt::Dialog | Qt::WindowTitleHint),
11 ui(std::make_unique<Ui::ChoiceListDialog>()),
12 ItemIDsWithLabels(std::move(ItemIDsWithLabels)), ParamName(ParamName), Optional(IsOptional),
13 ItemIcon(IconResourcePath.data()), Values(Values)
14{
15 ui->setupUi(this);
16
17 setWindowTitle(QString("Select items - ") + ParamName.data());
18
19 connect(ui->LWAvailable, &QListWidget::itemChanged, [this](QListWidgetItem*) { ui->LWAvailable->sortItems(); });
20}
21
22void ChoiceListDialog::showEvent(QShowEvent* event)
23{
24 const auto SelectionFilter = [this](bool SelectionState, const auto& IDLabelPair) {
25 return (std::find_if(Values.cbegin(), Values.cend(), [&IDLabelPair = std::as_const(IDLabelPair)](const auto ID) {
26 return IDLabelPair.second == ID;
27 }) == Values.cend()) != SelectionState;
28 };
29
30 const auto SelectedFilter = [&SelectionFilter](const auto& IDLabelPair) { return SelectionFilter(true, IDLabelPair); };
31 const auto NotSelectedFilter = [&SelectionFilter](const auto& IDLabelPair) { return SelectionFilter(false, IDLabelPair); };
32
33 const auto AddListWidgetItem = [this](const decltype(ItemIDsWithLabels)::value_type& Item, QListWidget* List) {
34 auto ListItem = new QListWidgetItem(QString::fromStdString(Item.first), List);
35 ListItem->setIcon(ItemIcon);
36 ListItem->setToolTip("ID " + QString::number(Item.second));
37 ListItem->setData(Qt::UserRole, QVariant::fromValue(Item.second));
38 };
39
40 ui->LWAvailable->clear();
41 for (const auto& Item : ItemIDsWithLabels | std::views::filter(NotSelectedFilter))
42 AddListWidgetItem(Item, ui->LWAvailable);
43
44 // Do not directly insert, to sort first according to Values vector.
46 for (const auto& Item : ItemIDsWithLabels | std::views::filter(SelectedFilter))
47 SelectedItems.push_back(Item);
48
49 std::sort(SelectedItems.begin(), SelectedItems.end(), [&Values = std::as_const(Values)](const auto& a, const auto& b) {
50 const auto ItA = std::find(Values.cbegin(), Values.cend(), a.second);
51 const auto ItB = std::find(Values.cbegin(), Values.cend(), b.second);
52
53 return ItA == Values.cend() || ItB == Values.cend() || ItA - Values.cbegin() < ItB - Values.cbegin();
54 });
55
56 ui->LWSelected->clear();
57 for (const auto& Item : SelectedItems)
58 AddListWidgetItem(Item, ui->LWSelected);
59
60 event->accept();
61}
62
64{
65 auto SelectedItems = ui->LWAvailable->selectedItems();
66 ui->LWAvailable->clearSelection();
67 ui->LWSelected->clearSelection();
68
69 for (auto Item : SelectedItems)
70 {
71 ui->LWSelected->addItem(ui->LWAvailable->takeItem(ui->LWAvailable->row(Item)));
72 Item->setSelected(true);
73 }
74}
75
77{
78 auto SelectedItems = ui->LWSelected->selectedItems();
79 ui->LWAvailable->clearSelection();
80 ui->LWSelected->clearSelection();
81
82 for (auto Item : SelectedItems)
83 {
84 ui->LWAvailable->addItem(ui->LWSelected->takeItem(ui->LWSelected->row(Item)));
85 Item->setSelected(true);
86 }
87}
88
90{
91 auto SelectedItems = ui->LWSelected->selectedItems();
92 std::sort(SelectedItems.begin(), SelectedItems.end(), [this](const auto& a, const auto& b) {
93 return ui->LWSelected->row(a) < ui->LWSelected->row(b);
94 });
95
96 for (auto Item : SelectedItems)
97 {
98 const auto Row = ui->LWSelected->row(Item);
99 if (Row <= 0)
100 continue;
101
102 ui->LWSelected->insertItem(Row - 1, ui->LWSelected->takeItem(Row));
103 Item->setSelected(true);
104 }
105}
106
108{
109 auto SelectedItems = ui->LWSelected->selectedItems();
110 std::sort(SelectedItems.begin(), SelectedItems.end(), [this](const auto& a, const auto& b) {
111 return ui->LWSelected->row(a) > ui->LWSelected->row(b);
112 });
113
114 for (auto Item : SelectedItems)
115 {
116 const auto Row = ui->LWSelected->row(Item);
117 if (Row >= ui->LWSelected->count() - 1)
118 continue;
119
120 ui->LWSelected->insertItem(Row + 1, ui->LWSelected->takeItem(Row));
121 Item->setSelected(true);
122 }
123}
124
126{
127 if (!IsOptional() && !ui->LWSelected->count())
128 {
129 QMessageBox::warning(this, "DynExp - Parameter empty",
130 QString("The parameter \"") + GetParamName().data() + "\" must not be empty. Please assign at least one item.");
131 return;
132 }
133
134 Values.clear();
135 for (Util::return_of_t<decltype(&QListWidget::count)> i = 0; i < ui->LWSelected->count(); ++i)
136 Values.push_back(ui->LWSelected->item(i)->data(Qt::UserRole).value<decltype(Values)::value_type>());
137
138 QDialog::accept();
139}
140
142{
143 QDialog::reject();
144}
Implements a dialog with a list of available items on the left and a list of selected items on the ri...
std::vector< DynExp::ItemIDType > Values
std::string_view GetParamName() const
virtual void showEvent(QShowEvent *event) override
bool IsOptional() const noexcept
virtual void reject() override
const std::string ParamName
const Util::TextValueListType< IndexType > ItemIDsWithLabels
std::unique_ptr< Ui::ChoiceListDialog > ui
ChoiceListDialog(QWidget *parent, Util::TextValueListType< IndexType > &&ItemIDsWithLabels, std::string_view ParamName, bool IsOptional, std::string_view IconResourcePath, const std::vector< DynExp::ItemIDType > &Values)
virtual void accept() override
typename member_fn_ptr_traits< CallableT >::return_type return_of_t
Alias for the return type of a member function callable of type CallableT.
Definition Util.h:362
std::vector< std::pair< TextType, ValueType > > TextValueListType
Type of a list containing key-value pairs where key is a text of type Util::TextType.
Definition QtUtil.h:37
Accumulates include statements to provide a precompiled header.