如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Chinese forum

Moderator: paullee

Forum rules
论坛规矩 / 論壇規矩 , 有用的资讯 / 有用的資訊
重要:寻求帮助之前,请先看看这里 /
重要:尋求幫助之前,請先看看這裡

另外,对论坛用户 友善!阅读FreeCAD 行为准则!
/ 另外,對論壇用戶 友善! 閱讀FreeCAD
行為準則
月下竹云
Posts: 5
Joined: Mon Feb 28, 2022 9:21 am

如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by 月下竹云 »

# 一些介绍

当前版本(0.20之前),FreeCAD的使用过程中,一旦使用中文命名则命名会被“_______”替换。读取对象名称,会返回一堆下划线。
命名被替换的范围,包含新建物体名称,以及新建属性名称。
这对于需要中文,英文掺杂使用的我,代码脚本建模,简直是噩梦,维护命名表,与对应的建立命名表,十分难受。
我使用中文标识我自己写的函数和变量,使用英文,表示依赖的库、函数和变量。

# 修改的缘由

(1)在测试FreeCAD的参数化建模的一个用例过程中,我使用了18个变量进行控制,这些变量命名中,最长的命名为29个英文字符。我认为,一旦我一个文档内用例一多,属性名称字符长度过长会发生,而且长命名对我个人而言,难以快速回忆起来这个变量的用途。

到后期需要把变量全部集中到一个表格中,表格中的变量可以相互引用和计算,建模的公式引用可以引用表格单元格索引的别名(如 sheet1::A0 等价于 sheet1.属性名 )这个是对FreeCAD以后功能的期望,不在本片帖子的主题范围

(2)FreeCAD公式支持2种引用, var.属性 引用和 <<var>>.标签名称 引用。暂时,属性名称还不支持标签重命名,也就是属性命名错了,只能删除属性再重新新建属性

由以上2点,加上我想使用大量变量进行参数化可调建模,所以萌生了修改代码支持中文命名,
那时的想法很简单,FreeCAD集成了python控制台,那FreeCAD肯定能支持中文命名,而且修改的地方应该不会多。
最终,修改的位置事实上也不算多,而且基本没去修改过FreeCAD的核心函数,功能函数。


# FreeCAD的基础

我追踪过FreeCAD的命名过程,由此得到了一些信息,这些成为修改的基础,也指向了修改代码的方向。
(1)命名的过程,先经过规整化函数判断和替换,最后再写入文档之中
(2)FreeCAD是界面和功能完全分开的架构,界面是界面,功能是功能,他们之间通过运行cmd代码的形式连接。点击1个按钮会执行1个函数,原本这个函数是功能代码,但到了这里,只简化为 cmd代码 = “python代码发f{名称}”,运行 cmd代码就结束了。
(3)界面的字符及字符流的编码是QString(utf-16)
(4) cmd代码 = “python代码f{名称}”的编码是(utf-8),这个实际就是python的运行控制台
(5)文档存储是接受utf-8字节流格式,以Latin1的形式存储下来,这里有点绕,可以简单理解为把字符转化为utf-8字节形式交给cmd代码就行。

以此基本就知道改如何修改代码了,得益于FreeCAD界面和功能完全分开,通过python控制台相互连接的方式,只要把界面获取的字符转码成utf-8字节流或者Latin1的形式交给控制台,从控制台获取的字符转码成QString交给界面即可。这个过程统一编码保证输入、显示和存储是一致的。

中文变量的支持实际的基础是python控制台本身支持中文命名和FreeCAD存档是以utf-8编码存储的,因此使用中文命名变量是十分可靠的,不会影响FreeCAD的正常运行,属于python控制台支持utf-8编码的特性,是基础设施。即使界面显示乱码,也不必担心损坏存档,毕竟字节流是一样的。

以此为方向,最终修改成功,使用也正常,虽然修改过程有一些意外的波折,但却是与代码修改方向无关的问题。

我修改成功时候,建模运行,保存文档,再读取均无问题,当然这以我修改了一部界面的字符转换代码,没有修改全部界面,我也没有使用全部界面有关系,算是未经过大量的测试。

# 代码修改

