Merge branch 'feature/manual-layout' into develop

This commit is contained in:
Roman Telezhynskyi 2021-09-13 17:28:31 +03:00
commit 332de25210
357 changed files with 62787 additions and 9753 deletions

View file

@ -2,7 +2,7 @@
host = https://www.transifex.com
lang_map = uk: uk_UA, cs : cs_CZ, nl : nl_NL, fi : fi_FI, es : es_ES, id : id_ID
[valentina-project.valentina_ts]
[valentina-project.valentina-ts]
file_filter = share/translations/valentina_<lang>.ts
minimum_perc = 20
source_file = share/translations/valentina.ts

View file

@ -8,6 +8,8 @@
- Fix finding point of intersection curve and axis. Case when the axis's point lies on the curve.
- Fix visualization for tool point of intersection line and axis. Case when the axis's point lies on the line.
- Table of variables is available in Details mode.
- Fix incorrect comparison of the global length of passmark to minimal allowed value.
- Make an increment name valid after user selected it from a completion list.
# Valentina 0.7.49 July 1, 2021
- Fix crash.

View file

@ -132,7 +132,10 @@ The path to output destination folder. By default the directory at which the app
.BR "*" " PDF tiled files (*.pdf) = 33,"
.RE
.RS
.BR "*" " TIFF файли (*.tif) = 35."
.BR "*" " TIFF файли (*.tif) = 35,"
.RE
.RS
.BR "*" " TIFF файли (*.tif) = 36."
.RE
.IP "--bdxf"
.RB "Export dxf in binary form."

BIN
dist/Puzzle.icns vendored Normal file

Binary file not shown.

1
dist/debian/menu vendored
View file

@ -1,2 +1,3 @@
?package(valentina): needs="X11" section="Applications/Graphics" title="Valentina" command="valentina"
?package(valentina): needs="X11" section="Applications/Data Management" title="Tape" command="tape"
?package(valentina): needs="X11" section="Applications/Data Management" title="Puzzle" command="puzzle"

55
dist/debian/puzzle.1 vendored Normal file
View file

@ -0,0 +1,55 @@
.\" Manpage for puzzle
.\" Contact dismine@gmail.com to correct errors.
.TH puzzle 1 "23 March, 2020" "puzzle man page"
.SH NAME
Puzzle \- Valentina's manual layout
.SH SYNOPSIS
puzzle [options] file
.SH DESCRIPTION
.B Valentina
Puzzle is the name of the new application to create manual layouts. Similar to "Tape", it is an application that is separated from Valentina and work on it's own, but is a part of the Valentina package and work closely together with Valentina.
.B Puzzle
is a part of Valentina. And used for creating and editing manual layouts.
.IP "-h, --help"
Displays this help.
.IP "-v, --version"
Displays version information.
.IP "-e, --exportFile <The filename of layout file>"
The filename of exported layout file. Use it to enable console export mode.
.IP "-r, --rawLayout <The raw layout data file>"
Load pattern pieces form the raw layout data file.
.IP "-f, --format <Format number>"
Number corresponding to tiled pdf page template (default = 0, export mode with tiled pdf format): <not defined>
.IP "--bdxf"
Export dxf in binary form.
.IP "--text2paths"
Export text as paths.
.IP "-c, --crop"
Auto crop unused length (export mode).
.IP "--cropWidth"
Auto crop unused width (export mode).
.IP "--tiledPageformat <Template number>"
Number corresponding to tiled pdf page template (default = 0, export mode with tiled pdf format): <not defined>
.IP "--tiledlmargin <The left margin>"
Tiled page left margin in current units like 3.0 (export mode). If not set will be used default value 1 cm.
.IP "--tiledrmargin <The right margin>"
Tiled page right margin in current units like 3.0 (export mode). If not set will be used default value 1 cm.
.IP "--tiledtmargin <The top margin>"
Tiled page top margin in current units like 3.0 (export mode). If not set will be used value default value 1 cm.
.IP "--tiledbmargin <The bottom margin>"
Tiled page bottom margin in current units like 3.0 (export mode). If not set will be used value default value 1 cm.
.IP "--tiledLandscape"
Set tiled page orienatation to landscape (export mode). Default value if not set portrait.
.IP "-t, --test"
Run the program in a test mode. The program in this mode loads a single layout file and silently quit without showing the main window. The key have priority before key 'exportFile'.
.IP "--no-scaling"
Disable high dpi scaling. Call this option if has problem with scaling (by default scaling enabled). Alternatively you can use the QT_AUTO_SCREEN_SCALE_FACTOR=0 environment variable.
.IP Arguments:
.I filename
\- the manual layout file.
.SH AUTHOR
.RI "This manual page was written by Roman Telezhynskyi <" dismine@gmail.com ">"
.BR valentina (1)

View file

@ -1,10 +1,13 @@
debian/usr/share/pixmaps/valentina.png
debian/usr/share/pixmaps/tape.png
debian/usr/share/pixmaps/puzzle.png
debian/usr/share/pixmaps/application-x-valentina-pattern.png
debian/usr/share/pixmaps/application-x-valentina-i-measurements.png
debian/usr/share/pixmaps/application-x-valentina-s-measurements.png
debian/usr/share/pixmaps/application-x-valentina-layout.png
debian/valentina/usr/bin/valentina
debian/valentina/usr/bin/tape
debian/valentina/usr/bin/puzzle
debian/valentina/usr/share/valentina/diagrams.rcc
debian/valentina/usr/share/valentina/translations/measurements_p0_cs_CZ.qm
debian/valentina/usr/share/valentina/translations/measurements_p0_de_DE.qm

0
dist/debian/tape.1 vendored Normal file → Executable file
View file

0
dist/debian/valentina.1 vendored Normal file → Executable file
View file

View file

@ -1,2 +1,3 @@
debian/valentina.1
debian/tape.1
debian/puzzle.1

View file

@ -1,3 +1,4 @@
application/x-valentina-pattern; valentina %s; nametemplate=%s.val; description="Valentina pattern" edit=valentina '%s'; priority=6
application/x-valentina-i-pattern; tape %s; nametemplate=%s.vit; description="Valentina individual measurments" edit=tape '%s'; priority=6
application/x-valentina-s-pattern; tape %s; nametemplate=%s.vst; description="Valentina standard measurments" edit=tape '%s'; priority=6
application/x-valentina-layout; puzzle %s; nametemplate=%s.vlt; description="Valentina layout" edit=puzzle '%s'; priority=6

View file

@ -282,4 +282,98 @@
<glob pattern="*.vst"/>
<icon name="application-x-valentina-s-measurements"/>
</mime-type>
<mime-type type="application/x-valentina-layout">
<sub-class-of type="text/xml"/>
<_comment>Valentina layout</_comment>
<comment xml:lang="af">Valentina layout</comment>
<comment xml:lang="ar">Valentina layout</comment>
<comment xml:lang="as">Valentina layout</comment>
<comment xml:lang="ast">Valentina layout</comment>
<comment xml:lang="be">Valentina layout</comment>
<comment xml:lang="bg">Valentina layout</comment>
<comment xml:lang="bn">Valentina layout</comment>
<comment xml:lang="br">Valentina layout</comment>
<comment xml:lang="bs">Valentina layout</comment>
<comment xml:lang="ca">Valentina layout</comment>
<comment xml:lang="ca-valencia">Valentina layout</comment>
<comment xml:lang="cs">Valentina layout</comment>
<comment xml:lang="cy">Valentina layout</comment>
<comment xml:lang="da">Valentina layout</comment>
<comment xml:lang="de">Valentina layout</comment>
<comment xml:lang="dz">Valentina layout</comment>
<comment xml:lang="el">Valentina layout</comment>
<comment xml:lang="en-GB">Valentina layout</comment>
<comment xml:lang="en-ZA">Valentina layout</comment>
<comment xml:lang="eo">Valentina layout</comment>
<comment xml:lang="es">Valentina layout</comment>
<comment xml:lang="et">Valentina layout</comment>
<comment xml:lang="eu">Valentina layout</comment>
<comment xml:lang="fa">Valentina layout</comment>
<comment xml:lang="fi">Valentina layout</comment>
<comment xml:lang="fr">Valentina layout</comment>
<comment xml:lang="ga">Valentina layout</comment>
<comment xml:lang="gd">Valentina layout</comment>
<comment xml:lang="gl">Valentina layout</comment>
<comment xml:lang="gu">Valentina layout</comment>
<comment xml:lang="he">Valentina layout</comment>
<comment xml:lang="hi">Valentina layout</comment>
<comment xml:lang="hr">Valentina layout</comment>
<comment xml:lang="hu">Valentina layout</comment>
<comment xml:lang="id">Valentina layout</comment>
<comment xml:lang="is">Valentina layout</comment>
<comment xml:lang="it">Valentina layout</comment>
<comment xml:lang="ja">Valentina layout</comment>
<comment xml:lang="ka">Valentina layout</comment>
<comment xml:lang="kk">Valentina layout</comment>
<comment xml:lang="km">Valentina layout</comment>
<comment xml:lang="kmr-Latn">Valentina layout</comment>
<comment xml:lang="ko">Valentina layout</comment>
<comment xml:lang="lt">Valentina layout</comment>
<comment xml:lang="lv">Valentina layout</comment>
<comment xml:lang="mk">Valentina layout</comment>
<comment xml:lang="ml">Valentina layout</comment>
<comment xml:lang="mn">Valentina layout</comment>
<comment xml:lang="mr">Valentina layout</comment>
<comment xml:lang="nb">Valentina layout</comment>
<comment xml:lang="ne">Valentina layout</comment>
<comment xml:lang="nl">Valentina layout</comment>
<comment xml:lang="nn">Valentina layout</comment>
<comment xml:lang="nr">Valentina layout</comment>
<comment xml:lang="nso">Valentina layout</comment>
<comment xml:lang="oc">Valentina layout</comment>
<comment xml:lang="om">Valentina layout</comment>
<comment xml:lang="or">Valentina layout</comment>
<comment xml:lang="pa-IN">Valentina layout</comment>
<comment xml:lang="pl">Valentina layout</comment>
<comment xml:lang="pt">Valentina layout</comment>
<comment xml:lang="pt-BR">Valentina layout</comment>
<comment xml:lang="ro">Valentina layout</comment>
<comment xml:lang="ru">Valentina раскладка</comment>
<comment xml:lang="rw">Valentina layout</comment>
<comment xml:lang="si">Valentina layout</comment>
<comment xml:lang="sk">Valentina layout</comment>
<comment xml:lang="sl">Valentina layout</comment>
<comment xml:lang="sr">Valentina layout</comment>
<comment xml:lang="ss">Valentina layout</comment>
<comment xml:lang="st">Valentina layout</comment>
<comment xml:lang="sv">Valentina layout</comment>
<comment xml:lang="ta">Valentina layout</comment>
<comment xml:lang="te">Valentina layout</comment>
<comment xml:lang="tg">Valentina layout</comment>
<comment xml:lang="th">Valentina layout</comment>
<comment xml:lang="tn">Valentina layout</comment>
<comment xml:lang="tr">Valentina layout</comment>
<comment xml:lang="ts">Valentina layout</comment>
<comment xml:lang="ug">Valentina layout</comment>
<comment xml:lang="uk">Valentina розкладка</comment>
<comment xml:lang="uz">Valentina layout</comment>
<comment xml:lang="ve">Valentina layout</comment>
<comment xml:lang="vi">Valentina layout</comment>
<comment xml:lang="xh">Valentina layout</comment>
<comment xml:lang="zh-CN">Valentina layout</comment>
<comment xml:lang="zh-TW">Valentina layout</comment>
<comment xml:lang="zu">Valentina layout</comment>
<glob pattern="*.vlt"/>
<icon name="application-x-valentina-layout"/>
</mime-type>
</mime-info>

View file

@ -59,6 +59,7 @@ src_install() {
doman dist/debian/${PN}.1
doman dist/debian/tape.1
doman dist/debian/puzzle.1
cp dist/debian/valentina.sharedmimeinfo dist/debian/${PN}.xml || die
insinto /usr/share/mime/packages

BIN
dist/macx/layout.icns vendored Normal file

Binary file not shown.

72
dist/macx/puzzle/Info.plist vendored Executable file
View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>CFBundleIconFile</key>
<string>@ICON@</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSMinimumSystemVersion</key>
<string>10.7</string>
<key>NSHumanReadableCopyright</key>
<string>© 2013-2021, Valentina project</string>
<key>CFBundleSignature</key>
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@EXECUTABLE@</string>
<key>CFBundleIdentifier</key>
<string>io.bitbucket.valentinaproject.@EXECUTABLE@</string>
<key>CFBundleShortVersionString</key>
<string>0.7.47</string>
<key>CFBundleVersion</key>
<string>0.7.47.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleTypeIconFile</key>
<string>layout.incs</string>
<key>LSItemContentTypes</key>
<array>
<string>io.bitbucket.valentinaproject.vlt</string>
</array>
<key>CFBundleTypeName</key>
<string>Valentina layout</string>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.text</string>
<string>public.xml</string>
</array>
<key>UTTypeDescription</key>
<string>Valentina layout</string>
<key>UTTypeIconFile</key>
<string>layout.icns</string>
<key>UTTypeIdentifier</key>
<string>io.bitbucket.valentinaproject.vlt</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>vlt</string>
</array>
<key>public.mime-type</key>
<string>text/xml</string>
</dict>
</dict>
</array>
<key>NSRequiresAquaSystemAppearance</key>
<true/>
</dict>
</plist>

14
dist/puzzle.desktop vendored Normal file
View file

@ -0,0 +1,14 @@
[Desktop Entry]
Type=Application
Name=Puzzle
Exec=puzzle %F
Version=1.0
GenericName=Valentina's layout editor
Comment=Create and edit layouts
Comment[uk]=Створюйте і редагуйте розкладки
Comment[ru]=Создавайте и редактируйте раскладку
Icon=puzzle
Terminal=false
MimeType=application/x-valentina-layout;
Categories=Qt;Utility;FileTools;
TryExec=puzzle

View file

@ -151,6 +151,9 @@ gzip -9c dist/debian/%{name}.1 > dist/debian/%{name}.1.gz &&
gzip -9c dist/debian/tape.1 > dist/debian/tape.1.gz &&
%{__install} -Dm 644 dist/debian/tape.1.gz %{buildroot}%{_mandir}/man1/tape.1.gz
gzip -9c dist/debian/puzzle.1 > dist/debian/puzzle.1.gz &&
%{__install} -Dm 644 dist/debian/puzzle.1.gz %{buildroot}%{_mandir}/man1/puzzle.1.gz
cp dist/debian/valentina.sharedmimeinfo dist/debian/%{name}.xml &&
%{__install} -Dm 644 dist/debian/%{name}.xml %{buildroot}%{_datadir}/mime/packages/%{name}.xml
@ -160,6 +163,7 @@ cp dist/debian/valentina.mime dist/debian/%{name} &&
%if 0%{?suse_version} > 0
%suse_update_desktop_file -r %{name} Graphics VectorGraphics 2DGraphics
%suse_update_desktop_file -r tape Utility Applet
%suse_update_desktop_file -r puzzle Utility Applet
%endif
%post
@ -194,8 +198,10 @@ fi
%license LICENSE_GPL.txt
%doc %{_mandir}/man1/%{name}.1*
%doc %{_mandir}/man1/tape.1*
%doc %{_mandir}/man1/puzzle.1*
%{_bindir}/valentina
%{_bindir}/tape
%{_bindir}/puzzle
%{_libdir}/libvpropertyexplorer.so
%{_libdir}/libvpropertyexplorer.so.*
%{_libdir}/libqmuparser.so
@ -208,6 +214,7 @@ fi
%{_datadir}/mime/packages/%{name}.xml
%{_datadir}/applications/%{name}.desktop
%{_datadir}/applications/tape.desktop
%{_datadir}/applications/puzzle.desktop
%dir %{_datadir}/icons/
%dir %{_datadir}/icons/hicolor/
@ -242,7 +249,7 @@ fi
%{_datadir}/%{name}/labels/*.xml
%clean
rm -f dist/debian/%{name}.1.gz dist/debian/tape.1.gz dist/debian/%{name}.xml dist/debian/%{name}
rm -f dist/debian/%{name}.1.gz dist/debian/tape.1.gz dist/debian/puzzle.1.gz dist/debian/%{name}.xml dist/debian/%{name}
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}

View file

@ -86,6 +86,7 @@ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescrip
Name: "fileassoc1"; Description: "{cm:CreateFileAssocVal}"; GroupDescription: "{cm:FileAssoc}"
Name: "fileassoc2"; Description: "{cm:CreateFileAssocVit}"; GroupDescription: "{cm:FileAssoc}"
Name: "fileassoc3"; Description: "{cm:CreateFileAssocVst}"; GroupDescription: "{cm:FileAssoc}"
Name: "fileassoc4"; Description: "{cm:CreateFileAssocVlt}"; GroupDescription: "{cm:FileAssoc}"
Name: "deletesettings"; Description: "{cm:RemoveAnyExistingSettings}"; GroupDescription: "{cm:ManageSettings}"; Flags: unchecked
[Types]
@ -161,6 +162,7 @@ Name: "lang_files\chinese"; Description: "Chinese (China)"; Types: full custom;
; Signing
Source: ".\valentina\valentina.exe"; DestDir: "{app}"; Flags: ignoreversion sign
Source: ".\valentina\tape.exe"; DestDir: "{app}"; Flags: ignoreversion sign
Source: ".\valentina\puzzle.exe"; DestDir: "{app}"; Flags: ignoreversion sign
Source: ".\valentina\vpropertyexplorer.dll"; DestDir: "{app}"; Flags: ignoreversion sign
Source: ".\valentina\qmuparser2.dll"; DestDir: "{app}"; Flags: ignoreversion sign
; Localizations
@ -249,6 +251,7 @@ Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChang
Root: "HKCR"; Subkey: ".val"; ValueType: string; ValueName: ""; ValueData: "Valentina.Pattern"; Flags: uninsdeletevalue; Tasks: fileassoc1
Root: "HKCR"; Subkey: ".vit"; ValueType: string; ValueName: ""; ValueData: "Valentina.IndividualMeasurements"; Flags: uninsdeletevalue; Tasks: fileassoc2
Root: "HKCR"; Subkey: ".vst"; ValueType: string; ValueName: ""; ValueData: "Valentina.StandardMeasurements"; Flags: uninsdeletevalue; Tasks: fileassoc3
Root: "HKCR"; Subkey: ".vlt"; ValueType: string; ValueName: ""; ValueData: "Valentina.Layout"; Flags: uninsdeletevalue; Tasks: fileassoc3
Root: "HKCR"; Subkey: "Valentina.Pattern"; ValueType: string; ValueData: "Valentina pattern file"; Flags: uninsdeletekey; Tasks: fileassoc1
Root: "HKCR"; Subkey: "Valentina.Pattern\DefaultIcon"; ValueType: string; ValueData: "{app}\pattern.ico,0"; Tasks: fileassoc1
@ -262,6 +265,10 @@ Root: "HKCR"; Subkey: "Valentina.StandardMeasurements"; ValueType: string; Value
Root: "HKCR"; Subkey: "Valentina.StandardMeasurements\DefaultIcon"; ValueType: string; ValueData: "{app}\s-measurements.ico,0"; Tasks: fileassoc3
Root: "HKCR"; Subkey: "Valentina.StandardMeasurements\shell\open\command"; ValueType: string; ValueData: """{app}\tape.exe"" ""%1"""; Tasks: fileassoc3
Root: "HKCR"; Subkey: "Valentina.Layout"; ValueType: string; ValueData: "Valentina layout file"; Flags: uninsdeletekey; Tasks: fileassoc1
Root: "HKCR"; Subkey: "Valentina.Layout\DefaultIcon"; ValueType: string; ValueData: "{app}\layout.ico,0"; Tasks: fileassoc1
Root: "HKCR"; Subkey: "Valentina.Layout\shell\open\command"; ValueType: string; ValueData: """{app}\puzzle.exe"" ""%1"""; Tasks: fileassoc1
[CustomMessages]
FileAssoc = Create file associations
english.FileAssoc = Create file associations
@ -287,6 +294,12 @@ russian.CreateFileAssocVst = *.vst (Мультиразмерный файл ме
ukrainian.CreateFileAssocVst = *.vst (Мультирозмірний файл мірок)
german.CreateFileAssocVst = *.vst (Multi-Size Maßdatei)
CreateFileAssocVlt = *.vlt (Layout file)
english.CreateFileAssocVlt = *.vlt (Layout file)
russian.CreateFileAssocVlt = *.vlt (Файл раскладки)
ukrainian.CreateFileAssocVlt = *.vlt (Файл роскладки)
german.CreateFileAssocVlt = *.vlt (Layoutdatei)
WarnRemoveOld = is installed at the moment. Remove old version?
english.WarnRemoveOld = is installed at the moment. Remove old version?
russian.WarnRemoveOld = установлена на данный момент. Удалить старую версию?

BIN
dist/win/layout.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

0
scripts/travis-deploy.sh Executable file → Normal file
View file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -10,6 +10,7 @@ TEMPLATE = app
DEPENDPATH += \
../../src/app/valentina \
../../src/app/tape \
../../src/app/puzzle \
../../src/libs/qmuparser \
../../src/libs/vpropertyexplorer \
../../src/libs/ifc \
@ -25,6 +26,7 @@ DEPENDPATH += \
include(../../src/app/valentina/valentina.pri)
include(../../src/app/tape/tape.pri)
include(../../src/app/puzzle/puzzle.pri)
include(../../src/libs/qmuparser/qmuparser.pri)
include(../../src/libs/vpropertyexplorer/vpropertyexplorer.pri)
include(../../src/libs/ifc/ifc.pri)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,10 @@
TEMPLATE = subdirs
SUBDIRS = \
tape \
valentina
valentina \
puzzle
macx{# For making app bundle tape must exist before valentina.app will be created
macx{# For making app bundle tape and puzzle must exist before valentina.app will be created
valentina.depends = tape
valentina.depends = puzzle
}

View file

@ -0,0 +1,292 @@
/************************************************************************
**
** @file vpcarrousel.cpp
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpcarrousel.h"
#include "ui_vpcarrousel.h"
#include <QVBoxLayout>
#include <QMessageBox>
#include <QScrollBar>
#include <QFontMetrics>
#include "../vmisc/backport/qoverload.h"
#include "../layout/vpsheet.h"
#include "../layout/vplayout.h"
#include <QLoggingCategory>
#include <QMenu>
#include <QPainter>
Q_LOGGING_CATEGORY(pCarrousel, "p.carrousel")
//---------------------------------------------------------------------------------------------------------------------
VPCarrousel::VPCarrousel(const VPLayoutPtr &layout, QWidget *parent) :
QWidget(parent),
ui(new Ui::VPCarrousel),
m_layout(layout)
{
SCASSERT(not layout.isNull())
ui->setupUi(this);
ui->listWidget->SetCarrousel(this);
// init the combo box
connect(ui->comboBoxPieceList, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&VPCarrousel::on_ActivePieceListChanged);
connect(layout.get(), &VPLayout::ActiveSheetChanged, this, &VPCarrousel::on_ActiveSheetChanged);
connect(layout.get(), &VPLayout::SheetListChanged, this, &VPCarrousel::Refresh);
// ------ then we fill the carrousel with the layout content
Refresh();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::Refresh()
{
const QUuid sheetUuid = ui->comboBoxPieceList->currentData().toUuid();
// --- clears the content of the carrousel
ui->comboBoxPieceList->blockSignals(true);
Clear();
ui->comboBoxPieceList->blockSignals(false);
// --- add the content saved in the layout to the carrousel.
// Do not rely on m_layout because we do not control it.
m_pieceLists = QList<VPCarrouselSheet>();
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
{
VPCarrouselSheet carrouselSheet;
carrouselSheet.unplaced = true;
carrouselSheet.active = false;
carrouselSheet.name = tr("Unplaced pieces");
carrouselSheet.pieces = layout->GetUnplacedPieces();
m_pieceLists.append(carrouselSheet);
}
QList<VPSheetPtr> sheets = layout->GetSheets();
for (const auto &sheet : sheets)
{
if (not sheet.isNull())
{
VPCarrouselSheet carrouselSheet;
carrouselSheet.unplaced = false;
carrouselSheet.active = (sheet == layout->GetFocusedSheet());
carrouselSheet.name = sheet->GetName();
carrouselSheet.pieces = sheet->GetPieces();
carrouselSheet.sheetUuid = sheet->Uuid();
m_pieceLists.append(carrouselSheet);
}
}
ui->comboBoxPieceList->blockSignals(true);
for (const auto& sheet: m_pieceLists)
{
ui->comboBoxPieceList->addItem(GetSheetName(sheet), sheet.sheetUuid);
}
ui->comboBoxPieceList->blockSignals(false);
}
ui->comboBoxPieceList->blockSignals(true);
ui->comboBoxPieceList->setCurrentIndex(-1);
ui->comboBoxPieceList->blockSignals(false);
int index = ui->comboBoxPieceList->findData(sheetUuid);
ui->comboBoxPieceList->setCurrentIndex(index != -1 ? index : 0);
RefreshOrientation();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::on_ActiveSheetChanged(const VPSheetPtr &sheet)
{
if (not sheet.isNull())
{
int index = ui->comboBoxPieceList->findData(sheet->Uuid());
if (index != -1)
{
ui->comboBoxPieceList->setCurrentIndex(index);
}
}
else
{
ui->comboBoxPieceList->setCurrentIndex(0);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::RefreshSheetNames()
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return;
}
for (int i=0; i < m_pieceLists.size(); ++i)
{
if (not m_pieceLists.at(i).unplaced)
{
VPSheetPtr sheet = layout->GetSheet(m_pieceLists.at(i).sheetUuid);
if (not sheet.isNull())
{
m_pieceLists[i].name = sheet->GetName();
m_pieceLists[i].active = (sheet == layout->GetFocusedSheet());
}
}
else
{
m_pieceLists[i].name = tr("Unplaced pieces");
}
ui->comboBoxPieceList->setItemText(i, GetSheetName(m_pieceLists.at(i)));
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::Clear()
{
// remove the combobox entries
ui->comboBoxPieceList->clear();
ui->listWidget->clear();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::on_ActivePieceListChanged(int index)
{
qCDebug(pCarrousel, "index changed %i", index);
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return;
}
if (not m_pieceLists.isEmpty() && index >= 0 && index < m_pieceLists.size())
{
ui->listWidget->SetCurrentPieceList(m_pieceLists.at(index).pieces);
if (index > 0)
{
QUuid sheetUuid = ui->comboBoxPieceList->currentData().toUuid();
VPSheetPtr sheet = layout->GetSheet(sheetUuid);
if (not sheet.isNull())
{
VPSheetPtr activeSheet = layout->GetFocusedSheet();
if (not activeSheet.isNull())
{
activeSheet->ClearSelection();
}
m_ignoreActiveSheetChange = true;
layout->SetFocusedSheet(sheet);
m_ignoreActiveSheetChange = false;
}
}
}
else
{
ui->listWidget->SetCurrentPieceList(QList<VPPiecePtr>());
m_ignoreActiveSheetChange = true;
layout->SetFocusedSheet(VPSheetPtr());
m_ignoreActiveSheetChange = false;
}
RefreshSheetNames();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::SetOrientation(Qt::Orientation orientation)
{
m_orientation = orientation;
RefreshOrientation();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::RefreshOrientation()
{
// then update the scrollarea min height / width and scrollbar behaviour
if(m_orientation == Qt::Horizontal)
{
ui->comboBoxPieceList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// scroll bar policy of scroll area
ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
ui->listWidget->setFlow(QListView::TopToBottom);
}
else // Qt::Vertical
{
ui->comboBoxPieceList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
// scroll bar policy of scroll area
ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->listWidget->setFlow(QListView::LeftToRight);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
RefreshSheetNames();
on_ActivePieceListChanged(ui->comboBoxPieceList->currentIndex());
}
// remember to call base class implementation
QWidget::changeEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPCarrousel::GetSheetName(const VPCarrouselSheet &sheet) -> QString
{
if (sheet.unplaced)
{
return sheet.name;
}
if (sheet.active)
{
return QStringLiteral("--> %1 %2 <--").arg(tr("Pieces of"), sheet.name);
}
return tr("Pieces of ") + sheet.name;
}

View file

@ -0,0 +1,112 @@
/************************************************************************
**
** @file vpcarrousel.h
** @author Ronan Le Tiec
** @date 13 04, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPCARROUSEL_H
#define VPCARROUSEL_H
#include <QWidget>
#include <QComboBox>
#include <QScrollArea>
#include "../layout/vppiece.h"
#include "../layout/layoutdef.h"
namespace Ui
{
class VPCarrousel;
}
struct VPCarrouselSheet
{
bool unplaced{true};
bool active{false};
QString name{};
QList<VPPiecePtr> pieces{};
QUuid sheetUuid{};
};
class VPCarrousel : public QWidget
{
Q_OBJECT
public:
explicit VPCarrousel(const VPLayoutPtr &layout, QWidget *parent = nullptr);
virtual ~VPCarrousel() = default;
/**
* @brief SetOrientation Sets the orientation to the given value and refreshes
* the orientation of the carrousel.
* @param orientation the orientation to set the carrousel to.
*/
void SetOrientation(Qt::Orientation orientation);
/**
* @brief RefreshOrientation Refreshes the orientation of the carrousel with the
* m_orientation value;
*/
void RefreshOrientation();
void RefreshSheetNames();
/**
* @brief Clear Clears the carrousel (removes everything)
*/
void Clear();
public slots:
/**
* @brief Refresh Refreshes the content of the carrousel
*/
void Refresh();
void on_ActiveSheetChanged(const VPSheetPtr &sheet);
protected:
virtual void changeEvent(QEvent* event) override;
private slots:
/**
* @brief on_ActivePieceListChanged Called when the active piece list is changed
* @param index piece index
*/
void on_ActivePieceListChanged(int index);
private:
Q_DISABLE_COPY(VPCarrousel)
Ui::VPCarrousel *ui;
VPLayoutWeakPtr m_layout{};
QList<VPCarrouselSheet> m_pieceLists{};
Qt::Orientation m_orientation{Qt::Vertical};
bool m_ignoreActiveSheetChange{false};
static auto GetSheetName(const VPCarrouselSheet &sheet) -> QString;
};
#endif // VPCARROUSEL_H

