-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Sketcher] Add copy/cut/paste sketcher commands #11537
Conversation
@abdullahtahiriyo there is one architectural question for the ViewProvider deleteSelected function that I use in the cut command. So I don't know if its acceptable to change it to public. If it is acceptable, then ViewProviderSketchShortcutListenerAttorney needs to be removed I guess? |
0ee62dd
to
760f5a2
Compare
In LibreCAD, when user pastes from clipboard, it's automatically dragged with the mouse cursor. 1 Would it be better to mimic the same look-and-feel? Footnotes |
Yes I want to do this as well. But first we need to enable group dragging.
…On Sun, Nov 26, 2023, 13:48 xtemp09 ***@***.***> wrote:
In *LibreCAD*, when user pastes from clipboard, it's automatically
dragged with the mouse cursor. 1
<#m_2944609140585950446_user-content-fn-1-c117b8c6093510eee342439d0d7849c8>
Would it be better to mimic the same look-and-feel?
Footnotes
1.
https://youtu.be/8xeuNbu_8rc?t=23 ↩
<#m_2944609140585950446_user-content-fnref-1-c117b8c6093510eee342439d0d7849c8>
—
Reply to this email directly, view it on GitHub
<#11537 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEYO6MLND4OT567XFMCMOELYGM3BHAVCNFSM6AAAAAA72UXHVGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMRWG43TKNZQGE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
760f5a2
to
9910223
Compare
Interesting. If the command is neither in the menu nor the toolbar, then the shortcut doesn't work. Just waiting for @abdullahtahiriyo feedback about the deleteSelected function before switching to ready. |
Is 4000 a magic number? If it's not, then would it simpler instead of GeoId = std::atoi(it->substr(4, 4000).c_str()) - 1; use GeoId = std::stoi( it->substr(4) ) - 1; ? Would it be simpler to use compare instead of substr? In this case, if (it->size() > 4 && it->substr(0, 4) == "Edge") becomes: if ( it->compare(0, 4, "Edge") == 0 )
std::string data = QGuiApplication::clipboard()->text().toStdString();
<...>
if (data.find("</GeometryList>", 0) != std::string::npos) {
geoString = data.substr(0, data.find("</GeometryList>", 0) + 16);
}
Is there a reason to use XML? Clipboard content is intended to be used on the forum, would it be better to use JSON, since it is more human-readable?
|
@xtemp09 for your 2 first comments, this was a copy paste of a code that is in many places. By the way it would probably be a good idea to make a function getting the list of geoId from the selection rather than having this block copy pasted everywhere. XML is used because we are using the available
Sorry I don't understand. We can add a warning in the status bar, or better a user notification if copy failed. But I am not sure this is necessary. |
There is no reason for the function to return value if this value is not taken into consideration at all. If the value is somewhat important, should it be checked and some action performed? About the last part. If a user copies similar fragments twice, but the last time the program failed to copy, the clipboard buffer will contain the first fragment. I just thought that the user should be notified about the failure to avoid copy-and-paste mistakes. |
@xtemp09 thanks for the review. I will check them in more details when I get back to this branch. |
There are several ways to copy and paste between sketches or even inside one. One option is XML. Another option is using commands (via PythonConverter). The XML used in save function stores a geometry and all its extensions, so as to be able to retrieve it "as is". One caveat is that geometry extensions may have geometry specific information (specific to one sketch, to one specific use of geometry as people in ArchSketch WB are using by storing in extensions meta-information, or even just a Geometry ID). While using XML is at a first glance a brilliant idea (close to zero effort implementation), the question arises how to handle the issue of copying what is wanted, but not copying what is not wanted. Taking into account that part of it may come from stock FreeCAD by design (such as the Geometry ID or geometry index), but others are even inserted by third party tools. Deciding what to copy "as is" and what to "regenerate" (such as unique indices/uuids) or not copy at all is not straight-forward. We should also put an eye to impact for external geometry (ExternalGeometryExtension) and its use by code coming from the TopoNaming project (at least RT's implementation used it). On the other hand we have PythonConverter, which copies console commands to reproduce the geometry, but will not handle any other special extension information. It is like adding the elements anew. The best advantage I see to this path is that the commands can be copied anywhere and even used to create macros. It is the "internal macro language" used by FreeCAD. The drawbacks are that some other information from extensions, which might perhaps be desirable to copy (visualisation attributes, or layer grouping information when it is available), is, at least in the current state of development of PythonConverter ignored. So XML is copy all and then go and figure out what needs to be removed. While PythonConverter is copy the basic and add whatever else you may need. This is one of the reasons (scarce review time being the other) why this PR (or better said its predecessor) has been queuing for some time. So essentially I say two things: |
I think python converter is a great idea. This way the code can be used in macros as well. I didn't thought about using this, and at the time of the initial work, python converter was not available. |
Yes next year is fine no hurry. |
Indeed. Pythonconverter was not available at the time, and I still think your idea of using XML code for serialisation is brilliant in many ways. Very creative approach. Anyway, we look at it next year. |
9910223
to
cf3aeb6
Compare
I have move from using XML to use python instead. This way the copied text can be used in macros and so on. Anyone willing to test and review? |
I've just tried it. Seems to be working. When pasting FreeCAD reports sometimes:
The clipboard:# Copied from sketcher.
lastGeoId = len(ActiveSketch.Geometry)
geoList = []
geoList.append(Part.LineSegment(App.Vector(-51.587891,39.518017,0.000000),App.Vector(-51.587891,10.801011,0.000000)))
geoList.append(Part.LineSegment(App.Vector(-51.587891,10.801011,0.000000),App.Vector(24.187309,10.801011,0.000000)))
geoList.append(Part.LineSegment(App.Vector(24.187309,10.801011,0.000000),App.Vector(24.187309,39.518017,0.000000)))
geoList.append(Part.LineSegment(App.Vector(24.187309,39.518017,0.000000),App.Vector(-51.587891,39.518017,0.000000)))
geoList.append(Part.Circle(App.Vector(0.000000, 0.000000, 0.000000), App.Vector(0.000000, 0.000000, 1.000000), 11.719850))
objectStr.addGeometry(geoList,False)
del geoList
constraintList = []
constraintList.append(Sketcher.Constraint('Coincident', 0, 2, 1, 1))
constraintList.append(Sketcher.Constraint('Coincident', 1, 2, 2, 1))
constraintList.append(Sketcher.Constraint('Coincident', 2, 2, 3, 1))
constraintList.append(Sketcher.Constraint('Coincident', 3, 2, 0, 1))
constraintList.append(Sketcher.Constraint('Vertical', 0))
constraintList.append(Sketcher.Constraint('Vertical', 2))
constraintList.append(Sketcher.Constraint('Horizontal', 1))
constraintList.append(Sketcher.Constraint('Horizontal', 3))
constraintList.append(Sketcher.Constraint('Coincident', 0, 3, -1, 1))
objectStr.addConstraint(constraintList)
del constraintList OS: Ubuntu 22.04.3 LTS (KDE/plasma)
Word size of FreeCAD: 64-bit
Version: 0.22.0dev.35569 (Git)
Build type: Debug
Branch: copy_paste_2023
Hash: cf3aeb6618cf68af754a74ac97f094fbb8188702
Python 3.10.12, Qt 5.15.12, Coin 4.0.0, Vtk 9.1.0, OCC 7.5.1
Locale: English/United States (en_US) Is there a reason to use return boost::str(boost::format("Sketcher.Constraint('Parallel', %s %i, %s %i)")
% lastGeoId % constr->First % lastGeoId % constr->Second); there is no gain in speed. |
Thanks!
There is a problem with your last coincident, the geoid2 is -1, I must have
made a mistake in the process function. With all the %s %i. Btw there's
probably a better syntax for this I will check tomorrow
…On Thu, Jan 11, 2024, 20:33 xtemp09 ***@***.***> wrote:
I've just tried it. Seems to be working. When pasting *FreeCAD* reports
sometimes:
02:16:10 Sketcher constraint number 9 is malformed!
02:16:10 Unnamed#Sketch001: The Sketch has malformed constraints!
02:16:10 Sketcher constraint number 9 is malformed!
02:16:10 Sketcher constraint number 9 is malformed!
02:16:10 Unnamed#Sketch001: The Sketch has malformed constraints!
The clipboard:
# Copied from sketcher.lastGeoId = len(ActiveSketch.Geometry)
geoList = []
geoList.append(Part.LineSegment(App.Vector(-51.587891,39.518017,0.000000),App.Vector(-51.587891,10.801011,0.000000)))
geoList.append(Part.LineSegment(App.Vector(-51.587891,10.801011,0.000000),App.Vector(24.187309,10.801011,0.000000)))
geoList.append(Part.LineSegment(App.Vector(24.187309,10.801011,0.000000),App.Vector(24.187309,39.518017,0.000000)))
geoList.append(Part.LineSegment(App.Vector(24.187309,39.518017,0.000000),App.Vector(-51.587891,39.518017,0.000000)))
geoList.append(Part.Circle(App.Vector(0.000000, 0.000000, 0.000000), App.Vector(0.000000, 0.000000, 1.000000), 11.719850))
objectStr.addGeometry(geoList,False)del geoListconstraintList = []constraintList.append(Sketcher.Constraint('Coincident', 0, 2, 1, 1))constraintList.append(Sketcher.Constraint('Coincident', 1, 2, 2, 1))constraintList.append(Sketcher.Constraint('Coincident', 2, 2, 3, 1))constraintList.append(Sketcher.Constraint('Coincident', 3, 2, 0, 1))constraintList.append(Sketcher.Constraint('Vertical', 0))constraintList.append(Sketcher.Constraint('Vertical', 2))constraintList.append(Sketcher.Constraint('Horizontal', 1))constraintList.append(Sketcher.Constraint('Horizontal', 3))constraintList.append(Sketcher.Constraint('Coincident', 0, 3, -1, 1))objectStr.addConstraint(constraintList)del constraintList
OS: Ubuntu 22.04.3 LTS (KDE/plasma)Word size of FreeCAD: 64-bitVersion: 0.22.0dev.35569 (Git)Build type: DebugBranch: copy_paste_2023Hash: cf3aeb6618cf68af754a74ac97f094fbb8188702Python 3.10.12, Qt 5.15.12, Coin 4.0.0, Vtk 9.1.0, OCC 7.5.1Locale: English/United States (en_US)
------------------------------
Is there a reason to use boost::format instead of std::format?
boost::format is supposed to be faster, but in the strings like this:
return boost::str(boost::format("Sketcher.Constraint('Parallel', %s %i, %s %i)")
% lastGeoId % constr->First % lastGeoId % constr->Second);
there is no gain in speed.
—
Reply to this email directly, view it on GitHub
<#11537 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEYO6MK7LXC5RKHQY3CZDOTYOA5ANAVCNFSM6AAAAAA72UXHVGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBXHAZTKNRTGE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
53c695e
to
66c728b
Compare
I have refactored my changes to python converter, it is cleaner now. Also I tested all constraint types (I think) and added the missing angleByPoint in pythonconverter. Regarding the boost::format vs std::format I have no idea about it. As this is code that Abdullah wrote I don't want to change it because he may have had a reason and it is not related to this PR. |
The copy/paste seems to be working fine and looks pretty handy. When compiling, compiler warns a lot about unused parameters. Lint shows these warnings, like
Is there a reason to separate entries with empty line when filling I think it would be neater if there was an empty line (or two) between the fragments of |
Thanks for your comments.
|
66c728b
to
3f861d9
Compare
Strictly speaking, I would beatify it even more, added spaces to some App.Vectors.
is spaceless while
contains spaces. I would also add additional check, if a number contained zeroes, I would delete them, therefore:
would become:
and
would become:
or, if possible,
This is more readable for human eye. But, it's just my opinion. |
3f861d9
to
17cb744
Compare
I fixed the white space missing in some geos. |
@chennes this PR is ready if you're looking for something to review ;) |
17cb744
to
17893d3
Compare
@PaddleStroke should I add them in the Sketcher context menu if we have a selection? I have to adjust it to also work with external geometry as well. |
Unless I am mistaken (or have missed an intermediate PR) there is something wrong with how constraints are pasted. Their geoids are not updated.
|
It should update the geoId, I may have broken things with my latest commit dealing with the boolean blindness. |
Hmm, you are right, it does for most constraints. But apparently the symmetry constrain, which I decided to use for my first tests, is not handled properly. |
I have just tested on my side with a single line with a length constraint. And it fails as you described. I will check in more details now |
I found the issue, it was not updating geoId when only one geometry was selected. |
Add support to copy/paste geometries in sketcher using ctrl-X/C and ctrl-V
Geometries (and relevent constraints) are copied to computer clipboard as python command text. Enabling exporting and paste in other Freecad instances or even share on forum.
Video description : https://forum.freecadweb.org/viewtopic.php?f=9&t=65892
This is a rework of #5480
So it appeared that creating commands in sketcher with the same shortcuts override CommandDoc general commands. Which solves the initial problem.