[GSoC 2024] - Command-Line Preferences Manipulation

Hello everyone!
I hope you are all doing great,

I am Ahmed Khaled, a second-year Computer Science Student from Egypt,
I am thrilled about the opportunity to contribute to FreeCAD through the GSoC “Command-Line Preferences Manipulation” Project, the idea of working on automating the FreeCAD installation process using a command-line tool is very exciting, and this project aligns with my knowledge of C++ and my interest towards working with command-line tools, additionally I find CAD software very interesting to work on

I have already browsed through the FreeCAD preferences stored in https://github.com/FreeCAD/FreeCAD/tree/main/src/Gui/PreferencePackTemplates, and I created a simple external C++ Command-line tool that can read/modify the XML preference values given a preference key, for example, writing “cli_config_tool Preferences.Mod.Arch.WallColor 543” would search in all the files in the PreferencePackTemplates folder and find in which file the key “Preferences.Mod.Arch.WallColor” exists, and then edits the value of this key to “543”, I was wondering if this is how you expect the tool to work in terms of modifying the preferences (Meaning that the tool will be given a key and a value to insert in that key),

I am also curious about a few more details:

  • Are all .cfg files stored in a single folder? (I also saw some .cfg files in https://github.com/FreeCAD/FreeCAD/tree/main/src/Gui/PreferencePacks, so probably this is not true, but I would still like to check how many folders is the tool required to edit in.


  • Do all preferences start with Root then BaseApp?


  • Are these the only datatypes you have for preferences (FCBool, FCUInt, FCText, and FCFloat)?


  • Am I expected to backup the .cfg files somehow before modifying them?


  • In the project description you mentioned the tool having the ability to create/delete preferences, I was wondering how you expect these 2 operations to be done.

Of course, currently, this Command-line tool is external, but since I have more experience using C++ than Python, I am open to either creating the command-line tool externally or to add it in the FreeCAD executable, I would greatly appreciate any guidance that I can get on what I should try to do currently to get a better understanding of the project and to show Initiative towards working on it, Until I get a response I will download FreeCAD and start checking the preferences from the GUI point of view and I will try to understand the command line options in the FreeCAD executable,
Thanks in advance, I am looking forward to discussing further details and I am very excited to contribute!

You have correctly answered the question yourself

  • Do all preferences start with Root then BaseApp?

No. On my mac the config files are store in ~/Library/Preferences/FreeCAD and somewhere under ~/Library/Application\ Support/FreeCAD
Furthermore, I’m not sure if you want to handle also files handling the Path toolbit libraries.

Thanks for taking the time to reply, I apologize for not clarifying the second question properly, I meant to ask if all preferences start with Root then BaseApp in the Preferences XML hierarchy/tree.

Example:

Also, nothing about the Path toolbit libraries was mentioned in the project description, so I believe initially I am not required to handle them.

the templates do not cover all available preferences for freecad, they are only templates that set certain things. Rather than just looking at some config files and tryign to reverse engineer from that I would advice you to check the actual code dealing with preferences.

Do all preferences start with Root then BaseApp?

No, there’s also Root/Tux at least and any addon could add other arbitrary groups I think. There is also separation between user and system config although I don’t quite understand what is the purpose of that since they are both stored in the same directory. In the system config groups are usually directly bellow Root with no BaseApp.

Try using freecad, open the preference page and click ok then close FreeCAD, this would populate your preferences with a lot of things and I feel that would be abetter reference than the preference packs. What OS are you using? You can find were your preferences are stored by running

FreeCAD.getUserConfigDir()

in freecad’s python console

also, I would expect a commanline utility to modify the user preferences, not the shipped preference packs. I guess it would be nice to have the ability to create and apply preference packs too.

btw, it is already somewhat possible to modify freecad’s preferences from commandline:

python -c "import freecad; FreeCAD.ParamGet(\"User parameter:BaseApp/Preferences/OpenGL\").SetBool(\"UseSoftwareOpenGL\", 1); FreeCAD.saveParameter()"

Hello Everyone.
I am Harshita Saraswat, a 3rd year undergraduate student at Chandigarh University, India. I am pursuing a Bachelor’s degree in Computer Science and Engineering.
I have been working with Python for the past 3 years and I have also worked with C++. I have been working with FreeCAD for the past 3 months contributing to the Component Management System project. I have also worked on command-line tools for my personal projects and I think I can contribute to this project.

I am excited for the opportunity of working on command-line preferences manipulation project and with FreeCAD. I have gone through the project description and I think it is a great project to work on. I have also been working on command-line tools and I think I can contribute to this project.
I have gone through the source code of both Python and C++ side of the project and I think I have a good understanding of that the the functions and classes being used for the preferences manipulation.
I am primarily a Python developer but I have also worked on C++ and I think I can contribute to any, the Python and C++ side of the project.
I have experience in creating CLI applications in Python and I think I can create a good CLI application for the project.

I have a few questions regarding the project, I would be grateful if you could answer them. I have gone through the source code and I think I have found some answers but I would like to confirm them.

  1. How should the final command-line tool look like?
    Ans: I think it should be a command-line tool that allows CRUD operations on FreeCAD preferences(the cfg files). Maybe Delete operation is not desired?

Should it look something like this?

freecad-preferences --scope <user|global> --parameter <parameter_name> --value <value>

example:

  1. for getting the value of a parameter.
freecad-preferences --scope user --parameter BaseApp:Preferences:Macro:GuiAsComment
  1. for crating a new parameter or updating an existing parameter.
freecad-preferences --scope user --parameter BaseApp:Preferences:Macro:GuiAsComment --value true
  1. Where are the .cfg files located?
    Ans: User config file which resides at ~/.config/FreeCAD in my system(fond it using FreeCAD.getUserConfigDir()). But is there any other location where the .cfg files are located that is to be used for FreeCAD command-line preferences manipulation?
    There are other .cfg files in the same directory but I think those files are not to be manipulated. I think the user.cfg is the file that is to be manipulated.
  2. What is the purpose of PreferencePackTemplates & PreferencePack?
    Ans: I think these are the presets for the preferences for various MODULES in FreeCAD. Is it like some defaults or system wide preferences for the modules?
  3. What configuration files are to be used for FreeCAD command-line preferences manipulation?
    Ans: In the User config file, I assume all the default preferences of all the mods of system are stored in this file(I did some random searches and compared the parameters in user.cfg and cfg files form PreferencePack).
    I also found that the FreeCAD.ParamGet() in python and Application::GetParameterSet in C++ is used to get the parameters from the .cfg file. I think this is the file that is to be manipulated.
  4. Can there be any set of preferences for FreeCAD command-line manipulation(as in can any preferences be created and put in the cfg file or there is an internal guideline for valid types)?
    Ans: Could not find much information on this. I followed back the FreeCAD.ParamGet() and found that it is a wrapper(defined in src/App/ApplicationPy.cpp) around the Application::GetParameterGroupByPath.

I also followed Application::sSaveParameter which uses Application::GetParameterSet to first looks if the parameter exists first then saves it. But from where is it searching for the valid parameters? I think it is searching in the .cfg file.

User preferences could usually modified using Python, so probably it is not a big hassle to invoke freecad with a python script that should do the job, as said by adrianinsaval above.

About location it depends heavily on which OS you are and if you have not overridden the settings, (I do this every time to have different user configuration for developing things for different customers) as suggested in:

https://wiki.freecad.org/Download#Notes_for_GNU.2FLinux_users


See maybe:

https://wiki.freecad.org/Macro_findConfigFiles/en

or:

https://wiki.freecad.org/Start_up_and_Configuration

see Environment Variables and Configuration set Sections.

Hope it helps.

Kind Regards

Carlo D.

Thank You for the reference articles.

https://wiki.freecad.org/Start_up_and_Configuration

see Environment Variables and Configuration set Sections.

I went through them and now have a better understand of what variables are are set and how on various Operating systems.
But I still have doubt in few of the my questions:-

What is the purpose of PreferencePackTemplates & PreferencePack?

What configuration files are to be used for FreeCAD command-line preferences manipulation?

Can there be any set of preferences for FreeCAD command-line manipulation(as in can any preferences be created and put in the cfg file or there is an internal guideline for valid types)?

Sorry but I don’t have this in deep knowledge.

Kind Regards

Carlo D.

The Preference Pack Templates are the default values of a limited subset of available options. There is no global database, preferences can be created “on the fly”
at any time.

Thanks chennes for the clarification.

As suggested by onekk, I went through https://wiki.freecad.org/Macro_findConfigFiles/en
Is says about resetting freecad’s setting by renaming the user.cfg and system.cfg files files to restore the setting as freecad will automatically create the files with the default config. So is it so that all the preferences that exists or can exist will be present in these files? If this is not the case then how to fetch those if not from PreferencePackTemplates & PreferencePack?

Not exactly the file hold the preference that are set, not all the preferences that exist are in the configuration file.

About how to find all the existing preferences that are related to “Preference Packs” (PP for short) I don’t know, if there is a way to do so, as a “PP” could set many preferences.

A rough guess is that to know what preferences are set by a “PP” you should scan the “PP” file and see what the “PP” is setting.

Kind regards

Carlo D.

The Preference Pack templates are hand-generated default value lists for the variable that I thought most likely to be included in Preference Packs. I basically generated them by looking in the code itself for calls to GetParameterGroupByPath and reading the code that accesses the variable that call creates. Calls to SetBool, SetInt, SetUnsigned, SetFloat, SetASCII explicitly create a new entry in the User.cfg file for a new preference. But it is critical to note that this is not required to use a preference: the Get* allow one to get a non-existent preference, and return a specified default value if that preference is not in the database. That is the most common use in our code, and demonstrates how there cannot be a single, global list of all preferences, because at any time a developer can create a new one simply by referring to it.

As an example: search the code for “CustomMaterialsDir” – you will find that there is no explicit “Set” method for this configuration entry. If the user never opens the Materials preferences dialog, it is never set. The call that accesses it,

param->GetASCII("CustomMaterialsDir", "")

will return the empty string, “”, because that is the default value specified directly in that call to GetASCII. If the user opens the Materials preferences panel, however, and then saves their preferences, that panel will end up creating an entry in User.cfg, which will override the default (even if they don’t change the value and leave it at “” in the preferences panel).

Thanks for the details everyone.
If there is no such fixed preferences saved somewhere, and developer can create any preference with any default value if not found, the desired plan of development seem to me is more leaning away from the DECLARATIVE implementation and more towards using the existing function to set and the parameters and make a wrapper around it.
This way the CL Preferences Manager can be more dynamic and powerful. But I am not sure about the security implications of such implementation. There will be no control on what preferences are created/overridden or how many of them are created.

I think a user can already do much more serious harm with the command line version of FreeCAD, simply by running a Python script that does anything we can dread… Modifying the preferences in itself is not very dangerous, and in any case any script could manipulate the config files outside FreeCAD already. So I wouldn’t worry about that point. This is mostly about being more convenient, it does not offer new possibilities that did not exist before

Happy to announce that Harshita_Saraswat has been selected as a GSoC project for FreeCAD this year! She will be mentored by jnxd and pieterhijma. Glad to have you working on this!

Harshita, I suggest you post here the plan you submitted to GSoC, so everybody can see and comment.

It goes without saying but I would suggest also you do your best to keep communicating and posting here as much as possible on your findings and advancements. Projects that do that generally get a lot of good feedback and it makes things fly higher.

Your mentors will contact you later on to see how you guys want to work and setup the next steps.

I am also acting as the main FreeCAD GSoC admin, so don’t hesitate to get back to me if you meet any problem your mentors cannot help with. I’ll also do my best to always notify everybody and make sure all deadlines are met.

Looking forward to this!

Thankyou yorik. I am very exited to work on the project this summer. I will start the main work after 19th may as by then I would have wrapped up my semester examinations. I am posting the project proposal in the post below.

Command-Line Preferences Manipulation

Brief summary of Project
The project aims to create a Command-line utility tool to manage and manipulate FreeCAD
preferences from outside the FreeCAD application. This tool is intended to be used for installing
and configuring the FreeCAD all through the scripts.

Project Description (Detailed)

Introduction
The FreeCAD Preference Manipulation CLI Tool will be designed to streamline the customization
of your CAD software directly from the command line interface, eliminating the need for complex
graphical interfaces. It will facilitate the management of FreeCAD’s preferences, enabling users to
perform various tasks such as modifying existing configurations, accessing preferences stored in
files, and removing unnecessary settings. Whether users are adjusting preferences for personal use
or system-wide configurations affecting all FreeCAD users, this tool will offer comprehensive
control. Users will be able to swiftly create tailored preferences and make precise adjustments
without the inconvenience of additional windows, enhancing workflow efficiency.
In scripts for installing FreeCAD, the FreeCAD Preference Manipulation CLI Tool will play a
crucial role in automating the setup process and configuring FreeCAD installations according to
specific preferences.
The tool will be developed in Python programming language which FreeCAD supports so that it
can be easy incorporated in the current system. Python can easily interface and parse the
configuration files (i.e. .cfg files) which uses XML version 1.0 for storing preferences and can
manipulate it.

Information and current state
At present the FreeCAD’s python library has a preference manipulation function that can be used
for managing the preferences but it cannot directly be used in a terminal of used in scripts to
automate installations.

Functional Requirements

Configuration file interface
To interface with FreeCAD’s configuration files, which are typically in XML format, using Python,
we can utilize the built-in XML parsing library called xml.dom. This library allows us to parse
XML files, navigate through the XML tree structure, and manipulate XML elements and attributes.
To interface with XML configuration files in Python using the xml.dom module, we can follow
these steps:
• Parse the XML File: Use the xml.dom.minidom module to parse the XML file and create a
DOM (Document Object Model) tree.
• Navigate the DOM Tree: Traverse the DOM tree to locate and manipulate the desired
elements and attributes.
• Modify Preferences: Update the values of specific elements or attributes to reflect the
desired preferences.
• Write Changes to File: Serialize the modified DOM tree back to an XML file.
Screenshot 2024-05-05 144959.png
Command Line Tool
The FreeCAD Preference Manipulation CLI Tool is made to make changing FreeCAD settings
easier by using commands you type into the computer. It’s like having a helper that can quickly
adjust how FreeCAD works without needing to click around in the program. This tool is all about
saving time and keeping things the same across different projects or places where you use
FreeCAD.
Basically, it lets you tell FreeCAD what you want it to do without having to manually change
settings every time. You can create simple instructions, called scripts, that tell FreeCAD what
settings to change. This makes it handy for making FreeCAD work just the way you like it, no
matter what you’re working on or where you’re working from.
Using it, one can perform various operations to manage FreeCAD settings efficiently. These
operations include:
• Modifying Preferences: You can change FreeCAD settings such as default file paths,
interface preferences, unit configurations, macro settings, and more.
• Automation: By scripting preference modifications, you can automate repetitive tasks and
ensure consistency across projects. This helps save time and minimizes the risk of errors.
• Integration with Workflows: You can integrate preference adjustments into larger
automation workflows or shell scripts, allowing seamless management of FreeCAD
configurations alongside other processes.
• Version Control: Scripting preference changes enables version control of configuration
adjustments, making it easier to track changes and reproduce configurations across different
setups.
• Customization: Users can tailor FreeCAD settings to specific use cases or workflows by
scripting modifications according to their needs, enhancing productivity and usability.
Screenshot 2024-05-05 145104.png
Scriptablity
In the future, the FreeCAD Preference Manipulation CLI Tool will offer easy-to-use scriptability,
making it simple to automate preference adjustments directly from the command line. This tool will
streamline configuration management by allowing users to create scripts that modify FreeCAD
preferences, saving time and ensuring consistency across projects and environments. By defining
preference modifications in scripts, users will be able to smoothly integrate FreeCAD configuration
changes into larger automation workflows or shell scripts, boosting efficiency and minimizing the
risk of mistakes. Additionally, scriptability will support version control of configuration changes
alongside project code, making it easier to reproduce configurations and deploy them across
different setups.
In practice, users will write shell scripts or batch files that utilize the CLI tool to modify FreeCAD
preferences based on specific requirements. These scripts will be able to include conditionals, loops,
or function calls to handle various scenarios and configurations. Executing these scripts from the
command line or integrating them into automation workflows will enable effortless management of
FreeCAD configurations, ensuring that preferences are tailored to specific use cases or workflows.
Thorough testing and validation of scripts will ensure correct modification of preferences and
validate resulting FreeCAD configurations, providing users with a dependable and effective method
for configuring FreeCAD according to their needs.

Example:
A real scenario using the FreeCAD Preference Manipulation CLI Tool based on the provided user
configuration could be automating the adjustment of certain preferences for specific workbenches.
Let’s say you want to ensure that certain preferences are set to specific values whenever the Arch
workbench is activated.
3.png
Interface
The FreeCAD Preference Manipulation CLI Tool is a command-line utility designed to interact with
FreeCAD’s preferences, allowing users to manage parameters either at the user or system level. This
manual provides detailed instructions on how to use the tool to perform various operations such as
retrieving parameter values, modifying parameters, creating new parameters, and deleting
parameters.

General Syntax:
4.png
Options:
• --scope or -s: Select the scope for parameter manipulation. Options are “user” or “system”.
Default is “user”.
• --modify or -m: Modify the value of a parameter.
• --create or -c: Create a new parameter.
• --delete or -d: Delete an existing parameter.
• -y: proceed without conformation


Python Module
Notes:
• If no scope is specified, the tool will default to the user scope.
• For modifying or creating parameters, if the parameter name already exists, its value will be
overwritten with the new value provided.
• When deleting a parameter, the tool will prompt for confirmation before proceeding with the
deletion.
9.png
Tools and Technology
• Python
• git + GitHub
• Argparse
• xml.dom (python library)
• pytest

Hi Harshita_Saraswat ! How is it going? Any progress to share already?

While researching and looking at the source code, I figured out there are datatypes managed by the code for preferences. I figured that implement a xml parser from ground up will be more time consuming and will not be robust. So in place of that I think importing the Freecad module to the python and using it with already developed parameters logic would be a better option.
I figured it out how to import it in a standalone python code and got it working.

current state:

  1. freecad module working in python code on windows
  2. implementing command design patter for the app

Doubt:

  1. any way to figure out the location of freecad lib files so that it can be imported in script and be cross platform?