View file

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VPCarrousel</class>
<widget class="QWidget" name="VPCarrousel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>583</width>
<height>557</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Carrousel</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QComboBox" name="comboBoxPieceList">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
</widget>
</item>
<item>
<widget class="VPCarrouselPieceList" name="listWidget">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="movement">
<enum>QListView::Static</enum>
</property>
<property name="flow">
<enum>QListView::TopToBottom</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="spacing">
<number>6</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>VPCarrouselPieceList</class>
<extends>QListWidget</extends>
<header>carousel/vpcarrouselpiecelist.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,154 @@
/************************************************************************
**
** @file vpcarrouselpiece.cpp
** @author Ronan Le Tiec
** @date 25 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpcarrouselpiece.h"
#include <QApplication>
#include <QMenu>
#include <QPainter>
#include "vpmimedatapiece.h"
#include "vpcarrouselpiecelist.h"
#include "vpcarrousel.h"
#include "../layout/vpsheet.h"
#include "../layout/vppiece.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pCarrouselPiece, "p.carrouselPiece")
//---------------------------------------------------------------------------------------------------------------------
VPCarrouselPiece::VPCarrouselPiece(const VPPiecePtr &piece, QListWidget* parent) :
QListWidgetItem(parent, Type),
m_piece(piece)
{
SCASSERT(m_piece != nullptr)
int width = 120 - 8;
QFontMetrics metrix = QFontMetrics(QFont());
QString clippedText = metrix.elidedText(piece->GetName(), Qt::ElideRight, width);
setIcon(CreatePieceIcon(QSize(120, 120)));
setText(clippedText);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPCarrouselPiece::GetPiece() const -> VPPiecePtr
{
return m_piece;
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPiece::RefreshSelection()
{
VPPiecePtr piece = GetPiece();
if (not piece.isNull())
{
setSelected(piece->IsSelected());
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPCarrouselPiece::CreatePieceIcon(const QSize &size, bool isDragIcon) const -> QIcon
{
VPPiecePtr piece = GetPiece();
if (piece.isNull())
{
return {};
}
QRectF boundingRect = piece->DetailBoundingRect();
qreal canvasSize = qMax(boundingRect.height(), boundingRect.width());
QRectF canvas = QRectF(0, 0, canvasSize, canvasSize);
qreal dx = canvas.center().x() - boundingRect.center().x();
qreal dy = canvas.center().y() - boundingRect.center().y();
QVector<QIcon::Mode> iconModes;
iconModes.append(QIcon::Normal);
if(not isDragIcon)
{
iconModes.append(QIcon::Selected);
}
QIcon icon;
for(auto iconMode : iconModes)
{
QPixmap pixmap(size);
if(not isDragIcon)
{
pixmap.fill(QColor(Qt::white));
}
else
{
pixmap.fill(QColor(Qt::transparent));
}
QPainter painter;
painter.begin(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
int spacing = 2;
painter.translate(spacing, spacing);
qreal scaleFactorX = canvasSize * 100 / (size.width() - spacing*2) / 100;
qreal scaleFactorY = canvasSize * 100 / (size.height() - spacing*2) / 100;
painter.scale(1./scaleFactorX, 1./scaleFactorY);
painter.setPen(QPen(Qt::black, 0.8*qMax(scaleFactorX, scaleFactorY)));
if(not isDragIcon)
{
painter.translate(dx, dy);
}
else
{
painter.translate(-boundingRect.topLeft().x()+spacing, -boundingRect.topLeft().y()+spacing);
}
if(iconMode == QIcon::Selected)
{
painter.setBrush(QBrush(QColor(255,160,160,60)));
}
else
{
painter.setBrush(QBrush(Qt::white));
}
piece->DrawMiniature(painter);
painter.end();
icon.addPixmap(pixmap,iconMode);
}
return icon;
}

View file

@ -0,0 +1,68 @@
/************************************************************************
**
** @file vpcarrouselpiece.h
** @author Ronan Le Tiec
** @date 25 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPCARROUSELPIECE_H
#define VPCARROUSELPIECE_H
#include <QMouseEvent>
#include <QListWidgetItem>
#include "../layout/layoutdef.h"
class VPCarrouselPiece : public QListWidgetItem
{
public:
enum { Type = UserType + 1};
explicit VPCarrouselPiece(const VPPiecePtr &piece, QListWidget* parent);
virtual ~VPCarrouselPiece() = default;
/**
* @brief GetPiece Returns the corresponding layout piece
* @return the corresponding layout piece
*/
auto GetPiece() const -> VPPiecePtr;
/**
* @brief RefreshSelection refreshes the selection of the piece according to the selection information of m_piece
*/
void RefreshSelection();
/**
* @brief CreatePieceIcon Creates an icon of the piece of given size
* @param size of the icon
* @return the created icon
*/
auto CreatePieceIcon(const QSize &size, bool isDragIcon = false) const -> QIcon;
private:
Q_DISABLE_COPY(VPCarrouselPiece)
VPPieceWeakPtr m_piece;
};
#endif // VPCARROUSELPIECE_H

View file

@ -0,0 +1,250 @@
/************************************************************************
**
** @file vpcarrouselpiecelist.cpp
** @author Ronan Le Tiec
** @date 25 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpcarrouselpiecelist.h"
#include <QDrag>
#include <QDragMoveEvent>
#include <QPainter>
#include <QApplication>
#include <QMenu>
#include "vpcarrousel.h"
#include "vpcarrouselpiece.h"
#include "../vmisc/backport/qoverload.h"
#include "vpmimedatapiece.h"
#include "../layout/vpsheet.h"
#include "../layout/vplayout.h"
#include "../undocommands/vpundomovepieceonsheet.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pCarrouselPieceList, "p.carrouselPieceList")
//---------------------------------------------------------------------------------------------------------------------
VPCarrouselPieceList::VPCarrouselPieceList(QWidget* parent) :
QListWidget(parent)
{
setStyleSheet("QListWidget::item{border: 2px solid transparent; color: black;} "
"QListWidget::item:selected {border: 2px solid rgb(255,160,160);}");
setContextMenuPolicy(Qt::DefaultContextMenu);
setSelectionMode(QAbstractItemView::MultiSelection);
setViewMode(QListView::IconMode);
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::SetCarrousel(VPCarrousel *carrousel)
{
m_carrousel = carrousel;
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::Refresh()
{
clear();
if(not m_pieceList.isEmpty())
{
// create the corresponding carrousel pieces
for (auto piece : m_pieceList)
{
if (not piece.isNull())
{
// update the label of the piece
auto* carrouselpiece = new VPCarrouselPiece(piece, this);
carrouselpiece->setSelected(piece->IsSelected());
}
}
sortItems();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::SetCurrentPieceList(const QList<VPPiecePtr> &pieceList)
{
m_pieceList = pieceList;
Refresh();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_dragStart = event->pos();
}
if (!(event->modifiers() & Qt::ControlModifier))
{
// clearSelection doesn't work properly here so we go through the elements.
for(auto *item: selectedItems())
{
item->setSelected(false);
}
}
QListWidget::mousePressEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::mouseMoveEvent(QMouseEvent *event)
{
if (((event->buttons() & Qt::LeftButton) != 0U) &&
((event->pos() - m_dragStart).manhattanLength() >= QApplication::startDragDistance()) &&
(selectedItems().count() > 0) &&
(not m_pieceList.isEmpty() && m_pieceList.first()->Sheet() == nullptr)) // only if it's from unplaced pieces
{
startDrag(Qt::MoveAction);
}
else
{
QListWidget::mouseMoveEvent(event);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::startDrag(Qt::DropActions supportedActions)
{
Q_UNUSED(supportedActions)
QListWidgetItem* _item = currentItem();
if(_item->type() == VPCarrouselPiece::Type)
{
auto *pieceItem = static_cast<VPCarrouselPiece *> (_item);
// starts the dragging
auto *drag = new QDrag(this);
auto *mimeData = new VPMimeDataPiece();
VPPiecePtr piece = pieceItem->GetPiece();
mimeData->SetPiecePtr(piece);
QPixmap pixmap = pieceItem->CreatePieceIcon(QSize(120, 120), true).pixmap(QSize(120, 120));
drag->setDragCursor(VPMimeDataPiece::DragCursor(pixmap), Qt::MoveAction);
drag->setMimeData(mimeData);
if(drag->exec() == Qt::MoveAction)
{
m_carrousel->Refresh();
piece->SetSelected(true);
VPLayoutPtr layout = piece->Layout();
if (not layout.isNull())
{
emit layout->PieceSelectionChanged(piece);
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::dragMoveEvent(QDragMoveEvent* e)
{
qCDebug(pCarrouselPieceList, "drag move");
e->acceptProposedAction();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::contextMenuEvent(QContextMenuEvent *event)
{
QListWidgetItem* _item = currentItem();
if(_item != nullptr && _item->type() == VPCarrouselPiece::Type)
{
auto *pieceItem = static_cast<VPCarrouselPiece *> (_item);
QMenu menu;
QAction *moveAction = menu.addAction(tr("Move to Sheet"));
moveAction->setVisible(false);
QAction *deleteAction = menu.addAction(tr("Delete"));
deleteAction->setVisible(false);
QAction *removeAction = menu.addAction(tr("Remove from Sheet"));
removeAction->setVisible(false);
if(not m_pieceList.isEmpty() && m_pieceList.first()->Sheet() == nullptr)
{
moveAction->setVisible(true);
deleteAction->setVisible(true);
}
if(not m_pieceList.isEmpty() && m_pieceList.first()->Sheet() != nullptr)
{
removeAction->setVisible(true);
}
QAction *selectedAction = menu.exec(event->globalPos());
VPPiecePtr piece = pieceItem->GetPiece();
VPLayoutPtr layout = piece->Layout();
if (piece.isNull() || layout.isNull())
{
return;
}
if (selectedAction == moveAction)
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
piece->ClearTransformations();
QRectF rect = sheet->GetMarginsRect();
piece->SetPosition(QPointF(rect.topLeft().x() + 1, rect.topLeft().y() + 1));
auto *command = new VPUndoMovePieceOnSheet(layout->GetFocusedSheet(), piece);
layout->UndoStack()->push(command);
}
}
else if (selectedAction == deleteAction)
{
auto *command = new VPUndoMovePieceOnSheet(layout->GetTrashSheet(), piece);
layout->UndoStack()->push(command);
}
else if (selectedAction == removeAction)
{
auto *command = new VPUndoMovePieceOnSheet(VPSheetPtr(), piece);
layout->UndoStack()->push(command);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrouselPieceList::on_SelectionChangedExternal()
{
blockSignals(true);
for(int i = 0; i < count(); ++i)
{
QListWidgetItem* _item = item(i);
if(_item->type() == VPCarrouselPiece::Type)
{
auto *itemPiece = static_cast<VPCarrouselPiece *> (_item);
itemPiece->RefreshSelection();
}
}
blockSignals(false);
}

View file

@ -0,0 +1,84 @@
/************************************************************************
**
** @file vpcarrouselpiecelist.h
** @author Ronan Le Tiec
** @date 25 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPCARROUSELPIECELIST_H
#define VPCARROUSELPIECELIST_H
#include <QListWidget>
#include "vpcarrousel.h"
class VPCarrouselPieceList : public QListWidget
{
Q_OBJECT
public:
explicit VPCarrouselPieceList(QWidget* parent);
virtual ~VPCarrouselPieceList() = default;
/**
* @brief Refresh refreshes the items of the carrousel piece list
*/
void Refresh();
/**
* @brief SetCurrentPieceList Sets the current piece list to the given piece list and redraw
* the carrousel.
*/
void SetCurrentPieceList(const QList<VPPiecePtr> &pieceList);
/**
* @brief SetCarrousel Sets the carrousel corresponding to the list
* @param carrousel pointer to the carrousel
*/
void SetCarrousel(VPCarrousel *carrousel);
public slots:
/**
* @brief on_SelectionChangedExternal when the selection was changed outside of the carrousel
*/
void on_SelectionChangedExternal();
protected:
void startDrag(Qt::DropActions supportedActions) override;
void dragMoveEvent(QDragMoveEvent* e) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
private:
Q_DISABLE_COPY(VPCarrouselPieceList)
QList<VPPiecePtr> m_pieceList{};
QPoint m_dragStart{};
VPCarrousel *m_carrousel{nullptr};
};
#endif // VPCARROUSELPIECELIST_H

View file

@ -0,0 +1,67 @@
/************************************************************************
**
** @file vpmimedatapiece.cpp
** @author Ronan Le Tiec
** @date 4 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpmimedatapiece.h"
#include <QPainter>
#include <QPixmap>
#include "../layout/vppiece.h"
const QString VPMimeDataPiece::mineFormatPiecePtr = QStringLiteral("application/vnd.puzzle.piece.ptr");
//---------------------------------------------------------------------------------------------------------------------
auto VPMimeDataPiece::formats() const -> QStringList
{
return {mineFormatPiecePtr};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPMimeDataPiece::GetPiecePtr() const -> VPPiecePtr
{
return m_piece;
}
//---------------------------------------------------------------------------------------------------------------------
void VPMimeDataPiece::SetPiecePtr(const VPPiecePtr &piece)
{
m_piece = piece;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPMimeDataPiece::DragCursor(const QPixmap &piecePixmap) -> QPixmap
{
QPixmap dragCursor(piecePixmap.width()*2, piecePixmap.height()*2);
dragCursor.fill(Qt::transparent);
QPainter painter(&dragCursor);
painter.drawPixmap(dragCursor.width()/2, dragCursor.height()/2, piecePixmap);
QPixmap cursor = QPixmap("://cursor/collect.png");
painter.drawPixmap(dragCursor.width()/2 - cursor.width()/2, dragCursor.height()/2 - cursor.height()/2, cursor);
painter.end();
return dragCursor;
}

View file

@ -0,0 +1,69 @@
/************************************************************************
**
** @file vpmimedatapiece.h
** @author Ronan Le Tiec
** @date 4 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPMIMEDATAPIECE_H
#define VPMIMEDATAPIECE_H
#include <QMimeData>
#include <QSharedPointer>
#include "../layout/layoutdef.h"
class VPMimeDataPiece : public QMimeData
{
Q_OBJECT
public:
VPMimeDataPiece() = default;
virtual ~VPMimeDataPiece() = default;
virtual auto formats() const -> QStringList override;
/**
* @brief GetPiecePtr Returns the piece pointer of the mime data
* @return piece pointer
*/
auto GetPiecePtr() const -> VPPiecePtr;
/**
* @brief SetPiecePtr sets the piece pointer to the given value
* @param piece the piece pointer
*/
void SetPiecePtr(const VPPiecePtr &piece);
static auto DragCursor(const QPixmap &piecePixmap) -> QPixmap;
static const QString mineFormatPiecePtr;
private:
Q_DISABLE_COPY(VPMimeDataPiece)
VPPieceWeakPtr m_piece{};
};
#endif // VPMIMEDATAPIECE_H

View file

@ -0,0 +1,163 @@
/************************************************************************
**
** @file puzzlepreferencesconfigurationpage.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 21 5, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "puzzlepreferencesconfigurationpage.h"
#include "ui_puzzlepreferencesconfigurationpage.h"
#include "../../vpapplication.h"
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesConfigurationPage::PuzzlePreferencesConfigurationPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::PuzzlePreferencesConfigurationPage)
{
ui->setupUi(this);
InitLanguages(ui->langCombo);
connect(ui->langCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]()
{
m_langChanged = true;
});
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
// Theme
ui->darkModeCheck->setChecked(settings->GetDarkMode());
// Native dialogs
ui->checkBoxDontUseNativeDialog->setChecked(settings->IsDontUseNativeDialog());
//----------------------- Toolbar
ui->toolBarStyleCheck->setChecked(settings->GetToolBarStyle());
// Undo
ui->undoCount->setValue(settings->GetUndoCount());
//Graphical output
ui->graphOutputCheck->setChecked(settings->GetGraphicalOutput());
ui->checkBoxOpenGLRender->setChecked(settings->IsOpenGLRender());
// Tab Scrolling
ui->spinBoxDuration->setMinimum(VCommonSettings::scrollingDurationMin);
ui->spinBoxDuration->setMaximum(VCommonSettings::scrollingDurationMax);
ui->spinBoxDuration->setValue(settings->GetScrollingDuration());
ui->spinBoxUpdateInterval->setMinimum(VCommonSettings::scrollingUpdateIntervalMin);
ui->spinBoxUpdateInterval->setMaximum(VCommonSettings::scrollingUpdateIntervalMax);
ui->spinBoxUpdateInterval->setValue(settings->GetScrollingUpdateInterval());
ui->doubleSpinBoxSensor->setMinimum(VCommonSettings::sensorMouseScaleMin);
ui->doubleSpinBoxSensor->setMaximum(VCommonSettings::sensorMouseScaleMax);
ui->doubleSpinBoxSensor->setValue(settings->GetSensorMouseScale());
ui->doubleSpinBoxWheel->setMinimum(VCommonSettings::wheelMouseScaleMin);
ui->doubleSpinBoxWheel->setMaximum(VCommonSettings::wheelMouseScaleMax);
ui->doubleSpinBoxWheel->setValue(settings->GetWheelMouseScale());
ui->doubleSpinBoxAcceleration->setMinimum(VCommonSettings::scrollingAccelerationMin);
ui->doubleSpinBoxAcceleration->setMaximum(VCommonSettings::scrollingAccelerationMax);
ui->doubleSpinBoxAcceleration->setValue(settings->GetScrollingAcceleration());
}
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesConfigurationPage::~PuzzlePreferencesConfigurationPage()
{
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
auto PuzzlePreferencesConfigurationPage::Apply() -> QStringList
{
QStringList preferences;
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
settings->SetToolBarStyle(ui->toolBarStyleCheck->isChecked());
if (settings->GetDarkMode() != ui->darkModeCheck->isChecked())
{
settings->SetDarkMode(ui->darkModeCheck->isChecked());
preferences.append(tr("dark mode"));
}
if (settings->IsDontUseNativeDialog() != ui->checkBoxDontUseNativeDialog->isChecked())
{
settings->SetDontUseNativeDialog(ui->checkBoxDontUseNativeDialog->isChecked());
}
if (m_langChanged)
{
const QString locale = qvariant_cast<QString>(ui->langCombo->currentData());
settings->SetLocale(locale);
m_langChanged = false;
VAbstractApplication::VApp()->LoadTranslation(locale);
qApp->processEvents();// force to call changeEvent
}
/* Maximum number of commands in undo stack may only be set when the undo stack is empty, since setting it on a
* non-empty stack might delete the command at the current index. Calling setUndoLimit() on a non-empty stack
* prints a warning and does nothing.*/
if (settings->GetUndoCount() != ui->undoCount->value())
{
preferences.append(tr("undo limit"));
settings->SetUndoCount(ui->undoCount->value());
}
// Scene antialiasing
if (settings->GetGraphicalOutput() != ui->graphOutputCheck->isChecked())
{
preferences.append(tr("antialiasing"));
settings->SetGraphicalOutput(ui->graphOutputCheck->isChecked());
}
if (settings->IsOpenGLRender() != ui->checkBoxOpenGLRender->isChecked())
{
preferences.append(tr("scene render"));
settings->SetOpenGLRender(ui->checkBoxOpenGLRender->isChecked());
}
// Tab Scrolling
settings->SetScrollingDuration(ui->spinBoxDuration->value());
settings->SetScrollingUpdateInterval(ui->spinBoxUpdateInterval->value());
settings->SetSensorMouseScale(ui->doubleSpinBoxSensor->value());
settings->SetWheelMouseScale(ui->doubleSpinBoxWheel->value());
settings->SetScrollingAcceleration(ui->doubleSpinBoxAcceleration->value());
return preferences;
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesConfigurationPage::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
}
// remember to call base class implementation
QWidget::changeEvent(event);
}

View file