在修改过程中,有些波折,最后定位成功,问题是出在交给python控制台的ss字节流上,混用了编码,没有把所有到ss字节流的字符统一成utf-8字节流的形式。
主要的修改也是在统一SS字符流编码,最终把输入到ss字节流的混乱的编制统一成utf-8字节流之后,界面显示及python控制台显示都正常。
界面显示的修改较为简单,QString::fromLatin1改成QString::fromUtf8(propName),选择了正确的转换编码即能正常显示。

主要修改的界面为组合浏览器界面、选择浏览器界面、属性界面、其他界面未修改,即使需要修改,道理和方式也是一致的。

一、去除下划线替换。
FreeCADBase/Source Files/Tools.cpp

伪代码:
std::string Base::Tools::getIdentifier(const std::string& name)下一行
直接return name;使其不对输入的字符进行处理,也不会弹出字符限制弹出窗口。

二、GUI界面中文正确显示
(1)上一条去除下划线替换,python命令台也能正常显示中文

(2)选择浏览器界面显示中文
文件:
FreeCADGui/Dock Windowns/SelectionView.cpp

伪代码:
1)在
void SelectionView::onSelectionChanged(const SelectionChanges &Reason)
if (Reason.Type == SelectionChanges::AddSelection)
else if (Reason.Type == SelectionChanges::ClrSelection)
else if (Reason.Type == SelectionChanges::RmvSelection)
else if (Reason.Type == SelectionChanges::SetSelection)
else if (Reason.Type == SelectionChanges::PickedListChanged)
修改点:
5个位置的代码块末行前面
增加一行selObject = QString::fromUtf8(selObject.toLatin1());
同时label.value由fromUtf8改成fromLatin1

最终经过修改后交给控制台的cmd代码为
str << QString::fromLatin1(obj->Label.getValue());
selObject = QString::fromUtf8(selObject.toLatin1());
QListWidgetItem* item = new QListWidgetItem(selObject, selectionView);

2)
伪代码:
void SelectionView::preselect(QListWidgetItem* item)
修改点:
text().toLatin1()改成text().toUtf8()
修改结果
std::string name = item->text().toUtf8().constData();

3)2处toLatin1改为toUtf8
伪代码:
void SelectionView::toggleSelect(QListWidgetItem* item)
修改点:
text().toLatin1()改成text().toUtf8()

(3)属性显示中文
文件
FreeCADGui/Propertyeditor/PropertyModel.cpp

伪代码:
static void setPropertyItemName(PropertyItem *item, const char *propName, QString groupName)
修改点:
QString::fromLatin1改成QString::fromUtf8(propName)
修改结果:
QString name = QString::fromUtf8(propName);

(4)属性设置值的时候cmd代码能正确运行
伪代码:
void PropertyItem::setPropertyValue(const QString& value)
修改点:
代码块里的value.toUtf8().constData()改成value.toLatin1().constData()
最终结果为
ss << parent->getPropertyPrefix() << prop->getName()
<< " = " << value.toLatin1().constData() << '\n';


三、Assembly4去除变量限制

文件:
VariablesLib.py
修改点:
直接return,解除按钮限制
修改结果:
def onNameEdited(self):
return ""

# 编译拾遗


这个问题与代码修改没有关系,但导致win10平台编译不成功,为此做个简记.
编译环境的准备请参照【realthunder的FreeCAD编译依赖库】【https://github.com/realthunder/FreeCAD_ ... s/tag/0.11

将PartDesign/SketchBasedFeatures/FeatureHole.cpp,高级保存为utf-8带Boom的形式,保存之后重新编译即能成功,原因不明。
其他文件不做修改都编译正常,唯独它需要改编码重新保存。
这份文件主要影响PartDesign工作台,编译成功后,PartDesign工作台能正常使用。
paullee
Veteran
Posts: 5098
Joined: Wed May 04, 2016 3:58 pm

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by paullee »

月下竹云 wrote: Wed Mar 02, 2022 8:51 am 当前版本(0.20之前),FreeCAD的使用过程中,一旦使用中文命名则命名会被“_______”替换。读取对象名称,会返回一堆下划线。
...
歡迎 :)

完全看不懂內容 :lol: 有沒有高手可討論一下?
realthunder wrote: Ping

另,名字是甚麼意思?
User avatar
johnwang
Veteran
Posts: 1345
Joined: Sun Jan 27, 2019 12:41 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by johnwang »

"我使用中文标识我自己写的函数和变量"

