/************************************************************************ ** ** @file mainwindow.cpp ** @author Roman Telezhynskyi ** @date November 15, 2013 ** ** @brief ** @copyright ** This source code is part of the Valentine project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2013-2015 Valentina project ** 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 . ** *************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include "../vgeometry/vspline.h" #include "../ifc/exception/vexceptionobjecterror.h" #include "../ifc/exception/vexceptionconversionerror.h" #include "../ifc/exception/vexceptionemptyparameter.h" #include "../ifc/exception/vexceptionwrongid.h" #include "../ifc/exception/vexceptionundo.h" #include "version.h" #include "core/vapplication.h" #include "../vmisc/undoevent.h" #include "../vmisc/vsettings.h" #include "../vmisc/def.h" #include "undocommands/renamepp.h" #include "core/vtooloptionspropertybrowser.h" #include "options.h" #include "../ifc/xml/vpatternconverter.h" #include "../vmisc/logging.h" #include "../vformat/vmeasurements.h" #include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vvitconverter.h" #include "../vwidgets/vwidgetpopup.h" #include "../vwidgets/vmaingraphicsscene.h" #include "tools/drawTools/drawtools.h" #include "../vtools/dialogs/tooldialogs.h" #include "tools/vtoolseamallowance.h" #include "tools/nodeDetails/vtoolpiecepath.h" #include "tools/vtooluniondetails.h" #include "dialogs/dialogs.h" #include "dialogs/vwidgetgroups.h" #include "../vtools/undocommands/addgroup.h" #include "dialogs/vwidgetdetails.h" #include "../vpatterndb/vpiecepath.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_OS_MAC) #include #include #endif //defined(Q_OS_MAC) QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes") QT_WARNING_DISABLE_INTEL(1418) Q_LOGGING_CATEGORY(vMainWindow, "v.mainwindow") QT_WARNING_POP const QString autosavePrefix = QStringLiteral(".autosave"); //--------------------------------------------------------------------------------------------------------------------- /** * @brief MainWindow constructor. * @param parent parent widget. */ MainWindow::MainWindow(QWidget *parent) :MainWindowsNoGUI(parent), ui(new Ui::MainWindow), watcher(new QFileSystemWatcher(this)), currentTool(Tool::Arrow), lastUsedTool(Tool::Arrow), sceneDraw(nullptr), sceneDetails(nullptr), mouseCoordinate(nullptr), helpLabel(nullptr), isInitialized(false), mChanges(false), mChangesAsked(true), patternReadOnly(false), dialogTable(nullptr), dialogTool(nullptr), dialogHistory(nullptr), comboBoxDraws(nullptr), patternPieceLabel(nullptr), mode(Draw::Calculation), currentDrawIndex(0), currentToolBoxIndex(0), isDockToolOptionsVisible(true), isDockGroupsVisible(true), drawMode(true), recentFileActs(), separatorAct(nullptr), leftGoToStage(nullptr), rightGoToStage(nullptr), autoSaveTimer(nullptr), guiEnabled(true), gradationHeights(nullptr), gradationSizes(nullptr), gradationHeightsLabel(nullptr), gradationSizesLabel(nullptr), toolOptions(nullptr), groupsWidget(nullptr), detailsWidget(nullptr), lock(nullptr), toolButtonPointerList() { for (int i = 0; i < MaxRecentFiles; ++i) { recentFileActs[i] = nullptr; } CreateActions(); InitScenes(); doc = new VPattern(pattern, &mode, sceneDraw, sceneDetails); connect(doc, &VPattern::ClearMainWindow, this, &MainWindow::Clear); connect(doc, &VPattern::patternChanged, this, &MainWindow::PatternChangesWereSaved); connect(doc, &VPattern::UndoCommand, this, &MainWindow::FullParseFile); connect(doc, &VPattern::SetEnabledGUI, this, &MainWindow::SetEnabledGUI); connect(doc, &VPattern::CheckLayout, RECEIVER(this)[this]() { if (pattern->DataPieces()->count() == 0) { if(not ui->actionDraw->isChecked()) { ActionDraw(true); } } }); connect(doc, &VPattern::SetCurrentPP, this, &MainWindow::GlobalChangePP); qApp->setCurrentDocument(doc); InitDocksContain(); CreateMenus(); ToolBarDraws(); ToolBarStages(); InitToolButtons(); helpLabel = new QLabel(QObject::tr("Create new pattern piece to start working.")); ui->statusBar->addWidget(helpLabel); ToolBarTools(); connect(qApp->getUndoStack(), &QUndoStack::cleanChanged, this, &MainWindow::PatternChangesWereSaved); InitAutoSave(); ui->toolBox->setCurrentIndex(0); ReadSettings(); setCurrentFile(""); WindowsLocale(); connect(ui->listWidget, &QListWidget::currentRowChanged, this, &MainWindow::ShowPaper); ui->dockWidgetLayoutPages->setVisible(false); connect(watcher, &QFileSystemWatcher::fileChanged, this, &MainWindow::MeasurementsChanged); connect(qApp, &QApplication::focusChanged, RECEIVER(this)[this](QWidget *old, QWidget *now) { if (old == nullptr && isAncestorOf(now) == true) {// focus IN if (mChanges && not mChangesAsked) { mChangesAsked = true; const auto answer = QMessageBox::question(this, tr("Measurements"), tr("Measurements were changed. Do you want to sync measurements now?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes); if (answer == QMessageBox::Yes) { SyncMeasurements(); } } } // In case we will need it // else if (isAncestorOf(old) == true && now == nullptr) // focus OUT }); #if defined(Q_OS_MAC) // On Mac deafault icon size is 32x32. ui->toolBarDraws->setIconSize(QSize(24, 24)); ui->toolBarOption->setIconSize(QSize(24, 24)); ui->toolBarStages->setIconSize(QSize(24, 24)); ui->toolBarTools->setIconSize(QSize(24, 24)); setUnifiedTitleAndToolBarOnMac(true); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 2) // Mac OS Dock Menu QMenu *menu = new QMenu(this); QAction *actionNewPattern = menu->addAction(tr("New pattern")); actionNewPattern->setMenuRole(QAction::NoRole); connect(actionNewPattern, &QAction::triggered, this, &MainWindow::New); QAction *actionOpenPattern = menu->addAction(tr("Open pattern")); actionOpenPattern->setMenuRole(QAction::NoRole); connect(actionOpenPattern, &QAction::triggered, this, &MainWindow::Open); QAction *actionOpenTape = menu->addAction(tr("Create/Edit measurements")); actionOpenTape->setMenuRole(QAction::NoRole); connect(actionOpenTape, &QAction::triggered, this, &MainWindow::CreateMeasurements); QAction *actionPreferences = menu->addAction(tr("Preferences")); actionPreferences->setMenuRole(QAction::NoRole); connect(actionPreferences, &QAction::triggered, this, &MainWindow::Preferences); extern void qt_mac_set_dock_menu(QMenu *); qt_mac_set_dock_menu(menu); #endif #endif //defined(Q_OS_MAC) } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::AddPP(const QString &PPName) { if (doc->appendPP(PPName) == false) { qCDebug(vMainWindow, "Error creating pattern piece with the name %s.", qUtf8Printable(PPName)); return; } if (comboBoxDraws->count() == 0) { sceneDraw->InitOrigins(); sceneDetails->InitOrigins(); } comboBoxDraws->blockSignals(true); comboBoxDraws->addItem(PPName); pattern->ClearGObjects(); //Create single point ui->view->itemClicked(nullptr);//hide options previous tool const QString label = doc->GenerateLabel(LabelType::NewPatternPiece); const QPointF startPosition = StartPositionNewPP(); VPointF *point = new VPointF(startPosition.x(), startPosition.y(), label, 5, 10); auto spoint = VToolBasePoint::Create(0, PPName, point, sceneDraw, doc, pattern, Document::FullParse, Source::FromGui); ui->view->itemClicked(spoint); SetEnableTool(true); SetEnableWidgets(true); const qint32 index = comboBoxDraws->findText(PPName); if ( index != -1 ) { // -1 for not found comboBoxDraws->setCurrentIndex(index); } else { comboBoxDraws->setCurrentIndex(0); } comboBoxDraws->blockSignals(false); // Show best for new PP VMainGraphicsView::NewSceneRect(ui->view->scene(), ui->view); ui->view->fitInView(doc->ActiveDrawBoundingRect(), Qt::KeepAspectRatio); ui->view->NewFactor(ui->view->transform().m11()); ui->actionNewDraw->setEnabled(true); helpLabel->setText(""); } //--------------------------------------------------------------------------------------------------------------------- QPointF MainWindow::StartPositionNewPP() const { const qreal originX = 30.0; const qreal originY = 40.0; const qreal margin = 40.0; if (comboBoxDraws->count() > 1) { const QRectF rect = sceneDraw->VisibleItemsBoundingRect(); if (rect.width() <= rect.height()) { return QPointF(rect.width()+margin, originY); } else { return QPointF(originX, rect.height()+margin); } } else { return QPointF(originX, originY); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::InitScenes() { sceneDraw = new VMainGraphicsScene(this); currentScene = sceneDraw; qApp->setCurrentScene(¤tScene); connect(this, &MainWindow::EnableItemMove, sceneDraw, &VMainGraphicsScene::EnableItemMove); connect(this, &MainWindow::ItemsSelection, sceneDraw, &VMainGraphicsScene::ItemsSelection); connect(this, &MainWindow::EnableLabelSelection, sceneDraw, &VMainGraphicsScene::ToggleLabelSelection); connect(this, &MainWindow::EnablePointSelection, sceneDraw, &VMainGraphicsScene::TogglePointSelection); connect(this, &MainWindow::EnableLineSelection, sceneDraw, &VMainGraphicsScene::ToggleLineSelection); connect(this, &MainWindow::EnableArcSelection, sceneDraw, &VMainGraphicsScene::ToggleArcSelection); connect(this, &MainWindow::EnableElArcSelection, sceneDraw, &VMainGraphicsScene::ToggleElArcSelection); connect(this, &MainWindow::EnableSplineSelection, sceneDraw, &VMainGraphicsScene::ToggleSplineSelection); connect(this, &MainWindow::EnableSplinePathSelection, sceneDraw, &VMainGraphicsScene::ToggleSplinePathSelection); connect(this, &MainWindow::EnableLabelHover, sceneDraw, &VMainGraphicsScene::ToggleLabelHover); connect(this, &MainWindow::EnablePointHover, sceneDraw, &VMainGraphicsScene::TogglePointHover); connect(this, &MainWindow::EnableLineHover, sceneDraw, &VMainGraphicsScene::ToggleLineHover); connect(this, &MainWindow::EnableArcHover, sceneDraw, &VMainGraphicsScene::ToggleArcHover); connect(this, &MainWindow::EnableElArcHover, sceneDraw, &VMainGraphicsScene::ToggleElArcHover); connect(this, &MainWindow::EnableSplineHover, sceneDraw, &VMainGraphicsScene::ToggleSplineHover); connect(this, &MainWindow::EnableSplinePathHover, sceneDraw, &VMainGraphicsScene::ToggleSplinePathHover); connect(sceneDraw, &VMainGraphicsScene::mouseMove, this, &MainWindow::MouseMove); sceneDetails = new VMainGraphicsScene(this); connect(this, &MainWindow::EnableItemMove, sceneDetails, &VMainGraphicsScene::EnableItemMove); connect(this, &MainWindow::EnableNodeLabelSelection, sceneDetails, &VMainGraphicsScene::ToggleNodeLabelSelection); connect(this, &MainWindow::EnableNodePointSelection, sceneDetails, &VMainGraphicsScene::ToggleNodePointSelection); connect(this, &MainWindow::EnableDetailSelection, sceneDetails, &VMainGraphicsScene::ToggleDetailSelection); connect(this, &MainWindow::EnableNodeLabelHover, sceneDetails, &VMainGraphicsScene::ToggleNodeLabelHover); connect(this, &MainWindow::EnableNodePointHover, sceneDetails, &VMainGraphicsScene::ToggleNodePointHover); connect(this, &MainWindow::EnableDetailHover, sceneDetails, &VMainGraphicsScene::ToggleDetailHover); connect(sceneDetails, &VMainGraphicsScene::mouseMove, this, &MainWindow::MouseMove); ui->view->setScene(currentScene); sceneDraw->setTransform(ui->view->transform()); sceneDetails->setTransform(ui->view->transform()); connect(ui->view, &VMainGraphicsView::NewFactor, sceneDraw, &VMainGraphicsScene::SetFactor); QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding); policy.setHorizontalStretch(12); ui->view->setSizePolicy(policy); qApp->setSceneView(ui->view); } //--------------------------------------------------------------------------------------------------------------------- QSharedPointer MainWindow::OpenMeasurementFile(const QString &path) { QSharedPointer m; if (path.isEmpty()) { return m; } try { m = QSharedPointer(new VMeasurements(pattern)); m->setXMLContent(path); if (m->Type() == MeasurementsType::Unknown) { VException e(tr("Measurement file has unknown format.")); throw e; } if (m->Type() == MeasurementsType::Standard) { VVSTConverter converter(path); m->setXMLContent(converter.Convert());// Read again after conversion } else { VVITConverter converter(path); m->setXMLContent(converter.Convert());// Read again after conversion } if (not m->IsDefinedKnownNamesValid()) { VException e(tr("Measurement file contains invalid known measurement(s).")); throw e; } CheckRequiredMeasurements(m.data()); if (m->Type() == MeasurementsType::Standard) { if (m->MUnit() == Unit::Inch) { qCCritical(vMainWindow, "%s\n\n%s", qUtf8Printable(tr("Wrong units.")), qUtf8Printable(tr("Application doesn't support standard table with inches."))); m->clear(); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_DATAERR); } return m; } } } catch (VException &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); m->clear(); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return m; } return m; } //--------------------------------------------------------------------------------------------------------------------- bool MainWindow::LoadMeasurements(const QString &path) { QSharedPointer m = OpenMeasurementFile(path); if (m->isNull()) { return false; } if (qApp->patternUnit() == Unit::Inch && m->Type() == MeasurementsType::Standard) { qWarning()<Type() == MeasurementsType::Standard) { m->SetDataSize(); m->SetDataHeight(); } try { qApp->setPatternType(m->Type()); ToolBarOption(); pattern->ClearVariables(VarType::Measurement); m->ReadMeasurements(); } catch (VExceptionEmptyParameter &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return false; } return true; } //--------------------------------------------------------------------------------------------------------------------- bool MainWindow::UpdateMeasurements(const QString &path, int size, int height) { QSharedPointer m = OpenMeasurementFile(path); if (m->isNull()) { return false; } if (qApp->patternType() != m->Type()) { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Measurement files types have not match."))); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_DATAERR); } return false; } if (m->Type() == MeasurementsType::Standard) { pattern->SetSize(size); pattern->SetHeight(height); } try { pattern->ClearVariables(VarType::Measurement); m->ReadMeasurements(); } catch (VExceptionEmptyParameter &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return false; } return true; } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::CheckRequiredMeasurements(const VMeasurements *m) { const QSet match = doc->ListMeasurements().toSet().subtract(m->ListAll().toSet()); if (not match.isEmpty()) { QList list = match.toList(); for (int i = 0; i < list.size(); ++i) { list[i] = qApp->TrVars()->MToUser(list.at(i)); } VException e(tr("Measurement file doesn't include all required measurements.")); e.AddMoreInformation(tr("Please, additionaly provide: %1").arg(QStringList(list).join(", "))); throw e; } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief SetToolButton set tool and show dialog. * @param checked true if tool button checked. * @param t tool type. * @param cursor path tool cursor icon. * @param toolTip first tooltipe. * @param closeDialogSlot function what handle after close dialog. */ template void MainWindow::SetToolButton(bool checked, Tool t, const QString &cursor, const QString &toolTip, Func closeDialogSlot) { if (checked) { CancelTool(); emit EnableItemMove(false); currentTool = lastUsedTool = t; auto cursorResource = cursor; if (qApp->devicePixelRatio() >= 2) { // Try to load HiDPI versions of the cursors if availible auto cursorHidpiResource = QString(cursor).replace(".png", "@2x.png"); if (QFileInfo(cursorResource).exists()) { cursorResource = cursorHidpiResource; } } QPixmap pixmap(cursorResource); QCursor cur(pixmap, 2, 3); ui->view->setCursor(cur); helpLabel->setText(toolTip); ui->view->setShowToolOptions(false); dialogTool = new Dialog(pattern, 0, this); switch(t) { case Tool::Midpoint: dialogTool->Build(t); break; case Tool::PiecePath: dialogTool->SetPiecesList(doc->GetActivePPPieces()); break; default: break; } VMainGraphicsScene *scene = qobject_cast(currentScene); SCASSERT(scene != nullptr) connect(scene, &VMainGraphicsScene::ChoosedObject, dialogTool.data(), &DialogTool::ChosenObject); connect(scene, &VMainGraphicsScene::SelectedObject, dialogTool.data(), &DialogTool::SelectedObject); connect(dialogTool.data(), &DialogTool::DialogClosed, this, closeDialogSlot); connect(dialogTool.data(), &DialogTool::ToolTip, this, &MainWindow::ShowToolTip); connect(ui->view, &VMainGraphicsView::MouseRelease, [this](){EndVisualization(true);}); ui->view->itemClicked(nullptr); } else { if (QToolButton *tButton = qobject_cast< QToolButton * >(this->sender())) { tButton->setChecked(true); } } } //--------------------------------------------------------------------------------------------------------------------- template /** * @brief SetToolButtonWithApply set tool and show dialog. * @param checked true if tool button checked. * @param t tool type. * @param cursor path tool cursor icon. * @param toolTip first tooltipe. * @param closeDialogSlot function to handle close of dialog. * @param applyDialogSlot function to handle apply in dialog. */ void MainWindow::SetToolButtonWithApply(bool checked, Tool t, const QString &cursor, const QString &toolTip, Func closeDialogSlot, Func2 applyDialogSlot) { if (checked) { SetToolButton(checked, t, cursor, toolTip, closeDialogSlot); connect(dialogTool.data(), &DialogTool::DialogApplied, this, applyDialogSlot); } else { if (QToolButton *tButton = qobject_cast< QToolButton * >(this->sender())) { tButton->setChecked(true); } } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ClosedDialog handle close dialog * @param result result working dialog. */ template void MainWindow::ClosedDialog(int result) { SCASSERT(not dialogTool.isNull()) if (result == QDialog::Accepted) { VMainGraphicsScene *scene = qobject_cast(currentScene); SCASSERT(scene != nullptr) QGraphicsItem *tool = dynamic_cast(DrawTool::Create(dialogTool, scene, doc, pattern)); ui->view->itemClicked(tool); } ArrowTool(); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ClosedDialogWithApply handle close dialog that has apply button * @param result result working dialog. */ template void MainWindow::ClosedDialogWithApply(int result, VMainGraphicsScene *scene) { SCASSERT(not dialogTool.isNull()) if (result == QDialog::Accepted) { // Only create tool if not already created with apply if (dialogTool->GetAssociatedTool() == nullptr) { SCASSERT(scene != nullptr) dialogTool->SetAssociatedTool( dynamic_cast (DrawTool::Create(dialogTool, scene, doc, pattern))); } else { // Or update associated tool with data VDrawTool * vtool= static_cast(dialogTool->GetAssociatedTool()); vtool->FullUpdateFromGuiApply(); } } SCASSERT(not dialogTool.isNull()) QGraphicsItem *tool = dynamic_cast(dialogTool->GetAssociatedTool()); ui->view->itemClicked(tool); if (dialogTool->GetAssociatedTool() != nullptr) { VDrawTool *vtool= static_cast(dialogTool->GetAssociatedTool()); vtool->DialogLinkDestroy(); connect(vtool, &VDrawTool::ToolTip, this, &MainWindow::ShowToolTip); } ArrowTool(); // If insert not to the end of file call lite parse if (doc->getCursor() > 0) { doc->LiteParseTree(Document::LiteParse); if (dialogHistory) { dialogHistory->UpdateHistory(); } } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ApplyDialog handle apply in dialog */ template void MainWindow::ApplyDialog(VMainGraphicsScene *scene) { SCASSERT(not dialogTool.isNull()) // Only create tool if not already created with apply if (dialogTool->GetAssociatedTool() == nullptr) { SCASSERT(scene != nullptr) dialogTool->SetAssociatedTool( static_cast (DrawTool::Create(dialogTool, scene, doc, pattern))); } else { // Or update associated tool with data VDrawTool * vtool= static_cast(dialogTool->GetAssociatedTool()); SCASSERT(vtool != nullptr) vtool->FullUpdateFromGuiApply(); } } //--------------------------------------------------------------------------------------------------------------------- template void MainWindow::ClosedDrawDialogWithApply(int result) { ClosedDialogWithApply(result, sceneDraw); } //--------------------------------------------------------------------------------------------------------------------- template void MainWindow::ApplyDrawDialog() { ApplyDialog(sceneDraw); } //--------------------------------------------------------------------------------------------------------------------- template void MainWindow::ClosedDetailsDialogWithApply(int result) { ClosedDialogWithApply(result, sceneDetails); } //--------------------------------------------------------------------------------------------------------------------- template void MainWindow::ApplyDetailsDialog() { ApplyDialog(sceneDetails); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolEndLine handler tool endLine. * @param checked true - button checked. */ void MainWindow::ToolEndLine(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::EndLine, ":/cursor/endline_cursor.png", tr("Select point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolLine handler tool line. * @param checked true - button checked. */ void MainWindow::ToolLine(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::Line, ":/cursor/line_cursor.png", tr("Select first point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolAlongLine handler tool alongLine. * @param checked true - button checked. */ void MainWindow::ToolAlongLine(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::AlongLine, ":/cursor/alongline_cursor.png", tr("Select point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolMidpoint(bool checked) { ToolSelectPointByRelease(); // Reuse DialogAlongLine and VToolAlongLine but with different cursor SetToolButtonWithApply(checked, Tool::Midpoint, ":/cursor/midpoint_cursor.png", tr("Select point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolShoulderPoint handler tool shoulderPoint. * @param checked true - button checked. */ void MainWindow::ToolShoulderPoint(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::ShoulderPoint, ":/cursor/shoulder_cursor.png", tr("Select point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolNormal handler tool normal. * @param checked true - button checked. */ void MainWindow::ToolNormal(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::Normal, ":/cursor/normal_cursor.png", tr("Select first point of line"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolBisector handler tool bisector. * @param checked true - button checked. */ void MainWindow::ToolBisector(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::Bisector, ":/cursor/bisector_cursor.png", tr("Select first point of angle"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolLineIntersect handler tool lineIntersect. * @param checked true - button checked. */ void MainWindow::ToolLineIntersect(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::LineIntersect, ":/cursor/intersect_cursor.png", tr("Select first point of first line"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolSpline handler tool spline. * @param checked true - button checked. */ void MainWindow::ToolSpline(bool checked) { ToolSelectPointByPress(); SetToolButtonWithApply(checked, Tool::Spline, ":/cursor/spline_cursor.png", tr("Select first point curve"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolCubicBezier(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::CubicBezier, ":/cursor/cubic_bezier_cursor.png", tr("Select first curve point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolCutSpline handler tool CutSpline. * @param checked true - button is checked */ void MainWindow::ToolCutSpline(bool checked) { ToolSelectSpline(); SetToolButtonWithApply(checked, Tool::CutSpline, ":/cursor/spline_cut_point_cursor.png", tr("Select simple curve"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolArc handler tool arc. * @param checked true - button checked. */ void MainWindow::ToolArc(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::Arc, ":/cursor/arc_cursor.png", tr("Select point of center of arc"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolEllipticalArc handler tool arc. * @param checked true - button checked. */ void MainWindow::ToolEllipticalArc(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::EllipticalArc, ":/cursor/el_arc_cursor.png", tr("Select point of center of elliptical arc"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolSplinePath handler tool splinePath. * @param checked true - button checked. */ void MainWindow::ToolSplinePath(bool checked) { ToolSelectPointByPress(); SetToolButtonWithApply(checked, Tool::SplinePath, ":/cursor/splinepath_cursor.png", tr("Select point of curve path"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolCubicBezierPath(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::CubicBezierPath, ":/cursor/cubic_bezier_path_cursor.png", tr("Select point of cubic bezier path"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolCutSplinePath handler tool CutSplinePath. * @param checked true - button is checked */ void MainWindow::ToolCutSplinePath(bool checked) { ToolSelectSplinePath(); SetToolButtonWithApply(checked, Tool::CutSplinePath, ":/cursor/splinepath_cut_point_cursor.png", tr("Select curve path"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolPointOfContact handler tool pointOfContact. * @param checked true - button checked. */ void MainWindow::ToolPointOfContact(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::PointOfContact, ":/cursor/pointcontact_cursor.png", tr("Select first point of line"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolDetail handler tool detail. * @param checked true - button checked. */ void MainWindow::ToolDetail(bool checked) { ToolSelectAllDrawObjects(); SetToolButtonWithApply(checked, Tool::Piece, "://cursor/new_detail_cursor.png", tr("Select main path objects clockwise."), &MainWindow::ClosedDetailsDialogWithApply, &MainWindow::ApplyDetailsDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolPiecePath(bool checked) { ToolSelectAllDrawObjects(); SetToolButton(checked, Tool::PiecePath, "://cursor/path_cursor.png", tr("Select path objects, Shift - reverse direction curve"), &MainWindow::ClosedDialogPiecePath); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolHeight handler tool height. * @param checked true - button checked. */ void MainWindow::ToolHeight(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::Height, ":/cursor/height_cursor.png", tr("Select base point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolTriangle handler tool triangle. * @param checked true - button checked. */ void MainWindow::ToolTriangle(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::Triangle, ":/cursor/triangle_cursor.png", tr("Select first point of axis"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolPointOfIntersection handler tool pointOfIntersection. * @param checked true - button checked. */ void MainWindow::ToolPointOfIntersection(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::PointOfIntersection, ":/cursor/pointofintersect_cursor.png", tr("Select point for X value (vertical)"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolUnionDetails handler tool unionDetails. * @param checked true - button checked. */ void MainWindow::ToolUnionDetails(bool checked) { ToolSelectDetail(); SetToolButton(checked, Tool::UnionDetails, ":/cursor/union_cursor.png", tr("Select detail"), &MainWindow::ClosedDialogUnionDetails); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ClosedDialogUnionDetails actions after closing DialogUnionDetails. * @param result result of dialog working. */ void MainWindow::ClosedDialogUnionDetails(int result) { ClosedDialog(result); doc->LiteParseTree(Document::LiteParse); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolGroup(bool checked) { ToolSelectGroupObjects(); SetToolButton(checked, Tool::Group, ":/cursor/group_plus_cursor.png", tr("Select one or more objects, Enter - finish creation"), &MainWindow::ClosedDialogGroup); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolRotation(bool checked) { ToolSelectOperationObjects(); SetToolButtonWithApply(checked, Tool::Rotation, ":/cursor/rotation_cursor.png", tr("Select one or more objects, Enter - confirm selection"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolFlippingByLine(bool checked) { ToolSelectOperationObjects(); SetToolButtonWithApply(checked, Tool::FlippingByLine, ":/cursor/flipping_line_cursor.png", tr("Select one or more objects, Enter - confirm selection"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolFlippingByAxis(bool checked) { ToolSelectOperationObjects(); SetToolButtonWithApply(checked, Tool::FlippingByAxis, ":/cursor/flipping_axis_cursor.png", tr("Select one or more objects, Enter - confirm selection"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolMove(bool checked) { ToolSelectOperationObjects(); SetToolButtonWithApply(checked, Tool::Move, ":/cursor/move_cursor.png", tr("Select one or more objects, Enter - confirm selection"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ClosedDialogGroup(int result) { SCASSERT(dialogTool != nullptr) if (result == QDialog::Accepted) { DialogGroup *dialog = qobject_cast(dialogTool); SCASSERT(dialog != nullptr) const QDomElement group = doc->CreateGroup(pattern->getNextId(), dialog->GetName(), dialog->GetGroup()); if (not group.isNull()) { AddGroup *addGroup = new AddGroup(group, doc); connect(addGroup, &AddGroup::UpdateGroups, groupsWidget, &VWidgetGroups::UpdateGroups); qApp->getUndoStack()->push(addGroup); } } ArrowTool(); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ClosedDialogPiecePath(int result) { SCASSERT(dialogTool != nullptr); if (result == QDialog::Accepted) { VToolPiecePath::Create(dialogTool, sceneDetails, doc, pattern); } ArrowTool(); doc->LiteParseTree(Document::LiteParse); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolCutArc handler tool cutArc. * @param checked true - button checked. */ void MainWindow::ToolCutArc(bool checked) { ToolSelectArc(); SetToolButtonWithApply(checked, Tool::CutArc, ":/cursor/arc_cut_cursor.png", tr("Select arc"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolLineIntersectAxis(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::LineIntersectAxis, ":/cursor/line_intersect_axis_cursor.png", tr("Select first point of line"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolCurveIntersectAxis(bool checked) { ToolSelectAllDrawObjects(); SetToolButtonWithApply(checked, Tool::CurveIntersectAxis, ":/cursor/curve_intersect_axis_cursor.png", tr("Select curve"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolArcIntersectAxis(bool checked) { ToolSelectAllDrawObjects(); // Reuse ToolCurveIntersectAxis but with different cursor and tool tip SetToolButtonWithApply(checked, Tool::ArcIntersectAxis, ":/cursor/arc_intersect_axis_cursor.png", tr("Select arc"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolPointOfIntersectionArcs(bool checked) { ToolSelectArc(); SetToolButtonWithApply(checked, Tool::PointOfIntersectionArcs, "://cursor/point_of_intersection_arcs.png", tr("Select first an arc"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolPointOfIntersectionCircles(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::PointOfIntersectionCircles, "://cursor/point_of_intersection_circles.png", tr("Select first circle center"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolPointOfIntersectionCurves(bool checked) { ToolSelectCurve(); SetToolButtonWithApply(checked, Tool::PointOfIntersectionCurves, "://cursor/intersection_curves_cursor.png", tr("Select first curve"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolPointFromCircleAndTangent(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::PointFromCircleAndTangent, "://cursor/point_from_circle_and_tangent_cursor.png", tr("Select point on tangent"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolPointFromArcAndTangent(bool checked) { ToolSelectPointArc(); SetToolButtonWithApply(checked, Tool::PointFromArcAndTangent, "://cursor/point_from_arc_and_tangent_cursor.png", tr("Select point on tangent"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolArcWithLength(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::ArcWithLength, "://cursor/arc_with_length_cursor.png", tr("Select point of the center of the arc"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolTrueDarts(bool checked) { ToolSelectPointByRelease(); SetToolButtonWithApply(checked, Tool::TrueDarts, "://cursor/true_darts_cursor.png", tr("Select the first base line point"), &MainWindow::ClosedDrawDialogWithApply, &MainWindow::ApplyDrawDialog); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ShowTool highlight tool.Tip show tools tooltip. * @param toolTip tooltip text. */ void MainWindow::ShowToolTip(const QString &toolTip) { helpLabel->setText(toolTip); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief showEvent handle after show window. * @param event show event. */ void MainWindow::showEvent( QShowEvent *event ) { QMainWindow::showEvent( event ); if ( event->spontaneous() ) { return; } if (isInitialized) { return; } // do your init stuff here MinimumScrollBar(); isInitialized = true;//first show windows are held } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::changeEvent(QEvent *event) { if (event->type() == QEvent::LanguageChange) { // retranslate designer form (single inheritance approach) ui->retranslateUi(this); undoAction->setText(tr("&Undo")); redoAction->setText(tr("&Redo")); helpLabel->setText(QObject::tr("Changes applied.")); patternPieceLabel->setText(tr("Pattern Piece:")); UpdateWindowTitle(); emit sceneDetails->LanguageChanged(); } // remember to call base class implementation QMainWindow::changeEvent(event); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief closeEvent handle after close window. * @param event close event. */ void MainWindow::closeEvent(QCloseEvent *event) { qCDebug(vMainWindow, "Closing main window"); if (MaybeSave()) { FileClosedCorrect(); event->accept(); qApp->closeAllWindows(); } else { qCDebug(vMainWindow, "Closing canceled."); event->ignore(); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::customEvent(QEvent *event) { if (event->type() == UNDO_EVENT) { qApp->getUndoStack()->undo(); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::CleanLayout() { qDeleteAll (scenes); scenes.clear(); shadows.clear(); papers.clear(); ui->listWidget->clear(); SetLayoutModeActions(); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::PrepareSceneList() { for (int i=1; i<=scenes.size(); ++i) { QListWidgetItem *item = new QListWidgetItem(ScenePreview(i-1), QString::number(i)); ui->listWidget->addItem(item); } if (not scenes.isEmpty()) { ui->listWidget->setCurrentRow(0); SetLayoutModeActions(); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::LoadIndividual() { const QString filter = tr("Individual measurements (*.vit);;Standard measurements (*.vst)"); //Use standard path to individual measurements const QString path = qApp->ValentinaSettings()->GetPathIndividualMeasurements(); const QString mPath = QFileDialog::getOpenFileName(this, tr("Open file"), path, filter); if (not mPath.isEmpty()) { if (LoadMeasurements(mPath)) { if (not doc->MPath().isEmpty()) { watcher->removePath(AbsoluteMPath(curFile, doc->MPath())); } ui->actionUnloadMeasurements->setEnabled(true); doc->SetPath(RelativeMPath(curFile, mPath)); watcher->addPath(mPath); PatternChangesWereSaved(false); ui->actionShowM->setEnabled(true); helpLabel->setText(tr("Measurements loaded")); doc->LiteParseTree(Document::LiteParse); UpdateWindowTitle(); } } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::LoadStandard() { const QString filter = tr("Standard measurements (*.vst);;Individual measurements (*.vit)"); //Use standard path to standard measurements const QString path = qApp->ValentinaSettings()->GetPathStandardMeasurements(); const QString mPath = QFileDialog::getOpenFileName(this, tr("Open file"), path, filter); if (not mPath.isEmpty()) { QString hText; if (not gradationHeights.isNull()) { hText = gradationHeights->currentText(); } QString sText; if (not gradationSizes.isNull()) { sText = gradationSizes->currentText(); } if(LoadMeasurements(mPath)) { if (not doc->MPath().isEmpty()) { watcher->removePath(AbsoluteMPath(curFile, doc->MPath())); } ui->actionUnloadMeasurements->setEnabled(true); doc->SetPath(RelativeMPath(curFile, mPath)); watcher->addPath(mPath); PatternChangesWereSaved(false); ui->actionShowM->setEnabled(true); helpLabel->setText(tr("Measurements loaded")); doc->LiteParseTree(Document::LiteParse); UpdateWindowTitle(); if (qApp->patternType() == MeasurementsType::Standard) { if (not hText.isEmpty() && not gradationSizes.isNull()) { gradationHeights->setCurrentText(hText); } if (not sText.isEmpty() && not gradationSizes.isNull()) { gradationSizes->setCurrentText(sText); } } } } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::UnloadMeasurements() { if (doc->MPath().isEmpty()) { ui->actionUnloadMeasurements->setDisabled(true); return; } if (doc->ListMeasurements().isEmpty()) { watcher->removePath(AbsoluteMPath(curFile, doc->MPath())); doc->SetPath(QString()); PatternChangesWereSaved(false); ui->actionShowM->setEnabled(false); ui->actionUnloadMeasurements->setDisabled(true); helpLabel->setText(tr("Measurements unloaded")); UpdateWindowTitle(); } else { qCWarning(vMainWindow, "%s", qUtf8Printable(tr("Couldn't unload measurements. Some of them are used in the pattern."))); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ShowMeasurements() { if (not doc->MPath().isEmpty()) { const QString absoluteMPath = AbsoluteMPath(curFile, doc->MPath()); QStringList arguments; if (qApp->patternType() == MeasurementsType::Standard) { arguments = QStringList() << absoluteMPath << "-u" << VDomDocument::UnitsToStr(qApp->patternUnit()) << "-e" << QString().setNum(static_cast(UnitConvertor(pattern->height(), doc->MUnit(), Unit::Cm))) << "-s" << QString().setNum(static_cast(UnitConvertor(pattern->size(), doc->MUnit(), Unit::Cm))); } else { arguments = QStringList() << absoluteMPath << "-u" << VDomDocument::UnitsToStr(qApp->patternUnit()); } if (isNoScaling) { arguments.append(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING); } const QString tape = qApp->TapeFilePath(); const QString workingDirectory = QFileInfo(tape).absoluteDir().absolutePath(); QProcess::startDetached(tape, arguments, workingDirectory); } else { ui->actionShowM->setEnabled(false); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::MeasurementsChanged(const QString &path) { mChanges = false; QFileInfo checkFile(path); if (checkFile.exists()) { mChanges = true; mChangesAsked = false; } else { for(int i=0; i<=1000; i=i+10) { if (checkFile.exists()) { mChanges = true; mChangesAsked = false; break; } else { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } } UpdateWindowTitle(); ui->actionSyncMeasurements->setEnabled(mChanges); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::SyncMeasurements() { if (mChanges) { const QString path = AbsoluteMPath(curFile, doc->MPath()); if(UpdateMeasurements(path, static_cast(pattern->size()), static_cast(pattern->height()))) { if (not watcher->files().contains(path)) { watcher->addPath(path); } const QString msg = tr("Measurements have been synced"); qCDebug(vMainWindow, "%s", qUtf8Printable(msg)); helpLabel->setText(msg); VWidgetPopup::PopupMessage(this, msg); doc->LiteParseTree(Document::LiteParse); mChanges = false; mChangesAsked = true; UpdateWindowTitle(); ui->actionSyncMeasurements->setEnabled(mChanges); } else { qCWarning(vMainWindow, "%s", qUtf8Printable(tr("Couldn't sync measurements."))); } } } //--------------------------------------------------------------------------------------------------------------------- #if defined(Q_OS_MAC) void MainWindow::OpenAt(QAction *where) { const QString path = curFile.left(curFile.indexOf(where->text())) + where->text(); if (path == curFile) { return; } QProcess process; process.start(QStringLiteral("/usr/bin/open"), QStringList() << path, QIODevice::ReadOnly); process.waitForFinished(); } #endif //defined(Q_OS_MAC) //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolBarOption enable option toolbar. */ void MainWindow::ToolBarOption() { ui->toolBarOption->clear(); if (not mouseCoordinate.isNull()) { delete mouseCoordinate; } if (not gradationHeights.isNull()) { delete gradationHeights; } if (not gradationSizes.isNull()) { delete gradationSizes; } if (not gradationHeightsLabel.isNull()) { delete gradationHeightsLabel; } if (not gradationSizesLabel.isNull()) { delete gradationSizesLabel; } if (qApp->patternType() == MeasurementsType::Standard) { const QStringList listHeights = VMeasurement::ListHeights(doc->GetGradationHeights(), qApp->patternUnit()); const QStringList listSizes = VMeasurement::ListSizes(doc->GetGradationSizes(), qApp->patternUnit()); gradationHeightsLabel = new QLabel(tr("Height:"), this); gradationHeights = SetGradationList(gradationHeightsLabel, listHeights); // set default height SetDefaultHeight(); connect(gradationHeights.data(), static_cast(&QComboBox::currentIndexChanged), this, &MainWindow::ChangedHeight); gradationSizesLabel = new QLabel(tr("Size:"), this); gradationSizes = SetGradationList(gradationSizesLabel, listSizes); // set default size SetDefaultSize(); connect(gradationSizes.data(), static_cast(&QComboBox::currentIndexChanged), this, &MainWindow::ChangedSize); ui->toolBarOption->addSeparator(); } mouseCoordinate = new QLabel(QString("0, 0 (%1)").arg(doc->UnitsToStr(qApp->patternUnit(), true))); ui->toolBarOption->addWidget(mouseCoordinate); } //--------------------------------------------------------------------------------------------------------------------- QComboBox *MainWindow::SetGradationList(QLabel *label, const QStringList &list) { ui->toolBarOption->addWidget(label); QComboBox *comboBox = new QComboBox(this); comboBox->addItems(list); ui->toolBarOption->addWidget(comboBox); return comboBox; } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolBarStages() { leftGoToStage = new QLabel(this); leftGoToStage->setPixmap(QPixmap("://icon/24x24/fast_forward_left_to_right_arrow.png")); ui->toolBarStages->insertWidget(ui->actionDetails, leftGoToStage); rightGoToStage = new QLabel(this); rightGoToStage->setPixmap(QPixmap("://icon/24x24/left_to_right_arrow.png")); ui->toolBarStages->insertWidget(ui->actionLayout, rightGoToStage); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ToolBarDraws enable draw toolbar. */ void MainWindow::ToolBarDraws() { patternPieceLabel = new QLabel(tr("Pattern Piece:")); ui->toolBarDraws->addWidget(patternPieceLabel); // By using Qt UI Designer we can't add QComboBox to toolbar comboBoxDraws = new QComboBox; ui->toolBarDraws->addWidget(comboBoxDraws); comboBoxDraws->setSizeAdjustPolicy(QComboBox::AdjustToContents); comboBoxDraws->setEnabled(false); connect(comboBoxDraws, static_cast(&QComboBox::currentIndexChanged), RECEIVER(this)[this](int index){ChangePP(index);}); connect(ui->actionOptionDraw, &QAction::triggered, RECEIVER(this)[this]() { const QString activDraw = doc->GetNameActivPP(); const QString nameDraw = PatternPieceName(activDraw); if (nameDraw.isEmpty()) { return; } RenamePP *renamePP = new RenamePP(doc, nameDraw, comboBoxDraws); qApp->getUndoStack()->push(renamePP); }); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolBarTools() { /*First we will try use Standard Shortcuts from Qt, but because keypad "-" and "+" not the same keys like in main keypad, shortcut Ctrl+"-" or "+" from keypad will not working with standard shortcut (QKeySequence::ZoomIn or QKeySequence::ZoomOut). For examle "+" is Qt::Key_Plus + Qt::KeypadModifier for keypad. Also for me don't work Qt:CTRL and work Qt::ControlModifier.*/ QList zoomInShortcuts; zoomInShortcuts.append(QKeySequence(QKeySequence::ZoomIn)); zoomInShortcuts.append(QKeySequence(Qt::ControlModifier + Qt::Key_Plus + Qt::KeypadModifier)); ui->actionZoomIn->setShortcuts(zoomInShortcuts); connect(ui->actionZoomIn, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomIn); QList zoomOutShortcuts; zoomOutShortcuts.append(QKeySequence(QKeySequence::ZoomOut)); zoomOutShortcuts.append(QKeySequence(Qt::ControlModifier + Qt::Key_Minus + Qt::KeypadModifier)); ui->actionZoomOut->setShortcuts(zoomOutShortcuts); connect(ui->actionZoomOut, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomOut); QList zoomOriginalShortcuts; zoomOriginalShortcuts.append(QKeySequence(Qt::ControlModifier + Qt::Key_0)); zoomOriginalShortcuts.append(QKeySequence(Qt::ControlModifier + Qt::Key_0 + Qt::KeypadModifier)); ui->actionZoomOriginal->setShortcuts(zoomOriginalShortcuts); connect(ui->actionZoomOriginal, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomOriginal); QList zoomFitBestShortcuts; zoomFitBestShortcuts.append(QKeySequence(Qt::ControlModifier + Qt::Key_Equal)); ui->actionZoomFitBest->setShortcuts(zoomFitBestShortcuts); connect(ui->actionZoomFitBest, &QAction::triggered, ui->view, &VMainGraphicsView::ZoomFitBest); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::InitToolButtons() { toolButtonPointerList.append(ui->toolButtonPointerPoint); toolButtonPointerList.append(ui->toolButtonPointerLine); toolButtonPointerList.append(ui->toolButtonPointerCurve); toolButtonPointerList.append(ui->toolButtonPointerArc); toolButtonPointerList.append(ui->toolButtonPointerDetail); toolButtonPointerList.append(ui->toolButtonPointerOperations); toolButtonPointerList.append(ui->toolButtonPointerEllipticalArc); for (auto pointer : toolButtonPointerList) { connect(pointer, &QToolButton::clicked, this, &MainWindow::ArrowTool); } // This check helps to find missed tools Q_STATIC_ASSERT_X(static_cast(Tool::LAST_ONE_DO_NOT_USE) == 51, "Check if all tools were connected."); connect(ui->toolButtonEndLine, &QToolButton::clicked, this, &MainWindow::ToolEndLine); connect(ui->toolButtonLine, &QToolButton::clicked, this, &MainWindow::ToolLine); connect(ui->toolButtonAlongLine, &QToolButton::clicked, this, &MainWindow::ToolAlongLine); connect(ui->toolButtonShoulderPoint, &QToolButton::clicked, this, &MainWindow::ToolShoulderPoint); connect(ui->toolButtonNormal, &QToolButton::clicked, this, &MainWindow::ToolNormal); connect(ui->toolButtonBisector, &QToolButton::clicked, this, &MainWindow::ToolBisector); connect(ui->toolButtonLineIntersect, &QToolButton::clicked, this, &MainWindow::ToolLineIntersect); connect(ui->toolButtonSpline, &QToolButton::clicked, this, &MainWindow::ToolSpline); connect(ui->toolButtonCubicBezier, &QToolButton::clicked, this, &MainWindow::ToolCubicBezier); connect(ui->toolButtonArc, &QToolButton::clicked, this, &MainWindow::ToolArc); connect(ui->toolButtonSplinePath, &QToolButton::clicked, this, &MainWindow::ToolSplinePath); connect(ui->toolButtonCubicBezierPath, &QToolButton::clicked, this, &MainWindow::ToolCubicBezierPath); connect(ui->toolButtonPointOfContact, &QToolButton::clicked, this, &MainWindow::ToolPointOfContact); connect(ui->toolButtonNewDetail, &QToolButton::clicked, this, &MainWindow::ToolDetail); connect(ui->toolButtonPiecePath, &QToolButton::clicked, this, &MainWindow::ToolPiecePath); connect(ui->toolButtonHeight, &QToolButton::clicked, this, &MainWindow::ToolHeight); connect(ui->toolButtonTriangle, &QToolButton::clicked, this, &MainWindow::ToolTriangle); connect(ui->toolButtonPointOfIntersection, &QToolButton::clicked, this, &MainWindow::ToolPointOfIntersection); connect(ui->toolButtonSplineCutPoint, &QToolButton::clicked, this, &MainWindow::ToolCutSpline); connect(ui->toolButtonSplinePathCutPoint, &QToolButton::clicked, this, &MainWindow::ToolCutSplinePath); connect(ui->toolButtonUnionDetails, &QToolButton::clicked, this, &MainWindow::ToolUnionDetails); connect(ui->toolButtonArcCutPoint, &QToolButton::clicked, this, &MainWindow::ToolCutArc); connect(ui->toolButtonLineIntersectAxis, &QToolButton::clicked, this, &MainWindow::ToolLineIntersectAxis); connect(ui->toolButtonCurveIntersectAxis, &QToolButton::clicked, this, &MainWindow::ToolCurveIntersectAxis); connect(ui->toolButtonArcIntersectAxis, &QToolButton::clicked, this, &MainWindow::ToolArcIntersectAxis); connect(ui->toolButtonLayoutSettings, &QToolButton::clicked, this, &MainWindow::ToolLayoutSettings); connect(ui->toolButtonPointOfIntersectionArcs, &QToolButton::clicked, this, &MainWindow::ToolPointOfIntersectionArcs); connect(ui->toolButtonPointOfIntersectionCircles, &QToolButton::clicked, this, &MainWindow::ToolPointOfIntersectionCircles); connect(ui->toolButtonIntersectionCurves, &QToolButton::clicked, this, &MainWindow::ToolPointOfIntersectionCurves); connect(ui->toolButtonPointFromCircleAndTangent, &QToolButton::clicked, this, &MainWindow::ToolPointFromCircleAndTangent); connect(ui->toolButtonPointFromArcAndTangent, &QToolButton::clicked, this, &MainWindow::ToolPointFromArcAndTangent); connect(ui->toolButtonArcWithLength, &QToolButton::clicked, this, &MainWindow::ToolArcWithLength); connect(ui->toolButtonTrueDarts, &QToolButton::clicked, this, &MainWindow::ToolTrueDarts); connect(ui->toolButtonGroup, &QToolButton::clicked, this, &MainWindow::ToolGroup); connect(ui->toolButtonRotation, &QToolButton::clicked, this, &MainWindow::ToolRotation); connect(ui->toolButtonFlippingByLine, &QToolButton::clicked, this, &MainWindow::ToolFlippingByLine); connect(ui->toolButtonFlippingByAxis, &QToolButton::clicked, this, &MainWindow::ToolFlippingByAxis); connect(ui->toolButtonMove, &QToolButton::clicked, this, &MainWindow::ToolMove); connect(ui->toolButtonMidpoint, &QToolButton::clicked, this, &MainWindow::ToolMidpoint); connect(ui->toolButtonLayoutExportAs, &QToolButton::clicked, this, &MainWindow::ExportLayoutAs); connect(ui->toolButtonEllipticalArc, &QToolButton::clicked, this, &MainWindow::ToolEllipticalArc); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief mouseMove save mouse position and show user. * @param scenePos position mouse. */ void MainWindow::MouseMove(const QPointF &scenePos) { if (mouseCoordinate) { //: Coords in status line: "X, Y (units)" mouseCoordinate->setText(QString("%1, %2 (%3)").arg(static_cast(qApp->fromPixel(scenePos.x()))) .arg(static_cast(qApp->fromPixel(scenePos.y()))) .arg(doc->UnitsToStr(qApp->patternUnit(), true))); } } //--------------------------------------------------------------------------------------------------------------------- QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wswitch-default") /** * @brief CancelTool cancel tool. */ void MainWindow::CancelTool() { // This check helps to find missed tools in the switch Q_STATIC_ASSERT_X(static_cast(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were handled."); qCDebug(vMainWindow, "Canceling tool."); delete dialogTool; qCDebug(vMainWindow, "Dialog closed."); currentScene->setFocus(Qt::OtherFocusReason); currentScene->clearSelection(); switch ( currentTool ) { case Tool::Arrow: for (auto pointer : toolButtonPointerList) { pointer->setChecked(false); } helpLabel->setText(""); // Crash: using CRTL+Z while using line tool. // related bug report: // https://bitbucket.org/dismine/valentina/issues/454/crash-using-crtl-z-while-using-line-tool undoAction->setEnabled(false); redoAction->setEnabled(false); return; case Tool::BasePoint: case Tool::SinglePoint: case Tool::DoublePoint: case Tool::LinePoint: case Tool::AbstractSpline: case Tool::Cut: case Tool::LAST_ONE_DO_NOT_USE: case Tool::NodePoint: case Tool::NodeArc: case Tool::NodeElArc: case Tool::NodeSpline: case Tool::NodeSplinePath: Q_UNREACHABLE(); //-V501 //Nothing to do here because we can't create this tool from main window. break; case Tool::EndLine: ui->toolButtonEndLine->setChecked(false); break; case Tool::Line: ui->toolButtonLine->setChecked(false); break; case Tool::AlongLine: ui->toolButtonAlongLine->setChecked(false); break; case Tool::Midpoint: ui->toolButtonMidpoint->setChecked(false); break; case Tool::ShoulderPoint: ui->toolButtonShoulderPoint->setChecked(false); break; case Tool::Normal: ui->toolButtonNormal->setChecked(false); break; case Tool::Bisector: ui->toolButtonBisector->setChecked(false); break; case Tool::LineIntersect: ui->toolButtonLineIntersect->setChecked(false); break; case Tool::Spline: ui->toolButtonSpline->setChecked(false); break; case Tool::CubicBezier: ui->toolButtonCubicBezier->setChecked(false); break; case Tool::Arc: ui->toolButtonArc->setChecked(false); break; case Tool::ArcWithLength: ui->toolButtonArcWithLength->setChecked(false); break; case Tool::SplinePath: ui->toolButtonSplinePath->setChecked(false); break; case Tool::CubicBezierPath: ui->toolButtonCubicBezierPath->setChecked(false); break; case Tool::PointOfContact: ui->toolButtonPointOfContact->setChecked(false); break; case Tool::Piece: ui->toolButtonNewDetail->setChecked(false); break; case Tool::PiecePath: ui->toolButtonPiecePath->setChecked(false); break; case Tool::Height: ui->toolButtonHeight->setChecked(false); break; case Tool::Triangle: ui->toolButtonTriangle->setChecked(false); break; case Tool::PointOfIntersection: ui->toolButtonPointOfIntersection->setChecked(false); break; case Tool::CutSpline: ui->toolButtonSplineCutPoint->setChecked(false); break; case Tool::CutSplinePath: ui->toolButtonSplinePathCutPoint->setChecked(false); break; case Tool::UnionDetails: ui->toolButtonUnionDetails->setChecked(false); break; case Tool::CutArc: ui->toolButtonArcCutPoint->setChecked(false); break; case Tool::LineIntersectAxis: ui->toolButtonLineIntersectAxis->setChecked(false); break; case Tool::CurveIntersectAxis: ui->toolButtonCurveIntersectAxis->setChecked(false); break; case Tool::ArcIntersectAxis: ui->toolButtonArcIntersectAxis->setChecked(false); break; case Tool::PointOfIntersectionArcs: ui->toolButtonPointOfIntersectionArcs->setChecked(false); break; case Tool::PointOfIntersectionCircles: ui->toolButtonPointOfIntersectionCircles->setChecked(false); break; case Tool::PointOfIntersectionCurves: ui->toolButtonIntersectionCurves->setChecked(false); break; case Tool::PointFromCircleAndTangent: ui->toolButtonPointFromCircleAndTangent->setChecked(false); break; case Tool::PointFromArcAndTangent: ui->toolButtonPointFromArcAndTangent->setChecked(false); break; case Tool::TrueDarts: ui->toolButtonTrueDarts->setChecked(false); break; case Tool::Group: ui->toolButtonGroup->setChecked(false); break; case Tool::Rotation: ui->toolButtonRotation->setChecked(false); break; case Tool::FlippingByLine: ui->toolButtonFlippingByLine->setChecked(false); break; case Tool::FlippingByAxis: ui->toolButtonFlippingByAxis->setChecked(false); break; case Tool::Move: ui->toolButtonMove->setChecked(false); break; case Tool::EllipticalArc: ui->toolButtonEllipticalArc->setChecked(false); break; } // Crash: using CRTL+Z while using line tool. // related bug report: // https://bitbucket.org/dismine/valentina/issues/454/crash-using-crtl-z-while-using-line-tool undoAction->setEnabled(qApp->getUndoStack()->canUndo()); redoAction->setEnabled(qApp->getUndoStack()->canRedo()); } QT_WARNING_POP //--------------------------------------------------------------------------------------------------------------------- /** * @brief ArrowTool enable arrow tool. */ void MainWindow::ArrowTool() { qCDebug(vMainWindow, "Arrow tool."); CancelTool(); for (auto pointer : toolButtonPointerList) { pointer->setChecked(true); } currentTool = Tool::Arrow; emit EnableItemMove(true); emit ItemsSelection(SelectionType::ByMouseRelease); // Only true for rubber band selection emit EnableLabelSelection(true); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); emit EnableNodeLabelSelection(true); emit EnableNodePointSelection(true); emit EnableDetailSelection(true);// Disable when done visualization details // Hovering emit EnableLabelHover(true); emit EnablePointHover(true); emit EnableLineHover(true); emit EnableArcHover(true); emit EnableElArcHover(true); emit EnableSplineHover(true); emit EnableSplinePathHover(true); emit EnableNodeLabelHover(true); emit EnableNodePointHover(true); emit EnableDetailHover(true); ui->view->AllowRubberBand(true); RestoreOverrideCursor(cursorArrowCloseHand); RestoreOverrideCursor(cursorArrowOpenHand); QCursor cur(Qt::ArrowCursor); ui->view->setCursor(cur); helpLabel->setText(""); ui->view->setShowToolOptions(true); qCDebug(vMainWindow, "Enabled arrow tool."); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief keyPressEvent handle key press events. * @param event key event. */ void MainWindow::keyPressEvent ( QKeyEvent * event ) { switch (event->key()) { case Qt::Key_Escape: ArrowTool(); break; case Qt::Key_Return: case Qt::Key_Enter: EndVisualization(); break; default: break; } QMainWindow::keyPressEvent ( event ); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief SaveCurrentScene save scene options before set another. */ void MainWindow::SaveCurrentScene() { if (mode == Draw::Calculation || mode == Draw::Modeling) { VMainGraphicsScene *scene = qobject_cast(currentScene); SCASSERT(scene != nullptr) /*Save transform*/ scene->setTransform(ui->view->transform()); /*Save scroll bars value for previous scene.*/ QScrollBar *horScrollBar = ui->view->horizontalScrollBar(); scene->setHorScrollBar(horScrollBar->value()); QScrollBar *verScrollBar = ui->view->verticalScrollBar(); scene->setVerScrollBar(verScrollBar->value()); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief RestoreCurrentScene restore scene options after change. */ void MainWindow::RestoreCurrentScene() { VMainGraphicsScene *scene = qobject_cast(currentScene); SCASSERT(scene != nullptr) /*Set transform for current scene*/ ui->view->setTransform(scene->transform()); /*Set value for current scene scroll bar.*/ QScrollBar *horScrollBar = ui->view->horizontalScrollBar(); horScrollBar->setValue(scene->getHorScrollBar()); QScrollBar *verScrollBar = ui->view->verticalScrollBar(); verScrollBar->setValue(scene->getVerScrollBar()); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ActionDraw show draw scene. * @param checked true - button checked. */ void MainWindow::ActionDraw(bool checked) { if (checked) { qCDebug(vMainWindow, "Show draw scene"); ArrowTool(); leftGoToStage->setPixmap(QPixmap("://icon/24x24/fast_forward_left_to_right_arrow.png")); rightGoToStage->setPixmap(QPixmap("://icon/24x24/left_to_right_arrow.png")); ui->actionDraw->setChecked(true); ui->actionDetails->setChecked(false); ui->actionLayout->setChecked(false); SaveCurrentScene(); currentScene = sceneDraw; ui->view->setScene(currentScene); connect(ui->view, &VMainGraphicsView::NewFactor, sceneDraw, &VMainGraphicsScene::SetFactor, Qt::UniqueConnection); RestoreCurrentScene(); mode = Draw::Calculation; comboBoxDraws->setCurrentIndex(currentDrawIndex);//restore current pattern peace drawMode = true; SetEnableTool(true); SetEnableWidgets(true); ui->toolBox->setCurrentIndex(currentToolBoxIndex); if (qApp->patternType() == MeasurementsType::Standard) { ui->toolBarOption->setVisible(true); } ui->dockWidgetLayoutPages->setVisible(false); ui->dockWidgetToolOptions->setVisible(isDockToolOptionsVisible); ui->dockWidgetGroups->setWidget(groupsWidget); ui->dockWidgetGroups->setVisible(isDockGroupsVisible); ui->dockWidgetGroups->setToolTip(tr("Contains all visibility groups")); } else { ui->actionDraw->setChecked(true); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ActionDetails show details scene. * @param checked true - button checked. */ void MainWindow::ActionDetails(bool checked) { if (checked) { ArrowTool(); if(drawMode) { currentDrawIndex = comboBoxDraws->currentIndex();//save current pattern piece drawMode = false; } comboBoxDraws->setCurrentIndex(comboBoxDraws->count()-1);// Need to get data about all details leftGoToStage->setPixmap(QPixmap("://icon/24x24/right_to_left_arrow.png")); rightGoToStage->setPixmap(QPixmap("://icon/24x24/left_to_right_arrow.png")); ui->actionDraw->setChecked(false); ui->actionDetails->setChecked(true); ui->actionLayout->setChecked(false); if(not qApp->getOpeningPattern()) { if (pattern->DataPieces()->count() == 0) { QMessageBox::information(this, tr("Detail mode"), tr("You can't use now the Detail mode. " "Please, create at least one workpiece."), QMessageBox::Ok, QMessageBox::Ok); ActionDraw(true); return; } } detailsWidget->UpdateList(); qCDebug(vMainWindow, "Show details scene"); SaveCurrentScene(); currentScene = sceneDetails; ui->view->itemClicked(nullptr); ui->view->setScene(currentScene); disconnect(ui->view, &VMainGraphicsView::NewFactor, sceneDraw, &VMainGraphicsScene::SetFactor); RestoreCurrentScene(); if (mode == Draw::Calculation) { currentToolBoxIndex = ui->toolBox->currentIndex(); } mode = Draw::Modeling; SetEnableTool(true); SetEnableWidgets(true); ui->toolBox->setCurrentIndex(5); if (qApp->patternType() == MeasurementsType::Standard) { ui->toolBarOption->setVisible(true); } ui->dockWidgetLayoutPages->setVisible(false); ui->dockWidgetToolOptions->setVisible(isDockToolOptionsVisible); ui->dockWidgetGroups->setWidget(detailsWidget); ui->dockWidgetGroups->setVisible(isDockGroupsVisible); ui->dockWidgetGroups->setToolTip(tr("Show which details will go in layout")); helpLabel->setText(""); } else { ui->actionDetails->setChecked(true); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ActionLayout begin creation layout. * @param checked true - button checked. */ void MainWindow::ActionLayout(bool checked) { if (checked) { ArrowTool(); if(drawMode) { currentDrawIndex = comboBoxDraws->currentIndex();//save current pattern piece drawMode = false; } comboBoxDraws->setCurrentIndex(comboBoxDraws->count()-1);// Need to get data about all details leftGoToStage->setPixmap(QPixmap("://icon/24x24/right_to_left_arrow.png")); rightGoToStage->setPixmap(QPixmap("://icon/24x24/fast_forward_right_to_left_arrow.png")); ui->actionDraw->setChecked(false); ui->actionDetails->setChecked(false); ui->actionLayout->setChecked(true); QHash details; if(not qApp->getOpeningPattern()) { const QHash *allDetails = pattern->DataPieces(); if (allDetails->count() == 0) { QMessageBox::information(this, tr("Layout mode"), tr("You can't use now the Layout mode. " "Please, create at least one workpiece."), QMessageBox::Ok, QMessageBox::Ok); ActionDraw(true); return; } else { QHash::const_iterator i = allDetails->constBegin(); while (i != allDetails->constEnd()) { if (i.value().IsInLayout()) { details.insert(i.key(), i.value()); } ++i; } if (details.count() == 0) { QMessageBox::information(this, tr("Layout mode"), tr("You can't use now the Layout mode. Please, " "include at least one detail in layout."), QMessageBox::Ok, QMessageBox::Ok); mode == Draw::Calculation ? ActionDraw(true) : ActionDetails(true); return; } } } comboBoxDraws->setCurrentIndex(-1);// Hide pattern pieces qCDebug(vMainWindow, "Show layout scene"); SaveCurrentScene(); PrepareDetailsForLayout(&details); currentScene = tempSceneLayout; ui->view->itemClicked(nullptr); ui->view->setScene(currentScene); disconnect(ui->view, &VMainGraphicsView::NewFactor, sceneDraw, &VMainGraphicsScene::SetFactor); if (mode == Draw::Calculation) { currentToolBoxIndex = ui->toolBox->currentIndex(); } mode = Draw::Layout; SetEnableTool(true); SetEnableWidgets(true); ui->toolBox->setCurrentIndex(ui->toolBox->indexOf(ui->layoutPage)); mouseCoordinate->setText(""); if (qApp->patternType() == MeasurementsType::Standard) { ui->toolBarOption->setVisible(false); } ui->dockWidgetLayoutPages->setVisible(true); ui->dockWidgetToolOptions->blockSignals(true); ui->dockWidgetToolOptions->setVisible(false); ui->dockWidgetToolOptions->blockSignals(false); ui->dockWidgetGroups->blockSignals(true); ui->dockWidgetGroups->setVisible(false); ui->dockWidgetGroups->blockSignals(false); ShowPaper(ui->listWidget->currentRow()); if (scenes.isEmpty()) { ui->toolButtonLayoutSettings->click(); } helpLabel->setText(""); } else { ui->actionLayout->setChecked(true); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief SaveAs save as pattern file. * @return true for successes saving. */ bool MainWindow::SaveAs() { QString filters(tr("Pattern files (*.val)")); QString dir; if (curFile.isEmpty()) { dir = qApp->ValentinaSettings()->GetPathPattern() + "/" + tr("pattern") + ".val"; } else { dir = QFileInfo(curFile).absolutePath() + "/" + tr("pattern") + ".val"; } QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), dir, filters); if (fileName.isEmpty()) { return false; } QFileInfo f( fileName ); if (f.suffix().isEmpty() && f.suffix() != "val") { fileName += ".val"; } if (QFileInfo(fileName).exists()) { // Temporary try to lock the file before saving // Also help to rewite current read-only pattern VLockGuard tmp(fileName); if (not tmp.IsLocked()) { qCCritical(vMainWindow, "%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 wasModified = doc->IsModified(); // Need because SetReadOnly() will change internal state const bool readOnly = doc->IsReadOnly(); doc->SetReadOnly(false);// Save as... disable read only state QString error; const bool result = SavePattern(fileName, error); if (result == false) { QMessageBox messageBox(this); messageBox.setIcon(QMessageBox::Warning); messageBox.setInformativeText(tr("Could not save file")); messageBox.setDefaultButton(QMessageBox::Ok); messageBox.setDetailedText(error); messageBox.setStandardButtons(QMessageBox::Ok); messageBox.exec(); // Restoring previous state doc->SetReadOnly(readOnly); doc->SetModified(wasModified); return result; } patternReadOnly = false; qCDebug(vMainWindow, "Locking file"); VlpCreateLock(lock, fileName); if (lock->IsLocked()) { qCDebug(vMainWindow, "Pattern file %s was locked.", qUtf8Printable(fileName)); } else { qCDebug(vMainWindow, "Failed to lock %s", qUtf8Printable(fileName)); qCDebug(vMainWindow, "Error type: %d", lock->GetLockError()); qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Failed to lock. This file already opened in another window. Expect " "collissions when run 2 copies of the program."))); } return result; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Save save pattern file. * @return true for successes saving. */ bool MainWindow::Save() { if (curFile.isEmpty() || patternReadOnly) { return SaveAs(); } else { #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) { QMessageBox messageBox(this); messageBox.setIcon(QMessageBox::Question); messageBox.setText(tr("The document has no write permissions.")); messageBox.setInformativeText("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) { QMessageBox messageBox(this); 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.setDefaultButton(QMessageBox::Ok); messageBox.setStandardButtons(QMessageBox::Ok); messageBox.exec(); return false; } } else { return false; } } QString error; bool result = SavePattern(curFile, error); if (result) { QFile::remove(curFile + autosavePrefix); } else { QMessageBox messageBox(this); 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 result; } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Open ask user select pattern file. */ void MainWindow::Open() { qCDebug(vMainWindow, "Openning new file."); const QString filter(tr("Pattern files (*.val)")); //Get list last open files const QStringList files = qApp->ValentinaSettings()->GetRecentFileList(); QString dir; if (files.isEmpty()) { dir = QDir::homePath(); } else { //Absolute path to last open file dir = QFileInfo(files.first()).absolutePath(); } qCDebug(vMainWindow, "Run QFileDialog::getOpenFileName: dir = %s.", qUtf8Printable(dir)); const QString filePath = QFileDialog::getOpenFileName(this, tr("Open file"), dir, filter); if (filePath.isEmpty()) { return; } LoadPattern(filePath); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief Clear reset to default window. */ void MainWindow::Clear() { qCDebug(vMainWindow, "Reseting main window."); lock.reset(); qCDebug(vMainWindow, "Unlocked pattern file."); ActionDraw(true); qCDebug(vMainWindow, "Returned to Draw mode."); pattern->Clear(); qCDebug(vMainWindow, "Clearing pattern."); if (not curFile.isEmpty() && not doc->MPath().isEmpty()) { watcher->removePath(AbsoluteMPath(curFile, doc->MPath())); } doc->clear(); setCurrentFile(QString()); qCDebug(vMainWindow, "Clearing scenes."); sceneDraw->clear(); sceneDetails->clear(); ArrowTool(); comboBoxDraws->clear(); ui->actionDraw->setEnabled(false); ui->actionDetails->setEnabled(false); ui->actionLayout->setEnabled(false); ui->actionNewDraw->setEnabled(false); ui->actionOptionDraw->setEnabled(false); ui->actionSave->setEnabled(false); ui->actionSaveAs->setEnabled(false); ui->actionPattern_properties->setEnabled(false); ui->actionZoomIn->setEnabled(false); ui->actionZoomOut->setEnabled(false); ui->actionZoomFitBest->setEnabled(false); ui->actionZoomOriginal->setEnabled(false); ui->actionHistory->setEnabled(false); ui->actionTable->setEnabled(false); ui->actionLast_tool->setEnabled(false); ui->actionShowCurveDetails->setEnabled(false); ui->actionLoadIndividual->setEnabled(false); ui->actionLoadStandard->setEnabled(false); ui->actionUnloadMeasurements->setEnabled(false); ui->actionShowM->setEnabled(false); SetEnableTool(false); qApp->setPatternUnit(Unit::Cm); qApp->setPatternType(MeasurementsType::Unknown); ui->toolBarOption->clear(); #ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); #endif CleanLayout(); listDetails.clear(); // don't move to CleanLayout() qApp->getUndoStack()->clear(); toolOptions->ClearPropertyBrowser(); toolOptions->itemClicked(nullptr); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::FileClosedCorrect() { WriteSettings(); //File was closed correct. QStringList restoreFiles = qApp->ValentinaSettings()->GetRestoreFileList(); restoreFiles.removeAll(curFile); qApp->ValentinaSettings()->SetRestoreFileList(restoreFiles); // Remove autosave file QFile autofile(curFile + autosavePrefix); if (autofile.exists()) { autofile.remove(); } qCDebug(vMainWindow, "File %s closed correct.", qUtf8Printable(curFile)); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::FullParseFile() { qCDebug(vMainWindow, "Full parsing file"); toolOptions->ClearPropertyBrowser(); try { SetEnabledGUI(true); doc->Parse(Document::FullParse); } catch (const VExceptionUndo &e) { Q_UNUSED(e) /* If user want undo last operation before undo we need finish broken redo operation. For those we post event * myself. Later in method customEvent call undo.*/ QApplication::postEvent(this, new UndoEvent()); return; } catch (const VExceptionObjectError &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("Error parsing file.")), //-V807 qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } catch (const VExceptionConversionError &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("Error can't convert value.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } catch (const VExceptionEmptyParameter &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("Error empty parameter.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } catch (const VExceptionWrongId &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("Error wrong id.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } catch (VException &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("Error parsing file.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } catch (const std::bad_alloc &) { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Error parsing file (std::bad_alloc)."))); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } QString patternPiece; if (comboBoxDraws->currentIndex() != -1) { patternPiece = comboBoxDraws->itemText(comboBoxDraws->currentIndex()); } comboBoxDraws->blockSignals(true); comboBoxDraws->clear(); comboBoxDraws->addItems(doc->getPatternPieces()); if (not drawMode) { comboBoxDraws->setCurrentIndex(comboBoxDraws->count()-1); } else { const qint32 index = comboBoxDraws->findText(patternPiece); if ( index != -1 ) { comboBoxDraws->setCurrentIndex(index); } } comboBoxDraws->blockSignals(false); ui->actionPattern_properties->setEnabled(true); GlobalChangePP(patternPiece); SetEnableTool(comboBoxDraws->count() > 0); detailsWidget->UpdateList(); VMainGraphicsView::NewSceneRect(sceneDraw, qApp->getSceneView()); VMainGraphicsView::NewSceneRect(sceneDetails, qApp->getSceneView()); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::GlobalChangePP(const QString &patternPiece) { const qint32 index = comboBoxDraws->findText(patternPiece); try { if ( index != -1 ) { // -1 for not found ChangePP(index, false); } else { ChangePP(0, false); } } catch (VExceptionBadId &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("Bad id.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } catch (const VExceptionEmptyParameter &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("Error empty parameter.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); SetEnabledGUI(false); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return; } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::SetEnabledGUI(bool enabled) { if (guiEnabled != enabled) { if (enabled == false) { ArrowTool(); qApp->getUndoStack()->clear(); } SetEnableWidgets(enabled); guiEnabled = enabled; SetEnableTool(enabled); ui->toolBarOption->setEnabled(enabled); #ifndef QT_NO_CURSOR QApplication::setOverrideCursor(Qt::ArrowCursor); #endif } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief SetEnableWidgets enable action button. * @param enable enable value. */ void MainWindow::SetEnableWidgets(bool enable) { const bool drawStage = (mode == Draw::Calculation); const bool designStage = (drawStage || mode == Draw::Modeling); comboBoxDraws->setEnabled(enable && drawStage); ui->actionOptionDraw->setEnabled(enable && drawStage); ui->actionSave->setEnabled(isWindowModified() && enable && not patternReadOnly); ui->actionSaveAs->setEnabled(enable); ui->actionPattern_properties->setEnabled(enable && designStage); ui->actionZoomIn->setEnabled(enable); ui->actionZoomOut->setEnabled(enable); ui->actionArrowTool->setEnabled(enable && designStage); ui->actionHistory->setEnabled(enable && drawStage); ui->actionNewDraw->setEnabled(enable && drawStage); ui->actionDraw->setEnabled(enable); ui->actionDetails->setEnabled(enable); ui->actionLayout->setEnabled(enable); ui->actionTable->setEnabled(enable && drawStage); ui->actionZoomFitBest->setEnabled(enable); ui->actionZoomOriginal->setEnabled(enable); ui->actionShowCurveDetails->setEnabled(enable && drawStage); ui->actionLoadIndividual->setEnabled(enable && designStage); ui->actionLoadStandard->setEnabled(enable && designStage); ui->actionUnloadMeasurements->setEnabled(enable && designStage); actionDockWidgetToolOptions->setEnabled(enable && designStage); actionDockWidgetGroups->setEnabled(enable && designStage); undoAction->setEnabled(enable && designStage && qApp->getUndoStack()->canUndo()); redoAction->setEnabled(enable && designStage && qApp->getUndoStack()->canRedo()); //Now we don't want allow user call context menu sceneDraw->SetDisableTools(!enable, doc->GetNameActivPP()); ui->view->setEnabled(enable); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::UpdateHeightsList(const QStringList &list) { QString val; if (gradationHeights->currentIndex() != -1) { val = gradationHeights->currentText(); } gradationHeights->blockSignals(true); gradationHeights->clear(); gradationHeights->addItems(list); gradationHeights->blockSignals(false); int index = gradationHeights->findText(val); if (index != -1) { gradationHeights->setCurrentIndex(index); } else { ChangedHeight(list.at(0)); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::UpdateSizesList(const QStringList &list) { QString val; if (gradationSizes->currentIndex() != -1) { val = gradationSizes->currentText(); } gradationSizes->blockSignals(true); gradationSizes->clear(); gradationSizes->addItems(list); gradationSizes->blockSignals(false); int index = gradationSizes->findText(val); if (index != -1) { gradationSizes->setCurrentIndex(index); } else { ChangedSize(list.at(0)); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief NewPattern create new empty pattern. */ void MainWindow::New() { if (comboBoxDraws->count() == 0) { qCDebug(vMainWindow, "New PP."); QString patternPieceName = tr("Pattern piece %1").arg(comboBoxDraws->count()+1); qCDebug(vMainWindow, "Generated PP name: %s", qUtf8Printable(patternPieceName)); qCDebug(vMainWindow, "First PP"); DialogNewPattern newPattern(pattern, patternPieceName, this); if (newPattern.exec() == QDialog::Accepted) { patternPieceName = newPattern.name(); qApp->setPatternUnit(newPattern.PatternUnit()); qCDebug(vMainWindow, "PP name: %s", qUtf8Printable(patternPieceName)); } else { qCDebug(vMainWindow, "Creation a new pattern was canceled."); return; } //Set scene size to size scene view VMainGraphicsView::NewSceneRect(sceneDraw, ui->view); VMainGraphicsView::NewSceneRect(sceneDetails, ui->view); AddPP(patternPieceName); mouseCoordinate = new QLabel(QString("0, 0 (%1)").arg(doc->UnitsToStr(qApp->patternUnit(), true))); ui->toolBarOption->addWidget(mouseCoordinate); } else { OpenNewValentina(); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief haveChange enable action save if we have unsaved change. */ void MainWindow::PatternChangesWereSaved(bool saved) { if (guiEnabled) { const bool state = doc->IsModified() || !saved; setWindowModified(state); not patternReadOnly ? ui->actionSave->setEnabled(state): ui->actionSave->setEnabled(false); isLayoutStale = true; } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ChangedSize change new size value. * @param text value size. */ void MainWindow::ChangedSize(const QString & text) { const int size = static_cast(pattern->size()); if (UpdateMeasurements(AbsoluteMPath(curFile, doc->MPath()), text.toInt(), static_cast(pattern->height()))) { doc->LiteParseTree(Document::LiteParse); emit sceneDetails->DimensionsChanged(); } else { qCWarning(vMainWindow, "%s", qUtf8Printable(tr("Couldn't update measurements."))); const qint32 index = gradationSizes->findText(QString().setNum(size)); if (index != -1) { gradationSizes->setCurrentIndex(index); } else { qCDebug(vMainWindow, "Couldn't restore size value."); } } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ChangedGrowth change new height value. * @param text value height. */ void MainWindow::ChangedHeight(const QString &text) { const int height = static_cast(pattern->height()); if (UpdateMeasurements(AbsoluteMPath(curFile, doc->MPath()), static_cast(pattern->size()), text.toInt())) { doc->LiteParseTree(Document::LiteParse); emit sceneDetails->DimensionsChanged(); } else { qCWarning(vMainWindow, "%s", qUtf8Printable(tr("Couldn't update measurements."))); const qint32 index = gradationHeights->findText(QString().setNum(height)); if (index != -1) { gradationHeights->setCurrentIndex(index); } else { qCDebug(vMainWindow, "Couldn't restore height value."); } } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::SetDefaultHeight() { const QString defHeight = QString().setNum(doc->GetDefCustomHeight()); int index = gradationHeights->findText(defHeight); if (index != -1) { gradationHeights->setCurrentIndex(index); } else { index = gradationHeights->findText(QString().setNum(pattern->height())); if (index != -1) { gradationHeights->setCurrentIndex(index); } } pattern->SetHeight(gradationHeights->currentText().toInt()); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::SetDefaultSize() { const QString defSize = QString().setNum(doc->GetDefCustomSize()); int index = gradationSizes->findText(defSize); if (index != -1) { gradationSizes->setCurrentIndex(index); } else { index = gradationSizes->findText(QString().setNum(pattern->size())); if (index != -1) { gradationSizes->setCurrentIndex(index); } } pattern->SetSize(gradationSizes->currentText().toInt()); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief SetEnableTool enable button. * @param enable enable value. */ void MainWindow::SetEnableTool(bool enable) { bool drawTools = false; bool modelingTools = false; bool layoutTools = false; switch (mode) { case Draw::Calculation: drawTools = enable; break; case Draw::Modeling: modelingTools = enable; break; case Draw::Layout: layoutTools = enable; break; default: break; } // This check helps to find missed tools Q_STATIC_ASSERT_X(static_cast(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were handled."); //Drawing Tools ui->toolButtonEndLine->setEnabled(drawTools); ui->toolButtonLine->setEnabled(drawTools); ui->toolButtonAlongLine->setEnabled(drawTools); ui->toolButtonShoulderPoint->setEnabled(drawTools); ui->toolButtonNormal->setEnabled(drawTools); ui->toolButtonBisector->setEnabled(drawTools); ui->toolButtonLineIntersect->setEnabled(drawTools); ui->toolButtonSpline->setEnabled(drawTools); ui->toolButtonCubicBezier->setEnabled(drawTools); ui->toolButtonArc->setEnabled(drawTools); ui->toolButtonSplinePath->setEnabled(drawTools); ui->toolButtonCubicBezierPath->setEnabled(drawTools); ui->toolButtonPointOfContact->setEnabled(drawTools); ui->toolButtonNewDetail->setEnabled(drawTools); ui->toolButtonPiecePath->setEnabled(drawTools); ui->toolButtonHeight->setEnabled(drawTools); ui->toolButtonTriangle->setEnabled(drawTools); ui->toolButtonPointOfIntersection->setEnabled(drawTools); ui->toolButtonSplineCutPoint->setEnabled(drawTools); ui->toolButtonSplinePathCutPoint->setEnabled(drawTools); ui->toolButtonArcCutPoint->setEnabled(drawTools); ui->toolButtonLineIntersectAxis->setEnabled(drawTools); ui->toolButtonCurveIntersectAxis->setEnabled(drawTools); ui->toolButtonArcIntersectAxis->setEnabled(drawTools); ui->toolButtonPointOfIntersectionArcs->setEnabled(drawTools); ui->toolButtonIntersectionCurves->setEnabled(drawTools); ui->toolButtonPointOfIntersectionCircles->setEnabled(drawTools); ui->toolButtonPointFromCircleAndTangent->setEnabled(drawTools); ui->toolButtonPointFromArcAndTangent->setEnabled(drawTools); ui->toolButtonArcWithLength->setEnabled(drawTools); ui->toolButtonTrueDarts->setEnabled(drawTools); ui->toolButtonGroup->setEnabled(drawTools); ui->toolButtonRotation->setEnabled(drawTools); ui->toolButtonFlippingByLine->setEnabled(drawTools); ui->toolButtonFlippingByAxis->setEnabled(drawTools); ui->toolButtonMove->setEnabled(drawTools); ui->toolButtonMidpoint->setEnabled(drawTools); ui->toolButtonEllipticalArc->setEnabled(drawTools); ui->actionLast_tool->setEnabled(drawTools); for (auto pointer : toolButtonPointerList) { pointer->setEnabled(drawTools || modelingTools); pointer->setChecked(drawTools || modelingTools); } //Modeling Tools ui->toolButtonUnionDetails->setEnabled(modelingTools); //Layout tools ui->toolButtonLayoutSettings->setEnabled(layoutTools); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::SetLayoutModeActions() { const bool enabled = not scenes.isEmpty(); ui->toolButtonLayoutExportAs->setEnabled(enabled); ui->actionExportAs->setEnabled(enabled); ui->actionPrintPreview->setEnabled(enabled); ui->actionPrintPreviewTiled->setEnabled(enabled); ui->actionSaveAsTiledPDF->setEnabled(enabled); ui->actionPrint->setEnabled(enabled); ui->actionPrintTiled->setEnabled(enabled); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief MinimumScrollBar set scroll bar to minimum. */ void MainWindow::MinimumScrollBar() { QScrollBar *horScrollBar = ui->view->horizontalScrollBar(); horScrollBar->setValue(horScrollBar->minimum()); QScrollBar *verScrollBar = ui->view->verticalScrollBar(); verScrollBar->setValue(verScrollBar->minimum()); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief SavePattern save pattern file. * @param fileName pattern file name. * @return true if all is good. */ bool MainWindow::SavePattern(const QString &fileName, QString &error) { qCDebug(vMainWindow, "Saving pattern file %s.", qUtf8Printable(fileName)); QFileInfo tempInfo(fileName); const QString mPath = AbsoluteMPath(curFile, doc->MPath()); if (not mPath.isEmpty() && curFile != fileName) { doc->SetPath(RelativeMPath(fileName, mPath)); } const bool result = doc->SaveDocument(fileName, error); if (result) { if (tempInfo.suffix() != QLatin1String("autosave")) { setCurrentFile(fileName); helpLabel->setText(tr("File saved")); qCDebug(vMainWindow, "File %s saved.", qUtf8Printable(fileName)); PatternChangesWereSaved(result); } } else { doc->SetPath(mPath); qCDebug(vMainWindow, "Could not save file %s. %s.", qUtf8Printable(fileName), qUtf8Printable(error)); } return result; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief AutoSavePattern start safe saving. */ void MainWindow::AutoSavePattern() { qCDebug(vMainWindow, "Autosaving pattern."); if (curFile.isEmpty() == false && this->isWindowModified() == true) { QString autofile = curFile + autosavePrefix; QString error; SavePattern(autofile, error); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief setCurrentFile the function is called to reset the state of a few variables when a file * is loaded or saved, or when the user starts editing a new file (in which case fileName is empty). * @param fileName file name. */ void MainWindow::setCurrentFile(const QString &fileName) { qCDebug(vMainWindow, "Set current name to \"%s\"", qUtf8Printable(fileName)); curFile = fileName; qApp->getUndoStack()->setClean(); if (not curFile.isEmpty() && VApplication::IsGUIMode()) { qCDebug(vMainWindow, "Updating recent file list."); VSettings *settings = qApp->ValentinaSettings(); QStringList files = settings->GetRecentFileList(); files.removeAll(fileName); files.prepend(fileName); while (files.size() > MaxRecentFiles) { files.removeLast(); } settings->SetRecentFileList(files); UpdateRecentFileActions(); qCDebug(vMainWindow, "Updating restore file list."); QStringList restoreFiles = settings->GetRestoreFileList(); restoreFiles.removeAll(fileName); restoreFiles.prepend(fileName); settings->SetRestoreFileList(restoreFiles); } UpdateWindowTitle(); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ReadSettings read setting for app. */ void MainWindow::ReadSettings() { qCDebug(vMainWindow, "Reading settings."); const VSettings *settings = qApp->ValentinaSettings(); restoreGeometry(settings->GetGeometry()); restoreState(settings->GetWindowState()); restoreState(settings->GetToolbarsState(), APP_VERSION); // Scene antialiasing const bool graphOutputValue = settings->GetGraphicalOutput(); ui->view->setRenderHint(QPainter::Antialiasing, graphOutputValue); ui->view->setRenderHint(QPainter::SmoothPixmapTransform, graphOutputValue); // Stack limit qApp->getUndoStack()->setUndoLimit(settings->GetUndoCount()); // Text under tool buton icon ToolBarStyles(); isDockToolOptionsVisible = ui->dockWidgetToolOptions->isVisible(); isDockGroupsVisible = ui->dockWidgetGroups->isVisible(); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief WriteSettings save setting for app. */ void MainWindow::WriteSettings() { ActionDraw(true); VSettings *setings = qApp->ValentinaSettings(); setings->SetGeometry(saveGeometry()); setings->SetWindowState(saveState()); setings->SetToolbarsState(saveState(APP_VERSION)); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief MaybeSave The function is called to save pending changes. * @return returns true in all cases, except when the user clicks Cancel. */ bool MainWindow::MaybeSave() { if (this->isWindowModified() && guiEnabled) { QMessageBox *messageBox = new QMessageBox(tr("Unsaved changes"), tr("The pattern has been modified.\n" "Do you want to save your changes?"), QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel, this, Qt::Sheet); messageBox->setDefaultButton(QMessageBox::Yes); messageBox->setEscapeButton(QMessageBox::Cancel); messageBox->setButtonText(QMessageBox::Yes, curFile.isEmpty() || patternReadOnly ? tr("Save...") : tr("Save")); messageBox->setButtonText(QMessageBox::No, tr("Don't Save")); messageBox->setWindowModality(Qt::ApplicationModal); const auto ret = static_cast(messageBox->exec()); switch (ret) { case QMessageBox::Yes: if (patternReadOnly) { return SaveAs(); } else { return Save(); } case QMessageBox::No: return true; case QMessageBox::Cancel: return false; default: break; } } return true; } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::UpdateRecentFileActions() { qCDebug(vMainWindow, "Updating recent file actions."); const QStringList files = qApp->ValentinaSettings()->GetRecentFileList(); const int numRecentFiles = qMin(files.size(), static_cast(MaxRecentFiles)); for (int i = 0; i < numRecentFiles; ++i) { QString text = QString("&%1. %2").arg(i + 1).arg(StrippedName(files.at(i))); recentFileActs[i]->setText(text); recentFileActs[i]->setData(files.at(i)); recentFileActs[i]->setVisible(true); } for (int j = numRecentFiles; j < MaxRecentFiles; ++j) { recentFileActs[j]->setVisible(false); } separatorAct->setVisible(numRecentFiles > 0); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::CreateMenus() { for (int i = 0; i < MaxRecentFiles; ++i) { ui->menuFile->insertAction(ui->actionPreferences, recentFileActs[i]); } separatorAct = new QAction(this); separatorAct->setSeparator(true); ui->menuFile->insertAction(ui->actionPreferences, separatorAct); UpdateRecentFileActions(); //Add Undo/Redo actions. undoAction = qApp->getUndoStack()->createUndoAction(this, tr("&Undo")); connect(undoAction, &QAction::triggered, toolOptions, &VToolOptionsPropertyBrowser::RefreshOptions); undoAction->setShortcuts(QKeySequence::Undo); undoAction->setIcon(QIcon::fromTheme("edit-undo")); ui->menuPatternPiece->insertAction(ui->actionLast_tool, undoAction); ui->toolBarTools->addAction(undoAction); redoAction = qApp->getUndoStack()->createRedoAction(this, tr("&Redo")); connect(redoAction, &QAction::triggered, toolOptions, &VToolOptionsPropertyBrowser::RefreshOptions); redoAction->setShortcuts(QKeySequence::Redo); redoAction->setIcon(QIcon::fromTheme("edit-redo")); ui->menuPatternPiece->insertAction(ui->actionLast_tool, redoAction); ui->toolBarTools->addAction(redoAction); separatorAct = new QAction(this); separatorAct->setSeparator(true); ui->menuPatternPiece->insertAction(ui->actionPattern_properties, separatorAct); AddDocks(); } //--------------------------------------------------------------------------------------------------------------------- QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wswitch-default") void MainWindow::LastUsedTool() { // This check helps to find missed tools in the switch Q_STATIC_ASSERT_X(static_cast(Tool::LAST_ONE_DO_NOT_USE) == 51, "Not all tools were handled."); if (currentTool == lastUsedTool) { return; } switch ( lastUsedTool ) { case Tool::Arrow: for (auto pointer : toolButtonPointerList) { pointer->setChecked(true); } ArrowTool(); break; case Tool::BasePoint: case Tool::SinglePoint: case Tool::DoublePoint: case Tool::LinePoint: case Tool::AbstractSpline: case Tool::Cut: case Tool::LAST_ONE_DO_NOT_USE: case Tool::NodePoint: case Tool::NodeArc: case Tool::NodeElArc: case Tool::NodeSpline: case Tool::NodeSplinePath: Q_UNREACHABLE(); //-V501 //Nothing to do here because we can't create this tool from main window. break; case Tool::EndLine: ui->toolButtonEndLine->setChecked(true); ToolEndLine(true); break; case Tool::Line: ui->toolButtonLine->setChecked(true); ToolLine(true); break; case Tool::AlongLine: ui->toolButtonAlongLine->setChecked(true); ToolAlongLine(true); break; case Tool::Midpoint: ui->toolButtonMidpoint->setChecked(true); ToolMidpoint(true); break; case Tool::ShoulderPoint: ui->toolButtonShoulderPoint->setChecked(true); ToolShoulderPoint(true); break; case Tool::Normal: ui->toolButtonNormal->setChecked(true); ToolNormal(true); break; case Tool::Bisector: ui->toolButtonBisector->setChecked(true); ToolBisector(true); break; case Tool::LineIntersect: ui->toolButtonLineIntersect->setChecked(true); ToolLineIntersect(true); break; case Tool::Spline: ui->toolButtonSpline->setChecked(true); ToolSpline(true); break; case Tool::CubicBezier: ui->toolButtonCubicBezier->setChecked(true); ToolCubicBezier(true); break; case Tool::Arc: ui->toolButtonArc->setChecked(true); ToolArc(true); break; case Tool::SplinePath: ui->toolButtonSplinePath->setChecked(true); ToolSplinePath(true); break; case Tool::CubicBezierPath: ui->toolButtonCubicBezierPath->setChecked(true); ToolCubicBezierPath(true); break; case Tool::PointOfContact: ui->toolButtonPointOfContact->setChecked(true); ToolPointOfContact(true); break; case Tool::Piece: ui->toolButtonNewDetail->setChecked(true); ToolDetail(true); break; case Tool::PiecePath: ui->toolButtonPiecePath->setChecked(true); ToolPiecePath(true); break; case Tool::Height: ui->toolButtonHeight->setChecked(true); ToolHeight(true); break; case Tool::Triangle: ui->toolButtonTriangle->setChecked(true); ToolTriangle(true); break; case Tool::PointOfIntersection: ui->toolButtonPointOfIntersection->setChecked(true); ToolPointOfIntersection(true); break; case Tool::PointOfIntersectionArcs: ui->toolButtonPointOfIntersectionArcs->setChecked(true); ToolPointOfIntersectionArcs(true); break; case Tool::CutSpline: ui->toolButtonSplineCutPoint->setChecked(true); ToolCutSpline(true); break; case Tool::CutSplinePath: ui->toolButtonSplinePathCutPoint->setChecked(true); ToolCutSplinePath(true); break; case Tool::UnionDetails: ui->toolButtonUnionDetails->setChecked(true); ToolUnionDetails(true); break; case Tool::CutArc: ui->toolButtonArcCutPoint->setChecked(true); ToolCutArc(true); break; case Tool::LineIntersectAxis: ui->toolButtonLineIntersectAxis->setChecked(true); ToolLineIntersectAxis(true); break; case Tool::CurveIntersectAxis: ui->toolButtonCurveIntersectAxis->setChecked(true); ToolCurveIntersectAxis(true); break; case Tool::ArcIntersectAxis: ui->toolButtonArcIntersectAxis->setChecked(true); ToolArcIntersectAxis(true); break; case Tool::PointOfIntersectionCircles: ui->toolButtonPointOfIntersectionCircles->setChecked(true); ToolPointOfIntersectionCircles(true); break; case Tool::PointOfIntersectionCurves: ui->toolButtonIntersectionCurves->setChecked(true); ToolPointOfIntersectionCurves(true); break; case Tool::PointFromCircleAndTangent: ui->toolButtonPointFromCircleAndTangent->setChecked(true); ToolPointFromCircleAndTangent(true); break; case Tool::PointFromArcAndTangent: ui->toolButtonPointFromArcAndTangent->setChecked(true); ToolPointFromArcAndTangent(true); break; case Tool::ArcWithLength: ui->toolButtonArcWithLength->setChecked(true); ToolArcWithLength(true); break; case Tool::TrueDarts: ui->toolButtonTrueDarts->setChecked(true); ToolTrueDarts(true); break; case Tool::Group: ui->toolButtonGroup->setChecked(true); ToolGroup(true); break; case Tool::Rotation: ui->toolButtonRotation->setChecked(true); ToolRotation(true); break; case Tool::FlippingByLine: ui->toolButtonFlippingByLine->setChecked(true); ToolFlippingByLine(true); break; case Tool::FlippingByAxis: ui->toolButtonFlippingByAxis->setChecked(true); ToolFlippingByAxis(true); break; case Tool::Move: ui->toolButtonMove->setChecked(true); ToolMove(true); break; case Tool::EllipticalArc: ui->toolButtonEllipticalArc->setChecked(true); ToolEllipticalArc(true); break; } } QT_WARNING_POP //--------------------------------------------------------------------------------------------------------------------- void MainWindow::AddDocks() { //Add dock actionDockWidgetToolOptions = ui->dockWidgetToolOptions->toggleViewAction(); ui->menuPatternPiece->insertAction(ui->actionPattern_properties, actionDockWidgetToolOptions); connect(ui->dockWidgetToolOptions, &QDockWidget::visibilityChanged, RECEIVER(this)[this](bool visible) { isDockToolOptionsVisible = visible; }); actionDockWidgetGroups = ui->dockWidgetGroups->toggleViewAction(); ui->menuPatternPiece->insertAction(ui->actionPattern_properties, actionDockWidgetGroups); connect(ui->dockWidgetGroups, &QDockWidget::visibilityChanged, RECEIVER(this)[this](bool visible) { isDockGroupsVisible = visible; }); separatorAct = new QAction(this); separatorAct->setSeparator(true); ui->menuPatternPiece->insertAction(ui->actionPattern_properties, separatorAct); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::InitDocksContain() { qCDebug(vMainWindow, "Initialization property browser."); toolOptions = new VToolOptionsPropertyBrowser(ui->dockWidgetToolOptions); connect(ui->view, &VMainGraphicsView::itemClicked, toolOptions, &VToolOptionsPropertyBrowser::itemClicked); connect(doc, &VPattern::FullUpdateFromFile, toolOptions, &VToolOptionsPropertyBrowser::UpdateOptions); qCDebug(vMainWindow, "Initialization groups dock."); groupsWidget = new VWidgetGroups(doc, this); ui->dockWidgetGroups->setWidget(groupsWidget); detailsWidget = new VWidgetDetails(pattern, doc, this); connect(doc, &VPattern::FullUpdateFromFile, detailsWidget, &VWidgetDetails::UpdateList); connect(doc, &VPattern::UpdateInLayoutList, detailsWidget, &VWidgetDetails::UpdateList); connect(doc, &VPattern::ShowDetail, detailsWidget, &VWidgetDetails::SelectDetail); connect(detailsWidget, &VWidgetDetails::Highlight, sceneDetails, &VMainGraphicsScene::HighlightItem); detailsWidget->setVisible(false); } //--------------------------------------------------------------------------------------------------------------------- bool MainWindow::OpenNewValentina(const QString &fileName) const { if (this->isWindowModified() || curFile.isEmpty() == false) { VApplication::NewValentina(fileName); return true; } return false; } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::CreateActions() { ui->setupUi(this); connect(ui->actionArrowTool, &QAction::triggered, this, &MainWindow::ArrowTool); connect(ui->actionDraw, &QAction::triggered, this, &MainWindow::ActionDraw); connect(ui->actionDetails, &QAction::triggered, this, &MainWindow::ActionDetails); connect(ui->actionLayout, &QAction::triggered, this, &MainWindow::ActionLayout); connect(ui->actionHistory, &QAction::triggered, RECEIVER(this)[this](bool checked) { if (checked) { dialogHistory = new DialogHistory(pattern, doc, this); dialogHistory->setWindowFlags(Qt::Window); connect(this, &MainWindow::RefreshHistory, dialogHistory.data(), &DialogHistory::UpdateHistory); connect(dialogHistory.data(), &DialogHistory::DialogClosed, RECEIVER(this)[this]() { ui->actionHistory->setChecked(false); delete dialogHistory; }); // Fix issue #526. Dialog Detail is not on top after selection second object on Mac. dialogHistory->setWindowFlags(dialogHistory->windowFlags() | Qt::WindowStaysOnTopHint); dialogHistory->show(); } else { ui->actionHistory->setChecked(true); dialogHistory->activateWindow(); } }); connect(ui->actionNewDraw, &QAction::triggered, RECEIVER(this)[this]() { qCDebug(vMainWindow, "New PP."); QString patternPieceName = tr("Pattern piece %1").arg(comboBoxDraws->count()+1); qCDebug(vMainWindow, "Generated PP name: %s", qUtf8Printable(patternPieceName)); qCDebug(vMainWindow, "PP count %d", comboBoxDraws->count()); patternPieceName = PatternPieceName(patternPieceName); qCDebug(vMainWindow, "PP name: %s", qUtf8Printable(patternPieceName)); if (patternPieceName.isEmpty()) { qCDebug(vMainWindow, "Name empty."); return; } AddPP(patternPieceName); }); connect(ui->actionSaveAs, &QAction::triggered, this, &MainWindow::SaveAs); connect(ui->actionSave, &QAction::triggered, this, &MainWindow::Save); connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::Open); connect(ui->actionNew, &QAction::triggered, this, &MainWindow::New); connect(ui->actionTable, &QAction::triggered, RECEIVER(this)[this](bool checked) { if (checked) { dialogTable = new DialogIncrements(pattern, doc, this); connect(dialogTable.data(), &DialogIncrements::DialogClosed, RECEIVER(this)[this]() { ui->actionTable->setChecked(false); delete dialogTable; }); dialogTable->show(); } else { ui->actionTable->setChecked(true); dialogTable->activateWindow(); } }); connect(ui->actionAbout_Qt, &QAction::triggered, RECEIVER(this)[this]() { QMessageBox::aboutQt(this, tr("About Qt")); }); connect(ui->actionAbout_Valentina, &QAction::triggered, RECEIVER(this)[this]() { DialogAboutApp *aboutDialog = new DialogAboutApp(this); aboutDialog->setAttribute(Qt::WA_DeleteOnClose, true); aboutDialog->show(); }); connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); connect(ui->actionPreferences, &QAction::triggered, this, &MainWindow::Preferences); connect(ui->actionReportBug, &QAction::triggered, RECEIVER(this)[this]() { qCDebug(vMainWindow, "Reporting bug"); QDesktopServices::openUrl(QUrl(QStringLiteral("https://bitbucket.org/dismine/valentina/issues/new"))); }); connect(ui->actionOnlineHelp, &QAction::triggered, RECEIVER(this)[this]() { qCDebug(vMainWindow, "Showing online help"); QDesktopServices::openUrl(QUrl(QStringLiteral("https://bitbucket.org/dismine/valentina/wiki/manual/Content"))); }); connect(ui->actionLast_tool, &QAction::triggered, this, &MainWindow::LastUsedTool); connect(ui->actionPattern_properties, &QAction::triggered, RECEIVER(this)[this]() { DialogPatternProperties proper(curFile, doc, pattern, this); connect(&proper, &DialogPatternProperties::UpdateGradation, RECEIVER(this)[this]() { UpdateHeightsList(VMeasurement::ListHeights(doc->GetGradationHeights(), qApp->patternUnit())); UpdateSizesList(VMeasurement::ListSizes(doc->GetGradationSizes(), qApp->patternUnit())); }); proper.exec(); }); ui->actionPattern_properties->setEnabled(false); connect(ui->actionClosePattern, &QAction::triggered, RECEIVER(this)[this]() { if (MaybeSave()) { FileClosedCorrect(); Clear(); } }); connect(ui->actionShowCurveDetails, &QAction::triggered, RECEIVER(this)[this](bool checked) { ui->view->itemClicked(nullptr); sceneDraw->EnableDetailsMode(checked); }); connect(ui->actionLoadIndividual, &QAction::triggered, this, &MainWindow::LoadIndividual); connect(ui->actionLoadStandard, &QAction::triggered, this, &MainWindow::LoadStandard); connect(ui->actionCreateNew, &QAction::triggered, RECEIVER(this)[this]() { const QString tape = qApp->TapeFilePath(); const QString workingDirectory = QFileInfo(tape).absoluteDir().absolutePath(); QStringList arguments; if (isNoScaling) { arguments.append(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING); } QProcess::startDetached(tape, arguments, workingDirectory); }); connect(ui->actionShowM, &QAction::triggered, this, &MainWindow::ShowMeasurements); connect(ui->actionExportAs, &QAction::triggered, this, &MainWindow::ExportLayoutAs); connect(ui->actionPrintPreview, &QAction::triggered, this, &MainWindow::PrintPreviewOrigin); connect(ui->actionPrintPreviewTiled, &QAction::triggered, this, &MainWindow::PrintPreviewTiled); connect(ui->actionSaveAsTiledPDF, &QAction::triggered, this, &MainWindow::SaveAsTiledPDF); connect(ui->actionPrint, &QAction::triggered, this, &MainWindow::PrintOrigin); connect(ui->actionPrintTiled, &QAction::triggered, this, &MainWindow::PrintTiled); //Actions for recent files loaded by a main window application. for (int i = 0; i < MaxRecentFiles; ++i) { QAction *action = new QAction(this); action->setVisible(false); recentFileActs[i] = action; connect(recentFileActs[i], &QAction::triggered, RECEIVER(this)[action, this]() { if (action != nullptr) { const QString filePath = action->data().toString(); if (not filePath.isEmpty()) { LoadPattern(filePath); } } }); } connect(ui->actionSyncMeasurements, &QAction::triggered, this, &MainWindow::SyncMeasurements); connect(ui->actionUnloadMeasurements, &QAction::triggered, this, &MainWindow::UnloadMeasurements); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::InitAutoSave() { //Autosaving file each 1 minutes delete autoSaveTimer; autoSaveTimer = nullptr; autoSaveTimer = new QTimer(this); autoSaveTimer->setTimerType(Qt::VeryCoarseTimer); connect(autoSaveTimer, &QTimer::timeout, this, &MainWindow::AutoSavePattern); autoSaveTimer->stop(); if (qApp->ValentinaSettings()->GetAutosaveState()) { const qint32 autoTime = qApp->ValentinaSettings()->GetAutosaveTime(); autoSaveTimer->start(autoTime*60000); qCDebug(vMainWindow, "Autosaving each %d minutes.", autoTime); } qApp->setAutoSaveTimer(autoSaveTimer); } //--------------------------------------------------------------------------------------------------------------------- QString MainWindow::PatternPieceName(const QString &text) { QInputDialog *dlg = new QInputDialog(this); dlg->setInputMode( QInputDialog::TextInput ); dlg->setLabelText(tr("Pattern piece:")); dlg->setTextEchoMode(QLineEdit::Normal); dlg->setWindowTitle(tr("Enter a new label for the pattern piece.")); dlg->resize(300, 100); dlg->setTextValue(text); QString nameDraw; while (1) { const bool bOk = dlg->exec(); nameDraw = dlg->textValue(); if (bOk == false || nameDraw.isEmpty()) { delete dlg; return QString(); } if (comboBoxDraws->findText(nameDraw) == -1) { break;//repeate show dialog } } delete dlg; return nameDraw; } //--------------------------------------------------------------------------------------------------------------------- MainWindow::~MainWindow() { CancelTool(); CleanLayout(); delete doc; delete ui; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief LoadPattern open pattern file. * @param fileName name of file. */ bool MainWindow::LoadPattern(const QString &fileName, const QString& customMeasureFile) { qCDebug(vMainWindow, "Loading new file %s.", qUtf8Printable(fileName)); //We have unsaved changes or load more then one file per time if (OpenNewValentina(fileName)) { return false; } if (fileName.isEmpty()) { qCDebug(vMainWindow, "Got empty file."); Clear(); return false; } try { // Here comes undocumented Valentina's feature. // Because app bundle in Mac OS X doesn't allow setup assosiation for Tape we must do this through Valentina VMeasurements m(pattern); m.setXMLContent(fileName); if (m.Type() == MeasurementsType::Standard || m.Type() == MeasurementsType::Individual) { const QString tape = qApp->TapeFilePath(); const QString workingDirectory = QFileInfo(tape).absoluteDir().absolutePath(); QStringList arguments = QStringList() << fileName; if (isNoScaling) { arguments.append(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING); } QProcess::startDetached(tape, arguments, workingDirectory); qApp->exit(V_EX_OK); return false; // stop continue processing } } catch (VException &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); Clear(); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return false; } qCDebug(vMainWindow, "Loking file"); VlpCreateLock(lock, fileName); if (lock->IsLocked()) { qCDebug(vMainWindow, "Pattern file %s was locked.", qUtf8Printable(fileName)); } else { if (not IgnoreLocking(lock->GetLockError(), fileName)) { return false; } } // On this stage scene empty. Fit scene size to view size VMainGraphicsView::NewSceneRect(sceneDraw, ui->view); VMainGraphicsView::NewSceneRect(sceneDetails, ui->view); qApp->setOpeningPattern();//Begin opening file try { VPatternConverter converter(fileName); doc->setXMLContent(converter.Convert()); if (!customMeasureFile.isEmpty()) { doc->SetPath(RelativeMPath(fileName, customMeasureFile)); } qApp->setPatternUnit(doc->MUnit()); const QString path = AbsoluteMPath(fileName, doc->MPath()); if (not path.isEmpty()) { // Check if exist const QString newPath = CheckPathToMeasurements(fileName, path); if (newPath.isEmpty()) { qApp->setOpeningPattern();// End opening file Clear(); qCCritical(vMainWindow, "%s", qUtf8Printable(tr("The measurements file '%1' could not be found.") .arg(path))); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return false; } if (not LoadMeasurements(newPath)) { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("The measurements file '%1' could not be found.") .arg(newPath))); qApp->setOpeningPattern();// End opening file Clear(); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return false; } else { ui->actionUnloadMeasurements->setEnabled(true); watcher->addPath(path); ui->actionShowM->setEnabled(true); } } if (qApp->patternType() == MeasurementsType::Unknown) {// Show toolbar only if was not uploaded any measurements. ToolBarOption(); } } catch (VException &e) { qCCritical(vMainWindow, "%s\n\n%s\n\n%s", qUtf8Printable(tr("File error.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); qApp->setOpeningPattern();// End opening file Clear(); if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_NOINPUT); } return false; } FullParseFile(); if (guiEnabled) { // No errors occurred patternReadOnly = doc->IsReadOnly(); SetEnableWidgets(true); setCurrentFile(fileName); helpLabel->setText(tr("File loaded")); qCDebug(vMainWindow, "File loaded."); //Fit scene size to best size for first show ZoomFirstShow(); ActionDraw(true); qApp->setOpeningPattern();// End opening file return true; } else { qApp->setOpeningPattern();// End opening file return false; } } //--------------------------------------------------------------------------------------------------------------------- QStringList MainWindow::GetUnlokedRestoreFileList() const { #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) QStringList restoreFiles; //Take all files that need to be restored QStringList files = qApp->ValentinaSettings()->GetRestoreFileList(); if (files.size() > 0) { for (int i = 0; i < files.size(); ++i) { // Seeking file that realy need reopen VLockGuard tmp(files.at(i)); if (tmp.IsLocked()) { restoreFiles.append(files.at(i)); } } // Clearing list after filtering for (int i = 0; i < restoreFiles.size(); ++i) { files.removeAll(restoreFiles.at(i)); } // Clear all files that do not exist. QStringList filtered; for (int i = 0; i < files.size(); ++i) { if (QFileInfo(files.at(i)).exists()) { filtered.append(files.at(i)); } } qApp->ValentinaSettings()->SetRestoreFileList(filtered); } return restoreFiles; #else return qApp->ValentinaSettings()->GetRestoreFileList(); #endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::WindowsLocale() { qApp->ValentinaSettings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c()); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolBarStyles() { ToolBarStyle(ui->toolBarDraws); ToolBarStyle(ui->toolBarOption); ToolBarStyle(ui->toolBarStages); ToolBarStyle(ui->toolBarTools); ToolBarStyle(ui->mainToolBar); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ShowPaper(int index) { if (index < 0 || index >= scenes.size()) { ui->view->setScene(tempSceneLayout); } else { ui->view->setScene(scenes.at(index)); } ui->view->fitInView(ui->view->scene()->sceneRect(), Qt::KeepAspectRatio); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::Preferences() { // Calling constructor of the dialog take some time. Because of this user have time to call the dialog twice. static QPointer guard;// Prevent any second run if (guard.isNull()) { ConfigDialog *config = new ConfigDialog(this); // QScopedPointer needs to be sure any exception will never block guard QScopedPointer dlg(config); guard = config; connect(dlg.data(), &ConfigDialog::UpdateProperties, this, &MainWindow::WindowsLocale); // Must be first connect(dlg.data(), &ConfigDialog::UpdateProperties, toolOptions, &VToolOptionsPropertyBrowser::RefreshOptions); connect(dlg.data(), &ConfigDialog::UpdateProperties, this, &MainWindow::ToolBarStyles); if (guard->exec() == QDialog::Accepted) { InitAutoSave(); } } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::CreateMeasurements() { const QString tape = qApp->TapeFilePath(); const QString workingDirectory = QFileInfo(tape).absoluteDir().absolutePath(); QStringList arguments; if (isNoScaling) { arguments.append(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING); } QProcess::startDetached(tape, arguments, workingDirectory); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ExportLayoutAs() { if (isLayoutStale) { if (ContinueIfLayoutStale() == QMessageBox::No) { ui->toolButtonLayoutExportAs->setChecked(false); return; } } try { DialogSaveLayout dialog(scenes.size(), FileName(), this); if (dialog.exec() == QDialog::Rejected) { ui->toolButtonLayoutExportAs->setChecked(false); return; } ExportLayout(dialog); } catch (const VException &e) { ui->toolButtonLayoutExportAs->setChecked(false); qCritical("%s\n\n%s\n\n%s", qUtf8Printable(tr("Export error.")), qUtf8Printable(e.ErrorMessage()), qUtf8Printable(e.DetailedInformation())); return; } ui->toolButtonLayoutExportAs->setChecked(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolBarStyle(QToolBar *bar) { if (qApp->ValentinaSettings()->GetToolBarStyle()) { bar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); } else { bar->setToolButtonStyle(Qt::ToolButtonIconOnly); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ReopenFilesAfterCrash(QStringList &args) { const QStringList files = GetUnlokedRestoreFileList(); if (files.size() > 0) { qCDebug(vMainWindow, "Reopen files after crash."); QStringList restoreFiles; for (int i = 0; i < files.size(); ++i) { QFile file(files.at(i) + autosavePrefix); if (file.exists()) { restoreFiles.append(files.at(i)); } } if (restoreFiles.size() > 0) { QMessageBox::StandardButton reply; const QString mes = tr("Valentina didn't shut down correctly. Do you want reopen files (%1) you had open?") .arg(restoreFiles.size()); reply = QMessageBox::question(this, tr("Reopen files."), mes, QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes); if (reply == QMessageBox::Yes) { qCDebug(vMainWindow, "User said Yes."); for (int i = 0; i < restoreFiles.size(); ++i) { QString error; if (VDomDocument::SafeCopy(restoreFiles.at(i) + autosavePrefix, restoreFiles.at(i), error)) { QFile autoFile(restoreFiles.at(i) + autosavePrefix); autoFile.remove(); LoadPattern(restoreFiles.at(i)); args.removeAll(restoreFiles.at(i));// Do not open file twice after we restore him. } else { qCDebug(vMainWindow, "Could not copy %s%s to %s %s", qUtf8Printable(restoreFiles.at(i)), qUtf8Printable(autosavePrefix), qUtf8Printable(restoreFiles.at(i)), qUtf8Printable(error)); } } } } } } //--------------------------------------------------------------------------------------------------------------------- QString MainWindow::CheckPathToMeasurements(const QString &patternPath, const QString &path) { if (path.isEmpty()) { return path; } QFileInfo table(path); if (table.exists() == false) { if (!qApp->IsGUIMode()) { return QString();// console mode doesn't support fixing path to a measurement file } else { const QString text = tr("The measurements file

%1

could not be found. Do you " "want to update the file location?").arg(path); QMessageBox::StandardButton res = QMessageBox::question(this, tr("Loading measurements file"), text, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if (res == QMessageBox::No) { return QString(); } else { MeasurementsType patternType; if (table.suffix() == QLatin1String("vst")) { patternType = MeasurementsType::Standard; } else if (table.suffix() == QLatin1String("vit")) { patternType = MeasurementsType::Individual; } else { patternType = MeasurementsType::Unknown; } QString mPath; if (patternType == MeasurementsType::Standard) { const QString filter = tr("Standard measurements (*.vst)"); //Use standard path to standard measurements const QString path = qApp->ValentinaSettings()->GetPathStandardMeasurements(); mPath = QFileDialog::getOpenFileName(this, tr("Open file"), path, filter); } else if (patternType == MeasurementsType::Individual) { const QString filter = tr("Individual measurements (*.vit)"); //Use standard path to individual measurements const QString path = qApp->ValentinaSettings()->GetPathIndividualMeasurements(); mPath = QFileDialog::getOpenFileName(this, tr("Open file"), path, filter); } else { const QString filter = tr("Individual measurements (*.vit);;Standard measurements (*.vst)"); //Use standard path to individual measurements const QString path = qApp->ValentinaSettings()->GetPathIndividualMeasurements(); mPath = QFileDialog::getOpenFileName(this, tr("Open file"), path, filter); } if (mPath.isEmpty()) { return mPath; } else { QScopedPointer m(new VMeasurements(pattern)); m->setXMLContent(mPath); patternType = m->Type(); if (patternType == MeasurementsType::Unknown) { VException e(tr("Measurement file has unknown format.")); throw e; } if (patternType == MeasurementsType::Standard) { VVSTConverter converter(mPath); m->setXMLContent(converter.Convert());// Read again after conversion } else { VVITConverter converter(mPath); m->setXMLContent(converter.Convert());// Read again after conversion } if (not m->IsDefinedKnownNamesValid()) { VException e(tr("Measurement file contains invalid known measurement(s).")); throw e; } CheckRequiredMeasurements(m.data()); doc->SetPath(RelativeMPath(patternPath, mPath)); PatternChangesWereSaved(false); qApp->setPatternType(patternType); return mPath; } } } } return path; } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ChangePP(int index, bool zoomBestFit) { if (index != -1) { doc->ChangeActivPP(comboBoxDraws->itemText(index)); doc->setCurrentData(); emit RefreshHistory(); if (drawMode) { ArrowTool(); if (zoomBestFit) { ui->view->fitInView(doc->ActiveDrawBoundingRect(), Qt::KeepAspectRatio); ui->view->NewFactor(ui->view->transform().m11()); } } toolOptions->itemClicked(nullptr);//hide options for tool in previous pattern piece groupsWidget->UpdateGroups(); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::EndVisualization(bool click) { if (not dialogTool.isNull()) { dialogTool->ShowDialog(click); } } //--------------------------------------------------------------------------------------------------------------------- /** * @brief ZoomFirstShow Fit scene size to best size for first show */ void MainWindow::ZoomFirstShow() { /* If don't call ZoomFitBest() twice, after first scaling or moving pattern piece, scene change coordinate and whole * pattern will be moved. Looks very ugly. It is best solution that i have now. */ if (pattern->DataPieces()->size() > 0) { ActionDetails(true); ui->view->ZoomFitBest(); } if (not ui->actionDraw->isChecked()) { ActionDraw(true); } ui->view->ZoomFitBest(); VMainGraphicsView::NewSceneRect(sceneDraw, ui->view); VMainGraphicsView::NewSceneRect(sceneDetails, ui->view); if (pattern->DataPieces()->size() > 0) { ActionDetails(true); ui->view->ZoomFitBest(); } if (not ui->actionDraw->isChecked()) { ActionDraw(true); } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::DoExport(const VCommandLinePtr &expParams) { auto settings = expParams->DefaultGenerator(); const QHash *details = pattern->DataPieces(); if(not qApp->getOpeningPattern()) { if (details->count() == 0) { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("You can't export empty scene."))); qApp->exit(V_EX_DATAERR); return; } } PrepareDetailsForLayout(details); if (LayoutSettings(*settings.get())) { try { DialogSaveLayout dialog(scenes.size(), expParams->OptBaseName(), this); dialog.SetDestinationPath(expParams->OptDestinationPath()); dialog.SelectFormate(expParams->OptExportType()); ExportLayout(dialog); } catch (const VException &e) { qCCritical(vMainWindow, "%s\n\n%s", qUtf8Printable(tr("Export error.")), qUtf8Printable(e.ErrorMessage())); qApp->exit(V_EX_DATAERR); return; } } else { return; } qApp->exit(V_EX_OK); } //--------------------------------------------------------------------------------------------------------------------- bool MainWindow::SetSize(const QString &text) { if (not qApp->IsGUIMode()) { if (this->isWindowModified() || not curFile.isEmpty()) { if (qApp->patternType() == MeasurementsType::Standard) { const int size = static_cast(UnitConvertor(text.toInt(), Unit::Cm, *pattern->GetPatternUnit())); const qint32 index = gradationSizes->findText(QString().setNum(size)); if (index != -1) { gradationSizes->setCurrentIndex(index); } else { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Not supported size value '%1' for this pattern file.").arg(text))); return false; } } else { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Couldn't set size. Need a file with standard measurements."))); return false; } } else { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Couldn't set size. File wasn't opened."))); return false; } } else { qCWarning(vMainWindow, "%s", qUtf8Printable(tr("The method %1 does nothing in GUI mode").arg(Q_FUNC_INFO))); return false; } return true; } //--------------------------------------------------------------------------------------------------------------------- bool MainWindow::SetHeight(const QString &text) { if (not qApp->IsGUIMode()) { if (this->isWindowModified() || not curFile.isEmpty()) { if (qApp->patternType() == MeasurementsType::Standard) { const int height = static_cast(UnitConvertor(text.toInt(), Unit::Cm, *pattern->GetPatternUnit())); const qint32 index = gradationHeights->findText(QString().setNum(height)); if (index != -1) { gradationHeights->setCurrentIndex(index); } else { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Not supported height value '%1' for this pattern file.").arg(text))); return false; } } else { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Couldn't set height. Need a file with standard measurements."))); return false; } } else { qCCritical(vMainWindow, "%s", qUtf8Printable(tr("Couldn't set height. File wasn't opened."))); return false; } } else { qCWarning(vMainWindow, "%s", qUtf8Printable(tr("The method %1 does nothing in GUI mode").arg(Q_FUNC_INFO))); return false; } return true; } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ProcessCMD() { const VCommandLinePtr cmd = qApp->CommandLine(); auto args = cmd->OptInputFileNames(); isNoScaling = cmd->IsNoScalingEnabled(); if (VApplication::IsGUIMode()) { ReopenFilesAfterCrash(args); } else { if (args.size() != 1) { qCritical() << tr("Please, provide one input file."); qApp->exit(V_EX_NOINPUT); return; } } for (int i=0, sz = args.size(); i < sz; ++i) { const bool loaded = LoadPattern(args.at(static_cast(i)), cmd->OptMeasurePath()); if (not loaded && not VApplication::IsGUIMode()) { return; // process only one input file } bool hSetted = true; bool sSetted = true; if (loaded && (cmd->IsTestModeEnabled() || cmd->IsExportEnabled())) { if (cmd->IsSetGradationSize()) { sSetted = SetSize(cmd->OptGradationSize()); } if (cmd->IsSetGradationHeight()) { hSetted = SetHeight(cmd->OptGradationHeight()); } } if (not cmd->IsTestModeEnabled()) { if (cmd->IsExportEnabled()) { if (loaded && hSetted && sSetted) { DoExport(cmd); return; // process only one input file } else { qApp->exit(V_EX_DATAERR); return; } break; } } } if (not VApplication::IsGUIMode()) { qApp->exit(V_EX_OK);// close program after processing in console mode } } //--------------------------------------------------------------------------------------------------------------------- QString MainWindow::GetPatternFileName() { QString shownName = tr("untitled.val"); if(not curFile.isEmpty()) { shownName = StrippedName(curFile); } shownName += QLatin1String("[*]"); return shownName; } //--------------------------------------------------------------------------------------------------------------------- QString MainWindow::GetMeasurementFileName() { if(doc->MPath().isEmpty()) { return ""; } else { QString shownName(" ["); shownName += StrippedName(AbsoluteMPath(curFile, doc->MPath())); if(mChanges) { shownName += QLatin1String("*"); } shownName += QLatin1String("]"); return shownName; } } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::UpdateWindowTitle() { 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*/ } if (not patternReadOnly && isFileWritable) { setWindowTitle(GetPatternFileName()+GetMeasurementFileName()); } else { setWindowTitle(GetPatternFileName()+GetMeasurementFileName() + QLatin1String(" (") + tr("read only") + QLatin1String(")")); } setWindowFilePath(curFile); #if defined(Q_OS_MAC) static QIcon fileIcon = QIcon(QApplication::applicationDirPath() + QLatin1String("/../Resources/Valentina.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) } //--------------------------------------------------------------------------------------------------------------------- bool MainWindow::IgnoreLocking(int error, const QString &path) { #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) 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; #else Q_UNUSED(error) Q_UNUSED(path) return true;// On older Qt lock assumed always taken. Allow user to ignore warning. #endif // QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectPoint() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(true); emit EnablePointHover(true); emit EnableLineHover(false); emit EnableArcHover(false); emit EnableElArcHover(false); emit EnableSplineHover(false); emit EnableSplinePathHover(false); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectPointByRelease() const { ToolSelectPoint(); emit ItemsSelection(SelectionType::ByMouseRelease); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectPointByPress() const { ToolSelectPoint(); emit ItemsSelection(SelectionType::ByMousePress); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectSpline() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(false); emit EnablePointHover(false); emit EnableLineHover(false); emit EnableArcHover(false); emit EnableElArcHover(false); emit EnableSplineHover(true); emit EnableSplinePathHover(false); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectSplinePath() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(false); emit EnablePointHover(false); emit EnableLineHover(false); emit EnableArcHover(false); emit EnableElArcHover(false); emit EnableSplineHover(false); emit EnableSplinePathHover(true); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectArc() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(false); emit EnablePointHover(false); emit EnableLineHover(false); emit EnableArcHover(true); emit EnableElArcHover(false); emit EnableSplineHover(false); emit EnableSplinePathHover(false); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectElArc() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(false); emit EnablePointHover(false); emit EnableLineHover(false); emit EnableArcHover(false); emit EnableElArcHover(true); emit EnableSplineHover(false); emit EnableSplinePathHover(false); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectPointArc() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(true); emit EnablePointHover(true); emit EnableLineHover(false); emit EnableArcHover(true); emit EnableElArcHover(false); emit EnableSplineHover(false); emit EnableSplinePathHover(false); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectCurve() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(false); emit EnablePointHover(false); emit EnableLineHover(false); emit EnableArcHover(true); emit EnableElArcHover(true); emit EnableSplineHover(true); emit EnableSplinePathHover(true); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectAllDrawObjects() const { // Only true for rubber band selection emit EnableLabelSelection(false); emit EnablePointSelection(false); emit EnableLineSelection(false); emit EnableArcSelection(false); emit EnableElArcSelection(false); emit EnableSplineSelection(false); emit EnableSplinePathSelection(false); // Hovering emit EnableLabelHover(true); emit EnablePointHover(true); emit EnableLineHover(false); emit EnableArcHover(true); emit EnableElArcHover(true); emit EnableSplineHover(true); emit EnableSplinePathHover(true); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectOperationObjects() const { // Only true for rubber band selection emit EnableLabelSelection(true); emit EnablePointSelection(true); emit EnableLineSelection(false); emit EnableArcSelection(true); emit EnableElArcSelection(true); emit EnableSplineSelection(true); emit EnableSplinePathSelection(true); // Hovering emit EnableLabelHover(true); emit EnablePointHover(true); emit EnableLineHover(false); emit EnableArcHover(true); emit EnableElArcHover(true); emit EnableSplineHover(true); emit EnableSplinePathHover(true); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(true); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectGroupObjects() const { ToolSelectOperationObjects(); // Only true for rubber band selection emit EnableLineSelection(true); // Hovering emit EnableLineHover(true); } //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ToolSelectDetail() const { // Only true for rubber band selection emit EnableNodeLabelSelection(false); emit EnableNodePointSelection(false); emit EnableDetailSelection(true);// Disable when done visualization details // Hovering emit EnableNodeLabelHover(true); emit EnableNodePointHover(true); emit EnableDetailHover(true); emit ItemsSelection(SelectionType::ByMouseRelease); ui->view->AllowRubberBand(false); }