Skip to content

Commit 45dcda9

Browse files
committed
Show context for items with duplicate names in combo boxes
Closes #211
1 parent 8f18150 commit 45dcda9

File tree

4 files changed

+51
-17
lines changed

4 files changed

+51
-17
lines changed

src/dialogs/ascent_dialog.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ QString AscentDialog::getEditWindowTitle()
155155
*/
156156
void AscentDialog::populateComboBoxes()
157157
{
158-
populateItemCombo(db.regionsTable, db.regionsTable.nameColumn, true, regionFilterCombo, selectableRegionIDs, tr("All regions (no filter)"));
159-
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs);
158+
populateItemCombo(db.regionsTable, db.regionsTable.nameColumn, true, regionFilterCombo, selectableRegionIDs, tr("All regions (no filter)"), &db.regionsTable.rangeIDColumn, &db.rangesTable.nameColumn);
159+
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs, QString(), &db.peaksTable.regionIDColumn, &db.regionsTable.nameColumn);
160160

161161
hikeKindCombo->insertItems(1, EnumNames::translateList(EnumNames::hikeKindNames));
162162

@@ -293,9 +293,9 @@ void AscentDialog::handle_regionFilterChanged()
293293
{
294294
ItemID regionID = parseItemCombo(regionFilterCombo, selectableRegionIDs);
295295
if (regionID.isValid()) {
296-
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs, QString(), &db.peaksTable.regionIDColumn, regionID);
296+
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs, QString(), &db.peaksTable.regionIDColumn, &db.regionsTable.nameColumn, &db.peaksTable.regionIDColumn, regionID);
297297
} else {
298-
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs);
298+
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs, QString(), &db.peaksTable.regionIDColumn, &db.regionsTable.nameColumn);
299299
}
300300
}
301301

@@ -309,7 +309,7 @@ void AscentDialog::handle_newPeak()
309309
BufferRowIndex newPeakIndex = openNewPeakDialogAndStore(this, mainWindow, db);
310310
if (newPeakIndex.isInvalid()) return;
311311

312-
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs);
312+
populateItemCombo(db.peaksTable, db.peaksTable.nameColumn, true, peakCombo, selectablePeakIDs, QString(), &db.peaksTable.regionIDColumn, &db.regionsTable.nameColumn);
313313
const ValidItemID newPeakID = db.peaksTable.getPrimaryKeyAt(newPeakIndex);
314314
regionFilterCombo->setCurrentIndex(0);
315315
peakCombo->setCurrentIndex(selectablePeakIDs.indexOf(newPeakID) + 1); // 0 is None

src/dialogs/item_dialog.cpp

