mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Merge remote-tracking branch 'origin/bstoeger-range'
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
commit
46365b3199
13 changed files with 175 additions and 167 deletions
|
@ -206,6 +206,7 @@ HEADERS += \
|
|||
core/pref.h \
|
||||
core/profile.h \
|
||||
core/qthelper.h \
|
||||
core/range.h \
|
||||
core/save-html.h \
|
||||
core/statistics.h \
|
||||
core/units.h \
|
||||
|
|
|
@ -147,6 +147,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
|
|||
qt-init.cpp
|
||||
qthelper.cpp
|
||||
qthelper.h
|
||||
range.h
|
||||
sample.c
|
||||
sample.h
|
||||
save-git.c
|
||||
|
|
|
@ -104,26 +104,11 @@ static const char *negate_description[2] {
|
|||
QT_TRANSLATE_NOOP("gettextFromC", "is not"),
|
||||
};
|
||||
|
||||
static constexpr size_t type_descriptions_count()
|
||||
{
|
||||
return std::size(type_descriptions);
|
||||
}
|
||||
|
||||
static constexpr size_t string_mode_descriptions_count()
|
||||
{
|
||||
return std::size(string_mode_descriptions);
|
||||
}
|
||||
|
||||
static constexpr size_t range_mode_descriptions_count()
|
||||
{
|
||||
return std::size(range_mode_descriptions);
|
||||
}
|
||||
|
||||
static const type_description *get_type_description(enum filter_constraint_type type)
|
||||
{
|
||||
for (size_t i = 0; i < type_descriptions_count(); ++i) {
|
||||
if (type_descriptions[i].type == type)
|
||||
return &type_descriptions[i];
|
||||
for (const auto &desc: type_descriptions) {
|
||||
if (desc.type == type)
|
||||
return &desc;
|
||||
}
|
||||
report_error("unknown filter constraint type: %d", type);
|
||||
return nullptr;
|
||||
|
@ -131,9 +116,9 @@ static const type_description *get_type_description(enum filter_constraint_type
|
|||
|
||||
static const string_mode_description *get_string_mode_description(enum filter_constraint_string_mode mode)
|
||||
{
|
||||
for (size_t i = 0; i < string_mode_descriptions_count(); ++i) {
|
||||
if (string_mode_descriptions[i].mode == mode)
|
||||
return &string_mode_descriptions[i];
|
||||
for (const auto &desc: string_mode_descriptions) {
|
||||
if (desc.mode == mode)
|
||||
return &desc;
|
||||
}
|
||||
report_error("unknown filter constraint string mode: %d", mode);
|
||||
return nullptr;
|
||||
|
@ -141,9 +126,9 @@ static const string_mode_description *get_string_mode_description(enum filter_co
|
|||
|
||||
static const range_mode_description *get_range_mode_description(enum filter_constraint_range_mode mode)
|
||||
{
|
||||
for (size_t i = 0; i < range_mode_descriptions_count(); ++i) {
|
||||
if (range_mode_descriptions[i].mode == mode)
|
||||
return &range_mode_descriptions[i];
|
||||
for (const auto &desc: range_mode_descriptions) {
|
||||
if (desc.mode == mode)
|
||||
return &desc;
|
||||
}
|
||||
report_error("unknown filter constraint range mode: %d", mode);
|
||||
return nullptr;
|
||||
|
@ -151,9 +136,9 @@ static const range_mode_description *get_range_mode_description(enum filter_cons
|
|||
|
||||
static enum filter_constraint_type filter_constraint_type_from_string(const char *s)
|
||||
{
|
||||
for (size_t i = 0; i < type_descriptions_count(); ++i) {
|
||||
if (same_string(type_descriptions[i].token, s))
|
||||
return type_descriptions[i].type;
|
||||
for (const auto &desc: type_descriptions) {
|
||||
if (same_string(desc.token, s))
|
||||
return desc.type;
|
||||
}
|
||||
report_error("unknown filter constraint type: %s", s);
|
||||
return FILTER_CONSTRAINT_DATE;
|
||||
|
@ -161,9 +146,9 @@ static enum filter_constraint_type filter_constraint_type_from_string(const char
|
|||
|
||||
static enum filter_constraint_string_mode filter_constraint_string_mode_from_string(const char *s)
|
||||
{
|
||||
for (size_t i = 0; i < string_mode_descriptions_count(); ++i) {
|
||||
if (same_string(string_mode_descriptions[i].token, s))
|
||||
return string_mode_descriptions[i].mode;
|
||||
for (const auto &desc: string_mode_descriptions) {
|
||||
if (same_string(desc.token, s))
|
||||
return desc.mode;
|
||||
}
|
||||
report_error("unknown filter constraint string mode: %s", s);
|
||||
return FILTER_CONSTRAINT_EXACT;
|
||||
|
@ -171,9 +156,9 @@ static enum filter_constraint_string_mode filter_constraint_string_mode_from_str
|
|||
|
||||
static enum filter_constraint_range_mode filter_constraint_range_mode_from_string(const char *s)
|
||||
{
|
||||
for (size_t i = 0; i < range_mode_descriptions_count(); ++i) {
|
||||
if (same_string(range_mode_descriptions[i].token, s))
|
||||
return range_mode_descriptions[i].mode;
|
||||
for (const auto &desc: range_mode_descriptions) {
|
||||
if (same_string(desc.token, s))
|
||||
return desc.mode;
|
||||
}
|
||||
report_error("unknown filter constraint range mode: %s", s);
|
||||
return FILTER_CONSTRAINT_EQUAL;
|
||||
|
@ -217,21 +202,21 @@ extern "C" int filter_constraint_range_mode_to_index(enum filter_constraint_rang
|
|||
|
||||
extern "C" enum filter_constraint_type filter_constraint_type_from_index(int index)
|
||||
{
|
||||
if (index >= 0 && index < (int)type_descriptions_count())
|
||||
if (index >= 0 && index < (int)std::size(type_descriptions))
|
||||
return type_descriptions[index].type;
|
||||
return (enum filter_constraint_type)-1;
|
||||
}
|
||||
|
||||
extern "C" enum filter_constraint_string_mode filter_constraint_string_mode_from_index(int index)
|
||||
{
|
||||
if (index >= 0 && index < (int)string_mode_descriptions_count())
|
||||
if (index >= 0 && index < (int)std::size(string_mode_descriptions))
|
||||
return string_mode_descriptions[index].mode;
|
||||
return (enum filter_constraint_string_mode)-1;
|
||||
}
|
||||
|
||||
extern "C" enum filter_constraint_range_mode filter_constraint_range_mode_from_index(int index)
|
||||
{
|
||||
if (index >= 0 && index < (int)range_mode_descriptions_count())
|
||||
if (index >= 0 && index < (int)std::size(range_mode_descriptions))
|
||||
return range_mode_descriptions[index].mode;
|
||||
return (enum filter_constraint_range_mode)-1;
|
||||
}
|
||||
|
@ -347,32 +332,32 @@ static double base_to_display_unit(int i, enum filter_constraint_type type)
|
|||
QStringList filter_constraint_type_list_translated()
|
||||
{
|
||||
QStringList res;
|
||||
for (size_t i = 0; i < type_descriptions_count(); ++i)
|
||||
res.push_back(gettextFromC::tr(type_descriptions[i].text_ui));
|
||||
for (const auto &desc: type_descriptions)
|
||||
res.push_back(gettextFromC::tr(desc.text_ui));
|
||||
return res;
|
||||
}
|
||||
|
||||
QStringList filter_constraint_string_mode_list_translated()
|
||||
{
|
||||
QStringList res;
|
||||
for (size_t i = 0; i < string_mode_descriptions_count(); ++i)
|
||||
res.push_back(gettextFromC::tr(string_mode_descriptions[i].text_ui));
|
||||
for (const auto &desc: string_mode_descriptions)
|
||||
res.push_back(gettextFromC::tr(desc.text_ui));
|
||||
return res;
|
||||
}
|
||||
|
||||
QStringList filter_constraint_range_mode_list_translated()
|
||||
{
|
||||
QStringList res;
|
||||
for (size_t i = 0; i < range_mode_descriptions_count(); ++i)
|
||||
res.push_back(gettextFromC::tr(range_mode_descriptions[i].text_ui));
|
||||
for (const auto &desc: range_mode_descriptions)
|
||||
res.push_back(gettextFromC::tr(desc.text_ui));
|
||||
return res;
|
||||
}
|
||||
|
||||
QStringList filter_constraint_range_mode_list_translated_date()
|
||||
{
|
||||
QStringList res;
|
||||
for (size_t i = 0; i < range_mode_descriptions_count(); ++i)
|
||||
res.push_back(gettextFromC::tr(range_mode_descriptions[i].text_ui_date));
|
||||
for (const auto &desc: range_mode_descriptions)
|
||||
res.push_back(gettextFromC::tr(desc.text_ui_date));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_
|
|||
return cylinder_idx;
|
||||
}
|
||||
|
||||
int get_gasidx(struct dive *dive, struct gasmix mix)
|
||||
static int get_gasidx(struct dive *dive, struct gasmix mix)
|
||||
{
|
||||
return find_best_gasmix_match(mix, &dive->cylinders);
|
||||
}
|
||||
|
|
|
@ -42,22 +42,13 @@ extern "C" {
|
|||
|
||||
extern int validate_gas(const char *text, struct gasmix *gas);
|
||||
extern int validate_po2(const char *text, int *mbar_po2);
|
||||
extern timestamp_t current_time_notz(void);
|
||||
extern void set_last_stop(bool last_stop_6m);
|
||||
extern void set_verbatim(bool verbatim);
|
||||
extern void set_display_runtime(bool display);
|
||||
extern void set_display_duration(bool display);
|
||||
extern void set_display_transitions(bool display);
|
||||
extern int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_t time);
|
||||
extern int get_gasidx(struct dive *dive, struct gasmix mix);
|
||||
extern bool diveplan_empty(struct diveplan *diveplan);
|
||||
extern void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, int error);
|
||||
extern const char *get_planner_disclaimer();
|
||||
extern char *get_planner_disclaimer_formatted();
|
||||
|
||||
extern void free_dps(struct diveplan *diveplan);
|
||||
extern struct dive *planned_dive;
|
||||
extern char *cache_data;
|
||||
|
||||
struct divedatapoint *plan_add_segment(struct diveplan *diveplan, int duration, int depth, int cylinderid, int po2, bool entered, enum divemode_t divemode);
|
||||
struct divedatapoint *create_dp(int time_incr, int depth, int cylinderid, int po2);
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <QApplication>
|
||||
#include <QTextDocument>
|
||||
#include <QPainter>
|
||||
#include <QProgressDialog> // TODO: remove with convertThumbnails()
|
||||
#include <QSvgRenderer>
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
|
@ -676,7 +675,7 @@ QString get_water_type_string(int salinity)
|
|||
QStringList getWaterTypesAsString()
|
||||
{
|
||||
QStringList res;
|
||||
res.reserve(std::end(waterTypes) - std::begin(waterTypes)); // Waiting for C++17's std::size()
|
||||
res.reserve(std::size(waterTypes));
|
||||
for (const char *t: waterTypes)
|
||||
res.push_back(gettextFromC::tr(t));
|
||||
return res;
|
||||
|
@ -719,17 +718,17 @@ static const char *printing_templates = "printing_templates";
|
|||
|
||||
QString getPrintingTemplatePathUser()
|
||||
{
|
||||
static QString path = QString();
|
||||
if (path.isEmpty())
|
||||
path = QString(system_default_directory()) + QDir::separator() + QString(printing_templates);
|
||||
// Function-local statics are initialized on first invocation
|
||||
static QString path(QString(system_default_directory()) +
|
||||
QDir::separator() +
|
||||
QString(printing_templates));
|
||||
return path;
|
||||
}
|
||||
|
||||
QString getPrintingTemplatePathBundle()
|
||||
{
|
||||
static QString path = QString();
|
||||
if (path.isEmpty())
|
||||
path = getSubsurfaceDataPath(printing_templates);
|
||||
// Function-local statics are initialized on first invocation
|
||||
static QString path(getSubsurfaceDataPath(printing_templates));
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -1072,45 +1071,6 @@ extern "C" char *hashfile_name_string()
|
|||
return copy_qstring(hashfile_name());
|
||||
}
|
||||
|
||||
// During a transition period, convert old thumbnail-hashes to individual files
|
||||
// TODO: remove this code in due course
|
||||
static void convertThumbnails(const QHash <QString, QImage> &thumbnails)
|
||||
{
|
||||
if (thumbnails.empty())
|
||||
return;
|
||||
// This is a singular occurrence, therefore translating the strings seems not worth it
|
||||
QProgressDialog progress("Convert thumbnails...", "Abort", 0, thumbnails.size());
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
|
||||
int count = 0;
|
||||
for (const QString &name: thumbnails.keys()) {
|
||||
const QImage thumbnail = thumbnails[name];
|
||||
|
||||
if (thumbnail.isNull())
|
||||
continue;
|
||||
|
||||
// This is duplicate code (see qt-models/divepicturemodel.cpp)
|
||||
// Not a problem, since this routine will be removed in due course.
|
||||
QString filename = thumbnailFileName(name);
|
||||
if (filename.isEmpty())
|
||||
continue;
|
||||
|
||||
QSaveFile file(filename);
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
QDataStream stream(&file);
|
||||
|
||||
quint32 type = MEDIATYPE_PICTURE;
|
||||
stream << type;
|
||||
stream << thumbnail;
|
||||
file.commit();
|
||||
|
||||
progress.setValue(++count);
|
||||
if (progress.wasCanceled())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is a temporary helper struct. Remove in due course with convertLocalFilename().
|
||||
struct HashToFile {
|
||||
QByteArray hash;
|
||||
|
@ -1129,7 +1089,7 @@ static void convertLocalFilename(const QHash<QString, QByteArray> &hashOf, const
|
|||
return;
|
||||
|
||||
// Create a vector of hash/filename pairs and sort by hash.
|
||||
// Elements can than be accessed with binary search.
|
||||
// Elements can then be accessed with binary search.
|
||||
QHash<QByteArray, QString> canonicalFilenameByHash;
|
||||
QVector<HashToFile> h2f;
|
||||
h2f.reserve(hashOf.size());
|
||||
|
@ -1166,7 +1126,6 @@ void read_hashes()
|
|||
stream >> localFilenameOf;
|
||||
locker.unlock();
|
||||
hashfile.close();
|
||||
convertThumbnails(thumbnailCache);
|
||||
convertLocalFilename(hashOf, localFilenameByHash);
|
||||
}
|
||||
QMutexLocker locker(&hashOfMutex);
|
||||
|
|
|
@ -108,31 +108,6 @@ void uiNotification(const QString &msg);
|
|||
#define TITLE_OR_TEXT(_t, _m) _t, _m
|
||||
#endif
|
||||
|
||||
// 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(...)
|
||||
// rangeBegin: index of first element
|
||||
// rangeEnd: index one *past* last element
|
||||
// destination: index to element before which the range will be moved
|
||||
// Owing to std::begin() magic, this function works with STL-like containers:
|
||||
// QVector<int> v{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
// moveInVector(v, 1, 4, 6);
|
||||
// as well as with C-style arrays:
|
||||
// int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
// moveInVector(array, 1, 4, 6);
|
||||
// Both calls will have the following effect:
|
||||
// Before: 0 1 2 3 4 5 6 7 8 9
|
||||
// After: 0 4 5 1 2 3 6 7 8 9
|
||||
// No sanitizing of the input arguments is performed.
|
||||
template <typename Vector>
|
||||
void moveInVector(Vector &v, int rangeBegin, int rangeEnd, int destination)
|
||||
{
|
||||
auto it = std::begin(v);
|
||||
if (destination > rangeEnd)
|
||||
std::rotate(it + rangeBegin, it + rangeEnd, it + destination);
|
||||
else if (destination < rangeBegin)
|
||||
std::rotate(it + destination, it + rangeBegin, it + rangeEnd);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 3) Functions visible to C and C++
|
||||
|
|
101
core/range.h
Normal file
101
core/range.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Helper functions for range manipulations
|
||||
#ifndef RANGE_H
|
||||
#define RANGE_H
|
||||
|
||||
#include <utility> // for std::pair
|
||||
#include <vector> // 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(...)
|
||||
// rangeBegin: index of first element
|
||||
// rangeEnd: index one *past* last element
|
||||
// destination: index to element before which the range will be moved
|
||||
// Owing to std::begin() magic, this function works with STL-like containers:
|
||||
// QVector<int> v{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
// move_in_range(v, 1, 4, 6);
|
||||
// as well as with C-style arrays:
|
||||
// int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
// move_in_range(array, 1, 4, 6);
|
||||
// Both calls will have the following effect:
|
||||
// Before: 0 1 2 3 4 5 6 7 8 9
|
||||
// After: 0 4 5 1 2 3 6 7 8 9
|
||||
// No sanitizing of the input arguments is performed.
|
||||
template <typename Range>
|
||||
void move_in_range(Range &v, int rangeBegin, int rangeEnd, int destination)
|
||||
{
|
||||
auto it = std::begin(v);
|
||||
if (destination > rangeEnd)
|
||||
std::rotate(it + rangeBegin, it + rangeEnd, it + destination);
|
||||
else if (destination < rangeBegin)
|
||||
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 <typename Range>
|
||||
class enumerated_range
|
||||
{
|
||||
Range &base;
|
||||
public:
|
||||
using base_iterator = decltype(std::begin(std::declval<Range>()));
|
||||
class iterator {
|
||||
int idx;
|
||||
base_iterator it;
|
||||
public:
|
||||
std::pair<int, decltype(*it)> 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)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Find the index of an element in a range. Return -1 if not found
|
||||
// Range must have a random access iterator.
|
||||
template <typename Range, typename Element>
|
||||
int index_of(const Range &range, const Element &e)
|
||||
{
|
||||
auto it = std::find(std::begin(range), std::end(range), e);
|
||||
return it == std::end(range) ? -1 : it - std::begin(range);
|
||||
}
|
||||
|
||||
template <typename Range, typename Func>
|
||||
int index_of_if(const Range &range, Func f)
|
||||
{
|
||||
auto it = std::find_if(std::begin(range), std::end(range), f);
|
||||
return it == std::end(range) ? -1 : it - std::begin(range);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,6 +3,7 @@
|
|||
#include "templateedit.h"
|
||||
#include "templatelayout.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/range.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
|
@ -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);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "core/event.h"
|
||||
#include "core/subsurface-string.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/range.h"
|
||||
#include "core/settings/qPrefTechnicalDetails.h"
|
||||
#include "core/settings/qPrefPartialPressureGas.h"
|
||||
#include "profile-widget/diveeventitem.h"
|
||||
|
@ -870,8 +871,8 @@ void ProfileWidget2::pointsRemoved(const QModelIndex &, int start, int end)
|
|||
|
||||
void ProfileWidget2::pointsMoved(const QModelIndex &, int start, int end, const QModelIndex &, int row)
|
||||
{
|
||||
moveInVector(handles, start, end + 1, row);
|
||||
moveInVector(gases, start, end + 1, row);
|
||||
move_in_range(handles, start, end + 1, row);
|
||||
move_in_range(gases, start, end + 1, row);
|
||||
}
|
||||
|
||||
void ProfileWidget2::repositionDiveHandlers()
|
||||
|
@ -1319,7 +1320,7 @@ void ProfileWidget2::pictureOffsetChanged(dive *dIn, QString filename, offset_t
|
|||
// Move image from old to new position
|
||||
int oldIndex = oldPos - pictures.begin();
|
||||
int newIndex = newPos - pictures.begin();
|
||||
moveInVector(pictures, oldIndex, oldIndex + 1, newIndex);
|
||||
move_in_range(pictures, oldIndex, oldIndex + 1, newIndex);
|
||||
} else {
|
||||
// Case 1b): remove picture
|
||||
pictures.erase(oldPos);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "core/imagedownloader.h"
|
||||
#include "core/picture.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/range.h"
|
||||
#include "core/selection.h"
|
||||
#include "core/subsurface-qt/divelistnotifier.h"
|
||||
#include "commands/command.h"
|
||||
|
@ -205,8 +206,8 @@ void DivePictureModel::picturesAdded(dive *d, QVector<PictureObj> picsIn)
|
|||
// Convert the picture-data into our own format
|
||||
std::vector<PictureEntry> pics;
|
||||
pics.reserve(picsIn.size());
|
||||
for (int i = 0; i < picsIn.size(); ++i)
|
||||
pics.push_back(PictureEntry(d, picsIn[i]));
|
||||
for (const PictureObj &pic: picsIn)
|
||||
pics.push_back(PictureEntry(d, pic));
|
||||
|
||||
// Insert batch-wise to avoid too many reloads
|
||||
pictures.reserve(pictures.size() + pics.size());
|
||||
|
@ -241,10 +242,8 @@ int DivePictureModel::rowCount(const QModelIndex&) const
|
|||
|
||||
int DivePictureModel::findPictureId(const std::string &filename)
|
||||
{
|
||||
for (int i = 0; i < (int)pictures.size(); ++i)
|
||||
if (pictures[i].filename == filename)
|
||||
return i;
|
||||
return -1;
|
||||
return index_of_if(pictures, [&filename](const PictureEntry &p)
|
||||
{ return p.filename == filename; });
|
||||
}
|
||||
|
||||
static void addDurationToThumbnail(QImage &img, duration_t duration)
|
||||
|
@ -312,6 +311,6 @@ void DivePictureModel::pictureOffsetChanged(dive *d, const QString filenameIn, o
|
|||
if (oldIndex == newIndex || oldIndex + 1 == newIndex)
|
||||
return;
|
||||
beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
|
||||
moveInVector(pictures, oldIndex, oldIndex + 1, newIndex);
|
||||
move_in_range(pictures, oldIndex, oldIndex + 1, newIndex);
|
||||
endMoveRows();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "qt-models/models.h"
|
||||
#include "core/device.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/range.h"
|
||||
#include "core/sample.h"
|
||||
#include "core/settings/qPrefDivePlanner.h"
|
||||
#include "core/settings/qPrefUnit.h"
|
||||
|
@ -877,7 +878,7 @@ void DivePlannerPointsModel::editStop(int row, divedatapoint newData)
|
|||
|
||||
if (newRow != row && newRow != row + 1) {
|
||||
beginMoveRows(QModelIndex(), row, row, QModelIndex(), newRow);
|
||||
moveInVector(divepoints, row, row + 1, newRow);
|
||||
move_in_range(divepoints, row, row + 1, newRow);
|
||||
endMoveRows();
|
||||
|
||||
// Account for moving the row backwards in the array.
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "core/string-format.h"
|
||||
#include "core/trip.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/range.h"
|
||||
#include "core/divesite.h"
|
||||
#include "core/picture.h"
|
||||
#include "core/subsurface-string.h"
|
||||
|
@ -205,8 +206,8 @@ static QPixmap &getPhotoIcon(int idx)
|
|||
if (!icons) {
|
||||
const IconMetrics &im = defaultIconMetrics();
|
||||
icons = std::make_unique<QPixmap[]>(std::size(icon_names));
|
||||
for (size_t i = 0; i < std::size(icon_names); ++i)
|
||||
icons[i] = QIcon(icon_names[i]).pixmap(im.sz_small, im.sz_small);
|
||||
for (auto [i, name]: enumerated_range(icon_names))
|
||||
icons[i] = QIcon(name).pixmap(im.sz_small, im.sz_small);
|
||||
}
|
||||
return icons[idx];
|
||||
}
|
||||
|
@ -974,7 +975,7 @@ void DiveTripModelTree::topLevelChanged(int idx)
|
|||
// If index changed, move items
|
||||
if (newIdx != idx && newIdx != idx + 1) {
|
||||
beginMoveRows(QModelIndex(), idx, idx, QModelIndex(), newIdx);
|
||||
moveInVector(items, idx, idx + 1, newIdx);
|
||||
move_in_range(items, idx, idx + 1, newIdx);
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
|
@ -1007,34 +1008,26 @@ void DiveTripModelTree::addDivesToTrip(int trip, const QVector<dive *> &dives)
|
|||
|
||||
int DiveTripModelTree::findTripIdx(const dive_trip *trip) const
|
||||
{
|
||||
for (int i = 0; i < (int)items.size(); ++i)
|
||||
if (items[i].d_or_t.trip == trip)
|
||||
return i;
|
||||
return -1;
|
||||
return index_of_if(items, [trip] (const Item &item)
|
||||
{ return item.d_or_t.trip == trip; });
|
||||
}
|
||||
|
||||
int DiveTripModelTree::findDiveIdx(const dive *d) const
|
||||
{
|
||||
for (int i = 0; i < (int)items.size(); ++i)
|
||||
if (items[i].isDive(d))
|
||||
return i;
|
||||
return -1;
|
||||
return index_of_if(items, [d] (const Item &item)
|
||||
{ return item.isDive(d); });
|
||||
}
|
||||
|
||||
int DiveTripModelTree::findDiveInTrip(int tripIdx, const dive *d) const
|
||||
{
|
||||
const Item &item = items[tripIdx];
|
||||
for (int i = 0; i < (int)item.dives.size(); ++i)
|
||||
if (item.dives[i] == d)
|
||||
return i;
|
||||
return -1;
|
||||
return index_of(items[tripIdx].dives, d);
|
||||
}
|
||||
|
||||
int DiveTripModelTree::findInsertionIndex(const dive_trip *trip) const
|
||||
{
|
||||
dive_or_trip d_or_t{ nullptr, (dive_trip *)trip };
|
||||
for (int i = 0; i < (int)items.size(); ++i) {
|
||||
if (dive_or_trip_less_than(d_or_t, items[i].d_or_t))
|
||||
for (auto [i, item]: enumerated_range(items)) {
|
||||
if (dive_or_trip_less_than(d_or_t, item.d_or_t))
|
||||
return i;
|
||||
}
|
||||
return items.size();
|
||||
|
@ -1121,8 +1114,8 @@ static QVector<dive *> visibleDives(const QVector<dive *> &dives)
|
|||
#ifdef SUBSURFACE_MOBILE
|
||||
int DiveTripModelTree::tripInDirection(const struct dive *d, int direction) const
|
||||
{
|
||||
for (int i = 0; i < (int)items.size(); ++i) {
|
||||
if (items[i].d_or_t.dive == d || (items[i].d_or_t.trip && findDiveInTrip(i, d) != -1)) {
|
||||
for (auto [i, item]: enumerated_range(items)) {
|
||||
if (item.d_or_t.dive == d || (item.d_or_t.trip && findDiveInTrip(i, d) != -1)) {
|
||||
// now walk in the direction given to find a trip
|
||||
int offset = direction;
|
||||
while (i + offset >= 0 && i + offset < (int)items.size()) {
|
||||
|
@ -1405,8 +1398,8 @@ void DiveTripModelTree::divesSelectedTrip(dive_trip *trip, const QVector<dive *>
|
|||
// Since both lists are sorted, we can do this linearly. Perhaps a binary search
|
||||
// would be better?
|
||||
int j = 0; // Index in items array
|
||||
for (int i = 0; i < dives.size(); ++i) {
|
||||
while (j < (int)items.size() && !items[j].isDive(dives[i]))
|
||||
for (struct dive *dive: dives) {
|
||||
while (j < (int)items.size() && !items[j].isDive(dive))
|
||||
++j;
|
||||
if (j >= (int)items.size())
|
||||
break;
|
||||
|
@ -1426,8 +1419,8 @@ void DiveTripModelTree::divesSelectedTrip(dive_trip *trip, const QVector<dive *>
|
|||
// would be better?
|
||||
int j = 0; // Index in items array
|
||||
const Item &entry = items[idx];
|
||||
for (int i = 0; i < dives.size(); ++i) {
|
||||
while (j < (int)entry.dives.size() && entry.dives[j] != dives[i])
|
||||
for (struct dive *dive: dives) {
|
||||
while (j < (int)entry.dives.size() && entry.dives[j] != dive)
|
||||
++j;
|
||||
if (j >= (int)entry.dives.size())
|
||||
break;
|
||||
|
@ -1662,8 +1655,8 @@ void DiveTripModelList::divesSelected(const QVector<dive *> &divesIn)
|
|||
// Since both lists are sorted, we can do this linearly. Perhaps a binary search
|
||||
// would be better?
|
||||
int j = 0; // Index in items array
|
||||
for (int i = 0; i < dives.size(); ++i) {
|
||||
while (j < (int)items.size() && items[j] != dives[i])
|
||||
for (struct dive *dive: dives) {
|
||||
while (j < (int)items.size() && items[j] != dive)
|
||||
++j;
|
||||
if (j >= (int)items.size())
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue