DynExp
Highly flexible laboratory automation for dynamically changing experiments.
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 "ChoiceListDialog.h"
6 
8  std::string_view ParamName, bool IsOptional, std::string_view IconResourcePath, const std::vector<DynExp::ItemIDType>& Values)
9  : QDialog(parent, Qt::Dialog | Qt::WindowTitleHint),
10  ItemIDsWithLabels(std::move(ItemIDsWithLabels)), ParamName(ParamName), Optional(IsOptional),
11  ItemIcon(IconResourcePath.data()), Values(Values)
12 {
13  ui.setupUi(this);
14 
15  setWindowTitle(QString("Select items - ") + ParamName.data());
16 
17  connect(ui.LWAvailable, &QListWidget::itemChanged, [this](QListWidgetItem*) { ui.LWAvailable->sortItems(); });
18 }
19 
20 void ChoiceListDialog::showEvent(QShowEvent* event)
21 {
22  const auto SelectionFilter = [this](bool SelectionState, const auto& IDLabelPair) {
23  return (std::find_if(Values.cbegin(), Values.cend(), [&IDLabelPair = std::as_const(IDLabelPair)](const auto ID) {
24  return IDLabelPair.second == ID;
25  }) == Values.cend()) != SelectionState;
26  };
27 
28  const auto SelectedFilter = [&SelectionFilter](const auto& IDLabelPair) { return SelectionFilter(true, IDLabelPair); };
29  const auto NotSelectedFilter = [&SelectionFilter](const auto& IDLabelPair) { return SelectionFilter(false, IDLabelPair); };
30 
31  const auto AddListWidgetItem = [this](const decltype(ItemIDsWithLabels)::value_type& Item, QListWidget* List) {
32  auto ListItem = new QListWidgetItem(QString::fromStdString(Item.first), List);
33  ListItem->setIcon(ItemIcon);
34  ListItem->setToolTip("ID " + QString::number(Item.second));
35  ListItem->setData(Qt::UserRole, QVariant::fromValue(Item.second));
36  };
37 
38  ui.LWAvailable->clear();
39  for (const auto& Item : ItemIDsWithLabels | std::views::filter(NotSelectedFilter))
40  AddListWidgetItem(Item, ui.LWAvailable);
41 
42  // Do not directly insert, to sort first according to Values vector.
44  for (const auto& Item : ItemIDsWithLabels | std::views::filter(SelectedFilter))
45  SelectedItems.push_back(Item);
46 
47  std::sort(SelectedItems.begin(), SelectedItems.end(), [&Values = std::as_const(Values)](const auto& a, const auto& b) {
48  const auto ItA = std::find(Values.cbegin(), Values.cend(), a.second);
49  const auto ItB = std::find(Values.cbegin(), Values.cend(), b.second);
50 
51  return ItA == Values.cend() || ItB == Values.cend() || ItA - Values.cbegin() < ItB - Values.cbegin();
52  });
53 
54  ui.LWSelected->clear();
55  for (const auto& Item : SelectedItems)
56  AddListWidgetItem(Item, ui.LWSelected);
57 
58  event->accept();
59 }
60 
62 {
63  auto SelectedItems = ui.LWAvailable->selectedItems();
64  ui.LWAvailable->clearSelection();
65  ui.LWSelected->clearSelection();
66 
67  for (auto Item : SelectedItems)
68  {
69  ui.LWSelected->addItem(ui.LWAvailable->takeItem(ui.LWAvailable->row(Item)));
70  Item->setSelected(true);
71  }
72 }
73 
75 {
76  auto SelectedItems = ui.LWSelected->selectedItems();
77  ui.LWAvailable->clearSelection();
78  ui.LWSelected->clearSelection();
79 
80  for (auto Item : SelectedItems)
81  {
82  ui.LWAvailable->addItem(ui.LWSelected->takeItem(ui.LWSelected->row(Item)));
83  Item->setSelected(true);
84  }
85 }
86 
88 {
89  auto SelectedItems = ui.LWSelected->selectedItems();
90  std::sort(SelectedItems.begin(), SelectedItems.end(), [this](const auto& a, const auto& b) {
91  return ui.LWSelected->row(a) < ui.LWSelected->row(b);
92  });
93 
94  for (auto Item : SelectedItems)
95  {
96  const auto Row = ui.LWSelected->row(Item);
97  if (Row <= 0)
98  continue;
99 
100  ui.LWSelected->insertItem(Row - 1, ui.LWSelected->takeItem(Row));
101  Item->setSelected(true);
102  }
103 }
104 
106 {
107  auto SelectedItems = ui.LWSelected->selectedItems();
108  std::sort(SelectedItems.begin(), SelectedItems.end(), [this](const auto& a, const auto& b) {
109  return ui.LWSelected->row(a) > ui.LWSelected->row(b);
110  });
111 
112  for (auto Item : SelectedItems)
113  {
114  const auto Row = ui.LWSelected->row(Item);
115  if (Row >= ui.LWSelected->count() - 1)
116  continue;
117 
118  ui.LWSelected->insertItem(Row + 1, ui.LWSelected->takeItem(Row));
119  Item->setSelected(true);
120  }
121 }
122 
124 {
125  if (!IsOptional() && !ui.LWSelected->count())
126  {
127  QMessageBox::warning(this, "DynExp - Parameter empty",
128  QString("The parameter \"") + GetParamName().data() + "\" must not be empty. Please assign at least one item.");
129  return;
130  }
131 
132  Values.clear();
133  for (Util::return_of_t<decltype(&QListWidget::count)> i = 0; i < ui.LWSelected->count(); ++i)
134  Values.push_back(ui.LWSelected->item(i)->data(Qt::UserRole).value<decltype(Values)::value_type>());
135 
136  QDialog::accept();
137 }
138 
140 {
141  QDialog::reject();
142 }
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
Ui::ChoiceListDialog ui
const QIcon ItemIcon
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.