@ -0,0 +1,57 @@
/************************************************************************
**
** @file puzzlepreferencesconfigurationpage.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 21 5, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef PUZZLEPREFERENCESCONFIGURATIONPAGE_H
#define PUZZLEPREFERENCESCONFIGURATIONPAGE_H
#include <QWidget>
namespace Ui
{
class PuzzlePreferencesConfigurationPage;
}
class PuzzlePreferencesConfigurationPage : public QWidget
{
Q_OBJECT
public:
explicit PuzzlePreferencesConfigurationPage(QWidget *parent = nullptr);
virtual ~PuzzlePreferencesConfigurationPage();
QStringList Apply();
protected:
virtual void changeEvent(QEvent* event) override;
private:
Q_DISABLE_COPY(PuzzlePreferencesConfigurationPage)
Ui::PuzzlePreferencesConfigurationPage *ui;
bool m_langChanged{false};
};
#endif // PUZZLEPREFERENCESCONFIGURATIONPAGE_H

View file

@ -0,0 +1,385 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PuzzlePreferencesConfigurationPage</class>
<widget class="QWidget" name="PuzzlePreferencesConfigurationPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>702</width>
<height>741</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabGeneral">
<attribute name="title">
<string>General</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>660</width>
<height>672</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Language</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>GUI language:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="langCombo"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Toolbar</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QCheckBox" name="toolBarStyleCheck">
<property name="text">
<string>The text appears under the icon (recommended for beginners).</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>User Interface</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QCheckBox" name="darkModeCheck">
<property name="text">
<string>Activate dark mode</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxDontUseNativeDialog">
<property name="text">
<string>Don't use the native file dialog</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Graphical output</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="graphOutputCheck">
<property name="text">
<string>Use antialiasing</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxOpenGLRender">
<property name="toolTip">
<string>Use OpenGL to render a scene.
This option will take an affect after restart.</string>
</property>
<property name="text">
<string>Use OpenGL render</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Undo</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Count steps (0 - no limit):</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="undoCount"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabScrolling">
<attribute name="title">
<string>Scrolling</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QScrollArea" name="scrollArea_2">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>660</width>
<height>672</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Animation</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Duration:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxDuration">
<property name="toolTip">
<string>Scrolling animation duration</string>
</property>
<property name="suffix">
<string comment="milliseconds">ms</string>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>300</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Update interval:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxUpdateInterval">
<property name="toolTip">
<string>Time in milliseconds between each animation update</string>
</property>
<property name="suffix">
<string comment="milliseconds">ms</string>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>30</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string>Mouse scale</string>
</property>
<layout class="QFormLayout" name="formLayout_4">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string comment="sensor mouse">Sensor:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxSensor">
<property name="toolTip">
<string>Scale scrolling sensitivity for mouse with sensor</string>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>2.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string comment="mouse wheel">Wheel:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxWheel">
<property name="toolTip">
<string>Scale scrolling sensitivity for mouse with wheel</string>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>45.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Scrolling</string>
</property>
<layout class="QFormLayout" name="formLayout_5">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Acceleration:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxAcceleration">
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.300000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>359</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,659 @@
/************************************************************************
**
** @file puzzlepreferenceslayoutpage.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 20 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "puzzlepreferenceslayoutpage.h"
#include "ui_puzzlepreferenceslayoutpage.h"
#include "vpapplication.h"
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesLayoutPage::PuzzlePreferencesLayoutPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::PuzzlePreferencesLayoutPage)
{
ui->setupUi(this);
VPApplication::VApp()->PuzzleSettings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
InitLayoutUnits();
VAbstractLayoutDialog::InitTemplates(ui->comboBoxSheetTemplates);
VAbstractLayoutDialog::InitTileTemplates(ui->comboBoxTileTemplates);
MinimumSheetPaperSize();
MinimumTilePaperSize();
ReadSettings();
connect(ui->comboBoxLayoutUnit, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &PuzzlePreferencesLayoutPage::ConvertPaperSize);
connect(ui->comboBoxSheetTemplates, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]{SheetSize(SheetTemplate());});
connect(ui->comboBoxTileTemplates, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]{TileSize(TileTemplate());});
connect(ui->doubleSpinBoxSheetPaperWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::SheetPaperSizeChanged);
connect(ui->doubleSpinBoxSheetPaperHeight, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::SheetPaperSizeChanged);
connect(ui->doubleSpinBoxTilePaperWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::TilePaperSizeChanged);
connect(ui->doubleSpinBoxTilePaperHeight, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::TilePaperSizeChanged);
connect(ui->doubleSpinBoxSheetPaperWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::FindSheetTemplate);
connect(ui->doubleSpinBoxSheetPaperHeight, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::FindSheetTemplate);
connect(ui->doubleSpinBoxTilePaperWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::FindTileTemplate);
connect(ui->doubleSpinBoxTilePaperHeight, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::FindTileTemplate);
connect(ui->doubleSpinBoxSheetPaperWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins);
connect(ui->doubleSpinBoxSheetPaperHeight, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins);
connect(ui->doubleSpinBoxTilePaperWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins);
connect(ui->doubleSpinBoxTilePaperHeight, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &PuzzlePreferencesLayoutPage::CorrectMaxMargins);
connect(ui->checkBoxLayoutIgnoreFileds, &QCheckBox::stateChanged, this,
&PuzzlePreferencesLayoutPage::LayoutSheetIgnoreMargins);
connect(ui->checkBoxTileIgnoreFileds, &QCheckBox::stateChanged, this,
&PuzzlePreferencesLayoutPage::LayoutTileIgnoreMargins);
connect(ui->toolButtonSheetPortraitOritation, &QToolButton::toggled, this,
&PuzzlePreferencesLayoutPage::SwapSheetOrientation);
connect(ui->toolButtonSheetLandscapeOrientation, &QToolButton::toggled, this,
&PuzzlePreferencesLayoutPage::SwapSheetOrientation);
connect(ui->toolButtonTilePortraitOrientation, &QToolButton::toggled, this,
&PuzzlePreferencesLayoutPage::SwapTileOrientation);
connect(ui->toolButtonTileLandscapeOrientation, &QToolButton::toggled, this,
&PuzzlePreferencesLayoutPage::SwapTileOrientation);
}
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesLayoutPage::~PuzzlePreferencesLayoutPage()
{
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
auto PuzzlePreferencesLayoutPage::Apply() -> QStringList
{
QStringList preferences;
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
settings->SetLayoutUnit(LayoutUnit());
settings->SetLayoutSheetPaperHeight(
UnitConvertor(ui->doubleSpinBoxSheetPaperHeight->value(), m_oldLayoutUnit, Unit::Px));
settings->SetLayoutSheetPaperWidth(
UnitConvertor(ui->doubleSpinBoxSheetPaperWidth->value(), m_oldLayoutUnit, Unit::Px));
settings->SetLayoutSheetIgnoreMargins(ui->checkBoxLayoutIgnoreFileds->isChecked());
settings->SetLayoutSheetMargins(GetSheetMargins());
settings->SetLayoutTileShowTiles(ui->checkBoxTileShowTiles->isChecked());
settings->SetLayoutTileShowWatermark(ui->checkBoxTileShowWatermark->isChecked());
settings->SetLayoutTilePaperHeight(
UnitConvertor(ui->doubleSpinBoxTilePaperHeight->value(), m_oldLayoutUnit, Unit::Px));
settings->SetLayoutTilePaperWidth(
UnitConvertor(ui->doubleSpinBoxTilePaperWidth->value(), m_oldLayoutUnit, Unit::Px));
settings->SetLayoutTileIgnoreMargins(ui->checkBoxTileIgnoreFileds->isChecked());
settings->SetLayoutTileMargins(GetTileMargins());
settings->SetLayoutPieceGap(UnitConvertor(ui->doubleSpinBoxPiecesGap->value(), m_oldLayoutUnit, Unit::Px));
settings->SetLayoutWarningPiecesSuperposition(ui->checkBoxWarningPiecesSuperposition->isChecked());
settings->SetLayoutStickyEdges(ui->checkBoxStickyEdges->isChecked());
settings->SetLayoutWarningPiecesOutOfBound(ui->checkBoxWarningPiecesOutOfBound->isChecked());
settings->SetLayoutFollowGrainline(ui->checkBoxFollowGrainline->isChecked());
preferences.append(tr("default layout settings"));
return preferences;
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
}
// remember to call base class implementation
QWidget::changeEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::ConvertPaperSize()
{
const Unit layoutUnit = LayoutUnit();
const qreal sheetWidth = ui->doubleSpinBoxSheetPaperWidth->value();
const qreal sheetHeight = ui->doubleSpinBoxSheetPaperHeight->value();
const qreal sheetLeftMargin = ui->doubleSpinBoxSheetMarginLeft->value();
const qreal sheetRightMargin = ui->doubleSpinBoxSheetMarginRight->value();
const qreal sheetTopMargin = ui->doubleSpinBoxSheetMarginTop->value();
const qreal sheetBottomMargin = ui->doubleSpinBoxSheetMarginBottom->value();
ui->doubleSpinBoxSheetPaperWidth->blockSignals(true);
ui->doubleSpinBoxSheetPaperHeight->blockSignals(true);
ui->doubleSpinBoxSheetPaperWidth->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit));
ui->doubleSpinBoxSheetPaperHeight->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit));
ui->doubleSpinBoxSheetPaperWidth->blockSignals(false);
ui->doubleSpinBoxSheetPaperHeight->blockSignals(false);
const qreal newSheetWidth = UnitConvertor(sheetWidth, m_oldLayoutUnit, layoutUnit);
const qreal newSheetHeight = UnitConvertor(sheetHeight, m_oldLayoutUnit, layoutUnit);
const qreal newSheetLeftMargin = UnitConvertor(sheetLeftMargin, m_oldLayoutUnit, layoutUnit);
const qreal newSheetRightMargin = UnitConvertor(sheetRightMargin, m_oldLayoutUnit, layoutUnit);
const qreal newSheetTopMargin = UnitConvertor(sheetTopMargin, m_oldLayoutUnit, layoutUnit);
const qreal newSheetBottomMargin = UnitConvertor(sheetBottomMargin, m_oldLayoutUnit, layoutUnit);
const qreal tileWidth = ui->doubleSpinBoxTilePaperWidth->value();
const qreal tileHeight = ui->doubleSpinBoxTilePaperHeight->value();
const qreal tileLeftMargin = ui->doubleSpinBoxTileMarginLeft->value();
const qreal tileRightMargin = ui->doubleSpinBoxTileMarginRight->value();
const qreal tileTopMargin = ui->doubleSpinBoxTileMarginTop->value();
const qreal tileBottomMargin = ui->doubleSpinBoxTileMarginBottom->value();
ui->doubleSpinBoxTilePaperWidth->blockSignals(true);
ui->doubleSpinBoxTilePaperHeight->blockSignals(true);
ui->doubleSpinBoxTilePaperWidth->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit));
ui->doubleSpinBoxTilePaperHeight->setMaximum(FromPixel(QIMAGE_MAX, layoutUnit));
ui->doubleSpinBoxTilePaperWidth->blockSignals(false);
ui->doubleSpinBoxTilePaperHeight->blockSignals(false);
const qreal newTileWidth = UnitConvertor(tileWidth, m_oldLayoutUnit, layoutUnit);
const qreal newTileHeight = UnitConvertor(tileHeight, m_oldLayoutUnit, layoutUnit);
const qreal newTileLeftMargin = UnitConvertor(tileLeftMargin, m_oldLayoutUnit, layoutUnit);
const qreal newTileRightMargin = UnitConvertor(tileRightMargin, m_oldLayoutUnit, layoutUnit);
const qreal newTileTopMargin = UnitConvertor(tileTopMargin, m_oldLayoutUnit, layoutUnit);
const qreal newTileBottomMargin = UnitConvertor(tileBottomMargin, m_oldLayoutUnit, layoutUnit);
qreal newGap = UnitConvertor(ui->doubleSpinBoxPiecesGap->value(), m_oldLayoutUnit, layoutUnit);
m_oldLayoutUnit = layoutUnit;
CorrectPaperDecimals();
MinimumSheetPaperSize();
MinimumTilePaperSize();
ui->doubleSpinBoxSheetPaperWidth->setValue(newSheetWidth);
ui->doubleSpinBoxSheetPaperHeight->setValue(newSheetHeight);
ui->doubleSpinBoxSheetMarginLeft->setValue(newSheetLeftMargin);
ui->doubleSpinBoxSheetMarginRight->setValue(newSheetRightMargin);
ui->doubleSpinBoxSheetMarginTop->setValue(newSheetTopMargin);
ui->doubleSpinBoxSheetMarginBottom->setValue(newSheetBottomMargin);
ui->doubleSpinBoxTilePaperWidth->setValue(newTileWidth);
ui->doubleSpinBoxTilePaperHeight->setValue(newTileHeight);
ui->doubleSpinBoxTileMarginLeft->setValue(newTileLeftMargin);
ui->doubleSpinBoxTileMarginRight->setValue(newTileRightMargin);
ui->doubleSpinBoxTileMarginTop->setValue(newTileTopMargin);
ui->doubleSpinBoxTileMarginBottom->setValue(newTileBottomMargin);
ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Cm, layoutUnit));
ui->doubleSpinBoxPiecesGap->setValue(newGap);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::LayoutSheetIgnoreMargins(int state)
{
ui->doubleSpinBoxSheetMarginLeft->setDisabled(state != 0);
ui->doubleSpinBoxSheetMarginRight->setDisabled(state != 0);
ui->doubleSpinBoxSheetMarginTop->setDisabled(state != 0);
ui->doubleSpinBoxSheetMarginBottom->setDisabled(state != 0);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::LayoutTileIgnoreMargins(int state)
{
ui->doubleSpinBoxTileMarginLeft->setDisabled(state != 0);
ui->doubleSpinBoxTileMarginRight->setDisabled(state != 0);
ui->doubleSpinBoxTileMarginTop->setDisabled(state != 0);
ui->doubleSpinBoxTileMarginBottom->setDisabled(state != 0);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::FindSheetTemplate()
{
const qreal width = ui->doubleSpinBoxSheetPaperWidth->value();
const qreal height = ui->doubleSpinBoxSheetPaperHeight->value();
FindTemplate(ui->comboBoxSheetTemplates, width, height);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::FindTileTemplate()
{
const qreal width = ui->doubleSpinBoxTilePaperWidth->value();
const qreal height = ui->doubleSpinBoxTilePaperHeight->value();
FindTemplate(ui->comboBoxTileTemplates, width, height);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::CorrectMaxMargins()
{
const qreal sheetWidth = ui->doubleSpinBoxSheetPaperWidth->value();
const qreal sheetHeight = ui->doubleSpinBoxSheetPaperHeight->value();
// 80%/2 of paper size for each field
const qreal sheetWidthMargin = (sheetWidth*80.0/100.0)/2.0;
const qreal sheetHeightMargin = (sheetHeight*80.0/100.0)/2.0;
ui->doubleSpinBoxSheetMarginLeft->setMaximum(sheetWidthMargin);
ui->doubleSpinBoxSheetMarginRight->setMaximum(sheetWidthMargin);
ui->doubleSpinBoxSheetMarginTop->setMaximum(sheetHeightMargin);
ui->doubleSpinBoxSheetMarginBottom->setMaximum(sheetHeightMargin);
const qreal tileWidth = ui->doubleSpinBoxTilePaperWidth->value();
const qreal tileHeight = ui->doubleSpinBoxTilePaperHeight->value();
// 80%/2 of paper size for each field
const qreal tileWidthMargin = (tileWidth*80.0/100.0)/2.0;
const qreal tileHeightMargin = (tileHeight*80.0/100.0)/2.0;
ui->doubleSpinBoxTileMarginLeft->setMaximum(tileWidthMargin);
ui->doubleSpinBoxTileMarginRight->setMaximum(tileWidthMargin);
ui->doubleSpinBoxTileMarginTop->setMaximum(tileHeightMargin);
ui->doubleSpinBoxTileMarginBottom->setMaximum(tileHeightMargin);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SwapSheetOrientation(bool checked)
{
if (checked)
{
const qreal width = ui->doubleSpinBoxSheetPaperWidth->value();
const qreal height = ui->doubleSpinBoxSheetPaperHeight->value();
ui->doubleSpinBoxSheetPaperWidth->blockSignals(true);
ui->doubleSpinBoxSheetPaperWidth->setValue(height);
ui->doubleSpinBoxSheetPaperWidth->blockSignals(false);
ui->doubleSpinBoxSheetPaperHeight->blockSignals(true);
ui->doubleSpinBoxSheetPaperHeight->setValue(width);
ui->doubleSpinBoxSheetPaperHeight->blockSignals(false);
SheetPaperSizeChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SwapTileOrientation(bool checked)
{
if (checked)
{
const qreal width = ui->doubleSpinBoxTilePaperWidth->value();
const qreal height = ui->doubleSpinBoxTilePaperHeight->value();
ui->doubleSpinBoxTilePaperWidth->blockSignals(true);
ui->doubleSpinBoxTilePaperWidth->setValue(height);
ui->doubleSpinBoxTilePaperWidth->blockSignals(false);
ui->doubleSpinBoxTilePaperHeight->blockSignals(true);
ui->doubleSpinBoxTilePaperHeight->setValue(width);
ui->doubleSpinBoxTilePaperHeight->blockSignals(false);
TilePaperSizeChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::InitLayoutUnits()
{
ui->comboBoxLayoutUnit->addItem(tr("Millimiters"), QVariant(UnitsToStr(Unit::Mm)));
ui->comboBoxLayoutUnit->addItem(tr("Centimeters"), QVariant(UnitsToStr(Unit::Cm)));
ui->comboBoxLayoutUnit->addItem(tr("Inches"), QVariant(UnitsToStr(Unit::Inch)));
ui->comboBoxLayoutUnit->addItem(tr("Pixels"), QVariant(UnitsToStr(Unit::Px)));
// set default unit
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
m_oldLayoutUnit = StrToUnits(settings->GetUnit());
const qint32 indexUnit = ui->comboBoxLayoutUnit->findData(settings->GetUnit());
if (indexUnit != -1)
{
ui->comboBoxLayoutUnit->setCurrentIndex(indexUnit);
}
}
//---------------------------------------------------------------------------------------------------------------------
QSizeF PuzzlePreferencesLayoutPage::Template(VAbstractLayoutDialog::PaperSizeTemplate t) const
{
const Unit layoutUnit = LayoutUnit();
switch (t)
{
case VAbstractLayoutDialog::PaperSizeTemplate::A0:
case VAbstractLayoutDialog::PaperSizeTemplate::A1:
case VAbstractLayoutDialog::PaperSizeTemplate::A2:
case VAbstractLayoutDialog::PaperSizeTemplate::A3:
case VAbstractLayoutDialog::PaperSizeTemplate::A4:
case VAbstractLayoutDialog::PaperSizeTemplate::Letter:
case VAbstractLayoutDialog::PaperSizeTemplate::Legal:
case VAbstractLayoutDialog::PaperSizeTemplate::Tabloid:
return VAbstractLayoutDialog::GetTemplateSize(t, layoutUnit);
case VAbstractLayoutDialog::PaperSizeTemplate::Roll24in:
case VAbstractLayoutDialog::PaperSizeTemplate::Roll30in:
case VAbstractLayoutDialog::PaperSizeTemplate::Roll36in:
case VAbstractLayoutDialog::PaperSizeTemplate::Roll42in:
case VAbstractLayoutDialog::PaperSizeTemplate::Roll44in:
case VAbstractLayoutDialog::PaperSizeTemplate::Roll48in:
case VAbstractLayoutDialog::PaperSizeTemplate::Roll62in:
case VAbstractLayoutDialog::PaperSizeTemplate::Roll72in:
return VAbstractLayoutDialog::GetTemplateSize(t, layoutUnit);
case VAbstractLayoutDialog::PaperSizeTemplate::Custom:
return VAbstractLayoutDialog::GetTemplateSize(t, layoutUnit);
default:
break;
}
return QSizeF();
}
//---------------------------------------------------------------------------------------------------------------------
auto PuzzlePreferencesLayoutPage::SheetTemplate() const -> QSizeF
{
auto t = static_cast<VAbstractLayoutDialog::PaperSizeTemplate>(ui->comboBoxSheetTemplates->currentData().toInt());
return Template(t);
}
//---------------------------------------------------------------------------------------------------------------------
auto PuzzlePreferencesLayoutPage::TileTemplate() const -> QSizeF
{
auto t = static_cast<VAbstractLayoutDialog::PaperSizeTemplate>(ui->comboBoxTileTemplates->currentData().toInt());
return Template(t);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::MinimumSheetPaperSize()
{
const qreal value = UnitConvertor(1, Unit::Px, m_oldLayoutUnit);
ui->doubleSpinBoxSheetPaperWidth->setMinimum(value);
ui->doubleSpinBoxSheetPaperHeight->setMinimum(value);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::MinimumTilePaperSize()
{
const qreal value = UnitConvertor(1, Unit::Px, m_oldLayoutUnit);
ui->doubleSpinBoxTilePaperWidth->setMinimum(value);
ui->doubleSpinBoxTilePaperHeight->setMinimum(value);
}
//---------------------------------------------------------------------------------------------------------------------
auto PuzzlePreferencesLayoutPage::LayoutUnit() const -> Unit
{
return StrToUnits(ui->comboBoxLayoutUnit->currentData().toString());
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SetLayoutUnit(Unit unit)
{
const qint32 indexUnit = ui->comboBoxLayoutUnit->findData(UnitsToStr(unit));
if (indexUnit != -1)
{
ui->comboBoxLayoutUnit->setCurrentIndex(indexUnit);
}
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SheetSize(const QSizeF &size)
{
m_oldLayoutUnit = LayoutUnit();
ui->doubleSpinBoxSheetPaperWidth->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit));
ui->doubleSpinBoxSheetPaperHeight->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit));
ui->doubleSpinBoxSheetPaperWidth->setValue(size.width());
ui->doubleSpinBoxSheetPaperHeight->setValue(size.height());
CorrectPaperDecimals();
SheetPaperSizeChanged();
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::TileSize(const QSizeF &size)
{
m_oldLayoutUnit = LayoutUnit();
ui->doubleSpinBoxTilePaperWidth->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit));
ui->doubleSpinBoxTilePaperHeight->setMaximum(FromPixel(QIMAGE_MAX, m_oldLayoutUnit));
ui->doubleSpinBoxTilePaperWidth->setValue(size.width());
ui->doubleSpinBoxTilePaperHeight->setValue(size.height());
CorrectPaperDecimals();
TilePaperSizeChanged();
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::CorrectPaperDecimals()
{
switch (m_oldLayoutUnit)
{
case Unit::Cm:
case Unit::Mm:
case Unit::Px:
ui->doubleSpinBoxSheetPaperWidth->setDecimals(2);
ui->doubleSpinBoxSheetPaperHeight->setDecimals(2);
ui->doubleSpinBoxTilePaperWidth->setDecimals(2);
ui->doubleSpinBoxTilePaperHeight->setDecimals(2);
ui->doubleSpinBoxSheetMarginLeft->setDecimals(4);
ui->doubleSpinBoxSheetMarginRight->setDecimals(4);
ui->doubleSpinBoxSheetMarginTop->setDecimals(4);
ui->doubleSpinBoxSheetMarginBottom->setDecimals(4);
ui->doubleSpinBoxTileMarginLeft->setDecimals(4);
ui->doubleSpinBoxTileMarginRight->setDecimals(4);
ui->doubleSpinBoxTileMarginTop->setDecimals(4);
ui->doubleSpinBoxTileMarginBottom->setDecimals(4);
ui->doubleSpinBoxPiecesGap->setDecimals(2);
break;
case Unit::Inch:
ui->doubleSpinBoxSheetPaperWidth->setDecimals(5);
ui->doubleSpinBoxSheetPaperHeight->setDecimals(5);
ui->doubleSpinBoxTilePaperWidth->setDecimals(5);
ui->doubleSpinBoxTilePaperHeight->setDecimals(5);
ui->doubleSpinBoxSheetMarginLeft->setDecimals(5);
ui->doubleSpinBoxSheetMarginRight->setDecimals(5);
ui->doubleSpinBoxSheetMarginTop->setDecimals(5);
ui->doubleSpinBoxSheetMarginBottom->setDecimals(5);
ui->doubleSpinBoxTileMarginLeft->setDecimals(5);
ui->doubleSpinBoxTileMarginRight->setDecimals(5);
ui->doubleSpinBoxTileMarginTop->setDecimals(5);
ui->doubleSpinBoxTileMarginBottom->setDecimals(5);
ui->doubleSpinBoxPiecesGap->setDecimals(5);
break;
default:
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SheetPaperSizeChanged()
{
bool portrait = ui->doubleSpinBoxSheetPaperHeight->value() > ui->doubleSpinBoxSheetPaperWidth->value();
ui->toolButtonSheetPortraitOritation->blockSignals(true);
ui->toolButtonSheetPortraitOritation->setChecked(portrait);
ui->toolButtonSheetPortraitOritation->blockSignals(false);
ui->toolButtonSheetLandscapeOrientation->blockSignals(true);
ui->toolButtonSheetLandscapeOrientation->setChecked(not portrait);
ui->toolButtonSheetLandscapeOrientation->blockSignals(false);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::TilePaperSizeChanged()
{
bool portrait = ui->doubleSpinBoxTilePaperHeight->value() > ui->doubleSpinBoxTilePaperWidth->value();
ui->toolButtonTilePortraitOrientation->blockSignals(true);
ui->toolButtonTilePortraitOrientation->setChecked(portrait);
ui->toolButtonTilePortraitOrientation->blockSignals(false);
ui->toolButtonTileLandscapeOrientation->blockSignals(true);
ui->toolButtonTileLandscapeOrientation->setChecked(not portrait);
ui->toolButtonTileLandscapeOrientation->blockSignals(false);
}
//---------------------------------------------------------------------------------------------------------------------
auto PuzzlePreferencesLayoutPage::GetSheetMargins() const -> QMarginsF
{
QMarginsF fields;
fields.setLeft(UnitConvertor(ui->doubleSpinBoxSheetMarginLeft->value(), m_oldLayoutUnit, Unit::Px));
fields.setRight(UnitConvertor(ui->doubleSpinBoxSheetMarginRight->value(), m_oldLayoutUnit, Unit::Px));
fields.setTop(UnitConvertor(ui->doubleSpinBoxSheetMarginTop->value(), m_oldLayoutUnit, Unit::Px));
fields.setBottom(UnitConvertor(ui->doubleSpinBoxSheetMarginBottom->value(), m_oldLayoutUnit, Unit::Px));
return fields;
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SetSheetMargins(const QMarginsF &value)
{
ui->doubleSpinBoxSheetMarginLeft->setValue(UnitConvertor(value.left(), Unit::Px, LayoutUnit()));
ui->doubleSpinBoxSheetMarginRight->setValue(UnitConvertor(value.right(), Unit::Px, LayoutUnit()));
ui->doubleSpinBoxSheetMarginTop->setValue(UnitConvertor(value.top(), Unit::Px, LayoutUnit()));
ui->doubleSpinBoxSheetMarginBottom->setValue(UnitConvertor(value.bottom(), Unit::Px, LayoutUnit()));
}
//---------------------------------------------------------------------------------------------------------------------
auto PuzzlePreferencesLayoutPage::GetTileMargins() const -> QMarginsF
{
QMarginsF fields;
fields.setLeft(UnitConvertor(ui->doubleSpinBoxTileMarginLeft->value(), m_oldLayoutUnit, Unit::Px));
fields.setRight(UnitConvertor(ui->doubleSpinBoxTileMarginRight->value(), m_oldLayoutUnit, Unit::Px));
fields.setTop(UnitConvertor(ui->doubleSpinBoxTileMarginTop->value(), m_oldLayoutUnit, Unit::Px));
fields.setBottom(UnitConvertor(ui->doubleSpinBoxTileMarginBottom->value(), m_oldLayoutUnit, Unit::Px));
return fields;
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SetTileMargins(const QMarginsF &value)
{
ui->doubleSpinBoxTileMarginLeft->setValue(UnitConvertor(value.left(), Unit::Px, LayoutUnit()));
ui->doubleSpinBoxTileMarginRight->setValue(UnitConvertor(value.right(), Unit::Px, LayoutUnit()));
ui->doubleSpinBoxTileMarginTop->setValue(UnitConvertor(value.top(), Unit::Px, LayoutUnit()));
ui->doubleSpinBoxTileMarginBottom->setValue(UnitConvertor(value.bottom(), Unit::Px, LayoutUnit()));
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::SetPieceGap(qreal gap)
{
qreal value = UnitConvertor(gap, Unit::Px, LayoutUnit());
ui->doubleSpinBoxPiecesGap->setValue(value);
CorrectPaperDecimals();
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::ReadSettings()
{
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
SetLayoutUnit(settings->LayoutUnit());
m_oldLayoutUnit = LayoutUnit();
const qreal sheetWidth = UnitConvertor(settings->GetLayoutSheetPaperWidth(), Unit::Px, LayoutUnit());
const qreal sheetHeight = UnitConvertor(settings->GetLayoutSheetPaperHeight(), Unit::Px, LayoutUnit());
SheetSize(QSizeF(sheetWidth, sheetHeight));
ui->checkBoxLayoutIgnoreFileds->setChecked(settings->GetLayoutSheetIgnoreMargins());
SetSheetMargins(settings->GetLayoutSheetMargins());
const qreal tileWidth = UnitConvertor(settings->GetLayoutTilePaperWidth(), Unit::Px, LayoutUnit());
const qreal tileHeight = UnitConvertor(settings->GetLayoutTilePaperHeight(), Unit::Px, LayoutUnit());
TileSize(QSizeF(tileWidth, tileHeight));
ui->checkBoxTileShowTiles->setChecked(settings->GetLayoutTileShowTiles());
ui->checkBoxTileShowWatermark->setChecked(settings->GetLayoutTileShowWatermark());
ui->checkBoxTileIgnoreFileds->setChecked(settings->GetLayoutTileIgnoreMargins());
SetTileMargins(settings->GetLayoutSheetMargins());
ui->checkBoxWarningPiecesSuperposition->setChecked(settings->GetLayoutWarningPiecesSuperposition());
ui->checkBoxStickyEdges->setChecked(settings->GetLayoutStickyEdges());
ui->checkBoxWarningPiecesOutOfBound->setChecked(settings->GetLayoutWarningPiecesOutOfBound());
ui->checkBoxFollowGrainline->setChecked(settings->GetLayoutFollowGrainline());
ui->doubleSpinBoxPiecesGap->setMaximum(UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Px, LayoutUnit()));
SetPieceGap(settings->GetLayoutPieceGap());
FindSheetTemplate();
FindTileTemplate();
SheetPaperSizeChanged();
TilePaperSizeChanged();
LayoutSheetIgnoreMargins(static_cast<int>(ui->checkBoxLayoutIgnoreFileds->isChecked()));
LayoutTileIgnoreMargins(static_cast<int>(ui->checkBoxTileIgnoreFileds->isChecked()));
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesLayoutPage::FindTemplate(QComboBox *box, qreal width, qreal height)
{
SCASSERT(box != nullptr)
const Unit paperUnit = LayoutUnit();
const int max = static_cast<int>(VAbstractLayoutDialog::PaperSizeTemplate::Custom);
for (int i=0; i < max; ++i)
{
const QSizeF tmplSize = VAbstractLayoutDialog::GetTemplateSize(
static_cast<VAbstractLayoutDialog::PaperSizeTemplate>(i), paperUnit);
if (QSizeF(width, height) == tmplSize || QSizeF(height, width) == tmplSize)
{
box->blockSignals(true);
const int index = box->findData(i);
if (index != -1)
{
box->setCurrentIndex(index);
}
box->blockSignals(false);
return;
}
}
box->blockSignals(true);
const int index = box->findData(max);
if (index != -1)
{
box->setCurrentIndex(index);
}
box->blockSignals(false);
}

View file

@ -0,0 +1,102 @@
/************************************************************************
**
** @file puzzlepreferenceslayoutpage.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 20 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef PUZZLEPREFERENCESLAYOUTPAGE_H
#define PUZZLEPREFERENCESLAYOUTPAGE_H
#include <QWidget>
#include "../vmisc/def.h"
#include "../vlayout/dialogs/vabstractlayoutdialog.h"
namespace Ui
{
class PuzzlePreferencesLayoutPage;
}
class PuzzlePreferencesLayoutPage : public QWidget
{
Q_OBJECT
public:
explicit PuzzlePreferencesLayoutPage(QWidget *parent = nullptr);
~PuzzlePreferencesLayoutPage();
QStringList Apply();
protected:
virtual void changeEvent(QEvent* event) override;
private slots:
void ConvertPaperSize();
void LayoutSheetIgnoreMargins(int state);
void LayoutTileIgnoreMargins(int state);
void FindSheetTemplate();
void FindTileTemplate();
void CorrectMaxMargins();
void SwapSheetOrientation(bool checked);
void SwapTileOrientation(bool checked);
private:
Q_DISABLE_COPY(PuzzlePreferencesLayoutPage)
Ui::PuzzlePreferencesLayoutPage *ui;
Unit m_oldLayoutUnit{Unit::Mm};
void InitLayoutUnits();
QSizeF Template(VAbstractLayoutDialog::PaperSizeTemplate t) const;
QSizeF SheetTemplate() const;
QSizeF TileTemplate() const;
void MinimumSheetPaperSize();
void MinimumTilePaperSize();
Unit LayoutUnit() const;
void SetLayoutUnit(Unit unit);
void SheetSize(const QSizeF &size);
void TileSize(const QSizeF &size);
void CorrectPaperDecimals();
void SheetPaperSizeChanged();
void TilePaperSizeChanged();
QMarginsF GetSheetMargins() const;
void SetSheetMargins(const QMarginsF &value);
QMarginsF GetTileMargins() const;
void SetTileMargins(const QMarginsF &value);
void SetPieceGap(qreal gap);
void ReadSettings();
void FindTemplate(QComboBox *box, qreal width, qreal height);
};
#endif // PUZZLEPREFERENCESLAYOUTPAGE_H

View file

@ -0,0 +1,663 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PuzzlePreferencesLayoutPage</class>
<widget class="QWidget" name="PuzzlePreferencesLayoutPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>616</width>
<height>668</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Sheet</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBoxPaperFormat">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="title">
<string>Format</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelLayoutUnit">
<property name="text">
<string>Unit:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxLayoutUnit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Templates:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxSheetTemplates"/>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="toolButtonSheetPortraitOritation">
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/16x16/portrait.png</normaloff>:/icon/16x16/portrait.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonSheetLandscapeOrientation">
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/16x16/landscape.png</normaloff>:/icon/16x16/landscape.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelWidth">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Width:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelHeight">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Height:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxSheetPaperHeight">
<property name="minimumSize">
<size>
<width>94</width>
<height>0</height>
</size>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxSheetPaperWidth">
<property name="minimumSize">
<size>
<width>94</width>
<height>0</height>
</size>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>99999.990000000005239</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxSheetMargin">
<property name="title">
<string>Margins</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="2">
<widget class="QLabel" name="labelSheetMarginRight">
<property name="text">
<string>Right:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QDoubleSpinBox" name="doubleSpinBoxSheetMarginTop">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labelSheetMarginTop">
<property name="text">
<string>Top:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxSheetMarginLeft">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QDoubleSpinBox" name="doubleSpinBoxSheetMarginRight">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelSheetMarginLeft">
<property name="text">
<string>Left:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="labelSheetMarginBottom">
<property name="text">
<string>Bottom:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="doubleSpinBoxSheetMarginBottom">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLayoutIgnoreFileds">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Ignore margins</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxLayoutControl">
<property name="title">
<string>Control</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<widget class="QCheckBox" name="checkBoxWarningPiecesSuperposition">
<property name="text">
<string>Warning superposition of pieces</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxWarningPiecesOutOfBound">
<property name="text">
<string>Warning pieces out of bound</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxStickyEdges">
<property name="text">
<string>Sticky edges</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxFollowGrainline">
<property name="text">
<string>Follow grainline</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelSheetPiecesGap">
<property name="text">
<string>Pieces gap</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxPiecesGap"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Tiles</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QCheckBox" name="checkBoxTileShowTiles">
<property name="text">
<string>Show Tiles on sheet</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTileShowWatermark">
<property name="toolTip">
<string>Show watermark preview</string>
</property>
<property name="text">
<string>Show watermark</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxPaperFormat_2">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="title">
<string>Format</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Templates:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxTileTemplates"/>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QToolButton" name="toolButtonTilePortraitOrientation">
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/16x16/portrait.png</normaloff>:/icon/16x16/portrait.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonTileLandscapeOrientation">
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/16x16/landscape.png</normaloff>:/icon/16x16/landscape.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelWidth_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Width:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelHeight_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Height:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxTilePaperHeight">
<property name="minimumSize">
<size>
<width>94</width>
<height>0</height>
</size>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxTilePaperWidth">
<property name="minimumSize">
<size>
<width>94</width>
<height>0</height>
</size>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>99999.990000000005239</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxSheetMargin_2">
<property name="title">
<string>Margins</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="2">
<widget class="QLabel" name="labelSheetMarginRight_2">
<property name="text">
<string>Right:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QDoubleSpinBox" name="doubleSpinBoxTileMarginTop">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labelSheetMarginTop_2">
<property name="text">
<string>Top:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxTileMarginLeft">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QDoubleSpinBox" name="doubleSpinBoxTileMarginRight">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelSheetMarginLeft_2">
<property name="text">
<string>Left:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="labelSheetMarginBottom_2">
<property name="text">
<string>Bottom:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="doubleSpinBoxTileMarginBottom">
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTileIgnoreFileds">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Ignore margins</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../../libs/vmisc/share/resources/icon.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -0,0 +1,220 @@
/************************************************************************
**
** @file puzzlepreferencespathpage.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 21 5, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "puzzlepreferencespathpage.h"
#include "ui_puzzlepreferencespathpage.h"
#include "../../vpapplication.h"
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesPathPage::PuzzlePreferencesPathPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::PuzzlePreferencesPathPage)
{
ui->setupUi(this);
InitTable();
connect(ui->pathTable, &QTableWidget::itemSelectionChanged, this, [this]()
{
ui->defaultButton->setEnabled(not ui->pathTable->selectedItems().isEmpty());
ui->defaultButton->setDefault(false);
ui->editButton->setEnabled(not ui->pathTable->selectedItems().isEmpty());
ui->editButton->setDefault(true);
});
connect(ui->defaultButton, &QPushButton::clicked, this, &PuzzlePreferencesPathPage::DefaultPath);
connect(ui->editButton, &QPushButton::clicked, this, &PuzzlePreferencesPathPage::EditPath);
}
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesPathPage::~PuzzlePreferencesPathPage()
{
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesPathPage::Apply()
{
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
settings->SetPathIndividualMeasurements(ui->pathTable->item(0, 1)->text());
settings->SetPathMultisizeMeasurements(ui->pathTable->item(1, 1)->text());
settings->SetPathPattern(ui->pathTable->item(2, 1)->text());
settings->SetPathTemplate(ui->pathTable->item(3, 1)->text());
settings->SetPathManualLayouts(ui->pathTable->item(4, 1)->text());
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesPathPage::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
InitTable();
}
// remember to call base class implementation
QWidget::changeEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesPathPage::DefaultPath()
{
const int row = ui->pathTable->currentRow();
QTableWidgetItem *item = ui->pathTable->item(row, 1);
SCASSERT(item != nullptr)
QString path;
switch (row)
{
case 0: // individual measurements
path = VCommonSettings::GetDefPathIndividualMeasurements();
break;
case 1: // multisize measurements
path = VCommonSettings::GetDefPathMultisizeMeasurements();
break;
case 2: // pattern path
path = VCommonSettings::GetDefPathPattern();
break;
case 3: // templates
path = VCommonSettings::GetDefPathTemplate();
break;
case 4: // layouts
path = VCommonSettings::GetDefPathManualLayouts();
break;
default:
break;
}
item->setText(path);
item->setToolTip(path);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesPathPage::EditPath()
{
const int row = ui->pathTable->currentRow();
QTableWidgetItem *item = ui->pathTable->item(row, 1);
SCASSERT(item != nullptr)
QString path;
switch (row)
{
case 0: // individual measurements
path = VPApplication::VApp()->PuzzleSettings()->GetPathIndividualMeasurements();
break;
case 1: // multisize measurements
path = VPApplication::VApp()->PuzzleSettings()->GetPathMultisizeMeasurements();
path = VCommonSettings::PrepareMultisizeTables(path);
break;
case 2: // pattern path
path = VPApplication::VApp()->PuzzleSettings()->GetPathPattern();
break;
case 3: // templates
path = VPApplication::VApp()->PuzzleSettings()->GetPathTemplate();
break;
case 4: // layouts
path = VPApplication::VApp()->PuzzleSettings()->GetPathManualLayouts();
break;
default:
break;
}
bool usedNotExistedDir = false;
QDir directory(path);
if (not directory.exists())
{
usedNotExistedDir = directory.mkpath(QChar('.'));
}
const QString dir = QFileDialog::getExistingDirectory(
this, tr("Open Directory"), path,
VAbstractApplication::VApp()->NativeFileDialog(QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks));
if (dir.isEmpty())
{
if (usedNotExistedDir)
{
QDir(path).rmpath(QChar('.'));
}
DefaultPath();
return;
}
item->setText(dir);
item->setToolTip(dir);
}
//---------------------------------------------------------------------------------------------------------------------
void PuzzlePreferencesPathPage::InitTable()
{
ui->pathTable->clearContents();
ui->pathTable->setRowCount(5);
ui->pathTable->setColumnCount(2);
const VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
{
ui->pathTable->setItem(0, 0, new QTableWidgetItem(tr("My Individual Measurements")));
QTableWidgetItem *item = new QTableWidgetItem(settings->GetPathIndividualMeasurements());
item->setToolTip(settings->GetPathIndividualMeasurements());
ui->pathTable->setItem(0, 1, item);
}
{
ui->pathTable->setItem(1, 0, new QTableWidgetItem(tr("My Multisize Measurements")));
QTableWidgetItem *item = new QTableWidgetItem(settings->GetPathMultisizeMeasurements());
item->setToolTip(settings->GetPathMultisizeMeasurements());
ui->pathTable->setItem(1, 1, item);
}
{
ui->pathTable->setItem(2, 0, new QTableWidgetItem(tr("My Patterns")));
QTableWidgetItem *item = new QTableWidgetItem(settings->GetPathPattern());
item->setToolTip(settings->GetPathPattern());
ui->pathTable->setItem(2, 1, item);
}
{
ui->pathTable->setItem(3, 0, new QTableWidgetItem(tr("My Templates")));
QTableWidgetItem *item = new QTableWidgetItem(settings->GetPathTemplate());
item->setToolTip(settings->GetPathTemplate());
ui->pathTable->setItem(3, 1, item);
}
{
ui->pathTable->setItem(4, 0, new QTableWidgetItem(tr("My Layouts")));
QTableWidgetItem *item = new QTableWidgetItem(settings->GetPathManualLayouts());
item->setToolTip(settings->GetPathManualLayouts());
ui->pathTable->setItem(4, 1, item);
}
ui->pathTable->verticalHeader()->setDefaultSectionSize(20);
ui->pathTable->resizeColumnsToContents();
ui->pathTable->resizeRowsToContents();
ui->pathTable->horizontalHeader()->setStretchLastSection(true);
}

View file

@ -0,0 +1,62 @@
/************************************************************************
**
** @file puzzlepreferencespathpage.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 21 5, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef PUZZLEPREFERENCESPATHPAGE_H
#define PUZZLEPREFERENCESPATHPAGE_H
#include <QWidget>
namespace Ui
{
class PuzzlePreferencesPathPage;
}
class PuzzlePreferencesPathPage : public QWidget
{
Q_OBJECT
public:
explicit PuzzlePreferencesPathPage(QWidget *parent = nullptr);
virtual ~PuzzlePreferencesPathPage();
void Apply();
protected:
virtual void changeEvent(QEvent* event) override;
private slots:
void DefaultPath();
void EditPath();
private:
Q_DISABLE_COPY(PuzzlePreferencesPathPage)
Ui::PuzzlePreferencesPathPage *ui;
void InitTable();
};
#endif // PUZZLEPREFERENCESPATHPAGE_H

View file

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PuzzlePreferencesPathPage</class>
<widget class="QWidget" name="PuzzlePreferencesPathPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>586</width>
<height>808</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Paths that Valentina uses</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="pathTable">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Type</string>
</property>
</column>
<column>
<property name="text">
<string>Path</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="defaultButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Default</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="editButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,164 @@
/************************************************************************
**
** @file dialogpuzzlepreferences.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 21 5, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "dialogpuzzlepreferences.h"
#include "ui_dialogpuzzlepreferences.h"
#include "../vpapplication.h"
#include "configpages/puzzlepreferencesconfigurationpage.h"
#include "configpages/puzzlepreferencespathpage.h"
#include "configpages/puzzlepreferenceslayoutpage.h"
#include <QMessageBox>
#include <QPushButton>
#include <QShowEvent>
//---------------------------------------------------------------------------------------------------------------------
DialogPuzzlePreferences::DialogPuzzlePreferences(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogPuzzlePreferences),
m_configurationPage(new PuzzlePreferencesConfigurationPage),
m_layoutPage(new PuzzlePreferencesLayoutPage),
m_pathPage(new PuzzlePreferencesPathPage)
{
ui->setupUi(this);
#if defined(Q_OS_MAC)
setWindowFlags(Qt::Window);
#endif
VAbstractApplication::VApp()->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
SCASSERT(bOk != nullptr)
connect(bOk, &QPushButton::clicked, this, &DialogPuzzlePreferences::Ok);
QPushButton *bApply = ui->buttonBox->button(QDialogButtonBox::Apply);
SCASSERT(bApply != nullptr)
connect(bApply, &QPushButton::clicked, this, &DialogPuzzlePreferences::Apply);
ui->pagesWidget->insertWidget(0, m_configurationPage);
ui->pagesWidget->insertWidget(1, m_layoutPage);
ui->pagesWidget->insertWidget(2, m_pathPage);
connect(ui->contentsWidget, &QListWidget::currentItemChanged, this, &DialogPuzzlePreferences::PageChanged);
ui->pagesWidget->setCurrentIndex(0);
}
//---------------------------------------------------------------------------------------------------------------------
DialogPuzzlePreferences::~DialogPuzzlePreferences()
{
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
void DialogPuzzlePreferences::showEvent(QShowEvent *event)
{
QDialog::showEvent( event );
if ( event->spontaneous() )
{
return;
}
if (m_isInitialized)
{
return;
}
// do your init stuff here
QSize sz = VAbstractApplication::VApp()->Settings()->GetPreferenceDialogSize();
if (not sz.isEmpty())
{
resize(sz);
}
m_isInitialized = true;//first show windows are held
}
//---------------------------------------------------------------------------------------------------------------------
void DialogPuzzlePreferences::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event)
// remember the size for the next time this dialog is opened, but only
// if widget was already initialized, which rules out the resize at
// dialog creating, which would
if (m_isInitialized)
{
VAbstractApplication::VApp()->Settings()->SetPreferenceDialogSize(size());
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogPuzzlePreferences::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
}
// remember to call base class implementation
QDialog::changeEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogPuzzlePreferences::Apply()
{
QStringList preferences;
preferences += m_configurationPage->Apply();
preferences += m_layoutPage->Apply();
m_pathPage->Apply();
if (not preferences.isEmpty())
{
const QString text = tr("Followed %n option(s) require restart to take effect: %1.", "",
preferences.size()).arg(preferences.join(QStringLiteral(", ")));
QMessageBox::information(this, QCoreApplication::applicationName(), text);
}
VPApplication::VApp()->PuzzleSettings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
emit UpdateProperties();
setResult(QDialog::Accepted);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogPuzzlePreferences::Ok()
{
Apply();
done(QDialog::Accepted);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogPuzzlePreferences::PageChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
if (current == nullptr)
{
current = previous;
}
int rowIndex = ui->contentsWidget->row(current);
ui->pagesWidget->setCurrentIndex(rowIndex);
}

View file

@ -0,0 +1,73 @@
/************************************************************************
**
** @file dialogpuzzlepreferences.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 21 5, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef DIALOGPUZZLEPREFERENCES_H
#define DIALOGPUZZLEPREFERENCES_H
#include <QDialog>
namespace Ui
{
class DialogPuzzlePreferences;
}
class PuzzlePreferencesConfigurationPage;
class PuzzlePreferencesPathPage;
class QListWidgetItem;
class PuzzlePreferencesLayoutPage;
class DialogPuzzlePreferences : public QDialog
{
Q_OBJECT
public:
explicit DialogPuzzlePreferences(QWidget *parent = nullptr);
virtual ~DialogPuzzlePreferences();
signals:
void UpdateProperties();
protected:
virtual void showEvent(QShowEvent *event) override;
virtual void resizeEvent(QResizeEvent *event) override;
virtual void changeEvent(QEvent* event) override;
private slots:
void Apply();
void Ok();
void PageChanged(QListWidgetItem *current, QListWidgetItem *previous);
private:
Q_DISABLE_COPY(DialogPuzzlePreferences)
Ui::DialogPuzzlePreferences *ui;
bool m_isInitialized{false};
PuzzlePreferencesConfigurationPage *m_configurationPage;
PuzzlePreferencesLayoutPage *m_layoutPage;
PuzzlePreferencesPathPage *m_pathPage;
};
#endif // DIALOGPUZZLEPREFERENCES_H

View file

@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogPuzzlePreferences</class>
<widget class="QDialog" name="DialogPuzzlePreferences">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>851</width>
<height>551</height>
</rect>
</property>
<property name="windowTitle">
<string>Puzzle preferences</string>
</property>
<property name="windowIcon">
<iconset resource="../share/resources/puzzleicon.qrc">
<normaloff>:/puzzleicon/64x64/logo.png</normaloff>:/puzzleicon/64x64/logo.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="contentsWidget">
<property name="minimumSize">
<size>
<width>128</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>128</width>
<height>16777215</height>
</size>
</property>
<property name="iconSize">
<size>
<width>96</width>
<height>84</height>
</size>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="movement">
<enum>QListView::Static</enum>
</property>
<property name="spacing">
<number>12</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
<property name="currentRow">
<number>-1</number>
</property>
<item>
<property name="text">
<string>Configuration</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
<property name="icon">
<iconset resource="../../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/config.png</normaloff>:/icon/config.png</iconset>
</property>
<property name="flags">
<set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
</property>
</item>
<item>
<property name="text">
<string>Layout</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
<property name="icon">
<iconset resource="../../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/layout.png</normaloff>:/icon/layout.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Paths</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
<property name="icon">
<iconset resource="../../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/path_config.png</normaloff>:/icon/path_config.png</iconset>
</property>
<property name="flags">
<set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
</property>
</item>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="pagesWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<widget class="QWidget" name="page_2"/>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../share/resources/puzzleicon.qrc"/>
<include location="../../../libs/vmisc/share/resources/icon.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogPuzzlePreferences</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogPuzzlePreferences</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,592 @@
/************************************************************************
**
** @file dialogsavemanuallayout.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 3 9, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "dialogsavemanuallayout.h"
#include "ui_dialogsavemanuallayout.h"
#include "../vpapplication.h"
#include "../ifc/exception/vexception.h"
#include "../vlayout/vlayoutexporter.h"
#include <QMessageBox>
#include <QShowEvent>
#include <QtDebug>
#ifndef Q_OS_WIN
Q_GLOBAL_STATIC_WITH_ARGS(const QString, baseFilenameRegExp, (QLatin1String("^[^\\/]+$")))
#else
Q_GLOBAL_STATIC_WITH_ARGS(const QString, baseFilenameRegExp, (QLatin1String("^[^\\:?\"*|\\/<>]+$")))
#endif
bool DialogSaveManualLayout::havePdf = false;
bool DialogSaveManualLayout::tested = false;
//---------------------------------------------------------------------------------------------------------------------
DialogSaveManualLayout::DialogSaveManualLayout(int count, bool consoleExport, const QString &fileName, QWidget *parent)
: VAbstractLayoutDialog(parent),
ui(new Ui::DialogSaveManualLayout),
m_count(count),
m_consoleExport(consoleExport)
{
ui->setupUi(this);
#if defined(Q_OS_MAC)
setWindowFlags(Qt::Window);
#endif
VPApplication::VApp()->PuzzleSettings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
SCASSERT(bOk != nullptr)
bOk->setEnabled(false);
ui->lineEditFileName->setValidator( new QRegularExpressionValidator(QRegularExpression(*baseFilenameRegExp), this));
const QString mask = m_count > 1 ? fileName + '_' : fileName;
if (not m_consoleExport)
{
ui->lineEditFileName->setText(mask);
}
else
{
if (QRegularExpression(*baseFilenameRegExp).match(mask).hasMatch())
{
ui->lineEditFileName->setText(mask);
}
else
{
throw VException(tr("The base filename does not match a regular expression."));
}
}
for (auto &v : InitFormats())
{
ui->comboBoxFormat->addItem(v.first, QVariant(static_cast<int>(v.second)));
}
#ifdef V_NO_ASSERT // Temporarily unavailable
RemoveFormatFromList(LayoutExportFormats::OBJ);
#endif
// RemoveFormatFromList(LayoutExportFormats::NC); // No support for now
connect(bOk, &QPushButton::clicked, this, &DialogSaveManualLayout::Save);
connect(ui->lineEditFileName, &QLineEdit::textChanged, this, &DialogSaveManualLayout::ShowExample);
connect(ui->comboBoxFormat, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &DialogSaveManualLayout::ShowExample);
connect(ui->pushButtonBrowse, &QPushButton::clicked, this, [this]()
{
const QString dirPath = VPApplication::VApp()->PuzzleSettings()->GetPathManualLayouts();
bool usedNotExistedDir = false;
QDir directory(dirPath);
if (not directory.exists())
{
usedNotExistedDir = directory.mkpath(QChar('.'));
}
const QString dir = QFileDialog::getExistingDirectory(
this, tr("Select folder"), dirPath,
VAbstractApplication::VApp()->NativeFileDialog(QFileDialog::ShowDirsOnly |
QFileDialog::DontResolveSymlinks));
if (not dir.isEmpty())
{// If paths equal the signal will not be called, we will do this manually
dir == ui->lineEditPath->text() ? PathChanged(dir) : ui->lineEditPath->setText(dir);
}
if (usedNotExistedDir)
{
QDir directory(dirPath);
directory.rmpath(QChar('.'));
}
});
connect(ui->lineEditPath, &QLineEdit::textChanged, this, &DialogSaveManualLayout::PathChanged);
ui->lineEditPath->setText(VPApplication::VApp()->PuzzleSettings()->GetPathManualLayouts());
ReadSettings();
ShowExample();//Show example for current format.
}
//---------------------------------------------------------------------------------------------------------------------
DialogSaveManualLayout::~DialogSaveManualLayout()
{
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::Path() const -> QString
{
return ui->lineEditPath->text();
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::FileName() const -> QString
{
return ui->lineEditFileName->text();
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::Format() const -> LayoutExportFormats
{
return static_cast<LayoutExportFormats>(ui->comboBoxFormat->currentData().toInt());
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::SelectFormat(LayoutExportFormats format)
{
if (static_cast<int>(format) < 0 || format >= LayoutExportFormats::COUNT)
{
throw VException(tr("Tried to use out of range format number."));
}
const int i = ui->comboBoxFormat->findData(static_cast<int>(format));
if (i < 0)
{
throw VException(tr("Selected not present format."));
}
ui->comboBoxFormat->setCurrentIndex(i);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::SetBinaryDXFFormat(bool binary)
{
switch(Format())
{
case LayoutExportFormats::DXF_AC1006_Flat:
case LayoutExportFormats::DXF_AC1009_Flat:
case LayoutExportFormats::DXF_AC1012_Flat:
case LayoutExportFormats::DXF_AC1014_Flat:
case LayoutExportFormats::DXF_AC1015_Flat:
case LayoutExportFormats::DXF_AC1018_Flat:
case LayoutExportFormats::DXF_AC1021_Flat:
case LayoutExportFormats::DXF_AC1024_Flat:
case LayoutExportFormats::DXF_AC1027_Flat:
case LayoutExportFormats::DXF_AC1006_AAMA:
case LayoutExportFormats::DXF_AC1009_AAMA:
case LayoutExportFormats::DXF_AC1012_AAMA:
case LayoutExportFormats::DXF_AC1014_AAMA:
case LayoutExportFormats::DXF_AC1015_AAMA:
case LayoutExportFormats::DXF_AC1018_AAMA:
case LayoutExportFormats::DXF_AC1021_AAMA:
case LayoutExportFormats::DXF_AC1024_AAMA:
case LayoutExportFormats::DXF_AC1027_AAMA:
case LayoutExportFormats::DXF_AC1006_ASTM:
case LayoutExportFormats::DXF_AC1009_ASTM:
case LayoutExportFormats::DXF_AC1012_ASTM:
case LayoutExportFormats::DXF_AC1014_ASTM:
case LayoutExportFormats::DXF_AC1015_ASTM:
case LayoutExportFormats::DXF_AC1018_ASTM:
case LayoutExportFormats::DXF_AC1021_ASTM:
case LayoutExportFormats::DXF_AC1024_ASTM:
case LayoutExportFormats::DXF_AC1027_ASTM:
ui->checkBoxBinaryDXF->setChecked(binary);
break;
default:
ui->checkBoxBinaryDXF->setChecked(false);
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::IsBinaryDXFFormat() const -> bool
{
switch(Format())
{
case LayoutExportFormats::DXF_AC1006_Flat:
case LayoutExportFormats::DXF_AC1009_Flat:
case LayoutExportFormats::DXF_AC1012_Flat:
case LayoutExportFormats::DXF_AC1014_Flat:
case LayoutExportFormats::DXF_AC1015_Flat:
case LayoutExportFormats::DXF_AC1018_Flat:
case LayoutExportFormats::DXF_AC1021_Flat:
case LayoutExportFormats::DXF_AC1024_Flat:
case LayoutExportFormats::DXF_AC1027_Flat:
case LayoutExportFormats::DXF_AC1006_AAMA:
case LayoutExportFormats::DXF_AC1009_AAMA:
case LayoutExportFormats::DXF_AC1012_AAMA:
case LayoutExportFormats::DXF_AC1014_AAMA:
case LayoutExportFormats::DXF_AC1015_AAMA:
case LayoutExportFormats::DXF_AC1018_AAMA:
case LayoutExportFormats::DXF_AC1021_AAMA:
case LayoutExportFormats::DXF_AC1024_AAMA:
case LayoutExportFormats::DXF_AC1027_AAMA:
case LayoutExportFormats::DXF_AC1006_ASTM:
case LayoutExportFormats::DXF_AC1009_ASTM:
case LayoutExportFormats::DXF_AC1012_ASTM:
case LayoutExportFormats::DXF_AC1014_ASTM:
case LayoutExportFormats::DXF_AC1015_ASTM:
case LayoutExportFormats::DXF_AC1018_ASTM:
case LayoutExportFormats::DXF_AC1021_ASTM:
case LayoutExportFormats::DXF_AC1024_ASTM:
case LayoutExportFormats::DXF_AC1027_ASTM:
return ui->checkBoxBinaryDXF->isChecked();
default:
return false;
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::SetDestinationPath(const QString &cmdDestinationPath)
{
QString path;
if (cmdDestinationPath.isEmpty())
{
path = QDir::currentPath();
}
else if (QDir(cmdDestinationPath).isAbsolute())
{
path = cmdDestinationPath;
}
else
{
QDir dir;
if (not dir.cd(cmdDestinationPath))
{
throw VException(tr("The destination directory doesn't exists or is not readable."));
}
path = dir.absolutePath();
}
qDebug() << "Output full path: " << path << "\n";
ui->lineEditPath->setText(path);
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::IsTextAsPaths() const -> bool
{
return ui->checkBoxTextAsPaths->isChecked();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::SetTextAsPaths(bool textAsPaths)
{
ui->checkBoxTextAsPaths->setChecked(textAsPaths);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::SetExportUnified(bool value)
{
switch(Format())
{
case LayoutExportFormats::PDF:
case LayoutExportFormats::PDFTiled:
case LayoutExportFormats::PS:
case LayoutExportFormats::EPS:
ui->checkBoxExportUnified->setChecked(value);
break;
default:
ui->checkBoxExportUnified->setChecked(false);
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::IsExportUnified() const -> bool
{
switch(Format())
{
case LayoutExportFormats::PDF:
case LayoutExportFormats::PDFTiled:
case LayoutExportFormats::PS:
case LayoutExportFormats::EPS:
return ui->checkBoxExportUnified->isChecked();
default:
return false;
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::SetTilesScheme(bool value)
{
switch(Format())
{
case LayoutExportFormats::PDFTiled:
ui->checkBoxTilesScheme->setChecked(value);
break;
default:
ui->checkBoxTilesScheme->setChecked(false);
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
bool DialogSaveManualLayout::IsTilesScheme() const
{
switch(Format())
{
case LayoutExportFormats::PDFTiled:
return ui->checkBoxTilesScheme->isChecked();
default:
return false;
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::showEvent(QShowEvent *event)
{
QDialog::showEvent( event );
if ( event->spontaneous() )
{
return;
}
if (m_isInitialized)
{
return;
}
// do your init stuff here
setFixedHeight(size().height());
m_isInitialized = true;//first show windows are held
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::Save()
{
WriteSettings();
for (int i=0; i < m_count; ++i)
{
QString name;
if (m_count > 1 && not IsExportUnified())
{
name = Path() + '/' + FileName() + QString::number(i+1) + VLayoutExporter::ExportFormatSuffix(Format());
}
else
{
name = Path() + '/' + FileName() + VLayoutExporter::ExportFormatSuffix(Format());
}
if (QFile::exists(name))
{
QMessageBox::StandardButton res = QMessageBox::question(this, tr("Name conflict"),
tr("Folder already contain file with name %1. Rewrite all conflict file names?")
.arg(name), QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
if (res == QMessageBox::No)
{
reject();
return;
}
break;
}
}
accept();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::PathChanged(const QString &text)
{
QPushButton *bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
SCASSERT(bOk != nullptr)
QPalette palette = ui->lineEditPath->palette();
QDir dir(text);
dir.setPath(text);
if (not text.isEmpty() && dir.exists(text))
{
bOk->setEnabled(true);
palette.setColor(ui->lineEditPath->foregroundRole(), Qt::black);
}
else
{
bOk->setEnabled(false);
palette.setColor(ui->lineEditPath->foregroundRole(), Qt::red);
}
ui->lineEditPath->setPalette(palette);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::ShowExample()
{
const LayoutExportFormats currentFormat = Format();
QString example;
if (m_count > 1)
{
example = tr("Example:") + FileName() + QLatin1Char('1') + VLayoutExporter::ExportFormatSuffix(currentFormat);
}
else
{
example = tr("Example:") + FileName() + VLayoutExporter::ExportFormatSuffix(currentFormat);
}
ui->labelExample->setText(example);
ui->checkBoxBinaryDXF->setEnabled(false);
ui->checkBoxTextAsPaths->setEnabled(true);
ui->checkBoxExportUnified->setEnabled(false);
ui->checkBoxTilesScheme->setEnabled(false);
switch(currentFormat)
{
case LayoutExportFormats::DXF_AC1006_Flat:
case LayoutExportFormats::DXF_AC1009_Flat:
case LayoutExportFormats::DXF_AC1012_Flat:
case LayoutExportFormats::DXF_AC1014_Flat:
case LayoutExportFormats::DXF_AC1015_Flat:
case LayoutExportFormats::DXF_AC1018_Flat:
case LayoutExportFormats::DXF_AC1021_Flat:
case LayoutExportFormats::DXF_AC1024_Flat:
case LayoutExportFormats::DXF_AC1027_Flat:
case LayoutExportFormats::DXF_AC1006_AAMA:
case LayoutExportFormats::DXF_AC1009_AAMA:
case LayoutExportFormats::DXF_AC1012_AAMA:
case LayoutExportFormats::DXF_AC1014_AAMA:
case LayoutExportFormats::DXF_AC1015_AAMA:
case LayoutExportFormats::DXF_AC1018_AAMA:
case LayoutExportFormats::DXF_AC1021_AAMA:
case LayoutExportFormats::DXF_AC1024_AAMA:
case LayoutExportFormats::DXF_AC1027_AAMA:
case LayoutExportFormats::DXF_AC1006_ASTM:
case LayoutExportFormats::DXF_AC1009_ASTM:
case LayoutExportFormats::DXF_AC1012_ASTM:
case LayoutExportFormats::DXF_AC1014_ASTM:
case LayoutExportFormats::DXF_AC1015_ASTM:
case LayoutExportFormats::DXF_AC1018_ASTM:
case LayoutExportFormats::DXF_AC1021_ASTM:
case LayoutExportFormats::DXF_AC1024_ASTM:
case LayoutExportFormats::DXF_AC1027_ASTM:
ui->checkBoxBinaryDXF->setEnabled(true);
break;
case LayoutExportFormats::RLD:
ui->checkBoxTextAsPaths->setEnabled(false);
break;
case LayoutExportFormats::PDFTiled:
ui->checkBoxTilesScheme->setEnabled(true);
ui->checkBoxExportUnified->setEnabled(true);
break;
case LayoutExportFormats::PDF:
case LayoutExportFormats::PS:
case LayoutExportFormats::EPS:
ui->checkBoxExportUnified->setEnabled(true);
break;
case LayoutExportFormats::SVG:
case LayoutExportFormats::PNG:
case LayoutExportFormats::OBJ:
case LayoutExportFormats::NC:
case LayoutExportFormats::TIF:
default:
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::SupportPSTest() -> bool
{
if (!tested)
{
havePdf = VLayoutExporter::SupportPDFConversion();
tested = true;
}
return havePdf;
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSaveManualLayout::InitFormats() -> QVector<std::pair<QString, LayoutExportFormats> >
{
QVector<std::pair<QString, LayoutExportFormats>> list;
auto InitFormat = [&list](LayoutExportFormats format)
{
list.append(std::make_pair(VLayoutExporter::ExportFormatDescription(format), format));
};
InitFormat(LayoutExportFormats::SVG);
InitFormat(LayoutExportFormats::PDF);
InitFormat(LayoutExportFormats::PNG);
InitFormat(LayoutExportFormats::OBJ);
if (SupportPSTest())
{
InitFormat(LayoutExportFormats::PS);
InitFormat(LayoutExportFormats::EPS);
}
InitFormat(LayoutExportFormats::DXF_AC1006_Flat);
InitFormat(LayoutExportFormats::DXF_AC1009_Flat);
InitFormat(LayoutExportFormats::DXF_AC1012_Flat);
InitFormat(LayoutExportFormats::DXF_AC1014_Flat);
InitFormat(LayoutExportFormats::DXF_AC1015_Flat);
InitFormat(LayoutExportFormats::DXF_AC1018_Flat);
InitFormat(LayoutExportFormats::DXF_AC1021_Flat);
InitFormat(LayoutExportFormats::DXF_AC1024_Flat);
InitFormat(LayoutExportFormats::DXF_AC1027_Flat);
InitFormat(LayoutExportFormats::DXF_AC1006_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1009_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1012_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1014_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1015_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1018_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1021_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1024_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1027_AAMA);
InitFormat(LayoutExportFormats::DXF_AC1006_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1009_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1012_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1014_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1015_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1018_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1021_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1024_ASTM);
InitFormat(LayoutExportFormats::DXF_AC1027_ASTM);
InitFormat(LayoutExportFormats::PDFTiled);
// InitFormat(LayoutExportFormats::NC);
InitFormat(LayoutExportFormats::RLD);
InitFormat(LayoutExportFormats::TIF);
return list;
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::RemoveFormatFromList(LayoutExportFormats format)
{
const int index = ui->comboBoxFormat->findData(static_cast<int>(format));
if (index != -1)
{
ui->comboBoxFormat->removeItem(index);
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::ReadSettings()
{
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
SelectFormat(static_cast<LayoutExportFormats>(settings->GetLayoutExportFormat()));
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSaveManualLayout::WriteSettings() const
{
if (m_consoleExport)
{
return;
}
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
settings->SetLayoutExportFormat(static_cast<qint8>(Format()));
}

View file

@ -0,0 +1,95 @@
/************************************************************************
**
** @file dialogsavemanuallayout.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 3 9, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef DIALOGSAVEMANUALLAYOUT_H
#define DIALOGSAVEMANUALLAYOUT_H
#include "../vlayout/dialogs/vabstractlayoutdialog.h"
#include "../vlayout/vlayoutdef.h"
namespace Ui
{
class DialogSaveManualLayout;
}
class DialogSaveManualLayout : public VAbstractLayoutDialog
{
Q_OBJECT
public:
explicit DialogSaveManualLayout(int count, bool consoleExport, const QString &fileName = QString(),
QWidget *parent = nullptr);
virtual ~DialogSaveManualLayout();
auto Path() const -> QString;
auto FileName() const -> QString;
auto Format() const -> LayoutExportFormats;
void SelectFormat(LayoutExportFormats format);
void SetBinaryDXFFormat(bool binary);
auto IsBinaryDXFFormat() const -> bool;
void SetDestinationPath(const QString& cmdDestinationPath);
auto IsTextAsPaths() const -> bool;
void SetTextAsPaths(bool textAsPaths);
void SetExportUnified(bool value);
auto IsExportUnified() const -> bool;
void SetTilesScheme(bool value);
auto IsTilesScheme() const -> bool;
protected:
virtual void showEvent(QShowEvent *event) override;
private slots:
void Save();
void PathChanged(const QString &text);
void ShowExample();
private:
Q_DISABLE_COPY(DialogSaveManualLayout)
Ui::DialogSaveManualLayout *ui;
int m_count;
bool m_isInitialized{false};
bool m_scaleConnected{true};
bool m_consoleExport;
static bool havePdf;
static bool tested;
static bool SupportPSTest();
static QVector<std::pair<QString, LayoutExportFormats> > InitFormats();
void RemoveFormatFromList(LayoutExportFormats format);
void ReadSettings();
void WriteSettings() const;
};
#endif // DIALOGSAVEMANUALLAYOUT_H

View file

@ -0,0 +1,280 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogSaveManualLayout</class>
<widget class="QDialog" name="DialogSaveManualLayout">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>413</width>
<height>290</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Path:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditPath">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Destination folder</string>
</property>
<property name="placeholderText">
<string>Path to destination folder</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonBrowse">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Select path to destination folder</string>
</property>
<property name="text">
<string>Browse…</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="label_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>File format:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxFormat">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QGroupBox" name="groupBoxFormatOptions_2">
<property name="title">
<string>Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="checkBoxBinaryDXF">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Binary form</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTextAsPaths">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Text as paths</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxExportUnified">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Export unified</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTilesScheme">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Tiles scheme</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QLabel" name="label_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>File name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditFileName">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>File base name</string>
</property>
<property name="placeholderText">
<string>File base name</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelExample">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>130</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogSaveManualLayout</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogSaveManualLayout</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,141 @@
/************************************************************************
**
** @file vpdialogabout.cpp
** @author Ronan Le Tiec
** @date 11 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpdialogabout.h"
#include "ui_vpdialogabout.h"
#include "../version.h"
#include "../vmisc/def.h"
#include "../fervor/fvupdater.h"
#include <QDate>
#include <QDesktopServices>
#include <QMessageBox>
#include <QShowEvent>
#include <QUrl>
#include <QtDebug>
//---------------------------------------------------------------------------------------------------------------------
VPDialogAbout::VPDialogAbout(QWidget *parent)
:QDialog(parent),
ui(new Ui::VPDialogAbout),
isInitialized(false)
{
ui->setupUi(this);
//mApp->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
RetranslateUi();
connect(ui->pushButton_Web_Site, &QPushButton::clicked, this, []()
{
if ( not QDesktopServices::openUrl(QUrl(VER_COMPANYDOMAIN_STR)))
{
qWarning() << tr("Cannot open your default browser");
}
});
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &VPDialogAbout::close);
connect(ui->pushButtonCheckUpdate, &QPushButton::clicked, []()
{
// Set feed URL before doing anything else
FvUpdater::sharedUpdater()->SetFeedURL(FvUpdater::CurrentFeedURL());
FvUpdater::sharedUpdater()->CheckForUpdatesNotSilent();
});
// By default on Windows font point size 8 points we need 11 like on Linux.
FontPointSize(ui->label_Legal_Stuff, 11);
FontPointSize(ui->label_Puzzle_Built, 11);
FontPointSize(ui->label_QT_Version, 11);
}
//---------------------------------------------------------------------------------------------------------------------
VPDialogAbout::~VPDialogAbout()
{
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
void VPDialogAbout::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
RetranslateUi();
}
// remember to call base class implementation
QDialog::changeEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPDialogAbout::showEvent(QShowEvent *event)
{
QDialog::showEvent( event );
if ( event->spontaneous() )
{
return;
}
if (isInitialized)
{
return;
}
// do your init stuff here
setMaximumSize(size());
setMinimumSize(size());
isInitialized = true;//first show windows are held
}
//---------------------------------------------------------------------------------------------------------------------
void VPDialogAbout::FontPointSize(QWidget *w, int pointSize)
{
SCASSERT(w != nullptr)
QFont font = w->font();
font.setPointSize(pointSize);
w->setFont(font);
}
//---------------------------------------------------------------------------------------------------------------------
void VPDialogAbout::RetranslateUi()
{
ui->label_Puzzle_Version->setText(QString("Puzzle %1").arg(APP_VERSION_STR));
ui->labelBuildRevision->setText(tr("Build revision: %1").arg(BUILD_REVISION));
ui->label_QT_Version->setText(buildCompatibilityString());
const QDate date = QLocale::c().toDate(QString(__DATE__).simplified(), QLatin1String("MMM d yyyy"));
ui->label_Puzzle_Built->setText(tr("Built on %1 at %2").arg(date.toString(), __TIME__));
ui->label_Legal_Stuff->setText(QApplication::translate("InternalStrings",
"The program is provided AS IS with NO WARRANTY OF ANY "
"KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY "
"AND FITNESS FOR A PARTICULAR PURPOSE."));
ui->pushButton_Web_Site->setText(tr("Web site : %1").arg(VER_COMPANYDOMAIN_STR));
}

View file

@ -0,0 +1,61 @@
/************************************************************************
**
** @file vpdialogabout.h
** @author Ronan Le Tiec
** @date 11 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPDIALOGABOUT_H
#define VPDIALOGABOUT_H
#include <QDialog>
namespace Ui
{
class VPDialogAbout;
}
class VPDialogAbout : public QDialog
{
Q_OBJECT
public:
explicit VPDialogAbout(QWidget *parent = nullptr);
virtual ~VPDialogAbout();
protected:
virtual void changeEvent(QEvent* event) override;
virtual void showEvent(QShowEvent *event) override;
private:
Q_DISABLE_COPY(VPDialogAbout)
Ui::VPDialogAbout *ui;
bool isInitialized;
void FontPointSize(QWidget *w, int pointSize);
void RetranslateUi();
};
#endif // VPDIALOGABOUT_H

View file

@ -0,0 +1,302 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VPDialogAbout</class>
<widget class="QDialog" name="VPDialogAbout">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>462</width>
<height>338</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>About Puzzle</string>
</property>
<property name="windowIcon">
<iconset resource="../share/resources/puzzleicon.qrc">
<normaloff>:/puzzleicon/64x64/logo.png</normaloff>:/puzzleicon/64x64/logo.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>16</number>
</property>
<item>
<widget class="QLabel" name="label_appIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../share/resources/puzzleicon.qrc">:/puzzleicon/64x64/logo.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_Puzzle_Version">
<property name="font">
<font>
<pointsize>15</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Puzzle version</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="labelBuildRevision">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Build revision:</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="label">
<property name="text">
<string>This program is part of Valentina project.</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_Web_Site">
<property name="palette">
<palette>
<active>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>120</red>
<green>120</green>
<blue>120</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="font">
<font>
<underline>true</underline>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string notr="true">pushButton_Web_Site</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Puzzle_Built">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">label_Tape_Built</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_QT_Version">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">label_QT_Version</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_Legal_Stuff">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">label_Legal_Stuff</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="pushButtonCheckUpdate">
<property name="text">
<string>Check For Updates</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../share/resources/puzzleicon.qrc"/>
<include location="../share/resources/puzzleicon.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -0,0 +1,92 @@
/************************************************************************
**
** @file layoutdef.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 31 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "layoutdef.h"
#include <QString>
#include <QStringList>
//---------------------------------------------------------------------------------------------------------------------
auto GrainlineTypeToStr(GrainlineType type) -> QString
{
QString result;
switch (type)
{
case GrainlineType::Horizontal:
result = QStringLiteral("horizontal");
break;
case GrainlineType::Vertical:
result = QStringLiteral("vertical");
break;
case GrainlineType::NotFixed:
default:
result = QStringLiteral("notFixed");
break;
}
return result;
}
//---------------------------------------------------------------------------------------------------------------------
auto StrToGrainlineType(const QString &string) -> GrainlineType
{
const QStringList types
{
QStringLiteral("horizontal"), // 0
QStringLiteral("vertical"), // 1
QStringLiteral("notFixed") // 2
};
GrainlineType type = GrainlineType::NotFixed;
switch (types.indexOf(string))
{
case 0:// horizontal
type = GrainlineType::Horizontal;
break;
case 2:// vertical
type = GrainlineType::Vertical;
break;
case 3:// notFixed
default:
type = GrainlineType::NotFixed;
break;
}
return type;
}
//---------------------------------------------------------------------------------------------------------------------
bool VPTransformationOrigon::operator==(const VPTransformationOrigon &origin) const
{
return this->origin == origin.origin && custom == origin.custom;
}
//---------------------------------------------------------------------------------------------------------------------
bool VPTransformationOrigon::operator!=(const VPTransformationOrigon &origin) const
{
return !VPTransformationOrigon::operator==(origin);
}

View file

@ -0,0 +1,67 @@
/************************************************************************
**
** @file layoutdef.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 16 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef LAYOUTDEF_H
#define LAYOUTDEF_H
#include <QPointF>
template <typename T> class QSharedPointer;
template <typename T> class QWeakPointer;
class VPLayout;
using VPLayoutPtr = QSharedPointer<VPLayout>;
using VPLayoutWeakPtr = QWeakPointer<VPLayout>;
class VPPiece;
using VPPiecePtr = QSharedPointer<VPPiece>;
using VPPieceWeakPtr = QWeakPointer<VPPiece>;
class VPSheet;
using VPSheetPtr = QSharedPointer<VPSheet>;
using VPSheetWeakPtr = QWeakPointer<VPSheet>;
enum class GrainlineType : qint8
{
Vertical,
Horizontal,
NotFixed
};
auto GrainlineTypeToStr(GrainlineType type) -> QString;
auto StrToGrainlineType(const QString &string) -> GrainlineType;
struct VPTransformationOrigon
{
QPointF origin{};
bool custom{false};
bool operator==(const VPTransformationOrigon &origin) const;
bool operator!=(const VPTransformationOrigon &origin) const;
};
#endif // LAYOUTDEF_H

View file

@ -0,0 +1,403 @@
/************************************************************************
**
** @file vplayout.cpp
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vplayout.h"
#include "vppiece.h"
#include "vpsheet.h"
#include "../vpapplication.h"
#include "../vptilefactory.h"
#include "../ifc/xml/vwatermarkconverter.h"
#include "../vformat/vwatermark.h"
#include "../ifc/exception/vexception.h"
#include <QLoggingCategory>
#include <QUndoStack>
#include <QPixmapCache>
Q_LOGGING_CATEGORY(pLayout, "p.layout")
//---------------------------------------------------------------------------------------------------------------------
VPLayout::VPLayout(QUndoStack *undoStack) :
m_undoStack(undoStack)
{
SCASSERT(m_undoStack != nullptr)
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::CreateLayout(QUndoStack *undoStack) -> VPLayoutPtr
{
SCASSERT(undoStack != nullptr)
undoStack->clear();
VPLayoutPtr layout(new VPLayout(undoStack));
layout->AddTrashSheet(VPSheetPtr(new VPSheet(layout)));
// create a standard sheet
VPSheetPtr sheet(new VPSheet(layout));
sheet->SetName(tr("Sheet %1").arg(layout->GetAllSheets().size()+1));
layout->AddSheet(sheet);
layout->SetFocusedSheet(sheet);
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
layout->LayoutSettings().SetUnit(settings->LayoutUnit());
layout->LayoutSettings().SetShowTiles(settings->GetLayoutTileShowTiles());
layout->LayoutSettings().SetShowWatermark(settings->GetLayoutTileShowWatermark());
layout->LayoutSettings().SetTilesSize(QSizeF(settings->GetLayoutTilePaperWidth(),
settings->GetLayoutTilePaperHeight()));
layout->LayoutSettings().SetIgnoreTilesMargins(settings->GetLayoutTileIgnoreMargins());
layout->LayoutSettings().SetTilesMargins(settings->GetLayoutTileMargins());
layout->LayoutSettings().SetWarningSuperpositionOfPieces(settings->GetLayoutWarningPiecesSuperposition());
layout->LayoutSettings().SetWarningPiecesOutOfBound(settings->GetLayoutWarningPiecesOutOfBound());
layout->LayoutSettings().SetFollowGrainline(settings->GetLayoutFollowGrainline());
layout->LayoutSettings().SetStickyEdges(settings->GetLayoutStickyEdges());
layout->LayoutSettings().SetPiecesGap(settings->GetLayoutPieceGap());
// ----- for test purposes, to be removed------------------
layout->LayoutSettings().SetTitle(QString("My Test Layout"));
layout->LayoutSettings().SetDescription(QString("Description of my Layout"));
// --------------------------------------------------------
// init the tile factory
auto *tileFactory = new VPTileFactory(layout, settings);
tileFactory->refreshTileInfos();
layout->SetTileFactory(tileFactory);
return layout;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddPiece(const VPLayoutPtr &layout, const VPPiecePtr &piece)
{
piece->SetLayout(layout);
layout->AddPiece(piece);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddPiece(const VPPiecePtr &piece)
{
if (not piece.isNull())
{
if (not m_pieces.contains(piece->GetUniqueID()))
{
m_pieces.insert(piece->GetUniqueID(), piece);
}
else
{
VPPiecePtr oldPiece = m_pieces.value(piece->GetUniqueID());
if (not oldPiece.isNull())
{
oldPiece->Update(piece);
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
VPTileFactory *VPLayout::TileFactory() const
{
return m_tileFactory;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::SetTileFactory(VPTileFactory *newTileFactory)
{
m_tileFactory = newTileFactory;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::RefreshScenePieces() const
{
for (const auto& sheet : GetSheets())
{
if (not sheet.isNull())
{
sheet->SceneData()->RefreshPieces();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::WatermarkData() const -> VWatermarkData
{
VWatermarkData data;
if (not m_layoutSettings.WatermarkPath().isEmpty())
{
try
{
VWatermarkConverter converter(m_layoutSettings.WatermarkPath());
VWatermark watermark;
watermark.setXMLContent(converter.Convert());
data = watermark.GetWatermark();
}
catch (VException &)
{
data.invalidFile = true;
data.opacity = 20;
data.showImage = true;
data.path = "fake.png";
data.showText = false;
return data;
}
}
return data;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::IsSheetsUniform() const -> bool
{
QList<VPSheetPtr> sheets = GetSheets();
if (sheets.size() < 2)
{
return true;
}
VPSheetPtr sheet = sheets.first();
if (sheet.isNull())
{
return false;
}
QSizeF sheetSize = sheet->GetSheetSize().toSize();
return std::all_of(sheets.begin(), sheets.end(), [sheetSize](const VPSheetPtr &sheet)
{
if (sheet.isNull())
{
return false;
}
QSize size = sheet->GetSheetSize().toSize();
return size == sheetSize || size.transposed() == sheetSize;
});
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetPieces() const -> QList<VPPiecePtr>
{
return m_pieces.values();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetPlacedPieces() const -> QList<VPPiecePtr>
{
QList<VPPiecePtr> pieces;
pieces.reserve(m_pieces.size());
for (const auto& piece : m_pieces)
{
if (not piece->isNull() && piece->Sheet() != VPSheetPtr() && piece->Sheet() != m_trashSheet)
{
pieces.append(piece);
}
}
return pieces;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetUnplacedPieces() const -> QList<VPPiecePtr>
{
return PiecesForSheet(VPSheetPtr());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetTrashedPieces() const -> QList<VPPiecePtr>
{
if (m_trashSheet.isNull())
{
return {};
}
return PiecesForSheet(m_trashSheet->Uuid());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr
{
if (not sheet.isNull() && GetSheet(sheet->Uuid()).isNull())
{
m_sheets.append(sheet);
connect(this, &VPLayout::PieceTransformationChanged, sheet.get(), &VPSheet::CheckPiecePositionValidity);
}
return sheet;
}
//---------------------------------------------------------------------------------------------------------------------
QList<VPSheetPtr> VPLayout::GetAllSheets() const
{
return m_sheets;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetSheets() const -> QList<VPSheetPtr>
{
QList<VPSheetPtr> sheets;
sheets.reserve(m_sheets.size());
for (const auto &sheet : m_sheets)
{
if (not sheet.isNull() && sheet->IsVisible())
{
sheets.append(sheet);
}
}
return sheets;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetSheet(const QUuid &uuid) -> VPSheetPtr
{
auto sheet = std::find_if(m_sheets.begin(), m_sheets.end(),
[uuid](const VPSheetPtr &sheet) { return sheet->Uuid() == uuid; });
if (sheet != m_sheets.end())
{
return *sheet;
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::SetFocusedSheet(const VPSheetPtr &focusedSheet)
{
if (m_sheets.isEmpty())
{
m_focusedSheet = {};
}
else
{
m_focusedSheet = focusedSheet.isNull() ? m_sheets.first() : focusedSheet;
}
emit ActiveSheetChanged(m_focusedSheet);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetFocusedSheet() -> VPSheetPtr
{
return m_focusedSheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::GetTrashSheet() -> VPSheetPtr
{
return m_trashSheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::LayoutSettings() -> VPLayoutSettings &
{
return m_layoutSettings;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::PiecesForSheet(const VPSheetPtr &sheet) const -> QList<VPPiecePtr>
{
QList<VPPiecePtr> list;
list.reserve(m_pieces.size());
for (const auto& piece : m_pieces)
{
if (not piece.isNull() && piece->Sheet() == sheet)
{
list.append(piece);
}
}
return list;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::PiecesForSheet(const QUuid &uuid) const -> QList<VPPiecePtr>
{
QList<VPPiecePtr> list;
list.reserve(m_pieces.size());
for (const auto& piece : m_pieces)
{
if (not piece.isNull())
{
VPSheetPtr sheet = piece->Sheet();
if (not sheet.isNull() && sheet->Uuid() == uuid)
{
list.append(piece);
}
}
}
return list;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayout::UndoStack() const -> QUndoStack *
{
return m_undoStack;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::SetUndoStack(QUndoStack *newUndoStack)
{
m_undoStack = newUndoStack;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::Clear()
{
if (m_undoStack != nullptr)
{
m_undoStack->clear();
}
m_pieces.clear();
m_trashSheet->Clear();
m_sheets.clear();
m_focusedSheet.clear();
m_layoutSettings = VPLayoutSettings();
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::CheckPiecesPositionValidity() const
{
for (const auto &sheet : m_sheets)
{
if (not sheet.isNull())
{
sheet->ValidateSuperpositionOfPieces();
sheet->ValidatePiecesOutOfBound();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddTrashSheet(const VPSheetPtr &sheet)
{
m_trashSheet = sheet;
m_trashSheet->SetTrashSheet(true);
}

View file

@ -0,0 +1,136 @@
/************************************************************************
**
** @file vplayout.h
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPLAYOUT_H
#define VPLAYOUT_H
#include <QList>
#include <QMap>
#include "def.h"
#include "vplayoutsettings.h"
#include "layoutdef.h"
class VPPiece;
class VPSheet;
class QUndoStack;
class VPTileFactory;
struct VWatermarkData;
class VPLayout : public QObject
{
Q_OBJECT
public:
virtual ~VPLayout() = default;
static auto CreateLayout(QUndoStack *undoStack) -> VPLayoutPtr;
static void AddPiece(const VPLayoutPtr &layout, const VPPiecePtr &piece);
auto GetPieces() const -> QList<VPPiecePtr>;
auto GetPlacedPieces() const -> QList<VPPiecePtr>;
auto GetUnplacedPieces() const -> QList<VPPiecePtr>;
auto GetTrashedPieces() const -> QList<VPPiecePtr>;
auto AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr;
auto GetAllSheets() const -> QList<VPSheetPtr>;
auto GetSheets() const -> QList<VPSheetPtr>;
auto GetSheet(const QUuid &uuid) -> VPSheetPtr;
/**
* @brief SetFocusedSheet Sets the focused sheet, to which pieces are added from the carrousel via drag
* and drop
* @param focusedSheet the new active sheet. If nullptr, then it sets automaticaly the first sheet from m_sheets
*/
void SetFocusedSheet(const VPSheetPtr &focusedSheet = VPSheetPtr());
/**
* @brief GetFocusedSheet Returns the focused sheet, to which pieces are added from the carrousel via drag
* and drop
* @return the focused sheet
*/
auto GetFocusedSheet() -> VPSheetPtr;
void AddTrashSheet(const VPSheetPtr &sheet);
auto GetTrashSheet() -> VPSheetPtr;
auto LayoutSettings() -> VPLayoutSettings &;
auto PiecesForSheet(const VPSheetPtr &sheet) const -> QList<VPPiecePtr>;
auto PiecesForSheet(const QUuid &uuid) const -> QList<VPPiecePtr>;
QUndoStack *UndoStack() const;
void SetUndoStack(QUndoStack *newUndoStack);
void Clear();
void CheckPiecesPositionValidity() const;
auto TileFactory() const -> VPTileFactory *;
void SetTileFactory(VPTileFactory *newTileFactory);
void RefreshScenePieces() const;
auto WatermarkData() const -> VWatermarkData;
auto IsSheetsUniform() const -> bool;
signals:
void PieceSheetChanged(const VPPiecePtr &piece);
void ActiveSheetChanged(const VPSheetPtr &focusedSheet);
void PieceTransformationChanged(const VPPiecePtr &piece);
void TransformationOriginChanged();
void SheetListChanged();
void PieceSelectionChanged(const VPPiecePtr &piece);
void PiecePositionValidityChanged(const VPPiecePtr &piece);
void LayoutChanged();
protected:
explicit VPLayout(QUndoStack *undoStack);
void AddPiece(const VPPiecePtr &piece);
private:
Q_DISABLE_COPY(VPLayout)
QMap<QString, VPPiecePtr> m_pieces{};
VPSheetPtr m_trashSheet{};
QList<VPSheetPtr> m_sheets{};
VPSheetPtr m_focusedSheet{};
VPLayoutSettings m_layoutSettings{};
QUndoStack *m_undoStack;
VPTileFactory *m_tileFactory{nullptr};
};
Q_DECLARE_METATYPE(VPLayoutPtr)
#endif // VPLAYOUT_H