我在自己的函数前加个特殊字串。比如用名字缩写。我叫Harry Potter, 我写了个box函数,我叫这个函数为hpBox。这样可以与其他人写的box函数区分开来。
hfc series CAE workbenches for FreeCAD (hfcNastran95, hfcMystran, hfcFrame3DD, hfcSU2 and more)
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by realthunder »

感谢你的努力。按照你的描述我在我自己的branch初步试了下,基本上可以。我的branch之前已经支持中文Spreadsheet alias,但不支持文件,对象,及属性。下次可能的话最好直接去FreeCAD github主页发PR。不过你这次建议的改动其实挺大的,肯定需要不少时间打磨才会被接受。

月下竹云 wrote: Wed Mar 02, 2022 8:51 am 伪代码:
std::string Base::Tools::getIdentifier(const std::string& name)下一行
直接return name;使其不对输入的字符进行处理,也不会弹出字符限制弹出窗口。
为了能让对象和属性可当成正常的Python attribute来引用,最好还是替换空格以及标点符号。参看这里.

月下竹云 wrote: Wed Mar 02, 2022 8:51 am 那时的想法很简单,FreeCAD集成了python控制台,那FreeCAD肯定能支持中文命名,而且修改的地方应该不会多。
最终,修改的位置事实上也不算多,而且基本没去修改过FreeCAD的核心函数,功能函数。
这里的确是想的简单了些。由于上面getIdentifier去除了Latin1的限制涉及的范围非常广,需要改的地方其实很多。我只是初步过了一边,涉及超过60个文件,肯定还漏了不少。

月下竹云 wrote: Wed Mar 02, 2022 8:51 am (4)属性设置值的时候cmd代码能正确运行
伪代码:
void PropertyItem::setPropertyValue(const QString& value)
修改点:
代码块里的value.toUtf8().constData()改成value.toLatin1().constData()
最终结果为
ss << parent->getPropertyPrefix() << prop->getName()
<< " = " << value.toLatin1().constData() << '\n';
应该是toLatin1()换成toUtf8()吧。是手误吗,还有几个地方也是这样的问题。


另外,Expression Completer,已及Python Console auto completer都需要一些小改动来支持输入法。
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
felixlee868
Posts: 126
Joined: Wed Jul 03, 2019 8:15 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by felixlee868 »

看了相关讨论,谈一下个人看法。

建议编写一个处理不同编码方案的函数,来解决中文化的问题,而不是简单使用将latin1字符编码方案替换成utf8这种方式。
提出以上意见的原因,是由于FreeCAD是一个开放平台,还有其它国家的不同语言编码方案需要使用,且除了utf8字符编码方案之外,还有utf16等不同的方案。只通过替换latin1到utf8方式,进行编码表扩展,只是将一个问题,转换成另一个问题。
另外,对于使用非utf8编码方案的语言来说,utf8编码方案过于繁杂。

如果使用一个函数,通过不同的编码方案作为参数,来进行字符编码的转换,可以更为灵活的解决多语言平台对于FreeCAD的使用用户界面显示问题。
月下竹云
Posts: 5
Joined: Mon Feb 28, 2022 9:21 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by 月下竹云 »

realthunder wrote: Fri Mar 04, 2022 2:21 pm 感谢你的努力。按照你的描述我在我自己的branch初步试了下,基本上可以。我的branch之前已经支持中文Spreadsheet alias,但不支持文件,对象,及属性。下次可能的话最好直接去FreeCAD github主页发PR。不过你这次建议的改动其实挺大的,肯定需要不少时间打磨才会被接受。

月下竹云 wrote: Wed Mar 02, 2022 8:51 am 伪代码:
std::string Base::Tools::getIdentifier(const std::string& name)下一行
直接return name;使其不对输入的字符进行处理,也不会弹出字符限制弹出窗口。
为了能让对象和属性可当成正常的Python attribute来引用,最好还是替换空格以及标点符号。参看这里.

月下竹云 wrote: Wed Mar 02, 2022 8:51 am 那时的想法很简单,FreeCAD集成了python控制台,那FreeCAD肯定能支持中文命名,而且修改的地方应该不会多。
最终,修改的位置事实上也不算多,而且基本没去修改过FreeCAD的核心函数,功能函数。
这里的确是想的简单了些。由于上面getIdentifier去除了Latin1的限制涉及的范围非常广,需要改的地方其实很多。我只是初步过了一边,涉及超过60个文件,肯定还漏了不少。

