1031 lines
38 KiB
C++
1031 lines
38 KiB
C++
/************************************************************************
|
|
**
|
|
** @file vwidgetbackgroundimages.cpp
|
|
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
|
** @date 26 1, 2022
|
|
**
|
|
** @brief
|
|
** @copyright
|
|
** This source code is part of the Valentina project, a pattern making
|
|
** program, whose allow create and modeling patterns of clothing.
|
|
** Copyright (C) 2022 Valentina project
|
|
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
|
**
|
|
** Valentina is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** Valentina is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
|
**
|
|
*************************************************************************/
|
|
#include "vwidgetbackgroundimages.h"
|
|
#include "../ifc/xml/vabstractpattern.h"
|
|
#include "../ifc/xml/vbackgroundpatternimage.h"
|
|
#include "../vmisc/def.h"
|
|
#include "../vmisc/lambdaconstants.h"
|
|
#include "../vmisc/theme/themeDef.h"
|
|
#include "../vmisc/theme/vtheme.h"
|
|
#include "../vmisc/vabstractapplication.h"
|
|
#include "../vtools/undocommands/image/hideallbackgroundimages.h"
|
|
#include "../vtools/undocommands/image/hidebackgroundimage.h"
|
|
#include "../vtools/undocommands/image/holdallbackgroundimages.h"
|
|
#include "../vtools/undocommands/image/holdbackgroundimage.h"
|
|
#include "../vtools/undocommands/image/movebackgroundimage.h"
|
|
#include "../vtools/undocommands/image/renamebackgroundimage.h"
|
|
#include "../vtools/undocommands/image/resetbackgroundimage.h"
|
|
#include "../vtools/undocommands/image/rotatebackgroundimage.h"
|
|
#include "../vtools/undocommands/image/scalebackgroundimage.h"
|
|
#include "../vtools/undocommands/image/zvaluemovebackgroundimage.h"
|
|
#include "../vwidgets/vmousewheelwidgetadjustmentguard.h"
|
|
#include "ui_vwidgetbackgroundimages.h"
|
|
|
|
#include <QMenu>
|
|
#include <QPushButton>
|
|
|
|
namespace
|
|
{
|
|
enum ImageData
|
|
{
|
|
Hold = 0,
|
|
Visibility = 1,
|
|
Name = 2
|
|
};
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void SetImageHold(QTableWidgetItem *item, const VBackgroundPatternImage &image)
|
|
{
|
|
if (item)
|
|
{
|
|
const QString resource = QStringLiteral("icon");
|
|
(image.Hold()) ? item->setIcon(VTheme::GetIconResource(resource, QStringLiteral("16x16/hold_image.png")))
|
|
: item->setIcon(VTheme::GetIconResource(resource, QStringLiteral("16x16/not_hold_image.png")));
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void SetImageVisibility(QTableWidgetItem *item, const VBackgroundPatternImage &image)
|
|
{
|
|
if (item)
|
|
{
|
|
const QString resource = QStringLiteral("icon");
|
|
item->setIcon(image.Visible() ? VTheme::GetIconResource(resource, QStringLiteral("16x16/open_eye.png"))
|
|
: VTheme::GetIconResource(resource, QStringLiteral("16x16/closed_eye.png")));
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void SetImageName(QTableWidgetItem *item, const VBackgroundPatternImage &image, const QString &def)
|
|
{
|
|
QString imageName = def;
|
|
if (not image.Name().isEmpty())
|
|
{
|
|
imageName = image.Name();
|
|
}
|
|
item->setText(imageName);
|
|
item->setToolTip(imageName);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void SetCheckBoxValue(QCheckBox *checkbox, bool value)
|
|
{
|
|
checkbox->blockSignals(true);
|
|
checkbox->setChecked(value);
|
|
checkbox->blockSignals(false);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto ScaleUnitConvertor(qreal base, qreal value, ScaleUnit from, ScaleUnit to) -> qreal
|
|
{
|
|
auto FromPxTo = [base, to](qreal value)
|
|
{
|
|
switch (to)
|
|
{
|
|
case ScaleUnit::Mm:
|
|
return (value / PrintDPI) * 25.4;
|
|
case ScaleUnit::Cm:
|
|
return ((value / PrintDPI) * 25.4) / 10.0;
|
|
case ScaleUnit::Inch:
|
|
return value / PrintDPI;
|
|
case ScaleUnit::Px:
|
|
return value;
|
|
case ScaleUnit::Percent:
|
|
if (qFuzzyIsNull(base))
|
|
{
|
|
return 0.0;
|
|
}
|
|
return value / base * 100.;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0.0;
|
|
};
|
|
|
|
switch (from)
|
|
{
|
|
case ScaleUnit::Percent:
|
|
return FromPxTo(base * (value / 100.));
|
|
case ScaleUnit::Px:
|
|
return FromPxTo(value);
|
|
case ScaleUnit::Mm:
|
|
return FromPxTo((value / 25.4) * PrintDPI);
|
|
case ScaleUnit::Cm:
|
|
return FromPxTo(((value * 10.0) / 25.4) * PrintDPI);
|
|
case ScaleUnit::Inch:
|
|
return FromPxTo(value * PrintDPI);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
} // namespace
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
VWidgetBackgroundImages::VWidgetBackgroundImages(VAbstractPattern *doc, QWidget *parent)
|
|
: QWidget(parent),
|
|
ui(new Ui::VWidgetBackgroundImages),
|
|
m_doc(doc)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
// Prevent stealing focus when scrolling
|
|
VMouseWheelWidgetAdjustmentGuard::InstallEventFilter(ui->doubleSpinBoxImageHorizontalTranslate);
|
|
VMouseWheelWidgetAdjustmentGuard::InstallEventFilter(ui->comboBoxTranslateUnit);
|
|
VMouseWheelWidgetAdjustmentGuard::InstallEventFilter(ui->doubleSpinBoxImageVerticalTranslate);
|
|
VMouseWheelWidgetAdjustmentGuard::InstallEventFilter(ui->doubleSpinBoxScaleWidth);
|
|
VMouseWheelWidgetAdjustmentGuard::InstallEventFilter(ui->comboBoxScaleUnit);
|
|
VMouseWheelWidgetAdjustmentGuard::InstallEventFilter(ui->doubleSpinBoxScaleHeight);
|
|
VMouseWheelWidgetAdjustmentGuard::InstallEventFilter(ui->doubleSpinBoxRotationAngle);
|
|
|
|
SCASSERT(doc != nullptr)
|
|
|
|
UpdateImages();
|
|
|
|
ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
connect(doc, &VAbstractPattern::BackgroundImageHoldChanged, this, &VWidgetBackgroundImages::UpdateImage);
|
|
connect(doc, &VAbstractPattern::BackgroundImageVisibilityChanged, this, &VWidgetBackgroundImages::UpdateImage);
|
|
connect(doc, &VAbstractPattern::BackgroundImageNameChanged, this, &VWidgetBackgroundImages::UpdateImage);
|
|
connect(doc, &VAbstractPattern::BackgroundImagesHoldChanged, this, &VWidgetBackgroundImages::UpdateImages);
|
|
connect(doc, &VAbstractPattern::BackgroundImagesVisibilityChanged, this, &VWidgetBackgroundImages::UpdateImages);
|
|
connect(doc, &VAbstractPattern::BackgroundImagePositionChanged, this,
|
|
&VWidgetBackgroundImages::ImagePositionChanged);
|
|
connect(doc, &VAbstractPattern::BackgroundImageTransformationChanged, this,
|
|
&VWidgetBackgroundImages::ImagePositionChanged);
|
|
|
|
connect(ui->tableWidget, &QTableWidget::cellClicked, this, &VWidgetBackgroundImages::ImageHoldChanged);
|
|
connect(ui->tableWidget, &QTableWidget::cellClicked, this, &VWidgetBackgroundImages::ImageVisibilityChanged);
|
|
connect(ui->tableWidget, &QTableWidget::cellChanged, this, &VWidgetBackgroundImages::ImageNameChanged);
|
|
connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, &VWidgetBackgroundImages::ContextMenu);
|
|
connect(ui->tableWidget, &QTableWidget::currentCellChanged, this, &VWidgetBackgroundImages::CurrentImageChanged);
|
|
|
|
connect(ui->toolButtonTop, &QToolButton::clicked, this, &VWidgetBackgroundImages::MoveImageOnTop);
|
|
connect(ui->toolButtonUp, &QToolButton::clicked, this, &VWidgetBackgroundImages::MoveImageUp);
|
|
connect(ui->toolButtonDown, &QToolButton::clicked, this, &VWidgetBackgroundImages::MoveImageDown);
|
|
connect(ui->toolButtonBottom, &QToolButton::clicked, this, &VWidgetBackgroundImages::MoveImageBottom);
|
|
|
|
InitImageTranslation();
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
VWidgetBackgroundImages::~VWidgetBackgroundImages()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::UpdateImages()
|
|
{
|
|
FillTable(m_doc->GetBackgroundImages());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::UpdateImage(const QUuid &id)
|
|
{
|
|
int const row = ImageRow(id);
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
if (image.IsNull())
|
|
{
|
|
return;
|
|
}
|
|
|
|
ui->tableWidget->blockSignals(true);
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, ImageData::Hold);
|
|
SetImageHold(item, image);
|
|
|
|
item = ui->tableWidget->item(row, ImageData::Visibility);
|
|
SetImageVisibility(item, image);
|
|
|
|
item = ui->tableWidget->item(row, ImageData::Name);
|
|
SetImageName(item, image, tr("Background image"));
|
|
|
|
ui->tableWidget->blockSignals(false);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ImageSelected(const QUuid &id)
|
|
{
|
|
int const row = ImageRow(id);
|
|
|
|
ui->tableWidget->blockSignals(true);
|
|
ui->tableWidget->setCurrentCell(row, ImageData::Name);
|
|
ui->tableWidget->blockSignals(false);
|
|
|
|
if (row != -1 && not ui->checkBoxRelativeTranslation->isChecked())
|
|
{
|
|
SetAbsolutePisition(id);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ImageHoldChanged(int row, int column)
|
|
{
|
|
if (column != ImageData::Hold)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, column);
|
|
if (item != nullptr)
|
|
{
|
|
ToggleImageHold(item->data(Qt::UserRole).toUuid());
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ImageVisibilityChanged(int row, int column)
|
|
{
|
|
if (column != ImageData::Visibility)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, column);
|
|
if (item != nullptr)
|
|
{
|
|
ToggleImageVisibility(item->data(Qt::UserRole).toUuid());
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ImageNameChanged(int row, int column)
|
|
{
|
|
if (column != ImageData::Name)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, column);
|
|
if (item != nullptr)
|
|
{
|
|
auto *command = new RenameBackgroundImage(item->data(Qt::UserRole).toUuid(), item->text(), m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ContextMenu(const QPoint &pos)
|
|
{
|
|
QTableWidgetItem *item = ui->tableWidget->itemAt(pos);
|
|
if (item == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const int row = item->row();
|
|
item = ui->tableWidget->item(row, 0);
|
|
const QUuid id = item->data(Qt::UserRole).toUuid();
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
if (image.IsNull())
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto MultipleChangeHoldTo = [this](bool visibility)
|
|
{
|
|
for (int r = 0; r < ui->tableWidget->rowCount(); ++r)
|
|
{
|
|
QTableWidgetItem *rowItem = ui->tableWidget->item(r, ImageData::Visibility);
|
|
if (rowItem && visibility != m_doc->GetBackgroundImage(rowItem->data(Qt::UserRole).toUuid()).Hold())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
auto MultipleChangeVisibilityTo = [this](bool visibility)
|
|
{
|
|
for (int r = 0; r < ui->tableWidget->rowCount(); ++r)
|
|
{
|
|
QTableWidgetItem *rowItem = ui->tableWidget->item(r, ImageData::Visibility);
|
|
if (rowItem && visibility != m_doc->GetBackgroundImage(rowItem->data(Qt::UserRole).toUuid()).Visible())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
QMenu menu;
|
|
|
|
QAction *holdOption = menu.addAction(tr("Hold"));
|
|
holdOption->setCheckable(true);
|
|
holdOption->setChecked(image.Hold());
|
|
|
|
QAction *actionVisible = menu.addAction(tr("Visible"));
|
|
actionVisible->setCheckable(true);
|
|
actionVisible->setChecked(image.Visible());
|
|
|
|
QAction *actionReset = menu.addAction(tr("Reset transformation"));
|
|
actionReset->setEnabled(not image.Hold());
|
|
|
|
QAction *actionDelete = menu.addAction(FromTheme(VThemeIcon::EditDelete), tr("Delete"));
|
|
|
|
menu.addSeparator();
|
|
QAction *actionHoldAll = menu.addAction(tr("Hold All"));
|
|
actionHoldAll->setEnabled(MultipleChangeHoldTo(true));
|
|
QAction *actionUnholdAll = menu.addAction(tr("Unhold All"));
|
|
actionUnholdAll->setEnabled(MultipleChangeHoldTo(false));
|
|
|
|
menu.addSeparator();
|
|
QAction *actionHideAll = menu.addAction(tr("Hide All"));
|
|
actionHideAll->setEnabled(MultipleChangeVisibilityTo(false));
|
|
QAction *actionShowAll = menu.addAction(tr("Show All"));
|
|
actionShowAll->setEnabled(MultipleChangeVisibilityTo(true));
|
|
|
|
QAction *selectedAction = menu.exec(ui->tableWidget->viewport()->mapToGlobal(pos));
|
|
|
|
if (selectedAction == holdOption)
|
|
{
|
|
ToggleImageHold(id);
|
|
}
|
|
else if (selectedAction == actionVisible)
|
|
{
|
|
ToggleImageVisibility(id);
|
|
}
|
|
else if (selectedAction == actionReset)
|
|
{
|
|
VAbstractApplication::VApp()->getUndoStack()->push(new ResetBackgroundImage(image.Id(), m_doc));
|
|
}
|
|
else if (selectedAction == actionDelete)
|
|
{
|
|
emit DeleteImage(id);
|
|
}
|
|
else if (selectedAction == actionHoldAll)
|
|
{
|
|
auto *command = new HoldAllBackgroundImages(true, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
else if (selectedAction == actionUnholdAll)
|
|
{
|
|
auto *command = new HoldAllBackgroundImages(false, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
else if (selectedAction == actionHideAll)
|
|
{
|
|
auto *command = new HideAllBackgroundImages(true, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
else if (selectedAction == actionShowAll)
|
|
{
|
|
auto *command = new HideAllBackgroundImages(false, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::CurrentImageChanged(int currentRow, int currentColumn, int previousRow,
|
|
int previousColumn)
|
|
{
|
|
Q_UNUSED(currentColumn)
|
|
Q_UNUSED(previousColumn)
|
|
if (previousRow != currentRow)
|
|
{
|
|
QTableWidgetItem *item = ui->tableWidget->item(currentRow, 0);
|
|
if (item != nullptr)
|
|
{
|
|
emit SelectImage(item->data(Qt::UserRole).toUuid());
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::MoveImageOnTop()
|
|
{
|
|
int const row = ui->tableWidget->currentRow();
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
auto *command = new ZValueMoveBackgroundImage(id, ZValueMoveType::Top, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::MoveImageUp()
|
|
{
|
|
int const row = ui->tableWidget->currentRow();
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
auto *command = new ZValueMoveBackgroundImage(id, ZValueMoveType::Up, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::MoveImageDown()
|
|
{
|
|
int const row = ui->tableWidget->currentRow();
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
auto *command = new ZValueMoveBackgroundImage(id, ZValueMoveType::Down, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::MoveImageBottom()
|
|
{
|
|
int const row = ui->tableWidget->currentRow();
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
auto *command = new ZValueMoveBackgroundImage(id, ZValueMoveType::Bottom, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ApplyImageTransformation()
|
|
{
|
|
int const row = ui->tableWidget->currentRow();
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
|
|
if (image.IsNull() || image.Hold())
|
|
{
|
|
return;
|
|
}
|
|
|
|
const int index = ui->tabWidgetImageTransformation->currentIndex();
|
|
if (ui->tabWidgetImageTransformation->indexOf(ui->tabTranslate) == index)
|
|
{ // translate
|
|
qreal dx = UnitConvertor(ui->doubleSpinBoxImageHorizontalTranslate->value(), CurrentTranslateUnit(), Unit::Px);
|
|
qreal dy = UnitConvertor(ui->doubleSpinBoxImageVerticalTranslate->value(), CurrentTranslateUnit(), Unit::Px);
|
|
|
|
if (not ui->checkBoxRelativeTranslation->isChecked())
|
|
{
|
|
QRectF const rect = image.BoundingRect();
|
|
dx = dx - rect.topLeft().x();
|
|
dy = dy - rect.topLeft().y();
|
|
}
|
|
|
|
auto *command = new MoveBackgroundImage(id, dx, dy, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
else if (ui->tabWidgetImageTransformation->indexOf(ui->tabScale) == index)
|
|
{ // scale
|
|
qreal const sx =
|
|
WidthScaleUnitConvertor(ui->doubleSpinBoxScaleWidth->value(), CurrentScaleUnit(), ScaleUnit::Percent) / 100;
|
|
qreal const sy =
|
|
HeightScaleUnitConvertor(ui->doubleSpinBoxScaleHeight->value(), CurrentScaleUnit(), ScaleUnit::Percent) /
|
|
100;
|
|
|
|
QTransform imageMatrix = image.Matrix();
|
|
QPointF const originPos = image.BoundingRect().center();
|
|
|
|
QTransform m;
|
|
m.translate(originPos.x(), originPos.y());
|
|
m.scale(sx, sy);
|
|
m.translate(-originPos.x(), -originPos.y());
|
|
imageMatrix *= m;
|
|
|
|
auto *command = new ScaleBackgroundImage(id, imageMatrix, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
else if (ui->tabWidgetImageTransformation->indexOf(ui->tabRotate) == index)
|
|
{ // rotate
|
|
qreal angle = ui->doubleSpinBoxRotationAngle->value();
|
|
|
|
if (ui->toolButtonImageRotationClockwise->isChecked())
|
|
{
|
|
angle *= -1;
|
|
}
|
|
|
|
QTransform imageMatrix = image.Matrix();
|
|
|
|
QPointF const originPos = image.BoundingRect().center();
|
|
|
|
QTransform m;
|
|
m.translate(originPos.x(), originPos.y());
|
|
m.rotate(-angle);
|
|
m.translate(-originPos.x(), -originPos.y());
|
|
imageMatrix *= m;
|
|
|
|
auto *command = new RotateBackgroundImage(id, imageMatrix, m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ResetImageTransformationSettings()
|
|
{
|
|
const int index = ui->tabWidgetImageTransformation->currentIndex();
|
|
if (ui->tabWidgetImageTransformation->indexOf(ui->tabTranslate) == index)
|
|
{ // translate
|
|
if (ui->checkBoxRelativeTranslation->isChecked())
|
|
{
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setValue(0);
|
|
ui->doubleSpinBoxImageVerticalTranslate->setValue(0);
|
|
}
|
|
else
|
|
{
|
|
if (ui->tableWidget->currentRow() == -1)
|
|
{
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setValue(0);
|
|
ui->doubleSpinBoxImageVerticalTranslate->setValue(0);
|
|
}
|
|
}
|
|
|
|
int const unitIndex = ui->comboBoxTranslateUnit->findData(QVariant(static_cast<int>(Unit::Px)));
|
|
if (unitIndex != -1)
|
|
{
|
|
ui->comboBoxTranslateUnit->setCurrentIndex(unitIndex);
|
|
}
|
|
}
|
|
else if (ui->tabWidgetImageTransformation->indexOf(ui->tabScale) == index)
|
|
{ // scale
|
|
if (int const unitIndex = ui->comboBoxScaleUnit->findData(QVariant(static_cast<int>(ScaleUnit::Percent)));
|
|
unitIndex != -1)
|
|
{
|
|
ui->comboBoxScaleUnit->setCurrentIndex(unitIndex);
|
|
}
|
|
|
|
ui->doubleSpinBoxScaleHeight->setValue(100);
|
|
ui->doubleSpinBoxScaleWidth->setValue(100);
|
|
}
|
|
else if (ui->tabWidgetImageTransformation->indexOf(ui->tabRotate) == index)
|
|
{ // rotate
|
|
ui->doubleSpinBoxRotationAngle->setValue(0);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::RelativeTranslationChanged(bool checked)
|
|
{
|
|
if (checked)
|
|
{
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setValue(0);
|
|
ui->doubleSpinBoxImageVerticalTranslate->setValue(0);
|
|
}
|
|
else
|
|
{
|
|
int const row = ui->tableWidget->currentRow();
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
SetAbsolutePisition(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ScaleProportionallyChanged(bool checked)
|
|
{
|
|
if (checked)
|
|
{
|
|
qreal const value = ui->doubleSpinBoxScaleWidth->value();
|
|
ui->doubleSpinBoxScaleHeight->setValue(value);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ScaleWidthChanged(double value)
|
|
{
|
|
if (ui->checkBoxScaleProportionally->isChecked())
|
|
{
|
|
ScaleUnit const unit = CurrentScaleUnit();
|
|
if (unit == ScaleUnit::Percent)
|
|
{
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(true);
|
|
ui->doubleSpinBoxScaleHeight->setValue(value);
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(false);
|
|
}
|
|
else
|
|
{
|
|
qreal const factor = WidthScaleUnitConvertor(value, unit, ScaleUnit::Percent) / 100.;
|
|
qreal const heightPx = ImageHeight() * factor;
|
|
qreal const height = HeightScaleUnitConvertor(heightPx, ScaleUnit::Px, unit);
|
|
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(true);
|
|
ui->doubleSpinBoxScaleHeight->setValue(height);
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ScaleHeightChanged(double value)
|
|
{
|
|
if (ui->checkBoxScaleProportionally->isChecked())
|
|
{
|
|
ScaleUnit const unit = CurrentScaleUnit();
|
|
if (unit == ScaleUnit::Percent)
|
|
{
|
|
ui->doubleSpinBoxScaleWidth->blockSignals(true);
|
|
ui->doubleSpinBoxScaleWidth->setValue(value);
|
|
ui->doubleSpinBoxScaleWidth->blockSignals(false);
|
|
}
|
|
else
|
|
{
|
|
qreal const factor = HeightScaleUnitConvertor(value, unit, ScaleUnit::Percent) / 100.;
|
|
qreal const widthPx = ImageWidth() * factor;
|
|
qreal const width = WidthScaleUnitConvertor(widthPx, ScaleUnit::Px, unit);
|
|
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(true);
|
|
ui->doubleSpinBoxScaleHeight->setValue(width);
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ImagePositionChanged(const QUuid &id)
|
|
{
|
|
if (ui->checkBoxRelativeTranslation->isChecked())
|
|
{
|
|
return;
|
|
}
|
|
|
|
int const row = ui->tableWidget->currentRow();
|
|
if (row == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
if (QUuid const curentId = item->data(Qt::UserRole).toUuid(); curentId != id)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetAbsolutePisition(id);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::FillTable(const QVector<VBackgroundPatternImage> &images)
|
|
{
|
|
ui->tableWidget->blockSignals(true);
|
|
ui->tableWidget->clear();
|
|
|
|
ui->tableWidget->setColumnCount(3);
|
|
ui->tableWidget->setRowCount(static_cast<int>(images.size()));
|
|
qint32 currentRow = -1;
|
|
|
|
auto ReadOnly = [](QTableWidgetItem *item)
|
|
{
|
|
// set the item non-editable (view only), and non-selectable
|
|
Qt::ItemFlags flags = item->flags();
|
|
flags &= ~(Qt::ItemIsEditable); // reset/clear the flag
|
|
item->setFlags(flags);
|
|
};
|
|
|
|
for (const auto &image : images)
|
|
{
|
|
++currentRow;
|
|
|
|
// Hold
|
|
auto *item = new QTableWidgetItem();
|
|
item->setTextAlignment(Qt::AlignHCenter);
|
|
SetImageHold(item, image);
|
|
item->setData(Qt::UserRole, image.Id());
|
|
ReadOnly(item);
|
|
ui->tableWidget->setItem(currentRow, 0, item);
|
|
|
|
// Visibility
|
|
item = new QTableWidgetItem();
|
|
item->setTextAlignment(Qt::AlignHCenter);
|
|
SetImageVisibility(item, image);
|
|
item->setData(Qt::UserRole, image.Id());
|
|
ReadOnly(item);
|
|
ui->tableWidget->setItem(currentRow, 1, item);
|
|
|
|
item = new QTableWidgetItem();
|
|
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
item->setData(Qt::UserRole, image.Id());
|
|
SetImageName(item, image, tr("Background image"));
|
|
ui->tableWidget->setItem(currentRow, 2, item);
|
|
}
|
|
|
|
ui->tableWidget->resizeColumnsToContents();
|
|
ui->tableWidget->resizeRowsToContents();
|
|
ui->tableWidget->blockSignals(false);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ToggleImageHold(const QUuid &id) const
|
|
{
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
if (not image.IsNull())
|
|
{
|
|
auto *command = new HoldBackgroundImage(image.Id(), not image.Hold(), m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::ToggleImageVisibility(const QUuid &id) const
|
|
{
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
if (not image.IsNull())
|
|
{
|
|
auto *command = new HideBackgroundImage(image.Id(), image.Visible(), m_doc);
|
|
VAbstractApplication::VApp()->getUndoStack()->push(command);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto VWidgetBackgroundImages::ImageRow(const QUuid &id) const -> int
|
|
{
|
|
for (int r = 0; r < ui->tableWidget->rowCount(); ++r)
|
|
{
|
|
QTableWidgetItem *item = ui->tableWidget->item(r, 0);
|
|
if (item != nullptr && id == item->data(Qt::UserRole).toUuid())
|
|
{
|
|
return r;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto VWidgetBackgroundImages::CurrentTranslateUnit() const -> Unit
|
|
{
|
|
return static_cast<Unit>(ui->comboBoxTranslateUnit->currentData().toInt());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto VWidgetBackgroundImages::CurrentScaleUnit() const -> ScaleUnit
|
|
{
|
|
return static_cast<ScaleUnit>(ui->comboBoxScaleUnit->currentData().toInt());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::InitImageTranslation()
|
|
{
|
|
// Translate
|
|
ui->comboBoxTranslateUnit->addItem(tr("Pixels"), QVariant(static_cast<int>(Unit::Px)));
|
|
ui->comboBoxTranslateUnit->addItem(tr("Millimiters"), QVariant(static_cast<int>(Unit::Mm)));
|
|
ui->comboBoxTranslateUnit->addItem(tr("Centimeters"), QVariant(static_cast<int>(Unit::Cm)));
|
|
ui->comboBoxTranslateUnit->addItem(tr("Inches"), QVariant(static_cast<int>(Unit::Inch)));
|
|
|
|
ui->comboBoxTranslateUnit->blockSignals(true);
|
|
ui->comboBoxTranslateUnit->setCurrentIndex(0);
|
|
ui->comboBoxTranslateUnit->blockSignals(false);
|
|
|
|
const int minTranslate = -10000;
|
|
const int maxTranslate = 10000;
|
|
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setMinimum(
|
|
UnitConvertor(minTranslate, Unit::Cm, m_oldImageTranslationUnit));
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setMaximum(
|
|
UnitConvertor(maxTranslate, Unit::Cm, m_oldImageTranslationUnit));
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setValue(0);
|
|
|
|
ui->doubleSpinBoxImageVerticalTranslate->setMinimum(
|
|
UnitConvertor(minTranslate, Unit::Cm, m_oldImageTranslationUnit));
|
|
ui->doubleSpinBoxImageVerticalTranslate->setMaximum(
|
|
UnitConvertor(maxTranslate, Unit::Cm, m_oldImageTranslationUnit));
|
|
ui->doubleSpinBoxImageVerticalTranslate->setValue(0);
|
|
|
|
connect(ui->comboBoxTranslateUnit, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
|
[this V_LAMBDA_CONSTANTS(minTranslate, maxTranslate)]()
|
|
{
|
|
const Unit newUnit = CurrentTranslateUnit();
|
|
const qreal oldTranslateX = ui->doubleSpinBoxImageHorizontalTranslate->value();
|
|
const qreal oldTranslateY = ui->doubleSpinBoxImageVerticalTranslate->value();
|
|
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setMinimum(UnitConvertor(minTranslate, Unit::Cm, newUnit));
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setMaximum(UnitConvertor(maxTranslate, Unit::Cm, newUnit));
|
|
|
|
ui->doubleSpinBoxImageVerticalTranslate->setMinimum(UnitConvertor(minTranslate, Unit::Cm, newUnit));
|
|
ui->doubleSpinBoxImageVerticalTranslate->setMaximum(UnitConvertor(maxTranslate, Unit::Cm, newUnit));
|
|
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setValue(
|
|
UnitConvertor(oldTranslateX, m_oldImageTranslationUnit, newUnit));
|
|
ui->doubleSpinBoxImageVerticalTranslate->setValue(
|
|
UnitConvertor(oldTranslateY, m_oldImageTranslationUnit, newUnit));
|
|
|
|
m_oldImageTranslationUnit = newUnit;
|
|
});
|
|
|
|
SetCheckBoxValue(ui->checkBoxRelativeTranslation, true);
|
|
connect(ui->checkBoxRelativeTranslation, &QCheckBox::toggled, this,
|
|
&VWidgetBackgroundImages::RelativeTranslationChanged);
|
|
|
|
// Scale
|
|
ui->comboBoxScaleUnit->addItem(QChar('%'), QVariant(static_cast<int>(ScaleUnit::Percent)));
|
|
ui->comboBoxScaleUnit->addItem(tr("Millimiters"), QVariant(static_cast<int>(ScaleUnit::Mm)));
|
|
ui->comboBoxScaleUnit->addItem(tr("Centimeters"), QVariant(static_cast<int>(ScaleUnit::Cm)));
|
|
ui->comboBoxScaleUnit->addItem(tr("Inches"), QVariant(static_cast<int>(ScaleUnit::Inch)));
|
|
ui->comboBoxScaleUnit->addItem(tr("Pixels"), QVariant(static_cast<int>(ScaleUnit::Px)));
|
|
|
|
ui->comboBoxScaleUnit->blockSignals(true);
|
|
ui->comboBoxScaleUnit->setCurrentIndex(0);
|
|
ui->comboBoxScaleUnit->blockSignals(false);
|
|
|
|
const int minScale = -100000;
|
|
const int maxScale = 100000;
|
|
|
|
ui->doubleSpinBoxScaleWidth->setMinimum(minScale);
|
|
ui->doubleSpinBoxScaleWidth->setMaximum(maxScale);
|
|
ui->doubleSpinBoxScaleWidth->setValue(100);
|
|
|
|
ui->doubleSpinBoxScaleHeight->setMinimum(minScale);
|
|
ui->doubleSpinBoxScaleHeight->setMaximum(maxScale);
|
|
ui->doubleSpinBoxScaleHeight->setValue(100);
|
|
|
|
connect(
|
|
ui->comboBoxScaleUnit, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
|
[this V_LAMBDA_CONSTANTS(minScale, maxScale)]()
|
|
{
|
|
const ScaleUnit newUnit = CurrentScaleUnit();
|
|
const qreal oldScaleWidth = ui->doubleSpinBoxScaleWidth->value();
|
|
const qreal oldScaleHeight = ui->doubleSpinBoxScaleHeight->value();
|
|
|
|
ui->doubleSpinBoxScaleWidth->blockSignals(true);
|
|
|
|
ui->doubleSpinBoxScaleWidth->setMinimum(WidthScaleUnitConvertor(minScale, ScaleUnit::Percent, newUnit));
|
|
ui->doubleSpinBoxScaleWidth->setMinimum(WidthScaleUnitConvertor(minScale, ScaleUnit::Percent, newUnit));
|
|
|
|
ui->doubleSpinBoxScaleWidth->setValue(WidthScaleUnitConvertor(oldScaleWidth, m_oldImageScaleUnit, newUnit));
|
|
ui->doubleSpinBoxScaleWidth->blockSignals(false);
|
|
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(true);
|
|
|
|
ui->doubleSpinBoxScaleHeight->setMaximum(HeightScaleUnitConvertor(maxScale, ScaleUnit::Percent, newUnit));
|
|
ui->doubleSpinBoxScaleHeight->setMaximum(HeightScaleUnitConvertor(maxScale, ScaleUnit::Percent, newUnit));
|
|
|
|
if (ui->checkBoxScaleProportionally->isChecked() && newUnit == ScaleUnit::Percent)
|
|
{
|
|
ui->doubleSpinBoxScaleHeight->setValue(ui->doubleSpinBoxScaleWidth->value());
|
|
}
|
|
else
|
|
{
|
|
ui->doubleSpinBoxScaleHeight->setValue(
|
|
HeightScaleUnitConvertor(oldScaleHeight, m_oldImageScaleUnit, newUnit));
|
|
}
|
|
ui->doubleSpinBoxScaleHeight->blockSignals(false);
|
|
|
|
m_oldImageScaleUnit = newUnit;
|
|
});
|
|
|
|
connect(ui->doubleSpinBoxScaleHeight, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
|
&VWidgetBackgroundImages::ScaleHeightChanged);
|
|
connect(ui->doubleSpinBoxScaleWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
|
&VWidgetBackgroundImages::ScaleWidthChanged);
|
|
|
|
SetCheckBoxValue(ui->checkBoxScaleProportionally, true);
|
|
connect(ui->checkBoxScaleProportionally, &QCheckBox::toggled, this,
|
|
&VWidgetBackgroundImages::ScaleProportionallyChanged);
|
|
|
|
// Rotate
|
|
ui->doubleSpinBoxRotationAngle->setValue(0);
|
|
|
|
ui->toolButtonImageRotationAnticlockwise->setChecked(true);
|
|
|
|
QPushButton *bApply = ui->buttonBox->button(QDialogButtonBox::Apply);
|
|
SCASSERT(bApply != nullptr)
|
|
connect(bApply, &QPushButton::clicked, this, &VWidgetBackgroundImages::ApplyImageTransformation);
|
|
|
|
QPushButton *bReset = ui->buttonBox->button(QDialogButtonBox::Reset);
|
|
SCASSERT(bReset != nullptr)
|
|
connect(bReset, &QPushButton::clicked, this, &VWidgetBackgroundImages::ResetImageTransformationSettings);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto VWidgetBackgroundImages::ImageWidth() const -> qreal
|
|
{
|
|
qreal width = 0;
|
|
|
|
if (int const row = ui->tableWidget->currentRow(); row != -1)
|
|
{
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
width = image.Size().width();
|
|
}
|
|
}
|
|
|
|
return width;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto VWidgetBackgroundImages::ImageHeight() const -> qreal
|
|
{
|
|
qreal height = 0;
|
|
|
|
if (int const row = ui->tableWidget->currentRow(); row != -1)
|
|
{
|
|
QTableWidgetItem *item = ui->tableWidget->item(row, 0);
|
|
if (item != nullptr)
|
|
{
|
|
QUuid const id = item->data(Qt::UserRole).toUuid();
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
height = image.Size().height();
|
|
}
|
|
}
|
|
|
|
return height;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto VWidgetBackgroundImages::WidthScaleUnitConvertor(qreal value, ScaleUnit from, ScaleUnit to) const -> qreal
|
|
{
|
|
return ScaleUnitConvertor(ImageWidth(), value, from, to);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
auto VWidgetBackgroundImages::HeightScaleUnitConvertor(qreal value, ScaleUnit from, ScaleUnit to) const -> qreal
|
|
{
|
|
return ScaleUnitConvertor(ImageHeight(), value, from, to);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
void VWidgetBackgroundImages::SetAbsolutePisition(const QUuid &id)
|
|
{
|
|
VBackgroundPatternImage const image = m_doc->GetBackgroundImage(id);
|
|
QRectF const rect = image.BoundingRect();
|
|
|
|
ui->doubleSpinBoxImageHorizontalTranslate->setValue(
|
|
UnitConvertor(rect.topLeft().x(), Unit::Px, CurrentTranslateUnit()));
|
|
ui->doubleSpinBoxImageVerticalTranslate->setValue(
|
|
UnitConvertor(rect.topLeft().y(), Unit::Px, CurrentTranslateUnit()));
|
|
}
|