Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pan for openSUSE:Factory checked in at 2025-08-19 16:46:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pan (Old) and /work/SRC/openSUSE:Factory/.pan.new.1085 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pan" Tue Aug 19 16:46:30 2025 rev:28 rq:1300211 version:0.164 Changes: -------- --- /work/SRC/openSUSE:Factory/pan/pan.changes 2025-05-30 17:24:38.849573044 +0200 +++ /work/SRC/openSUSE:Factory/.pan.new.1085/pan.changes 2025-08-19 16:48:24.968600895 +0200 @@ -1,0 +2,11 @@ +Mon Aug 18 08:50:06 UTC 2025 - Atri Bhattacharya <badshah...@gmail.com> + +- Update to version 0.164: + * Fix article part detection where multipart articles were + detected as many articles instaed of one article with many + parts. + * Fix crash when displaying emoticon replacement +- Force GCC 11 on Leap 15.6 and older for c++ filesystem support. +- Drop empty %check section. + +------------------------------------------------------------------- Old: ---- pan-v0.163.tar.bz2 New: ---- pan-v0.164.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pan.spec ++++++ --- /var/tmp/diff_new_pack.QC9HFG/_old 2025-08-19 16:48:25.576626212 +0200 +++ /var/tmp/diff_new_pack.QC9HFG/_new 2025-08-19 16:48:25.580626378 +0200 @@ -1,7 +1,7 @@ # # spec file for package pan # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2025 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,8 +17,12 @@ %define __builder ninja +# C++ <filesystem> support is neede, so force newer GCC on 15.6 and older +%if 0%{?suse_version} < 1600 +%define gcc_ver 11 +%endif Name: pan -Version: 0.163 +Version: 0.164 Release: 0 Summary: A Newsreader for GNOME License: GPL-2.0-or-later @@ -27,7 +31,7 @@ Source0: https://gitlab.gnome.org/GNOME/pan/-/archive/v%{version}/%{name}-v%{version}.tar.bz2 BuildRequires: cmake BuildRequires: fdupes -BuildRequires: gcc-c++ +BuildRequires: gcc%{?gcc_ver}-c++ BuildRequires: gettext >= 0.21 BuildRequires: itstool BuildRequires: libxml2-tools @@ -57,6 +61,8 @@ %build # Build with static libs: https://gitlab.gnome.org/GNOME/pan/-/issues/190 %cmake \ + -DCMAKE_C_COMPILER=gcc%{?gcc_ver:-%{gcc_ver}} \ + -DCMAKE_CXX_COMPILER=g++%{?gcc_ver:-%{gcc_ver}} \ -DBUILD_SHARED_LIBS=OFF \ -DBUILD_STATIC_LIBS=ON \ -DENABLE_MANUAL=ON \ @@ -72,8 +78,6 @@ %find_lang %{name} %{?no_lang_C} %fdupes %{buildroot}/%{_prefix} -%check - %files %license COPYING COPYING-DOCS %doc AUTHORS NEWS README.org ++++++ pan-v0.163.tar.bz2 -> pan-v0.164.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pan-v0.163/.clang-format new/pan-v0.164/.clang-format --- old/pan-v0.163/.clang-format 2025-05-25 15:27:28.000000000 +0200 +++ new/pan-v0.164/.clang-format 2025-08-15 15:37:08.000000000 +0200 @@ -1,223 +1,3 @@ --- -Language: Cpp - -AccessModifierOffset: 2 - -# Ideally this would put ) on own line if and only if it had split the -# parameters onto the next line. BlockAlign doesn't really work visually -# IMO -AlignAfterOpenBracket: Align - -AlignArrayOfStructures: None -AlignConsecutiveAssignments: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: true -AlignConsecutiveBitFields: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: false -AlignConsecutiveDeclarations: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: false -AlignConsecutiveMacros: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - PadOperators: false -AlignEscapedNewlines: Right -AlignOperands: Align -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortEnumsOnASingleLine: true -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortLambdasOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine -AttributeMacros: - - __capability -BinPackArguments: false -BinPackParameters: false -BraceWrapping: - AfterCaseLabel: true - AfterClass: true - AfterControlStatement: Always - AfterEnum: true - AfterFunction: true - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: true - AfterUnion: true - AfterExternBlock: true - BeforeElse: true - BeforeLambdaBody: true - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeConceptDeclarations: Always -BreakBeforeBraces: Custom -BreakBeforeInheritanceComma: false -BreakInheritanceList: AfterColon -BreakBeforeTernaryOperators: false -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: AfterColon -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -QualifierAlignment: Right -CompactNamespaces: false -ConstructorInitializerIndentWidth: 2 -ContinuationIndentWidth: 2 -Cpp11BracedListStyle: true -DeriveLineEnding: true -DerivePointerAlignment: false -DisableFormat: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock -ExperimentalAutoDetectBinPacking: false -PackConstructorInitializers: Never -BasedOnStyle: '' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -AllowAllConstructorInitializersOnNextLine: false -FixNamespaceComments: true -ForEachMacros: - - foreach - - foreach_const - - Q_FOREACH - - BOOST_FOREACH -IfMacros: - - KJ_IF_MAYBE -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - SortPriority: 0 - CaseSensitive: false - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - SortPriority: 0 - CaseSensitive: false - - Regex: '.*' - Priority: 1 - SortPriority: 0 - CaseSensitive: false -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' -IndentAccessModifiers: true -IndentCaseLabels: true -IndentCaseBlocks: false -IndentGotoLabels: true -IndentPPDirectives: None -IndentExternBlock: AfterExternBlock -IndentRequiresClause: true -IndentWidth: 2 -IndentWrappedFunctionNames: false -InsertBraces: true -InsertTrailingCommas: None -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -LambdaBodyIndentation: Signature -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 2 -ObjCBreakBeforeNestedBlockParam: true -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakOpenParenthesis: 0 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 10000 -PenaltyIndentedWhitespace: 0 -PointerAlignment: Right -PPIndentWidth: -1 -ReferenceAlignment: Pointer -ReflowComments: true -RemoveBracesLLVM: false -RequiresClausePosition: OwnLine -SeparateDefinitionBlocks: Always -ShortNamespaceLines: 1 -SortIncludes: CaseSensitive -SortJavaStaticImport: Before -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: true -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements -SpaceBeforeParensOptions: - AfterControlStatements: true - AfterForeachMacros: false - AfterFunctionDefinitionName: false - AfterFunctionDeclarationName: false - AfterIfMacros: true - AfterOverloadedOperator: false - AfterRequiresInClause: false - AfterRequiresInExpression: false - BeforeNonEmptyParentheses: false -SpaceAroundPointerQualifiers: Default -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never -SpacesInConditionalStatement: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 -SpacesInParentheses: false -SpacesInSquareBrackets: false -SpaceBeforeSquareBrackets: false -BitFieldColonSpacing: Both -Standard: Latest -StatementAttributeLikeMacros: - - Q_EMIT -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION - - check - - check_eq -TabWidth: 8 -UseCRLF: false -UseTab: Never -WhitespaceSensitiveMacros: - - STRINGIZE - - PP_STRINGIZE - - BOOST_PP_STRINGIZE - - NS_SWIFT_NAME - - CF_SWIFT_NAME -... - +# We'll use defaults from the LLVM style +BasedOnStyle: LLVM diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pan-v0.163/NEWS new/pan-v0.164/NEWS --- old/pan-v0.163/NEWS 2025-05-25 15:27:28.000000000 +0200 +++ new/pan-v0.164/NEWS 2025-08-15 15:37:08.000000000 +0200 @@ -1,3 +1,11 @@ +0.164 "Kupiansk" (Куп'янськ) 2025-08-15 + +* The main changes of this release are: + - fix article part detection where multipart articles + were detected as many articles instaed of one article + with many parts. + - fix crash when displaying emoticon replacement + 0.163 "Kryvyi Rih" (Кривий Ріг) 2025-05-25 * The main changes of this release are: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pan-v0.163/README.org new/pan-v0.164/README.org --- old/pan-v0.163/README.org 2025-05-25 15:27:28.000000000 +0200 +++ new/pan-v0.164/README.org 2025-08-15 15:37:08.000000000 +0200 @@ -10,6 +10,7 @@ - [[#installation-1][Installation]] - [[#build-options][Build options]] - [[#debug-build][Debug build]] + - [[#running-pan][Running pan]] - [[#cc-language-server-support][CC++ language server support]] - [[#tls-support][TLS support]] - [[#upgrading][Upgrading]] @@ -124,7 +125,8 @@ On Fedora, dependencies can be installed with: #+BEGIN_SRC shell :results verbatim - sudo dnf install cmake gtk3-devel glib-devel gmime30-devel gspell-devel gnutls-devel + sudo dnf install gcc gcc-c++ ninja-build libassuan-devel \ + cmake gtk3-devel glib-devel gmime30-devel gspell-devel gnutls-devel #+END_SRC Note that I work on Debian and I did not test this instructions on @@ -221,6 +223,25 @@ cmake --build debug-build -j 8 #+END_SRC +** Running pan + +After compilation, you **must** run pan from the repository root: + +#+BEGIN_SRC shell :results verbatim +./debug-build/pan/gui/pan +#+END_SRC + +If pan was installed with a package, you can run pan from anywhere. + +Why ? Pan searches for icon in 2 locations: +- =./pan/icons= which is useful when hacking pan +- =$PAN_SYSTEM_ICON_PATH= (which is =/usr/share/pan/icons= on + Linux). This directory should be provided by pan package. + +When icons are not found, pan shows this kind of messages: +#+begin_example +Unable to load icon_article_read.png icon. Use --debug flag for more details +#+end_example ** CC++ language server support @@ -259,7 +280,19 @@ * How to report bugs -For details on how to report bugs, see [[http://pan.rebelbase.com/bugs/][Pan bug report page]]. +The first question to answer is where does this bug comes from ? +Depending on how you installed Pan, a bug can come from Pan or +Pan packaging. + +To find out, you can: +1. Try to reproduce the bug with Pan compiled from source +2. Reach out to the maintainer of your Pan package +3. Ask on [[http://lists.nongnu.org/mailman/listinfo/pan-users][pan-users]] mailing list + +Once you're pretty sure you've found a bug coming from Pan, you should: +1. check if this bug already exists [[https://gitlab.gnome.org/GNOME/pan/-/issues][Pan issue page]] +2. If yes, add a comment there +3. If no, create a new issue. * Help Wanted diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pan-v0.163/pan/data-impl/xover.cc new/pan-v0.164/pan/data-impl/xover.cc --- old/pan-v0.163/pan/data-impl/xover.cc 2025-05-25 15:27:28.000000000 +0200 +++ new/pan-v0.164/pan/data-impl/xover.cc 2025-08-15 15:37:08.000000000 +0200 @@ -123,10 +123,11 @@ part = parts = 1; } - /* but if it's starting the subject with "Re:" and doesn't - have many lines, it's probably a followup to a part, rather - than an actual part. */ - if (Article::has_reply_leader(subj) && line_count<100) + /* but if it's starting the subject with "Re:" and doesn't have + many lines, it's probably a followup to a part, rather than an + actual part. Note that server may provide a bogus zero line + count in which case the last test is misleading. */ + if (Article::has_reply_leader(subj) && line_count != 0 && line_count < 100) part = parts = 0; /* Subjects containing (0/N) aren't part of an N-part binary; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pan-v0.163/pan/gui/body-pane.cc new/pan-v0.164/pan/gui/body-pane.cc --- old/pan-v0.163/pan/gui/body-pane.cc 2025-05-25 15:27:28.000000000 +0200 +++ new/pan-v0.164/pan/gui/body-pane.cc 2025-08-15 15:37:08.000000000 +0200 @@ -810,7 +810,12 @@ GdkPixbuf *pixbuf) { g_assert(! text.empty()); - g_assert(pixbuf != nullptr); + if (pixbuf == nullptr) + { + // emoticon icon was not found. No need to crash pan + std::cout << "No icon loaded for emoticon " << text << std::endl; + return; + } GtkTextTagTable *tags(gtk_text_buffer_get_tag_table(buffer)); GtkTextTag *url_tag(gtk_text_tag_table_lookup(tags, "url")); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pan-v0.163/pan/gui/header-pane.cc new/pan-v0.164/pan/gui/header-pane.cc --- old/pan-v0.163/pan/gui/header-pane.cc 2025-05-25 15:27:28.000000000 +0200 +++ new/pan-v0.164/pan/gui/header-pane.cc 2025-08-15 15:37:08.000000000 +0200 @@ -1972,168 +1972,115 @@ } } // namespace -void HeaderPane ::build_tree_columns() -{ +void HeaderPane::build_tree_columns() { GtkTreeView *tree_view(GTK_TREE_VIEW(_tree_view)); int const xpad(_prefs.get_int("tree-view-row-margins", 1)); // out with the old columns, if any GList *old_columns = gtk_tree_view_get_columns(tree_view); - for (GList *l = old_columns; l != nullptr; l = l->next) - { + for (GList *l = old_columns; l != nullptr; l = l->next) { gtk_tree_view_remove_column(tree_view, GTK_TREE_VIEW_COLUMN(l->data)); } g_list_free(old_columns); - // get the user-configurable column list - const std::string columns(_prefs.get_string( - "header-pane-columns", "state,action,subject,score,author,lines,date")); - StringView v(columns), tok; - while (v.pop_token(tok, ',')) - { - std::string const &name(tok.to_string()); - const std::string width_key = - std::string("header-pane-") + name + "-column-width"; - GtkTreeViewColumn *col(nullptr); - - if (name == "state") - { - GtkCellRenderer *r = GTK_CELL_RENDERER(g_object_new( - GTK_TYPE_CELL_RENDERER_PIXBUF, "xpad", xpad, "ypad", 0, nullptr)); - col = gtk_tree_view_column_new(); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - // used a fixed width since the column is not resizable - gtk_tree_view_column_set_fixed_width (col, 24); - gtk_tree_view_column_set_resizable(col, false); - gtk_tree_view_column_pack_start(col, r, false); - gtk_tree_view_column_set_cell_data_func( - col, r, render_state, nullptr, nullptr); - gtk_tree_view_column_set_sort_column_id(col, COL_STATE); - gtk_tree_view_append_column(tree_view, col); + // Column configuration structure + struct ColumnConfig { + char const *name; + char const *title; + GType renderer_type; + bool resizable; + int default_width; + int sort_column_id; + GtkTreeCellDataFunc data_func; + bool right_align; + bool is_expander; + }; + + // Define all column configurations + ColumnConfig configs[] = { + {"state", nullptr, GTK_TYPE_CELL_RENDERER_PIXBUF, false, 24, COL_STATE, + render_state, false, false}, + {"action", nullptr, GTK_TYPE_CELL_RENDERER_PIXBUF, false, 24, -1, + render_action, false, false}, + {"subject", _("Subject"), GTK_TYPE_CELL_RENDERER_TEXT, true, 400, + COL_SUBJECT, render_subject, false, true}, + {"score", _("Score"), GTK_TYPE_CELL_RENDERER_TEXT, true, 50, COL_SCORE, + render_score, true, false}, + {"author", _("Author"), GTK_TYPE_CELL_RENDERER_TEXT, true, 133, + COL_SHORT_AUTHOR, render_author, false, false}, + {"lines", _("Lines"), GTK_TYPE_CELL_RENDERER_TEXT, true, 60, COL_LINES, + render_lines, true, false}, + {"bytes", _("Bytes"), GTK_TYPE_CELL_RENDERER_TEXT, true, 80, COL_BYTES, + render_bytes, true, false}, + {"date", _("Date"), GTK_TYPE_CELL_RENDERER_TEXT, true, 120, COL_DATE, + render_date, false, false}}; + + // Helper function to create a column + auto create_column = [&](ColumnConfig const &config) -> GtkTreeViewColumn * { + std::string const width_key = + std::string("header-pane-") + config.name + "-column-width"; + + GtkCellRenderer *r; + if (config.renderer_type == GTK_TYPE_CELL_RENDERER_PIXBUF) { + r = GTK_CELL_RENDERER( + g_object_new(config.renderer_type, "xpad", xpad, "ypad", 0, nullptr)); + } else { + if (config.right_align) { + r = GTK_CELL_RENDERER(g_object_new(config.renderer_type, "xpad", xpad, + "ypad", 0, "xalign", 1.0, nullptr)); + } else { + r = GTK_CELL_RENDERER(g_object_new(config.renderer_type, "xpad", xpad, + "ypad", 0, nullptr)); + } + ellipsize_if_supported(G_OBJECT(r)); } - else if (name == "action") - { - GtkCellRenderer *r = GTK_CELL_RENDERER(g_object_new( - GTK_TYPE_CELL_RENDERER_PIXBUF, "xpad", xpad, "ypad", 0, nullptr)); + + GtkTreeViewColumn *col; + if (config.title) { + col = gtk_tree_view_column_new_with_attributes(config.title, r, nullptr); + } else { col = gtk_tree_view_column_new(); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - // used a fixed width since the column is not resizable - gtk_tree_view_column_set_fixed_width (col, 24); - gtk_tree_view_column_set_resizable(col, false); gtk_tree_view_column_pack_start(col, r, false); - gtk_tree_view_column_set_cell_data_func( - col, r, render_action, nullptr, nullptr); - gtk_tree_view_append_column(tree_view, col); - } - else if (name == "subject") - { - GtkCellRenderer *r = GTK_CELL_RENDERER(g_object_new( - GTK_TYPE_CELL_RENDERER_TEXT, "xpad", xpad, "ypad", 0, nullptr)); - ellipsize_if_supported(G_OBJECT(r)); - col = gtk_tree_view_column_new_with_attributes(_("Subject"), r, nullptr); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(col, _prefs.get_int(width_key, 400)); - gtk_tree_view_column_set_resizable(col, true); - gtk_tree_view_column_set_sort_column_id(col, COL_SUBJECT); - gtk_tree_view_column_set_cell_data_func( - col, r, render_subject, this, nullptr); - gtk_tree_view_append_column(tree_view, col); - gtk_tree_view_set_expander_column(tree_view, col); - } - else if (name == "score") - { - GtkCellRenderer *r = - GTK_CELL_RENDERER(g_object_new(GTK_TYPE_CELL_RENDERER_TEXT, - "xpad", - xpad, - "ypad", - 0, - "xalign", - 1.0, - nullptr)); - ellipsize_if_supported(G_OBJECT(r)); - col = gtk_tree_view_column_new_with_attributes(_("Score"), r, nullptr); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(col, _prefs.get_int(width_key, 50)); - gtk_tree_view_column_set_resizable(col, true); - gtk_tree_view_column_set_sort_column_id(col, COL_SCORE); - gtk_tree_view_column_set_cell_data_func( - col, r, render_score, this, nullptr); - gtk_tree_view_append_column(tree_view, col); - } - else if (name == "author") - { - GtkCellRenderer *r = GTK_CELL_RENDERER(g_object_new( - GTK_TYPE_CELL_RENDERER_TEXT, "xpad", xpad, "ypad", 0, nullptr)); - ellipsize_if_supported(G_OBJECT(r)); - col = gtk_tree_view_column_new_with_attributes(_("Author"), r, nullptr); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(col, _prefs.get_int(width_key, 133)); - gtk_tree_view_column_set_resizable(col, true); - gtk_tree_view_column_set_sort_column_id(col, COL_SHORT_AUTHOR); - gtk_tree_view_column_set_cell_data_func( - col, r, render_author, this, nullptr); - gtk_tree_view_append_column(tree_view, col); - } - else if (name == "lines") - { - GtkCellRenderer *r = - GTK_CELL_RENDERER(g_object_new(GTK_TYPE_CELL_RENDERER_TEXT, - "xpad", - xpad, - "ypad", - 0, - "xalign", - 1.0, - nullptr)); - ellipsize_if_supported(G_OBJECT(r)); - col = gtk_tree_view_column_new_with_attributes(_("Lines"), r, nullptr); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(col, _prefs.get_int(width_key, 60)); - gtk_tree_view_column_set_resizable(col, true); - gtk_tree_view_column_set_sort_column_id(col, COL_LINES); - gtk_tree_view_column_set_cell_data_func( - col, r, render_lines, this, nullptr); - gtk_tree_view_append_column(tree_view, col); } - else if (name == "bytes") - { - GtkCellRenderer *r = - GTK_CELL_RENDERER(g_object_new(GTK_TYPE_CELL_RENDERER_TEXT, - "xpad", - xpad, - "ypad", - 0, - "xalign", - 1.0, - nullptr)); - ellipsize_if_supported(G_OBJECT(r)); - col = gtk_tree_view_column_new_with_attributes(_("Bytes"), r, nullptr); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(col, _prefs.get_int(width_key, 80)); - gtk_tree_view_column_set_resizable(col, true); - gtk_tree_view_column_set_sort_column_id(col, COL_BYTES); - gtk_tree_view_column_set_cell_data_func( - col, r, render_bytes, this, nullptr); - gtk_tree_view_append_column(tree_view, col); - } - else if (name == "date") - { - GtkCellRenderer *r = GTK_CELL_RENDERER(g_object_new( - GTK_TYPE_CELL_RENDERER_TEXT, "xpad", xpad, "ypad", 0, nullptr)); - ellipsize_if_supported(G_OBJECT(r)); - col = gtk_tree_view_column_new_with_attributes(_("Date"), r, nullptr); - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(col, _prefs.get_int(width_key, 120)); - gtk_tree_view_column_set_resizable(col, true); - gtk_tree_view_column_set_sort_column_id(col, COL_DATE); - gtk_tree_view_column_set_cell_data_func( - col, r, render_date, this, nullptr); - gtk_tree_view_append_column(tree_view, col); + + gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_fixed_width( + col, _prefs.get_int(width_key, config.default_width)); + gtk_tree_view_column_set_resizable(col, config.resizable); + + if (config.sort_column_id != -1) { + gtk_tree_view_column_set_sort_column_id(col, config.sort_column_id); } - g_object_set_data_full( - G_OBJECT(col), "column-width-key", g_strdup(width_key.c_str()), g_free); + gtk_tree_view_column_set_cell_data_func(col, r, config.data_func, this, + nullptr); + + g_object_set_data_full(G_OBJECT(col), "column-width-key", + g_strdup(width_key.c_str()), g_free); + + return col; + }; + + // get the user-configurable column list + const std::string columns(_prefs.get_string( + "header-pane-columns", "state,action,subject,score,author,lines,date")); + StringView v(columns), tok; + + while (v.pop_token(tok, ',')) { + std::string const &name(tok.to_string()); + + // Find the configuration for this column + for (const auto& config : configs) { + if (name == config.name) { + GtkTreeViewColumn *col = create_column(config); + gtk_tree_view_append_column(tree_view, col); + + if (config.is_expander) { + gtk_tree_view_set_expander_column(tree_view, col); + } + break; + } + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pan-v0.163/pan/gui/load-icon.cc new/pan-v0.164/pan/gui/load-icon.cc --- old/pan-v0.163/pan/gui/load-icon.cc 2025-05-25 15:27:28.000000000 +0200 +++ new/pan-v0.164/pan/gui/load-icon.cc 2025-08-15 15:37:08.000000000 +0200 @@ -24,15 +24,17 @@ // try system icon pixbuf = load_icon_from_path(file_name, PAN_SYSTEM_ICON_PATH); - if (pixbuf != nullptr) { + if (pixbuf != nullptr) + { return pixbuf; } - std::cerr << "Unable to load " << file_name << " icon. Use --debug flag for more details"; + std::cerr << "Unable to load " << file_name + << " icon. Use --debug flag for more details" << std::endl; return nullptr; } -GdkPixbuf *load_icon_from_path(const gchar *file_name, const gchar *icon_dir) +GdkPixbuf *load_icon_from_path(gchar const *file_name, gchar const *icon_dir) { GError *error = NULL; gchar *icon_path = g_build_filename(icon_dir, file_name, NULL); @@ -40,7 +42,8 @@ if (error != NULL) { - pan_debug("Unable to load icon " << file_name << " from " << icon_dir << ": " << error->message); + pan_debug("Unable to load icon " << file_name << " from " << icon_dir + << ": " << error->message); g_error_free(error); }