月下竹云 wrote: Wed Mar 02, 2022 8:51 am (4)属性设置值的时候cmd代码能正确运行
伪代码:
void PropertyItem::setPropertyValue(const QString& value)
修改点:
代码块里的value.toUtf8().constData()改成value.toLatin1().constData()
最终结果为
ss << parent->getPropertyPrefix() << prop->getName()
<< " = " << value.toLatin1().constData() << '\n';
应该是toLatin1()换成toUtf8()吧。是手误吗,还有几个地方也是这样的问题。


另外,Expression Completer,已及Python Console auto completer都需要一些小改动来支持输入法。
谢谢啦,您的测试,解答了我最初的疑惑。
我回顾了下帖子,发现有些问题没有解释清楚,也没有说明在这里发帖的原因。

我现在发在这里的修改是,第2稿的修改。

一、第一稿修改
我最初的修改,是十分简单的,全部修改QString.toLatin1到QString.toUtf8,但是使用过程出现了问题,我无法理解ss统一成Utf8字符,反而出错,我试过追踪过,但毫无头绪。
需要说明的是,我平常用的是python,我没有C++的编程经验,我查看C++代码的方式是以python的眼光看待的,修改的方式也是复制代码加替换同类型函数。
因为不懂C++的原因,在网上查找了FreeCAD的字符编码设计资料,
资料不是很多,但明确了原来的方向是对的,但可能需要的是字节序,而不是字符。
后面我改变了思路,不是一次性全部替换,而是一个函数按照统一Utf8字节序的思路一个函数慢慢替换。

二、第二稿修改
我把第一稿FreeCAD源代码的修改,全部覆盖回去,从字符处理开始修改,1个函数替换,一次编译,看下FreeCAD的表现,有些时候,把toutf8修改回tolatin1反而表现正常,我当时的理解是前面已经是utf8字节形式的latin1格式存储,在toutf8有可能会导致字节增加而出错(我对utf8字节格式实际也不是很清楚),所以会有几处反而修改是toLatin1()。

现在看您的解释,也可能会是我前面修改后因能运行,没再修改回去的原因。
toLatin1可能是遗留的错误修改,但因能运行而保留下来,这些修改代码现在看是存在问题的。

我第2次修改的思路反而是能少修改就少修改,只要程序能跑起来就行,不去影响FreeCAD其他的部分,让他们维持原来的方式运行即可。我常用的几个界面能用,不出错,存储再读取,显示一致我就达到目的。

三、不去GitHub,而在FreeCAD论坛发帖的原因
我不懂C++,以前只接触C语言,后面用python。
而且我在发现FreeCAD的ss字符流即存在Latin1也存在Utf8,同时第一次修改时发现Latin1的位置简直无处不在。
我那时的理解python支持utf8是天然的事情,但FreeCAD的Latin1出现非常高,这个可能是字符编码的顶层设计问题,需要有广泛的讨论,才有可能修改。
我并不具备这样的能力,所以选在论坛发帖,给有这部分需要的人,可以参考下。
月下竹云
Posts: 5
Joined: Mon Feb 28, 2022 9:21 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by 月下竹云 »

johnwang wrote: Wed Mar 02, 2022 8:15 pm "我使用中文标识我自己写的函数和变量"

我在自己的函数前加个特殊字串。比如用名字缩写。我叫Harry Potter, 我写了个box函数,我叫这个函数为hpBox。这样可以与其他人写的box函数区分开来。
是的,我有时也这样用,我这样用的原因是到了后期,函数功能和命名大致确定,基本不会修改的时候。
我在最初的时候,都是先实现功能,后面在拆分,这个过程会涉及多次修改,多次修改的阶段,我使用中文标识。我主要用的是python
月下竹云
Posts: 5
Joined: Mon Feb 28, 2022 9:21 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by 月下竹云 »

felixlee868 wrote: Fri Mar 04, 2022 3:26 pm 看了相关讨论,谈一下个人看法。

