From de5ccbaedadb189bef11bdd14faa58f5656355f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20L=C3=B6tscher?= Date: Sun, 12 Nov 2023 15:16:22 +0100 Subject: [PATCH] Allow FORMAT_STR to use signed integers --- src/core/control/xojfile/LoadHandler.cpp | 3 +- src/core/gui/SearchBar.cpp | 9 ++-- .../menus/menubar/RecentDocumentsSubmenu.cpp | 2 +- .../gui/toolbarMenubar/ToolPageSpinner.cpp | 7 ++- src/util/PlaceholderString.cpp | 38 ------------- src/util/include/util/PlaceholderString.h | 54 ++++++++++++++++--- src/util/serializing/ObjectInputStream.cpp | 8 +-- test/unit_tests/util/I18nTest.cpp | 15 ++++++ 8 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/core/control/xojfile/LoadHandler.cpp b/src/core/control/xojfile/LoadHandler.cpp index 3e2b1e03d4c2..cd116fcb7fb2 100644 --- a/src/core/control/xojfile/LoadHandler.cpp +++ b/src/core/control/xojfile/LoadHandler.cpp @@ -1047,8 +1047,7 @@ void LoadHandler::parserText(GMarkupParseContext* context, const gchar* text, gs } else { g_warning("%s", FC(_F("xoj-File: {1}") % handler->filepath.string().c_str())); g_warning("%s", FC(_F("Wrong number of pressure values, got {1}, expected {2}") % - as_signed(handler->pressureBuffer.size()) % - (as_signed(handler->stroke->getPointCount()) - 1))); + handler->pressureBuffer.size() % (handler->stroke->getPointCount() - 1))); } handler->pressureBuffer.clear(); } diff --git a/src/core/gui/SearchBar.cpp b/src/core/gui/SearchBar.cpp index 8992107686cf..0a9e70065ba4 100644 --- a/src/core/gui/SearchBar.cpp +++ b/src/core/gui/SearchBar.cpp @@ -126,11 +126,10 @@ void SearchBar::search(Fun next) { if (found) { control->getScrollHandler()->scrollToPage(page, matchRect); control->getScrollHandler(); - gtk_label_set_text( - GTK_LABEL(lbSearchState), - (occurrences == 1 ? FC(_F("Text found once on page {1}") % (as_signed(page) + 1)) : - FC(_F("Text found {1} times on page {2} ({3} of {1})") % - as_signed(occurrences) % (as_signed(page) + 1) % as_signed(indexInPage)))); + gtk_label_set_text(GTK_LABEL(lbSearchState), + (occurrences == 1 ? FC(_F("Text found once on page {1}") % (page + 1)) : + FC(_F("Text found {1} times on page {2} ({3} of {1})") % + occurrences % (page + 1) % indexInPage))); return; } if (page == originalPage) { diff --git a/src/core/gui/menus/menubar/RecentDocumentsSubmenu.cpp b/src/core/gui/menus/menubar/RecentDocumentsSubmenu.cpp index fb3125183df3..0e32f0c6750a 100644 --- a/src/core/gui/menus/menubar/RecentDocumentsSubmenu.cpp +++ b/src/core/gui/menus/menubar/RecentDocumentsSubmenu.cpp @@ -39,7 +39,7 @@ auto createRecentMenuItem(const GtkRecentInfo* info, size_t i) { // escape underscore StringUtils::replaceAllChars(display_name, {replace_pair('_', "__")}); - std::string label = FS(FORMAT_STR("{1}. {2}") % (as_signed(i) + 1) % display_name); + std::string label = FS(FORMAT_STR("{1}. {2}") % (i + 1) % display_name); std::string action = G_ACTION_NAMESPACE; action += OPEN_ACTION_NAME; diff --git a/src/core/gui/toolbarMenubar/ToolPageSpinner.cpp b/src/core/gui/toolbarMenubar/ToolPageSpinner.cpp index a5526fcfd899..d6615f2adcbd 100644 --- a/src/core/gui/toolbarMenubar/ToolPageSpinner.cpp +++ b/src/core/gui/toolbarMenubar/ToolPageSpinner.cpp @@ -9,7 +9,6 @@ #include "util/Assert.h" // for xoj_assert #include "util/gtk4_helper.h" // for gtk_box_append #include "util/i18n.h" // for FS, _, _F, C_F -#include "util/safe_casts.h" // for as_signed ToolPageSpinner::ToolPageSpinner(std::string id, IconNameHelper iconNameHelper): AbstractToolItem(std::move(id)), @@ -29,12 +28,12 @@ void ToolPageSpinner::setPageInfo(const size_t pageCount, const size_t pdfPage) } void ToolPageSpinner::updateLabels() { - std::string ofString = FS(C_F("Page {pagenumber} \"of {pagecount}\"", " of {1}") % as_signed(this->pageCount)); + std::string ofString = FS(C_F("Page {pagenumber} \"of {pagecount}\"", " of {1}") % this->pageCount); if (this->pdfPage > 0) { if (this->orientation == GTK_ORIENTATION_HORIZONTAL) { - ofString += std::string(", ") + FS(_F("PDF Page {1}") % as_signed(this->pdfPage)); + ofString += std::string(", ") + FS(_F("PDF Page {1}") % this->pdfPage); } else { - ofString += std::string("\n") + FS(_F("PDF {1}") % as_signed(this->pdfPage)); + ofString += std::string("\n") + FS(_F("PDF {1}") % this->pdfPage); } gtk_label_set_text(GTK_LABEL(lbPageNo.get()), ofString.c_str()); } diff --git a/src/util/PlaceholderString.cpp b/src/util/PlaceholderString.cpp index 0ab4b080786c..716bc0fc1a1c 100644 --- a/src/util/PlaceholderString.cpp +++ b/src/util/PlaceholderString.cpp @@ -1,55 +1,17 @@ #include "util/PlaceholderString.h" -#include // for size_t #include // for exception -#include // for move #include // for g_error #include "util/safe_casts.h" // for as_unsigned -/** - * Format String - */ -class PlaceholderElementString: public PlaceholderElement { -public: - explicit PlaceholderElementString(std::string text): text(std::move(text)) {} - - auto format(std::string format) const -> std::string override { return text; } - -private: - std::string text; -}; - -/** - * Format int - */ -class PlaceholderElementInt: public PlaceholderElement { -public: - explicit PlaceholderElementInt(int64_t value): value(value) {} - - auto format(std::string format) const -> std::string override { return std::to_string(value); } - -private: - int64_t value; -}; - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// PlaceholderString::PlaceholderString(std::string text): text(std::move(text)) {} -auto PlaceholderString::operator%(int64_t value) -> PlaceholderString& { - data.emplace_back(std::make_unique(value)); - return *this; -} - -auto PlaceholderString::operator%(std::string value) -> PlaceholderString& { - data.emplace_back(std::make_unique(std::move(value))); - return *this; -} - auto PlaceholderString::formatPart(std::string format) const -> std::string { std::string formatDef; diff --git a/src/util/include/util/PlaceholderString.h b/src/util/include/util/PlaceholderString.h index dcd3241a4755..aa44221ef03f 100644 --- a/src/util/include/util/PlaceholderString.h +++ b/src/util/include/util/PlaceholderString.h @@ -14,11 +14,15 @@ #pragma once -#include // for int64_t -#include // for unique_ptr -#include // for ostream -#include // for string -#include // for vector +#include // for size_t +#include // for int64_t +#include // for unique_ptr +#include // for ostream +#include // for string +#include // for move +#include // for vector + +#include // for g_error /** * Base class for Formatting @@ -34,6 +38,35 @@ class PlaceholderElement { virtual auto format(std::string format) const -> std::string = 0; }; + +/** + * Format String + */ +class PlaceholderElementString: public PlaceholderElement { +public: + explicit PlaceholderElementString(std::string text): text(std::move(text)) {} + + auto format(std::string format) const -> std::string override { return text; } + +private: + std::string text; +}; + +/** + * Format int + */ +template +class PlaceholderElementInt: public PlaceholderElement { +public: + explicit PlaceholderElementInt(T value): value(value) {} + + auto format(std::string format) const -> std::string override { return std::to_string(value); } + +private: + T value; +}; + + /** * Placeholder String, used for formatting. Support Placeholder like * {1}, {2} etc. Use {{ for { @@ -42,8 +75,15 @@ struct PlaceholderString { PlaceholderString(std::string text); // Placeholder methods - PlaceholderString& operator%(int64_t value); - PlaceholderString& operator%(std::string value); + template + auto operator%(T value) -> PlaceholderString& { + if constexpr (std::is_integral_v) { + data.emplace_back(std::make_unique>(value)); + } else { + data.emplace_back(std::make_unique(std::move(value))); + } + return *this; + } // Process Method std::string str() const; diff --git a/src/util/serializing/ObjectInputStream.cpp b/src/util/serializing/ObjectInputStream.cpp index 581bed1b6c46..8c64051f66a2 100644 --- a/src/util/serializing/ObjectInputStream.cpp +++ b/src/util/serializing/ObjectInputStream.cpp @@ -132,16 +132,16 @@ auto ObjectInputStream::readImage() -> std::string { void ObjectInputStream::checkType(char type) { if (istream.str().size() < 2) { - throw InputStreamException(FS(FORMAT_STR("End reached, but try to read {1}, index {2} of {3}") % getType(type) % - (uint32_t)pos() % (uint32_t)len), - __FILE__, __LINE__); + throw InputStreamException( + FS(FORMAT_STR("End reached, but try to read {1}, index {2} of {3}") % getType(type) % pos() % len), + __FILE__, __LINE__); } char t = 0, underscore = 0; istream >> underscore >> t; if (underscore != '_') { throw InputStreamException(FS(FORMAT_STR("Expected type signature of {1}, index {2} of {3}, but read '{4}'") % - getType(type) % ((uint32_t)pos() + 1) % (uint32_t)len % underscore), + getType(type) % (pos() + 1) % len % underscore), __FILE__, __LINE__); } diff --git a/test/unit_tests/util/I18nTest.cpp b/test/unit_tests/util/I18nTest.cpp index 976c42016d7d..1752d87b7482 100644 --- a/test/unit_tests/util/I18nTest.cpp +++ b/test/unit_tests/util/I18nTest.cpp @@ -64,3 +64,18 @@ TEST(UtilI18n, test3) { string msg = FS(FORMAT_STR(" of {1}{2}") % 5 % 6); EXPECT_EQ(std::string(" of 56"), msg); } + +TEST(UtilI18n, test16bit) { + string msg = FS(FORMAT_STR("{1} = {2} and {3}") % 60123 % 60123U % -65536); + EXPECT_EQ(std::string("60123 = 60123 and -65536"), msg); +} + +TEST(UtilI18n, test32bit) { + string msg = FS(FORMAT_STR("{1} and {2}") % 4294967295U % -12345678); + EXPECT_EQ(std::string("4294967295 and -12345678"), msg); +} + +TEST(UtilI18n, test64bit) { + string msg = FS(FORMAT_STR("{1} and {2}") % 1234567890123456789U % -1234567890123456789); + EXPECT_EQ(std::string("1234567890123456789 and -1234567890123456789"), msg); +}