From cea171ffd4e11b40ed8df2f5e52a9c283fcf4f48 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sat, 24 Sep 2022 19:08:05 +0200 Subject: [PATCH] core: implement an enumerating iterator In the printing-template code, we loop through a vector and then determine the index of the current element by searching the vector. This irks me. Since looping over a collection with an index is a rather common theme, implement an enumerating iterator that can be used as in: for (auto [idx, item]: enumerated_range(v)) { ... } For now, use it for the above vexing case. Convert other iterations of this theme later. Signed-off-by: Berthold Stoeger --- core/range.h | 53 ++++++++++++++++++++++++++++++++ desktop-widgets/printoptions.cpp | 5 +-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/core/range.h b/core/range.h index fa4f1465c..59dbf090d 100644 --- a/core/range.h +++ b/core/range.h @@ -3,6 +3,9 @@ #ifndef RANGE_H #define RANGE_H +#include // for std::pair +#include // we need a declaration of std::begin() and std::end() + // Move a range in a vector to a different position. // The parameters are given according to the usual STL-semantics: // v: a container with STL-like random access iterator via std::begin(...) @@ -29,4 +32,54 @@ void move_in_range(Range &v, int rangeBegin, int rangeEnd, int destination) std::rotate(it + destination, it + rangeBegin, it + rangeEnd); } +// A rudimentary adaptor for looping over ranges with an index: +// for (auto [idx, item]: enumerated_range(v)) ... +// The index is a signed integer, since this is what we use more often. +template +class enumerated_range +{ + Range &base; +public: + using base_iterator = decltype(std::begin(std::declval())); + class iterator { + int idx; + base_iterator it; + public: + std::pair operator*() const + { + return { idx, *it }; + } + iterator &operator++() + { + ++idx; + ++it; + return *this; + } + iterator(int idx, base_iterator it) : idx(idx), it(it) + { + } + bool operator==(const iterator &it2) const + { + return it == it2.it; + } + bool operator!=(const iterator &it2) const + { + return it != it2.it; + } + }; + + iterator begin() + { + return iterator(0, std::begin(base)); + } + iterator end() + { + return iterator(-1, std::end(base)); + } + + enumerated_range(Range &base) : base(base) + { + } +}; + #endif diff --git a/desktop-widgets/printoptions.cpp b/desktop-widgets/printoptions.cpp index e36351443..88cf57c4f 100644 --- a/desktop-widgets/printoptions.cpp +++ b/desktop-widgets/printoptions.cpp @@ -3,6 +3,7 @@ #include "templateedit.h" #include "templatelayout.h" #include "core/qthelper.h" +#include "core/range.h" #include #include @@ -63,10 +64,10 @@ void PrintOptions::setupTemplates() currList.sort(); int current_index = 0; ui.printTemplate->clear(); - Q_FOREACH(const QString& theme, currList) { + for (auto [idx, theme]: enumerated_range(currList)) { // find the stored template in the list if (theme == storedTemplate || theme == lastImportExportTemplate) - current_index = currList.indexOf(theme); + current_index = idx; ui.printTemplate->addItem(theme.split('.')[0], theme); } ui.printTemplate->setCurrentIndex(current_index);