Add copy action

Sun, 03 Jul 2022 22:32:50 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Sun, 03 Jul 2022 22:32:50 +0300
changeset 327
2aa15daa0216
parent 326
65dbfcb859a7
child 328
3ea38fd469ca

Add copy action

icons/copy.png file | annotate | diff | comparison | revisions
icons/cut.png file | annotate | diff | comparison | revisions
icons/paste.png file | annotate | diff | comparison | revisions
icons_svg/copy.svg file | annotate | diff | comparison | revisions
icons_svg/cut.svg file | annotate | diff | comparison | revisions
icons_svg/paste.svg file | annotate | diff | comparison | revisions
resources.qrc file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
src/mainwindow.ui file | annotate | diff | comparison | revisions
src/parser.cpp file | annotate | diff | comparison | revisions
Binary file icons/copy.png has changed
Binary file icons/cut.png has changed
Binary file icons/paste.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/icons_svg/copy.svg	Sun Jul 03 22:32:50 2022 +0300
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="512"
+   height="512"
+   viewBox="0 0 512 512"
+   version="1.1"
+   id="svg81"
+   sodipodi:docname="copy.svg"
+   inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <defs
+     id="defs85" />
+  <sodipodi:namedview
+     id="namedview83"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="1.4746094"
+     inkscape:cx="227.85695"
+     inkscape:cy="256"
+     inkscape:window-width="1920"
+     inkscape:window-height="970"
+     inkscape:window-x="0"
+     inkscape:window-y="40"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg81" />
+  <title
+     id="title75">ionicons-v5-e</title>
+  <path
+     d="M383.5,128l.5-24a56.16,56.16,0,0,0-56-56H112a64.19,64.19,0,0,0-64,64V328a56.16,56.16,0,0,0,56,56h24"
+     style="fill:#cccccc;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px;fill-opacity:1"
+     id="path79" />
+  <rect
+     x="128"
+     y="128"
+     width="336"
+     height="336"
+     rx="57"
+     ry="57"
+     style="fill:#ffffff;stroke:#000;stroke-linejoin:round;stroke-width:32px;fill-opacity:1"
+     id="rect77" />
+  <metadata
+     id="metadata1194">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title>ionicons-v5-e</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/icons_svg/cut.svg	Sun Jul 03 22:32:50 2022 +0300
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="512"
+   height="512"
+   viewBox="0 0 512 512"
+   version="1.1"
+   id="svg16"
+   sodipodi:docname="cut.svg"
+   inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <defs
+     id="defs20" />
+  <sodipodi:namedview
+     id="namedview18"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="1.5332031"
+     inkscape:cx="174.47134"
+     inkscape:cy="66.853503"
+     inkscape:window-width="1920"
+     inkscape:window-height="970"
+     inkscape:window-x="0"
+     inkscape:window-y="40"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg16" />
+  <title
+     id="title2">ionicons-v5-h</title>
+  <circle
+     cx="104"
+     cy="152"
+     r="56"
+     style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"
+     id="circle4" />
+  <circle
+     cx="104"
+     cy="360"
+     r="56"
+     style="fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"
+     id="circle6" />
+  <path
+     d="M157,175,146,190,183,205s3.46-6.42,7-10Z"
+     style="fill:none;stroke:#000;stroke-linecap:square;stroke-miterlimit:10;stroke-width:32px"
+     id="path8" />
+  <path
+     d="M154.17,334.43,460,162c-2.5-6.7-28-12-64-4-29.12,6.47-121.16,29.05-159.16,56.05C205.85,236.06,227,272,192,298c-25.61,19-44.43,22.82-44.43,22.82Z"
+     style="fill:#cccccc;stroke:#000;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px;fill-opacity:1"
+     id="path10" />
+  <path
+     d="M344.47,278.24,295,306.67c14.23,6.74,65.54,33.27,117,36.33,14.92.89,30,.39,39-6Z"
+     style="fill:#cccccc;stroke:#000;stroke-linecap:round;stroke-miterlimit:10;stroke-width:32px;fill-opacity:1"
+     id="path12" />
+  <circle
+     cx="256"
+     cy="240"
+     r="32"
+     style="fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:32px"
+     id="circle14" />
+  <metadata
+     id="metadata923">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title>ionicons-v5-h</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/icons_svg/paste.svg	Sun Jul 03 22:32:50 2022 +0300
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="512"
+   height="512"
+   viewBox="0 0 512 512"
+   version="1.1"
+   id="svg8"
+   sodipodi:docname="paste.svg"
+   inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <defs
+     id="defs12" />
+  <sodipodi:namedview
+     id="namedview10"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="0.95708927"
+     inkscape:cx="37.091629"
+     inkscape:cy="305.61413"
+     inkscape:window-width="1920"
+     inkscape:window-height="970"
+     inkscape:window-x="0"
+     inkscape:window-y="40"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg8" />
+  <title
+     id="title2">ionicons-v5-l</title>
+  <path
+     d="M336,64h32a48,48,0,0,1,48,48V432a48,48,0,0,1-48,48H144a48,48,0,0,1-48-48V112a48,48,0,0,1,48-48h32"
+     style="fill:#aa8800;stroke:#000;stroke-linejoin:round;stroke-width:32px;fill-opacity:1"
+     id="path4" />
+  <rect
+     x="176"
+     y="32"
+     width="160"
+     height="64"
+     rx="26.13"
+     ry="26.13"
+     style="fill:#cccccc;stroke:#000;stroke-linejoin:round;stroke-width:32px;fill-opacity:1"
+     id="rect6" />
+  <rect
+     x="153.92816"
+     y="148.49352"
+     width="206.68349"
+     height="268.68854"
+     rx="31.002522"
+     ry="31.002522"
+     style="fill:#ffffff;stroke:#000000;stroke-width:20.6683px;stroke-linejoin:round;fill-opacity:1"
+     id="rect4" />
+  <line
+     x1="205.59903"
+     y1="200.16438"
+     x2="308.94077"
+     y2="200.16438"
+     style="fill:none;stroke:#000000;stroke-width:20.6683px;stroke-linecap:round;stroke-linejoin:round"
+     id="line6" />
+  <line
+     x1="205.59903"
+     y1="251.83525"
+     x2="308.94077"
+     y2="251.83525"
+     style="fill:none;stroke:#000000;stroke-width:20.6683px;stroke-linecap:round;stroke-linejoin:round"
+     id="line8" />
+  <line
+     x1="205.59903"
+     y1="303.50613"
+     x2="257.2699"
+     y2="303.50613"
+     style="fill:none;stroke:#000000;stroke-width:20.6683px;stroke-linecap:round;stroke-linejoin:round"
+     id="line10" />
+  <metadata
+     id="metadata1217">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title>ionicons-v5-l</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+</svg>
--- a/resources.qrc	Sun Jul 03 22:24:12 2022 +0300
+++ b/resources.qrc	Sun Jul 03 22:32:50 2022 +0300
@@ -33,5 +33,8 @@
         <file>icons/polyline.png</file>
         <file>icons/linetype-circularprimitive.png</file>
         <file>icons/appicon.png</file>