+43-9
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,20 @@ bool displayDeleteWarning(QWidget* parent, QString windowTitle, const QList<What
181181
* Repopulates the given combo box with the given table's entries, filtered and sorted according to
182182
* the given parameters, and writes the IDs of the entries to the referenced list.
183183
*
184-
* @param table The table to get the entries from.
185-
* @param displayAndSortColumn The column of the table to use for displaying and sorting the entries.
186-
* @param sortAsString Whether to sort the entries as strings. Otherwise, QVariant::compare() is used.
187-
* @param combo The combo box to populate.
188-
* @param idList The list in which to store the IDs of the entries.
189-
* @param overrideFirstLine If not empty, this string will be used as the first line of the combo box instead of the table's none string.
190-
* @param filterColumn If not null, only entries whose foreign key ID in this column matches the given ID will be added to the combo box.
191-
* @param filterID The ID to use for filtering entries, or an invalid ID to filter for entries with no reference.
184+
* @param table The table to get the entries from.
185+
* @param displayAndSortColumn The column of the table to use for displaying and sorting the entries.
186+
* @param sortAsString Whether to sort the entries as strings. Otherwise, QVariant::compare() is used.
187+
* @param combo The combo box to populate.
188+
* @param idList The list in which to store the IDs of the entries.
189+
* @param overrideFirstLine If not empty, this string will be used as the first line of the combo box instead of the table's none string.
190+
* @param distinctionKeyColumn If not null, this column will be used to point to a cell in distinctionContentColumn.
191+
* @param distinctionContentColumn If not null, this column will be used to add a distinguishing name in brackets to entries with duplicate names.
192+
* @param filterColumn If not null, only entries whose foreign key ID in this column matches the given ID will be added to the combo box.
193+
* @param filterID The ID to use for filtering entries, or an invalid ID to filter for entries with no reference.
192194
*/
193-
void populateItemCombo(NormalTable& table, const ValueColumn& displayAndSortColumn, bool sortAsString, QComboBox* combo, QList<ValidItemID>& idList, QString overrideFirstLine, const ForeignKeyColumn* filterColumn, ItemID filterID)
195+
void populateItemCombo(NormalTable& table, const ValueColumn& displayAndSortColumn, bool sortAsString, QComboBox* combo, QList<ValidItemID>& idList, const QString& overrideFirstLine, const ForeignKeyColumn* distinctionKeyColumn, const ValueColumn* distinctionContentColumn, const ForeignKeyColumn* filterColumn, ItemID filterID)
194196
{
197+
assert(displayAndSortColumn.table == &table);
195198
assert(!(!filterColumn && filterID.isValid()));
196199

197200
combo->clear();
@@ -202,6 +205,7 @@ void populateItemCombo(NormalTable& table, const ValueColumn& displayAndSortColu
202205

203206
// Get pairs of ID and display/sort field
204207
QList<QPair<ValidItemID, QVariant>> selectableItems = table.pairIDWith(displayAndSortColumn);
208+
if (selectableItems.isEmpty()) return;
205209

206210
if (filterColumn) {
207211
// Filter entries: if an item's foreign key ID doesn't match the given one, discard it
@@ -222,6 +226,36 @@ void populateItemCombo(NormalTable& table, const ValueColumn& displayAndSortColu
222226
};
223227
std::sort(selectableItems.begin(), selectableItems.end(), comparator);
224228

229+
// Add distinction field in brackets in case of duplicates
230+
if (distinctionKeyColumn || distinctionContentColumn) {
231+
assert(distinctionKeyColumn && distinctionContentColumn);
232+
assert(distinctionKeyColumn->table == &table);
233+
assert(distinctionKeyColumn->foreignColumn->table == distinctionContentColumn->table);
234+
// Find duplicates
235+
QSet<int> duplicateNameIndices = QSet<int>();
236+
QString previousName;
237+
for (int i = 0; i < selectableItems.size(); i++) {
238+
const QString currentName = selectableItems.at(i).second.toString();
239+
const bool sameName = currentName == previousName && i != 0;
240+
if (sameName) {
241+
duplicateNameIndices.insert(i - 1);
242+
duplicateNameIndices.insert(i);
243+
}
244+
previousName = currentName;
245+
}
246+
// Append distinction column content to duplicate names
247+
for (const int duplicateNameIndex : duplicateNameIndices) {
248+
const ValidItemID& itemID = selectableItems.at(duplicateNameIndex).first;
249+
const ItemID& distinctionKey = distinctionKeyColumn->getValueFor(itemID);
250+
if (distinctionKey.isInvalid()) continue;
251+
const QString& distinctionContent = distinctionContentColumn->getValueFor(FORCE_VALID(distinctionKey)).toString();
252+
if (distinctionContent.isEmpty()) continue;
253+
const QString& currentName = selectableItems.at(duplicateNameIndex).second.toString();
254+
const QString newName = currentName + " (" + distinctionContent + ")";
255+
selectableItems[duplicateNameIndex].second = newName;
256+
}
257+
}
258+
225259
// Save IDs and populate combo box
226260
for (const auto& [itemID, name] : selectableItems) {
227261
idList.append(itemID);

src/dialogs/item_dialog.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class ItemDialog : public QDialog
105105

106106
bool displayDeleteWarning(QWidget* parent, QString windowTitle, const QList<WhatIfDeleteResult>& whatIfResults);
107107

108-
void populateItemCombo(NormalTable& table, const ValueColumn& displayAndSortColumn, bool sortAsString, QComboBox* combo, QList<ValidItemID>& idList, QString overrideFirstLine = QString(), const ForeignKeyColumn* filterColumn = nullptr, ItemID filterID = ItemID());
108+
void populateItemCombo(NormalTable& table, const ValueColumn& displayAndSortColumn, bool sortAsString, QComboBox* combo, QList<ValidItemID>& idList, const QString& overrideFirstLine = QString(), const ForeignKeyColumn* distinctionKeyColumn = nullptr, const ValueColumn* distinctionContentColumn = nullptr, const ForeignKeyColumn* filterColumn = nullptr, ItemID filterID = ItemID());
109109

110110

111111

src/dialogs/peak_dialog.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ QString PeakDialog::getEditWindowTitle()
114114
*/
115115
void PeakDialog::populateComboBoxes()
116116
{
117-
populateItemCombo(db.regionsTable, db.regionsTable.nameColumn, true, regionCombo, selectableRegionIDs);
117+
populateItemCombo(db.regionsTable, db.regionsTable.nameColumn, true, regionCombo, selectableRegionIDs, QString(), &db.regionsTable.rangeIDColumn, &db.rangesTable.nameColumn);
118118
}
119119

120120

@@ -202,7 +202,7 @@ void PeakDialog::handle_newRegion()
202202
BufferRowIndex newRegionIndex = openNewRegionDialogAndStore(this, mainWindow, db);
203203
if (newRegionIndex.isInvalid()) return;
204204

205-
populateItemCombo(db.regionsTable, db.regionsTable.nameColumn, true, regionCombo, selectableRegionIDs);
205+
populateItemCombo(db.regionsTable, db.regionsTable.nameColumn, true, regionCombo, selectableRegionIDs, QString(), &db.regionsTable.rangeIDColumn, &db.rangesTable.nameColumn);
206206
const ValidItemID newRegionID = db.regionsTable.getPrimaryKeyAt(newRegionIndex);
207207
regionCombo->setCurrentIndex(selectableRegionIDs.indexOf(newRegionID) + 1); // 0 is None
208208
}

0 commit comments

Comments
 (0)