From 66bbab9ae2d9f9cdd1dceeef53710eda0957c1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Wed, 16 May 2018 19:53:10 +0200 Subject: [PATCH] Sort file numbers naturally (#2467) --- rtgui/thumbbrowserentrybase.cc | 149 ++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 2fff95904..bc9506e3f 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -23,6 +23,153 @@ #include "../rtengine/mytime.h" +namespace +{ + +Glib::ustring getPaddedName(const Glib::ustring& name) +{ + enum class State { + OTHER, + NUMBER, + FRACTION + }; + + constexpr unsigned int pad_width = 17; // Must be at least 1 + + Glib::ustring res; + + State state = State::OTHER; + Glib::ustring number; + + for (auto c : name) { + switch (state) { + case State::OTHER: { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + number += c; + state = State::NUMBER; + break; + } + + case '.': { + res += c; + state = State::FRACTION; + break; + } + + default: { + res += c; + break; + } + } + break; + } + + case State::NUMBER: { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + number += c; + break; + } + + default: { + if (number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + res += number; + res += c; + number.clear(); + + state = + c == '.' + ? State::FRACTION + : State::OTHER; + break; + } + } + break; + } + + case State::FRACTION: { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + number += c; + break; + } + + default: { + res += number; + if (!number.empty() && number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + res += c; + number.clear(); + + if (c != '.') { + state = State::OTHER; + } + break; + } + } + break; + } + } + } + + switch (state) { + case State::OTHER: { + break; + } + + case State::NUMBER: { + if (number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + res += number; + break; + } + + case State::FRACTION: { + res += number; + if (!number.empty() && number.size() < pad_width) { + res.append(pad_width - number.size(), '0'); + } + break; + } + } + + return res; +} + +} + ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : fnlabw(0), fnlabh(0), @@ -57,7 +204,7 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) : bbFramed(false), bbPreview(nullptr), cursor_type(CSUndefined), - collate_name(dispname.casefold().collate_key()), + collate_name(getPaddedName(dispname).casefold_collate_key()), thumbnail(nullptr), filename(fname), shortname(dispname),