/*
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 .
*/
#include "templatecellwidget.h"
#include "../NameList/nameslist.h"
#include "../NameList/ui/namelistdialog.h"
#include "../NameList/ui/namelistwidget.h"
#include "../qeticons.h"
#include "../qetinformation.h"
#include "../titleblockcell.h"
#include "../titleblocktemplate.h"
#include "templatecommands.h"
/**
@brief TitleBlockTemplateCellWidget::TitleBlockTemplateCellWidget
Constructor
@param parent_template : TitleBlockTemplate
@param parent : QWidget
*/
TitleBlockTemplateCellWidget::TitleBlockTemplateCellWidget(
TitleBlockTemplate *parent_template,
QWidget *parent) :
QWidget(parent),
read_only_(false)
{
initWidgets();
updateLogosComboBox(parent_template);
}
/**
Destructor
*/
TitleBlockTemplateCellWidget::~TitleBlockTemplateCellWidget()
{
}
/**
Initialize layout and widgets.
*/
void TitleBlockTemplateCellWidget::initWidgets()
{
// type combo box: always displayed
cell_type_label_ = new QLabel(tr("Cell type:"));
cell_type_input_ = new QComboBox();
cell_type_input_ -> addItem(tr("Empty"), TitleBlockCell::EmptyCell);
cell_type_input_ -> addItem(tr("Text"), TitleBlockCell::TextCell);
cell_type_input_ -> addItem(tr("Logo"), TitleBlockCell::LogoCell);
// name input: displayed for text and logo cells
name_label_ = new QLabel(tr("Name:"));
name_input_ = new QLineEdit();
// widgets specific to empty cells
empty_label_ = new QLabel(tr("Warning: the edges of empty cells do not appear in the final render the sheet."));
// widgets specific to logo cells
logo_label_ = new QLabel(tr("Logo"));
logo_input_ = new QComboBox();
logo_input_ -> addItem(tr("No logo"));
add_logo_input_ = new QPushButton(QET::Icons::InsertImage, tr("Manage logos"));
// widgets specific to text cells
label_checkbox_ = new QCheckBox(tr("Display a label:"));
label_input_ = new QLineEdit();
label_input_ -> setReadOnly(true);
label_edit_ = new QPushButton(tr("Edit"));
value_label_ = new QLabel(tr("Text:"));
value_input_ = new QLineEdit();
value_input_ -> setReadOnly(true);
value_edit_ = new QPushButton(tr("Edit"));
align_label_ = new QLabel(tr("Alignment:"));
horiz_align_label_ = new QLabel(tr("horizontal:"));
horiz_align_input_ = new QComboBox();
horiz_align_input_ -> addItem(tr("Left"), Qt::AlignLeft);
horiz_align_input_ -> addItem(tr("Center"), Qt::AlignHCenter);
horiz_align_input_ -> addItem(tr("Right"), Qt::AlignRight);
horiz_align_indexes_.insert(Qt::AlignLeft, 0);
horiz_align_indexes_.insert(Qt::AlignHCenter, 1);
horiz_align_indexes_.insert(Qt::AlignRight, 2);
vert_align_label_= new QLabel(tr("vertical:"));
vert_align_input_ = new QComboBox();
vert_align_input_ -> addItem(tr("Top"), Qt::AlignTop);
vert_align_input_ -> addItem(tr("Middle"), Qt::AlignVCenter);
vert_align_input_ -> addItem(tr("Bottom"), Qt::AlignBottom);
vert_align_indexes_.insert(Qt::AlignTop, 0);
vert_align_indexes_.insert(Qt::AlignVCenter, 1);
vert_align_indexes_.insert(Qt::AlignBottom, 2);
font_size_label_ = new QLabel(tr("Font:"));
font_size_input_ = new QSpinBox();
font_adjust_input_ = new QCheckBox(tr("Adjust font size if needed"));
// layout
QHBoxLayout *label_edition = new QHBoxLayout();
label_edition -> addWidget(label_input_);
label_edition -> addWidget(label_edit_);
QHBoxLayout *value_edition = new QHBoxLayout();
value_edition -> addWidget(value_input_);
value_edition -> addWidget(value_edit_);
cell_editor_type_and_name_layout_ = new QHBoxLayout();
cell_editor_type_and_name_layout_ -> addWidget(cell_type_label_);
cell_editor_type_and_name_layout_ -> addWidget(cell_type_input_);
cell_editor_type_and_name_layout_ -> addWidget(name_label_);
cell_editor_type_and_name_layout_ -> addWidget(name_input_);
cell_editor_type_and_name_layout_ -> addStretch(5);
cell_editor_text_layout_ = new QGridLayout();
cell_editor_text_layout_ -> addWidget(label_checkbox_, 2, 0);
cell_editor_text_layout_ -> addLayout(label_edition, 2, 1);
cell_editor_text_layout_ -> addWidget(value_label_, 3, 0);
cell_editor_text_layout_ -> addLayout(value_edition, 3, 1);
cell_editor_text_layout_ -> addWidget(align_label_, 1, 2, 1, 2, Qt::AlignHCenter);
cell_editor_text_layout_ -> addWidget(horiz_align_label_, 2, 2);
cell_editor_text_layout_ -> addWidget(horiz_align_input_, 2, 3);
cell_editor_text_layout_ -> addWidget(vert_align_label_, 3, 2);
cell_editor_text_layout_ -> addWidget(vert_align_input_, 3, 3);
cell_editor_text_layout_ -> addWidget(font_size_label_, 4, 0);
cell_editor_text_layout_ -> addWidget(font_size_input_, 4, 1);
cell_editor_text_layout_ -> addWidget(font_adjust_input_, 4, 2, 1, 2, Qt::AlignLeft);
cell_editor_text_layout_ -> addWidget(logo_label_, 5, 0);
cell_editor_text_layout_ -> addWidget(logo_input_, 5, 1);
cell_editor_text_layout_ -> addWidget(add_logo_input_, 5, 2);
cell_editor_text_layout_ -> addWidget(empty_label_, 6, 0);
cell_editor_text_layout_ -> setColumnStretch(4, 4000);
cell_editor_layout_ = new QVBoxLayout();
cell_editor_layout_ -> addLayout(cell_editor_type_and_name_layout_);
cell_editor_layout_ -> addLayout(cell_editor_text_layout_);
cell_editor_layout_ -> addStretch();
setLayout(cell_editor_layout_);
// trigger the logo manager
connect(add_logo_input_, &QPushButton::released, this, &TitleBlockTemplateCellWidget::logoEditionRequested);
// handle cell modifications
connect(cell_type_input_, qOverload(&QComboBox::activated), this, &TitleBlockTemplateCellWidget::updateFormType);
connect(cell_type_input_, qOverload(&QComboBox::activated), this, &TitleBlockTemplateCellWidget::editType);
connect(name_input_, &QLineEdit::editingFinished, this, &TitleBlockTemplateCellWidget::editName);
connect(label_checkbox_, &QCheckBox::clicked, this, &TitleBlockTemplateCellWidget::editLabelDisplayed);
connect(label_edit_, &QPushButton::released, this, &TitleBlockTemplateCellWidget::editLabel);
connect(value_edit_, &QPushButton::released, this, &TitleBlockTemplateCellWidget::editValue);
connect(horiz_align_input_, qOverload(&QComboBox::activated), this, &TitleBlockTemplateCellWidget::editAlignment);
connect(vert_align_input_, qOverload(&QComboBox::activated), this, &TitleBlockTemplateCellWidget::editAlignment);
connect(font_size_input_, qOverload(&QSpinBox::valueChanged), this, &TitleBlockTemplateCellWidget::editFontSize);
connect(font_adjust_input_, &QCheckBox::clicked, this, &TitleBlockTemplateCellWidget::editAdjust);
connect(logo_input_, qOverload(&QComboBox::activated), this, &TitleBlockTemplateCellWidget::editLogo);
updateFormType(TitleBlockCell::TextCell);
}
/**
Shows or hides various widgets depending on the selected cell type
*/
void TitleBlockTemplateCellWidget::updateFormType(int cell_type) {
if (cell_type_input_ -> currentIndex() != cell_type) {
cell_type_input_ -> setCurrentIndex(cell_type);
}
name_label_ -> setVisible(cell_type);
name_input_ -> setVisible(cell_type);
empty_label_ -> setVisible(cell_type == TitleBlockCell::EmptyCell);
logo_label_ -> setVisible(cell_type == TitleBlockCell::LogoCell);
logo_input_ -> setVisible(cell_type == TitleBlockCell::LogoCell);
add_logo_input_ -> setVisible(cell_type == TitleBlockCell::LogoCell);
label_checkbox_ -> setVisible(cell_type == TitleBlockCell::TextCell);
label_input_ -> setVisible(cell_type == TitleBlockCell::TextCell);
label_edit_ -> setVisible(cell_type == TitleBlockCell::TextCell);
value_label_ -> setVisible(cell_type == TitleBlockCell::TextCell);
value_input_ -> setVisible(cell_type == TitleBlockCell::TextCell);
value_edit_ -> setVisible(cell_type == TitleBlockCell::TextCell);
align_label_ -> setVisible(cell_type == TitleBlockCell::TextCell);
horiz_align_label_ -> setVisible(cell_type == TitleBlockCell::TextCell);
horiz_align_input_ -> setVisible(cell_type == TitleBlockCell::TextCell);
vert_align_label_ -> setVisible(cell_type == TitleBlockCell::TextCell);
vert_align_input_ -> setVisible(cell_type == TitleBlockCell::TextCell);
font_size_label_ -> setVisible(cell_type == TitleBlockCell::TextCell);
font_size_input_ -> setVisible(cell_type == TitleBlockCell::TextCell);
font_adjust_input_ -> setVisible(cell_type == TitleBlockCell::TextCell);
}
/**
Set the title block cell to be edited. The cell pointer is stored by this
class; however, modifications made by the user are packaged as
ModifyTitleBlockCellCommand objects and emitted through the
cellModified() signal.
@param cell Title block cell to be edited
*/
void TitleBlockTemplateCellWidget::edit(TitleBlockCell *cell) {
if (!cell) return;
edited_cell_ = cell;
int type = cell -> type();
updateFormType(type);
name_input_ -> setText(cell -> value_name);
label_checkbox_ -> setChecked(cell -> display_label);
label_input_ -> setText(cell -> label.name());
value_input_ -> setText(cell -> value.name());
font_adjust_input_ -> setChecked(cell -> hadjust);
horiz_align_input_ -> setCurrentIndex(horiz_align_indexes_[cell -> horizontalAlign()]);
vert_align_input_ -> setCurrentIndex(vert_align_indexes_[cell -> verticalAlign()]);
font_size_input_ -> blockSignals(true); // QSpinBox has no signal triggered for each non-programmatic change
font_size_input_ -> setValue(TitleBlockTemplate::fontForCell(*cell).pointSize());
font_size_input_ -> blockSignals(false);
logo_input_ -> setCurrentIndex(logo_input_ -> findData(cell -> logo_reference));
}
/**
Emit a type modification command.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editType()
{
emitModification("type", cell_type_input_ -> itemData(cell_type_input_ -> currentIndex()));
}
/**
Emit a name modification command.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editName()
{
emitModification("name", name_input_ -> text());
}
/**
Emit a modification command stating whether the label should be displayed or not.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editLabelDisplayed()
{
emitModification("displaylabel", label_checkbox_ -> isChecked());
}
/**
Emit a label modification command.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editLabel()
{
if (!edited_cell_) return;
editTranslatableValue(edited_cell_ -> label, "label", tr("Label for this cell"));
label_input_ -> setText(edited_cell_ -> label.name());
}
/**
Emit a value modification command.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editValue()
{
if (!edited_cell_) return;
editTranslatableValue(edited_cell_ -> value, "value", tr("Value for this cell"));
value_input_ -> setText(edited_cell_ -> value.name());
}
/**
Emit an alignment modification command.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editAlignment()
{
emitModification("alignment", alignment());
}
/**
Emit a font size modification command.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editFontSize()
{
emitModification("fontsize", font_size_input_ -> value());
}
/**
Emit a modification command stating whether the text should be adjusted if needed.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editAdjust()
{
emitModification("horizontal_adjust", font_adjust_input_ -> isChecked());
}
/**
Emit a logo modification command.
@see ModifyTitleBlockCellCommand
*/
void TitleBlockTemplateCellWidget::editLogo()
{
emitModification("logo", logo_input_ -> currentText());
}
/**
Updates the list of available logos
@param parent_template The title block template which contains the currently edited cell
*/
void TitleBlockTemplateCellWidget::updateLogosComboBox(const TitleBlockTemplate *parent_template) {
// saves the current value before erasing all entries
QVariant current_value = logo_input_ -> itemData(logo_input_ -> currentIndex());
logo_input_ -> clear();
// default choice (the parent template may have no logo yet)
logo_input_ -> addItem(
tr("No logo", "text displayed in the combo box when a template has no logo"),
QVariant(QString(""))
);
logo_input_ -> setCurrentIndex(0);
if (!parent_template) return;
foreach (QString logo, parent_template -> logos()) {
logo_input_ -> addItem(logo, QVariant(logo));
}
int current_value_index = logo_input_ -> findData(current_value);
if (current_value_index != -1) {
logo_input_ -> setCurrentIndex(current_value_index);
}
}
/**
@param read_only whether this edition widget should be read only
*/
void TitleBlockTemplateCellWidget::setReadOnly(bool read_only) {
if (read_only_ == read_only) return;
read_only_ = read_only;
cell_type_input_ -> setEnabled(!read_only_);
logo_input_ -> setEnabled(!read_only_);
name_input_ -> setReadOnly(read_only_);
label_checkbox_ -> setEnabled(!read_only_);
label_edit_ -> setEnabled(!read_only_);
value_edit_ -> setEnabled(!read_only_);
horiz_align_input_ -> setEnabled(!read_only_);
vert_align_input_ -> setEnabled(!read_only_);
font_size_input_ -> setReadOnly(read_only_);
font_adjust_input_ -> setEnabled(!read_only_);
}
/**
Emit a horizontal alignment modification command.
@see ModifyTitleBlockCellCommand
*/
int TitleBlockTemplateCellWidget::horizontalAlignment() const
{
return(horiz_align_indexes_.key(horiz_align_input_ -> currentIndex()));
}
/**
Emit a vertical alignment modification command.
@see ModifyTitleBlockCellCommand
*/
int TitleBlockTemplateCellWidget::verticalAlignment() const
{
return(vert_align_indexes_.key(vert_align_input_ -> currentIndex()));
}
/**
@return the currently selected alignment.
*/
int TitleBlockTemplateCellWidget::alignment() const
{
return(horizontalAlignment() | verticalAlignment());
}
/**
@return whether this edition widget is read only
*/
bool TitleBlockTemplateCellWidget::isReadOnly() const
{
return(read_only_);
}
/**
Allow the user to edit a translatable string (e.g. value or label).
If the user modified the string, this method emits a
ModifyTitleBlockCellCommand object through the cellModified() signal.
@param names Translatable string to be edited
@param attribute Name of the edited cell attribute
@param title Title of the dialog window
*/
void TitleBlockTemplateCellWidget::editTranslatableValue(NamesList &names, const QString &attribute, const QString &title) const
{
NameListDialog dialog_;
dialog_.setWindowTitle(title);
dialog_.setInformationText(labelValueInformationString());
dialog_.setHelpText(defaultVariablesString());
NameListWidget *nlw_ = dialog_.namelistWidget();
nlw_->setNames(names);
nlw_->setClipboardValue(QETInformation::titleblockTranslatedKeyHashVar());
if(dialog_.exec() == QDialog::Accepted) {
emitModification(attribute, QVariant::fromValue(nlw_->names()));
}
}
/**
Create a ModifyTitleBlockCellCommand object to change \a attribute to \a new_value.
This object is then emitted through the cellModified() signal.
@see ModifyTitleBlockCellCommand
@param attribute Modified cell attribute
@param new_value New value for the modified cell attribute
*/
void TitleBlockTemplateCellWidget::emitModification(const QString &attribute, const QVariant &new_value) const
{
if (!edited_cell_) return;
// avoid creating a QUndoCommand object when no modification was actually done
if (edited_cell_ -> attribute(attribute) == new_value) return;
ModifyTitleBlockCellCommand *command = new ModifyTitleBlockCellCommand(edited_cell_);
command -> addModification(attribute, new_value);
command -> setText(
tr("Cell edition: %1", "label of and undo command when editing a cell")
.arg(TitleBlockCell::attributeName(attribute))
);
emit(cellModified(command));
}
/**
@return a string describing the various variables provided by default by
the application.
*/
QString TitleBlockTemplateCellWidget::defaultVariablesString() const
{
QString def_var_string = tr(
"By default, the following variables are available: - %{author}: author of "
"the sheet
- %{date}: sheet date
- %{title}: sheet "
"title
- %{filename}: filename of file
- %{plant}: name of the "
"installation (=) in which the sheet is located
- %{locmach}: name of the "
"location (+) where the sheet is located
- %{indexrev}: sheet revision "
"index
- %{version}: version number
- %{folio}: sheet "
"number
- %{folio-id}: position of sheet in the "
"project
- %{folio-total }: total number of sheets in the "
"project
- %{previous-folio-num}: number of the previous "
"sheet
- %{next-folio-num}: number of the next sheet< / "
"li>
- %{projecttitle}: title of the project
- %{projectpath}: path of the "
"project
- %{projectfilename}: filename of the projectfile
- %{saveddate}: date of saving the file in local format
- %{saveddate-eu}: "
"date of saving the file in format DD-MM-YYYY
- %{ saveddate-us}: date of "
"saving the file in format YYYY-MM-DD
- %{savedtime}: time of saving the "
"file
- %{savedfilename}: name of the file saved
- %{savedfilepath}: "
"path of the saved file
"
);
return(def_var_string);
}
/**
@return a string describing what the user may enter as cell label / value.
*/
QString TitleBlockTemplateCellWidget::labelValueInformationString() const
{
QString lab_val_inf_string = tr(
"Each cell of a title block displays a value, optionally preceded "
"by a label. Both can be translated to several languages.
Since "
"what you are currently editing is a title block template, "
"avoid entering raw data directly: prefer inserting variables like "
"%{variable-name}, which will be replaced afterwards with adequate "
"values in the sheet."
);
return(lab_val_inf_string);
}