View file

@ -0,0 +1,390 @@
/************************************************************************
**
** @file vplayoutsettings.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 29 7, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vplayoutsettings.h"
#include <QComboBox>
#include <QIcon>
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetUnit(Unit unit)
{
m_unit = unit;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetUnit() const -> Unit
{
return m_unit;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetWarningSuperpositionOfPieces(bool state)
{
m_warningSuperpositionOfPieces = state;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetWarningSuperpositionOfPieces() const -> bool
{
return m_warningSuperpositionOfPieces;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetWarningPiecesOutOfBound(bool state)
{
m_warningPiecesOutOfBound = state;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetWarningPiecesOutOfBound() const -> bool
{
return m_warningPiecesOutOfBound;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTitle(const QString &title)
{
m_title = title;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTitle() const -> QString
{
return m_title;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetDescription(const QString &description)
{
m_description = description;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetDescription() const -> QString
{
return m_description;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesSize(qreal width, qreal height)
{
m_tilesSize.setWidth(width);
m_tilesSize.setHeight(height);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesSizeConverted(qreal width, qreal height)
{
m_tilesSize.setWidth(UnitConvertor(width, m_unit, Unit::Px));
m_tilesSize.setHeight(UnitConvertor(height, m_unit, Unit::Px));
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesSize(const QSizeF &size)
{
m_tilesSize = size;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesSizeConverted(const QSizeF &size)
{
m_tilesSize = QSizeF(
UnitConvertor(size.width(), GetUnit(), Unit::Px),
UnitConvertor(size.height(), GetUnit(), Unit::Px)
);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTilesOrientation() const -> QPageLayout::Orientation
{
return m_tilesSize.height() >= m_tilesSize.width() ? QPageLayout::Portrait : QPageLayout::Landscape;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTilesSize() const -> QSizeF
{
return m_tilesSize;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTilesSize(Unit unit) const -> QSizeF
{
QSizeF convertedSize = QSizeF(
UnitConvertor(m_tilesSize.width(), Unit::Px, unit),
UnitConvertor(m_tilesSize.height(), Unit::Px, unit)
);
return convertedSize;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTilesSizeConverted() const -> QSizeF
{
return GetTilesSize(GetUnit());
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesMargins(qreal left, qreal top, qreal right, qreal bottom)
{
m_tilesMargins.setLeft(left);
m_tilesMargins.setTop(top);
m_tilesMargins.setRight(right);
m_tilesMargins.setBottom(bottom);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesMarginsConverted(qreal left, qreal top, qreal right, qreal bottom)
{
m_tilesMargins.setLeft(UnitConvertor(left, GetUnit(), Unit::Px));
m_tilesMargins.setTop(UnitConvertor(top, GetUnit(), Unit::Px));
m_tilesMargins.setRight(UnitConvertor(right, GetUnit(), Unit::Px));
m_tilesMargins.setBottom(UnitConvertor(bottom, GetUnit(), Unit::Px));
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesMargins(const QMarginsF &margins)
{
m_tilesMargins = margins;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetTilesMarginsConverted(const QMarginsF &margins)
{
m_tilesMargins = UnitConvertor(margins, GetUnit(), Unit::Px);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTilesMargins() const -> QMarginsF
{
return m_tilesMargins;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTilesMargins(Unit unit) const -> QMarginsF
{
return UnitConvertor(m_tilesMargins, Unit::Px, unit);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetTilesMarginsConverted() const -> QMarginsF
{
return UnitConvertor(m_tilesMargins, Unit::Px, GetUnit());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetShowTiles() const -> bool
{
return m_showTiles;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetShowTiles(bool value)
{
m_showTiles = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetFollowGrainline(bool state)
{
m_followGrainLine = state;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetFollowGrainline() const -> bool
{
return m_followGrainLine;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetPiecesGap(qreal value)
{
m_piecesGap = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetPiecesGapConverted(qreal value)
{
m_piecesGap = UnitConvertor(value, m_unit, Unit::Px);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetPiecesGap() const -> qreal
{
return m_piecesGap;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetPiecesGapConverted() const -> qreal
{
return UnitConvertor(m_piecesGap, Unit::Px, m_unit);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetStickyEdges(bool state)
{
m_stickyEdges = state;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetStickyEdges() const -> bool
{
return m_stickyEdges;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetShowGrid() const -> bool
{
return m_showGrid;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetShowGrid(bool value)
{
m_showGrid = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetGridColWidth() const -> qreal
{
return m_gridColWidth;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetGridColWidthConverted() const -> qreal
{
return UnitConvertor(m_gridColWidth, Unit::Px, m_unit);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetGridColWidth(qreal value)
{
m_gridColWidth = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetGridColWidthConverted(qreal value)
{
m_gridColWidth = UnitConvertor(value, m_unit, Unit::Px);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetGridRowHeight() const -> qreal
{
return m_gridRowHeight;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetGridRowHeightConverted() const -> qreal
{
return UnitConvertor(m_gridRowHeight, Unit::Px, m_unit);
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetGridRowHeight(qreal value)
{
m_gridRowHeight = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetGridRowHeightConverted(qreal value)
{
m_gridRowHeight = UnitConvertor(value, m_unit, Unit::Px);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::IgnoreTilesMargins() const -> bool
{
return m_ignoreTilesMargins;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetIgnoreTilesMargins(bool newIgnoreTilesMargins)
{
m_ignoreTilesMargins = newIgnoreTilesMargins;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::HorizontalScale() const -> qreal
{
return m_horizontalScale;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetHorizontalScale(qreal newHorizontalScale)
{
m_horizontalScale = newHorizontalScale;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::VerticalScale() const -> qreal
{
return m_verticalScale;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetVerticalScale(qreal newVerticalScale)
{
m_verticalScale = newVerticalScale;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::WatermarkPath() const -> const QString &
{
return m_watermarkPath;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetWatermarkPath(const QString &newWatermarkPath)
{
m_watermarkPath = newWatermarkPath;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPLayoutSettings::GetShowWatermark() const -> bool
{
return m_showWatermark;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetShowWatermark(bool newShowWatermark)
{
m_showWatermark = newShowWatermark;
}
//---------------------------------------------------------------------------------------------------------------------
bool VPLayoutSettings::GetPrintTilesScheme() const
{
return m_printTilesScheme;
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutSettings::SetPrintTilesScheme(bool newPrintTilesScheme)
{
m_printTilesScheme = newPrintTilesScheme;
}

View file

@ -0,0 +1,376 @@
/************************************************************************
**
** @file vplayoutsettings.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 29 7, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPLAYOUTSETTINGS_H
#define VPLAYOUTSETTINGS_H
#include <QMarginsF>
#include <QSizeF>
#include <QString>
#include <QCoreApplication>
#include "def.h"
class VPLayoutSettings
{
Q_DECLARE_TR_FUNCTIONS(VPLayoutSettings)
public:
VPLayoutSettings() = default;
// Layout
/**
* @brief SetUnit Sets the unit of the layout to the given unit
* @param unit the new unit
*/
void SetUnit(Unit unit);
/**
* @brief GetUnit Returns the current unit of the layout
* @return the unit
*/
auto GetUnit() const -> Unit;
/**
* @brief SetTitle Sets the title of the layout to the given value
* @param title the title of the layout
*/
void SetTitle(const QString &title);
/**
* @brief GetTitle Returns the title of the layout
* @return title of the layout
*/
auto GetTitle() const -> QString;
/**
* @brief SetDescription Sets the description of the layout to the given value
* @param description the description of the layout
*/
void SetDescription(const QString &description);
/**
* @brief GetDescription Returns the description of the layout.
* @return description of the layout
*/
auto GetDescription() const -> QString;
void SetStickyEdges(bool state);
auto GetStickyEdges() const -> bool;
// Piece
void SetWarningSuperpositionOfPieces(bool state);
auto GetWarningSuperpositionOfPieces() const -> bool;
void SetWarningPiecesOutOfBound(bool state);
auto GetWarningPiecesOutOfBound() const -> bool;
/**
* @brief SetFollowGrainline Sets the type of grainline for the pieces to follow
* @param state the type of grainline
*/
void SetFollowGrainline(bool state);
/**
* @brief GetFollowGrainline Returns if the sheet's pieces follow a grainline or not
* @return wether the pieces follow a grainline and if so, which grainline
*/
auto GetFollowGrainline() const -> bool;
/**
* @brief SetPiecesGap sets the pieces gap to the given value, the unit has to be in Unit::Px
* @param value pieces gap
*/
void SetPiecesGap(qreal value);
/**
* @brief SetPiecesGapConverted sets the pieces gap to the given value, the unit has to be in the layout's unit
* @param value pieces gap
*/
void SetPiecesGapConverted(qreal value);
/**
* @brief GetPiecesGap returns the pieces gap in Unit::Px
* @return the pieces gap in Unit::Px
*/
auto GetPiecesGap() const -> qreal;
/**
* @brief GetPiecesGapConverted returns the pieces gap in the layout's unit
* @return the pieces gap in the layout's unit
*/
auto GetPiecesGapConverted() const -> qreal;
// Tiles
/**
* @brief SetTilesSize sets the size of the tiles, the values have to be in Unit::Px
* @param width tiles width
* @param height tiles height
*/
void SetTilesSize(qreal width, qreal height);
/**
* @brief SetTilesSizeConverted sets the size of the sheet, the values have to be in the layout's unit
* @param width tiles width
* @param height tiles height
*/
void SetTilesSizeConverted(qreal width, qreal height);
/**
* @brief SetTilesSize sets the size of the tiles, the values have to be in Unit::Px
* @param size tiles size
*/
void SetTilesSize(const QSizeF &size);
/**
* @brief SetTilesSizeConverted sets the size of the tiles, the values have to be in the layout's unit
* @param size tiles size
*/
void SetTilesSizeConverted(const QSizeF &size);
auto GetTilesOrientation() const -> QPageLayout::Orientation;
/**
* @brief GetTilesSize Returns the size of the tiles in Unit::Px
* @return tiles size in Unit::Px
*/
auto GetTilesSize() const -> QSizeF;
/**
* @brief GetTilesSize Returns the size of the tiles in given Unit
* @return tiles size
*/
auto GetTilesSize(Unit unit) const -> QSizeF;
/**
* @brief GetTilesSizeConverted Returns the size of the tiles in the layout's unit
* @return the size in the layout's unit
*/
auto GetTilesSizeConverted() const -> QSizeF;
/**
* @brief SetTilesMargins, set the margins of the tiles, the values have to be in Unit::Px
* @param left in Unit::Px
* @param top in Unit::Px
* @param right in Unit::Px
* @param bottom in Unit::Px
*/
void SetTilesMargins(qreal left, qreal top, qreal right, qreal bottom);
/**
* @brief SetSheetMargins, set the margins of the tiles, the values have to be in the unit of the layout
* @param left in Unit::Px
* @param top in Unit::Px
* @param right in Unit::Px
* @param bottom in Unit::Px
*/
void SetTilesMarginsConverted(qreal left, qreal top, qreal right, qreal bottom);
/**
* @brief SetTilesMargins set the margins of the tiles, the values have to be in Unit::Px
* @param margins tiles margins
*/
void SetTilesMargins(const QMarginsF &margins);
/**
* @brief SetTilesMarginsConverted set the margins of the tiles, the values have to be in the unit of the layout
* @param margins tiles margins
*/
void SetTilesMarginsConverted(const QMarginsF &margins);
/**
* @brief GetTilesMargins Returns margins of the tiles in Unit::Px
* @return the margins in Unit::Px
*/
auto GetTilesMargins() const -> QMarginsF;
/**
* @brief GetTilesMargins Returns margins of the tiles in the given unit
* @param unit the unit in which we want the margins
* @return the margins in the given unit
*/
auto GetTilesMargins(Unit unit) const -> QMarginsF;
/**
* @brief GetTilesMarginsConverted Returns the margins of the tiles in the layout's unit
* @return the margins in the tiles's unit
*/
auto GetTilesMarginsConverted() const -> QMarginsF;
/**
* @brief GetShowTiles Returns true if the tiles has to be shown on the current sheet
* @return true if the tiles has to be shown on the current sheet
*/
auto GetShowTiles() const -> bool;
/**
* @brief SetShowTiles Sets wether to show the tiles on the current sheet or not
* @param value true to show the tiles
*/
void SetShowTiles(bool value);
// Sheet
/**
* @brief GetShowGrid Returns true if the placement grid has to be shown on the current sheet
* @return true if the placement grid has to be shown on the current sheet
*/
auto GetShowGrid() const -> bool;
/**
* @brief SetShowGrid Returns true if the placement grid has to be shown on the current sheet
* @param value whether to show the grid or not
*/
void SetShowGrid(bool value);
/**
* @brief GetGridColWidth returns the placement grid column width in Unit::Px
* @return the placement grid column width in Unit::Px
*/
auto GetGridColWidth() const -> qreal;
/**
* @brief GetGridColWidth returns the placement grid column width in the layout's unit
* @return the placement grid column width in the layout's unit
*/
auto GetGridColWidthConverted() const -> qreal;
/**
* @brief SetGridColWidth sets the placement grid column width to the given value, the unit has to be Unit::Px
* @param value the placement grid column width in Unit::Px
*/
void SetGridColWidth(qreal value);
/**
* @brief SetGridColWidthConverted sets the placement grid column width to the given value, the unit has to be in
* the layout's unit
* @param value the placement grid column width in the layout's unit
*/
void SetGridColWidthConverted(qreal value);
/**
* @brief GetGridRowHeight returns the placement grid row height in Unit::Px
* @return the placement grid row height in Unit::Px
*/
auto GetGridRowHeight() const -> qreal;
/**
* @brief GetGridRowHeightConverted returns the placement grid row height in the layout's unit
* @return the placement grid row height in the layout's unit
*/
auto GetGridRowHeightConverted() const -> qreal;
/**
* @brief SetGridRowHeight sets the placement grid row height to the given value, the unit has to be Unit::Px
* @param value the placement grid row height in Unit::Px
*/
void SetGridRowHeight(qreal value);
/**
* @brief SetGridRowHeightConverted sets the placement grid row height to the given value, the unit has to be in
* the layout's unit
* @param value the placement grid row height in the layout's unit
*/
void SetGridRowHeightConverted(qreal value);
auto IgnoreTilesMargins() const -> bool;
void SetIgnoreTilesMargins(bool newIgnoreTilesMargins);
auto HorizontalScale() const -> qreal;
void SetHorizontalScale(qreal newHorizontalScale);
auto VerticalScale() const -> qreal;
void SetVerticalScale(qreal newVerticalScale);
auto WatermarkPath() const -> const QString &;
void SetWatermarkPath(const QString &newWatermarkPath);
auto GetShowWatermark() const -> bool;
void SetShowWatermark(bool newShowWatermark);
bool GetPrintTilesScheme() const;
void SetPrintTilesScheme(bool newPrintTilesScheme);
private:
Unit m_unit{Unit::Cm};
bool m_warningSuperpositionOfPieces{false};
bool m_warningPiecesOutOfBound{false};
QString m_title{};
QString m_description{};
/**
* @brief m_size the Size of the tiles in Unit::Px
*/
QSizeF m_tilesSize{};
// margins
/**
* @brief m_margins the margins of the tiles in Unit::Px
*/
QMarginsF m_tilesMargins{};
bool m_ignoreTilesMargins{false};
bool m_showTiles{false};
bool m_showWatermark{false};
// control
bool m_followGrainLine{false};
/**
* @brief m_piecesGap the pieces gap in Unit::Px
*/
qreal m_piecesGap{0};
// placement grid
/**
* @brief GetShowGrid Returns true if the placement grid has to be shown on the current sheet
*/
bool m_showGrid{false};
/**
* @brief m_gridColWidth the column width of the placement grid in Unit::Px
*/
qreal m_gridColWidth{0};
/**
* @brief m_gridRowHeight the row height of the placement grid in Unit::Px
*/
qreal m_gridRowHeight{0};
bool m_stickyEdges{false};
qreal m_horizontalScale{1.0};
qreal m_verticalScale{1.0};
QString m_watermarkPath{};
bool m_printTilesScheme{false};
};
#endif // VPLAYOUTSETTINGS_H

