Merge remote-tracking branch 'refs/remotes/upstream/feature/manual-layout'

Conflicts:
	src/app/puzzle/vpmainwindow.cpp
	src/app/puzzle/vpmainwindow.h
This commit is contained in:
Ronan 2021-05-22 09:11:48 +02:00
commit c9a25613f5
81 changed files with 22238 additions and 1619 deletions

View File

@ -53,6 +53,3 @@ unix {
TEMPLATE = subdirs
SUBDIRS = src
RESOURCES += \
src/app/puzzle/share/resources/puzzleicon.qrc

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"

12
dist/debian/puzzle.1 vendored
View File

@ -20,7 +20,7 @@ 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>
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"
@ -40,20 +40,16 @@ Tiled page top margin in current units like 3.0 (export mode). If not set will b
.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.
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'.
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.
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 ">"
.SH "SEE ALSO"
.RB "Full " "User Manual" " is availiable in"
.UR https://bitbucket.org/dismine/valentina/wiki/manual/Content
.UE
.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

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.

View File

@ -9,9 +9,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSMinimumSystemVersion</key>
<string>10.6</string>
<string>10.7</string>
<key>NSHumanReadableCopyright</key>
<string>© 2013-2020, Valentina project</string>
<string>© 2013-2021, Valentina project</string>
<key>CFBundleSignature</key>
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
@ -19,11 +19,53 @@
<key>CFBundleIdentifier</key>
<string>io.bitbucket.valentinaproject.@EXECUTABLE@</string>
<key>CFBundleShortVersionString</key>
<string>0.7.0</string>
<string>0.7.47</string>
<key>CFBundleVersion</key>
<string>0.7.0.0</string>
<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>

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

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

@ -0,0 +1,104 @@
/************************************************************************
**
** @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;
});
// Theme
ui->darkModeCheck->setChecked(VPApplication::VApp()->PuzzleSettings()->GetDarkMode());
// Native dialogs
ui->checkBoxDontUseNativeDialog->setChecked(VPApplication::VApp()->PuzzleSettings()->IsDontUseNativeDialog());
//----------------------- Toolbar
ui->toolBarStyleCheck->setChecked(VPApplication::VApp()->PuzzleSettings()->GetToolBarStyle());
}
//---------------------------------------------------------------------------------------------------------------------
PuzzlePreferencesConfigurationPage::~PuzzlePreferencesConfigurationPage()
{
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
QStringList PuzzlePreferencesConfigurationPage::Apply()
{
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
}
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,117 @@
<?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>505</width>
<height>548</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<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>494</width>
<height>514</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<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>
<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>
<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,160 @@
/************************************************************************
**
** @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 <QMessageBox>
#include <QPushButton>
#include <QShowEvent>
//---------------------------------------------------------------------------------------------------------------------
DialogPuzzlePreferences::DialogPuzzlePreferences(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogPuzzlePreferences),
m_configurationPage(new PuzzlePreferencesConfigurationPage),
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_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();
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,71 @@
/************************************************************************
**
** @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 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;
PuzzlePreferencesPathPage *m_pathPage;
};
#endif // DIALOGPUZZLEPREFERENCES_H

View File

@ -0,0 +1,159 @@
<?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>0</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>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

@ -53,6 +53,11 @@ int main(int argc, char *argv[])
#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);
QT_REQUIRE_VERSION(argc, argv, "5.4.0")// clazy:exclude=qstring-arg,qstring-allocations

View File

@ -2,6 +2,9 @@
# This need for corect working file translations.pro
SOURCES += \
$$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.cpp \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.cpp \
$$PWD/dialogs/dialogpuzzlepreferences.cpp \
$$PWD/dialogs/vpdialogabout.cpp \
$$PWD/main.cpp \
$$PWD/vpapplication.cpp \
@ -30,6 +33,9 @@ SOURCES += \
*msvc*:SOURCES += $$PWD/stable.cpp
HEADERS += \
$$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.h \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.h \
$$PWD/dialogs/dialogpuzzlepreferences.h \
$$PWD/dialogs/vpdialogabout.h \
$$PWD/stable.h \
$$PWD/vpapplication.h \
@ -56,6 +62,9 @@ HEADERS += \
$$PWD/xml/vplayoutliterals.h
FORMS += \
$$PWD/dialogs/configpages/puzzlepreferencesconfigurationpage.ui \
$$PWD/dialogs/configpages/puzzlepreferencespathpage.ui \
$$PWD/dialogs/dialogpuzzlepreferences.ui \
$$PWD/dialogs/vpdialogabout.ui \
$$PWD/vpcarrousel.ui \
$$PWD/vpmainwindow.ui

View File

@ -66,17 +66,9 @@ include(../translations.pri)
# Set "make install" command for Unix-like systems.
unix{
# Prefix for binary file.
isEmpty(PREFIX){
PREFIX = $$DEFAULT_PREFIX
}
unix:!macx{
DATADIR =$$PREFIX/share
DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\"
!macx{
# Path to bin file after installation
target.path = $$PREFIX/bin
target.path = $$BINDIR
INSTALLS += \
target
@ -112,8 +104,7 @@ unix{
QMAKE_INFO_PLIST = $$PWD/../../../dist/macx/puzzle/Info.plist
format.path = $$RESOURCES_DIR/
format.files += $$PWD/../../../dist/macx/i-measurements.icns
format.files += $$PWD/../../../dist/macx/s-measurements.icns
format.files += $$PWD/../../../dist/macx/layout.icns
QMAKE_BUNDLE_DATA += \
#libraries \

View File

@ -61,7 +61,7 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
// writing a multithreaded application and the error happens on
// a non-GUI thread, you'll have to queue the message to the GUI
QCoreApplication *instance = QCoreApplication::instance();
const bool isGuiThread = instance && (QThread::currentThread() == instance->thread());
const bool isGuiThread = (instance != nullptr) && (QThread::currentThread() == instance->thread());
if (not isGuiThread)
{
@ -199,7 +199,7 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
if (type == QtWarningMsg || type == QtCriticalMsg || type == QtFatalMsg)
{
if (qApp->IsAppInGUIMode())
if (VPApplication::VApp()->IsAppInGUIMode())
{
if (topWinAllowsPop)
{
@ -234,9 +234,7 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
//---------------------------------------------------------------------------------------------------------------------
VPApplication::VPApplication(int &argc, char **argv)
:VAbstractApplication(argc, argv),
mainWindows(),
localServer(nullptr)
:VAbstractApplication(argc, argv)
{
setApplicationDisplayName(VER_PRODUCTNAME_STR);
setApplicationName(VER_INTERNALNAME_STR);
@ -264,7 +262,7 @@ VPApplication::~VPApplication()
* @return value that is returned from the receiver's event handler.
*/
// reimplemented from QApplication so we can throw exceptions in slots
bool VPApplication::notify(QObject *receiver, QEvent *event)
auto VPApplication::notify(QObject *receiver, QEvent *event) -> bool
{
try
{
@ -325,26 +323,24 @@ bool VPApplication::notify(QObject *receiver, QEvent *event)
/**
* @brief IsAppInGUIMode little hack that allow to have access to application state from VAbstractApplication class.
*/
bool VPApplication::IsAppInGUIMode() const
auto VPApplication::IsAppInGUIMode() const -> bool
{
return CommandLine()->IsGuiEnabled();
}
//---------------------------------------------------------------------------------------------------------------------
VPMainWindow *VPApplication::MainWindow()
auto VPApplication::MainWindow()-> VPMainWindow *
{
Clean();
if (mainWindows.isEmpty())
{
VPCommandLinePtr cmd;
VPCommandLine::ProcessInstance(cmd, QStringList());
NewMainWindow(VPCommandLinePtr());
NewMainWindow();
}
return mainWindows[0];
}
//---------------------------------------------------------------------------------------------------------------------
QList<VPMainWindow *> VPApplication::MainWindows()
auto VPApplication::MainWindows() -> QList<VPMainWindow *>
{
Clean();
QList<VPMainWindow*> list;
@ -356,13 +352,22 @@ QList<VPMainWindow *> VPApplication::MainWindows()
}
//---------------------------------------------------------------------------------------------------------------------
VPMainWindow *VPApplication::NewMainWindow(const VPCommandLinePtr &cmd)
auto VPApplication::NewMainWindow() -> VPMainWindow *
{
VPMainWindow *puzzle = new VPMainWindow(cmd);
VPCommandLinePtr cmd;
VPCommandLine::ProcessInstance(cmd, {ConstFirst<QString>(VPApplication::arguments())});
return NewMainWindow(cmd);
}
//---------------------------------------------------------------------------------------------------------------------
auto VPApplication::NewMainWindow(const VPCommandLinePtr &cmd) -> VPMainWindow *
{
auto *puzzle = new VPMainWindow(cmd);
mainWindows.prepend(puzzle);
if (cmd->IsGuiEnabled())
if (not cmd->IsTestModeEnabled())
{
puzzle->show();
puzzle->UpdateWindowTitle();
}
puzzle->InitZoom();
return puzzle;
@ -399,7 +404,7 @@ void VPApplication::InitOptions()
}
//---------------------------------------------------------------------------------------------------------------------
const VTranslateVars *VPApplication::TrVars()
auto VPApplication::TrVars() -> const VTranslateVars *
{
return nullptr;
}
@ -412,7 +417,7 @@ void VPApplication::OpenSettings()
}
//---------------------------------------------------------------------------------------------------------------------
VPSettings *VPApplication::PuzzleSettings()
auto VPApplication::PuzzleSettings() -> VPSettings *
{
SCASSERT(settings != nullptr)
return qobject_cast<VPSettings *>(settings);
@ -421,7 +426,7 @@ VPSettings *VPApplication::PuzzleSettings()
//---------------------------------------------------------------------------------------------------------------------
void VPApplication::ActivateDarkMode()
{
VPSettings *settings = qApp->PuzzleSettings();
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
if (settings->GetDarkMode())
{
QFile f(":qdarkstyle/style.qss");
@ -498,14 +503,14 @@ void VPApplication::ProcessArguments(const VPCommandLinePtr &cmd)
cmd.get()->parser.showHelp(V_EX_USAGE);
}
if (args.count() > 1 && rawLayouts.size() > 0)
if (args.count() > 1 && not rawLayouts.isEmpty())
{
qCCritical(pApp, "%s\n",
qPrintable(tr("Import raw layout data does not support penning several layout files.")));
qPrintable(tr("Import raw layout data does not support openning several layout files.")));
cmd.get()->parser.showHelp(V_EX_USAGE);
}
for (auto &arg : args)
for (const auto &arg : args)
{
NewMainWindow(cmd);
if (not MainWindow()->LoadFile(arg))
@ -518,7 +523,7 @@ void VPApplication::ProcessArguments(const VPCommandLinePtr &cmd)
continue;
}
if (rawLayouts.size() > 0)
if (not rawLayouts.isEmpty())
{
MainWindow()->ImportRawLayouts(rawLayouts);
}
@ -533,7 +538,7 @@ void VPApplication::ProcessArguments(const VPCommandLinePtr &cmd)
}
NewMainWindow(cmd);
if (rawLayouts.size() > 0)
if (not rawLayouts.isEmpty())
{
// MainWindow()->New(); // prepare layout settings
MainWindow()->ImportRawLayouts(rawLayouts);
@ -553,7 +558,7 @@ void VPApplication::ProcessCMD()
}
//---------------------------------------------------------------------------------------------------------------------
bool VPApplication::event(QEvent *e)
auto VPApplication::event(QEvent *e) -> bool
{
switch(e->type())
{
@ -561,12 +566,12 @@ bool VPApplication::event(QEvent *e)
// Mac specific).
case QEvent::FileOpen:
{
QFileOpenEvent *fileOpenEvent = static_cast<QFileOpenEvent *>(e);
auto *fileOpenEvent = static_cast<QFileOpenEvent *>(e);
const QString macFileOpen = fileOpenEvent->file();
if(not macFileOpen.isEmpty())
{
VPMainWindow *mw = MainWindow();
if (mw)
if (mw != nullptr)
{
mw->LoadFile(macFileOpen); // open file in existing window
}
@ -639,8 +644,14 @@ void VPApplication::Clean()
}
}
//--------------------------------------------------------------------------------------------
VPCommandLinePtr VPApplication::CommandLine() const
//---------------------------------------------------------------------------------------------------------------------
auto VPApplication::CommandLine() -> VPCommandLinePtr
{
return VPCommandLine::instance;
}
//---------------------------------------------------------------------------------------------------------------------
VPApplication *VPApplication::VApp()
{
return qobject_cast<VPApplication*>(QCoreApplication::instance());
}

View File

@ -35,15 +35,9 @@
#include <memory>
class VPApplication;// use in define
class VPMainWindow;
class QLocalServer;
#if defined(qApp)
#undef qApp
#endif
#define qApp (static_cast<VPApplication*>(VAbstractApplication::instance()))
enum class SocketConnection : bool {Client = false, Server = true};
class VPApplication : public VAbstractApplication
@ -58,6 +52,7 @@ public:
virtual bool IsAppInGUIMode() const override;
VPMainWindow *MainWindow();
QList<VPMainWindow*> MainWindows();
VPMainWindow *NewMainWindow();
VPMainWindow *NewMainWindow(const VPCommandLinePtr &cmd);
void InitOptions();
@ -70,7 +65,9 @@ public:
void ParseCommandLine(const SocketConnection &connection, const QStringList &arguments);
void ProcessArguments(const VPCommandLinePtr &cmd);
VPCommandLinePtr CommandLine() const;
static VPCommandLinePtr CommandLine();
static VPApplication *VApp();
public slots:
void ProcessCMD();
@ -86,8 +83,8 @@ private slots:
private:
Q_DISABLE_COPY(VPApplication)
QList<QPointer<VPMainWindow> > mainWindows;
QLocalServer *localServer;
QList<QPointer<VPMainWindow> > mainWindows{};
QLocalServer *localServer{nullptr};
void Clean();
};

View File

@ -44,6 +44,13 @@
#include "../ifc/exception/vexception.h"
#include "../vwidgets/vmaingraphicsscene.h"
#include "vpsheet.h"
#include "dialogs/dialogpuzzlepreferences.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
#include "../vmisc/backport/qscopeguard.h"
#else
#include <QScopeGuard>
#endif
#include <QLoggingCategory>
@ -57,19 +64,18 @@ QT_WARNING_POP
//---------------------------------------------------------------------------------------------------------------------
VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) :
QMainWindow(parent),
VAbstractMainWindow(parent),
ui(new Ui::VPMainWindow),
m_cmd(cmd)
m_cmd(cmd),
m_statusLabel(new QLabel(this))
{
m_layout = new VPLayout();
// create a standard sheet
VPSheet *sheet = new VPSheet(m_layout);
auto *sheet = new VPSheet(m_layout);
sheet->SetName(QObject::tr("Sheet 1"));
m_layout->AddSheet(sheet);
m_layout->SetFocusedSheet();
// ----- for test purposes, to be removed------------------
// // ----- for test purposes, to be removed------------------
sheet->SetSheetMarginsConverted(1, 1, 1, 1);
sheet->SetSheetSizeConverted(84.1, 118.9);
sheet->SetPiecesGapConverted(1);
@ -82,31 +88,42 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) :
m_layout->SetTilesSizeConverted(21,29.7);
m_layout->SetTilesOrientation(PageOrientation::Portrait);
m_layout->SetTilesMarginsConverted(1,1,1,1);
// m_layout->SetShowTiles(true);
m_layout->SetShowTiles(true);
// --------------------------------------------------------
ui->setupUi(this);
// init the tile factory
m_tileFactory = new VPTileFactory(m_layout, qApp->Settings());
m_tileFactory = new VPTileFactory(m_layout, VPApplication::VApp()->Settings());
m_tileFactory->refreshTileInfos();
// init the export tool
m_exporter = new VPExporter(m_layout, qApp->Settings());
InitMenuBar();
// init status bar
statusBar()->addPermanentWidget(m_statusLabel, 1);
SetupMenu();
InitProperties();
InitCarrousel();
InitMainGraphics();
InitZoomToolBar();
InitScaleToolBar();
SetPropertiesData();
ReadSettings();
#if defined(Q_OS_MAC)
// Mac OS Dock Menu
QMenu *menu = new QMenu(this);
connect(menu, &QMenu::aboutToShow, this, &VPMainWindow::AboutToShowDockMenu);
AboutToShowDockMenu();
menu->setAsDockMenu();
#endif //defined(Q_OS_MAC)
}
//---------------------------------------------------------------------------------------------------------------------
@ -117,11 +134,50 @@ VPMainWindow::~VPMainWindow()
}
//---------------------------------------------------------------------------------------------------------------------
bool VPMainWindow::LoadFile(QString path)
auto VPMainWindow::CurrentFile() const -> QString
{
return curFile;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPMainWindow::LoadFile(QString path) -> bool
{
if (not QFileInfo::exists(path))
{
qCCritical(pWindow, "%s", qUtf8Printable(tr("File '%1' doesn't exist!").arg(path)));
if (m_cmd->IsTestModeEnabled())
{
qApp->exit(V_EX_NOINPUT);
}
return false;
}
// Check if file already opened
QList<VPMainWindow*> list = VPApplication::VApp()->MainWindows();
auto w = std::find_if(list.begin(), list.end(),
[path](VPMainWindow *window) { return window->CurrentFile() == path; });
if (w != list.end())
{
(*w)->activateWindow();
close();
return false;
}
VlpCreateLock(lock, path);
if (not lock->IsLocked())
{
if (not IgnoreLocking(lock->GetLockError(), path, m_cmd->IsGuiEnabled()))
{
return false;
}
}
try
{
VLayoutConverter converter(path);
m_curFileFormatVersion = converter.GetCurrentFormatVersion();
m_curFileFormatVersionStr = converter.GetFormatVersionStr();
path = converter.Convert();
}
catch (VException &e)
@ -134,31 +190,81 @@ bool VPMainWindow::LoadFile(QString path)
QFile file(path);
file.open(QIODevice::ReadOnly);
QScopedPointer<VPLayoutFileReader> fileReader(new VPLayoutFileReader());
VPLayoutFileReader fileReader;
if(m_layout == nullptr)
{
m_layout = new VPLayout();
}
fileReader->ReadFile(m_layout, &file);
fileReader.ReadFile(m_layout, &file);
// TODO / FIXME : better return value and error handling
if (fileReader.hasError())
{
qCCritical(pWindow, "%s\n\n%s", qUtf8Printable(tr("File error.")),
qUtf8Printable(tr("Unable to read a layout file")));
lock.reset();
if (m_cmd->IsTestModeEnabled())
{
qApp->exit(V_EX_NOINPUT);
}
return false;
}
// updates the properties with the loaded data
SetPropertiesData();
// TODO : update the Carrousel and the QGraphicView
return true;
}
//---------------------------------------------------------------------------------------------------------------------
bool VPMainWindow::SaveFile(const QString &path)
void VPMainWindow::LayoutWasSaved(bool saved)
{
setWindowModified(!saved);
not lIsReadOnly ? ui->actionSave->setEnabled(!saved): ui->actionSave->setEnabled(false);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::SetCurrentFile(const QString &fileName)
{
curFile = fileName;
if (not curFile.isEmpty())
{
auto *settings = VPApplication::VApp()->PuzzleSettings();
QStringList files = settings->GetRecentFileList();
files.removeAll(fileName);
files.prepend(fileName);
while (files.size() > MaxRecentFiles)
{
files.removeLast();
}
settings->SetRecentFileList(files);
UpdateRecentFileActions();
}
UpdateWindowTitle();
}
//---------------------------------------------------------------------------------------------------------------------
auto VPMainWindow::SaveLayout(const QString &path, QString &error) -> bool
{
QFile file(path);
file.open(QIODevice::WriteOnly);
VPLayoutFileWriter *fileWriter = new VPLayoutFileWriter();
fileWriter->WriteFile(m_layout, &file);
VPLayoutFileWriter fileWriter;
fileWriter.WriteFile(m_layout, &file);
// TODO / FIXME : better return value and error handling
if (fileWriter.hasError())
{
error = tr("Fail to create layout.");
return false;
}
SetCurrentFile(path);
LayoutWasSaved(true);
return true;
}
@ -207,7 +313,10 @@ void VPMainWindow::ImportRawLayouts(const QStringList &rawLayouts)
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::InitZoom()
{
m_graphicsView->ZoomFitBest();
if (m_graphicsView != nullptr)
{
m_graphicsView->ZoomFitBest();
}
}
//---------------------------------------------------------------------------------------------------------------------
@ -234,13 +343,17 @@ VPPiece* VPMainWindow::CreatePiece(const VLayoutPiece &rawPiece)
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::InitMenuBar()
void VPMainWindow::SetupMenu()
{
// most of the actions are connected through name convention (auto-connection)
// -------------------- connects the actions for the file menu
ui->actionNew->setShortcuts(QKeySequence::New);
ui->actionSave->setShortcuts(QKeySequence::Save);
ui->actionSaveAs->setShortcuts(QKeySequence::SaveAs);
connect(ui->actionExit, &QAction::triggered, this, &VPMainWindow::close);
ui->actionExit->setShortcuts(QKeySequence::Quit);
// -------------------- connects the actions for the edit menu
// TODO : initialise the undo / redo
@ -250,8 +363,43 @@ void VPMainWindow::InitMenuBar()
// Add dock properties action
QAction* actionDockWidgetToolOptions = ui->dockWidgetProperties->toggleViewAction();
ui->menuWindows->addAction(actionDockWidgetToolOptions);
ui->menuEdit->addAction(actionDockWidgetToolOptions);
// File
m_recentFileActs.fill(nullptr);
for (auto & recentFileAct : m_recentFileActs)
{
auto *action = new QAction(this);
recentFileAct = action;
connect(action, &QAction::triggered, this, [this]()
{
if (auto *senderAction = qobject_cast<QAction *>(sender()))
{
const QString filePath = senderAction->data().toString();
if (not filePath.isEmpty())
{
LoadFile(filePath);
}
}
});
ui->menuFile->insertAction(ui->actionPreferences, recentFileAct);
recentFileAct->setVisible(false);
}
m_separatorAct = new QAction(this);
m_separatorAct->setSeparator(true);
m_separatorAct->setVisible(false);
ui->menuFile->insertAction(ui->actionPreferences, m_separatorAct);
// Actions for recent files loaded by a puzzle window application.
UpdateRecentFileActions();
// Window
connect(ui->menuWindow, &QMenu::aboutToShow, this, [this]()
{
ui->menuWindow->clear();
CreateWindowMenu(ui->menuWindow);
});
}
//---------------------------------------------------------------------------------------------------------------------
@ -603,10 +751,7 @@ void VPMainWindow::InitZoomToolBar()
delete m_doubleSpinBoxScale;
}
if (m_mouseCoordinate != nullptr)
{
delete m_mouseCoordinate;
}
delete m_mouseCoordinate;
// connect the zoom buttons and shortcuts to the slots
QList<QKeySequence> zoomInShortcuts;
@ -631,27 +776,29 @@ void VPMainWindow::InitZoomToolBar()
zoomFitBestShortcuts.append(QKeySequence(Qt::ControlModifier + Qt::Key_Equal));
ui->actionZoomFitBest->setShortcuts(zoomFitBestShortcuts);
connect(ui->actionZoomFitBest, &QAction::triggered, m_graphicsView, &VPMainGraphicsView::ZoomFitBest);
}
// defined the scale
ui->toolBarZoom->addSeparator();
QLabel* zoomScale = new QLabel(tr("Scale:"), this);
ui->toolBarZoom->addWidget(zoomScale);
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::InitScaleToolBar()
{
auto* zoomScale = new QLabel(tr("Scale:"), this);
ui->toolBarScale->addWidget(zoomScale);
m_doubleSpinBoxScale = new QDoubleSpinBox(this);
m_doubleSpinBoxScale->setDecimals(1);
m_doubleSpinBoxScale->setSuffix("%");
m_doubleSpinBoxScale->setSuffix(QChar('%'));
on_ScaleChanged(m_graphicsView->transform().m11());
connect(m_doubleSpinBoxScale.data(), QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, [this](double d){m_graphicsView->Zoom(d/100.0);});
ui->toolBarZoom->addWidget(m_doubleSpinBoxScale);
ui->toolBarScale->addWidget(m_doubleSpinBoxScale);
// define the mouse position
ui->toolBarZoom->addSeparator();
ui->toolBarScale->addSeparator();
m_mouseCoordinate = new QLabel(QString("0, 0 (%1)").arg(UnitsToStr(m_layout->GetUnit(), true)));
ui->toolBarZoom->addWidget(m_mouseCoordinate);
ui->toolBarZoom->addSeparator();
m_mouseCoordinate = new QLabel(QStringLiteral("0, 0 (%1)").arg(UnitsToStr(m_layout->GetUnit(), true)));
ui->toolBarScale->addWidget(m_mouseCoordinate);
ui->toolBarScale->addSeparator();
}
//---------------------------------------------------------------------------------------------------------------------
@ -670,11 +817,75 @@ void VPMainWindow::SetCheckBoxValue(QCheckBox *checkbox, bool value)
checkbox->blockSignals(false);
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::UpdateWindowTitle()
{
QString showName;
bool isFileWritable = true;
if (not curFile.isEmpty())
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
isFileWritable = QFileInfo(curFile).isWritable();
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
showName = StrippedName(curFile);
}
else
{
int index = VPApplication::VApp()->MainWindows().indexOf(this);
if (index != -1)
{
showName = tr("untitled %1.vlt").arg(index+1);
}
else
{
showName = tr("untitled.vlt");
}
}
showName += QLatin1String("[*]");
if (lIsReadOnly || not isFileWritable)
{
showName += QStringLiteral(" (") + tr("read only") + QChar(')');
}
setWindowTitle(showName);
setWindowFilePath(curFile);
#if defined(Q_OS_MAC)
static QIcon fileIcon = QIcon(QCoreApplication::applicationDirPath() +
QLatin1String("/../Resources/layout.icns"));
QIcon icon;
if (not curFile.isEmpty())
{
if (not isWindowModified())
{
icon = fileIcon;
}
else
{
static QIcon darkIcon;
if (darkIcon.isNull())
{
darkIcon = QIcon(darkenPixmap(fileIcon.pixmap(16, 16)));
}
icon = darkIcon;
}
}
setWindowIcon(icon);
#endif //defined(Q_OS_MAC)
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::ReadSettings()
{
qCDebug(pWindow, "Reading settings.");
const VPSettings *settings = qApp->PuzzleSettings();
const VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
if (settings->status() == QSettings::NoError)
{
@ -682,6 +893,9 @@ void VPMainWindow::ReadSettings()
restoreState(settings->GetWindowState());
restoreState(settings->GetToolbarsState(), APP_VERSION);
// Text under tool buton icon
ToolBarStyles();
ui->dockWidgetProperties->setVisible(settings->IsDockWidgetPropertiesActive());
ui->dockWidgetPropertiesContents->setVisible(settings->IsDockWidgetPropertiesContentsActive());
@ -700,7 +914,7 @@ void VPMainWindow::ReadSettings()
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::WriteSettings()
{
VPSettings *settings = qApp->PuzzleSettings();
VPSettings *settings = VPApplication::VApp()->PuzzleSettings();
settings->SetGeometry(saveGeometry());
settings->SetWindowState(saveState());
settings->SetToolbarsState(saveState(APP_VERSION));
@ -837,20 +1051,56 @@ void VPMainWindow::generateTiledPdf(QString fileName)
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::CreateWindowMenu(QMenu *menu)
{
SCASSERT(menu != nullptr)
QAction *action = menu->addAction(tr("&New Window"));
connect(action, &QAction::triggered, this, []()
{
VPApplication::VApp()->NewMainWindow()->activateWindow();
});
action->setMenuRole(QAction::NoRole);
menu->addSeparator();
const QList<VPMainWindow*> windows = VPApplication::VApp()->MainWindows();
for (int i = 0; i < windows.count(); ++i)
{
VPMainWindow *window = windows.at(i);
QString title = QStringLiteral("%1. %2").arg(i+1).arg(window->windowTitle());
const int index = title.lastIndexOf(QLatin1String("[*]"));
if (index != -1)
{
window->isWindowModified() ? title.replace(index, 3, QChar('*')) : title.replace(index, 3, QString());
}
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
QAction *action = menu->addAction(title, this, SLOT(ShowWindow()));
#else
QAction *action = menu->addAction(title, this, &VPMainWindow::ShowWindow);
#endif //QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
action->setData(i);
action->setCheckable(true);
action->setMenuRole(QAction::NoRole);
if (window->isActiveWindow())
{
action->setChecked(true);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionNew_triggered()
{
// just for test purpuses, to be removed:
QMessageBox msgBox;
msgBox.setText("TODO VPMainWindow::New");
int ret = msgBox.exec();
Q_UNUSED(ret);
// TODO
VPApplication::VApp()->NewMainWindow();
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::ShowToolTip(const QString &toolTip)
{
m_statusLabel->setText(toolTip);
}
//---------------------------------------------------------------------------------------------------------------------
@ -877,102 +1127,196 @@ void VPMainWindow::closeEvent(QCloseEvent *event)
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
WindowsLocale();
UpdateWindowTitle();
}
// remember to call base class implementation
QMainWindow::changeEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
QStringList VPMainWindow::RecentFileList() const
{
return VPApplication::VApp()->PuzzleSettings()->GetRecentFileList();
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionOpen_triggered()
{
qCDebug(pWindow, "Openning puzzle layout file.");
const QString filter(tr("Layout files") + QLatin1String(" (*.vlt)"));
//Use standard path to individual measurements
const QString pathTo = VPApplication::VApp()->PuzzleSettings()->GetPathManualLayouts();
//Get list last open files
QStringList recentFiles = qApp->PuzzleSettings()->GetRecentFileList();
QString dir;
if (recentFiles.isEmpty())
bool usedNotExistedDir = false;
QDir directory(pathTo);
if (not directory.exists())
{
dir = QDir::homePath();
}
else
{
//Absolute path to last open file
dir = QFileInfo(recentFiles.first()).absolutePath();
}
qCDebug(pWindow, "Run QFileDialog::getOpenFileName: dir = %s.", qUtf8Printable(dir));
const QString filePath = QFileDialog::getOpenFileName(this, tr("Open file"), dir, filter, nullptr);
if (filePath.isEmpty())
{
return;
usedNotExistedDir = directory.mkpath(QChar('.'));
}
const QString mPath = QFileDialog::getOpenFileName(this, tr("Open file"), pathTo, filter, nullptr,
VAbstractApplication::VApp()->NativeFileDialog());
// TODO : if m_layout == nullptr, open in current window
// otherwise open in new window
// TODO : if layout file has a lock, warning message
if(!LoadFile(filePath))
if (not mPath.isEmpty())
{
return;
VPApplication::VApp()->NewMainWindow()->LoadFile(mPath);
}
// Updates the list of recent files
recentFiles.removeAll(filePath);
recentFiles.prepend(filePath);
while (recentFiles.size() > MaxRecentFiles)
if (usedNotExistedDir)
{
recentFiles.removeLast();
QDir(pathTo).rmpath(QChar('.'));
}
qApp->PuzzleSettings()->SetRecentFileList(recentFiles);
// updates the properties with the loaded data
SetPropertiesData();
// TODO : update the Carrousel and the QGraphicView
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionSave_triggered()
bool VPMainWindow::on_actionSave_triggered()
{
// just for test purpuses, to be removed:
QMessageBox msgBox;
msgBox.setText("TODO VPMainWindow::Save");
int ret = msgBox.exec();
if (curFile.isEmpty() || lIsReadOnly)
{
return on_actionSaveAs_triggered();
}
Q_UNUSED(ret);
if (m_curFileFormatVersion < VLayoutConverter::LayoutMaxVer
&& not ContinueFormatRewrite(m_curFileFormatVersionStr, VLayoutConverter::LayoutMaxVerStr))
{
return false;
}
// TODO
if (not CheckFilePermissions(curFile, this))
{
return false;
}
QString error;
if (not SaveLayout(curFile, error))
{
QMessageBox messageBox;
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Could not save the file"));
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.setDetailedText(error);
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec();
return false;
}
m_curFileFormatVersion = VLayoutConverter::LayoutMaxVer;
m_curFileFormatVersionStr = VLayoutConverter::LayoutMaxVerStr;
return true;
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionSaveAs_triggered()
bool VPMainWindow::on_actionSaveAs_triggered()
{
// TODO / FIXME : See valentina how the save is done over there. we need to add the
// extension .vlt, check for empty file names etc.
QString filters = tr("Layout files") + QStringLiteral(" (*.vlt)");
QString suffix = QStringLiteral("vlt");
QString fName = tr("layout") + QChar('.') + suffix;
//Get list last open files
QStringList recentFiles = qApp->PuzzleSettings()->GetRecentFileList();
QString dir;
if (recentFiles.isEmpty())
if (curFile.isEmpty())
{
dir = QDir::homePath();
dir = VPApplication::VApp()->PuzzleSettings()->GetPathManualLayouts();
}
else
{
//Absolute path to last open file
dir = QFileInfo(recentFiles.first()).absolutePath();
dir = QFileInfo(curFile).absolutePath();
}
QString filters(tr("Layout files") + QLatin1String("(*.vlt)"));
QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"),
dir + QLatin1String("/") + tr("Layout") + QLatin1String(".vlt"),
filters, nullptr
#ifdef Q_OS_LINUX
, QFileDialog::DontUseNativeDialog
#endif
);
bool usedNotExistedDir = false;
QDir directory(dir);
if (not directory.exists())
{
usedNotExistedDir = directory.mkpath(QChar('.'));
}
SaveFile(fileName);
QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), dir + QChar('/') + fName, filters, nullptr,
VAbstractApplication::VApp()->NativeFileDialog());
auto RemoveTempDir = qScopeGuard([usedNotExistedDir, dir]()
{
if (usedNotExistedDir)
{
QDir(dir).rmpath(QChar('.'));
}
});
if (fileName.isEmpty())
{
return false;
}
QFileInfo f( fileName );
if (f.suffix().isEmpty() && f.suffix() != suffix)
{
fileName += QChar('.') + suffix;
}
if (QFileInfo::exists(fileName) && curFile != fileName)
{
// Temporary try to lock the file before saving
VLockGuard<char> tmp(fileName);
if (not tmp.IsLocked())
{
qCCritical(pWindow, "%s",
qUtf8Printable(tr("Failed to lock. This file already opened in another window.")));
return false;
}
}
// Need for restoring previous state in case of failure
// const bool readOnly = m_layout->IsReadOnly();
// m_layout->SetReadOnly(false);
lIsReadOnly = false;
QString error;
bool result = SaveLayout(fileName, error);
if (not result)
{
QMessageBox messageBox;
messageBox.setIcon(QMessageBox::Warning);
messageBox.setInformativeText(tr("Could not save file"));
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.setDetailedText(error);
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec();
// Restore previous state
// m_layout->SetReadOnly(readOnly);
// lIsReadOnly = readOnly;
return false;
}
m_curFileFormatVersion = VLayoutConverter::LayoutMaxVer;
m_curFileFormatVersionStr = VLayoutConverter::LayoutMaxVerStr;
// UpdatePadlock(false);
UpdateWindowTitle();
if (curFile == fileName && not lock.isNull())
{
lock->Unlock();
}
VlpCreateLock(lock, fileName);
if (not lock->IsLocked())
{
qCCritical(pWindow, "%s", qUtf8Printable(tr("Failed to lock. This file already opened in another window. "
"Expect collissions when run 2 copies of the program.")));
return false;
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
@ -1004,19 +1348,6 @@ void VPMainWindow::on_actionImportRawLayout_triggered()
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionCloseLayout_triggered()
{
// just for test purpuses, to be removed:
QMessageBox msgBox;
msgBox.setText("TODO VPMainWindow::CloseLayout");
int ret = msgBox.exec();
Q_UNUSED(ret);
// TODO
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionAboutQt_triggered()
{
@ -1509,3 +1840,64 @@ void VPMainWindow::on_MouseMoved(const QPointF &scenePos)
.arg(UnitsToStr(m_layout->GetUnit(), true)));
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::ShowWindow() const
{
if (auto *action = qobject_cast<QAction*>(sender()))
{
const QVariant v = action->data();
if (v.canConvert<int>())
{
const int offset = qvariant_cast<int>(v);
const QList<VPMainWindow*> windows = VPApplication::VApp()->MainWindows();
windows.at(offset)->raise();
windows.at(offset)->activateWindow();
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::on_actionPreferences_triggered()
{
// Calling constructor of the dialog take some time. Because of this user have time to call the dialog twice.
static QPointer<DialogPuzzlePreferences> guard;// Prevent any second run
if (guard.isNull())
{
QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
auto *preferences = new DialogPuzzlePreferences(this);
// QScopedPointer needs to be sure any exception will never block guard
QScopedPointer<DialogPuzzlePreferences> dlg(preferences);
guard = preferences;
// Must be first
connect(dlg.data(), &DialogPuzzlePreferences::UpdateProperties, this, &VPMainWindow::WindowsLocale);
connect(dlg.data(), &DialogPuzzlePreferences::UpdateProperties, this, &VPMainWindow::ToolBarStyles);
QGuiApplication::restoreOverrideCursor();
dlg->exec();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPMainWindow::ToolBarStyles()
{
ToolBarStyle(ui->mainToolBar);
ToolBarStyle(ui->toolBarZoom);
}
//---------------------------------------------------------------------------------------------------------------------
#if defined(Q_OS_MAC)
void VPMainWindow::AboutToShowDockMenu()
{
if (QMenu *menu = qobject_cast<QMenu *>(sender()))
{
menu->clear();
CreateWindowMenu(menu);
menu->addSeparator();
QAction *actionPreferences = menu->addAction(tr("Preferences"));
actionPreferences->setMenuRole(QAction::NoRole);
connect(actionPreferences, &QAction::triggered, this, &VPMainWindow::Preferences);
}
}
#endif //defined(Q_OS_MAC)

View File

@ -43,13 +43,15 @@
#include "vpexporter.h"
#include "vpcommandline.h"
#include "../vlayout/vlayoutdef.h"
#include "../vwidgets/vabstractmainwindow.h"
#include "../vmisc/vlockguard.h"
namespace Ui
{
class VPMainWindow;
}
class VPMainWindow : public QMainWindow
class VPMainWindow : public VAbstractMainWindow
{
Q_OBJECT
@ -57,6 +59,8 @@ public:
explicit VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent = nullptr);
virtual ~VPMainWindow();
QString CurrentFile() const;
/**
* @brief LoadFile Loads the layout file of given path in m_layout.
* This function doesn't update the gui.
@ -65,12 +69,15 @@ public:
*/
bool LoadFile(QString path);
void LayoutWasSaved(bool saved);
void SetCurrentFile(const QString &fileName);
/**
* @brief SaveFile Saves the current layout to the layout file of given path
* @brief SaveLayout Saves the current layout to the layout file of given path
* @param path path to layout file
* @return true if success
*/
bool SaveFile(const QString &path);
bool SaveLayout(const QString &path, QString &error);
/**
* @brief ImportRawLayouts The function imports the raw layouts of given paths
@ -83,6 +90,8 @@ public:
*/
void InitZoom();
void UpdateWindowTitle();
public slots:
/**
* @brief on_actionNew_triggered When the menu action File > New
@ -90,146 +99,14 @@ public slots:
*/
void on_actionNew_triggered();
virtual void ShowToolTip(const QString &toolTip) override;
protected:
enum { MaxRecentFiles = 5 };
virtual void closeEvent(QCloseEvent *event) override;
virtual void changeEvent(QEvent* event) override;
virtual QStringList RecentFileList() const override;
private:
Q_DISABLE_COPY(VPMainWindow)
Ui::VPMainWindow *ui;
VPCarrousel *m_carrousel{nullptr};
VPMainGraphicsView *m_graphicsView{nullptr};
VPCommandLinePtr m_cmd;
VPLayout *m_layout{nullptr};
QList<VPPiece *>m_selectedPieces{QList<VPPiece *>()};
VPTileFactory *m_tileFactory{nullptr};
VPExporter *m_exporter{nullptr};
/**
* @brief spin box with the scale factor of the graphic view
*/
QPointer<QDoubleSpinBox> m_doubleSpinBoxScale{nullptr};
/**
* @brief mouseCoordinate pointer to label who show mouse coordinate.
*/
QLabel* m_mouseCoordinate{nullptr};
/**
* @brief CreatePiece creates a piece from the given VLayoutPiece data
* @param rawPiece the raw piece data
*/
VPPiece* CreatePiece(const VLayoutPiece &rawPiece);
/**
* @brief InitMenuBar Inits the menu bar (File, Edit, Help ...)
*/
void InitMenuBar();
/**
* @brief InitProperties Init the properties
*/
void InitProperties();
/**
* @brief InitPropertyTabCurrentPiece Inits the current piece tab in the properties
*/
void InitPropertyTabCurrentPiece();
/**
* @brief InitPropertyTabCurrentSheet Inits the current sheet tab in the properties;
*/
void InitPropertyTabCurrentSheet();
/**
* @brief InitPropertyTabLayout Inits the layout tab in the properties
*/
void InitPropertyTabLayout();
/**
* @brief InitPropertyTabTiles Inits the tiles tab in the properties
*/
void InitPropertyTabTiles();
/**
* @brief InitCarrousel Inits the carrousel
*/
void InitCarrousel();
/**
* @brief InitMainGraphics Initialises the puzzle main graphics
*/
void InitMainGraphics();
/**
* @brief InitToolBar Initialises the tool bar
*/
void InitZoomToolBar();
/**
* @brief SetPropertiesData Sets the values of UI elements
* in all the property tabs to the values saved in m_layout
*/
void SetPropertiesData();
/**
* @brief SetPropertyTabCurrentPieceData Sets the values of UI elements
* in the Current Piece Tab to the values saved in m_layout
*/
void SetPropertyTabCurrentPieceData();
/**
* @brief SetPropertyTabSheetData Sets the values of UI elements
* in the Sheet Tab to the values saved in focused sheet
*/
void SetPropertyTabSheetData();
/**
* @brief SetPropertyTabTilesData Sets the values of UI elements
* in the Tiles Tab to the values saved in m_layout
*/
void SetPropertyTabTilesData();
/**
* @brief SetPropertyTabLayoutData Sets the values of UI elements
* in the Layout Tab to the values saved in m_layout
*/
void SetPropertyTabLayoutData();
/**
* @brief SetDoubleSpinBoxValue sets the given spinbox to the given value.
* the signals are blocked before changing the value and unblocked after
* @param spinBox pointer to spinbox
* @param value spinbox value
*/
void SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value);
/**
* @brief SetCheckBoxValue sets the given checkbox to the given value.
* the signals are blocked before changing the value and unblocked after
* @param checkbox pointer to checkbox
* @param value checkbox value
*/
void SetCheckBoxValue(QCheckBox *checkbox, bool value);
void ReadSettings();
void WriteSettings();
bool MaybeSave();
/**
* @brief generateTiledPdf Generates the tiled Pdf in the given filename
* @param fileName output file name
*/
void generateTiledPdf(QString fileName);
private slots:
private slots:
/**
* @brief on_actionOpen_triggered When the menu action File > Open is
* triggered.
@ -242,14 +119,14 @@ private slots:
* triggered.
* The slot is automatically connected through name convention.
*/
void on_actionSave_triggered();
bool on_actionSave_triggered();
/**
* @brief on_actionSaveAs_triggered When the menu action File > Save As
* is triggered.
* The slot is automatically connected through name convention.
*/
void on_actionSaveAs_triggered();
bool on_actionSaveAs_triggered();
/**
* @brief on_actionImportRawLayout_triggered When the menu action
@ -258,13 +135,6 @@ private slots:
*/
void on_actionImportRawLayout_triggered();
/**
* @brief on_actionCloseLayout_triggered When the menu action
* File > Close Layout is triggered.
* The slot is automatically connected through name convention.
*/
void on_actionCloseLayout_triggered();
/**
* @brief on_actionAboutQt_triggered When the menu action Help > About Qt
* is triggered.
@ -523,6 +393,165 @@ private slots:
* @param scenePos position mouse.
*/
void on_MouseMoved(const QPointF &scenePos);
void on_actionPreferences_triggered();
void ShowWindow() const;
void ToolBarStyles();
#if defined(Q_OS_MAC)
void AboutToShowDockMenu();
#endif //defined(Q_OS_MAC)
private:
Q_DISABLE_COPY(VPMainWindow)
Ui::VPMainWindow *ui;
VPCarrousel *m_carrousel{nullptr};
VPMainGraphicsView *m_graphicsView{nullptr};
VPCommandLinePtr m_cmd;
VPLayout *m_layout{new VPLayout()};
QList<VPPiece *>m_selectedPieces{QList<VPPiece *>()};
VPTileFactory *m_tileFactory{nullptr};
VPExporter *m_exporter{nullptr};
/**
* @brief spin box with the scale factor of the graphic view
*/
QPointer<QDoubleSpinBox> m_doubleSpinBoxScale{nullptr};
/**
* @brief mouseCoordinate pointer to label who show mouse coordinate.
*/
QLabel* m_mouseCoordinate{nullptr};
QLabel* m_statusLabel{nullptr};
QString curFile{};
bool isInitialized{false};
bool lIsReadOnly{false};
QSharedPointer<VLockGuard<char>> lock{nullptr};
/**
* @brief CreatePiece creates a piece from the given VLayoutPiece data
* @param rawPiece the raw piece data
*/
VPPiece* CreatePiece(const VLayoutPiece &rawPiece);
/**
* @brief InitMenuBar Inits the menu bar (File, Edit, Help ...)
*/
void SetupMenu();
/**
* @brief InitProperties Init the properties
*/
void InitProperties();
/**
* @brief InitPropertyTabCurrentPiece Inits the current piece tab in the properties
*/
void InitPropertyTabCurrentPiece();
/**
* @brief InitPropertyTabCurrentSheet Inits the current sheet tab in the properties;
*/
void InitPropertyTabCurrentSheet();
/**
* @brief InitPropertyTabLayout Inits the layout tab in the properties
*/
void InitPropertyTabLayout();
/**
* @brief InitPropertyTabTiles Inits the tiles tab in the properties
*/
void InitPropertyTabTiles();
/**
* @brief InitCarrousel Inits the carrousel
*/
void InitCarrousel();
/**
* @brief InitMainGraphics Initialises the puzzle main graphics
*/
void InitMainGraphics();
/**
* @brief InitToolBar Initialises the tool bar
*/
void InitZoomToolBar();
/**
* @brief InitScaleToolBar Initialises the scale tool bar
*/
void InitScaleToolBar();
/**
* @brief SetPropertiesData Sets the values of UI elements
* in all the property tabs to the values saved in m_layout
*/
void SetPropertiesData();
/**
* @brief SetPropertyTabCurrentPieceData Sets the values of UI elements
* in the Current Piece Tab to the values saved in m_layout
*/
void SetPropertyTabCurrentPieceData();
/**
* @brief SetPropertyTabSheetData Sets the values of UI elements
* in the Sheet Tab to the values saved in focused sheet
*/
void SetPropertyTabSheetData();
/**
* @brief SetPropertyTabTilesData Sets the values of UI elements
* in the Tiles Tab to the values saved in m_layout
*/
void SetPropertyTabTilesData();
/**
* @brief SetPropertyTabLayoutData Sets the values of UI elements
* in the Layout Tab to the values saved in m_layout
*/
void SetPropertyTabLayoutData();
/**
* @brief SetDoubleSpinBoxValue sets the given spinbox to the given value.
* the signals are blocked before changing the value and unblocked after
* @param spinBox pointer to spinbox
* @param value spinbox value
*/
void SetDoubleSpinBoxValue(QDoubleSpinBox *spinBox, qreal value);
/**
* @brief SetCheckBoxValue sets the given checkbox to the given value.
* the signals are blocked before changing the value and unblocked after
* @param checkbox pointer to checkbox
* @param value checkbox value
*/
void SetCheckBoxValue(QCheckBox *checkbox, bool value);
void ReadSettings();
void WriteSettings();
bool MaybeSave();
/**
* @brief generateTiledPdf Generates the tiled Pdf in the given filename
* @param fileName output file name
*/
void generateTiledPdf(QString fileName);
void CreateWindowMenu(QMenu *menu);
};
#endif // VPMAINWINDOW_H

View File

@ -14,7 +14,7 @@
<string>Puzzle</string>
</property>
<property name="windowIcon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/logo.png</normaloff>:/puzzleicon/64x64/logo.png</iconset>
</property>
<property name="layoutDirection">
@ -53,6 +53,8 @@
<addaction name="separator"/>
<addaction name="actionImportRawLayout"/>
<addaction name="separator"/>
<addaction name="actionPreferences"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuEdit">
@ -61,11 +63,10 @@
</property>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuWindows">
<widget class="QMenu" name="menuWindow">
<property name="title">
<string>&amp;Windows</string>
<string>&amp;Window</string>
</property>
<addaction name="actionCloseLayout"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuHelp">
@ -77,18 +78,29 @@
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuWindows"/>
<addaction name="menuWindow"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<property name="enabled">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>Menu</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QDockWidget" name="dockWidgetCarrousel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -163,6 +175,9 @@
</property>
<item>
<widget class="QTabWidget" name="tabWidgetProperties">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
@ -192,7 +207,7 @@
<string notr="true"/>
</property>
<attribute name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconCurrentPiece.png</normaloff>:/puzzleicon/64x64/iconCurrentPiece.png</iconset>
</attribute>
<attribute name="title">
@ -216,6 +231,9 @@
</property>
<item>
<widget class="QScrollArea" name="scrollAreaCurrentPiece">
<property name="enabled">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
@ -390,7 +408,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconRotate90Clockwise.png</normaloff>:/puzzleicon/64x64/iconRotate90Clockwise.png</iconset>
</property>
<property name="iconSize">
@ -410,7 +428,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconRotate90Anticlockwise.png</normaloff>:/puzzleicon/64x64/iconRotate90Anticlockwise.png</iconset>
</property>
<property name="iconSize">
@ -430,7 +448,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconRotateGrainlineVertical.png</normaloff>:/puzzleicon/64x64/iconRotateGrainlineVertical.png</iconset>
</property>
<property name="iconSize">
@ -450,7 +468,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconRotateGrainlineHorizontal.png</normaloff>:/puzzleicon/64x64/iconRotateGrainlineHorizontal.png</iconset>
</property>
<property name="iconSize">
@ -610,7 +628,7 @@
</widget>
<widget class="QWidget" name="tabSheetProperty">
<attribute name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconLayout.png</normaloff>:/puzzleicon/64x64/iconLayout.png</iconset>
</attribute>
<attribute name="title">
@ -762,7 +780,7 @@
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconPortrait.png</normaloff>:/puzzleicon/64x64/iconPortrait.png</iconset>
</property>
<property name="iconSize">
@ -785,7 +803,7 @@
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconLandscape.png</normaloff>:/puzzleicon/64x64/iconLandscape.png</iconset>
</property>
<property name="iconSize">
@ -977,7 +995,7 @@
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconGrainlineVertical.png</normaloff>:/puzzleicon/64x64/iconGrainlineVertical.png</iconset>
</property>
<property name="iconSize">
@ -997,7 +1015,7 @@
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconGrainlineHorizontal.png</normaloff>:/puzzleicon/64x64/iconGrainlineHorizontal.png</iconset>
</property>
<property name="iconSize">
@ -1083,7 +1101,7 @@
</widget>
<widget class="QWidget" name="tabTilesProperty">
<attribute name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconTiles.png</normaloff>:/puzzleicon/64x64/iconTiles.png</iconset>
</attribute>
<attribute name="title">
@ -1125,7 +1143,7 @@
<x>0</x>
<y>0</y>
<width>356</width>
<height>717</height>
<height>700</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
@ -1193,7 +1211,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconPortrait.png</normaloff>:/puzzleicon/64x64/iconPortrait.png</iconset>
</property>
<property name="iconSize">
@ -1213,7 +1231,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconLandscape.png</normaloff>:/puzzleicon/64x64/iconLandscape.png</iconset>
</property>
<property name="iconSize">
@ -1371,7 +1389,7 @@
</widget>
<widget class="QWidget" name="tabLayoutProperty">
<attribute name="icon">
<iconset resource="share/resources/puzzleicon.qrc">
<iconset>
<normaloff>:/puzzleicon/64x64/iconProperties.png</normaloff>:/puzzleicon/64x64/iconProperties.png</iconset>
</attribute>
<attribute name="title">
@ -1413,7 +1431,7 @@
<x>0</x>
<y>0</y>
<width>356</width>
<height>717</height>
<height>700</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
@ -1539,7 +1557,7 @@
</widget>
<widget class="QToolBar" name="toolBarZoom">
<property name="windowTitle">
<string>toolBar</string>
<string>zoom</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
@ -1555,7 +1573,26 @@
<addaction name="actionZoomOriginal"/>
<addaction name="actionZoomFitBest"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QToolBar" name="toolBarScale">
<property name="windowTitle">
<string>Scale</string>
</property>
<property name="allowedAreas">
<set>Qt::AllToolBarAreas</set>
</property>
<attribute name="toolBarArea">
<enum>BottomToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<action name="actionOpen">
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Open</string>
</property>
@ -1564,6 +1601,13 @@
</property>
</action>
<action name="actionSave">
<property name="enabled">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Save</string>
</property>
@ -1572,6 +1616,13 @@
</property>
</action>
<action name="actionSaveAs">
<property name="enabled">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="document-save-as">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Save &amp;As</string>
</property>
@ -1579,12 +1630,10 @@
<string>Ctrl+Shift+S</string>
</property>
</action>
<action name="actionCloseLayout">
<property name="text">
<string>&amp;Close Layout</string>
</property>
</action>
<action name="actionImportRawLayout">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Import Raw Layout Data</string>
</property>
@ -1603,8 +1652,15 @@
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
<property name="menuRole">
<enum>QAction::QuitRole</enum>
</property>
</action>
<action name="actionNew">
<property name="icon">
<iconset theme="document-new">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;New</string>
</property>
@ -1616,11 +1672,21 @@
<property name="text">
<string>About &amp;Qt</string>
</property>
<property name="menuRole">
<enum>QAction::AboutQtRole</enum>
</property>
</action>
<action name="actionAboutPuzzle">
<property name="icon">
<iconset theme="help-about">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>About &amp;Puzzle</string>
</property>
<property name="menuRole">
<enum>QAction::AboutRole</enum>
</property>
</action>
<action name="actionProperties">
<property name="checkable">
@ -1629,11 +1695,20 @@
<property name="checked">
<bool>true</bool>
</property>
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Properties</string>
</property>
<property name="menuRole">
<enum>QAction::PreferencesRole</enum>
</property>
</action>
<action name="actionZoomIn">
<property name="enabled">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-in">
<normaloff>.</normaloff>.</iconset>
@ -1643,6 +1718,9 @@
</property>
</action>
<action name="actionZoomOut">
<property name="enabled">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-out">
<normaloff>.</normaloff>.</iconset>
@ -1652,6 +1730,9 @@
</property>
</action>
<action name="actionZoomOriginal">
<property name="enabled">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-original">
<normaloff>.</normaloff>.</iconset>
@ -1661,6 +1742,9 @@
</property>
</action>
<action name="actionZoomFitBest">
<property name="enabled">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="zoom-fit-best">
<normaloff>.</normaloff>.</iconset>
@ -1672,6 +1756,11 @@
<string>Zoom sheet</string>
</property>
</action>
<action name="actionPreferences">
<property name="text">
<string>Preferences</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
@ -1721,9 +1810,6 @@
<tabstop>checkBoxLayoutWarningPiecesSuperposition</tabstop>
<tabstop>checkBoxLayoutWarningPiecesOutOfBound</tabstop>
</tabstops>
<resources>
<include location="share/resources/puzzleicon.qrc"/>
<include location="share/resources/puzzleicon.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View File

@ -70,8 +70,6 @@ class VPSheet : public QObject
{
Q_OBJECT
public:
explicit VPSheet(VPLayout* layout);
~VPSheet();

View File

@ -33,19 +33,6 @@
#include "../ifc/exception/vexception.h"
#include "../ifc/exception/vexceptionconversionerror.h"
//---------------------------------------------------------------------------------------------------------------------
VPLayoutFileReader::VPLayoutFileReader()
{
}
//---------------------------------------------------------------------------------------------------------------------
VPLayoutFileReader::~VPLayoutFileReader()
{
// TODO
}
//---------------------------------------------------------------------------------------------------------------------
bool VPLayoutFileReader::ReadFile(VPLayout *layout, QFile *file)
{
@ -56,7 +43,7 @@ bool VPLayoutFileReader::ReadFile(VPLayout *layout, QFile *file)
ReadLayout(layout);
}
return !error();
return hasError();
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -39,8 +39,8 @@ class VPLayoutFileReader : public QXmlStreamReader
{
Q_DECLARE_TR_FUNCTIONS(VPLayoutFileReader)
public:
VPLayoutFileReader();
~VPLayoutFileReader();
VPLayoutFileReader()=default;
~VPLayoutFileReader()=default;
bool ReadFile(VPLayout *layout, QFile *file);
@ -64,7 +64,7 @@ private:
static QString ReadAttributeEmptyString(const QXmlStreamAttributes &attribs, const QString &name);
static bool ReadAttributeBool(const QXmlStreamAttributes &attribs, const QString &name, const QString &defValue);
static qreal ReadAttributeDouble(const QXmlStreamAttributes &attribs, const QString &name,
const QString &defValue);
const QString &defValue);
};
#endif // VPLAYOUTFILEREADER_H

View File

@ -34,18 +34,6 @@
#include "vplayoutliterals.h"
#include "../ifc/xml/vlayoutconverter.h"
//---------------------------------------------------------------------------------------------------------------------
VPLayoutFileWriter::VPLayoutFileWriter()
{
}
//---------------------------------------------------------------------------------------------------------------------
VPLayoutFileWriter::~VPLayoutFileWriter()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VPLayoutFileWriter::WriteFile(VPLayout *layout, QFile *file)
{

View File

@ -31,6 +31,7 @@
#include <QLocale>
#include <QXmlStreamWriter>
#include <QCoreApplication>
#include "../vmisc/literals.h"
@ -43,14 +44,14 @@ class QMarginsF;
class VPLayoutFileWriter : public QXmlStreamWriter
{
Q_DECLARE_TR_FUNCTIONS(VPLayoutFileWriter)
public:
VPLayoutFileWriter();
~VPLayoutFileWriter();
VPLayoutFileWriter()= default;
~VPLayoutFileWriter()= default;
void WriteFile(VPLayout *layout, QFile *file);
private:
void WriteLayout(VPLayout *layout);
void WriteProperties(VPLayout *layout);
void WriteUnplacePiecesList(VPLayout *layout);
@ -69,7 +70,6 @@ private:
template <size_t N>
void SetAttribute(const QString &name, const char (&value)[N]);
};
//---------------------------------------------------------------------------------------------------------------------

View File

@ -70,6 +70,7 @@ void TapePreferencesPathPage::Apply()
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());
}
//---------------------------------------------------------------------------------------------------------------------
@ -107,6 +108,9 @@ void TapePreferencesPathPage::DefaultPath()
case 3: // templates
path = VCommonSettings::GetDefPathTemplate();
break;
case 4: // layouts
path = VCommonSettings::GetDefPathManualLayouts();
break;
default:
break;
}
@ -138,6 +142,9 @@ void TapePreferencesPathPage::EditPath()
case 3: // templates
path = MApplication::VApp()->TapeSettings()->GetPathTemplate();
break;
case 4: // layouts
path = MApplication::VApp()->TapeSettings()->GetPathManualLayouts();
break;
default:
break;
}
@ -171,7 +178,7 @@ void TapePreferencesPathPage::EditPath()
void TapePreferencesPathPage::InitTable()
{
ui->pathTable->clearContents();
ui->pathTable->setRowCount(4);
ui->pathTable->setRowCount(5);
ui->pathTable->setColumnCount(2);
const VTapeSettings *settings = MApplication::VApp()->TapeSettings();
@ -204,6 +211,13 @@ void TapePreferencesPathPage::InitTable()
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();

View File

@ -89,7 +89,7 @@ void DialogTapePreferences::showEvent(QShowEvent *event)
// do your init stuff here
QSize sz = VAbstractApplication::VApp()->Settings()->GetPreferenceDialogSize();
if (sz.isEmpty() == false)
if (not sz.isEmpty())
{
resize(sz);
}

View File

@ -374,7 +374,7 @@ bool MApplication::IsTestMode() const
*/
bool MApplication::IsAppInGUIMode() const
{
return IsTestMode();
return not IsTestMode();
}
//---------------------------------------------------------------------------------------------------------------------
@ -854,6 +854,7 @@ TMainWindow *MApplication::NewMainWindow()
if (not MApplication::VApp()->IsTestMode())
{
tape->show();
tape->UpdateWindowTitle();
}
return tape;
}

View File

@ -35,7 +35,6 @@
#include "../vmisc/vabstractapplication.h"
#include "dialogs/dialogmdatabase.h"
class MApplication;// use in define
class TMainWindow;
class QLocalServer;

View File

@ -133,7 +133,7 @@ TMainWindow::TMainWindow(QWidget *parent)
connect(gradation, &QTimer::timeout, this, &TMainWindow::GradationChanged);
SetupMenu();
UpdateWindowTitle();
ReadSettings();
#if defined(Q_OS_MAC)
@ -278,21 +278,20 @@ bool TMainWindow::LoadFile(const QString &path)
// Check if file already opened
const QList<TMainWindow*> list = MApplication::VApp()->MainWindows();
for (auto w : list)
auto w = std::find_if(list.begin(), list.end(),
[path](TMainWindow *window) { return window->CurrentFile() == path; });
if (w != list.end())
{
if (w->CurrentFile() == path)
{
w->activateWindow();
close();
return false;
}
(*w)->activateWindow();
close();
return false;
}
VlpCreateLock(lock, path);
if (not lock->IsLocked())
{
if (not IgnoreLocking(lock->GetLockError(), path))
if (not IgnoreLocking(lock->GetLockError(), path, MApplication::VApp()->IsAppInGUIMode()))
{
return false;
}
@ -388,13 +387,6 @@ bool TMainWindow::LoadFile(const QString &path)
return true;
}
//---------------------------------------------------------------------------------------------------------------------
void TMainWindow::ShowToolTip(const QString &toolTip)
{
Q_UNUSED(toolTip)
// do nothing
}
//---------------------------------------------------------------------------------------------------------------------
void TMainWindow::FileNew()
{
@ -597,11 +589,13 @@ void TMainWindow::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
VAbstractApplication::VApp()->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
WindowsLocale();
// retranslate designer form (single inheritance approach)
ui->retranslateUi(this);
UpdateWindowTitle();
InitMeasurementUnits();
if (mType == MeasurementsType::Multisize)
@ -782,48 +776,9 @@ bool TMainWindow::FileSave()
return false;
}
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
const bool isFileWritable = QFileInfo(curFile).isWritable();
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not isFileWritable)
if (not CheckFilePermissions(curFile, this))
{
QMessageBox messageBox(this);
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(tr("The measurements document has no write permissions."));
messageBox.setInformativeText(tr("Do you want to change the premissions?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
messageBox.setDefaultButton(QMessageBox::Yes);
if (messageBox.exec() == QMessageBox::Yes)
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
bool changed = QFile::setPermissions(curFile,
QFileInfo(curFile).permissions() | QFileDevice::WriteUser);
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not changed)
{
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Cannot set permissions for %1 to writable.").arg(curFile));
messageBox.setInformativeText(tr("Could not save the file."));
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.exec();
return false;
}
}
else
{
return false;
}
return false;
}
QString error;
@ -2410,7 +2365,6 @@ void TMainWindow::SetupMenu()
m_separatorAct->setVisible(false);
ui->menuFile->insertAction(ui->actionPreferences, m_separatorAct );
connect(ui->actionQuit, &QAction::triggered, this, &TMainWindow::close);
ui->actionQuit->setShortcuts(QKeySequence::Quit);
@ -3289,7 +3243,15 @@ void TMainWindow::UpdateWindowTitle()
}
else
{
showName = tr("untitled %1").arg(MApplication::VApp()->MainWindows().size()+1);
int index = MApplication::VApp()->MainWindows().indexOf(this);
if (index != -1)
{
showName = tr("untitled %1").arg(index+1);
}
else
{
showName = tr("untitled");
}
mType == MeasurementsType::Multisize ? showName += QLatin1String(".vst") : showName += QLatin1String(".vit");
}
@ -3525,21 +3487,20 @@ bool TMainWindow::LoadFromExistingFile(const QString &path)
// Check if file already opened
const QList<TMainWindow*> list = MApplication::VApp()->MainWindows();
for (auto w : list)
auto w = std::find_if(list.begin(), list.end(),
[path](TMainWindow *window) { return window->CurrentFile() == path; });
if (w != list.end())
{
if (w->CurrentFile() == path)
{
w->activateWindow();
close();
return false;
}
(*w)->activateWindow();
close();
return false;
}
VlpCreateLock(lock, path);
if (not lock->IsLocked())
{
if (not IgnoreLocking(lock->GetLockError(), path))
if (not IgnoreLocking(lock->GetLockError(), path, MApplication::VApp()->IsAppInGUIMode()))
{
return false;
}
@ -3653,7 +3614,11 @@ void TMainWindow::CreateWindowMenu(QMenu *menu)
window->isWindowModified() ? title.replace(index, 3, QChar('*')) : title.replace(index, 3, QString());
}
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
QAction *action = menu->addAction(title, this, SLOT(ShowWindow()));
#else
QAction *action = menu->addAction(title, this, &TMainWindow::ShowWindow);
#endif //QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
action->setData(i);
action->setCheckable(true);
action->setMenuRole(QAction::NoRole);
@ -3664,72 +3629,6 @@ void TMainWindow::CreateWindowMenu(QMenu *menu)
}
}
//---------------------------------------------------------------------------------------------------------------------
bool TMainWindow::IgnoreLocking(int error, const QString &path)
{
QMessageBox::StandardButton answer = QMessageBox::Abort;
if (not MApplication::VApp()->IsTestMode())
{
switch(error)
{
case QLockFile::LockFailedError:
answer = QMessageBox::warning(this, tr("Locking file"),
tr("This file already opened in another window. Ignore if you want "
"to continue (not recommended, can cause a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
case QLockFile::PermissionError:
answer = QMessageBox::question(this, tr("Locking file"),
tr("The lock file could not be created, for lack of permissions. "
"Ignore if you want to continue (not recommended, can cause "
"a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
case QLockFile::UnknownError:
answer = QMessageBox::question(this, tr("Locking file"),
tr("Unknown error happened, for instance a full partition "
"prevented writing out the lock file. Ignore if you want to "
"continue (not recommended, can cause a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
default:
answer = QMessageBox::Abort;
break;
}
}
if (answer == QMessageBox::Abort)
{
qCDebug(tMainWindow, "Failed to lock %s", qUtf8Printable(path));
qCDebug(tMainWindow, "Error type: %d", error);
if (MApplication::VApp()->IsTestMode())
{
switch(error)
{
case QLockFile::LockFailedError:
qCCritical(tMainWindow, "%s",
qUtf8Printable(tr("This file already opened in another window.")));
break;
case QLockFile::PermissionError:
qCCritical(tMainWindow, "%s",
qUtf8Printable(tr("The lock file could not be created, for lack of permissions.")));
break;
case QLockFile::UnknownError:
qCCritical(tMainWindow, "%s",
qUtf8Printable(tr("Unknown error happened, for instance a full partition "
"prevented writing out the lock file.")));
break;
default:
break;
}
qApp->exit(V_EX_NOINPUT);
}
return false;
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
void TMainWindow::HackDimensionBaseValue()
{

View File

@ -65,8 +65,7 @@ public:
bool LoadFile(const QString &path);
public slots:
virtual void ShowToolTip(const QString &toolTip) override;
void UpdateWindowTitle();
protected:
virtual void closeEvent(QCloseEvent *event) override;
@ -218,7 +217,6 @@ private:
void MeasurementGUI();
void Controls();
void MFields(bool enabled);
void UpdateWindowTitle();
void ReadSettings();
void WriteSettings();
@ -231,8 +229,6 @@ private:
void CreateWindowMenu(QMenu *menu);
bool IgnoreLocking(int error, const QString &path);
template <class T>
void HackWidget(T **widget);
void HackDimensionBaseValue();

View File

@ -3253,52 +3253,9 @@ bool MainWindow::on_actionSave_triggered()
return false;
}
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
const bool isFileWritable = QFileInfo(VAbstractValApplication::VApp()->GetPatternPath()).isWritable();
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not isFileWritable)
if (not CheckFilePermissions(VAbstractValApplication::VApp()->GetPatternPath(), this))
{
QMessageBox messageBox(this);
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(tr("The document has no write permissions."));
messageBox.setInformativeText(tr("Do you want to change the premissions?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
messageBox.setDefaultButton(QMessageBox::Yes);
if (messageBox.exec() == QMessageBox::Yes)
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
bool changed =
QFile::setPermissions(VAbstractValApplication::VApp()->GetPatternPath(),
QFileInfo(VAbstractValApplication::VApp()
->GetPatternPath()).permissions() | QFileDevice::WriteUser);
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not changed)
{
QMessageBox messageBox(this);
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Cannot set permissions for %1 to writable.")
.arg(VAbstractValApplication::VApp()->GetPatternPath()));
messageBox.setInformativeText(tr("Could not save the file."));
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.exec();
return false;
}
}
else
{
return false;
}
return false;
}
QString error;
@ -5325,7 +5282,7 @@ bool MainWindow::LoadPattern(QString fileName, const QString& customMeasureFile)
}
else
{
if (not IgnoreLocking(lock->GetLockError(), fileName))
if (not IgnoreLocking(lock->GetLockError(), fileName, VApplication::IsGUIMode()))
{
return false;
}
@ -6433,73 +6390,6 @@ void MainWindow::UpdateWindowTitle()
#endif //defined(Q_OS_MAC)
}
//---------------------------------------------------------------------------------------------------------------------
bool MainWindow::IgnoreLocking(int error, const QString &path)
{
QMessageBox::StandardButton answer = QMessageBox::Abort;
if (VApplication::IsGUIMode())
{
switch(error)
{
case QLockFile::LockFailedError:
answer = QMessageBox::warning(this, tr("Locking file"),
tr("This file already opened in another window. Ignore if you want "
"to continue (not recommended, can cause a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
case QLockFile::PermissionError:
answer = QMessageBox::question(this, tr("Locking file"),
tr("The lock file could not be created, for lack of permissions. "
"Ignore if you want to continue (not recommended, can cause "
"a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
case QLockFile::UnknownError:
answer = QMessageBox::question(this, tr("Locking file"),
tr("Unknown error happened, for instance a full partition prevented "
"writing out the lock file. Ignore if you want to continue (not "
"recommended, can cause a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
default:
answer = QMessageBox::Abort;
break;
}
}
if (answer == QMessageBox::Abort)
{
qCDebug(vMainWindow, "Failed to lock %s", qUtf8Printable(path));
qCDebug(vMainWindow, "Error type: %d", error);
Clear();
if (not VApplication::IsGUIMode())
{
switch(error)
{
case QLockFile::LockFailedError:
qCCritical(vMainWindow, "%s",
qUtf8Printable(tr("This file already opened in another window.")));
break;
case QLockFile::PermissionError:
qCCritical(vMainWindow, "%s",
qUtf8Printable(tr("The lock file could not be created, for lack of permissions.")));
break;
case QLockFile::UnknownError:
qCCritical(vMainWindow, "%s",
qUtf8Printable(tr("Unknown error happened, for instance a full partition prevented "
"writing out the lock file.")));
break;
default:
break;
}
qApp->exit(V_EX_NOINPUT);
}
return false;
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
void MainWindow::ToolSelectPoint()
{

View File

@ -392,8 +392,6 @@ private:
void UpdateWindowTitle();
bool IgnoreLocking(int error, const QString &path);
void ToolSelectPoint();
void ToolSelectPointByPress();
void ToolSelectPointByRelease();

View File

@ -149,66 +149,80 @@ unix{
tape.path = $$BINDIR
tape.files += $${OUT_PWD}/../tape/$${DESTDIR}/tape
puzzle.path = $$BINDIR
puzzle.files += $${OUT_PWD}/../puzzle/$${DESTDIR}/puzzle
# .desktop file
desktop.path = $$DATADIR/applications/
desktop.files += ../../../dist/$${TARGET}.desktop \
desktop.files += ../../../dist/tape.desktop
desktop.files += ../../../dist/tape.desktop \
desktop.files += ../../../dist/puzzle.desktop
# logo
hicolor_48_apps.path = $$DATADIR/icons/hicolor/48x48/apps/
hicolor_48_apps.files += \
../../../share/icons/48x48/apps/$${TARGET}.png \
../../../share/icons/48x48/apps/tape.png
../../../share/icons/48x48/apps/tape.png \
../../../share/icons/48x48/apps/puzzle.png
hicolor_48_mimetypes.path = $$DATADIR/icons/hicolor/48x48/mimetypes/
hicolor_48_mimetypes.files += \
../../../share/icons/48x48/mimetypes/application-x-valentina-pattern.png \
../../../share/icons/48x48/mimetypes/application-x-valentina-i-measurements.png \
../../../share/icons/48x48/mimetypes/application-x-valentina-s-measurements.png
../../../share/icons/48x48/mimetypes/application-x-valentina-s-measurements.png \
../../../share/icons/48x48/mimetypes/application-x-valentina-layout.png
hicolor_64_apps.path = $$DATADIR/icons/hicolor/64x64/apps/
hicolor_64_apps.files += \
../../../share/icons/64x64/apps/$${TARGET}.png \
../../../share/icons/64x64/apps/tape.png
../../../share/icons/64x64/apps/tape.png \
../../../share/icons/64x64/apps/puzzle.png
hicolor_64_mimetypes.path = $$DATADIR/icons/hicolor/64x64/mimetypes/
hicolor_64_mimetypes.files += \
../../../share/icons/64x64/mimetypes/application-x-valentina-pattern.png \
../../../share/icons/64x64/mimetypes/application-x-valentina-i-measurements.png \
../../../share/icons/64x64/mimetypes/application-x-valentina-s-measurements.png
../../../share/icons/64x64/mimetypes/application-x-valentina-s-measurements.png \
../../../share/icons/64x64/mimetypes/application-x-valentina-layout.png
hicolor_128_apps.path = $$DATADIR/icons/hicolor/128x128/apps/
hicolor_128_apps.files += \
../../../share/icons/128x128/apps/$${TARGET}.png \
../../../share/icons/128x128/apps/tape.png
../../../share/icons/128x128/apps/tape.png \
../../../share/icons/128x128/apps/puzzle.png
hicolor_128_mimetypes.path = $$DATADIR/icons/hicolor/128x128/mimetypes/
hicolor_128_mimetypes.files += \
../../../share/icons/128x128/mimetypes/application-x-valentina-pattern.png \
../../../share/icons/128x128/mimetypes/application-x-valentina-i-measurements.png \
../../../share/icons/128x128/mimetypes/application-x-valentina-s-measurements.png
../../../share/icons/128x128/mimetypes/application-x-valentina-s-measurements.png \
../../../share/icons/128x128/mimetypes/application-x-valentina-layout.png
hicolor_256_apps.path = $$DATADIR/icons/hicolor/256x256/apps/
hicolor_256_apps.files += \
../../../share/icons/256x256/apps/$${TARGET}.png \
../../../share/icons/256x256/apps/tape.png
../../../share/icons/256x256/apps/tape.png \
../../../share/icons/256x256/apps/puzzle.png
hicolor_256_mimetypes.path = $$DATADIR/icons/hicolor/256x256/mimetypes/
hicolor_256_mimetypes.files += \
../../../share/icons/256x256/mimetypes/application-x-valentina-pattern.png \
../../../share/icons/256x256/mimetypes/application-x-valentina-i-measurements.png \
../../../share/icons/256x256/mimetypes/application-x-valentina-s-measurements.png
../../../share/icons/256x256/mimetypes/application-x-valentina-s-measurements.png \
../../../share/icons/256x256/mimetypes/application-x-valentina-layout.png
hicolor_512_apps.path = $$DATADIR/icons/hicolor/512x512/apps/
hicolor_512_apps.files += \
../../../share/icons/512x512/apps/$${TARGET}.png \
../../../share/icons/512x512/apps/tape.png
../../../share/icons/512x512/apps/tape.png \
../../../share/icons/512x512/apps/puzzle.png
hicolor_512_mimetypes.path = $$DATADIR/icons/hicolor/512x512/mimetypes/
hicolor_512_mimetypes.files += \
../../../share/icons/512x512/mimetypes/application-x-valentina-pattern.png \
../../../share/icons/512x512/mimetypes/application-x-valentina-i-measurements.png \
../../../share/icons/512x512/mimetypes/application-x-valentina-s-measurements.png
../../../share/icons/512x512/mimetypes/application-x-valentina-s-measurements.png \
../../../share/icons/512x512/mimetypes/application-x-valentina-layout.png
# Path to translation files after installation
translations.path = $$PKGDATADIR/translations/
@ -229,6 +243,7 @@ unix{
INSTALLS += \
target \
tape \
puzzle \
desktop \
hicolor_48_apps \
hicolor_48_mimetypes \
@ -273,6 +288,9 @@ unix{
tape.path = $$MACOS_DIR
tape.files += $${OUT_PWD}/../tape/$${DESTDIR}/tape.app/$$MACOS_DIR/tape
puzzle.path = $$MACOS_DIR
puzzle.files += $${OUT_PWD}/../puzzle/$${DESTDIR}/puzzle.app/$$MACOS_DIR/puzzle
# Utility pdftops need for saving a layout image to PS and EPS formates.
xpdf.path = $$MACOS_DIR
xpdf.files += $${PWD}/../../../dist/macx/bin64/pdftops
@ -298,6 +316,7 @@ unix{
icns_resources.files += $$PWD/../../../dist/macx/i-measurements.icns
icns_resources.files += $$PWD/../../../dist/macx/s-measurements.icns
icns_resources.files += $$PWD/../../../dist/macx/pattern.icns
icns_resources.files += $$PWD/../../../dist/macx/layout.icns
# Copy to bundle multisize measurements files
# We cannot add none exist files to bundle through QMAKE_BUNDLE_DATA. That's why we must do this manually.
@ -309,6 +328,7 @@ unix{
label \
libraries \
tape \
puzzle \
xpdf \
icns_resources
}
@ -322,11 +342,13 @@ win32:*g++* {
package.files += \
$${OUT_PWD}/$${DESTDIR}/valentina.exe \
$${OUT_PWD}/../tape/$${DESTDIR}/tape.exe \
$${OUT_PWD}/../puzzle/$${DESTDIR}/puzzle.exe \
$${OUT_PWD}/../tape/$${DESTDIR}/diagrams.rcc \
$$PWD/../../../dist/win/valentina.ico \
$$PWD/../../../dist/win/i-measurements.ico \
$$PWD/../../../dist/win/s-measurements.ico \
$$PWD/../../../dist/win/pattern.ico \
$$PWD/../../../dist/win/layout.ico \
$$PWD/../../../dist/win/pdftops.exe \
$$PWD/../../../dist/win/EUDC.TTE \
$$PWD/../../../AUTHORS.txt \

View File

@ -153,16 +153,14 @@ QString VAbstractApplication::translationsPath(const QString &locale) const
{
return dir.absolutePath();
}
else
{
#if defined(APPIMAGE) && defined(Q_OS_LINUX)
/* Fix path to trasnaltions when run inside AppImage. */
return AppImageRoot() + PKGDATADIR + trPath;
/* Fix path to trasnaltions when run inside AppImage. */
return AppImageRoot() + PKGDATADIR + trPath;
#else
return PKGDATADIR + trPath;
return PKGDATADIR + trPath;
#endif // defined(APPIMAGE) && defined(Q_OS_LINUX)
}
#endif
#endif // Unix
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
/************************************************************************
/************************************************************************
**
** @file vcommonsettings.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>

View File

@ -831,12 +831,20 @@ QVector<QLineF> VPassmark::BuiltInSAPassmarkBaseLine(const VPiece &piece) const
}
else
{
const QString errorMsg = QObject::tr("Cannot calculate a notch for point '%1' in piece '%2' with built in "
"seam allowance. User must manually provide length.")
.arg(m_data.nodeName, m_data.pieceName);
VAbstractApplication::VApp()->IsPedantic() ? throw VExceptionInvalidNotch(errorMsg) :
qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
return QVector<QLineF>();
if (m_data.globalPassmarkLength > accuracyPointOnLine)
{
length = m_data.globalPassmarkLength;
}
else
{
const QString errorMsg = QObject::tr("Cannot calculate a notch for point '%1' in piece '%2' with built "
"in seam allowance. User must manually provide length.")
.arg(m_data.nodeName, m_data.pieceName);
VAbstractApplication::VApp()->IsPedantic()
? throw VExceptionInvalidNotch(errorMsg)
: qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
return {};
}
}
}

View File

@ -31,18 +31,31 @@
#include "../vmisc/vabstractapplication.h"
#include "../vmisc/compatibility.h"
#include "../vmisc/def.h"
#include "../vmisc/vsysexits.h"
#include "dialogs/dialogexporttocsv.h"
#include "../vwidgets/vmaingraphicsview.h"
#include <QStyle>
#include <QToolBar>
#include <QFileDialog>
#include <QAction>
#include <QLockFile>
#include <QMessageBox>
#if defined(Q_OS_MAC)
#include "../vwidgets/vmaingraphicsview.h"
#include <QStyleFactory>
#endif
#include <QLoggingCategory>
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes")
QT_WARNING_DISABLE_INTEL(1418)
Q_LOGGING_CATEGORY(abstactMainWindow, "abs.MainWindow")
QT_WARNING_POP
namespace
{
//---------------------------------------------------------------------------------------------------------------------
@ -134,6 +147,13 @@ VAbstractMainWindow::VAbstractMainWindow(QWidget *parent)
}
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractMainWindow::ShowToolTip(const QString &toolTip)
{
Q_UNUSED(toolTip)
// do nothing
}
//---------------------------------------------------------------------------------------------------------------------
bool VAbstractMainWindow::ContinueFormatRewrite(const QString &currentFormatVersion,
const QString &maxFormatVersion)
@ -197,6 +217,16 @@ QString VAbstractMainWindow::CSVFilePath()
return fileName;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractMainWindow::ExportToCSVData(const QString &fileName, bool withHeader, int mib, const QChar &separator)
{
Q_UNUSED(fileName)
Q_UNUSED(withHeader)
Q_UNUSED(mib)
Q_UNUSED(separator)
// do nothing
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractMainWindow::UpdateRecentFileActions()
{
@ -219,6 +249,121 @@ void VAbstractMainWindow::UpdateRecentFileActions()
m_separatorAct->setVisible(numRecentFiles>0);
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractMainWindow::CheckFilePermissions(const QString &path, QWidget *messageBoxParent) -> bool
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
// cppcheck-suppress unreadVariable
const bool isFileWritable = QFileInfo(path).isWritable();
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not isFileWritable)
{
QMessageBox messageBox(messageBoxParent);
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(tr("The measurements document has no write permissions."));
messageBox.setInformativeText(tr("Do you want to change the premissions?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
messageBox.setDefaultButton(QMessageBox::Yes);
if (messageBox.exec() == QMessageBox::Yes)
{
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup++; // turn checking on
#endif /*Q_OS_WIN32*/
bool changed = QFile::setPermissions(path, QFileInfo(path).permissions() | QFileDevice::WriteUser);
#ifdef Q_OS_WIN32
qt_ntfs_permission_lookup--; // turn it off again
#endif /*Q_OS_WIN32*/
if (not changed)
{
messageBox.setIcon(QMessageBox::Warning);
messageBox.setText(tr("Cannot set permissions for %1 to writable.").arg(path));
messageBox.setInformativeText(tr("Could not save the file."));
messageBox.setStandardButtons(QMessageBox::Ok);
messageBox.setDefaultButton(QMessageBox::Ok);
messageBox.exec();
return false;
}
}
else
{
return false;
}
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
bool VAbstractMainWindow::IgnoreLocking(int error, const QString &path, bool guiMode)
{
QMessageBox::StandardButton answer = QMessageBox::Abort;
if (guiMode)
{
switch(error)
{
case QLockFile::LockFailedError:
answer = QMessageBox::warning(this, tr("Locking file"),
tr("This file already opened in another window. Ignore if you want "
"to continue (not recommended, can cause a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
case QLockFile::PermissionError:
answer = QMessageBox::question(this, tr("Locking file"),
tr("The lock file could not be created, for lack of permissions. "
"Ignore if you want to continue (not recommended, can cause "
"a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
case QLockFile::UnknownError:
answer = QMessageBox::question(this, tr("Locking file"),
tr("Unknown error happened, for instance a full partition "
"prevented writing out the lock file. Ignore if you want to "
"continue (not recommended, can cause a data corruption)."),
QMessageBox::Abort|QMessageBox::Ignore, QMessageBox::Abort);
break;
default:
answer = QMessageBox::Abort;
break;
}
}
if (answer == QMessageBox::Abort)
{
qCDebug(abstactMainWindow, "Failed to lock %s", qUtf8Printable(path));
qCDebug(abstactMainWindow, "Error type: %d", error);
if (not guiMode)
{
switch(error)
{
case QLockFile::LockFailedError:
qCCritical(abstactMainWindow, "%s",
qUtf8Printable(tr("This file already opened in another window.")));
break;
case QLockFile::PermissionError:
qCCritical(abstactMainWindow, "%s",
qUtf8Printable(tr("The lock file could not be created, for lack of permissions.")));
break;
case QLockFile::UnknownError:
qCCritical(abstactMainWindow, "%s",
qUtf8Printable(tr("Unknown error happened, for instance a full partition "
"prevented writing out the lock file.")));
break;
default:
break;
}
qApp->exit(V_EX_NOINPUT);
}
return false;
}
return true;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractMainWindow::WindowsLocale()
{

View File

@ -45,7 +45,7 @@ public:
virtual ~VAbstractMainWindow() Q_DECL_EQ_DEFAULT;
public slots:
virtual void ShowToolTip(const QString &toolTip)=0;
virtual void ShowToolTip(const QString &toolTip);
virtual void UpdateVisibilityGroups();
virtual void UpdateDetailsList();
virtual void ZoomFitBestCurrent();
@ -66,11 +66,15 @@ protected:
QString CSVFilePath();
virtual void ExportToCSVData(const QString &fileName, bool withHeader, int mib, const QChar &separator)=0;
virtual void ExportToCSVData(const QString &fileName, bool withHeader, int mib, const QChar &separator);
virtual QStringList RecentFileList() const =0;
void UpdateRecentFileActions();
static bool CheckFilePermissions(const QString &path, QWidget *messageBoxParent=nullptr);
bool IgnoreLocking(int error, const QString &path, bool guiMode);
private:
Q_DISABLE_COPY(VAbstractMainWindow)
};