mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-25 00:14:15 +02:00
Add "Scale element..." to the element editor, keeping terminals on the grid
Edit > Scale element... scales the whole element about its hotspot by a factor picked from x0.5, x1.5, x2, x2.5, x3, x4. Only the factors that leave every terminal on the 10 px folio grid are offered, so wires to a scaled element stay straight. An element whose terminals are off the grid today is offered only the factors that bring them on to it; if none does, the dialog says so and OK is disabled. Drawn parts are scaled with their existing handleUserTransformation(), as the resize handles do. Texts, dynamic text fields and terminals are set directly so that font sizes (whole points, 4 pt minimum), terminal name offsets and line end sizes scale too, which the resize handles do not do. One undo step restores the element. Unlike "Import an element to resize", this needs no external program and works on the element being edited. Grew out of issue #1338. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
#include "../../dxf/dxftoelmt.h"
|
||||
#include "../../qet_elementscaler/qet_elementscaler.h"
|
||||
#include "../UndoCommand/openelmtcommand.h"
|
||||
#include "scaleelementdialog.h"
|
||||
#include "../../toolbarsettings.h"
|
||||
|
||||
#include <QSettings>
|
||||
@@ -1154,6 +1155,12 @@ void QETElementEditor::setupActions()
|
||||
ShortcutManager::instance().registerAction(ui->m_mirror_action, "elementeditor.mirror", tr("Éditeur d'élément"), Qt::Key_M);
|
||||
connect(ui->m_mirror_action, &QAction::triggered, [this]() {this -> elementScene() -> undoStack().push(new MirrorElementsCommand(this->elementScene()));});
|
||||
|
||||
//Scale the whole element by a factor that keeps its terminals on the grid
|
||||
m_scale_element_action = new QAction(tr("Mettre l'élément à l'échelle..."), this);
|
||||
ui->m_edit_menu->addAction(m_scale_element_action);
|
||||
ShortcutManager::instance().registerAction(m_scale_element_action, "elementeditor.scale_element", tr("Éditeur d'élément"), QKeySequence());
|
||||
connect(m_scale_element_action, &QAction::triggered, this, &QETElementEditor::scaleElement);
|
||||
|
||||
|
||||
//Zoom action
|
||||
ShortcutManager::instance().registerAction(ui->m_zoom_in_action, "elementeditor.zoom_in", tr("Éditeur d'élément"), QKeySequence::ZoomIn);
|
||||
@@ -1247,7 +1254,8 @@ void QETElementEditor::updateAction()
|
||||
//Action disabled if read only
|
||||
auto ro_list = m_add_part_action_grp->actions();
|
||||
ro_list << ui->m_paste_from_file_action
|
||||
<< ui->m_paste_from_element_action;
|
||||
<< ui->m_paste_from_element_action
|
||||
<< m_scale_element_action;
|
||||
for (auto action : std::as_const(ro_list)) {
|
||||
action->setDisabled(m_read_only);
|
||||
}
|
||||
@@ -1803,6 +1811,28 @@ void QETElementEditor::on_m_import_dxf_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief QETElementEditor::scaleElement
|
||||
Ask for a factor that keeps the terminals on the grid,
|
||||
then scale the whole element by it.
|
||||
*/
|
||||
void QETElementEditor::scaleElement()
|
||||
{
|
||||
QList<QPointF> terminals;
|
||||
for (CustomElementPart *part : m_elmt_scene->primitives()) {
|
||||
if (auto terminal = qgraphicsitem_cast<PartTerminal *>(part->toItem())) {
|
||||
terminals << terminal->scenePos();
|
||||
}
|
||||
}
|
||||
|
||||
ScaleElementDialog dialog(terminals, this);
|
||||
if (dialog.exec() != QDialog::Accepted || dialog.factor() == 1.0) {
|
||||
return;
|
||||
}
|
||||
m_elmt_scene->undoStack().push(
|
||||
new ScaleElementCommand(m_elmt_scene, dialog.factor(), dialog.scaleText()));
|
||||
}
|
||||
|
||||
void QETElementEditor::on_m_import_scaled_element_triggered()
|
||||
{
|
||||
if (ElementScalerIsPresent(true, this))
|
||||
|
||||
@@ -112,6 +112,7 @@ class QETElementEditor : public QMainWindow
|
||||
void on_m_about_qt_action_triggered();
|
||||
void on_m_import_dxf_triggered();
|
||||
void on_m_import_scaled_element_triggered();
|
||||
void scaleElement();
|
||||
|
||||
private:
|
||||
bool canClose();
|
||||
@@ -142,6 +143,7 @@ class QETElementEditor : public QMainWindow
|
||||
QList<QAction *> m_context_menu_action_list;
|
||||
|
||||
QAction
|
||||
*m_scale_element_action = nullptr,
|
||||
*m_undo_action = nullptr,
|
||||
*m_redo_action = nullptr;
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright 2006-2026 The QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "scaleelementdialog.h"
|
||||
|
||||
#include "../symbolscale.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
#include <QLocale>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
/**
|
||||
@brief ScaleElementDialog::ScaleElementDialog
|
||||
@param terminals : positions of the element's terminals, in scene
|
||||
coordinates (relative to the hotspot)
|
||||
@param parent
|
||||
*/
|
||||
ScaleElementDialog::ScaleElementDialog(const QList<QPointF> &terminals, QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Mettre l'élément à l'échelle"));
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
auto form = new QFormLayout();
|
||||
layout->addLayout(form);
|
||||
|
||||
m_factor = new QComboBox(this);
|
||||
const auto factors = SymbolScale::safeFactors(terminals);
|
||||
for (const qreal f : factors) {
|
||||
m_factor->addItem(QStringLiteral("× %1").arg(QLocale().toString(f)), f);
|
||||
}
|
||||
const int two = m_factor->findData(2.0);
|
||||
if (two >= 0) {
|
||||
m_factor->setCurrentIndex(two);
|
||||
}
|
||||
form->addRow(tr("Facteur :"), m_factor);
|
||||
|
||||
m_scale_text = new QCheckBox(tr("Mettre aussi les textes à l'échelle"), this);
|
||||
m_scale_text->setChecked(true);
|
||||
form->addRow(m_scale_text);
|
||||
|
||||
QString explanation;
|
||||
const int off_grid = SymbolScale::offGridCount(terminals);
|
||||
if (off_grid && factors.isEmpty()) {
|
||||
explanation = tr("%n borne(s) de cet élément ne sont pas sur la grille, "
|
||||
"et aucun facteur ne les y amène.", "", off_grid);
|
||||
} else if (off_grid) {
|
||||
explanation = tr("%n borne(s) de cet élément ne sont pas sur la grille. "
|
||||
"Seuls les facteurs qui les y amènent sont proposés.", "", off_grid);
|
||||
} else {
|
||||
explanation = tr("Seuls les facteurs qui gardent les bornes sur la grille "
|
||||
"sont proposés. L'élément est mis à l'échelle autour de son point de saisie.");
|
||||
}
|
||||
auto label = new QLabel(explanation, this);
|
||||
label->setWordWrap(true);
|
||||
layout->addWidget(label);
|
||||
|
||||
auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||
buttons->button(QDialogButtonBox::Ok)->setEnabled(!factors.isEmpty());
|
||||
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
layout->addWidget(buttons);
|
||||
|
||||
m_factor->setEnabled(!factors.isEmpty());
|
||||
m_scale_text->setEnabled(!factors.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
@return the chosen factor, or 1 if none could be offered
|
||||
*/
|
||||
qreal ScaleElementDialog::factor() const
|
||||
{
|
||||
return m_factor->count() ? m_factor->currentData().toReal() : 1.0;
|
||||
}
|
||||
|
||||
bool ScaleElementDialog::scaleText() const
|
||||
{
|
||||
return m_scale_text->isChecked();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2006-2026 The QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef SCALEELEMENTDIALOG_H
|
||||
#define SCALEELEMENTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
|
||||
/**
|
||||
@brief The ScaleElementDialog class
|
||||
Asks for the factor to scale the whole element by. Only the factors
|
||||
that leave every terminal on the folio grid are offered
|
||||
(see SymbolScale::safeFactors()).
|
||||
*/
|
||||
class ScaleElementDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScaleElementDialog(const QList<QPointF> &terminals, QWidget *parent = nullptr);
|
||||
|
||||
qreal factor() const;
|
||||
bool scaleText() const;
|
||||
|
||||
private:
|
||||
QComboBox *m_factor = nullptr;
|
||||
QCheckBox *m_scale_text = nullptr;
|
||||
};
|
||||
|
||||
#endif // SCALEELEMENTDIALOG_H
|
||||
Reference in New Issue
Block a user