建议编写一个处理不同编码方案的函数,来解决中文化的问题,而不是简单使用将latin1字符编码方案替换成utf8这种方式。
提出以上意见的原因,是由于FreeCAD是一个开放平台,还有其它国家的不同语言编码方案需要使用,且除了utf8字符编码方案之外,还有utf16等不同的方案。只通过替换latin1到utf8方式,进行编码表扩展,只是将一个问题,转换成另一个问题。
另外,对于使用非utf8编码方案的语言来说,utf8编码方案过于繁杂。

如果使用一个函数,通过不同的编码方案作为参数,来进行字符编码的转换,可以更为灵活的解决多语言平台对于FreeCAD的使用用户界面显示问题。
您是对的,FreeCAD的界面和功能分开的架构设计本身是存在字符编码转换设计的。

我会去折腾中文命名的原因,仅是FreeCAD集成了python控制台,python控制台是使用utf-8字符编码格式的。
所以不管FreeCAD的界面如何设计,功能如何设计,他们之间都是通过python控制台连接起来,都需要转成utf-8才能运行。
我的想法是python既然是基础设施,那利用utf-8的特性支持中文命名添加属性就行了,这样就达到了使用中文命名属性的目的。

我有时候只是不能理解,无论是界面还是功能,他们都需要转换成utf-8才能被python控制台识别和接受,他们使用其他编码的意义是什么。
界面我能理解,因为是Qt5写的,Qt5是Qstring(utf-16),这个没得选。

但功能部分也不使用utf-8,我是难以理解,后面,我想到的可能是依赖的库无法处理utf-8字符的原因吧。
我这样的理解,可能和我使用python有关,我常用的python库都能正确处理utf-8字符。
felixlee868
Posts: 126
Joined: Wed Jul 03, 2019 8:15 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by felixlee868 »

关于字符编吗问题,个人理解,其核心是计算环境的进程运行环境问题,如果对于操作系统内核,进程以及shell等计算机基本原理概念有所理解话,可以从整个系统的关系中来找到解决这个问题的方法。

Python只是与shell相同的一个语言解释器,也是操作系统下的一个进程,因此,个人理解,期还不是最为基础的一个软件组件。根据Unix系统设计哲学,所有问题的解决,都可以通过引入中间层来处理。这样的处理方法,对于系统来说,有足够的灵活性,还兼具系统的健壮性。因为每层都可以被其它更精细的软件层进行替换。这个处理问题的方法,应在统编写软件工程时,随着遵守。
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: 如何使自己编辑的FreeCAD版本添加属性时能支持中文命名?请看这里

Post by realthunder »

月下竹云 wrote: Sat Mar 05, 2022 2:28 am 我不懂C++,以前只接触C语言,后面用python。
不懂C++ 能做到这样很不错了。
而且我在发现FreeCAD的ss字符流即存在Latin1也存在Utf8,同时第一次修改时发现Latin1的位置简直无处不在。
我那时的理解python支持utf8是天然的事情,但FreeCAD的Latin1出现非常高,这个可能是字符编码的顶层设计问题,需要有广泛的讨论,才有可能修改。
我并不具备这样的能力,所以选在论坛发帖,给有这部分需要的人,可以参考下。
Linux系统字符编码基本上都是UTF8。Windows不太熟,我知道Windows下程序有两种,一种编译使用UTF16字符串,一种使用MBSC。FreeCAD用的应该是UTF16。Qt内部编码也是UTF16。Python则是UTF8。UTF8兼容Latin1。C++/C字符串本身不包含编码信息,只要是编码不包含0都可以。所以UTF8可以直接使用C++/C字符串,但是UTF16不行。FreeCAD内部编码是UTF8,但是面向用户的图形界面由于是使用Qt,所以是UTF16。之所以现存代码会有to/fromLatin1是因为Base::Tools::getIdentifier()限制了非Latin1的字符,所以很多地方默认的Latin1编码。其实只要都换成to/fromUtf8就行,区别只是一点点运行速度差异,应该可以忽略不计。
felixlee868 wrote: Fri Mar 04, 2022 3:26 pm 建议编写一个处理不同编码方案的函数,来解决中文化的问题,而不是简单使用将latin1字符编码方案替换成utf8这种方式。
上面提到现代操作系统和软件用的编码基本上不是UTF8就是UTF16,程序并不需要知道字符串的内容具体是哪种语言,基本只需要关心这两种编码的转换。
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
Post Reply