Skip to content

Sort installed mods list alphabetically#29325

Merged
chennes merged 6 commits intoFreeCAD:mainfrom
zeel2104:fix-sort-installed-mods-28927
Apr 22, 2026
Merged

Sort installed mods list alphabetically#29325
chennes merged 6 commits intoFreeCAD:mainfrom
zeel2104:fix-sort-installed-mods-28927

Conversation

@zeel2104
Copy link
Copy Markdown
Contributor

Sort the Installed mods list in About > Version alphabetically while keeping the existing entry formatting unchanged.

Issues

Fixes #28927

Before and After Images

Not applicable for this small text-ordering change in the About > Version output.

Testing

  • Built FreeCAD on Windows using pixi
  • Launched FreeCAD successfully
  • Verified the About > Version path still works
  • Confirmed the installed mods list is now sorted alphabetically in the generated output

@github-actions github-actions Bot added the Mod: Core Issue or PR touches core sections (App, Gui, Base) of FreeCAD label Apr 13, 2026
@maxwxyz maxwxyz added the Type: Feature FR for improvements or new features label Apr 13, 2026
@maxwxyz maxwxyz added this to the 1.2 milestone Apr 13, 2026
@maxwxyz maxwxyz moved this from Queue to Merge Meeting in Merge Queue Apr 13, 2026
Comment thread src/App/ProgramInformation.cpp Outdated
std::string entry;
};

std::optional<AddonInfo> getModuleInfo(const std::string& path)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
std::optional<AddonInfo> getModuleInfo(const std::string& path)
static std::optional<AddonInfo> getModuleInfo(const std::string& path)

@ElementW
Copy link
Copy Markdown
Contributor

Tested, works
My test list changes from

Installed mods:
  * Quetzal 1.8.9
  * DynamicData 2.77.0
  * Plot 2025.10.29

to

Installed mods:
  * DynamicData 2.77.0
  * Plot 2025.10.29
  * Quetzal 1.8.9

@chennes
Copy link
Copy Markdown
Member

chennes commented Apr 13, 2026

Thanks for the PR, @zeel2104 -- can you explain the design decision to make a struct with two strings in it, instead of just creating a vector of strings and sorting that?

@FEA-eng
Copy link
Copy Markdown
Contributor

FEA-eng commented Apr 13, 2026

I can't reproduce the issue this PR fixes. For me, they are already sorted alphabetically (even though I installed them in a different order on purpose). Perhaps it's OS-dependent? Or depends on when they were installed?

OS: Windows 11 build 26200
Architecture: x86_64
Version: 1.2.0dev.20260407 (Git shallow)
Build date: 2026/04/07 22:56:13
Build type: Release
Branch: (HEAD detached at 6db886fe0)
Hash: 6db886fe0e79bf060ffeaa50198da25702a17e31
Python 3.11.15, Qt 6.8.3, Coin 4.0.8, Vtk 9.3.1, boost 1_86, Eigen3 3.4.0, PySide 6.8.3
shiboken 6.8.3, xerces-c 3.3.0, IfcOpenShell 0.8.2, OCC 7.8.1
Locale: Polish/Poland (pl_PL)
Stylesheet/Theme/QtStyle: FreeCAD.qss/FreeCAD Light/
Navigation Style/Orbit Style/Rotation Mode: Blender/Rounded Arcball/Window center
Logical DPI/Physical DPI/Pixel Ratio: 96/81.5973/1
Installed mods:
  * A2plus 0.4.68
  * Assembly4 0.60.6
  * Cables Workbench 0.3.5
  * CfdOF 1.34.13
  * Curves workbench 0.6.71
  * Defeaturing Workbench 1.3.1
  * Road 2026.4.11
  * SheetMetal Workbench 0.8.10

@ElementW
Copy link
Copy Markdown
Contributor

@FEA-eng It is OS-dependent, specifically filesystem-dependent.
The mods list order is determined by filesystem enumeration order, where NT doesn't guarantee sorted enumeration (see FindFirstFile remarks) but NTFS is known to sort files internally, as is mentioned in this article by Raymond Chen.

@zeel2104
Copy link
Copy Markdown
Contributor Author

@chennes
I used a small struct to keep the sort key separate from the rendered output.

The displayed line is not just the addon name: it may also include the version, disabled state, and preserves the existing formatted entry text. Sorting only a vector<string> would sort by the full rendered line, which ties ordering to presentation details instead of the addon display name itself.

With the struct, name is only the sort key and entry is the final output line. That kept the sorting logic explicit and avoided reparsing formatted text after sorting.

If you prefer, I can refactor it to a more compact representation like std::pair<QString, std::string>.

@chennes
Copy link
Copy Markdown
Member

chennes commented Apr 13, 2026

That feels over-engineered to me: this is effectively debugging output, with a well-structured, straightforward format. I suggest simply renaming addModuleInfo to getModuleInfoString, returning a std::string instead of appending to the stream, and storing those strings in a vector. Sort the vector, then spit it out. No custom struct, no new method, minimal code intervention. The overarching principle of separating data from presentation is a good one, but it's overcomplicating this simple task.

@zeel2104
Copy link
Copy Markdown
Contributor Author

@chennes
I simplified it as suggested: the helper now returns a formatted std::string, the code stores those strings in a std::vector<std::string>, sorts the vector, and then writes the entries out. That removes the custom struct and keeps the change more local.

Comment thread src/App/ProgramInformation.cpp Outdated
Comment on lines 155 to 160
void ProgramInformation::addModuleInfo(std::stringstream& str, const std::string& path)
{
QString modPath = QString::fromStdString(path);
QFileInfo mod(modPath);
if (mod.isHidden()) { // Ignore hidden directories
return;
auto moduleInfo = getModuleInfoString(path);
if (!moduleInfo.empty()) {
str << moduleInfo;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we can just get rid of this whole function, it's unnecessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - removed addModuleInfo entirely since it’s redundant now.

@chennes
Copy link
Copy Markdown
Member

chennes commented Apr 14, 2026

You can avoid the large diff by putting the function back where the original one was, so it's clear at a glance that this is a nice, small change: basically the function signature and a little bit of plumbing.

@zeel2104
Copy link
Copy Markdown
Contributor Author

Done. I moved getModuleInfoString() back to the original helper location so the diff is easier to review at a glance. The behavior is unchanged.

@chennes
Copy link
Copy Markdown
Member

chennes commented Apr 21, 2026

Sorry I wasn't clearer in my last comment: the original function, addModuleInfo, was on line 111. If you move the "new" function, getModuleInfoString, to that exact same location, it will be obvious at a glance (and in a git blame) that there are actually very few changes here. The objective of the whole exercise is that this should be a very small, self-contained fix, and the overall size of the PR should reflect that.

@zeel2104
Copy link
Copy Markdown
Contributor Author

@chennes
Done

@chennes chennes enabled auto-merge (squash) April 21, 2026 18:09
@chennes chennes added Approved: Code Quality The PR was checked for code quality and approved Approved: Tested The PR was manually tested and approved labels Apr 21, 2026
@maxwxyz maxwxyz moved this from Merge Meeting to Approved in Merge Queue Apr 22, 2026
@chennes chennes merged commit 3bc8ccf into FreeCAD:main Apr 22, 2026
36 of 37 checks passed
@github-project-automation github-project-automation Bot moved this from Approved to Done in Merge Queue Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Approved: Code Quality The PR was checked for code quality and approved Approved: Tested The PR was manually tested and approved Mod: Core Issue or PR touches core sections (App, Gui, Base) of FreeCAD Type: Feature FR for improvements or new features

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Installed Mods list should be sorted Alphabetically.

5 participants