+        <file>icons/copy.png</file>
+        <file>icons/cut.png</file>
+        <file>icons/paste.png</file>
     </qresource>
 </RCC>
--- a/src/main.cpp	Sun Jul 03 22:24:12 2022 +0300
+++ b/src/main.cpp	Sun Jul 03 22:32:50 2022 +0300
@@ -1,4 +1,5 @@
 #include <QApplication>
+#include <QClipboard>
 #include <QCloseEvent>
 #include <QFileDialog>
 #include <QMdiSubWindow>
@@ -779,6 +780,21 @@
 			about(&mainWindow);
 		}
 	);
+	QObject::connect(
+		ui.actionCopy,
+		&QAction::triggered,
+		[&]{
+			if (Model* model = currentModelBody(&ui, &documents)) {
+				std::vector<int> selectedRows = rows(ui.modelListView->selectionModel()->selectedRows());
+				QString text;
+				for (int row : selectedRows) {
+					const std::size_t i = static_cast<std::size_t>(row);
+					text += modelElementToString((*model)[i]);
+					text += QStringLiteral("\r\n");
+				}
+				app.clipboard()->setText(text);
+			}
+		});
 	mainWindow.tabifyDockWidget(ui.messageLogDock, ui.toolOptionsDock);
 	mainWindow.restoreGeometry(setting<Setting::MainWindowGeometry>());
 	mainWindow.restoreState(setting<Setting::MainWindowState>());
--- a/src/mainwindow.ui	Sun Jul 03 22:24:12 2022 +0300
+++ b/src/mainwindow.ui	Sun Jul 03 22:32:50 2022 +0300
@@ -88,10 +88,14 @@
     <property name="title">
      <string>Edit</string>
     </property>
+    <addaction name="actionCut"/>
+    <addaction name="actionCopy"/>
+    <addaction name="actionPaste"/>
+    <addaction name="actionDelete"/>
+    <addaction name="separator"/>
     <addaction name="actionSelectAll"/>
     <addaction name="separator"/>
     <addaction name="actionInvert"/>
-    <addaction name="actionDelete"/>
     <addaction name="separator"/>
     <addaction name="actionGridFine"/>
     <addaction name="actionGridMedium"/>
@@ -531,6 +535,42 @@
     <string>Ctrl+A</string>
    </property>
   </action>
+  <action name="actionCopy">
+   <property name="icon">
+    <iconset resource="../resources.qrc">
+     <normaloff>:/icons/copy.png</normaloff>:/icons/copy.png</iconset>
+   </property>
+   <property name="text">
+    <string>Copy</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+C</string>
+   </property>
+  </action>
+  <action name="actionCut">
+   <property name="icon">
+    <iconset resource="../resources.qrc">
+     <normaloff>:/icons/cut.png</normaloff>:/icons/cut.png</iconset>
+   </property>
+   <property name="text">
+    <string>Cut</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+X</string>
+   </property>
+  </action>
+  <action name="actionPaste">
+   <property name="icon">
+    <iconset resource="../resources.qrc">
+     <normaloff>:/icons/paste.png</normaloff>:/icons/paste.png</iconset>
+   </property>
+   <property name="text">
+    <string>Paste</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+V</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../resources.qrc"/>
--- a/src/parser.cpp	Sun Jul 03 22:24:12 2022 +0300
+++ b/src/parser.cpp	Sun Jul 03 22:32:50 2022 +0300
@@ -53,7 +53,7 @@
 	{
 		// Some LDraw parts such as 53588.dat can contain "BFC  INVERTNEXT" with multiple inner whitespaces.
 		// So we need to pass the string through QString::simplified to catch these cases.
-		const QString line = this->readLine().simplified();
+		const QString line = this->readLine().trimmed();
 		if (line == "0 BFC INVERTNEXT" or line == "0 BFC CERTIFY INVERTNEXT")
 		{
 			invertNext = true;
@@ -200,7 +200,6 @@
 
 ModelElement parseLDrawLine(QString line)
 {
-	line = line.trimmed();
 	try
 	{
 		const QStringList tokens = line.simplified().split(" ");

mercurial