View file

@ -0,0 +1,514 @@
/************************************************************************
**
** @file vppiece.cpp
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vppiece.h"
#include <QtMath>
#include "../vmisc/def.h"
#include "vpsheet.h"
#include "vplayout.h"
#include "../vlayout/vtextmanager.h"
#include "../vlayout/vlayoutpiecepath.h"
#include <QIcon>
#include <QLoggingCategory>
#include <QPainter>
Q_LOGGING_CATEGORY(pPiece, "p.piece")
namespace
{
constexpr qreal minStickyDistance = ToPixel(3, Unit::Mm);
constexpr qreal maxStickyDistance = ToPixel(10, Unit::Mm);
constexpr qreal stickyShift = ToPixel(1, Unit::Mm);
//---------------------------------------------------------------------------------------------------------------------
auto CutEdge(const QLineF &edge) -> QVector<QPointF>
{
QVector<QPointF> points;
if (qFuzzyIsNull(stickyShift))
{
points.append(edge.p1());
points.append(edge.p2());
}
else
{
const int n = qFloor(edge.length()/stickyShift);
if (n <= 0)
{
points.append(edge.p1());
points.append(edge.p2());
}
else
{
points.reserve(n);
const qreal nShift = edge.length()/n;
for (int i = 1; i <= n+1; ++i)
{
QLineF l1 = edge;
l1.setLength(nShift*(i-1));
points.append(l1.p2());
}
}
}
return points;
}
//---------------------------------------------------------------------------------------------------------------------
auto PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>
{
if (path.size() < 2)
{
return path;
}
QVector<QPointF> stickyPath;
for (int i=0; i<path.size(); ++i)
{
stickyPath += CutEdge(QLineF(path.at(i), path.at(i < path.size()-1 ? i+1 : 0)));
}
return stickyPath;
}
//---------------------------------------------------------------------------------------------------------------------
auto ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF
{
qreal distance = INT_MAX;
QLineF closestDistance;
for (auto p1 : path1)
{
for (auto p2 : path2)
{
QLineF d(p1, p2);
if (d.length() <= distance)
{
distance = d.length();
closestDistance = d;
}
}
}
return closestDistance;
}
} // namespace
//---------------------------------------------------------------------------------------------------------------------
VPPiece::VPPiece(const VLayoutPiece &layoutPiece)
: VLayoutPiece(layoutPiece)
{
ClearTransformations();
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::Update(const VPPiecePtr &piece)
{
if (piece.isNull())
{
return;
}
SetName(piece->GetName());
SetCountourPoints(piece->GetContourPoints(), IsHideMainPath());
SetSeamAllowancePoints(GetSeamAllowancePoints(), piece->IsSeamAllowance(), piece->IsSeamAllowanceBuiltIn());
SetInternalPaths(GetInternalPaths());
SetPassmarks(GetPassmarks());
SetPlaceLabels(GetPlaceLabels());
SetGrainlineEnabled(piece->IsGrainlineEnabled());
SetGrainlineAngle(piece->GrainlineAngle());
SetGrainlineArrowType(piece->GrainlineArrowType());
SetGrainlinePoints(piece->GetGrainline());
SetPieceLabelRect(piece->GetPieceLabelRect());
SetPieceLabelData(piece->GetPieceLabelData());
SetPatternLabelRect(piece->GetPatternLabelRect());
SetPatternLabelData(piece->GetPatternLabelData());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::GetUniqueID() const -> QString
{
QString id = VLayoutPiece::GetUniqueID();
if (m_copyNumber > 1)
{
id = id + '_' + QString::number(m_copyNumber);
}
return id;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::ClearTransformations()
{
// Reset the piece position to the default state
SetMatrix(QTransform());
// restore original size
QTransform m;
m.scale(GetXScale(), GetYScale());
QTransform matrix = GetMatrix();
matrix *= m;
SetMatrix(matrix);
// translate the piece so that the top left corner of the bouding rect of the piece is at the position
// (0,0) in the sheet coordinate system
const QPointF offset = MappedDetailBoundingRect().topLeft();
Translate(-offset.x(), -offset.y());
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPosition(QPointF point)
{
QTransform matrix = GetMatrix();
const QPointF offset = MappedDetailBoundingRect().topLeft();
matrix.translate(point.x() - offset.x(), point.y() - offset.y());
SetMatrix(matrix);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::GetPosition() -> QPointF
{
QTransform matrix = GetMatrix();
return QPointF(matrix.dx(), matrix.dy());
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::RotateToGrainline(const VPTransformationOrigon &origin)
{
VPSheetPtr sheet = Sheet();
if (not IsGrainlineEnabled() || sheet.isNull())
{
return;
}
const QVector<QPointF> grainlinePoints = GetMappedGrainline();
if (grainlinePoints.count() < 2)
{
return;
}
QLineF grainline(grainlinePoints.first(), grainlinePoints.last());
QLineF canonical(grainlinePoints.first().x(), grainlinePoints.first().y(),
grainlinePoints.first().x()+100, grainlinePoints.first().y());
GrainlineType grainlineType = sheet->GrainlineOrientation();
auto DegreesAtFront = [grainline, canonical, grainlineType]()
{
QLineF atFront = canonical;
if (grainlineType == GrainlineType::Vertical)
{
atFront.setAngle(90);
}
qreal angleTo = grainline.angleTo(atFront);
return angleTo;
};
auto DegreesAtRear = [grainline, canonical, grainlineType]()
{
QLineF atRear = canonical;
atRear.setAngle(grainlineType == GrainlineType::Vertical ? 270 : 180);
qreal angleTo = grainline.angleTo(atRear);
return angleTo;
};
GrainlineArrowDirection type = GrainlineArrowType();
qreal degrees = 0;
if (type == GrainlineArrowDirection::atFront)
{
degrees = DegreesAtFront();
}
else if (type == GrainlineArrowDirection::atRear)
{
degrees = DegreesAtRear();
}
else
{
const qreal atFront = DegreesAtFront();
if (atFront <= 90 || atFront >= 270)
{
degrees = atFront;
}
else
{
degrees = DegreesAtRear();
}
}
if (origin.custom)
{
Rotate(MappedDetailBoundingRect().center(), degrees);
}
else
{
Rotate(origin.origin, degrees);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlineEnabled(bool enabled)
{
VLayoutPiece::SetGrainlineEnabled(enabled);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlineAngle(qreal angle)
{
VLayoutPiece::SetGrainlineAngle(angle);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlineArrowType(GrainlineArrowDirection type)
{
VLayoutPiece::SetGrainlineArrowType(type);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlinePoints(const QVector<QPointF> &points)
{
VLayoutPiece::SetGrainlinePoints(points);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::GetPieceLabelRect() const -> QVector<QPointF>
{
return VLayoutPiece::GetPieceLabelRect();
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPieceLabelRect(const QVector<QPointF> &rect)
{
VLayoutPiece::SetPieceLabelRect(rect);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::GetPieceLabelData() const -> VTextManager
{
return VLayoutPiece::GetPieceLabelData();
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPieceLabelData(const VTextManager &data)
{
VLayoutPiece::SetPieceLabelData(data);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::GetPatternLabelRect() const -> QVector<QPointF>
{
return VLayoutPiece::GetPatternLabelRect();
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPatternLabelRect(const QVector<QPointF> &rect)
{
VLayoutPiece::SetPatternLabelRect(rect);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::GetPatternLabelData() const -> VTextManager
{
return VLayoutPiece::GetPatternLabelData();
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetPatternLabelData(const VTextManager &data)
{
VLayoutPiece::SetPatternLabelData(data);
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::Flip()
{
QTransform pieceMatrix = GetMatrix();
QPointF center = pieceMatrix.map(DetailBoundingRect().center());
QTransform m;
m.translate(center.x(), 0);
m.scale(-1, 1);
m.translate(-center.x(), 0);
pieceMatrix *= m;
SetMatrix(pieceMatrix);
SetMirror(!IsMirror());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::StickyPosition(qreal &dx, qreal &dy) const -> bool
{
VPLayoutPtr layout = Layout();
if (layout.isNull() || not layout->LayoutSettings().GetStickyEdges())
{
return false;
}
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
if (pieceGap <= 0)
{
return false;
}
VPSheetPtr sheet = Sheet();
if (sheet.isNull())
{
return false;
}
QList<VPPiecePtr> allPieces = sheet->GetPieces();
if (allPieces.count() < 2)
{
return false;
}
QVector<QPointF> path = GetMappedExternalContourPoints();
QRectF boundingRect = VLayoutPiece::BoundingRect(path);
const qreal stickyDistance = pieceGap+minStickyDistance;
QRectF stickyZone = QRectF(boundingRect.topLeft().x()-stickyDistance, boundingRect.topLeft().y()-stickyDistance,
boundingRect.width()+stickyDistance*2, boundingRect.height()+stickyDistance*2);
QVector<QPointF> stickyPath = PrepareStickyPath(path);
QLineF closestDistance;
for (const auto& piece : allPieces)
{
if (piece.isNull() || piece->GetUniqueID() == GetUniqueID())
{
continue;
}
QVector<QPointF> piecePath = piece->GetMappedExternalContourPoints();
QRectF pieceBoundingRect = VLayoutPiece::BoundingRect(piecePath);
if (stickyZone.intersects(pieceBoundingRect) || pieceBoundingRect.contains(stickyZone) ||
stickyZone.contains(pieceBoundingRect))
{
if (not VPPiece::PathsSuperposition(path, piecePath))
{
QVector<QPointF> pieceStickyPath = PrepareStickyPath(piecePath);
closestDistance = ClosestDistance(stickyPath, pieceStickyPath);
}
}
}
if (closestDistance.isNull())
{
return false;
}
const qreal extraZone = qBound(minStickyDistance, pieceGap * 50 / 100, maxStickyDistance);
const qreal length = closestDistance.length();
if (length > pieceGap && length <= pieceGap + extraZone)
{
closestDistance.setLength(length - pieceGap);
QPointF diff = closestDistance.p2() - closestDistance.p1();
dx = diff.x();
dy = diff.y();
return true;
}
if (length < pieceGap && length >= pieceGap - extraZone)
{
closestDistance.setAngle(closestDistance.angle() + 180);
closestDistance.setLength(pieceGap - length);
QPointF diff = closestDistance.p2() - closestDistance.p1();
dx = diff.x();
dy = diff.y();
return true;
}
return false;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> bool
{
const QRectF path1Rect = VLayoutPiece::BoundingRect(path1);
const QPainterPath path1Path = VAbstractPiece::PainterPath(path1);
const QRectF path2Rect = VLayoutPiece::BoundingRect(path2);
const QPainterPath path2Path = VAbstractPiece::PainterPath(path2);
if (path1Rect.intersects(path2Rect) || path2Rect.contains(path1Rect) || path1Rect.contains(path2Rect))
{
if (path1Path.contains(path2Path) || path2Path.contains(path1Path) || path1Path.intersects(path2Path))
{
return true;
}
}
return false;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::IsValid() const -> bool
{
if (not IsHideMainPath() && GetContourPoints().isEmpty())
{
return false;
}
if (IsSeamAllowance() && IsSeamAllowanceBuiltIn() && GetContourPoints().isEmpty())
{
return false;
}
if (IsSeamAllowance() && not IsSeamAllowanceBuiltIn() && GetSeamAllowancePoints().isEmpty())
{
return false;
}
if (IsGrainlineEnabled() && GetGrainline().isEmpty())
{
return false;
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
quint16 VPPiece::CopyNumber() const
{
return m_copyNumber;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetCopyNumber(quint16 newCopyNumber)
{
m_copyNumber = qMax(static_cast<quint16>(1), newCopyNumber);
}

View file

@ -0,0 +1,205 @@
/************************************************************************
**
** @file vppiece.h
** @author Ronan Le Tiec
** @date 13 4, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPPIECE_H
#define VPPIECE_H
#include <QUuid>
#include <QVector>
#include <QPoint>
#include <QTransform>
#include "../vlayout/vlayoutpiece.h"
#include "../layout/layoutdef.h"
class VPLayout;
class VPSheet;
class VPPiece : public VLayoutPiece
{
public:
VPPiece() = default;
explicit VPPiece(const VLayoutPiece &layoutPiece);
virtual ~VPPiece() = default;
void Update(const VPPiecePtr &piece);
virtual auto GetUniqueID() const -> QString override;
void ClearTransformations();
/**
* @brief SetPosition Sets the position of the piece, in relation to the origin of the scene
* @param point the point where to set the piece
*/
void SetPosition(QPointF point);
/**
* @brief GetPosition Returns the position of the piece
* @return the position of the piece
*/
auto GetPosition() -> QPointF;
/**
* @brief RotateToGrainline rotates the piece to follow the grainline
*/
void RotateToGrainline(const VPTransformationOrigon &origin);
/**
* @brief SetSelected Sets wether the piece is selected
* @param value true if the piece is selected
*/
void SetSelected(bool value);
/**
* @brief IsSelected Returns wether the piece is selected. It emit the signal SelectionChanged
* @return true if the piece is selected
*/
auto IsSelected() const -> bool;
auto Sheet() const -> VPSheetPtr;
void SetSheet(const VPSheetPtr &newSheet);
auto Layout() const -> VPLayoutPtr;
void SetLayout(const VPLayoutPtr &layout);
void SetGrainlineEnabled(bool enabled);
void SetGrainlineAngle(qreal angle);
void SetGrainlineArrowType(GrainlineArrowDirection type);
void SetGrainlinePoints(const QVector<QPointF> &points);
auto GetPieceLabelRect() const -> QVector<QPointF>;
void SetPieceLabelRect(const QVector<QPointF> &rect);
auto GetPieceLabelData() const ->VTextManager;
void SetPieceLabelData(const VTextManager &data);
auto GetPatternLabelRect() const -> QVector<QPointF>;
void SetPatternLabelRect(const QVector<QPointF> &rect);
auto GetPatternLabelData() const ->VTextManager;
void SetPatternLabelData(const VTextManager &data);
/**
* @brief Flip horizontally mirror around center of bounding rect
*/
void Flip();
auto OutOfBound() const -> bool;
void SetOutOfBound(bool newOutOfBound);
auto HasSuperpositionWithPieces() const -> bool;
void SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces);
auto StickyPosition(qreal &dx, qreal &dy) const -> bool;
static auto PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> bool;
auto IsValid() const -> bool;
auto CopyNumber() const -> quint16;
void SetCopyNumber(quint16 newCopyNumber);
private:
Q_DISABLE_COPY(VPPiece)
VPLayoutWeakPtr m_layout{};
VPSheetWeakPtr m_sheet{};
bool m_isSelected{false};
bool m_outOfBound{false};
bool m_hasSuperpositionWithPieces{false};
quint16 m_copyNumber{1};
};
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetSelected(bool value)
{
m_isSelected = value;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::IsSelected() const -> bool
{
return m_isSelected;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::Sheet() const -> VPSheetPtr
{
return m_sheet;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetSheet(const VPSheetPtr &newSheet)
{
m_sheet = newSheet;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::Layout() const -> VPLayoutPtr
{
return m_layout;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetLayout(const VPLayoutPtr &layout)
{
SCASSERT(layout != nullptr)
m_layout = layout;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::OutOfBound() const -> bool
{
return m_outOfBound;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetOutOfBound(bool newOutOfBound)
{
m_outOfBound = newOutOfBound;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::HasSuperpositionWithPieces() const -> bool
{
return m_hasSuperpositionWithPieces;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces)
{
m_hasSuperpositionWithPieces = newHasSuperpositionWithPieces;
}
Q_DECLARE_METATYPE(VPPiecePtr)
#endif // VPPIECE_H

View file

@ -0,0 +1,839 @@
/************************************************************************
**
** @file vpsheet.cpp
** @author Ronan Le Tiec
** @date 23 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpsheet.h"
#include "vplayout.h"
#include "vppiece.h"
#include "../vpapplication.h"
#include "../vwidgets/vmaingraphicsscene.h"
#include "../scene/vpgraphicssheet.h"
#include "../scene/vpgraphicspiece.h"
#include "../scene/vpgraphicstilegrid.h"
#include "../scene/vpgraphicspiececontrols.h"
#include "../scene/vpgraphicstilegrid.h"
// VPSheetSceneData
//---------------------------------------------------------------------------------------------------------------------
VPSheetSceneData::VPSheetSceneData(const VPLayoutPtr &layout, const QUuid &sheetUuid)
: m_layout(layout),
m_scene(new VMainGraphicsScene()),
m_sheetUuid(sheetUuid)
{
SCASSERT(not layout.isNull())
m_graphicsSheet = new VPGraphicsSheet(layout);
m_graphicsSheet->setPos(0, 0);
m_scene->addItem(m_graphicsSheet);
m_graphicsTileGrid = new VPGraphicsTileGrid(layout, m_sheetUuid);
m_scene->addItem(m_graphicsTileGrid);
m_rotationControls = new VPGraphicsPieceControls(layout);
m_rotationControls->setVisible(false);
m_scene->addItem(m_rotationControls);
m_rotationOrigin = new VPGraphicsTransformationOrigin(layout);
m_rotationOrigin->setVisible(false);
m_scene->addItem(m_rotationOrigin);
QObject::connect(m_rotationControls, &VPGraphicsPieceControls::ShowOrigin,
m_rotationOrigin, &VPGraphicsTransformationOrigin::on_ShowOrigin);
QObject::connect(m_rotationControls, &VPGraphicsPieceControls::TransformationOriginChanged,
m_rotationOrigin, &VPGraphicsTransformationOrigin::SetTransformationOrigin);
}
//---------------------------------------------------------------------------------------------------------------------
VPSheetSceneData::~VPSheetSceneData()
{
delete m_scene;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheetSceneData::Scene() const -> VMainGraphicsScene *
{
return m_scene;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::RefreshLayout()
{
m_graphicsSheet->update();
m_graphicsTileGrid->update();
m_scene->update();
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::RefreshPieces()
{
qDeleteAll(m_graphicsPieces);
m_graphicsPieces.clear();
VPLayoutPtr layout = m_layout.toStrongRef();
if(layout.isNull())
{
return;
}
VPSheetPtr sheet = layout->GetSheet(m_sheetUuid);
if (not sheet.isNull())
{
QList<VPPiecePtr> pieces = sheet->GetPieces();
m_graphicsPieces.reserve(pieces.size());
for (const auto &piece : pieces)
{
if (not piece.isNull())
{
auto *graphicsPiece = new VPGraphicsPiece(piece);
m_graphicsPieces.append(graphicsPiece);
m_scene->addItem(graphicsPiece);
ConnectPiece(graphicsPiece);
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::PrepareForExport()
{
m_graphicsSheet->SetShowBorder(false);
m_graphicsSheet->SetShowMargin(false);
m_rotationControls->setVisible(false);
m_rotationOrigin->setVisible(false);
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
m_showGridTmp = layout->LayoutSettings().GetShowGrid();
layout->LayoutSettings().SetShowGrid(false);
m_showTilesTmp = layout->LayoutSettings().GetShowTiles();
layout->LayoutSettings().SetShowTiles(false);
VPSheetPtr sheet = layout->GetSheet(m_sheetUuid);
m_slectedPiecesTmp = sheet->GetSelectedPieces();
for (const auto& piece : m_slectedPiecesTmp)
{
if (not piece.isNull())
{
piece->SetSelected(false);
}
}
m_outOfBoundTmp = layout->LayoutSettings().GetWarningPiecesOutOfBound();
layout->LayoutSettings().SetWarningPiecesOutOfBound(false);
m_pieceSuperpositionTmp = layout->LayoutSettings().GetWarningSuperpositionOfPieces();
layout->LayoutSettings().SetWarningSuperpositionOfPieces(false);
}
RefreshLayout();
RefreshPieces();
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::CleanAfterExport()
{
m_graphicsSheet->SetShowBorder(true);
m_graphicsSheet->SetShowMargin(true);
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
layout->LayoutSettings().SetShowGrid(m_showGridTmp);
layout->LayoutSettings().SetShowTiles(m_showTilesTmp);
for (const auto& piece : m_slectedPiecesTmp)
{
if (not piece.isNull())
{
piece->SetSelected(true);
emit layout->PieceSelectionChanged(piece);
}
}
layout->LayoutSettings().SetWarningPiecesOutOfBound(m_outOfBoundTmp);
layout->LayoutSettings().SetWarningSuperpositionOfPieces(m_pieceSuperpositionTmp);
}
RefreshLayout();
RefreshPieces();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheetSceneData::GraphicsPieces() const -> const QList<VPGraphicsPiece *> &
{
return m_graphicsPieces;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheetSceneData::GraphicsPiecesAsItems() const -> QList<QGraphicsItem *>
{
QList<QGraphicsItem *> items;
items.reserve(m_graphicsPieces.size());
for(auto *item : m_graphicsPieces)
{
items.append(item);
}
return items;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheetSceneData::RotationControls() const -> VPGraphicsPieceControls *
{
return m_rotationControls;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheetSceneData::ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece *
{
VPGraphicsPiece *_graphicsPiece = nullptr;
for(auto *graphicPiece : m_graphicsPieces)
{
if(graphicPiece->GetPiece() == piece)
{
_graphicsPiece = graphicPiece;
}
}
return _graphicsPiece;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::RemovePiece(VPGraphicsPiece *piece)
{
m_graphicsPieces.removeAll(piece);
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::AddPiece(VPGraphicsPiece *piece)
{
m_graphicsPieces.append(piece);
ConnectPiece(piece);
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::SetTextAsPaths(bool textAsPaths) const
{
for (auto *piece : m_graphicsPieces)
{
if (piece != nullptr)
{
piece->SetTextAsPaths(textAsPaths);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::PrepareTilesScheme()
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
m_showTilesSchemeTmp = layout->LayoutSettings().GetShowTiles();
layout->LayoutSettings().SetShowTiles(true);
m_showTilesWatermarkSchemeTmp = layout->LayoutSettings().GetShowWatermark();
layout->LayoutSettings().SetShowWatermark(false);
}
RefreshLayout();
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::ClearTilesScheme()
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
layout->LayoutSettings().SetShowTiles(m_showTilesSchemeTmp);
layout->LayoutSettings().SetShowWatermark(m_showTilesWatermarkSchemeTmp);
}
RefreshLayout();
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::RefreshSheetSize()
{
if (m_graphicsSheet != nullptr)
{
m_graphicsSheet->RefreshBoundingRect();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheetSceneData::ConnectPiece(VPGraphicsPiece *piece)
{
SCASSERT(piece != nullptr)
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return;
}
QObject::connect(layout.get(), &VPLayout::PieceTransformationChanged, piece,
&VPGraphicsPiece::on_RefreshPiece);
QObject::connect(layout.get(), &VPLayout::PieceSelectionChanged,
m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls);
QObject::connect(layout.get(), &VPLayout::PiecePositionValidityChanged,
piece, &VPGraphicsPiece::on_RefreshPiece);
QObject::connect(piece, &VPGraphicsPiece::PieceTransformationChanged,
m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls);
QObject::connect(piece, &VPGraphicsPiece::HideTransformationHandles,
m_rotationControls, &VPGraphicsPieceControls::on_HideHandles);
QObject::connect(piece, &VPGraphicsPiece::HideTransformationHandles,
m_rotationOrigin, &VPGraphicsTransformationOrigin::on_HideHandles);
}
// VPSheet
//---------------------------------------------------------------------------------------------------------------------
VPSheet::VPSheet(const VPLayoutPtr &layout) :
m_layout(layout),
m_sceneData(new VPSheetSceneData(layout, Uuid()))
{
SCASSERT(not layout.isNull())
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
SetIgnoreMargins(settings->GetLayoutSheetIgnoreMargins());
SetSheetMargins(settings->GetLayoutSheetMargins());
SetSheetSize(QSizeF(settings->GetLayoutSheetPaperWidth(), settings->GetLayoutSheetPaperHeight()));
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetLayout() const -> VPLayoutPtr
{
return m_layout;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetPieces() const -> QList<VPPiecePtr>
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
return layout->PiecesForSheet(m_uuid);
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSelectedPieces() const -> QList<VPPiecePtr>
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
QList<VPPiecePtr> list = layout->PiecesForSheet(m_uuid);
QList<VPPiecePtr> selected;
selected.reserve(list.size());
for (const auto& piece : list)
{
if (not piece.isNull() && piece->IsSelected())
{
selected.append(piece);
}
}
return selected;
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetAsLayoutPieces() const -> QVector<VLayoutPiece>
{
QList<VPPiecePtr> pieces = GetPieces();
QVector<VLayoutPiece> details;
details.reserve(pieces.size());
for (const auto& piece : pieces)
{
if (not piece.isNull())
{
details.append(*piece);
}
}
return details;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetName() const -> QString
{
return m_name;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetName(const QString &name)
{
m_name = name;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::Uuid() const -> const QUuid &
{
return m_uuid;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::IsVisible() const -> bool
{
return m_visible;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetVisible(bool visible)
{
m_visible = visible;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GrainlineOrientation() const -> GrainlineType
{
if (m_grainlineType == GrainlineType::NotFixed)
{
if (m_size.height() < m_size.width())
{
return GrainlineType::Horizontal;
}
return GrainlineType::Vertical;
}
return m_grainlineType;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetGrainlineType() const -> GrainlineType
{
return m_grainlineType;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetGrainlineType(GrainlineType type)
{
m_grainlineType = type;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::TransformationOrigin() const -> const VPTransformationOrigon &
{
return m_transformationOrigin;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetTransformationOrigin(const VPTransformationOrigon &newTransformationOrigin)
{
m_transformationOrigin = newTransformationOrigin;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::Clear()
{
m_name.clear();
m_visible = true;
m_transformationOrigin = VPTransformationOrigon();
m_trashSheet = false;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::TrashSheet() const -> bool
{
return m_trashSheet;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetTrashSheet(bool newTrashSheet)
{
m_trashSheet = newTrashSheet;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidateSuperpositionOfPieces() const
{
QList<VPPiecePtr> pieces = GetPieces();
for (const auto &piece : pieces)
{
if (piece.isNull())
{
continue;
}
const bool oldSuperpositionOfPieces = piece->HasSuperpositionWithPieces();
QVector<QPointF> path1 = piece->GetMappedExternalContourPoints();
bool hasSuperposition = false;
for (const auto &p : pieces)
{
if (p.isNull() || piece == p)
{
continue;
}
QVector<QPointF> path2 = p->GetMappedExternalContourPoints();
bool superposition = VPPiece::PathsSuperposition(path1, path2);
if (superposition)
{
hasSuperposition = superposition;
break;
}
}
piece->SetHasSuperpositionWithPieces(hasSuperposition);
if (oldSuperpositionOfPieces != piece->HasSuperpositionWithPieces())
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
emit layout->PiecePositionValidityChanged(piece);
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const
{
if (piece.isNull())
{
return;
}
const bool oldOutOfBound = piece->OutOfBound();
QRectF pieceRect = piece->MappedDetailBoundingRect();
QRectF sheetRect = GetMarginsRect();
piece->SetOutOfBound(not sheetRect.contains(pieceRect));
if (oldOutOfBound != piece->OutOfBound())
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
emit layout->PiecePositionValidityChanged(piece);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidatePiecesOutOfBound() const
{
QList<VPPiecePtr> pieces = GetPieces();
for (const auto &piece : pieces)
{
ValidatePieceOutOfBound(piece);
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetRect() const -> QRectF
{
return QRectF(QPoint(0, 0), m_size);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetMarginsRect() const -> QRectF
{
if (not m_ignoreMargins)
{
QRectF rect = QRectF(QPointF(m_margins.left(), m_margins.top()),
QPointF(m_size.width() - m_margins.right(), m_size.height() - m_margins.bottom()));
return rect;
}
return QRectF(0, 0, m_size.width(), m_size.height());
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::RemoveUnusedLength()
{
VPLayoutPtr layout = GetLayout();
if (layout.isNull())
{
return;
}
QList<VPPiecePtr> pieces = GetPieces();
if (pieces.isEmpty())
{
return;
}
QRectF piecesBoundingRect;
for (const auto& piece : pieces)
{
if (not piece.isNull())
{
piecesBoundingRect = piecesBoundingRect.united(piece->MappedDetailBoundingRect());
}
}
const qreal extra = 2;
QRectF sheetRect = GetSheetRect();
GrainlineType type = GrainlineOrientation();
if (type == GrainlineType::Vertical)
{
qreal margin = 0;
if (not m_ignoreMargins)
{
margin = m_margins.bottom();
}
if (sheetRect.bottomRight().y() - margin > piecesBoundingRect.bottomRight().y())
{
m_size = QSizeF(m_size.width(), piecesBoundingRect.bottomRight().y() + margin + extra);
}
}
else if (type == GrainlineType::Horizontal)
{
qreal margin = 0;
if (not m_ignoreMargins)
{
margin = m_margins.right();
}
if (sheetRect.topRight().x() - margin > piecesBoundingRect.topRight().x())
{
m_size = QSizeF(piecesBoundingRect.topRight().x() + margin + extra, m_size.height());
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const
{
VPLayoutPtr layout = GetLayout();
if (layout.isNull())
{
return;
}
QList<VPPiecePtr> pieces = GetPieces();
if (piece.isNull() || not pieces.contains(piece))
{
return;
}
if (layout->LayoutSettings().GetWarningPiecesOutOfBound())
{
ValidatePieceOutOfBound(piece);
}
if (layout->LayoutSettings().GetWarningSuperpositionOfPieces())
{
ValidateSuperpositionOfPieces();
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::SceneData() const -> VPSheetSceneData *
{
return m_sceneData;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ClearSelection() const
{
QList<VPPiecePtr> selectedPieces = GetSelectedPieces();
for (const auto& piece : selectedPieces)
{
if (piece->IsSelected())
{
piece->SetSelected(false);
}
}
if (not selectedPieces.isEmpty())
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
emit layout->PieceSelectionChanged(VPPiecePtr());
}
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetOrientation() const -> QPageLayout::Orientation
{
return m_size.height() >= m_size.width() ? QPageLayout::Portrait : QPageLayout::Landscape;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::SheetUnits() const -> Unit
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
return layout->LayoutSettings().GetUnit();
}
return Unit::Cm;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetSize(qreal width, qreal height)
{
m_size.setWidth(width);
m_size.setHeight(height);
if (m_sceneData != nullptr)
{
m_sceneData->RefreshSheetSize();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetSizeConverted(qreal width, qreal height)
{
Unit unit = SheetUnits();
m_size.setWidth(UnitConvertor(width, unit, Unit::Px));
m_size.setHeight(UnitConvertor(height, unit, Unit::Px));
if (m_sceneData != nullptr)
{
m_sceneData->RefreshSheetSize();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetSize(const QSizeF &size)
{
m_size = size;
if (m_sceneData != nullptr)
{
m_sceneData->RefreshSheetSize();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetSizeConverted(const QSizeF &size)
{
Unit unit = SheetUnits();
m_size = QSizeF(UnitConvertor(size.width(), unit, Unit::Px),
UnitConvertor(size.height(), unit, Unit::Px));
if (m_sceneData != nullptr)
{
m_sceneData->RefreshSheetSize();
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetSize() const -> QSizeF
{
return m_size;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetSizeConverted() const -> QSizeF
{
Unit unit = SheetUnits();
QSizeF convertedSize = QSizeF(
UnitConvertor(m_size.width(), Unit::Px, unit),
UnitConvertor(m_size.height(), Unit::Px, unit)
);
return convertedSize;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetMargins(qreal left, qreal top, qreal right, qreal bottom)
{
m_margins.setLeft(left);
m_margins.setTop(top);
m_margins.setRight(right);
m_margins.setBottom(bottom);
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetMarginsConverted(qreal left, qreal top, qreal right, qreal bottom)
{
Unit unit = SheetUnits();
m_margins.setLeft(UnitConvertor(left, unit, Unit::Px));
m_margins.setTop(UnitConvertor(top, unit, Unit::Px));
m_margins.setRight(UnitConvertor(right, unit, Unit::Px));
m_margins.setBottom(UnitConvertor(bottom, unit, Unit::Px));
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetMargins(const QMarginsF &margins)
{
m_margins = margins;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetSheetMarginsConverted(const QMarginsF &margins)
{
Unit unit = SheetUnits();
m_margins = UnitConvertor(margins, unit, Unit::Px);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetMargins() const -> QMarginsF
{
return m_margins;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetMarginsConverted() const -> QMarginsF
{
Unit unit = SheetUnits();
return UnitConvertor(m_margins, Unit::Px, unit);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::IgnoreMargins() const -> bool
{
return m_ignoreMargins;
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::SetIgnoreMargins(bool newIgnoreMargins)
{
m_ignoreMargins = newIgnoreMargins;
}

View file

@ -0,0 +1,317 @@
/************************************************************************
**
** @file vpsheet.h
** @author Ronan Le Tiec
** @date 23 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPSHEET_H
#define VPSHEET_H
#include <QSizeF>
#include <QMarginsF>
#include <QList>
#include <QComboBox>
#include <QUuid>
#include "def.h"
#include "layoutdef.h"
class VPLayout;
class VPPiece;
class VMainGraphicsScene;
class VPGraphicsPieceControls;
class VPGraphicsTransformationOrigin;
class VPGraphicsPiece;
class VPGraphicsTileGrid;
class VPGraphicsSheet;
class VLayoutPiece;
class VPSheetSceneData
{
public:
explicit VPSheetSceneData(const VPLayoutPtr &layout, const QUuid &sheetUuid);
~VPSheetSceneData();
VMainGraphicsScene *Scene() const;
/**
* @brief RefreshLayout Refreshes the rectangles for the layout border and the margin
*/
void RefreshLayout();
void RefreshPieces();
/**
* @brief PrepareForExport prepares the graphic for an export (i.e hide margin etc)
*/
void PrepareForExport();
/**
* @brief CleanAfterExport cleans the graphic for an export (i.e show margin etc)
*/
void CleanAfterExport();
auto GraphicsPieces() const -> const QList<VPGraphicsPiece *> &;
auto GraphicsPiecesAsItems() const -> QList<QGraphicsItem *>;
auto RotationControls() const -> VPGraphicsPieceControls *;
auto ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece *;
void RemovePiece(VPGraphicsPiece *piece);
void AddPiece(VPGraphicsPiece *piece);
void SetTextAsPaths(bool textAsPaths) const;
void PrepareTilesScheme();
void ClearTilesScheme();
void RefreshSheetSize();
private:
Q_DISABLE_COPY(VPSheetSceneData)
VPLayoutWeakPtr m_layout{};
VMainGraphicsScene *m_scene;
VPGraphicsSheet *m_graphicsSheet{nullptr};
VPGraphicsTileGrid *m_graphicsTileGrid{nullptr};
VPGraphicsPieceControls *m_rotationControls{nullptr};
VPGraphicsTransformationOrigin *m_rotationOrigin{nullptr};
QList<VPGraphicsPiece*> m_graphicsPieces{};
/**
* variable to hold temporarly hte value of the show tiles
*/
bool m_showTilesTmp{false};
bool m_showTilesSchemeTmp{false};
bool m_showTilesWatermarkSchemeTmp{false};
/**
* variable to hold temporarly hte value of the show grid
*/
bool m_showGridTmp{false};
QUuid m_sheetUuid;
QList<VPPiecePtr> m_slectedPiecesTmp{};
bool m_outOfBoundTmp{false};
bool m_pieceSuperpositionTmp{false};
void ConnectPiece(VPGraphicsPiece *piece);
};
class VPSheet : public QObject
{
Q_OBJECT
public:
explicit VPSheet(const VPLayoutPtr &layout);
virtual ~VPSheet() = default;
/**
* @brief GetLayout Returns the Layout of the sheet
* @return Layout of the sheet
*/
auto GetLayout() const -> VPLayoutPtr;
auto GetPieces() const -> QList<VPPiecePtr>;
auto GetSelectedPieces() const -> QList<VPPiecePtr>;
auto GetAsLayoutPieces() const -> QVector<VLayoutPiece>;
/**
* @brief GetName Returns the name of the sheet
* @return the name
*/
auto GetName() const -> QString;
/**
* @brief SetName Sets the name of the sheet to the given name
* @param name the new sheet's name
*/
void SetName(const QString &name);
auto Uuid() const -> const QUuid &;
bool IsVisible() const;
void SetVisible(bool visible);
auto GrainlineOrientation() const -> GrainlineType;
auto GetGrainlineType() const -> GrainlineType;
void SetGrainlineType(GrainlineType type);
auto TransformationOrigin() const -> const VPTransformationOrigon &;
void SetTransformationOrigin(const VPTransformationOrigon &newTransformationOrigin);
void Clear();
auto TrashSheet() const -> bool;
void SetTrashSheet(bool newTrashSheet);
void ValidateSuperpositionOfPieces() const;
void ValidatePieceOutOfBound(const VPPiecePtr &piece) const;
void ValidatePiecesOutOfBound() const;
auto GetSheetRect() const -> QRectF;
auto GetMarginsRect() const -> QRectF;
void RemoveUnusedLength();
/**
* @brief SetSheetSize sets the size of the sheet, the values have to be in Unit::Px
* @param width sheet width
* @param height sheet height
*/
void SetSheetSize(qreal width, qreal height);
/**
* @brief SetSheetSize sets the size of the sheet, the values have to be in the layout's unit
* @param width sheet width
* @param height sheet height
*/
void SetSheetSizeConverted(qreal width, qreal height);
/**
* @brief SetSheetSize sets the size of the sheet, the values have to be in Unit::Px
* @param size sheet size
*/
void SetSheetSize(const QSizeF &size);
/**
* @brief SetSheetSizeConverted sets the size of the sheet, the values have to be in the layout's unit
* @param size sheet size
*/
void SetSheetSizeConverted(const QSizeF &size);
/**
* @brief GetSheetSize Returns the size in Unit::Px
* @return sheet size in Unit::Px
*/
auto GetSheetSize() const -> QSizeF;
/**
* @brief GetSheetSizeConverted Returns the size in the layout's unit
* @return the size in the layout's unit
*/
auto GetSheetSizeConverted() const -> QSizeF;
/**
* @brief SetSheetMargins, set the margins of the sheet, the values have to be in Unit::Px
* @param left in Unit::Px
* @param top in Unit::Px
* @param right in Unit::Px
* @param bottom in Unit::Px
*/
void SetSheetMargins(qreal left, qreal top, qreal right, qreal bottom);
/**
* @brief SetSheetMargins, set the margins of the sheet, the values have to be in the unit of the layout
* @param left in Unit::Px
* @param top in Unit::Px
* @param right in Unit::Px
* @param bottom in Unit::Px
*/
void SetSheetMarginsConverted(qreal left, qreal top, qreal right, qreal bottom);
/**
* @brief SetSheetMargins set the margins of the sheet, the values have to be in Unit::Px
* @param margins sheet margins
*/
void SetSheetMargins(const QMarginsF &margins);
/**
* @brief SetSheetMargins set the margins of the sheet, the values have to be in the unit of the layout
* @param margins sheet margins
*/
void SetSheetMarginsConverted(const QMarginsF &margins);
/**
* @brief GetSheetMargins Returns the size in Unit::Px
* @return the size in Unit::Px
*/
auto GetSheetMargins() const -> QMarginsF;
/**
* @brief GetSheetMarginsConverted Returns the margins in the layout's unit
* @return the margins in the sheet's unit
*/
auto GetSheetMarginsConverted() const -> QMarginsF;
auto IgnoreMargins() const -> bool;
void SetIgnoreMargins(bool newIgnoreMargins);
VPSheetSceneData *SceneData() const;
void ClearSelection() const;
auto GetSheetOrientation() const -> QPageLayout::Orientation;
public slots:
void CheckPiecePositionValidity(const VPPiecePtr &piece) const;
private:
Q_DISABLE_COPY(VPSheet)
VPLayoutWeakPtr m_layout{};
QString m_name{};
QUuid m_uuid{QUuid::createUuid()};
bool m_visible{true};
bool m_trashSheet{false};
VPTransformationOrigon m_transformationOrigin{};
/**
* @brief m_size the Size in Unit::Px
*/
QSizeF m_size{};
// margins
/**
* @brief m_margins the margins in Unit::Px
*/
QMarginsF m_margins{};
bool m_ignoreMargins{false};
GrainlineType m_grainlineType{GrainlineType::NotFixed};
VPSheetSceneData *m_sceneData{nullptr};
auto SheetUnits() const -> Unit;
};
Q_DECLARE_METATYPE(VPSheetPtr)
#endif // VPSHEET_H

86
src/app/puzzle/main.cpp Normal file
View file

@ -0,0 +1,86 @@
/************************************************************************
**
** @file main.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 16 2, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include <QMessageBox> // For QT_REQUIRE_VERSION
#include <QTimer>
#include "vpapplication.h"
#include "../fervor/fvupdater.h"
#include "../vmisc/vsysexits.h"
#include "../vmisc/def.h"
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
# include "../vmisc/backport/qscopeguard.h"
#else
# include <QScopeGuard>
#endif
# include "../vmisc/appimage.h"
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
int main(int argc, char *argv[])
{
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
/* Fix path to ICU_DATA when run AppImage.*/
char *exe_dir = IcuDataPath("/../share/icu");
auto FreeMemory = qScopeGuard([exe_dir] {free(exe_dir);});
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
Q_INIT_RESOURCE(puzzleicon);
Q_INIT_RESOURCE(theme);
Q_INIT_RESOURCE(icon);
Q_INIT_RESOURCE(schema);
Q_INIT_RESOURCE(flags);
Q_INIT_RESOURCE(style);
Q_INIT_RESOURCE(cursor);
QT_REQUIRE_VERSION(argc, argv, "5.4.0")// clazy:exclude=qstring-arg,qstring-allocations
#if defined(Q_OS_WIN)
VAbstractApplication::WinAttachConsole();
#endif
#ifndef Q_OS_MAC // supports natively
InitHighDpiScaling(argc, argv);
#endif //Q_OS_MAC
VPApplication app(argc, argv);
app.InitOptions();
QTimer::singleShot(0, &app, &VPApplication::ProcessCMD);
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
if (exe_dir)
{
qDebug() << "Path to ICU folder:" << exe_dir;
}
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
return app.exec();
}

93
src/app/puzzle/puzzle.pri Normal file
View file

@ -0,0 +1,93 @@
# ADD TO EACH PATH $$PWD VARIABLE!!!!!!
# This need for corect working file translations.pro
SOURCES += \
$$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.cpp \
$$PWD/dialogs/configpages/puzzlepreferenceslayoutpage.cpp \
$$PWD/dialogs/dialogpuzzlepreferences.cpp \
$$PWD/dialogs/vpdialogabout.cpp \
$$PWD/layout/layoutdef.cpp \
$$PWD/main.cpp \
$$PWD/undocommands/vpundoaddsheet.cpp \
$$PWD/undocommands/vpundocommand.cpp \
$$PWD/undocommands/vpundomovepieceonsheet.cpp \
$$PWD/undocommands/vpundooriginmove.cpp \
$$PWD/undocommands/vpundopiecemove.cpp \
$$PWD/undocommands/vpundopiecerotate.cpp \
$$PWD/undocommands/vpundoremovesheet.cpp \
$$PWD/vpapplication.cpp \
$$PWD/carousel/vpcarrousel.cpp \
$$PWD/carousel/vpcarrouselpiece.cpp \
$$PWD/carousel/vpcarrouselpiecelist.cpp \
$$PWD/vpcommandline.cpp \
$$PWD/vpcommands.cpp \
$$PWD/scene/vpgraphicspiece.cpp \
$$PWD/scene/vpgraphicspiececontrols.cpp \
$$PWD/scene/vpgraphicssheet.cpp \
$$PWD/scene/vpgraphicstilegrid.cpp \
$$PWD/layout/vplayout.cpp \
$$PWD/layout/vplayoutsettings.cpp \
$$PWD/scene/vpmaingraphicsview.cpp \
$$PWD/vpmainwindow.cpp \
$$PWD/carousel/vpmimedatapiece.cpp \
$$PWD/layout/vppiece.cpp \
$$PWD/vpsettings.cpp \
$$PWD/layout/vpsheet.cpp \
$$PWD/vptilefactory.cpp \
$$PWD/xml/vplayoutfilereader.cpp \
$$PWD/xml/vplayoutfilewriter.cpp \
$$PWD/xml/vplayoutliterals.cpp \
$$PWD/dialogs/dialogsavemanuallayout.cpp
*msvc*:SOURCES += $$PWD/stable.cpp
HEADERS += \
$$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.h \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.h \
$$PWD/dialogs/configpages/puzzlepreferenceslayoutpage.h \
$$PWD/dialogs/dialogpuzzlepreferences.h \
$$PWD/dialogs/vpdialogabout.h \
$$PWD/layout/layoutdef.h \
$$PWD/scene/scenedef.h \
$$PWD/stable.h \
$$PWD/undocommands/vpundoaddsheet.h \
$$PWD/undocommands/vpundocommand.h \
$$PWD/undocommands/vpundomovepieceonsheet.h \
$$PWD/undocommands/vpundooriginmove.h \
$$PWD/undocommands/vpundopiecemove.h \
$$PWD/undocommands/vpundopiecerotate.h \
$$PWD/undocommands/vpundoremovesheet.h \
$$PWD/vpapplication.h \
$$PWD/carousel/vpcarrousel.h \
$$PWD/carousel/vpcarrouselpiece.h \
$$PWD/carousel/vpcarrouselpiecelist.h \
$$PWD/vpcommandline.h \
$$PWD/vpcommands.h \
$$PWD/scene/vpgraphicspiece.h \
$$PWD/scene/vpgraphicspiececontrols.h \
$$PWD/scene/vpgraphicssheet.h \
$$PWD/scene/vpgraphicstilegrid.h \
$$PWD/layout/vplayout.h \
$$PWD/layout/vplayoutsettings.h \
$$PWD/scene/vpmaingraphicsview.h \
$$PWD/vpmainwindow.h \
$$PWD/carousel/vpmimedatapiece.h \
$$PWD/layout/vppiece.h \
$$PWD/vpsettings.h \
$$PWD/layout/vpsheet.h \
$$PWD/vptilefactory.h \
$$PWD/xml/vplayoutfilereader.h \
$$PWD/xml/vplayoutfilewriter.h \
$$PWD/xml/vplayoutliterals.h \
$$PWD/dialogs/dialogsavemanuallayout.h
FORMS += \
$$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.ui \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.ui \
$$PWD/dialogs/configpages/puzzlepreferenceslayoutpage.ui \
$$PWD/dialogs/dialogpuzzlepreferences.ui \
$$PWD/dialogs/vpdialogabout.ui \
$$PWD/carousel/vpcarrousel.ui \
$$PWD/vpmainwindow.ui \
$$PWD/dialogs/dialogsavemanuallayout.ui

345
src/app/puzzle/puzzle.pro Normal file
View file

@ -0,0 +1,345 @@
#-------------------------------------------------
#
# Project created by QtCreator 2020-02-16T17:16:07
#
#-------------------------------------------------
# File with common stuff for whole project
include(../../../common.pri)
QT += core gui widgets network xml svg xmlpatterns printsupport concurrent
# Name of binary file
TARGET = puzzle
# We want create executable file
TEMPLATE = app
# Use out-of-source builds (shadow builds)
CONFIG -= debug_and_release debug_and_release_target
# Since Q5.12 available support for C++17
equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 11) {
CONFIG += c++17
} else {
CONFIG += c++14
}
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# Since Qt 5.4.0 the source code location is recorded only in debug builds.
# We need this information also in release builds. For this need define QT_MESSAGELOGCONTEXT.
DEFINES += QT_MESSAGELOGCONTEXT
# Directory for executable file
DESTDIR = bin
# Directory for files created moc
MOC_DIR = moc
# Directory for objecs files
OBJECTS_DIR = obj
# Directory for files created rcc
RCC_DIR = rcc
# Directory for files created uic
UI_DIR = uic
# Suport subdirectories. Just better project code tree.
include(puzzle.pri)
RESOURCES += \
share/resources/cursor.qrc \
share/resources/puzzleicon.qrc
include(../translations.pri)
# Set "make install" command for Unix-like systems.
unix{
!macx{
# Path to bin file after installation
target.path = $$BINDIR
INSTALLS += \
target
}
macx{
# Some macx stuff
QMAKE_MAC_SDK = macosx
# QMAKE_MACOSX_DEPLOYMENT_TARGET defined in common.pri
CONFIG(release, debug|release){
QMAKE_RPATHDIR += @executable_path/../Frameworks
# Path to resources in app bundle
#RESOURCES_DIR = "Contents/Resources" defined in translation.pri
FRAMEWORKS_DIR = "Contents/Frameworks"
MACOS_DIR = "Contents/MacOS"
# On macx we will use app bundle. Bundle doesn't need bin directory inside.
# See issue #166: Creating OSX Homebrew (Mac OS X package manager) formula.
target.path = $$MACOS_DIR
#languages added inside translations.pri
# Symlinks also good names for copying. Make will take origin file and copy them with using symlink name.
# For bundle this names more then enough. We don't need care much about libraries versions.
#libraries.path = $$FRAMEWORKS_DIR
#libraries.files += $${OUT_PWD}/../../libs/qmuparser/$${DESTDIR}/libqmuparser.2.dylib
#libraries.files += $${OUT_PWD}/../../libs/vpropertyexplorer/$${DESTDIR}/libvpropertyexplorer.1.dylib
# logo on macx.
ICON = $$PWD/../../../dist/Puzzle.icns
QMAKE_INFO_PLIST = $$PWD/../../../dist/macx/puzzle/Info.plist
format.path = $$RESOURCES_DIR/
format.files += $$PWD/../../../dist/macx/layout.icns
QMAKE_BUNDLE_DATA += \
#libraries \
format
}
}
}
#win32 {
# for(DIR, INSTALL_OPENSSL) {
# #add these absolute paths to a variable which
# #ends up as 'mkcommands = path1 path2 path3 ...'
# openssl_path += $${PWD}/$$DIR
# }
# copyToDestdir($$openssl_path, $$shell_path($${OUT_PWD}/$$DESTDIR))
#}
# Compilation will fail without this files after we added them to this section.
OTHER_FILES += \
share/resources/puzzleicon/64x64/logo.ico # Puzzle's logo.
# Set using ccache. Function enable_ccache() defined in common.pri.
$$enable_ccache()
include(warnings.pri)
CONFIG(release, debug|release){
# Release mode
!*msvc*:CONFIG += silent
DEFINES += V_NO_ASSERT
!unix:*g++*{
QMAKE_CXXFLAGS += -fno-omit-frame-pointer # Need for exchndl.dll
}
noDebugSymbols{ # For enable run qmake with CONFIG+=noDebugSymbols
DEFINES += V_NO_DEBUG
} else {
# Turn on debug symbols in release mode on Unix systems.
# On Mac OS X temporarily disabled. Need find way how to strip binary file.
!macx:!*msvc*{
QMAKE_CXXFLAGS_RELEASE += -g -gdwarf-3
QMAKE_CFLAGS_RELEASE += -g -gdwarf-3
QMAKE_LFLAGS_RELEASE =
}
}
} else {
# Breakpoints do not work if debug the app inside of bundle. In debug mode we turn off creating a bundle.
# Probably it will breake some dependencies. Version for Mac designed to work inside an app bundle.
CONFIG -= app_bundle
}
DVCS_HESH=$$FindBuildRevision()
message("Build revision:" $${DVCS_HESH})
DEFINES += "BUILD_REVISION=$${DVCS_HESH}" # Make available build revision number in sources.
# Path to recource file.
win32:RC_FILE = share/resources/puzzle.rc
noRunPath{ # For enable run qmake with CONFIG+=noRunPath
# do nothing
} else {
unix:!macx{
# suppress the default RPATH
# helps to run the program without Qt Creator
# see problem with path to libqmuparser and libpropertybrowser
QMAKE_LFLAGS_RPATH =
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\' -Wl,-rpath,$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -Wl,-rpath,$${OUT_PWD}/../../libs/vpropertyexplorer/$${DESTDIR}"
}
}
# When the GNU linker sees a library, it discards all symbols that it doesn't need.
# Dependent library go first.
##VTools static library (depend on VWidgets, VMisc, VPatternDB)
#unix|win32: LIBS += -L$$OUT_PWD/../../libs/vtools/$${DESTDIR}/ -lvtools
#INCLUDEPATH += $$PWD/../../libs/vtools
#INCLUDEPATH += $$OUT_PWD/../../libs/vtools/$${UI_DIR} # For UI files
#DEPENDPATH += $$PWD/../../libs/vtools
#win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vtools/$${DESTDIR}/vtools.lib
#else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vtools/$${DESTDIR}/libvtools.a
# VLayout static library (depend on VGeometry, VFormat)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vlayout/$${DESTDIR}/ -lvlayout
INCLUDEPATH += $$PWD/../../libs/vlayout
DEPENDPATH += $$PWD/../../libs/vlayout
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/vlayout.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vlayout/$${DESTDIR}/libvlayout.a
# VFormat static library (depend on VPatternDB, IFC)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vformat/$${DESTDIR}/ -lvformat
INCLUDEPATH += $$PWD/../../libs/vformat
DEPENDPATH += $$PWD/../../libs/vformat
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/vformat.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vformat/$${DESTDIR}/libvformat.a
#VPatternDB static library (depend on vgeometry, vmisc)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vpatterndb/$${DESTDIR} -lvpatterndb
INCLUDEPATH += $$PWD/../../libs/vpatterndb
DEPENDPATH += $$PWD/../../libs/vpatterndb
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/vpatterndb.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vpatterndb/$${DESTDIR}/libvpatterndb.a
# Fervor static library (depend on VMisc, IFC)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/fervor/$${DESTDIR}/ -lfervor
INCLUDEPATH += $$PWD/../../libs/fervor
DEPENDPATH += $$PWD/../../libs/fervor
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/fervor/$${DESTDIR}/fervor.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/fervor/$${DESTDIR}/libfervor.a
# IFC static library (depend on QMuParser, VMisc)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/ifc/$${DESTDIR}/ -lifc
INCLUDEPATH += $$PWD/../../libs/ifc
DEPENDPATH += $$PWD/../../libs/ifc
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/ifc/$${DESTDIR}/ifc.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/ifc/$${DESTDIR}/libifc.a
#VWidgets static library
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vwidgets/$${DESTDIR}/ -lvwidgets
INCLUDEPATH += $$PWD/../../libs/vwidgets
DEPENDPATH += $$PWD/../../libs/vwidgets
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vwidgets/$${DESTDIR}/vwidgets.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vwidgets/$${DESTDIR}/libvwidgets.a
#VMisc static library
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vmisc/$${DESTDIR}/ -lvmisc
INCLUDEPATH += $$PWD/../../libs/vmisc
DEPENDPATH += $$PWD/../../libs/vmisc
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/vmisc.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vmisc/$${DESTDIR}/libvmisc.a
# VGeometry static library (depend on ifc)
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/ -lvgeometry
INCLUDEPATH += $$PWD/../../libs/vgeometry
DEPENDPATH += $$PWD/../../libs/vgeometry
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/vgeometry.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vgeometry/$${DESTDIR}/libvgeometry.a
# VObj static library
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vobj/$${DESTDIR}/ -lvobj
INCLUDEPATH += $$PWD/../../libs/vobj
DEPENDPATH += $$PWD/../../libs/vobj
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vobj/$${DESTDIR}/vobj.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vobj/$${DESTDIR}/libvobj.a
# VDxf static library
unix|win32: LIBS += -L$$OUT_PWD/../../libs/vdxf/$${DESTDIR}/ -lvdxf
INCLUDEPATH += $$PWD/../../libs/vdxf
DEPENDPATH += $$PWD/../../libs/vdxf
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/vdxf.lib
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../../libs/vdxf/$${DESTDIR}/libvdxf.a
# QMuParser library
win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser2
else:unix: LIBS += -L$${OUT_PWD}/../../libs/qmuparser/$${DESTDIR} -lqmuparser
INCLUDEPATH += $${PWD}/../../libs/qmuparser
DEPENDPATH += $${PWD}/../../libs/qmuparser
# VPropertyExplorer library
win32:CONFIG(release, debug|release): LIBS += -L$${OUT_PWD}/../../libs/vpropertyexplorer/$${DESTDIR} -lvpropertyexplorer
else:win32:CONFIG(debug, debug|release): LIBS += -L$${OUT_PWD}/../../libs/vpropertyexplorer/$${DESTDIR} -lvpropertyexplorer
else:unix: LIBS += -L$${OUT_PWD}/../../libs/vpropertyexplorer/$${DESTDIR} -lvpropertyexplorer
INCLUDEPATH += $${PWD}/../../libs/vpropertyexplorer
DEPENDPATH += $${PWD}/../../libs/vpropertyexplorer
contains(DEFINES, APPIMAGE) {
unix:!macx: LIBS += -licudata -licui18n -licuuc
}
CONFIG(release, debug|release){
noStripDebugSymbols {
# do nothing
} else {
!macx:!*msvc*{
noDebugSymbols{ # For enable run qmake with CONFIG+=noDebugSymbols
win32:!*msvc*{
# Strip debug symbols.
QMAKE_POST_LINK += objcopy --strip-debug bin/${TARGET}
}
unix:!macx{
# Strip after you link all libaries.
QMAKE_POST_LINK += objcopy --strip-debug ${TARGET}
}
} else {
win32:!*msvc*{
# Strip debug symbols.
QMAKE_POST_LINK += objcopy --only-keep-debug bin/${TARGET} bin/${TARGET}.dbg &&
QMAKE_POST_LINK += objcopy --strip-debug bin/${TARGET} &&
QMAKE_POST_LINK += objcopy --add-gnu-debuglink="bin/${TARGET}.dbg" bin/${TARGET}
QMAKE_DISTCLEAN += bin/${TARGET}.dbg
}
unix:!macx{
# Strip debug symbols.
QMAKE_POST_LINK += objcopy --only-keep-debug ${TARGET} ${TARGET}.dbg &&
QMAKE_POST_LINK += objcopy --strip-debug ${TARGET} &&
QMAKE_POST_LINK += objcopy --add-gnu-debuglink="${TARGET}.dbg" ${TARGET}
QMAKE_DISTCLEAN += ${TARGET}.dbg
}
}
}
}
}
CONFIG(release, debug|release){
macx{
# run macdeployqt to include all qt libraries in packet
QMAKE_POST_LINK += $$[QT_INSTALL_BINS]/macdeployqt $${OUT_PWD}/$${DESTDIR}/$${TARGET}.app
}
}

View file

@ -0,0 +1,38 @@
/************************************************************************
**
** @file scenedef.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 7 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef SCENEDEF_H
#define SCENEDEF_H
enum class PGraphicsItem : int
{
Piece = 1,
Handles = 2,
TransformationOrigin = 3
};
#endif // SCENEDEF_H

View file

@ -0,0 +1,702 @@
/************************************************************************
**
** @file vpgraphicspiece.cpp
** @author Ronan Le Tiec
** @date 4 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpgraphicspiece.h"
#include <QPen>
#include <QBrush>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneContextMenuEvent>
#include <QMenu>
#include <QtMath>
#include <QGraphicsScene>
#include <QApplication>
#include "../layout/vppiece.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include "../vlayout/vtextmanager.h"
#include "vlayoutpiecepath.h"
#include "vplacelabelitem.h"
#include "undocommands/vpundopiecemove.h"
#include "undocommands/vpundomovepieceonsheet.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
namespace
{
constexpr qreal penWidth = 1;
QColor mainColor = Qt::black;
QColor errorColor = Qt::red;
}
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsPiece::VPGraphicsPiece(const VPPiecePtr &piece, QGraphicsItem *parent) :
QGraphicsObject(parent),
m_piece(piece)
{
QPixmap cursor_pixmap = QIcon("://puzzleicon/svg/cursor_rotate.svg").pixmap(QSize(32,32));
m_rotateCursor= QCursor(cursor_pixmap, 16, 16);
// set some infos
setFlags(ItemIsSelectable | ItemSendsGeometryChanges);
setAcceptHoverEvents(true);
setCursor(Qt::OpenHandCursor);
PaintPiece();
InitLabels();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::GetPiece() -> VPPiecePtr
{
return m_piece.toStrongRef();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::boundingRect() const -> QRectF
{
QPainterPath shape;
shape.addPath(m_seamLine);
shape.addPath(m_cuttingLine);
shape.addPath(m_grainline);
shape.addPath(m_internalPaths);
shape.addPath(m_passmarks);
shape.addPath(m_placeLabels);
shape.addPath(m_stickyPath);
constexpr qreal halfPenWidth = penWidth/2.;
return shape.boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::shape() const -> QPainterPath
{
if(!m_cuttingLine.isEmpty())
{
return m_cuttingLine;
}
return m_seamLine;
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
QPen pen(PieceColor(), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
PaintPiece(painter);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
//perform the default behaviour
QGraphicsObject::mousePressEvent(event);
// change the cursor when clicking the left button
if((event->button() == Qt::LeftButton))
{
setCursor(Qt::ClosedHandCursor);
m_moveStartPoint = event->pos();
emit HideTransformationHandles(true);
m_hasStickyPosition = false;
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsObject::mouseMoveEvent(event);
GroupMove(event->pos());
m_moveStartPoint = event->pos();
allowChangeMerge = true;
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
//perform the default behaviour
QGraphicsItem::mouseReleaseEvent(event);
// change the cursor when clicking left button
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::OpenHandCursor);
emit HideTransformationHandles(false);
VPPiecePtr piece = m_piece.toStrongRef();
if (not piece.isNull())
{
VPLayoutPtr layout = piece->Layout();
if (not layout.isNull())
{
if (layout->LayoutSettings().GetStickyEdges() && m_hasStickyPosition)
{
auto *command = new VPUndoPieceMove(piece, m_stickyTranslateX, m_stickyTranslateY,
allowChangeMerge);
layout->UndoStack()->push(command);
SetStickyPoints(QVector<QPointF>());
}
}
}
allowChangeMerge = false;
m_hasStickyPosition = false;
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return;
}
QMenu menu;
QList<VPSheetPtr> sheets = layout->GetSheets();
sheets.removeAll(piece->Sheet());
QVector<QAction*> moveToActions;
if (not sheets.isEmpty())
{
QMenu *moveMenu = menu.addMenu(tr("Move to"));
for (const auto &sheet : sheets)
{
if (not sheet.isNull())
{
QAction* moveToSheet = moveMenu->addAction(sheet->GetName());
moveToSheet->setData(QVariant::fromValue(sheet));
moveToActions.append(moveToSheet);
}
}
}
// remove from layout action
QAction *removeAction = menu.addAction(tr("Remove from Sheet"));
QAction *selectedAction = menu.exec(event->screenPos());
if (moveToActions.contains(selectedAction))
{
auto *command = new VPUndoMovePieceOnSheet(qvariant_cast<VPSheetPtr>(selectedAction->data()), piece);
layout->UndoStack()->push(command);
}
else if (selectedAction == removeAction)
{
auto *command = new VPUndoMovePieceOnSheet(VPSheetPtr(), piece);
layout->UndoStack()->push(command);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::SetTextAsPaths(bool newTextAsPaths)
{
m_textAsPaths = newTextAsPaths;
InitLabels();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::InitLabels()
{
qDeleteAll(m_labelPathItems);
qDeleteAll(m_labelTextItems);
m_labelPathItems.clear();
m_labelTextItems.clear();
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
InitPieceLabel(piece->GetPieceLabelRect(), piece->GetPieceLabelData());
InitPieceLabel(piece->GetPatternLabelRect(), piece->GetPatternLabelData());
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::SetStickyPoints(const QVector<QPointF> &newStickyPoint)
{
m_stickyPoints = newStickyPoint;
prepareGeometryChange();
PaintPiece(); // refresh shapes
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::InitPieceLabel(const QVector<QPointF> &labelShape, const VTextManager &tm)
{
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
if (labelShape.count() > 2)
{
const qreal dW = QLineF(labelShape.at(0), labelShape.at(1)).length();
const qreal dH = QLineF(labelShape.at(1), labelShape.at(2)).length();
const qreal angle = - QLineF(labelShape.at(0), labelShape.at(1)).angle();
qreal dY = 0;
QColor color = PieceColor();
for (int i = 0; i < tm.GetSourceLinesCount(); ++i)
{
const TextLine& tl = tm.GetSourceLine(i);
QFont fnt = tm.GetFont();
fnt.setPixelSize(tm.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
QFontMetrics fm(fnt);
if (m_textAsPaths)
{
dY += fm.height();
}
if (dY > dH)
{
break;
}
QString qsText = tl.m_qsText;
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
if (fm.horizontalAdvance(qsText) > dW)
#else
if (fm.width(qsText) > dW)
#endif
{
qsText = fm.elidedText(qsText, Qt::ElideMiddle, static_cast<int>(dW));
}
qreal dX = 0;
if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0)
{
dX = 0;
}
else if ((tl.m_eAlign & Qt::AlignHCenter) > 0)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
dX = (dW - fm.horizontalAdvance(qsText))/2;
#else
dX = (dW - fm.width(qsText))/2;
#endif
}
else if ((tl.m_eAlign & Qt::AlignRight) > 0)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
dX = dW - fm.horizontalAdvance(qsText);
#else
dX = dW - fm.width(qsText);
#endif
}
// set up the rotation around top-left corner matrix
QTransform labelMatrix;
labelMatrix.translate(labelShape.at(0).x(), labelShape.at(0).y());
if (piece->IsMirror())
{
labelMatrix.scale(-1, 1);
labelMatrix.rotate(-angle);
labelMatrix.translate(-dW, 0);
labelMatrix.translate(dX, dY); // Each string has own position
}
else
{
labelMatrix.rotate(angle);
labelMatrix.translate(dX, dY); // Each string has own position
}
labelMatrix *= piece->GetMatrix();
if (m_textAsPaths)
{
QPainterPath path;
path.addText(0, - static_cast<qreal>(fm.ascent())/6., fnt, qsText);
auto* item = new QGraphicsPathItem(this);
item->setPath(path);
item->setBrush(QBrush(color));
item->setTransform(labelMatrix);
m_labelPathItems.append(item);
dY += tm.GetSpacing();
}
else
{
auto* item = new QGraphicsSimpleTextItem(this);
item->setFont(fnt);
item->setText(qsText);
item->setBrush(QBrush(color));
item->setTransform(labelMatrix);
m_labelTextItems.append(item);
dY += (fm.height() + tm.GetSpacing());
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::PaintPiece(QPainter *painter)
{
QBrush noBrush(Qt::NoBrush);
QBrush selectionBrush(QColor(255,160,160,60));
m_seamLine = QPainterPath();
m_cuttingLine = QPainterPath();
m_grainline = QPainterPath();
m_internalPaths = QPainterPath();
m_passmarks = QPainterPath();
m_placeLabels = QPainterPath();
m_stickyPath = QPainterPath();
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
// initialises the seam line
if (not piece->IsHideMainPath() || not piece->IsSeamAllowance())
{
QVector<QPointF> seamLinePoints = piece->GetMappedContourPoints();
if(!seamLinePoints.isEmpty())
{
m_seamLine.moveTo(seamLinePoints.first());
for (int i = 1; i < seamLinePoints.size(); i++)
{
m_seamLine.lineTo(seamLinePoints.at(i));
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(piece->IsSelected() ? selectionBrush : noBrush);
painter->drawPath(m_seamLine);
painter->restore();
}
}
}
// initiliases the cutting line
if (piece->IsSeamAllowance() && not piece->IsSeamAllowanceBuiltIn())
{
QVector<QPointF> cuttingLinepoints = piece->GetMappedSeamAllowancePoints();
if(!cuttingLinepoints.isEmpty())
{
m_cuttingLine.moveTo(cuttingLinepoints.first());
for (int i = 1; i < cuttingLinepoints.size(); i++)
{
m_cuttingLine.lineTo(cuttingLinepoints.at(i));
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(isSelected() ? selectionBrush : noBrush);
painter->drawPath(m_cuttingLine);
painter->restore();
}
}
}
// initialises the grainline
if(piece->IsGrainlineEnabled())
{
QVector<QPointF> grainLinepoints = piece->GetMappedGrainline();
if(!grainLinepoints.isEmpty())
{
m_grainline.moveTo(grainLinepoints.first());
for (int i = 1; i < grainLinepoints.size(); i++)
{
m_grainline.lineTo(grainLinepoints.at(i));
}
if (painter != nullptr)
{
painter->save();
// here to fill the grainlines arrow. Not wanted for mvp
// later maybe if it's configurable
// painter->setBrush(blackBrush);
painter->setBrush(noBrush);
painter->drawPath(m_grainline);
painter->restore();
}
}
}
// initialises the internal paths
QVector<VLayoutPiecePath> internalPaths = piece->GetInternalPaths();
for (const auto& piecePath : internalPaths)
{
QPainterPath path = piece->GetMatrix().map(piecePath.GetPainterPath());
if (painter != nullptr)
{
painter->save();
QPen pen = painter->pen();
pen.setStyle(piecePath.PenStyle());
painter->setPen(pen);
painter->drawPath(path);
painter->restore();
}
m_internalPaths.addPath(path);
}
// initialises the passmarks
QVector<VLayoutPassmark> passmarks = piece->GetMappedPassmarks();
for(auto &passmark : passmarks)
{
QPainterPath passmarkPath;
for (auto &line : passmark.lines)
{
passmarkPath.moveTo(line.p1());
passmarkPath.lineTo(line.p2());
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(noBrush);
painter->drawPath(passmarkPath);
painter->restore();
}
m_passmarks.addPath(passmarkPath);
}
// initialises the place labels (buttons etc)
QVector<VLayoutPlaceLabel> placeLabels = piece->GetMappedPlaceLabels();
for(auto &placeLabel : placeLabels)
{
QPainterPath path = VPlaceLabelItem::LabelShapePath(placeLabel.shape);
if (painter != nullptr)
{
painter->save();
painter->setBrush(noBrush);
painter->drawPath(path);
painter->restore();
}
m_placeLabels.addPath(path);
}
if (not m_stickyPoints.isEmpty())
{
m_stickyPath.moveTo(m_stickyPoints.first());
for (int i = 1; i < m_stickyPoints.size(); i++)
{
m_stickyPath.lineTo(m_stickyPoints.at(i));
}
if (painter != nullptr)
{
painter->save();
painter->setBrush(QBrush(Qt::BDiagPattern));
QPen pen = painter->pen();
pen.setStyle(Qt::DashLine);
pen.setColor(mainColor);
painter->setPen(pen);
painter->drawPath(m_stickyPath);
painter->restore();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::GroupMove(const QPointF &pos)
{
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return;
}
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return;
}
auto PreparePieces = [layout]()
{
QList<VPPiecePtr> pieces;
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
return sheet->GetSelectedPieces();
}
return pieces;
};
QList<VPPiecePtr> pieces = PreparePieces();
QPointF newPos = pos - m_moveStartPoint;
if (qFuzzyIsNull(newPos.x()) && qFuzzyIsNull(newPos.y()))
{
return;
}
if (pieces.size() == 1)
{
VPPiecePtr p = pieces.first();
auto *command = new VPUndoPieceMove(piece, newPos.x(), newPos.y(), allowChangeMerge);
layout->UndoStack()->push(command);
if (layout->LayoutSettings().GetStickyEdges())
{
QVector<QPointF> path;
if (not p.isNull() && p->StickyPosition(m_stickyTranslateX, m_stickyTranslateY))
{
path = p->GetMappedExternalContourPoints();
QTransform m;
m.translate(m_stickyTranslateX, m_stickyTranslateY);
path = m.map(path);
m_hasStickyPosition = true;
}
else
{
m_hasStickyPosition = false;
}
SetStickyPoints(path);
}
}
else if (pieces.size() > 1)
{
auto *command = new VPUndoPiecesMove(pieces, newPos.x(), newPos.y(), allowChangeMerge);
layout->UndoStack()->push(command);
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::PieceColor() const -> QColor
{
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return mainColor;
}
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return mainColor;
}
bool outOfBound = false;
if (layout->LayoutSettings().GetWarningPiecesOutOfBound())
{
outOfBound = piece->OutOfBound();
}
bool superposition = false;
if (layout->LayoutSettings().GetWarningSuperpositionOfPieces())
{
superposition = piece->HasSuperpositionWithPieces();
}
if (outOfBound || superposition)
{
return errorColor;
}
return mainColor;
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_RefreshPiece(const VPPiecePtr &piece)
{
if (m_piece == piece)
{
prepareGeometryChange();
PaintPiece(); // refresh shapes
InitLabels();
emit PieceTransformationChanged();
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &value) -> QVariant
{
if (scene() != nullptr)
{
if(change == ItemSelectedHasChanged)
{
VPPiecePtr piece = m_piece.toStrongRef();
if (not piece.isNull())
{
piece->SetSelected(value.toBool());
VPLayoutPtr layout = piece->Layout();
if (not layout.isNull())
{
emit layout->PieceSelectionChanged(piece);
}
}
}
}
return QGraphicsObject::itemChange(change, value);
}

View file

@ -0,0 +1,119 @@
/************************************************************************
**
** @file vpgraphicspiece.h
** @author Ronan Le Tiec
** @date 4 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPGRAPHICSPIECE_H
#define VPGRAPHICSPIECE_H
#include <QGraphicsItem>
#include <QCursor>
#include "scenedef.h"
#include "../layout/layoutdef.h"
class VTextManager;
class VPGraphicsPiece : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsPiece(const VPPiecePtr &piece, QGraphicsItem *parent = nullptr);
~VPGraphicsPiece() = default;
/**
* @brief GetPiece Returns the piece that corresponds to the graphics piece
* @return the piece
*/
auto GetPiece() -> VPPiecePtr;
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::Piece)};
void SetStickyPoints(const QVector<QPointF> &newStickyPoint);
void SetTextAsPaths(bool newTextAsPaths);
signals:
void HideTransformationHandles(bool hide);
void PieceTransformationChanged();
public slots:
void on_RefreshPiece(const VPPiecePtr &piece);
protected:
auto boundingRect() const -> QRectF override;
auto shape() const -> QPainterPath override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
auto itemChange(GraphicsItemChange change, const QVariant &value) -> QVariant override;
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
private:
Q_DISABLE_COPY(VPGraphicsPiece)
VPPieceWeakPtr m_piece;
QPainterPath m_cuttingLine{};
QPainterPath m_seamLine{};
QPainterPath m_grainline{};
QPainterPath m_internalPaths{};
QPainterPath m_passmarks{};
QPainterPath m_placeLabels{};
QPointF m_moveStartPoint{};
QPointF m_rotationStartPoint{};
QCursor m_rotateCursor{};
bool allowChangeMerge{false};
QVector<QPointF> m_stickyPoints{};
QPainterPath m_stickyPath{};
bool m_hasStickyPosition{false};
qreal m_stickyTranslateX{0};
qreal m_stickyTranslateY{0};
bool m_textAsPaths{false};
QVector<QGraphicsPathItem *> m_labelPathItems{};
QVector<QGraphicsSimpleTextItem *> m_labelTextItems{};
void InitLabels();
void InitPieceLabel(const QVector<QPointF> &labelShape, const VTextManager &tm);
void PaintPiece(QPainter *painter=nullptr);
void GroupMove(const QPointF &pos);
QColor PieceColor() const;
};
#endif // VPGRAPHICSPIECE_H

View file

@ -0,0 +1,857 @@
/************************************************************************
**
** @file vpgraphicspiececontrols.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 2 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpgraphicspiececontrols.h"
#include <QCursor>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QIcon>
#include <QPainter>
#include <QtDebug>
#include "../vmisc/compatibility.h"
#include "../vwidgets/global.h"
#include "../layout/vplayout.h"
#include "../layout/vppiece.h"
#include "../undocommands/vpundopiecerotate.h"
#include "../undocommands/vpundooriginmove.h"
#include "vpgraphicspiece.h"
namespace
{
const qreal arcStartAngle = 105;
const qreal arcAngle = 25;
const qreal arcRadius = 15;
const qreal arrowTail = 2;
const qreal arrowSide = 2;
const qreal arrowLength = 4;
const qreal arrow1Angle = 13;
const qreal arrow2Angle = 38;
constexpr qreal penWidth = 2;
const qreal centerRadius1 = 5;
const qreal centerRadius2 = 10;
const QColor defaultColor = Qt::black;
const QColor hoverColor = Qt::green;
enum class HandleCorner : int
{
Invalid = 0,
TopLeft = 1,
TopRight = 2,
BottomRight = 3,
BottomLeft = 4
};
auto TransformationOrigin(const VPLayoutPtr &layout, const QRectF &boundingRect) -> VPTransformationOrigon
{
SCASSERT(layout != nullptr)
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
return sheet->TransformationOrigin();
}
VPTransformationOrigon origin;
origin.origin = boundingRect.center();
origin.custom = false;
return origin;
}
} // namespace
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsTransformationOrigin::VPGraphicsTransformationOrigin(const VPLayoutPtr &layout, QGraphicsItem *parent)
: QGraphicsObject(parent),
m_layout(layout),
m_color(defaultColor)
{
SCASSERT(m_layout != nullptr)
setCursor(Qt::OpenHandCursor);
setZValue(1);
setAcceptHoverEvents(true);
connect(layout.get(), &VPLayout::TransformationOriginChanged, this,
&VPGraphicsTransformationOrigin::SetTransformationOrigin);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::SetTransformationOrigin()
{
prepareGeometryChange();
update();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::on_HideHandles(bool hide)
{
m_originVisible = not hide;
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::on_ShowOrigin(bool show)
{
setVisible(show);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsTransformationOrigin::boundingRect() const -> QRectF
{
constexpr qreal halfPenWidth = penWidth/2.;
return Center2().boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsTransformationOrigin::shape() const -> QPainterPath
{
return Center2();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
const qreal scale = SceneScale(scene());
QPen pen(m_color, penWidth/scale, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
if (m_originVisible)
{
painter->save();
painter->setBrush(QBrush(m_color));
painter->drawPath(Center1());
painter->restore();
painter->save();
painter->setBrush(QBrush());
painter->drawPath(Center2());
painter->restore();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
// change the cursor when clicking the left button
if((event->button() == Qt::LeftButton))
{
setCursor(Qt::ClosedHandCursor);
event->accept();
}
else
{
//perform the default behaviour
QGraphicsObject::mousePressEvent(event);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
origin.origin = event->scenePos();
origin.custom = true;
auto *command = new VPUndoOriginMove(sheet, origin, m_allowChangeMerge);
layout->UndoStack()->push(command);
}
prepareGeometryChange();
}
m_allowChangeMerge = true;
QGraphicsObject::mouseMoveEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
//perform the default behaviour
QGraphicsItem::mouseReleaseEvent(event);
// change the cursor when clicking left button
if (event->button() == Qt::LeftButton)
{
setCursor(Qt::OpenHandCursor);
m_allowChangeMerge = false;
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
m_color = hoverColor;
QGraphicsObject::hoverEnterEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTransformationOrigin::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
m_color = defaultColor;
QGraphicsObject::hoverEnterEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsTransformationOrigin::RotationCenter(QPainter *painter) const -> QPainterPath
{
QPainterPath path;
const qreal scale = SceneScale(scene());
qreal radius = centerRadius1/scale;
VPTransformationOrigon transformationOrigin = TransformationOrigin(m_layout, QRectF());
QRectF rect(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2., radius*2.);
QPainterPath center1;
center1.addEllipse(rect);
if (painter != nullptr)
{
painter->save();
painter->setBrush(QBrush(m_color));
painter->drawPath(Center1());
painter->restore();
}
path.addPath(center1);
radius = centerRadius2/scale;
rect = QRectF(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2., radius*2.);
QPainterPath center2;
center2.addEllipse(rect);
if (painter != nullptr)
{
painter->save();
painter->setBrush(QBrush());
painter->drawPath(Center2());
painter->restore();
}
path.addPath(center2);
return path;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsTransformationOrigin::Center1() const -> QPainterPath
{
const qreal scale = SceneScale(scene());
qreal radius = centerRadius1/scale;
VPTransformationOrigon transformationOrigin = TransformationOrigin(m_layout, QRectF());
QRectF rect(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2., radius*2.);
QPainterPath center1;
center1.addEllipse(rect);
return center1;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsTransformationOrigin::Center2() const -> QPainterPath
{
const qreal scale = SceneScale(scene());
qreal radius = centerRadius2/scale;
VPTransformationOrigon transformationOrigin = TransformationOrigin(m_layout, QRectF());
QRectF rect = QRectF(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2.,
radius*2.);
QPainterPath center2;
center2.addEllipse(rect);
return center2;
}
// VPGraphicsPieceControls
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsPieceControls::VPGraphicsPieceControls(const VPLayoutPtr &layout, QGraphicsItem *parent)
: QGraphicsObject(parent),
m_layout(layout)
{
SCASSERT(m_layout != nullptr)
QPixmap cursor_pixmap = QIcon("://puzzleicon/svg/cursor_rotate.svg").pixmap(QSize(32,32));
setCursor(QCursor(cursor_pixmap, 16, 16));
setZValue(1);
setAcceptHoverEvents(true);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::on_UpdateControls()
{
if (m_ignorePieceTransformation)
{
return;
}
m_selectedPieces = SelectedPieces();
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
setVisible(not m_pieceRect.isNull());
if (not m_pieceRect.isNull())
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
VPTransformationOrigon origin = sheet->TransformationOrigin();
if (not origin.custom)
{
origin.origin = m_pieceRect.center();
sheet->SetTransformationOrigin(origin);
emit TransformationOriginChanged();
}
}
}
}
emit ShowOrigin(not m_pieceRect.isNull());
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::on_HideHandles(bool hide)
{
m_controlsVisible = not hide;
update();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::boundingRect() const -> QRectF
{
constexpr qreal halfPenWidth = penWidth/2.;
return Handles().boundingRect().adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::shape() const -> QPainterPath
{
return Handles();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
const qreal scale = SceneScale(scene());
QPen pen(defaultColor, penWidth/scale, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
if (m_controlsVisible)
{
TopLeftControl(painter);
TopRightControl(painter);
BottomLeftControl(painter);
BottomRightControl(painter);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
m_rotationStartPoint = event->scenePos();
m_rotationSum = 0;
m_controlsVisible = false;
m_handleCorner = HandleCorner(event->scenePos());
m_ignorePieceTransformation = true;
prepareGeometryChange();
}
else
{
QGraphicsObject::mousePressEvent(event);
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if((event->modifiers() & Qt::ShiftModifier) != 0U
&& static_cast<enum HandleCorner>(m_handleCorner) != HandleCorner::Invalid)
{
if (not m_originSaved)
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
m_savedOrigin = sheet->TransformationOrigin();
m_originSaved = true;
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
VPTransformationOrigon origin;
origin.custom = true;
if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::TopLeft)
{
origin.origin = m_pieceRect.topLeft();
}
else if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::TopRight)
{
origin.origin = m_pieceRect.topRight();
}
else if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::BottomRight)
{
origin.origin = m_pieceRect.bottomRight();
}
else if (static_cast<enum HandleCorner>(m_handleCorner) == HandleCorner::BottomLeft)
{
origin.origin = m_pieceRect.bottomLeft();
}
sheet->SetTransformationOrigin(origin);
emit TransformationOriginChanged();
}
}
}
}
else
{
if (m_originSaved)
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (sheet != nullptr)
{
if (not m_savedOrigin.custom)
{
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
m_savedOrigin.origin = m_pieceRect.center();
}
sheet->SetTransformationOrigin(m_savedOrigin);
emit TransformationOriginChanged();
}
m_originSaved = false;
}
}
}
QPointF rotationNewPoint = event->scenePos();
// get the angle from the center to the initial click point
VPTransformationOrigon rotationOrigin = TransformationOrigin(m_layout, m_pieceRect);
QLineF initPosition(rotationOrigin.origin, m_rotationStartPoint);
QLineF initRotationPosition(rotationOrigin.origin, rotationNewPoint);
qreal rotateOn = initPosition.angleTo(initRotationPosition);
if (rotateOn > 180)
{
rotateOn = rotateOn - 360.;
}
if (not qFuzzyIsNull(rotateOn))
{
auto PreparePieces = [this]()
{
QList<VPPiecePtr> pieces;
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
pieces = sheet->GetSelectedPieces();
}
}
return pieces;
};
QList<VPPiecePtr> pieces = PreparePieces();
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
if (layout->LayoutSettings().GetFollowGrainline() && not rotationOrigin.custom)
{
if (m_rotationSum > 90 || m_rotationSum < -90)
{
m_rotationSum = rotateOn;
}
else
{
m_rotationSum += rotateOn;
}
}
else
{
m_rotationSum = rotateOn;
}
if (pieces.size() == 1)
{
auto *command = new VPUndoPieceRotate(pieces.first(), rotationOrigin, rotateOn, m_rotationSum,
allowChangeMerge);
layout->UndoStack()->push(command);
}
else if (pieces.size() > 1)
{
auto *command = new VPUndoPiecesRotate(pieces, rotationOrigin, rotateOn, m_rotationSum,
allowChangeMerge);
layout->UndoStack()->push(command);
}
}
}
if (m_originSaved && m_savedOrigin.custom)
{
QLineF line(rotationOrigin.origin, m_savedOrigin.origin);
line.setAngle(line.angle()+rotateOn);
m_savedOrigin.origin = line.p2();
}
m_rotationStartPoint = rotationNewPoint;
allowChangeMerge = true;
QGraphicsObject::mouseMoveEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
m_controlsVisible = true;
m_ignorePieceTransformation = false;
if (m_originSaved)
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
if (not m_savedOrigin.custom)
{
m_pieceRect = PiecesBoundingRect(m_selectedPieces);
m_savedOrigin.origin = m_pieceRect.center();
}
sheet->SetTransformationOrigin(m_savedOrigin);
emit TransformationOriginChanged();
}
m_originSaved = false;
}
}
on_UpdateControls();
allowChangeMerge = false;
}
QGraphicsObject::mouseReleaseEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPieceControls::SetIgnorePieceTransformation(bool newIgnorePieceTransformation)
{
m_ignorePieceTransformation = newIgnorePieceTransformation;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::TopLeftControl(QPainter *painter) const -> QPainterPath
{
return Controller(QTransform(), painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::TopRightControl(QPainter *painter) const -> QPainterPath
{
QTransform t;
t.scale(-1, 1);
t.translate(-(m_pieceRect.topLeft().x() * 2. + m_pieceRect.width()), 0);
return Controller(t, painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::BottomLeftControl(QPainter *painter) const -> QPainterPath
{
QTransform t;
t.scale(1, -1);
t.translate(0, -(m_pieceRect.topLeft().y() * 2. + m_pieceRect.height()));
return Controller(t, painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::BottomRightControl(QPainter *painter) const -> QPainterPath
{
QTransform t;
t.scale(-1, -1);
t.translate(-(m_pieceRect.topLeft().x() * 2. + m_pieceRect.width()),
-(m_pieceRect.topLeft().y() * 2. + m_pieceRect.height()));
return Controller(t, painter);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::Handles() const -> QPainterPath
{
QPainterPath path;
path.addPath(TopLeftControl());
path.addPath(TopRightControl());
path.addPath(BottomLeftControl());
path.addPath(BottomRightControl());
return path;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::Controller(const QTransform &t, QPainter *painter) const -> QPainterPath
{
if (painter != nullptr)
{
QPen pen = painter->pen();
pen.setColor(defaultColor);
painter->setPen(pen);
}
QBrush colorBrush(defaultColor);
QPainterPath controller = ArrowPath();
controller = t.map(controller);
if (painter != nullptr)
{
painter->save();
painter->setBrush(colorBrush);
painter->drawPath(controller);
painter->restore();
}
return controller;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::ControllersRect() const -> QRectF
{
const qreal scale = SceneScale(scene());
const qreal gap = 2;
QRectF rect = m_pieceRect;
const qreal minWidth = arcRadius/scale+gap;
const qreal minHeight = arcRadius/scale+gap;
if (m_pieceRect.width() < minWidth)
{
qreal diff = minWidth - m_pieceRect.width();
rect.adjust(-diff/2., 0, diff/2., 0);
}
if (m_pieceRect.height() < minHeight)
{
qreal diff = minHeight - m_pieceRect.height();
rect.adjust(0, -diff/2., 0, diff/2.);
}
return rect;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::ArrowPath() const -> QPainterPath
{
const qreal scale = SceneScale(scene())/2;
QPainterPath arrow;
QRectF pieceRect = ControllersRect();
QLineF start(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius+1)/scale);
start.setAngle(arcStartAngle);
arrow.moveTo(start.p2());
QLineF baseLine(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow1Angle);
arrow.lineTo(baseLine.p2());
QLineF leftSide = QLineF(baseLine.p2(), baseLine.p1());
leftSide.setLength(arrowSide/scale);
leftSide.setAngle(leftSide.angle()-90);
arrow.lineTo(leftSide.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - arcRadius/scale);
start.setAngle(arcStartAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+(arrowTail+arrowLength)/scale, start.p2().y()));
baseLine.setAngle(arrow1Angle);
arrow.lineTo(baseLine.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius-1)/scale);
start.setAngle(arcStartAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow1Angle);
QLineF rightSide = QLineF(baseLine.p2(), baseLine.p1());
rightSide.setLength(arrowSide/scale);
rightSide.setAngle(rightSide.angle()+90);
arrow.lineTo(rightSide.p2());
arrow.lineTo(baseLine.p2());
arrow.lineTo(start.p2());
// arc 1
QRectF arc1Rect(pieceRect.topLeft().x()-(arcRadius-1)/scale, pieceRect.topLeft().y()-(arcRadius-1)/scale,
(arcRadius-1)/scale*2, (arcRadius-1)/scale*2);
arrow.arcTo(arc1Rect, arcStartAngle, arcAngle);
// arrow 2
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius-1)/scale);
start.setAngle(arcStartAngle+arcAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow2Angle+180);
arrow.lineTo(baseLine.p2());
leftSide = QLineF(baseLine.p2(), baseLine.p1());
leftSide.setLength(arrowSide/scale);
leftSide.setAngle(leftSide.angle()-90);
arrow.lineTo(leftSide.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - arcRadius/scale);
start.setAngle(arcStartAngle+arcAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+(arrowTail+arrowLength)/scale, start.p2().y()));
baseLine.setAngle(arrow2Angle+180);
arrow.lineTo(baseLine.p2());
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius+1)/scale);
start.setAngle(arcStartAngle+arcAngle);
baseLine = QLineF(start.p2(), QPointF(start.p2().x()+arrowTail/scale, start.p2().y()));
baseLine.setAngle(arrow2Angle+180);
rightSide = QLineF(baseLine.p2(), baseLine.p1());
rightSide.setLength(arrowSide/scale);
rightSide.setAngle(rightSide.angle()+90);
arrow.lineTo(rightSide.p2());
arrow.lineTo(baseLine.p2());
arrow.lineTo(start.p2());
// arc 2
QRectF arc2Rect(pieceRect.topLeft().x()-(arcRadius+1)/scale, pieceRect.topLeft().y()-(arcRadius+1)/scale,
(arcRadius+1)/scale*2, (arcRadius+1)/scale*2);
QPainterPath arc;
start = QLineF(pieceRect.topLeft().x(), pieceRect.topLeft().y(),
pieceRect.topLeft().x(), pieceRect.topLeft().y() - (arcRadius+1)/scale);
start.setAngle(arcStartAngle);
arc.moveTo(start.p2());
arc.arcTo(arc2Rect, arcStartAngle, arcAngle);
arrow.addPath(arc.toReversed());
return arrow;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::SelectedPieces() const -> QList<VPPiecePtr>
{
QList<VPPiecePtr> pieces;
VPLayoutPtr layout = m_layout.toStrongRef();
if (not layout.isNull())
{
VPSheetPtr sheet = layout->GetFocusedSheet();
if (not sheet.isNull())
{
pieces = sheet->GetSelectedPieces();
}
}
return pieces;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::PiecesBoundingRect(const QList<VPPiecePtr> &selectedPieces) -> QRectF
{
QRectF rect;
for (const auto& item : selectedPieces)
{
if (not item.isNull())
{
rect = rect.united(item->MappedDetailBoundingRect());
}
}
return rect;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsPieceControls::HandleCorner(const QPointF &pos) const -> int
{
if (TopLeftControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::BottomRight);
}
if (TopRightControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::BottomLeft);
}
if (BottomLeftControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::TopRight);
}
if (BottomRightControl().boundingRect().contains(pos))
{
return static_cast<int>(HandleCorner::TopLeft);
}
return static_cast<int>(HandleCorner::Invalid);
}

View file

@ -0,0 +1,138 @@
/************************************************************************
**
** @file vpgraphicspiececontrols.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 2 8, 2021
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2021 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPGRAPHICSPIECECONTROLS_H
#define VPGRAPHICSPIECECONTROLS_H
#include <QColor>
#include <QGraphicsObject>
#include "scenedef.h"
#include "../layout/vpsheet.h"
class VPLayout;
class VPGraphicsPiece;
class VPGraphicsTransformationOrigin : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsTransformationOrigin(const VPLayoutPtr &layout, QGraphicsItem * parent = nullptr);
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::TransformationOrigin)};
public slots:
void SetTransformationOrigin();
void on_HideHandles(bool hide);
void on_ShowOrigin(bool show);
protected:
auto boundingRect() const -> QRectF override;
auto shape() const -> QPainterPath override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private:
Q_DISABLE_COPY(VPGraphicsTransformationOrigin)
bool m_originVisible{true};
VPLayoutWeakPtr m_layout{};
QColor m_color;
bool m_allowChangeMerge{false};
auto RotationCenter(QPainter *painter = nullptr) const -> QPainterPath;
auto Center1() const -> QPainterPath;
auto Center2() const -> QPainterPath;
};
class VPGraphicsPieceControls : public QGraphicsObject
{
Q_OBJECT
public:
explicit VPGraphicsPieceControls(const VPLayoutPtr &layout, QGraphicsItem * parent = nullptr);
virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(PGraphicsItem::Handles)};
void SetIgnorePieceTransformation(bool newIgnorePieceTransformation);
signals:
void ShowOrigin(bool show);
void TransformationOriginChanged();
public slots:
void on_UpdateControls();
void on_HideHandles(bool hide);
protected:
auto boundingRect() const -> QRectF override;
auto shape() const -> QPainterPath override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
Q_DISABLE_COPY(VPGraphicsPieceControls)
QRectF m_pieceRect{};
QPointF m_rotationStartPoint{};
qreal m_rotationSum{0};
bool m_controlsVisible{true};
VPLayoutWeakPtr m_layout{};
int m_handleCorner{0};
VPTransformationOrigon m_savedOrigin{};
bool m_originSaved{false};
bool allowChangeMerge{false};
QList<VPPiecePtr> m_selectedPieces{};
bool m_ignorePieceTransformation{false};
auto TopLeftControl(QPainter *painter = nullptr) const -> QPainterPath;
auto TopRightControl(QPainter *painter = nullptr) const -> QPainterPath;
auto BottomLeftControl(QPainter *painter = nullptr) const -> QPainterPath;
auto BottomRightControl(QPainter *painter = nullptr) const -> QPainterPath;
auto Handles() const -> QPainterPath;
auto Controller(const QTransform &t, QPainter *painter = nullptr) const -> QPainterPath;
auto ControllersRect() const -> QRectF;
auto ArrowPath() const -> QPainterPath;
auto HandleCorner(const QPointF &pos) const -> int;
auto SelectedPieces() const -> QList<VPPiecePtr>;
static auto PiecesBoundingRect(const QList<VPPiecePtr> &selectedPieces) -> QRectF;
};
#endif // VPGRAPHICSPIECECONTROLS_H

View file

@ -0,0 +1,158 @@
/*******************************************************************
**
** @file vpgraphicssheet.cpp
** @author Ronan Le Tiec
** @date 3 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vpgraphicssheet.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include <QtMath>
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsSheet::VPGraphicsSheet(const VPLayoutPtr &layout, QGraphicsItem *parent):
QGraphicsItem(parent),
m_layout(layout)
{}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
QPen pen(QColor(0,179,255), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
pen.setCosmetic(true);
QBrush noBrush(Qt::NoBrush);
painter->setPen(pen);
painter->setBrush(noBrush);
QRectF sheetRect = GetSheetRect();
if(m_showMargin)
{
painter->drawRect(GetMarginsRect());
}
if(m_showBorder)
{
pen.setColor(Qt::black);
painter->setPen(pen);
painter->drawRect(sheetRect);
}
VPLayoutPtr layout = m_layout.toStrongRef();
if(not layout.isNull() && layout->LayoutSettings().GetShowGrid())
{
pen.setColor(QColor(204,204,204));
painter->setPen(pen);
qreal colWidth = layout->LayoutSettings().GetGridColWidth();
if(colWidth > 0)
{
qreal colX = colWidth;
while (colX < sheetRect.right())
{
QLineF line = QLineF(colX, 0, colX, sheetRect.bottom());
painter->drawLine(line);
colX += colWidth;
}
}
qreal rowHeight = layout->LayoutSettings().GetGridRowHeight();
if(rowHeight > 0)
{
qreal rowY = rowHeight;
while (rowY < sheetRect.bottom())
{
QLineF line = QLineF(0, rowY, sheetRect.right(), rowY);
painter->drawLine(line);
rowY += rowHeight;
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::GetSheetRect() const -> QRectF
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return {};
}
VPSheetPtr sheet = layout->GetFocusedSheet();
if (sheet.isNull())
{
return {};
}
return sheet->GetSheetRect();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::GetMarginsRect() const -> QRectF
{
VPLayoutPtr layout = m_layout.toStrongRef();
if (layout.isNull())
{
return {};
}
VPSheetPtr sheet = layout->GetFocusedSheet();
if (sheet.isNull())
{
return {};
}
return sheet->GetMarginsRect();
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::SetShowMargin(bool value)
{
m_showMargin = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::SetShowBorder(bool value)
{
m_showBorder = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsSheet::RefreshBoundingRect()
{
prepareGeometryChange();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::boundingRect() const -> QRectF
{
return GetSheetRect();
}

View file

@ -0,0 +1,74 @@
/************************************************************************
**
** @file vpgraphicssheet.h
** @author Ronan Le Tiec
** @date 3 5, 2020
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2020 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VPGRAPHICSSHEET_H
#define VPGRAPHICSSHEET_H
#include <QGraphicsItem>
#include <QPainter>
#include "../layout/layoutdef.h"
class VPLayout;
class VPGraphicsSheet : public QGraphicsItem
{
public:
explicit VPGraphicsSheet(const VPLayoutPtr &layout, QGraphicsItem *parent = nullptr);
~VPGraphicsSheet()=default;
auto boundingRect() const -> QRectF override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
auto GetSheetRect() const -> QRectF;
auto GetMarginsRect() const -> QRectF;
/**
* @brief SetShowMargin Sets Wether we see the margin
* @param value true to show the margin
*/
void SetShowMargin(bool value);
/**
* @brief SetShowBorder Sets whether we see the border of the sheet
* @param value true to show the border
*/
void SetShowBorder(bool value);
void RefreshBoundingRect();
private:
Q_DISABLE_COPY(VPGraphicsSheet)
VPLayoutWeakPtr m_layout{};
bool m_showMargin{true};
bool m_showBorder{true};
};
#endif // VPGRAPHICSSHEET_H

View file

@ -0,0 +1,130 @@
#include "vpgraphicstilegrid.h"
#include "../vptilefactory.h"
#include "../layout/vplayout.h"
#include "../layout/vpsheet.h"
#include <QFileInfo>
#include <QImageReader>
#include <QPixmapCache>
#include <QSvgRenderer>
namespace
{
constexpr qreal penWidth = 1;
} // namespace
//---------------------------------------------------------------------------------------------------------------------
VPGraphicsTileGrid::VPGraphicsTileGrid(const VPLayoutPtr &layout, const QUuid &sheetUuid, QGraphicsItem *parent):
QGraphicsItem(parent),
m_layout(layout),
m_sheetUuid(sheetUuid)
{
}
//---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsTileGrid::boundingRect() const -> QRectF
{
VPLayoutPtr layout = m_layout.toStrongRef();
if(not layout.isNull() && layout->LayoutSettings().GetShowTiles())
{
VPSheetPtr sheet = layout->GetSheet(m_sheetUuid);
QMarginsF sheetMargins;
if (not sheet.isNull() && not sheet->IgnoreMargins())
{
sheetMargins = sheet->GetSheetMargins();
}
qreal xScale = layout->LayoutSettings().HorizontalScale();
qreal yScale = layout->LayoutSettings().VerticalScale();
qreal width = layout->TileFactory()->DrawingAreaWidth() - VPTileFactory::tileStripeWidth;
qreal height = layout->TileFactory()->DrawingAreaHeight() - VPTileFactory::tileStripeWidth;
QRectF rect(sheetMargins.left(), sheetMargins.top(),
layout->TileFactory()->ColNb(sheet) * (width / xScale),
layout->TileFactory()->RowNb(sheet) * (height / yScale));
constexpr qreal halfPenWidth = penWidth/2.;
return rect.adjusted(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
}
return {};
}
//---------------------------------------------------------------------------------------------------------------------
void VPGraphicsTileGrid::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);
Q_UNUSED(option);
VPLayoutPtr layout = m_layout.toStrongRef();
if(not layout.isNull() && layout->LayoutSettings().GetShowTiles())
{
VPSheetPtr sheet = layout->GetSheet(m_sheetUuid);
QMarginsF sheetMargins;
if (not sheet.isNull() && not sheet->IgnoreMargins())
{
sheetMargins = sheet->GetSheetMargins();
}
QPen pen(QColor(255,0,0,127), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
pen.setCosmetic(true);
pen.setStyle(Qt::DashLine);
QBrush noBrush(Qt::NoBrush);
painter->setPen(pen);
painter->setBrush(noBrush);
qreal xScale = layout->LayoutSettings().HorizontalScale();
qreal yScale = layout->LayoutSettings().VerticalScale();
const qreal width = (layout->TileFactory()->DrawingAreaWidth() - VPTileFactory::tileStripeWidth) / xScale;
const qreal height = (layout->TileFactory()->DrawingAreaHeight() - VPTileFactory::tileStripeWidth) / yScale;
const int nbCol = layout->TileFactory()->ColNb(sheet);
const int nbRow = layout->TileFactory()->RowNb(sheet);
VWatermarkData watermarkData = layout->TileFactory()->WatermarkData();
for(int j=0;j<=nbRow;++j)
{
// horizontal lines
painter->drawLine(QPointF(sheetMargins.left(), sheetMargins.top()+j*height),
QPointF(sheetMargins.left()+nbCol*width, sheetMargins.top()+j*height));
for(int i=0;i<=nbCol;++i)
{
// vertical lines
painter->drawLine(QPointF(sheetMargins.left()+i*width, sheetMargins.top()),
QPointF(sheetMargins.left()+i*width, sheetMargins.top() + nbRow*height));
if (j < nbRow && i < nbCol)
{
QRectF img(sheetMargins.left()+i*width, sheetMargins.top()+j*height,
width, height);
if (not layout->LayoutSettings().WatermarkPath().isEmpty() &&
layout->LayoutSettings().GetShowWatermark())
{
if (watermarkData.opacity > 0)
{
if (watermarkData.showImage && not watermarkData.path.isEmpty())
{
VPTileFactory::PaintWatermarkImage(painter, img, watermarkData,
layout->LayoutSettings().WatermarkPath());
}
if (watermarkData.showText && not watermarkData.text.isEmpty())
{
VPTileFactory::PaintWatermarkText(painter, img, watermarkData);
}
}
}
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more