Sun, 03 Jul 2022 22:32:50 +0300
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 |
--- /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(" ");