2626
2727#include < Qt>
2828#include < QtGlobal>
29+ #include < QAbstractButton>
2930#include < QChar>
3031#include < QCheckBox>
3132#include < QComboBox>
3637#include < QLatin1String>
3738#include < QLineEdit>
3839#include < QMessageBox>
40+ #include < QPlainTextEdit>
3941#include < QPushButton>
4042#include < QVBoxLayout>
4143#include < QWidget>
@@ -54,10 +56,10 @@ struct CompOpStruct {
5456};
5557
5658static const CompOpStruct compare_operations[4 ] = {
57- { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " equal to " ), [](const QString& key, const QString& pattern) { return key == pattern; } },
58- { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " not equal to " ), [](const QString& key, const QString& pattern) { return key != pattern; } },
59- { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " containing " ), [](const QString& key, const QString& pattern) { return key.contains (pattern); } },
60- { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " not containing " ), [](const QString& key, const QString& pattern) { return !key.contains (pattern); } }
59+ { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " is " ), [](const QString& key, const QString& pattern) { return key == pattern; } },
60+ { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " is not " ), [](const QString& key, const QString& pattern) { return key != pattern; } },
61+ { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " contains " ), [](const QString& key, const QString& pattern) { return key.contains (pattern); } },
62+ { QCoreApplication::translate (" OpenOrienteering::TagRemoveDialog" , " contains not " ), [](const QString& key, const QString& pattern) { return !key.contains (pattern); } }
6163};
6264
6365} // namespace
@@ -71,36 +73,46 @@ TagRemoveDialog::TagRemoveDialog(QWidget* parent, Map* map)
7173{
7274 setWindowTitle (tr (" Remove Tags" ));
7375
74- auto * h_layout = new QHBoxLayout ();
75- h_layout->addWidget (new QLabel (tr (" Remove all tags" )));
76-
76+ auto * search_operation_layout = new QHBoxLayout ();
77+ search_operation_layout->addWidget (new QLabel (tr (" Key" )));
7778 compare_op = new QComboBox ();
7879 for (auto & compare_operation : compare_operations)
7980 {
8081 compare_op->addItem (compare_operation.op );
8182 }
82- h_layout->addWidget (compare_op);
83-
83+ search_operation_layout->addWidget (compare_op);
8484 pattern_edit = new QLineEdit ();
85+ search_operation_layout->addWidget (pattern_edit);
8586
8687 undo_check = new QCheckBox (tr (" Add undo step" ));
87-
88- auto * button_box = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
89- ok_button = button_box->button (QDialogButtonBox::Ok);
90- ok_button->setEnabled (false );
88+ number_matching_objects = new QLabel ();
89+ number_matching_keys = new QLabel ();
90+ matching_keys_details = new QPlainTextEdit ();
91+ matching_keys_details->setReadOnly (true );
92+
93+ auto * button_box = new QDialogButtonBox ();
94+ find_button = new QPushButton (tr (" Find" ));
95+ find_button->setEnabled (false );
96+ button_box->addButton (find_button, QDialogButtonBox::ActionRole);
97+ button_box->addButton (QDialogButtonBox::Cancel);
98+ remove_button = new QPushButton (QIcon (QLatin1String (" :/images/delete.png" )), tr (" Remove" ));
99+ remove_button->setEnabled (false );
100+ button_box->addButton (remove_button, QDialogButtonBox::ActionRole);
91101
92102 auto * layout = new QVBoxLayout ();
93- layout->addLayout (h_layout);
94- layout->addWidget (pattern_edit);
95- layout->addWidget (new QLabel (tr (" from the selected objects." )));
103+ layout->addWidget (new QLabel (tr (" Remove tags from %n selected object(s)" , nullptr , map->getNumSelectedObjects ())));
104+ layout->addLayout (search_operation_layout);
96105 layout->addWidget (undo_check);
97106 layout->addItem (Util::SpacerItem::create (this ));
98- layout->addStretch ();
107+ layout->addWidget (number_matching_objects);
108+ layout->addWidget (number_matching_keys);
109+ layout->addWidget (matching_keys_details);
99110 layout->addWidget (button_box);
100111 setLayout (layout);
101112
102113 connect (button_box, &QDialogButtonBox::rejected, this , &QDialog::reject);
103- connect (button_box, &QDialogButtonBox::accepted, this , &TagRemoveDialog::okClicked);
114+ connect (find_button, &QAbstractButton::clicked, this , &TagRemoveDialog::findClicked);
115+ connect (remove_button, &QAbstractButton::clicked, this , &TagRemoveDialog::removeClicked);
104116 connect (pattern_edit, &QLineEdit::textChanged, this , &TagRemoveDialog::textChanged);
105117}
106118
@@ -110,11 +122,11 @@ TagRemoveDialog::~TagRemoveDialog() = default;
110122// slot
111123void TagRemoveDialog::textChanged (const QString& text)
112124{
113- ok_button ->setEnabled (!text.trimmed ().isEmpty ());
125+ find_button ->setEnabled (!text.trimmed ().isEmpty ());
114126}
115127
116128// slot
117- void TagRemoveDialog::okClicked ()
129+ void TagRemoveDialog::findClicked ()
118130{
119131 const auto pattern = pattern_edit->text ();
120132 const auto op = compare_op->currentIndex ();
@@ -136,61 +148,67 @@ void TagRemoveDialog::okClicked()
136148 if (object_matched)
137149 ++objects_count;
138150 }
139- if (matching_keys. empty ())
140- {
141- QMessageBox::information ( this , tr (" Information " ), tr ( " No matching object tags found. " ), QMessageBox::Ok );
142- return ;
143- }
144- else
151+
152+ number_matching_objects-> setText ( tr ( " Number of matching objects: %1 " ). arg (objects_count));
153+ number_matching_keys-> setText ( tr (" %n matching keys: " , nullptr , matching_keys. size ()) );
154+ matching_keys_details-> clear () ;
155+
156+ if (!matching_keys. empty ())
145157 {
146- QString detailed_text = std::accumulate ( begin (matching_keys),
158+ QString matching_keys_list = std::accumulate ( begin (matching_keys),
147159 end (matching_keys),
148- QString (tr ( " The following object tags will be removed: " ) ),
149- [](const QString& a, const QString& b) -> QString { return a + QChar::LineFeed + b; }
160+ QString (),
161+ [](const QString& a, const QString& b) -> QString { return a. isEmpty () ? b : a + QChar::LineFeed + b; }
150162 );
151- QMessageBox msgBox;
152- msgBox.setWindowTitle (tr (" Confirmation" ));
153- msgBox.setIcon (QMessageBox::Warning);
154- QString question = tr (" Do you want to remove %n tag(s)" , nullptr , matching_keys.size ());
155- question += QChar::Space + tr (" from %n object(s)?" , nullptr , objects_count);
156- msgBox.setText (question);
157- msgBox.setDetailedText (detailed_text);
158- msgBox.setStandardButtons (QMessageBox::Yes | QMessageBox::No);
159-
160- if (msgBox.exec () == QMessageBox::Yes)
163+ matching_keys_details->insertPlainText (matching_keys_list);
164+ remove_button->setEnabled (true );
165+ }
166+ }
167+
168+ // slot
169+ void TagRemoveDialog::removeClicked ()
170+ {
171+ const auto add_undo = undo_check->isChecked ();
172+
173+ auto question = QString (tr (" Do you really want to remove the found object tags?" ));
174+ if (!add_undo)
175+ question += QChar::LineFeed + QString (tr (" This cannot be undone." ));
176+ if (QMessageBox::question (this , tr (" Remove object tags" ), question, QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
177+ return ;
178+
179+ const auto pattern = pattern_edit->text ();
180+ const auto op = compare_op->currentIndex ();
181+
182+ CombinedUndoStep* combined_step;
183+ if (add_undo)
184+ combined_step = new CombinedUndoStep (map);
185+
186+ std::vector<QString> matching_keys;
187+ for (const auto & object : map->selectedObjects ())
188+ {
189+ matching_keys.clear ();
190+ for (const auto & tag : object->tags ())
161191 {
162- const auto add_undo = undo_check->isChecked ();
163- CombinedUndoStep* combined_step;
164- if (add_undo)
165- combined_step = new CombinedUndoStep (map);
166- std::vector<QString> matching_keys;
167- for (const auto & object : map->selectedObjects ())
192+ if ((compare_operations[op].fn )(tag.key , pattern))
168193 {
169- matching_keys.clear ();
170- for (const auto & tag : object->tags ())
171- {
172- if ((compare_operations[op].fn )(tag.key , pattern))
173- {
174- matching_keys.push_back (tag.key );
175- }
176- }
177- if (add_undo && !matching_keys.empty ())
178- {
179- auto undo_step = new ObjectTagsUndoStep (map);
180- undo_step->addObject (map->getCurrentPart ()->findObjectIndex (object));
181- combined_step->push (undo_step);
182- }
183- for (const auto & key : matching_keys)
184- {
185- object->removeTag (key);
186- }
194+ matching_keys.push_back (tag.key );
187195 }
188- if (add_undo)
189- map->push (combined_step);
196+ }
197+ if (add_undo && !matching_keys.empty ())
198+ {
199+ auto undo_step = new ObjectTagsUndoStep (map);
200+ undo_step->addObject (map->getCurrentPart ()->findObjectIndex (object));
201+ combined_step->push (undo_step);
202+ }
203+ for (const auto & key : matching_keys)
204+ {
205+ object->removeTag (key);
190206 }
191207 }
208+ if (add_undo)
209+ map->push (combined_step);
210+
192211 accept ();
193212}
194213
195-
196214} // namespace OpenOrienteering
0 commit comments