mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-09-13 20:23:04 +02:00
Began implementing a WYSIWYG title block template editor.
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/branches/0.3@1405 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
parent
271242d207
commit
5b2a2249af
@ -54,11 +54,11 @@ DEFINES += QET_ALLOW_OVERRIDE_CD_OPTION
|
||||
|
||||
TEMPLATE = app
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += sources sources/editor
|
||||
INCLUDEPATH += sources sources/editor sources/titleblock
|
||||
|
||||
# Fichiers sources
|
||||
HEADERS += sources/*.h sources/editor/*.h
|
||||
SOURCES += sources/*.cpp sources/editor/*.cpp
|
||||
HEADERS += sources/*.h sources/editor/*.h sources/titleblock/*.h
|
||||
SOURCES += sources/*.cpp sources/editor/*.cpp sources/titleblock/*.cpp
|
||||
|
||||
# Liste des fichiers qui seront incorpores au binaire en tant que ressources Qt
|
||||
RESOURCES += qelectrotech.qrc
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "fileelementscollection.h"
|
||||
#include "titleblocktemplate.h"
|
||||
#include "templateeditor.h"
|
||||
#include "qettemplateeditor.h"
|
||||
#include "qetproject.h"
|
||||
#include "qtextorientationspinboxwidget.h"
|
||||
#include "recentfiles.h"
|
||||
@ -862,13 +863,9 @@ void QETApp::openElementLocations(const QList<ElementsLocation> &locations_list)
|
||||
launched for a template creation.
|
||||
*/
|
||||
void QETApp::openTitleBlockTemplate(QETProject *project, const QString &template_name) {
|
||||
TemplateEditor *editor = new TemplateEditor();
|
||||
bool can_edit = editor -> edit(project, template_name);
|
||||
if (can_edit) {
|
||||
editor -> showNormal();
|
||||
} else {
|
||||
QMessageBox::warning(0, tr("Erreur"), tr("Impossible d'\351diter le template demand\351"));
|
||||
}
|
||||
QETTitleBlockTemplateEditor *qet_template_editor = new QETTitleBlockTemplateEditor();
|
||||
qet_template_editor -> edit(project, template_name);
|
||||
qet_template_editor -> showMaximized();
|
||||
}
|
||||
|
||||
/**
|
||||
|
58
sources/titleblock/dimension.cpp
Normal file
58
sources/titleblock/dimension.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "dimension.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param v Numeric value for this dimension
|
||||
@param t Kind of length, determining how to interpret the numeric value
|
||||
*/
|
||||
TitleBlockDimension::TitleBlockDimension(int v, QET::TitleBlockColumnLength t) :
|
||||
type(t),
|
||||
value(v)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
@return a string describing this dimension in a human-readable format.
|
||||
*/
|
||||
QString TitleBlockDimension::toString() const {
|
||||
QString dim_str;
|
||||
if (type == QET::Absolute) {
|
||||
dim_str = QObject::tr("%1px", "titleblock: absolute width");
|
||||
} else if (type == QET::RelativeToTotalLength) {
|
||||
dim_str = QObject::tr("%1%", "titleblock: width relative to total length");
|
||||
} else if (type == QET::RelativeToRemainingLength) {
|
||||
dim_str = QObject::tr("%1% du restant", "titleblock: width relative to remaining length");
|
||||
}
|
||||
return(dim_str.arg(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return a string describing this dimension in a short format.
|
||||
*/
|
||||
QString TitleBlockDimension::toShortString() const {
|
||||
QString short_string;
|
||||
if (type == QET::RelativeToTotalLength) {
|
||||
short_string = "t";
|
||||
} else if (type == QET::RelativeToRemainingLength) {
|
||||
short_string = "r";
|
||||
}
|
||||
short_string += QString("%1%2;").arg(value).arg(type == QET::Absolute ? "px" : "%");
|
||||
return(short_string);
|
||||
}
|
36
sources/titleblock/dimension.h
Normal file
36
sources/titleblock/dimension.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_DIMENSION_H
|
||||
#define TITLEBLOCK_SLASH_DIMENSION_H
|
||||
#include "qet.h"
|
||||
|
||||
/**
|
||||
This struct is a simple container associating a length with its type.
|
||||
@see TitleBlockColumnLength
|
||||
*/
|
||||
struct TitleBlockDimension {
|
||||
// constructor
|
||||
TitleBlockDimension(int, QET::TitleBlockColumnLength = QET::Absolute);
|
||||
// methods
|
||||
QString toString() const;
|
||||
QString toShortString() const;
|
||||
// attribute
|
||||
QET::TitleBlockColumnLength type; ///< Kind of length
|
||||
int value; ///< Numeric value
|
||||
};
|
||||
#endif
|
149
sources/titleblock/dimensionwidget.cpp
Normal file
149
sources/titleblock/dimensionwidget.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "dimensionwidget.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param complete True for this dialog to show the radio buttons that allow
|
||||
the user to specify whether the dimension is absolute, relative to the
|
||||
total width or relative to the remaining width.
|
||||
@param parent Parent QWidget
|
||||
*/
|
||||
TitleBlockDimensionWidget::TitleBlockDimensionWidget(bool complete, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
complete_(complete)
|
||||
{
|
||||
initWidgets();
|
||||
initLayouts();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
TitleBlockDimensionWidget::~TitleBlockDimensionWidget() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this dialog shows the optional radio buttons
|
||||
*/
|
||||
bool TitleBlockDimensionWidget::isComplete() const {
|
||||
return(complete_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return a pointer to the label displayed right before the spinbox.
|
||||
Useful to specify a custom text.
|
||||
*/
|
||||
QLabel *TitleBlockDimensionWidget::label() const {
|
||||
return(spinbox_label_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return a pointer to the spinbox
|
||||
Useful to specify custom parameters, such as the minimum value
|
||||
*/
|
||||
QSpinBox *TitleBlockDimensionWidget::spinbox() const {
|
||||
return(spinbox_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return The dimension as currently shown by the dialog
|
||||
*/
|
||||
TitleBlockDimension TitleBlockDimensionWidget::value() const {
|
||||
QET::TitleBlockColumnLength type = QET::Absolute;
|
||||
if (complete_) {
|
||||
type = static_cast<QET::TitleBlockColumnLength>(dimension_type_ -> checkedId());
|
||||
}
|
||||
return(TitleBlockDimension(spinbox_ -> value(), type));
|
||||
}
|
||||
|
||||
/**
|
||||
@param dim Dimension to be displayed and edited by this dialog
|
||||
*/
|
||||
void TitleBlockDimensionWidget::setValue(const TitleBlockDimension &dim) {
|
||||
spinbox_ -> setValue(dim.value);
|
||||
if (complete_) {
|
||||
if (QAbstractButton *button = dimension_type_ -> button(dim.type)) {
|
||||
button -> setChecked(true);
|
||||
}
|
||||
}
|
||||
updateSpinBoxSuffix();
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the widgets composing the dialog.
|
||||
*/
|
||||
void TitleBlockDimensionWidget::initWidgets() {
|
||||
// basic widgets: label + spinbox
|
||||
spinbox_label_ = new QLabel(tr("Largeur :", "default dialog label"));
|
||||
|
||||
spinbox_ = new QSpinBox();
|
||||
spinbox_ -> setMinimum(5);
|
||||
spinbox_ -> setMaximum(10000);
|
||||
spinbox_ -> setValue(50);
|
||||
|
||||
// extra widgets, for the user to specify whether the value is absolute, relative, etc.
|
||||
if (complete_) {
|
||||
absolute_button_ = new QRadioButton(tr("Absolu"));
|
||||
relative_button_ = new QRadioButton(tr("Relatif au total"));
|
||||
remaining_button_ = new QRadioButton(tr("Relatif au restant"));
|
||||
dimension_type_ = new QButtonGroup(this);
|
||||
dimension_type_ -> addButton(absolute_button_, QET::Absolute);
|
||||
dimension_type_ -> addButton(relative_button_, QET::RelativeToTotalLength);
|
||||
dimension_type_ -> addButton(remaining_button_, QET::RelativeToRemainingLength);
|
||||
absolute_button_ -> setChecked(true);
|
||||
connect(dimension_type_, SIGNAL(buttonClicked(int)), this, SLOT(updateSpinBoxSuffix()));
|
||||
}
|
||||
|
||||
updateSpinBoxSuffix();
|
||||
|
||||
// buttons, for the user to validate its input
|
||||
buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttons_, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttons_, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the layout of the dialog.
|
||||
*/
|
||||
void TitleBlockDimensionWidget::initLayouts() {
|
||||
QHBoxLayout *hlayout0 = new QHBoxLayout();
|
||||
hlayout0 -> addWidget(spinbox_label_);
|
||||
hlayout0 -> addWidget(spinbox_);
|
||||
QVBoxLayout *vlayout0 = new QVBoxLayout();
|
||||
vlayout0 -> addLayout(hlayout0);
|
||||
if (complete_) {
|
||||
vlayout0 -> addWidget(absolute_button_);
|
||||
vlayout0 -> addWidget(relative_button_);
|
||||
vlayout0 -> addWidget(remaining_button_);
|
||||
}
|
||||
vlayout0 -> addWidget(buttons_);
|
||||
setLayout(vlayout0);
|
||||
}
|
||||
|
||||
/**
|
||||
Ensure the suffix displayed by the spinbox matches the selected kind of length.
|
||||
*/
|
||||
void TitleBlockDimensionWidget::updateSpinBoxSuffix() {
|
||||
if (complete_ && dimension_type_ -> checkedId() != QET::Absolute) {
|
||||
spinbox_ -> setSuffix(tr("%", "spinbox suffix when changing the dimension of a row/column"));
|
||||
} else {
|
||||
spinbox_ -> setSuffix(tr("px", "spinbox suffix when changing the dimension of a row/column"));
|
||||
}
|
||||
spinbox_ -> selectAll();
|
||||
}
|
62
sources/titleblock/dimensionwidget.h
Normal file
62
sources/titleblock/dimensionwidget.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_DIMENSION_WIDGET_H
|
||||
#define TITLEBLOCK_SLASH_DIMENSION_WIDGET_H
|
||||
#include <QtGui>
|
||||
#include "dimension.h"
|
||||
|
||||
/**
|
||||
This class represents a dialog for the user to input a dimension: a row
|
||||
height, a column width, etc.
|
||||
*/
|
||||
class TitleBlockDimensionWidget : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
// constructors, destructor
|
||||
public:
|
||||
TitleBlockDimensionWidget(bool, QWidget * parent = 0);
|
||||
virtual ~TitleBlockDimensionWidget();
|
||||
private:
|
||||
TitleBlockDimensionWidget(const TitleBlockDimensionWidget &);
|
||||
|
||||
// methods
|
||||
public:
|
||||
bool isComplete() const;
|
||||
QLabel *label() const;
|
||||
QSpinBox *spinbox() const;
|
||||
TitleBlockDimension value() const;
|
||||
void setValue(const TitleBlockDimension &);
|
||||
private:
|
||||
void initWidgets();
|
||||
void initLayouts();
|
||||
|
||||
private slots:
|
||||
void updateSpinBoxSuffix();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
bool complete_; ///< Whether or not this dialog is required to be complete, i.e. displaying also
|
||||
QSpinBox *spinbox_; ///< Spinbox displaying the length
|
||||
QLabel *spinbox_label_; ///< Label shown right before the spinbox
|
||||
QRadioButton *absolute_button_; ///< Radio button to indicate the length is absolute
|
||||
QRadioButton *relative_button_; ///< Radio button to indicate the length is relative to the total length
|
||||
QRadioButton *remaining_button_; ///< Radio button to indicate the length is relative to the remaining length
|
||||
QButtonGroup *dimension_type_; ///< QButtonGroup for the three radio buttons
|
||||
QDialogButtonBox *buttons_; ///< Buttons to validate the dialog
|
||||
};
|
||||
#endif
|
90
sources/titleblock/gridlayoutanimation.cpp
Normal file
90
sources/titleblock/gridlayoutanimation.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "gridlayoutanimation.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param grid Grid to be animated
|
||||
@param parent Parent QObject
|
||||
*/
|
||||
GridLayoutAnimation::GridLayoutAnimation(QGraphicsGridLayout *grid, QObject *parent) :
|
||||
QVariantAnimation(parent),
|
||||
grid_(grid)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
GridLayoutAnimation::~GridLayoutAnimation() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return the animated grid
|
||||
*/
|
||||
QGraphicsGridLayout *GridLayoutAnimation::grid() {
|
||||
return(grid_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param grid The grid to be animated
|
||||
*/
|
||||
void GridLayoutAnimation::setGrid(QGraphicsGridLayout *grid) {
|
||||
grid_ = grid;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the index of the row/column to be animated
|
||||
*/
|
||||
int GridLayoutAnimation::index() const {
|
||||
return(index_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param index the index of the row/column to be animated
|
||||
*/
|
||||
void GridLayoutAnimation::setIndex(int index) {
|
||||
index_ = index;
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this object acts on a row, false if it acts on a column.
|
||||
*/
|
||||
bool GridLayoutAnimation::actsOnRows() const {
|
||||
return(row_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param acts_on_row true for this object to act on a row, false for it to
|
||||
act on a column.
|
||||
*/
|
||||
void GridLayoutAnimation::setActsOnRows(bool acts_on_row) {
|
||||
row_ = acts_on_row;
|
||||
}
|
||||
|
||||
/**
|
||||
Implementation of QVariantAnimation::updateCurrentValue().
|
||||
*/
|
||||
void GridLayoutAnimation::updateCurrentValue(const QVariant &value) {
|
||||
if (!grid_) return;
|
||||
if (row_) {
|
||||
grid_ -> setRowFixedHeight(index_, value.toReal());
|
||||
} else {
|
||||
grid_ -> setColumnFixedWidth(index_, value.toReal());
|
||||
}
|
||||
}
|
50
sources/titleblock/gridlayoutanimation.h
Normal file
50
sources/titleblock/gridlayoutanimation.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_GRID_LAYOUT_ANIMATION_H
|
||||
#define TITLEBLOCK_SLASH_GRID_LAYOUT_ANIMATION_H
|
||||
#include <QtGui>
|
||||
|
||||
/**
|
||||
This class allows animating a dimension change for a QGraphicsGridLayout
|
||||
row or column.
|
||||
*/
|
||||
class GridLayoutAnimation : public QVariantAnimation {
|
||||
// Constructors, destructor
|
||||
public:
|
||||
GridLayoutAnimation(QGraphicsGridLayout * = 0, QObject * = 0);
|
||||
virtual ~GridLayoutAnimation();
|
||||
|
||||
// methods
|
||||
public:
|
||||
QGraphicsGridLayout *grid();
|
||||
void setGrid(QGraphicsGridLayout *);
|
||||
int index() const;
|
||||
void setIndex(int);
|
||||
bool actsOnRows() const;
|
||||
void setActsOnRows(bool);
|
||||
|
||||
protected:
|
||||
void updateCurrentValue(const QVariant &);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
QGraphicsGridLayout *grid_; ///< Grid this class will animate
|
||||
bool row_; ///< Whether we should animate a row or a column
|
||||
int index_; ///< Index of the row/column to be animated
|
||||
};
|
||||
#endif
|
142
sources/titleblock/helpercell.cpp
Normal file
142
sources/titleblock/helpercell.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "helpercell.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param parent Parent QGraphicsItem
|
||||
*/
|
||||
HelperCell::HelperCell(QGraphicsItem *parent) :
|
||||
QGraphicsObject(parent),
|
||||
QGraphicsLayoutItem(),
|
||||
background_color(Qt::white),
|
||||
foreground_color(Qt::black),
|
||||
label(),
|
||||
orientation(Qt::Horizontal),
|
||||
index(-1)
|
||||
{
|
||||
setGraphicsItem(this);
|
||||
setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
HelperCell::~HelperCell() {
|
||||
}
|
||||
|
||||
/**
|
||||
Ensure geometry changes are handled for both QGraphicsObject and
|
||||
QGraphicsLayoutItem.
|
||||
@param g New geometry
|
||||
*/
|
||||
void HelperCell::setGeometry(const QRectF &g) {
|
||||
prepareGeometryChange();
|
||||
QGraphicsLayoutItem::setGeometry(g);
|
||||
setPos(g.topLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
@param which Size hint to be modified
|
||||
@param constraint New value for the size hint
|
||||
@return the size hint for \a which using the width or height of \a constraint
|
||||
*/
|
||||
QSizeF HelperCell::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const {
|
||||
Q_UNUSED(which);
|
||||
return(constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the bounding rect of this helper cell
|
||||
*/
|
||||
QRectF HelperCell::boundingRect() const {
|
||||
return QRectF(QPointF(0,0), geometry().size());
|
||||
}
|
||||
|
||||
/**
|
||||
Handles the helper cell visual rendering
|
||||
@param painter QPainter to be used for the rendering
|
||||
@param option Rendering options
|
||||
@param widget QWidget being painted, if any
|
||||
*/
|
||||
void HelperCell::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
|
||||
Q_UNUSED(option);
|
||||
Q_UNUSED(widget);
|
||||
|
||||
QRectF drawing_rectangle(QPointF(0, 0), geometry().size());
|
||||
|
||||
painter -> setPen(Qt::black);
|
||||
painter -> setBrush(background_color);
|
||||
painter -> drawRect(drawing_rectangle);
|
||||
|
||||
painter -> setPen(foreground_color);
|
||||
painter -> drawText(drawing_rectangle, Qt::AlignHCenter | Qt::AlignVCenter, label);
|
||||
}
|
||||
|
||||
/**
|
||||
@param type new type of this helper cell -- @see QET::TitleBlockColumnLength
|
||||
*/
|
||||
void HelperCell::setType(QET::TitleBlockColumnLength type) {
|
||||
if (type == QET::Absolute) {
|
||||
background_color = QColor("#C0FFFF");
|
||||
foreground_color = Qt::black;
|
||||
} else if (type == QET::RelativeToTotalLength) {
|
||||
background_color = QColor("#FFA858");
|
||||
foreground_color = Qt::black;
|
||||
} else if (type == QET::RelativeToRemainingLength) {
|
||||
background_color = QColor("#FFC0C0");
|
||||
foreground_color = Qt::black;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Set the list of actions displayed by the context menu of this helper cell.
|
||||
*/
|
||||
void HelperCell::setActions(const QList<QAction *> &actions) {
|
||||
actions_ = actions;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the list of actions displayed by the context menu of this helper cell.
|
||||
*/
|
||||
QList<QAction *> HelperCell::actions() const {
|
||||
return actions_;
|
||||
}
|
||||
|
||||
/**
|
||||
Handle context menu events.
|
||||
@param event Context menu event.
|
||||
*/
|
||||
void HelperCell::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
|
||||
if (actions_.isEmpty()) return;
|
||||
|
||||
QMenu context_menu;
|
||||
foreach (QAction *action, actions_) {
|
||||
context_menu.addAction(action);
|
||||
}
|
||||
emit(contextMenuTriggered(this));
|
||||
context_menu.exec(event -> screenPos());
|
||||
}
|
||||
|
||||
/**
|
||||
Handle double click events.
|
||||
*/
|
||||
void HelperCell::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
|
||||
|
||||
emit(doubleClicked(this));
|
||||
}
|
67
sources/titleblock/helpercell.h
Normal file
67
sources/titleblock/helpercell.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_HELPER_CELL_H
|
||||
#define TITLEBLOCK_SLASH_HELPER_CELL_H
|
||||
#include <QtGui>
|
||||
#include "qet.h"
|
||||
|
||||
/**
|
||||
This class implements a helper widget for cells that indicate the length of
|
||||
columns and rows.
|
||||
*/
|
||||
class HelperCell : public QGraphicsObject, public QGraphicsLayoutItem {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QGraphicsLayoutItem)
|
||||
|
||||
// constructor, destructor
|
||||
public:
|
||||
HelperCell(QGraphicsItem * = 0);
|
||||
virtual ~HelperCell();
|
||||
private:
|
||||
HelperCell(const HelperCell &);
|
||||
|
||||
// attributes
|
||||
public:
|
||||
QColor background_color; ///< Background color when rendering this cell
|
||||
QColor foreground_color; ///< Text color when rendering this cell
|
||||
QString label; ///< Label displayed in this cell
|
||||
Qt::Orientation orientation; ///< Orientation of this cell
|
||||
int index; ///< Index of this cell
|
||||
|
||||
// methods
|
||||
public:
|
||||
virtual void setGeometry(const QRectF &);
|
||||
virtual QSizeF sizeHint(Qt::SizeHint, const QSizeF & = QSizeF()) const;
|
||||
virtual QRectF boundingRect() const;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual void setType(QET::TitleBlockColumnLength);
|
||||
virtual void setActions(const QList<QAction *> &);
|
||||
virtual QList<QAction *> actions() const;
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent *);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
|
||||
|
||||
signals:
|
||||
void contextMenuTriggered(HelperCell *);
|
||||
void doubleClicked(HelperCell *);
|
||||
|
||||
private:
|
||||
QList<QAction *> actions_; ///< List of actions displayed by the context menu
|
||||
};
|
||||
#endif
|
295
sources/titleblock/qettemplateeditor.cpp
Normal file
295
sources/titleblock/qettemplateeditor.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "qettemplateeditor.h"
|
||||
#include "qeticons.h"
|
||||
#include "qetapp.h"
|
||||
#include "qetproject.h"
|
||||
#include "templatecellwidget.h"
|
||||
#include "templatecommands.h"
|
||||
#include "templateview.h"
|
||||
#include "templatelogomanager.h"
|
||||
#include "templatecellwidget.h"
|
||||
|
||||
/**
|
||||
@param parent parent QWidget of this window
|
||||
*/
|
||||
QETTitleBlockTemplateEditor::QETTitleBlockTemplateEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
read_only(false),
|
||||
parent_project_(0),
|
||||
tb_template_(0),
|
||||
logo_manager_(0)
|
||||
{
|
||||
initWidgets();
|
||||
initActions();
|
||||
initMenus();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
QETTitleBlockTemplateEditor::~QETTitleBlockTemplateEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Edit the given template.
|
||||
@param project Parent project of the template to edit.
|
||||
@param template_name Name of the template to edit within its parent project.
|
||||
@return true if this editor was able to edit the given template, false otherwise
|
||||
*/
|
||||
bool QETTitleBlockTemplateEditor::edit(QETProject *project, const QString &template_name) {
|
||||
// we require a project we will rattach templates to
|
||||
if (!project) return(false);
|
||||
|
||||
// the template name may be empty to create a new one
|
||||
const TitleBlockTemplate *tb_template_orig;
|
||||
if (template_name.isEmpty()) {
|
||||
// loads the default title block template provided by the application
|
||||
// it will be used as a start point to design the title block
|
||||
tb_template_orig = QETApp::defaultTitleBlockTemplate();
|
||||
} else {
|
||||
tb_template_orig = project -> getTemplateByName(template_name);
|
||||
}
|
||||
|
||||
if (!tb_template_orig) {
|
||||
/// TODO The TBT does not exist, manage error
|
||||
return(false);
|
||||
}
|
||||
|
||||
tb_template_ = tb_template_orig -> clone();
|
||||
parent_project_ = project;
|
||||
template_name_ = template_name;
|
||||
template_edition_area_view_ -> setTitleBlockTemplate(tb_template_);
|
||||
template_cell_editor_widget_ -> updateLogosComboBox(tb_template_);
|
||||
updateEditorTitle();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Launches the logo manager widget, which allows the user to manage the
|
||||
logos embedded within the edited template.
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::editLogos() {
|
||||
if (tb_template_) {
|
||||
if (!logo_manager_) {
|
||||
logo_manager_ = new TitleBlockTemplateLogoManager(tb_template_);
|
||||
}
|
||||
logo_manager_ -> show();
|
||||
template_cell_editor_widget_ -> updateLogosComboBox(tb_template_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the various actions.
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::initActions() {
|
||||
QETApp *qet_app = QETApp::instance();
|
||||
|
||||
save_ = new QAction(QET::Icons::DocumentSave, tr("&Enregistrer"), this);
|
||||
quit_ = new QAction(QET::Icons::ApplicationExit, tr("&Quitter"), this);
|
||||
configure_ = new QAction(QET::Icons::Configure, tr("&Configurer QElectroTech"), this);
|
||||
about_qet_ = new QAction(QET::Icons::QETLogo, tr("\300 &propos de QElectroTech"), this);
|
||||
about_qt_ = new QAction(QET::Icons::QtLogo, tr("\300 propos de &Qt"), this);
|
||||
merge_cells_ = new QAction(tr("&Fusionner les cellules"), this);
|
||||
split_cell_ = new QAction(tr("&S\351parer les cellules"), this);
|
||||
|
||||
save_ -> setShortcut(QKeySequence::Save);
|
||||
quit_ -> setShortcut(QKeySequence(tr("Ctrl+Q", "shortcut to quit")));
|
||||
merge_cells_ -> setShortcut(QKeySequence(tr("Ctrl+K", "shortcut to merge cells")));
|
||||
split_cell_ -> setShortcut(QKeySequence(tr("Ctrl+J", "shortcut to split merged cell")));
|
||||
|
||||
configure_ -> setStatusTip(tr("Permet de r\351gler diff\351rents param\350tres de QElectroTech", "status bar tip"));
|
||||
about_qet_ -> setStatusTip(tr("Affiche des informations sur QElectroTech", "status bar tip"));
|
||||
about_qt_ -> setStatusTip(tr("Affiche des informations sur la biblioth\350que Qt", "status bar tip"));
|
||||
|
||||
connect(save_, SIGNAL(triggered()), this, SLOT(save()));
|
||||
connect(quit_, SIGNAL(triggered()), this, SLOT(quit()));
|
||||
connect(configure_, SIGNAL(triggered()), qet_app, SLOT(configureQET()));
|
||||
connect(about_qet_, SIGNAL(triggered()), qet_app, SLOT(aboutQET()));
|
||||
connect(about_qt_, SIGNAL(triggered()), qet_app, SLOT(aboutQt()));
|
||||
connect(merge_cells_, SIGNAL(triggered()), template_edition_area_view_, SLOT(mergeSelectedCells()));
|
||||
connect(split_cell_, SIGNAL(triggered()), template_edition_area_view_, SLOT(splitSelectedCell()));
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the various menus.
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::initMenus() {
|
||||
file_menu_ = new QMenu(tr("&Fichier"), this);
|
||||
edit_menu_ = new QMenu(tr("&\311dition"), this);
|
||||
config_menu_ = new QMenu(tr("&Configuration"), this);
|
||||
help_menu_ = new QMenu(tr("&Aide"), this);
|
||||
|
||||
file_menu_ -> setTearOffEnabled(true);
|
||||
edit_menu_ -> setTearOffEnabled(true);
|
||||
config_menu_ -> setTearOffEnabled(true);
|
||||
help_menu_ -> setTearOffEnabled(true);
|
||||
|
||||
file_menu_ -> addAction(save_);
|
||||
file_menu_ -> addSeparator();
|
||||
file_menu_ -> addAction(quit_);
|
||||
|
||||
edit_menu_ -> addAction(merge_cells_);
|
||||
edit_menu_ -> addAction(split_cell_);
|
||||
|
||||
config_menu_ -> addAction(configure_);
|
||||
|
||||
help_menu_ -> addAction(about_qet_);
|
||||
help_menu_ -> addAction(about_qt_);
|
||||
|
||||
menuBar() -> addMenu(file_menu_);
|
||||
menuBar() -> addMenu(edit_menu_);
|
||||
menuBar() -> addMenu(config_menu_);
|
||||
menuBar() -> addMenu(help_menu_);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize layouts and widgets
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::initWidgets() {
|
||||
// undo list on the right
|
||||
undo_stack_ = new QUndoStack(this);
|
||||
undo_view_ = new QUndoView(undo_stack_);
|
||||
undo_view_ -> setEmptyLabel(tr("Aucune modification", "label displayed in the undo list when empty"));
|
||||
|
||||
undo_dock_widget_ = new QDockWidget(tr("Annulations", "dock title"));
|
||||
undo_dock_widget_ -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
undo_dock_widget_ -> setWidget(undo_view_);
|
||||
undo_dock_widget_ -> setMinimumWidth(290);
|
||||
addDockWidget(Qt::RightDockWidgetArea, undo_dock_widget_);
|
||||
|
||||
// WYSIWYG editor as central widget
|
||||
template_edition_area_scene_ = new QGraphicsScene(this);
|
||||
template_edition_area_view_ = new TitleBlockTemplateView(template_edition_area_scene_);
|
||||
setCentralWidget(template_edition_area_view_);
|
||||
|
||||
// cell edition widget at the bottom
|
||||
template_cell_editor_widget_ = new TitleBlockTemplateCellWidget(tb_template_);
|
||||
template_cell_editor_dock_widget_ = new QDockWidget(tr("Propri\351t\351s de la cellule", "dock title"), this);
|
||||
template_cell_editor_dock_widget_ -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
template_cell_editor_dock_widget_ -> setWidget(template_cell_editor_widget_);
|
||||
template_cell_editor_dock_widget_ -> setMinimumWidth(180);
|
||||
template_cell_editor_dock_widget_ -> setMinimumHeight(250);
|
||||
addDockWidget(Qt::BottomDockWidgetArea, template_cell_editor_dock_widget_);
|
||||
template_cell_editor_widget_ -> setVisible(false);
|
||||
|
||||
connect(
|
||||
template_edition_area_view_,
|
||||
SIGNAL(selectedCellsChanged(QList<TitleBlockCell *>)),
|
||||
this,
|
||||
SLOT(selectedCellsChanged(QList<TitleBlockCell *>))
|
||||
);
|
||||
connect(template_cell_editor_widget_, SIGNAL(logoEditionRequested()), this, SLOT(editLogos()));
|
||||
connect(
|
||||
template_cell_editor_widget_,
|
||||
SIGNAL(cellModified(ModifyTitleBlockCellCommand *)),
|
||||
this,
|
||||
SLOT(pushCellUndoCommand(ModifyTitleBlockCellCommand *))
|
||||
);
|
||||
connect(
|
||||
template_edition_area_view_,
|
||||
SIGNAL(gridModificationRequested(TitleBlockTemplateCommand *)),
|
||||
this,
|
||||
SLOT(pushGridUndoCommand(TitleBlockTemplateCommand *))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Update various things when user changes the selected cells.
|
||||
@param selected_cells List of selected cells.
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::selectedCellsChanged(QList<TitleBlockCell *> selected_cells) {
|
||||
if (selected_cells.count() == 1) {
|
||||
template_cell_editor_widget_ -> edit(selected_cells.at(0));
|
||||
template_cell_editor_widget_ -> setVisible(true);
|
||||
} else {
|
||||
template_cell_editor_widget_ -> setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Configure an undo Command before adding it to the undo stack.
|
||||
@param command to be added to the undo stack
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::pushCellUndoCommand(ModifyTitleBlockCellCommand *command) {
|
||||
command -> setView(template_edition_area_view_);
|
||||
pushUndoCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
Add an undo Command to the undo stack.
|
||||
@param command QUndoCommand to be added to the undo stack
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::pushGridUndoCommand(TitleBlockTemplateCommand *command) {
|
||||
pushUndoCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
Add an undo Command to the undo stack.
|
||||
@param command QUndoCommand to be added to the undo stack
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::pushUndoCommand(QUndoCommand *command) {
|
||||
undo_stack_ -> push(command);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the title of this editor.
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::updateEditorTitle() {
|
||||
QString min_title(
|
||||
tr(
|
||||
"QElectroTech - \311diteur de mod\350le de cartouche",
|
||||
"titleblock template editor: base window title"
|
||||
)
|
||||
);
|
||||
|
||||
QString title;
|
||||
if (template_name_.isEmpty()) {
|
||||
title = min_title;
|
||||
} else {
|
||||
title = QString(
|
||||
tr(
|
||||
"%1 - %2",
|
||||
"window title: %1 is the base window title, %2 is a template name"
|
||||
)
|
||||
).arg(min_title).arg(template_name_);
|
||||
}
|
||||
setWindowTitle(title);
|
||||
}
|
||||
|
||||
/**
|
||||
Save the currently edited title block template back to its parent project.
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::save() {
|
||||
QDomDocument doc;
|
||||
QDomElement elmt = doc.createElement("root");
|
||||
tb_template_ -> saveToXmlElement(elmt);
|
||||
doc.appendChild(elmt);
|
||||
|
||||
if (parent_project_ && !template_name_.isEmpty()) {
|
||||
parent_project_ -> setTemplateXmlDescription(template_name_, elmt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Close the current editor.
|
||||
*/
|
||||
void QETTitleBlockTemplateEditor::quit() {
|
||||
/// TODO save if needed
|
||||
close();
|
||||
}
|
95
sources/titleblock/qettemplateeditor.h
Normal file
95
sources/titleblock/qettemplateeditor.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_QET_TEMPLATE_EDITOR_H
|
||||
#define TITLEBLOCK_SLASH_QET_TEMPLATE_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "qet.h"
|
||||
#include "templateview.h"
|
||||
class ModifyTitleBlockCellCommand;
|
||||
class TitleBlockTemplateCommand;
|
||||
class TitleBlockTemplateCellWidget;
|
||||
class TitleBlockTemplateLogoManager;
|
||||
class QETProject;
|
||||
|
||||
/**
|
||||
This class implements the main window of QElectroTech's titleblock template
|
||||
editor. This editor aims at allowing users to easily create their own title
|
||||
block templates.
|
||||
*/
|
||||
class QETTitleBlockTemplateEditor : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
// constructor, destructor
|
||||
public:
|
||||
QETTitleBlockTemplateEditor(QWidget * = 0);
|
||||
virtual ~QETTitleBlockTemplateEditor();
|
||||
private:
|
||||
QETTitleBlockTemplateEditor(const QETTitleBlockTemplateEditor &);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
/// is the template read-only?
|
||||
bool read_only;
|
||||
/// menus TODO
|
||||
QMenu *file_menu_, *edit_menu_,/* *paste_from_menu_, *display_menu_, *tools_menu_,*/ *config_menu_, *help_menu_;
|
||||
/// actions
|
||||
QAction *save_, *quit_, *configure_, *about_qt_, *about_qet_, *merge_cells_, *split_cell_;
|
||||
/// Parent project of the currently edited template
|
||||
QETProject *parent_project_;
|
||||
/// Name of the currently edited template
|
||||
QString template_name_;
|
||||
/// Template Object edited
|
||||
TitleBlockTemplate *tb_template_;
|
||||
/// Template preview
|
||||
QGraphicsScene *template_edition_area_scene_;
|
||||
TitleBlockTemplateView *template_edition_area_view_;
|
||||
/// Individual cell widget edition
|
||||
QDockWidget *template_cell_editor_dock_widget_;
|
||||
TitleBlockTemplateCellWidget *template_cell_editor_widget_;
|
||||
/// Logo manager widget
|
||||
TitleBlockTemplateLogoManager *logo_manager_;
|
||||
/// Undo interface
|
||||
QUndoStack *undo_stack_;
|
||||
QUndoView *undo_view_;
|
||||
QDockWidget *undo_dock_widget_;
|
||||
|
||||
// methods
|
||||
public:
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
void initActions();
|
||||
void initMenus();
|
||||
void initWidgets();
|
||||
|
||||
public slots:
|
||||
void selectedCellsChanged(QList<TitleBlockCell *>);
|
||||
bool edit(QETProject *, const QString &);
|
||||
void editLogos();
|
||||
|
||||
private slots:
|
||||
void pushCellUndoCommand(ModifyTitleBlockCellCommand *);
|
||||
void pushGridUndoCommand(TitleBlockTemplateCommand *);
|
||||
void pushUndoCommand(QUndoCommand *);
|
||||
void updateEditorTitle();
|
||||
void save();
|
||||
void quit();
|
||||
};
|
||||
|
||||
#endif
|
63
sources/titleblock/splittedhelpercell.cpp
Normal file
63
sources/titleblock/splittedhelpercell.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "splittedhelpercell.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param parent Parent QGraphicsItem
|
||||
*/
|
||||
SplittedHelperCell::SplittedHelperCell(QGraphicsItem *parent) :
|
||||
HelperCell(parent),
|
||||
split_background_color(background_color),
|
||||
split_foreground_color(foreground_color),
|
||||
split_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
SplittedHelperCell::~SplittedHelperCell() {
|
||||
}
|
||||
|
||||
/**
|
||||
Handles the splitted helper cell visual rendering
|
||||
@param painter QPainter to be used for the rendering
|
||||
@param option Rendering options
|
||||
@param widget QWidget being painted, if any
|
||||
*/
|
||||
void SplittedHelperCell::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * widget) {
|
||||
if (!split_size) {
|
||||
HelperCell::paint(painter, option, widget);
|
||||
return;
|
||||
}
|
||||
QRectF first_drawing_rectangle(QPointF(0, 0), geometry().adjusted(0, 0, -split_size, 0).size());
|
||||
QRectF second_drawing_rectangle(first_drawing_rectangle.topRight(), QSize(split_size, first_drawing_rectangle.height()));
|
||||
qDebug() << first_drawing_rectangle << second_drawing_rectangle;
|
||||
|
||||
painter -> setPen(Qt::black);
|
||||
painter -> setBrush(background_color);
|
||||
painter -> drawRect(first_drawing_rectangle);
|
||||
painter -> setBrush(split_background_color);
|
||||
painter -> drawRect(second_drawing_rectangle);
|
||||
|
||||
painter -> setPen(foreground_color);
|
||||
painter -> drawText(first_drawing_rectangle, Qt::AlignHCenter | Qt::AlignVCenter, label);
|
||||
painter -> setPen(split_foreground_color);
|
||||
painter -> drawText(second_drawing_rectangle, Qt::AlignHCenter | Qt::AlignVCenter, split_label);
|
||||
}
|
45
sources/titleblock/splittedhelpercell.h
Normal file
45
sources/titleblock/splittedhelpercell.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_SPLITTED_HELPER_CELL_H
|
||||
#define TITLEBLOCK_SLASH_SPLITTED_HELPER_CELL_H
|
||||
#include "helpercell.h"
|
||||
|
||||
/**
|
||||
This class is a variant of HelperCell having the ability to display two
|
||||
labels, with a split line between them.
|
||||
*/
|
||||
class SplittedHelperCell : public HelperCell {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SplittedHelperCell(QGraphicsItem * = 0);
|
||||
virtual ~SplittedHelperCell();
|
||||
private:
|
||||
SplittedHelperCell(const SplittedHelperCell &);
|
||||
|
||||
// methods
|
||||
public:
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
|
||||
// attributes
|
||||
QColor split_background_color; ///< Background color on the split side
|
||||
QColor split_foreground_color; ///< Text color on the split side
|
||||
QString split_label; ///< Text displayed on the split side
|
||||
int split_size; ///< Length of the split side
|
||||
};
|
||||
|
||||
#endif
|
212
sources/titleblock/templatecellsset.cpp
Normal file
212
sources/titleblock/templatecellsset.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "templatecellsset.h"
|
||||
#include "templatevisualcell.h"
|
||||
#include "templateview.h"
|
||||
#include "titleblockcell.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param parent_view View this set of cells are rattached to
|
||||
*/
|
||||
TitleBlockTemplateCellsSet::TitleBlockTemplateCellsSet(const TitleBlockTemplateView *parent_view) :
|
||||
parent_view_(parent_view)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Copy constructor
|
||||
@param copy TitleBlockTemplateCellsSet object to copy
|
||||
*/
|
||||
TitleBlockTemplateCellsSet::TitleBlockTemplateCellsSet(const TitleBlockTemplateCellsSet ©) :
|
||||
QList<TitleBlockTemplateVisualCell *>(copy),
|
||||
parent_view_(copy.parent_view_)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
TitleBlockTemplateCellsSet::~TitleBlockTemplateCellsSet() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return a QPainterPath composed of the rectangles from cells within this set
|
||||
*/
|
||||
QPainterPath TitleBlockTemplateCellsSet::painterPath() const {
|
||||
QPainterPath cells_path;
|
||||
foreach (TitleBlockTemplateVisualCell *cell, *this) {
|
||||
cells_path.addRect(cell -> geometry());
|
||||
}
|
||||
return(cells_path);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if the cells within this set are composing a rectangle shape,
|
||||
false otherwise.
|
||||
*/
|
||||
bool TitleBlockTemplateCellsSet::isRectangle() const {
|
||||
if (!count()) return(false);
|
||||
if (count() == 1) return(true);
|
||||
|
||||
QPolygonF points = painterPath().simplified().toFillPolygon();
|
||||
if (points.isClosed()) points.pop_back();
|
||||
|
||||
return(points.count() == 4 || points.count() == 5);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if all cells within this set are selected
|
||||
*/
|
||||
bool TitleBlockTemplateCellsSet::allCellsAreSelected() const {
|
||||
foreach (TitleBlockTemplateVisualCell *cell, *this) {
|
||||
if (!cell -> isSelected()) {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this set includes at least one cell which is spanned by a
|
||||
cell not present in this set, false otherwise.
|
||||
*/
|
||||
bool TitleBlockTemplateCellsSet::hasExternalSpan() const {
|
||||
// fetches all cells concerned by this set
|
||||
QSet<TitleBlockCell *> all_cells = cells(true);
|
||||
|
||||
// look for cells spanned by cells that do not belong to this set
|
||||
foreach (TitleBlockCell *cell, all_cells) {
|
||||
if (cell -> spanner_cell && !all_cells.contains(cell -> spanner_cell)) {
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the top left cell within this set, or 0 if this set is empty
|
||||
*/
|
||||
TitleBlockTemplateVisualCell *TitleBlockTemplateCellsSet::topLeftCell() const {
|
||||
if (empty()) return(0);
|
||||
if (count() == 1) return(first());
|
||||
|
||||
// look for cells at the top
|
||||
QMultiMap<int, TitleBlockTemplateVisualCell *> top_cells;
|
||||
foreach (TitleBlockTemplateVisualCell *cell_view, *this) {
|
||||
if (TitleBlockCell *cell = cell_view -> cell()) {
|
||||
top_cells.insertMulti(cell -> num_row, cell_view);
|
||||
}
|
||||
}
|
||||
QList<TitleBlockTemplateVisualCell *> candidates = top_cells.values(top_cells.keys().first());
|
||||
if (candidates.count() == 1) return(candidates.first());
|
||||
|
||||
// look for the cell at the left
|
||||
int lowest_num_col = 100000;
|
||||
TitleBlockTemplateVisualCell *candidate = 0;
|
||||
foreach (TitleBlockTemplateVisualCell *cell_view, candidates) {
|
||||
if (TitleBlockCell *cell = cell_view -> cell()) {
|
||||
if (cell -> num_col < lowest_num_col) {
|
||||
lowest_num_col = cell -> num_col;
|
||||
candidate = cell_view;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(candidate);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the bottom right cell within this set, or 0 if this set is empty
|
||||
*/
|
||||
TitleBlockTemplateVisualCell *TitleBlockTemplateCellsSet::bottomRightCell() const {
|
||||
if (empty()) return(0);
|
||||
if (count() == 1) return(first());
|
||||
|
||||
// look for cells at the bottom
|
||||
QMultiMap<qreal, TitleBlockTemplateVisualCell *> bottom_cells;
|
||||
foreach (TitleBlockTemplateVisualCell *cell_view, *this) {
|
||||
bottom_cells.insertMulti(cell_view -> geometry().bottom(), cell_view);
|
||||
}
|
||||
QList<TitleBlockTemplateVisualCell *> candidates = bottom_cells.values(bottom_cells.keys().last());
|
||||
if (candidates.count() == 1) return(candidates.first());
|
||||
|
||||
// look for the cell at the right
|
||||
qreal highest_right = -100000;
|
||||
TitleBlockTemplateVisualCell *candidate = 0;
|
||||
foreach (TitleBlockTemplateVisualCell *cell_view, candidates) {
|
||||
qreal right = cell_view -> geometry().right();
|
||||
if (right > highest_right) {
|
||||
highest_right = right;
|
||||
candidate = cell_view;
|
||||
}
|
||||
}
|
||||
return(candidate);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the merge area, i.e. the rectangle delimited by the top left cell
|
||||
and the bottom right cell within this cells set.
|
||||
*/
|
||||
QRectF TitleBlockTemplateCellsSet::mergeAreaRect() const {
|
||||
QRectF merge_area;
|
||||
if (!parent_view_) return(merge_area);
|
||||
|
||||
TitleBlockTemplateVisualCell *top_left_cell = topLeftCell();
|
||||
if (!top_left_cell) return(merge_area);
|
||||
TitleBlockTemplateVisualCell *bottom_right_cell = bottomRightCell();
|
||||
if (!bottom_right_cell) return(merge_area);
|
||||
|
||||
merge_area.setTopLeft(top_left_cell -> geometry().topLeft());
|
||||
merge_area.setBottomRight(bottom_right_cell -> geometry().bottomRight());
|
||||
return(merge_area);
|
||||
}
|
||||
|
||||
/**
|
||||
@param rect (Optional) The merge area to be considered; if a null QRectF is
|
||||
provided, this method will use mergeAreaRect().
|
||||
@return the cells contained in the merge area of this cells set
|
||||
*/
|
||||
TitleBlockTemplateCellsSet TitleBlockTemplateCellsSet::mergeArea(const QRectF &rect) const {
|
||||
TitleBlockTemplateCellsSet merge_area(parent_view_);
|
||||
if (!parent_view_) return(merge_area);
|
||||
|
||||
QRectF merge_area_rect = rect.isNull() ? mergeAreaRect() : rect;
|
||||
|
||||
merge_area = parent_view_ -> cells(merge_area_rect);
|
||||
return(merge_area);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the list of cells rendered by the current selection
|
||||
@param include_spanned whether to include spanned cells or not
|
||||
*/
|
||||
QSet<TitleBlockCell *> TitleBlockTemplateCellsSet::cells(bool include_spanned) const {
|
||||
QSet<TitleBlockCell *> set;
|
||||
foreach (TitleBlockTemplateVisualCell *cell_view, *this) {
|
||||
if (TitleBlockCell *cell = cell_view -> cell()) {
|
||||
if (include_spanned) {
|
||||
foreach (TitleBlockCell *cell, cell_view -> cells()) {
|
||||
set << cell;
|
||||
}
|
||||
} else {
|
||||
set << cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(set);
|
||||
}
|
51
sources/titleblock/templatecellsset.h
Normal file
51
sources/titleblock/templatecellsset.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_TEMPLATE_CELLS_SET_H
|
||||
#define TITLEBLOCK_SLASH_TEMPLATE_CELLS_SET_H
|
||||
#include <QtGui>
|
||||
class TitleBlockCell;
|
||||
class TitleBlockTemplateVisualCell;
|
||||
class TitleBlockTemplateView;
|
||||
/**
|
||||
This class represents a set of cells (selected or not) when editing a
|
||||
title block template.
|
||||
*/
|
||||
class TitleBlockTemplateCellsSet : public QList<TitleBlockTemplateVisualCell *> {
|
||||
// Constructors, destructor
|
||||
public:
|
||||
TitleBlockTemplateCellsSet(const TitleBlockTemplateView *);
|
||||
TitleBlockTemplateCellsSet(const TitleBlockTemplateCellsSet &);
|
||||
virtual ~TitleBlockTemplateCellsSet();
|
||||
|
||||
// methods
|
||||
public:
|
||||
QPainterPath painterPath() const;
|
||||
bool isRectangle() const;
|
||||
bool allCellsAreSelected() const;
|
||||
bool hasExternalSpan() const;
|
||||
TitleBlockTemplateVisualCell *topLeftCell() const;
|
||||
TitleBlockTemplateVisualCell *bottomRightCell() const;
|
||||
QRectF mergeAreaRect() const;
|
||||
TitleBlockTemplateCellsSet mergeArea(const QRectF & = QRectF()) const;
|
||||
QSet<TitleBlockCell *> cells(bool = true) const;
|
||||
|
||||
// attributes
|
||||
public:
|
||||
const TitleBlockTemplateView *parent_view_; ///< the view displaying the cells
|
||||
};
|
||||
#endif
|
373
sources/titleblock/templatecellwidget.cpp
Normal file
373
sources/titleblock/templatecellwidget.cpp
Normal file
@ -0,0 +1,373 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "templatecellwidget.h"
|
||||
#include "titleblockcell.h"
|
||||
#include "nameslist.h"
|
||||
#include "nameslistwidget.h"
|
||||
#include "titleblocktemplate.h"
|
||||
#include "templatecommands.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param parent 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() {
|
||||
cell_type_label_ = new QLabel(tr("Type de cellule :"));
|
||||
cell_type_input_ = new QComboBox();
|
||||
cell_type_input_ -> addItem(tr("Vide"), TitleBlockCell::EmptyCell);
|
||||
cell_type_input_ -> addItem(tr("Texte"), TitleBlockCell::TextCell);
|
||||
cell_type_input_ -> addItem(tr("Logo"), TitleBlockCell::LogoCell);
|
||||
|
||||
logo_label_ = new QLabel(tr("Logo"));
|
||||
logo_input_ = new QComboBox();
|
||||
logo_input_ -> addItem(tr("Aucun logo"));
|
||||
add_logo_input_ = new QPushButton(tr("G\351rer les logos"));
|
||||
|
||||
name_label_ = new QLabel(tr("Nom :"));
|
||||
name_input_ = new QLineEdit();
|
||||
label_checkbox_ = new QCheckBox(tr("Afficher un label :"));
|
||||
label_input_ = new QLineEdit();
|
||||
label_input_ -> setReadOnly(true);
|
||||
label_edit_ = new QPushButton(tr("Editer"));
|
||||
value_label_ = new QLabel(tr("Texte :"));
|
||||
value_input_ = new QLineEdit();
|
||||
value_input_ -> setReadOnly(true);
|
||||
value_edit_ = new QPushButton(tr("Editer"));
|
||||
align_label_ = new QLabel(tr("Alignement :"));
|
||||
horiz_align_label_ = new QLabel(tr("horizontal :"));
|
||||
horiz_align_input_ = new QComboBox();
|
||||
horiz_align_input_ -> addItem(tr("Gauche"), Qt::AlignLeft);
|
||||
horiz_align_input_ -> addItem(tr("Centr\351"), Qt::AlignHCenter);
|
||||
horiz_align_input_ -> addItem(tr("Droite"), 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("Haut"), Qt::AlignTop);
|
||||
vert_align_input_ -> addItem(tr("Milieu"), Qt::AlignVCenter);
|
||||
vert_align_input_ -> addItem(tr("Bas"), 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("Police :");
|
||||
font_size_input_ = new QSpinBox();
|
||||
font_adjust_input_ = new QCheckBox(tr("Ajuster la taille de police si besoin"));
|
||||
|
||||
// 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_);
|
||||
|
||||
/// TODO fix widget alignment when switching cell type
|
||||
cell_editor_text_layout_ = new QGridLayout();
|
||||
cell_editor_text_layout_ -> addWidget(cell_type_label_, 0, 0);
|
||||
cell_editor_text_layout_ -> addWidget(cell_type_input_, 0, 1);
|
||||
cell_editor_text_layout_ -> addWidget(name_label_, 0, 2);
|
||||
cell_editor_text_layout_ -> addWidget(name_input_, 0, 3);
|
||||
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_ -> setColumnStretch(4, 4000);
|
||||
cell_editor_layout_ = new QVBoxLayout();
|
||||
cell_editor_layout_ -> addLayout(cell_editor_text_layout_);
|
||||
cell_editor_layout_ -> addStretch();
|
||||
setLayout(cell_editor_layout_);
|
||||
|
||||
// trigger the logo manager
|
||||
connect(add_logo_input_, SIGNAL(released()), this, SIGNAL(logoEditionRequested()));
|
||||
|
||||
// handle cell modifications
|
||||
connect(cell_type_input_, SIGNAL(activated(int)), this, SLOT(updateFormType(int)));
|
||||
connect(cell_type_input_, SIGNAL(activated(int)), this, SLOT(editType()));
|
||||
connect(name_input_, SIGNAL(editingFinished()), this, SLOT(editName()));
|
||||
connect(label_checkbox_, SIGNAL(clicked(bool)), this, SLOT(editLabelDisplayed()));
|
||||
connect(label_edit_, SIGNAL(released()), this, SLOT(editLabel()));
|
||||
connect(value_edit_, SIGNAL(released()), this, SLOT(editValue()));
|
||||
connect(horiz_align_input_, SIGNAL(activated(int)), this, SLOT(editAlignment()));
|
||||
connect(vert_align_input_, SIGNAL(activated(int)), this, SLOT(editAlignment()));
|
||||
connect(font_size_input_, SIGNAL(valueChanged(int)), this, SLOT(editFontSize()));
|
||||
connect(font_adjust_input_, SIGNAL(clicked(bool)), this, SLOT(editAdjust()));
|
||||
connect(logo_input_, SIGNAL(activated(int)), this, SLOT(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);
|
||||
|
||||
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 de cette cellule :"));
|
||||
}
|
||||
|
||||
/**
|
||||
Emit a value modification command.
|
||||
@see ModifyTitleBlockCellCommand
|
||||
*/
|
||||
void TitleBlockTemplateCellWidget::editValue() {
|
||||
if (!edited_cell_) return;
|
||||
editTranslatableValue(edited_cell_ -> value, "value", tr("Valeur de cette cellule :"));
|
||||
}
|
||||
|
||||
/**
|
||||
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("Aucun 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
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 label Label to be displayed when editing the string
|
||||
*/
|
||||
void TitleBlockTemplateCellWidget::editTranslatableValue(NamesList &names, const QString &attribute, const QString &label) const {
|
||||
NamesListWidget *names_widget = new NamesListWidget();
|
||||
names_widget -> setNames(names);
|
||||
QDialogButtonBox * buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
QVBoxLayout *editor_layout = new QVBoxLayout();
|
||||
editor_layout -> addWidget(new QLabel(label));
|
||||
editor_layout -> addWidget(names_widget);
|
||||
editor_layout -> addWidget(buttons);
|
||||
|
||||
QDialog edit_dialog;
|
||||
connect(buttons, SIGNAL(rejected()), &edit_dialog, SLOT(reject()));
|
||||
connect(buttons, SIGNAL(accepted()), &edit_dialog, SLOT(accept()));
|
||||
edit_dialog.setLayout(editor_layout);
|
||||
if (edit_dialog.exec() == QDialog::Accepted) {
|
||||
emitModification(attribute, qVariantFromValue(names_widget -> 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("Édition d'une cellule : %1", "label of and undo command when editing a cell")
|
||||
.arg(TitleBlockCell::attributeName(attribute))
|
||||
);
|
||||
emit(cellModified(command));
|
||||
}
|
111
sources/titleblock/templatecellwidget.h
Normal file
111
sources/titleblock/templatecellwidget.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_TEMPLATE_CELL_WIDGET_H
|
||||
#define TITLEBLOCK_SLASH_TEMPLATE_CELL_WIDGET_H
|
||||
#include <QtGui>
|
||||
#include "qet.h"
|
||||
class ModifyTitleBlockCellCommand;
|
||||
class TitleBlockTemplate;
|
||||
class TitleBlockCell;
|
||||
class NamesList;
|
||||
|
||||
/**
|
||||
This class implements an edition widget for cells that compose a title
|
||||
block template.
|
||||
*/
|
||||
class TitleBlockTemplateCellWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
// constructor, destructor
|
||||
public:
|
||||
TitleBlockTemplateCellWidget(TitleBlockTemplate * = 0, QWidget * = 0);
|
||||
virtual ~TitleBlockTemplateCellWidget();
|
||||
private:
|
||||
TitleBlockTemplateCellWidget(const TitleBlockTemplateCellWidget &);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
/// is the template read-only?
|
||||
bool read_only;
|
||||
QLabel *cell_type_label_;
|
||||
QComboBox *cell_type_input_;
|
||||
|
||||
QLabel *logo_label_;
|
||||
QComboBox *logo_input_;
|
||||
QPushButton *add_logo_input_;
|
||||
|
||||
QLabel *name_label_;
|
||||
QLineEdit *name_input_;
|
||||
QCheckBox *label_checkbox_;
|
||||
QLineEdit *label_input_;
|
||||
QPushButton *label_edit_;
|
||||
QLabel *value_label_;
|
||||
QLineEdit *value_input_;
|
||||
QPushButton *value_edit_;
|
||||
QLabel *align_label_;
|
||||
QLabel *horiz_align_label_;
|
||||
QComboBox *horiz_align_input_;
|
||||
QHash<int, int> horiz_align_indexes_;
|
||||
QLabel *vert_align_label_;
|
||||
QComboBox *vert_align_input_;
|
||||
QHash<int, int> vert_align_indexes_;
|
||||
QLabel *font_size_label_;
|
||||
QSpinBox *font_size_input_;
|
||||
QCheckBox *font_adjust_input_;
|
||||
QVBoxLayout *cell_editor_layout_;
|
||||
QGridLayout *cell_editor_text_layout_;
|
||||
QHBoxLayout *cell_editor_image_layout_;
|
||||
|
||||
TitleBlockCell *edited_cell_;
|
||||
|
||||
// methods
|
||||
public:
|
||||
int horizontalAlignment() const;
|
||||
int verticalAlignment() const;
|
||||
int alignment() const;
|
||||
|
||||
protected:
|
||||
void editTranslatableValue(NamesList &, const QString &, const QString &) const;
|
||||
void emitModification(const QString &, const QVariant &) const;
|
||||
|
||||
private:
|
||||
void initWidgets();
|
||||
|
||||
public slots:
|
||||
void updateFormType(int);
|
||||
void edit(TitleBlockCell *);
|
||||
void editType();
|
||||
void editName();
|
||||
void editLabelDisplayed();
|
||||
void editLabel();
|
||||
void editValue();
|
||||
void editAlignment();
|
||||
void editFontSize();
|
||||
void editAdjust();
|
||||
void editLogo();
|
||||
void updateLogosComboBox(const TitleBlockTemplate *);
|
||||
|
||||
private slots:
|
||||
|
||||
|
||||
signals:
|
||||
void logoEditionRequested();
|
||||
void cellModified(ModifyTitleBlockCellCommand *) const;
|
||||
};
|
||||
|
||||
#endif
|
779
sources/titleblock/templatecommands.cpp
Normal file
779
sources/titleblock/templatecommands.cpp
Normal file
@ -0,0 +1,779 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "templatecommands.h"
|
||||
#include "templatevisualcell.h"
|
||||
#include "templateview.h"
|
||||
#include "titleblockcell.h"
|
||||
#include "dimension.h"
|
||||
#define TITLEBLOCK_DEFAULT_ROW_HEIGHT TitleBlockDimension(25)
|
||||
#define TITLEBLOCK_DEFAULT_COL_WIDTH TitleBlockDimension(50)
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param cell Modified cell
|
||||
@param parent Parent QUndoCommand
|
||||
*/
|
||||
ModifyTitleBlockCellCommand::ModifyTitleBlockCellCommand(TitleBlockCell *cell, QUndoCommand *parent) :
|
||||
QUndoCommand(parent),
|
||||
view_(0),
|
||||
modified_cell_(cell)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
ModifyTitleBlockCellCommand::~ModifyTitleBlockCellCommand() {
|
||||
}
|
||||
|
||||
/**
|
||||
@see QUndoCommand::id()
|
||||
@return the ID of this command.
|
||||
*/
|
||||
int ModifyTitleBlockCellCommand::id() const {
|
||||
return(MODIFY_TITLE_BLOCK_CELL_COMMAND_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
@see QUndoCommand::mergeWith()
|
||||
@param command Command to merge with.
|
||||
@return true on success, false otherwise
|
||||
*/
|
||||
bool ModifyTitleBlockCellCommand::mergeWith(const QUndoCommand *command) {
|
||||
const ModifyTitleBlockCellCommand *other = static_cast<const ModifyTitleBlockCellCommand *>(command);
|
||||
if (other) {
|
||||
if (other -> modified_cell_ == modified_cell_) {
|
||||
if (other -> new_values_.keys() == new_values_.keys()) {
|
||||
qDebug() << Q_FUNC_INFO << "merging";
|
||||
new_values_ = other -> new_values_;
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Undo the change.
|
||||
*/
|
||||
void ModifyTitleBlockCellCommand::undo() {
|
||||
if (!modified_cell_) return;
|
||||
foreach (QString attribute, old_values_.keys()) {
|
||||
modified_cell_ -> setAttribute(attribute, old_values_[attribute]);
|
||||
}
|
||||
if (view_) view_ -> refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
Redo the change.
|
||||
*/
|
||||
void ModifyTitleBlockCellCommand::redo() {
|
||||
if (!modified_cell_) return;
|
||||
foreach (QString attribute, new_values_.keys()) {
|
||||
modified_cell_ -> setAttribute(attribute, new_values_[attribute]);
|
||||
}
|
||||
if (view_) view_ -> refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
@return the cell modified by this command
|
||||
*/
|
||||
TitleBlockCell *ModifyTitleBlockCellCommand::cell() const {
|
||||
return(modified_cell_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the cell modified by this command object
|
||||
@param modified_cell the cell modified by this command
|
||||
*/
|
||||
void ModifyTitleBlockCellCommand::setCell(TitleBlockCell *modified_cell) {
|
||||
modified_cell_ = modified_cell;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the view to be updated after the cell modification
|
||||
*/
|
||||
TitleBlockTemplateView *ModifyTitleBlockCellCommand::view() const {
|
||||
return(view_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the view to be updated after the cell modification
|
||||
@param view the view to be updated after the cell modification
|
||||
*/
|
||||
void ModifyTitleBlockCellCommand::setView(TitleBlockTemplateView *view) {
|
||||
view_ = view;
|
||||
}
|
||||
|
||||
/**
|
||||
Erase the known old/new values.
|
||||
*/
|
||||
void ModifyTitleBlockCellCommand::clear() {
|
||||
old_values_.clear();
|
||||
new_values_.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
Register a new modification on a title block template cell; you may
|
||||
indicate either the new value or the old one: this method will
|
||||
systematically fetch the other one.
|
||||
@param attribute Name of the modified attribute
|
||||
@param value Old or new value of the modified attribute, depending on is_old_value
|
||||
@param is_old_value (optional, defaults to false) Indicates whether the provided value is the old or the new one.
|
||||
*/
|
||||
void ModifyTitleBlockCellCommand::addModification(const QString &attribute, const QVariant &value, bool is_old_value) {
|
||||
if (is_old_value) {
|
||||
// the provided value is the old one; therefore, the one we fetch is the new one
|
||||
old_values_[attribute] = value;
|
||||
if (modified_cell_) {
|
||||
new_values_[attribute] = modified_cell_ -> attribute(attribute);
|
||||
}
|
||||
} else {
|
||||
// the provided value is the new one; therefore, we fetch the old one
|
||||
if (modified_cell_) {
|
||||
old_values_[attribute] = modified_cell_ -> attribute(attribute);
|
||||
}
|
||||
new_values_[attribute] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param tbtemplate Modified title block template
|
||||
@param parent Parent QUndoCommand
|
||||
*/
|
||||
TitleBlockTemplateCommand::TitleBlockTemplateCommand(TitleBlockTemplate *tbtemplate, QUndoCommand *parent) :
|
||||
QUndoCommand(parent),
|
||||
tbtemplate_(tbtemplate),
|
||||
view_(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
TitleBlockTemplateCommand::~TitleBlockTemplateCommand() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return the modified title block template.
|
||||
*/
|
||||
TitleBlockTemplate *TitleBlockTemplateCommand::titleBlockTemplate() const {
|
||||
return(tbtemplate_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the modified title block template.
|
||||
@param tbtemplate New modified title block template.
|
||||
*/
|
||||
void TitleBlockTemplateCommand::setTitleBlockTemplate(TitleBlockTemplate *tbtemplate) {
|
||||
tbtemplate_ = tbtemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the view to be updated after the template modification
|
||||
*/
|
||||
TitleBlockTemplateView *TitleBlockTemplateCommand::view() const {
|
||||
return(view_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the view to be updated after the template modification
|
||||
@param view the view to be updated after the template modification
|
||||
*/
|
||||
void TitleBlockTemplateCommand::setView(TitleBlockTemplateView *view) {
|
||||
view_ = view;
|
||||
}
|
||||
|
||||
/**
|
||||
This static method is a convenience to create a ModifyTemplateGridCommand
|
||||
that adds a row to \a tbtemplate at \a index.
|
||||
@param tbtemplate Modified title block template
|
||||
@param index Index where the row should be inserted.
|
||||
@return a ModifyTemplateGridCommand object, or 0 if something went wrong.
|
||||
*/
|
||||
ModifyTemplateGridCommand *ModifyTemplateGridCommand::addRow(TitleBlockTemplate *tbtemplate, int index) {
|
||||
if (!tbtemplate) return(0);
|
||||
|
||||
// create the command itself
|
||||
ModifyTemplateGridCommand *add_row_command = new ModifyTemplateGridCommand(tbtemplate);
|
||||
add_row_command -> setInsertion(true);
|
||||
add_row_command -> setType(true);
|
||||
add_row_command -> setCells(tbtemplate -> createRow());
|
||||
add_row_command -> setDimension(TITLEBLOCK_DEFAULT_ROW_HEIGHT);
|
||||
add_row_command -> setIndex(index);
|
||||
|
||||
return(add_row_command);
|
||||
}
|
||||
|
||||
/**
|
||||
This static method is a convenience to create a ModifyTemplateGridCommand
|
||||
that adds a column to \a tbtemplate at \a index.
|
||||
@param tbtemplate Modified title block template.
|
||||
@param index Index where the column should be inserted.
|
||||
@return a ModifyTemplateGridCommand object, or 0 if something went wrong.
|
||||
*/
|
||||
ModifyTemplateGridCommand *ModifyTemplateGridCommand::addColumn(TitleBlockTemplate *tbtemplate, int index) {
|
||||
if (!tbtemplate) return(0);
|
||||
|
||||
// create the command itself
|
||||
ModifyTemplateGridCommand *add_column_command = new ModifyTemplateGridCommand(tbtemplate);
|
||||
add_column_command -> setInsertion(true);
|
||||
add_column_command -> setType(false);
|
||||
add_column_command -> setCells(tbtemplate -> createColumn());
|
||||
add_column_command -> setDimension(TITLEBLOCK_DEFAULT_COL_WIDTH);
|
||||
add_column_command -> setIndex(index);
|
||||
|
||||
return(add_column_command);
|
||||
}
|
||||
|
||||
/**
|
||||
This static method is a convenience to create a ModifyTemplateGridCommand
|
||||
that removes the row at \a index from \a tbtemplate.
|
||||
@param tbtemplate Modified title block template.
|
||||
@param index Index of the removed row.
|
||||
@return a ModifyTemplateGridCommand object, or 0 if something went wrong.
|
||||
*/
|
||||
ModifyTemplateGridCommand *ModifyTemplateGridCommand::deleteRow(TitleBlockTemplate *tbtemplate, int index) {
|
||||
if (!tbtemplate) return(0);
|
||||
|
||||
// create the command itself
|
||||
ModifyTemplateGridCommand *del_row_command = new ModifyTemplateGridCommand(tbtemplate);
|
||||
del_row_command -> setInsertion(false);
|
||||
del_row_command -> setType(true);
|
||||
del_row_command -> setIndex(index);
|
||||
|
||||
return(del_row_command);
|
||||
}
|
||||
|
||||
/**
|
||||
This static method is a convenience to create a ModifyTemplateGridCommand
|
||||
that removes the column at \a index from \a tbtemplate.
|
||||
@param tbtemplate Modified title block template.
|
||||
@param index Index of the removed column.
|
||||
@return a ModifyTemplateGridCommand object, or 0 if something went wrong.
|
||||
*/
|
||||
ModifyTemplateGridCommand *ModifyTemplateGridCommand::deleteColumn(TitleBlockTemplate *tbtemplate, int index) {
|
||||
if (!tbtemplate) return(0);
|
||||
|
||||
// create the command itself
|
||||
ModifyTemplateGridCommand *del_column_command = new ModifyTemplateGridCommand(tbtemplate);
|
||||
del_column_command -> setInsertion(false);
|
||||
del_column_command -> setType(false);
|
||||
del_column_command -> setIndex(index);
|
||||
|
||||
return(del_column_command);
|
||||
}
|
||||
|
||||
/**
|
||||
Construct a default ModifyTemplateGridCommand, i.e. a command adding a 25px row at the bottom of the template.
|
||||
@param tbtemplate Modified title block template
|
||||
@param parent Parent QUndoCommand
|
||||
*/
|
||||
ModifyTemplateGridCommand::ModifyTemplateGridCommand(TitleBlockTemplate *tbtemplate, QUndoCommand *parent) :
|
||||
TitleBlockTemplateCommand(tbtemplate, parent),
|
||||
index_(-1),
|
||||
type_(true),
|
||||
dimension_(TITLEBLOCK_DEFAULT_ROW_HEIGHT),
|
||||
insertion_(true)
|
||||
{
|
||||
updateText();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
ModifyTemplateGridCommand::~ModifyTemplateGridCommand() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return the index of the inserted/deleted row/column
|
||||
*/
|
||||
int ModifyTemplateGridCommand::index() const {
|
||||
return(index_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the index of the inserted/deleted row/column.
|
||||
@param index Index of the inserted/deleted row/column.
|
||||
*/
|
||||
void ModifyTemplateGridCommand::setIndex(int index) {
|
||||
index_ = index;
|
||||
}
|
||||
|
||||
/**
|
||||
@return a list of pointers to cells composing the inserted/deleted row/column.
|
||||
*/
|
||||
QList<TitleBlockCell *> ModifyTemplateGridCommand::cells() const {
|
||||
return(cells_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the cells composing the inserted/deleted row/column.
|
||||
@param cells List of pointers to cells composing the inserted/deleted row/column.
|
||||
*/
|
||||
void ModifyTemplateGridCommand::setCells(const QList<TitleBlockCell *> &cells) {
|
||||
cells_ = cells;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the dimension of the inserted/deleted row/column.
|
||||
*/
|
||||
TitleBlockDimension ModifyTemplateGridCommand::dimension() const {
|
||||
return dimension_;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the dimension of the inserted/deleted row/column
|
||||
@param dimension Dimension of the inserted/deleted row/column
|
||||
*/
|
||||
void ModifyTemplateGridCommand::setDimension(const TitleBlockDimension &dimension) {
|
||||
dimension_ = dimension;
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this object is about inserting/deleting a row, false for a column.
|
||||
*/
|
||||
int ModifyTemplateGridCommand::type() const {
|
||||
return(type_);
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates whether this object inserts/deletes a row or a column.
|
||||
@param type true if this object is about inserting/deleting a row, false for a column.
|
||||
*/
|
||||
void ModifyTemplateGridCommand::setType(bool type) {
|
||||
type_ = type;
|
||||
updateText();
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if the row/column is inserted, false if it is deleted
|
||||
*/
|
||||
bool ModifyTemplateGridCommand::isInsertion() const {
|
||||
return(insertion_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param insertion true if the row/column is inserted, false if it is deleted
|
||||
*/
|
||||
void ModifyTemplateGridCommand::setInsertion(bool insertion) {
|
||||
insertion_ = insertion;
|
||||
updateText();
|
||||
}
|
||||
|
||||
/**
|
||||
Undo the change.
|
||||
*/
|
||||
void ModifyTemplateGridCommand::undo() {
|
||||
apply(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Redo the change.
|
||||
*/
|
||||
void ModifyTemplateGridCommand::redo() {
|
||||
apply(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Update the text describing what the command does.
|
||||
*/
|
||||
void ModifyTemplateGridCommand::updateText() {
|
||||
if (type_) {
|
||||
if (insertion_) {
|
||||
setText(QObject::tr("Insertion d'une ligne", "label used in the title block template editor undo list"));
|
||||
} else {
|
||||
setText(QObject::tr("Suppression d'une ligne", "label used in the title block template editor undo list"));
|
||||
}
|
||||
} else {
|
||||
if (insertion_) {
|
||||
setText(QObject::tr("Insertion d'une colonne", "label used in the title block template editor undo list"));
|
||||
} else {
|
||||
setText(QObject::tr("Suppression d'une colonne", "label used in the title block template editor undo list"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This method takes care of the actual job when undoing / redoing a
|
||||
row/column insertion/removal.
|
||||
@param true to undo the change, false to apply it.
|
||||
*/
|
||||
void ModifyTemplateGridCommand::apply(bool undo) {
|
||||
if (!tbtemplate_ || index_ == -1) return;
|
||||
|
||||
if (insertion_ ^ undo) {
|
||||
if (type_) {
|
||||
tbtemplate_ -> insertRow(dimension_.value, cells_, index_);
|
||||
} else {
|
||||
tbtemplate_ -> insertColumn(dimension_, cells_, index_);
|
||||
}
|
||||
} else {
|
||||
if (type_) {
|
||||
dimension_.value = tbtemplate_ -> rowDimension(index_);
|
||||
cells_ = tbtemplate_ -> takeRow(index_);
|
||||
} else {
|
||||
dimension_ = tbtemplate_ -> columnDimension(index_);
|
||||
cells_ = tbtemplate_ -> takeColumn(index_);
|
||||
}
|
||||
}
|
||||
|
||||
// update the view, if any
|
||||
if (view_) {
|
||||
view_ -> updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Construct a default ModifyTemplateDimension.
|
||||
@param tbtemplate Modified title block template
|
||||
@param parent Parent QUndoCommand
|
||||
*/
|
||||
ModifyTemplateDimension::ModifyTemplateDimension(TitleBlockTemplate *tbtemplate, QUndoCommand *parent) :
|
||||
TitleBlockTemplateCommand(tbtemplate, parent),
|
||||
index_(-1),
|
||||
type_(true),
|
||||
before_(TitleBlockDimension(-1)),
|
||||
after_(TitleBlockDimension(-1))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
ModifyTemplateDimension::~ModifyTemplateDimension() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return the index of the resized row/column
|
||||
*/
|
||||
int ModifyTemplateDimension::index() const {
|
||||
return(index_);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the index of the resized row/column.
|
||||
@param index Index of the resized row/column.
|
||||
*/
|
||||
void ModifyTemplateDimension::setIndex(int index) {
|
||||
index_ = index;
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this object is about resizing a row, false for a column.
|
||||
*/
|
||||
int ModifyTemplateDimension::type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates whether this object resizes a row or a column.
|
||||
@param type true if this object is about resizing a row, false for a column.
|
||||
*/
|
||||
void ModifyTemplateDimension::setType(bool type) {
|
||||
type_ = type;
|
||||
updateText();
|
||||
}
|
||||
|
||||
/**
|
||||
@return the dimension of the row/column before it is resized
|
||||
*/
|
||||
TitleBlockDimension ModifyTemplateDimension::dimensionBefore() const {
|
||||
return(before_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param dimension the dimension of the row/column before it is resized
|
||||
*/
|
||||
void ModifyTemplateDimension::setDimensionBefore(const TitleBlockDimension &dimension) {
|
||||
before_ = dimension;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the dimension of the row/column after it is resized
|
||||
*/
|
||||
TitleBlockDimension ModifyTemplateDimension::dimensionAfter() const {
|
||||
return(after_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param dimension the dimension of the row/column after it is resized
|
||||
*/
|
||||
void ModifyTemplateDimension::setDimensionAfter(const TitleBlockDimension &dimension) {
|
||||
after_ = dimension;
|
||||
}
|
||||
|
||||
/**
|
||||
Restore the previous size of the row/column.
|
||||
*/
|
||||
void ModifyTemplateDimension::undo() {
|
||||
apply(before_);
|
||||
}
|
||||
|
||||
/**
|
||||
Resize the row/column.
|
||||
*/
|
||||
void ModifyTemplateDimension::redo() {
|
||||
apply(after_);
|
||||
}
|
||||
|
||||
/**
|
||||
Update the text describing what the command does.
|
||||
*/
|
||||
void ModifyTemplateDimension::updateText() {
|
||||
if (type_) {
|
||||
setText(QObject::tr("Modification d'une ligne", "label used in the title block template editor undo list"));
|
||||
} else {
|
||||
setText(QObject::tr("Modification d'une colonne", "label used in the title block template editor undo list"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Applies a given size to the row/column
|
||||
@param dimension Size to apply
|
||||
*/
|
||||
void ModifyTemplateDimension::apply(const TitleBlockDimension &dimension) {
|
||||
if (!tbtemplate_) return;
|
||||
if (type_) {
|
||||
tbtemplate_ -> setRowDimension(index_, dimension);
|
||||
} else {
|
||||
tbtemplate_ -> setColumnDimension(index_, dimension);
|
||||
}
|
||||
if (view_) {
|
||||
if (type_) {
|
||||
view_ -> rowsDimensionsChanged();
|
||||
} else {
|
||||
view_ -> columnsDimensionsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Construct a command object that acts on \a tbtemplate in order to merge \a merged_cells.
|
||||
Note: you should check the resulting object is valid using isValid().
|
||||
@param merged_cells Cells to be merged together into a single one.
|
||||
@param tbtemplate Modified title block template.
|
||||
@param parent Parent QUndoCommand.
|
||||
*/
|
||||
MergeCellsCommand::MergeCellsCommand(const TitleBlockTemplateCellsSet &merged_cells, TitleBlockTemplate *tbtemplate, QUndoCommand *parent) :
|
||||
TitleBlockTemplateCommand(tbtemplate, parent),
|
||||
spanning_cell_(0),
|
||||
row_span_after_(-1),
|
||||
col_span_after_(-1)
|
||||
{
|
||||
// basic check
|
||||
if (merged_cells.count() < 2) return;
|
||||
|
||||
// the spanning cell is the top left cell
|
||||
TitleBlockTemplateVisualCell *top_left_cell = merged_cells.topLeftCell();
|
||||
if (!top_left_cell) return;
|
||||
spanning_cell_ = top_left_cell -> cell();
|
||||
if (!spanning_cell_) return;
|
||||
|
||||
// store the spanner_cell attribute of each cell implied in the merge
|
||||
foreach(TitleBlockCell *cell, merged_cells.cells()) {
|
||||
spanner_cells_before_merge_.insert(cell, cell -> spanner_cell);
|
||||
}
|
||||
|
||||
// store the former values of the row_span and col_span attributes of the spanning cell
|
||||
row_span_before_ = spanning_cell_ -> row_span;
|
||||
col_span_before_ = spanning_cell_ -> col_span;
|
||||
|
||||
// calculate their new values after the merge operation
|
||||
TitleBlockCell *bottom_right_cell = getBottomRightCell(merged_cells);
|
||||
if (!bottom_right_cell) return;
|
||||
row_span_after_ = bottom_right_cell -> num_row - spanning_cell_ -> num_row;
|
||||
col_span_after_ = bottom_right_cell -> num_col - spanning_cell_ -> num_col;
|
||||
|
||||
setText(
|
||||
QString(
|
||||
QObject::tr(
|
||||
"Fusion de %1 cellules",
|
||||
"label used in the title block template editor undo list; %1 is the number of merged cells"
|
||||
)
|
||||
).arg(merged_cells.count())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
MergeCellsCommand::~MergeCellsCommand() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this command object is valid and usable, false otherwise.
|
||||
*/
|
||||
bool MergeCellsCommand::isValid() const {
|
||||
// we consider having a non-zero spanning cell and positive spans makes a MergeCellsCommand valid
|
||||
return(spanning_cell_ && row_span_after_ != -1 && col_span_after_ != -1);
|
||||
}
|
||||
|
||||
/**
|
||||
Undo the merge operation.
|
||||
*/
|
||||
void MergeCellsCommand::undo() {
|
||||
if (!isValid()) return;
|
||||
|
||||
// restore the original spanning_cell attribute of all impacted cells
|
||||
foreach (TitleBlockCell *cell, spanner_cells_before_merge_.keys()) {
|
||||
cell -> spanner_cell = spanner_cells_before_merge_[cell];
|
||||
}
|
||||
|
||||
// restore the row_span and col_span attributes of the spanning cell
|
||||
spanning_cell_ -> row_span = row_span_before_;
|
||||
spanning_cell_ -> col_span = col_span_before_;
|
||||
|
||||
if (view_) view_ -> updateLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
Apply the merge operation
|
||||
*/
|
||||
void MergeCellsCommand::redo() {
|
||||
if (!isValid()) return;
|
||||
|
||||
// set the spanning_cell attributes of spanned cells to the spanning cell
|
||||
foreach (TitleBlockCell *cell, spanner_cells_before_merge_.keys()) {
|
||||
if (cell == spanning_cell_) continue;
|
||||
cell -> spanner_cell = spanning_cell_;
|
||||
}
|
||||
|
||||
// set the new values of the row_span and col_span attributes
|
||||
spanning_cell_ -> row_span = row_span_after_;
|
||||
spanning_cell_ -> col_span = col_span_after_;
|
||||
|
||||
if (view_) view_ -> updateLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
@param cells_set Set of title block template visual cells.
|
||||
@return the bottom right logical cell within a set of visual cells.
|
||||
*/
|
||||
TitleBlockCell *MergeCellsCommand::getBottomRightCell(const TitleBlockTemplateCellsSet &cells_set) {
|
||||
// first, we get the visual cell at the bottom right
|
||||
TitleBlockTemplateVisualCell *bottom_right_cell = cells_set.bottomRightCell();
|
||||
if (!bottom_right_cell) return(0);
|
||||
|
||||
// next, we get its logical cells: the painted one and the spanned ones (if any)
|
||||
QSet<TitleBlockCell *> logical_cells = bottom_right_cell -> cells();
|
||||
if (logical_cells.isEmpty()) return(0);
|
||||
if (logical_cells.count() == 1) return(logical_cells.toList().first());
|
||||
|
||||
// we then look for the bottom right logical cell
|
||||
int max_num_row = -1, max_num_col = -1;
|
||||
TitleBlockCell *candidate = 0;
|
||||
foreach(TitleBlockCell *cell, logical_cells) {
|
||||
if (cell -> num_row > max_num_row) max_num_row = cell -> num_row;
|
||||
if (cell -> num_col > max_num_col) max_num_col = cell -> num_col;
|
||||
if (cell -> num_row == max_num_row && cell -> num_col == max_num_col) {
|
||||
candidate = cell;
|
||||
}
|
||||
}
|
||||
return(candidate);
|
||||
}
|
||||
|
||||
/**
|
||||
Construct a command object that acts on \a tbtemplate in order to split
|
||||
\a splitted_cells.
|
||||
Note: you should check the resulting object is valid using isValid().
|
||||
@param splitted_cells Cell to be splitted.
|
||||
@param tbtemplate Modified title block template.
|
||||
@param parent Parent QUndoCommand.
|
||||
*/
|
||||
SplitCellsCommand::SplitCellsCommand(const TitleBlockTemplateCellsSet &splitted_cells, TitleBlockTemplate *tbtemplate, QUndoCommand *parent) :
|
||||
TitleBlockTemplateCommand(tbtemplate, parent),
|
||||
spanning_cell_(0),
|
||||
row_span_before_(-1),
|
||||
col_span_before_(-1)
|
||||
{
|
||||
// basic check: the command applies to a single visual cell only
|
||||
if (splitted_cells.count() != 1) return;
|
||||
|
||||
// fetch the spanning cell
|
||||
spanning_cell_ = splitted_cells.first() -> cell();
|
||||
if (!spanning_cell_) return;
|
||||
|
||||
// ensure the cell spans over other cells and therefore can be splitted
|
||||
if (!spanning_cell_ -> spans()) return;
|
||||
|
||||
// retrieve values necessary for the undo operation
|
||||
spanned_cells_ = tbtemplate_ -> spannedCells(spanning_cell_);
|
||||
row_span_before_ = spanning_cell_ -> row_span;
|
||||
col_span_before_ = spanning_cell_ -> col_span;
|
||||
|
||||
setText(
|
||||
QString(
|
||||
QObject::tr(
|
||||
"Séparation d'une cellule en %1",
|
||||
"label used in the title block template editor undo list; %1 is the number of cells after the split"
|
||||
)
|
||||
).arg(spanned_cells_.count() + 1)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
SplitCellsCommand::~SplitCellsCommand() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this command object is valid and usable, false otherwise.
|
||||
*/
|
||||
bool SplitCellsCommand::isValid() const {
|
||||
// we consider having a non-zero spanning cell and at least one spanned cell makes a SplitCellsCommand valid
|
||||
return(spanning_cell_ && spanned_cells_.count());
|
||||
}
|
||||
|
||||
/**
|
||||
Undo the split operation
|
||||
*/
|
||||
void SplitCellsCommand::undo() {
|
||||
if (!isValid()) return;
|
||||
|
||||
// the spanned cells are spanned again
|
||||
foreach(TitleBlockCell *cell, spanned_cells_) {
|
||||
cell -> spanner_cell = spanning_cell_;
|
||||
}
|
||||
|
||||
// the spanning cell span again
|
||||
spanning_cell_ -> row_span = row_span_before_;
|
||||
spanning_cell_ -> col_span = col_span_before_;
|
||||
|
||||
if (view_) view_ -> updateLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
Apply the split operation
|
||||
*/
|
||||
void SplitCellsCommand::redo() {
|
||||
if (!isValid()) return;
|
||||
|
||||
// the spanned cells are not spanned anymore
|
||||
foreach(TitleBlockCell *cell, spanned_cells_) {
|
||||
cell -> spanner_cell = 0;
|
||||
}
|
||||
|
||||
// the spanning cell does not span anymore
|
||||
spanning_cell_ -> row_span = 0;
|
||||
spanning_cell_ -> col_span = 0;
|
||||
|
||||
if (view_) view_ -> updateLayout();
|
||||
}
|
225
sources/titleblock/templatecommands.h
Normal file
225
sources/titleblock/templatecommands.h
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_TEMPLATE_COMMANDS_H
|
||||
#define TITLEBLOCK_SLASH_TEMPLATE_COMMANDS_H
|
||||
#define MODIFY_TITLE_BLOCK_CELL_COMMAND_ID 6378
|
||||
#include <QtCore>
|
||||
#include <QUndoCommand>
|
||||
#include "dimension.h"
|
||||
#include "templatecellsset.h"
|
||||
class TitleBlockTemplateView;
|
||||
class TitleBlockCell;
|
||||
class TitleBlockTemplate;
|
||||
|
||||
/**
|
||||
This class represents a set of modification applied to a title block
|
||||
template cell.
|
||||
*/
|
||||
class ModifyTitleBlockCellCommand : public QUndoCommand {
|
||||
// constructor, destructor
|
||||
public:
|
||||
ModifyTitleBlockCellCommand(TitleBlockCell *, QUndoCommand * = 0);
|
||||
virtual ~ModifyTitleBlockCellCommand();
|
||||
private:
|
||||
ModifyTitleBlockCellCommand(const ModifyTitleBlockCellCommand &);
|
||||
|
||||
// methods
|
||||
public:
|
||||
virtual int id() const;
|
||||
virtual bool mergeWith(const QUndoCommand *);
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
TitleBlockCell *cell() const;
|
||||
void setCell(TitleBlockCell *);
|
||||
TitleBlockTemplateView *view() const;
|
||||
void setView(TitleBlockTemplateView *);
|
||||
void clear();
|
||||
void addModification(const QString &, const QVariant &, bool = false);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
TitleBlockTemplateView *view_; ///< This class may trigger a view update
|
||||
TitleBlockCell *modified_cell_; ///< modified cell
|
||||
QHash<QString, QVariant> old_values_; ///< values before the cell is modified
|
||||
QHash<QString, QVariant> new_values_; ///< values after the cell has been modified
|
||||
};
|
||||
|
||||
/**
|
||||
This class is a base class for any UndoCommand that needs to work with a
|
||||
title block template.
|
||||
*/
|
||||
class TitleBlockTemplateCommand : public QUndoCommand {
|
||||
// Constructors, destructor
|
||||
public:
|
||||
TitleBlockTemplateCommand(TitleBlockTemplate * = 0, QUndoCommand * = 0);
|
||||
virtual ~TitleBlockTemplateCommand();
|
||||
private:
|
||||
TitleBlockTemplateCommand(const TitleBlockTemplateCommand &);
|
||||
|
||||
// methods
|
||||
public:
|
||||
TitleBlockTemplate *titleBlockTemplate() const;
|
||||
void setTitleBlockTemplate(TitleBlockTemplate *);
|
||||
TitleBlockTemplateView *view() const;
|
||||
void setView(TitleBlockTemplateView *);
|
||||
|
||||
// attributes
|
||||
protected:
|
||||
TitleBlockTemplate *tbtemplate_; ///< Modified TitleBlock Template
|
||||
TitleBlockTemplateView *view_; ///< This class may trigger a view update
|
||||
};
|
||||
|
||||
/**
|
||||
This class represents the action of adding or deleting a row or column
|
||||
within a title block template.
|
||||
*/
|
||||
class ModifyTemplateGridCommand : public TitleBlockTemplateCommand {
|
||||
// static factory methods
|
||||
public:
|
||||
static ModifyTemplateGridCommand *addRow(TitleBlockTemplate *, int = -1);
|
||||
static ModifyTemplateGridCommand *addColumn(TitleBlockTemplate *, int = -1);
|
||||
static ModifyTemplateGridCommand *deleteRow(TitleBlockTemplate *, int = -1);
|
||||
static ModifyTemplateGridCommand *deleteColumn(TitleBlockTemplate *, int = -1);
|
||||
|
||||
// Constructors, destructor
|
||||
public:
|
||||
ModifyTemplateGridCommand(TitleBlockTemplate * = 0, QUndoCommand * = 0);
|
||||
virtual ~ModifyTemplateGridCommand();
|
||||
private:
|
||||
ModifyTemplateGridCommand(const ModifyTemplateGridCommand &);
|
||||
|
||||
// methods
|
||||
public:
|
||||
int index() const;
|
||||
void setIndex(int);
|
||||
QList<TitleBlockCell *> cells() const;
|
||||
void setCells(const QList<TitleBlockCell *> &);
|
||||
TitleBlockDimension dimension() const;
|
||||
void setDimension(const TitleBlockDimension &);
|
||||
int type() const;
|
||||
void setType(bool);
|
||||
bool isInsertion() const;
|
||||
void setInsertion(bool);
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
private:
|
||||
void updateText();
|
||||
void apply(bool = false);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
int index_; ///< Index of the inserted/deleted row/column
|
||||
QList<TitleBlockCell *> cells_; ///< Cells composing the inserted/deleted row/column
|
||||
bool type_; ///< true for a row, false for a column
|
||||
TitleBlockDimension dimension_; ///< width/height of the column/row, which interpretation depends on type_
|
||||
bool insertion_; /// true if the row/column is inserted, false if it is deleted
|
||||
};
|
||||
|
||||
/**
|
||||
This class represents the action of changing the width/height of a
|
||||
specific row/column within a title block template.
|
||||
*/
|
||||
class ModifyTemplateDimension : public TitleBlockTemplateCommand {
|
||||
// Constructor, destructor
|
||||
public:
|
||||
ModifyTemplateDimension(TitleBlockTemplate * = 0, QUndoCommand * = 0);
|
||||
virtual ~ModifyTemplateDimension();
|
||||
private:
|
||||
ModifyTemplateDimension(const ModifyTemplateDimension &);
|
||||
|
||||
// methods
|
||||
public:
|
||||
int index() const;
|
||||
void setIndex(int);
|
||||
int type() const;
|
||||
void setType(bool);
|
||||
TitleBlockDimension dimensionBefore() const;
|
||||
void setDimensionBefore(const TitleBlockDimension &);
|
||||
TitleBlockDimension dimensionAfter() const;
|
||||
void setDimensionAfter(const TitleBlockDimension &);
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
private:
|
||||
void updateText();
|
||||
void apply(const TitleBlockDimension &);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
int index_; ///< Index of the resized row/column
|
||||
bool type_; ///< true for a row, false for a column
|
||||
TitleBlockDimension before_; ///< Size of the row/column before it is changed
|
||||
TitleBlockDimension after_; ///< Size of the row/column after it is changed
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
This class represents the action of merging 2 to n cells into a single one.
|
||||
*/
|
||||
class MergeCellsCommand : public TitleBlockTemplateCommand {
|
||||
// Constructor, destructor
|
||||
public:
|
||||
MergeCellsCommand(const TitleBlockTemplateCellsSet &, TitleBlockTemplate * = 0, QUndoCommand * = 0);
|
||||
virtual ~MergeCellsCommand();
|
||||
|
||||
// methods
|
||||
public:
|
||||
bool isValid() const;
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
private:
|
||||
static TitleBlockCell *getBottomRightCell(const TitleBlockTemplateCellsSet &);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
/// the cell spanning over the other ones
|
||||
TitleBlockCell *spanning_cell_;
|
||||
/// hash associating spanned cells with their spanner_cell attribute
|
||||
/// before the merge operation
|
||||
QHash<TitleBlockCell *, TitleBlockCell *> spanner_cells_before_merge_;
|
||||
int row_span_before_; ///< the row_span attribute of the spanning cell before the merge
|
||||
int col_span_before_; ///< the col_span attribute of the spanning cell before the merge
|
||||
int row_span_after_; ///< the row_span attribute of the spanning cell after the merge
|
||||
int col_span_after_; ///< the col_span attribute of the spanning cell after the merge
|
||||
};
|
||||
|
||||
/**
|
||||
This class represents the action of splitting a visual cell into at least two logical cells
|
||||
*/
|
||||
class SplitCellsCommand : public TitleBlockTemplateCommand {
|
||||
// Constructor, destructor
|
||||
public:
|
||||
SplitCellsCommand(const TitleBlockTemplateCellsSet &, TitleBlockTemplate * = 0, QUndoCommand * = 0);
|
||||
virtual ~SplitCellsCommand();
|
||||
|
||||
// methods
|
||||
public:
|
||||
bool isValid() const;
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
TitleBlockCell *spanning_cell_; ///< the cell spanning over the other ones
|
||||
QSet<TitleBlockCell *> spanned_cells_; ///< the spanned cells
|
||||
int row_span_before_; ///< the row_span attribute of the spanning cell after the merge
|
||||
int col_span_before_; ///< the col_span attribute of the spanning cell after the merge
|
||||
};
|
||||
|
||||
#endif
|
321
sources/titleblock/templatelogomanager.cpp
Normal file
321
sources/titleblock/templatelogomanager.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "templatelogomanager.h"
|
||||
#include "titleblocktemplate.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param managed_template Title block template this widget manages logos for.
|
||||
@param parent Parent QWidget.
|
||||
*/
|
||||
TitleBlockTemplateLogoManager::TitleBlockTemplateLogoManager(TitleBlockTemplate *managed_template, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
managed_template_(managed_template)
|
||||
{
|
||||
initWidgets();
|
||||
fillView();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
TitleBlockTemplateLogoManager::~TitleBlockTemplateLogoManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return the name of the currently selected logo, or a null QString if none
|
||||
is selected.
|
||||
*/
|
||||
QString TitleBlockTemplateLogoManager::currentLogo() const {
|
||||
if (!managed_template_) return QString();
|
||||
|
||||
QListWidgetItem *current_item = logos_view_ -> currentItem();
|
||||
if (!current_item) return QString();
|
||||
|
||||
return(current_item -> text());
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize widgets composing the Logo manager
|
||||
*/
|
||||
void TitleBlockTemplateLogoManager::initWidgets() {
|
||||
open_dialog_dir_ = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||
|
||||
setWindowTitle(tr("Gestionnaire de logos"));
|
||||
logos_label_ = new QLabel(tr("Logos embarqu\351s dans ce mod\350le :"));
|
||||
logos_view_ = new QListWidget();
|
||||
logos_view_ -> setViewMode(QListView::IconMode);
|
||||
logos_view_ -> setGridSize(iconsize() * 1.4);
|
||||
logos_view_ -> setMinimumSize(iconsize() * 2.9);
|
||||
logos_view_ -> setIconSize(iconsize());
|
||||
logos_view_ -> setWrapping(true);
|
||||
logos_view_ -> setFlow(QListView::LeftToRight);
|
||||
logos_view_ -> setMovement(QListView::Static);
|
||||
logos_view_ -> setResizeMode(QListView::Adjust);
|
||||
add_button_ = new QPushButton(tr("Ajouter un logo"));
|
||||
delete_button_ = new QPushButton(tr("Supprimer ce logo"));
|
||||
logo_box_ = new QGroupBox(tr("Propri\351t\351s"));
|
||||
logo_name_label_ = new QLabel(tr("Nom :"));
|
||||
logo_name_ = new QLineEdit();
|
||||
rename_button_ = new QPushButton(tr("Renommer"));
|
||||
logo_type_ = new QLabel(tr("Type :"));
|
||||
buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
|
||||
hlayout1_ = new QHBoxLayout();
|
||||
hlayout1_ -> addWidget(logo_name_label_);
|
||||
hlayout1_ -> addWidget(logo_name_);
|
||||
hlayout1_ -> addWidget(rename_button_);
|
||||
|
||||
hlayout0_ = new QHBoxLayout();
|
||||
hlayout0_ -> addWidget(add_button_);
|
||||
hlayout0_ -> addWidget(delete_button_);
|
||||
|
||||
vlayout1_ = new QVBoxLayout();
|
||||
vlayout1_ -> addLayout(hlayout1_);
|
||||
vlayout1_ -> addWidget(logo_type_);
|
||||
logo_box_ -> setLayout(vlayout1_);
|
||||
|
||||
vlayout0_ = new QVBoxLayout();
|
||||
vlayout0_ -> addWidget(logos_label_);
|
||||
vlayout0_ -> addWidget(logos_view_);
|
||||
vlayout0_ -> addLayout(hlayout0_);
|
||||
vlayout0_ -> addWidget(logo_box_);
|
||||
setLayout(vlayout0_);
|
||||
|
||||
connect(
|
||||
logos_view_,
|
||||
SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
|
||||
this,
|
||||
SLOT(updateLogoInformations(QListWidgetItem *, QListWidgetItem *))
|
||||
);
|
||||
connect(add_button_, SIGNAL(released()), this, SLOT(addLogo()));
|
||||
connect(delete_button_, SIGNAL(released()), this, SLOT(removeLogo()));
|
||||
connect(rename_button_, SIGNAL(released()), this, SLOT(renameLogo()));
|
||||
}
|
||||
|
||||
/**
|
||||
Update the logos display.
|
||||
*/
|
||||
void TitleBlockTemplateLogoManager::fillView() {
|
||||
if (!managed_template_) return;
|
||||
logos_view_ -> clear();
|
||||
|
||||
foreach (QString logo_name, managed_template_ -> logos()) {
|
||||
QIcon current_icon;
|
||||
QPixmap current_logo = managed_template_ -> bitmapLogo(logo_name);
|
||||
if (!current_logo.isNull()) {
|
||||
current_icon = QIcon(current_logo);
|
||||
} else {
|
||||
QSvgRenderer *svg_logo = managed_template_ -> vectorLogo(logo_name);
|
||||
if (svg_logo) {
|
||||
QPixmap *svg_pixmap = new QPixmap(iconsize());
|
||||
svg_pixmap -> fill();
|
||||
QPainter p;
|
||||
p.begin(svg_pixmap);
|
||||
svg_logo -> render(&p);
|
||||
p.end();
|
||||
current_icon = QIcon(*svg_pixmap);
|
||||
}
|
||||
}
|
||||
QListWidgetItem *qlwi = new QListWidgetItem(current_icon, logo_name);
|
||||
qlwi -> setTextAlignment(Qt::AlignBottom | Qt::AlignHCenter);
|
||||
logos_view_ -> insertItem(0, qlwi);
|
||||
}
|
||||
|
||||
QListWidgetItem *current_item = logos_view_ -> currentItem();
|
||||
updateLogoInformations(current_item, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the icon size to display the logos embedded within the managed
|
||||
template.
|
||||
*/
|
||||
QSize TitleBlockTemplateLogoManager::iconsize() const {
|
||||
return(QSize(80, 80));
|
||||
}
|
||||
|
||||
/**
|
||||
When adding a logo, it may occur its name is already used by another
|
||||
pre-existing logo. This method asks users whether they want to erase the
|
||||
existing logo, change the initial name or simply cancel the operation.
|
||||
@param initial_name Initial name of the logo to be added
|
||||
@return Either a null QString if the user cancelled the operation, or the
|
||||
name to be used when adding the logo.
|
||||
*/
|
||||
QString TitleBlockTemplateLogoManager::confirmLogoName(const QString &initial_name) {
|
||||
QString name = initial_name;
|
||||
QDialog *rename_dialog = 0;
|
||||
QLabel *rd_label = 0;
|
||||
QLineEdit *rd_input = 0;
|
||||
while (managed_template_ -> logos().contains(name)) {
|
||||
if (!rename_dialog) {
|
||||
rename_dialog = new QDialog(this);
|
||||
rename_dialog -> setWindowTitle(tr("Logo d\351j\340 existant"));
|
||||
|
||||
rd_label = new QLabel();
|
||||
rd_label -> setWordWrap(true);
|
||||
rd_input = new QLineEdit();
|
||||
QDialogButtonBox *rd_buttons = new QDialogButtonBox();
|
||||
QPushButton *replace_button = rd_buttons -> addButton(tr("Remplacer"), QDialogButtonBox::YesRole);
|
||||
QPushButton *rename_button = rd_buttons -> addButton(tr("Renommer"), QDialogButtonBox::NoRole);
|
||||
QPushButton *cancel_button = rd_buttons -> addButton(QDialogButtonBox::Cancel);
|
||||
|
||||
QVBoxLayout *rd_vlayout0 = new QVBoxLayout();
|
||||
rd_vlayout0 -> addWidget(rd_label);
|
||||
rd_vlayout0 -> addWidget(rd_input);
|
||||
rd_vlayout0 -> addWidget(rd_buttons);
|
||||
rename_dialog -> setLayout(rd_vlayout0);
|
||||
|
||||
QSignalMapper *signal_mapper = new QSignalMapper(rename_dialog);
|
||||
signal_mapper -> setMapping(replace_button, QDialogButtonBox::YesRole);
|
||||
signal_mapper -> setMapping(rename_button, QDialogButtonBox::NoRole);
|
||||
signal_mapper -> setMapping(cancel_button, QDialogButtonBox::RejectRole);
|
||||
connect(replace_button, SIGNAL(clicked()), signal_mapper, SLOT(map()));
|
||||
connect(rename_button, SIGNAL(clicked()), signal_mapper, SLOT(map()));
|
||||
connect(cancel_button, SIGNAL(clicked()), signal_mapper, SLOT(map()));
|
||||
connect(signal_mapper, SIGNAL(mapped(int)), rename_dialog, SLOT(done(int)));
|
||||
}
|
||||
rd_label -> setText(
|
||||
QString(tr(
|
||||
"Il existe d\351j\340 un logo portant le nom \"%1\" au sein de "
|
||||
"ce mod\350le de cartouche. Voulez-vous le remplacer ou "
|
||||
"pr\351f\351rez-vous sp\351cifier un autre nom pour ce nouveau "
|
||||
"logo ?"
|
||||
)).arg(name)
|
||||
);
|
||||
rd_input -> setText(name);
|
||||
int answer = rename_dialog -> exec();
|
||||
if (answer == QDialogButtonBox::YesRole) {
|
||||
// we can use the initial name
|
||||
break;
|
||||
} else if (answer == QDialogButtonBox::NoRole) {
|
||||
// the user provided another name
|
||||
name = rd_input -> text();
|
||||
/// TODO prevent the user from entering an empty name
|
||||
} else {
|
||||
// the user cancelled the operation
|
||||
return(QString());
|
||||
}
|
||||
};
|
||||
return(name);
|
||||
}
|
||||
|
||||
/**
|
||||
Update the displayed informations relative to the currently selected logo.
|
||||
@param current Newly selected logo item
|
||||
@param previous Previously selected logo item
|
||||
*/
|
||||
void TitleBlockTemplateLogoManager::updateLogoInformations(QListWidgetItem *current, QListWidgetItem *previous) {
|
||||
Q_UNUSED(previous);
|
||||
if (current) {
|
||||
QString logo_name = current -> text();
|
||||
logo_name_ -> setText(logo_name);
|
||||
if (managed_template_) {
|
||||
QString logo_type = managed_template_ -> logoType(logo_name);
|
||||
logo_type_ -> setText(tr("Type : %1").arg(logo_type));
|
||||
}
|
||||
} else {
|
||||
logo_name_ -> setText(QString());
|
||||
logo_type_ -> setText(tr("Type :"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Ask the user for a filepath, and add it as a new logo in the managed
|
||||
template.
|
||||
*/
|
||||
void TitleBlockTemplateLogoManager::addLogo() {
|
||||
if (!managed_template_) return;
|
||||
|
||||
QString filepath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
tr("Choisir une image / un logo"),
|
||||
open_dialog_dir_.absolutePath(),
|
||||
tr("Images vectorielles (*.svg);;Images bitmap (*.png *.jpg *.jpeg *.gif *.bmp *.xpm);;Tous les fichiers (*)")
|
||||
);
|
||||
if (filepath.isEmpty()) return;
|
||||
|
||||
// that filepath needs to point to a valid, readable file
|
||||
QFileInfo filepath_info(filepath);
|
||||
if (!filepath_info.exists() || !filepath_info.isReadable()) {
|
||||
QMessageBox::critical(this, tr("Erreur"), tr("Impossible d'ouvrir le fichier sp\351cifi\351"));
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure we can use the file name to add the logo
|
||||
QString logo_name = confirmLogoName(filepath_info.fileName());
|
||||
if (logo_name.isNull()) return;
|
||||
|
||||
open_dialog_dir_ = QDir(filepath);
|
||||
if (managed_template_ -> addLogoFromFile(filepath, logo_name)) {
|
||||
fillView();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Delete the currently selected logo.
|
||||
*/
|
||||
void TitleBlockTemplateLogoManager::removeLogo() {
|
||||
QString current_logo = currentLogo();
|
||||
if (current_logo.isNull()) return;
|
||||
|
||||
if (managed_template_ -> removeLogo(current_logo)) {
|
||||
fillView();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Rename currently selected logo.
|
||||
*/
|
||||
void TitleBlockTemplateLogoManager::renameLogo() {
|
||||
QString current_logo = currentLogo();
|
||||
if (current_logo.isNull()) return;
|
||||
|
||||
QString entered_name = logo_name_ -> text();
|
||||
QString warning_title = tr("Renommer un logo");
|
||||
if (entered_name == current_logo) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
warning_title,
|
||||
tr("Vous devez saisir un nouveau nom.")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entered_name.trimmed().isEmpty()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
warning_title,
|
||||
tr("Le nouveau nom ne peut pas \352tre vide.")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (managed_template_ -> logos().contains(entered_name)) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
warning_title,
|
||||
tr("Le nom saisi est d\351j\340 utilis\351 par un autre logo.")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (managed_template_ -> renameLogo(current_logo, entered_name)) {
|
||||
fillView();
|
||||
}
|
||||
}
|
68
sources/titleblock/templatelogomanager.h
Normal file
68
sources/titleblock/templatelogomanager.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_TEMPLATE_LOGO_MANAGER
|
||||
#define TITLEBLOCK_SLASH_TEMPLATE_LOGO_MANAGER
|
||||
#include <QtGui>
|
||||
class TitleBlockTemplate;
|
||||
|
||||
/**
|
||||
This widget allows users to manage (list, add, edit, delete) logos embedded
|
||||
within a title block template.
|
||||
*/
|
||||
class TitleBlockTemplateLogoManager : public QWidget {
|
||||
Q_OBJECT
|
||||
// Constructor, destructor
|
||||
public:
|
||||
TitleBlockTemplateLogoManager(TitleBlockTemplate *, QWidget * = 0);
|
||||
virtual ~TitleBlockTemplateLogoManager();
|
||||
|
||||
// methods
|
||||
public:
|
||||
QString currentLogo() const;
|
||||
|
||||
protected:
|
||||
private:
|
||||
void initWidgets();
|
||||
void fillView();
|
||||
QSize iconsize() const;
|
||||
QString confirmLogoName(const QString &);
|
||||
|
||||
private slots:
|
||||
void updateLogoInformations(QListWidgetItem *, QListWidgetItem *);
|
||||
void addLogo();
|
||||
void removeLogo();
|
||||
void renameLogo();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
TitleBlockTemplate *managed_template_; ///< title block template which this class manages logos
|
||||
QVBoxLayout *vlayout0_, *vlayout1_; ///< vertical layouts
|
||||
QHBoxLayout *hlayout0_, *hlayout1_; ///< horizontal layouts
|
||||
QLabel *logos_label_; ///< simple displayed label
|
||||
QListWidget *logos_view_; ///< area showing the logos
|
||||
QPushButton *add_button_; ///< button to add a new logo
|
||||
QPushButton *delete_button_; ///< button to delete an embeded logo
|
||||
QGroupBox *logo_box_; ///< current logo properties box
|
||||
QLabel *logo_name_label_; ///< "name:" label
|
||||
QLineEdit *logo_name_; ///< current logo name
|
||||
QPushButton *rename_button_; ///< button to rename the current logo
|
||||
QLabel *logo_type_; ///< current logo type
|
||||
QDialogButtonBox *buttons_; ///< ok/cancel buttons
|
||||
QDir open_dialog_dir_; ///< last opened directory
|
||||
};
|
||||
#endif
|
775
sources/titleblock/templateview.cpp
Normal file
775
sources/titleblock/templateview.cpp
Normal file
@ -0,0 +1,775 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "templateview.h"
|
||||
#include "templatevisualcell.h"
|
||||
#include "gridlayoutanimation.h"
|
||||
#include "helpercell.h"
|
||||
#include "splittedhelpercell.h"
|
||||
#include "templatecommands.h"
|
||||
#include "templatecellsset.h"
|
||||
#include "dimensionwidget.h"
|
||||
#include "qetapp.h"
|
||||
#define ROW_OFFSET 2
|
||||
#define COL_OFFSET 1
|
||||
#define DEFAULT_PREVIEW_WIDTH 600
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param parent Parent QWidget.
|
||||
*/
|
||||
TitleBlockTemplateView::TitleBlockTemplateView(QWidget *parent) :
|
||||
QGraphicsView(parent),
|
||||
tbtemplate_(0),
|
||||
tbgrid_(0),
|
||||
form_(0),
|
||||
preview_width_(DEFAULT_PREVIEW_WIDTH),
|
||||
apply_columns_widths_count_(0),
|
||||
apply_rows_heights_count_(0)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param parent Parent QWidget.
|
||||
*/
|
||||
TitleBlockTemplateView::TitleBlockTemplateView(QGraphicsScene *scene, QWidget *parent) :
|
||||
QGraphicsView(scene, parent),
|
||||
tbtemplate_(0),
|
||||
tbgrid_(0),
|
||||
preview_width_(DEFAULT_PREVIEW_WIDTH),
|
||||
apply_columns_widths_count_(0),
|
||||
apply_rows_heights_count_(0)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
TitleBlockTemplateView::~TitleBlockTemplateView() {
|
||||
}
|
||||
|
||||
/**
|
||||
@param tbtemplate Title block template to be rendered by this view.
|
||||
If set to zero, the View will render nothing.
|
||||
*/
|
||||
void TitleBlockTemplateView::setTitleBlockTemplate(TitleBlockTemplate *tbtemplate) {
|
||||
loadTemplate(tbtemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
@return The title block template object rendered by this view.
|
||||
*/
|
||||
TitleBlockTemplate *TitleBlockTemplateView::titleBlockTemplate() const {
|
||||
return(tbtemplate_);
|
||||
}
|
||||
|
||||
/**
|
||||
Emits the selectedCellsChanged() signal with the currently selected cells.
|
||||
*/
|
||||
void TitleBlockTemplateView::selectionChanged() {
|
||||
emit(selectedCellsChanged(selectedCells()));
|
||||
}
|
||||
|
||||
/**
|
||||
Zoom in by zoomFactor().
|
||||
@see zoomFactor()
|
||||
*/
|
||||
void TitleBlockTemplateView::zoomIn() {
|
||||
scale(zoomFactor(), zoomFactor());
|
||||
}
|
||||
|
||||
/**
|
||||
Zoom out by zoomFactor().
|
||||
@see zoomFactor()
|
||||
*/
|
||||
void TitleBlockTemplateView::zoomOut() {
|
||||
qreal zoom_factor = 1.0/zoomFactor();
|
||||
scale(zoom_factor, zoom_factor);
|
||||
}
|
||||
|
||||
/**
|
||||
Add a column right before the last index selected when calling the context
|
||||
menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::addColumnBefore() {
|
||||
int index = lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
requestGridModification(ModifyTemplateGridCommand::addColumn(tbtemplate_, index));
|
||||
}
|
||||
|
||||
/**
|
||||
Add a row right before the last index selected when calling the context
|
||||
menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::addRowBefore() {
|
||||
int index = lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
requestGridModification(ModifyTemplateGridCommand::addRow(tbtemplate_, index));
|
||||
}
|
||||
|
||||
/**
|
||||
Add a column right after the last index selected when calling the context
|
||||
menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::addColumnAfter() {
|
||||
int index = lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
requestGridModification(ModifyTemplateGridCommand::addColumn(tbtemplate_, index + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
Add a row right after the last index selected when calling the context
|
||||
menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::addRowAfter() {
|
||||
int index = lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
requestGridModification(ModifyTemplateGridCommand::addRow(tbtemplate_, index + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
Edit the width of a column.
|
||||
@param cell (optional) HelperCell of the column to be modified. If 0, this
|
||||
method uses the last index selected when calling the context menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::editColumn(HelperCell *cell) {
|
||||
int index = cell ? cell -> index : lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
|
||||
TitleBlockDimension dimension_before = tbtemplate_ -> columnDimension(index);
|
||||
TitleBlockDimensionWidget dialog(true, this);
|
||||
dialog.setWindowTitle(tr("Changer la largeur de la colonne", "window title when changing a column with"));
|
||||
dialog.label() -> setText(tr("Largeur :", "text before the spinbox to change a column width"));
|
||||
dialog.setValue(dimension_before);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
ModifyTemplateDimension *command = new ModifyTemplateDimension(tbtemplate_);
|
||||
command -> setType(false);
|
||||
command -> setIndex(index);
|
||||
command -> setDimensionBefore(dimension_before);
|
||||
command -> setDimensionAfter(dialog.value());
|
||||
requestGridModification(command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Edit the height of a row.
|
||||
@param cell (optional) HelperCell of the row to be modified. If 0, this
|
||||
method uses the last index selected when calling the context menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::editRow(HelperCell *cell) {
|
||||
int index = cell ? cell -> index : lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
|
||||
TitleBlockDimension dimension_before = TitleBlockDimension(tbtemplate_ -> rowDimension(index));
|
||||
TitleBlockDimensionWidget dialog(false, this);
|
||||
dialog.setWindowTitle(tr("Changer la hauteur de la ligne", "window title when changing a row height"));
|
||||
dialog.label() -> setText(tr("Hauteur :", "text before the spinbox to change a row height"));
|
||||
dialog.setValue(dimension_before);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
ModifyTemplateDimension *command = new ModifyTemplateDimension(tbtemplate_);
|
||||
command -> setType(true);
|
||||
command -> setIndex(index);
|
||||
command -> setDimensionBefore(dimension_before);
|
||||
command -> setDimensionAfter(dialog.value());
|
||||
requestGridModification(command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the column at the last index selected when calling the context menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::deleteColumn() {
|
||||
int index = lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
requestGridModification(ModifyTemplateGridCommand::deleteColumn(tbtemplate_, index));
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the row at the last index selected when calling the context menu.
|
||||
*/
|
||||
void TitleBlockTemplateView::deleteRow() {
|
||||
int index = lastContextMenuCellIndex();
|
||||
if (index == -1) return;
|
||||
requestGridModification(ModifyTemplateGridCommand::deleteRow(tbtemplate_, index));
|
||||
}
|
||||
|
||||
/**
|
||||
Merge the selected cells.
|
||||
*/
|
||||
void TitleBlockTemplateView::mergeSelectedCells() {
|
||||
// retrieve the selected cells
|
||||
TitleBlockTemplateCellsSet selected_cells = selectedCellsSet();
|
||||
|
||||
// merging applies only to cells composing a rectangle
|
||||
if (!selected_cells.isRectangle()) {
|
||||
qDebug() << "selected cells are not composing a rectangle";
|
||||
return;
|
||||
}
|
||||
|
||||
// the merge area may also be too small
|
||||
if (selected_cells.count() < 2) {
|
||||
qDebug() << "the merge area does not even contain 2 selected and mergeable cells";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "ok, ready for cells merge";
|
||||
MergeCellsCommand *merge_command = new MergeCellsCommand(selected_cells, tbtemplate_);
|
||||
if (merge_command -> isValid()) requestGridModification(merge_command);
|
||||
}
|
||||
|
||||
/**
|
||||
Split the selected cell.
|
||||
*/
|
||||
void TitleBlockTemplateView::splitSelectedCell() {
|
||||
// retrieve the selected cells
|
||||
TitleBlockTemplateCellsSet selected_cells = selectedCellsSet();
|
||||
|
||||
// we expect only one visual cell to be selected
|
||||
if (selected_cells.count() != 1) {
|
||||
qDebug() << "please select a single cell";
|
||||
return;
|
||||
}
|
||||
|
||||
SplitCellsCommand *split_command = new SplitCellsCommand(selected_cells, tbtemplate_);
|
||||
if (split_command -> isValid()) requestGridModification(split_command);
|
||||
}
|
||||
|
||||
/**
|
||||
Reimplement the way the background is drawn to render the title block
|
||||
template.
|
||||
*/
|
||||
void TitleBlockTemplateView::drawBackground(QPainter *painter, const QRectF &rect) {
|
||||
QGraphicsView::drawBackground(painter, rect);
|
||||
if (!tbtemplate_) return; // TODO shouldn't we draw a large uniform rect?
|
||||
}
|
||||
|
||||
/**
|
||||
@return the selected logical cells, not including the spanned ones.
|
||||
*/
|
||||
QList<TitleBlockCell *> TitleBlockTemplateView::selectedCells() const {
|
||||
return(selectedCellsSet().cells(false).toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@return the selected visual cells.
|
||||
*/
|
||||
TitleBlockTemplateCellsSet TitleBlockTemplateView::selectedCellsSet() const {
|
||||
return(makeCellsSetFromGraphicsItems(scene() -> selectedItems()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return the visual cells contained in the \a rect
|
||||
@param rect Rectangle in the coordinates of the QGraphicsWidget
|
||||
representing the title block template.
|
||||
*/
|
||||
TitleBlockTemplateCellsSet TitleBlockTemplateView::cells(const QRectF &rect) const {
|
||||
QPolygonF mapped_rect(form_ -> mapToScene(rect));
|
||||
QList<QGraphicsItem *> items = scene() -> items(mapped_rect, Qt::IntersectsItemShape);
|
||||
return(makeCellsSetFromGraphicsItems(items));
|
||||
}
|
||||
|
||||
/**
|
||||
Handles mouse wheel-related actions
|
||||
@param e QWheelEvent describing the wheel event
|
||||
*/
|
||||
void TitleBlockTemplateView::wheelEvent(QWheelEvent *e) {
|
||||
// si la touche Ctrl est enfoncee, on zoome / dezoome
|
||||
if (e -> modifiers() & Qt::ControlModifier) {
|
||||
if (e -> delta() > 0) {
|
||||
zoomIn();
|
||||
} else {
|
||||
zoomOut();
|
||||
}
|
||||
} else {
|
||||
QAbstractScrollArea::wheelEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return the zoom factor used by zoomIn() and zoomOut().
|
||||
*/
|
||||
qreal TitleBlockTemplateView::zoomFactor() const {
|
||||
return(1.1);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize this view (actions, signals/slots connections, etc.)
|
||||
*/
|
||||
void TitleBlockTemplateView::init() {
|
||||
add_column_before_ = new QAction(tr("Ajouter une colonne (avant)", "context menu"), this);
|
||||
add_row_before_ = new QAction(tr("Ajouter une ligne (avant)", "context menu"), this);
|
||||
add_column_after_ = new QAction(tr("Ajouter une colonne (apr\350s)", "context menu"), this);
|
||||
add_row_after_ = new QAction(tr("Ajouter une ligne (apr\350s)", "context menu"), this);
|
||||
edit_column_dim_ = new QAction(tr("Modifier les dimensions de cette colonne", "context menu"), this);
|
||||
edit_row_dim_ = new QAction(tr("Modifier les dimensions de cette ligne", "context menu"), this);
|
||||
delete_column_ = new QAction(tr("Supprimer cette colonne", "context menu"), this);
|
||||
delete_row_ = new QAction(tr("Supprimer cette ligne", "context menu"), this);
|
||||
change_preview_width_ = new QAction(tr("Modifier la largeur de cet aper\347u", "context menu"), this);
|
||||
|
||||
connect(add_column_before_, SIGNAL(triggered()), this, SLOT(addColumnBefore()));
|
||||
connect(add_row_before_, SIGNAL(triggered()), this, SLOT(addRowBefore()));
|
||||
connect(add_column_after_, SIGNAL(triggered()), this, SLOT(addColumnAfter()));
|
||||
connect(add_row_after_, SIGNAL(triggered()), this, SLOT(addRowAfter()));
|
||||
connect(edit_column_dim_, SIGNAL(triggered()), this, SLOT(editColumn()));
|
||||
connect(edit_row_dim_, SIGNAL(triggered()), this, SLOT(editRow()));
|
||||
connect(delete_column_, SIGNAL(triggered()), this, SLOT(deleteColumn()));
|
||||
connect(delete_row_, SIGNAL(triggered()), this, SLOT(deleteRow()));
|
||||
connect(change_preview_width_, SIGNAL(triggered()), this, SLOT(changePreviewWidth()));
|
||||
|
||||
setBackgroundBrush(QBrush(QColor(248, 255, 160)));
|
||||
|
||||
connect(scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
|
||||
}
|
||||
|
||||
/**
|
||||
Apply the columns widths currently specified by the edited title block
|
||||
template.
|
||||
@param animate true to animate the change, false otherwise.
|
||||
*/
|
||||
void TitleBlockTemplateView::applyColumnsWidths(bool animate) {
|
||||
// the first column is dedicated to helper cells showing the rows height
|
||||
tbgrid_ -> setColumnFixedWidth(0, 50);
|
||||
tbgrid_ -> setColumnSpacing(0, 0);
|
||||
|
||||
// we apply the other columns width based on the title block template data
|
||||
QList<int> widths = tbtemplate_ -> columnsWidth(preview_width_);
|
||||
int total_applied_width = 0;
|
||||
for (int i = 0 ; i < widths.count() ; ++ i) {
|
||||
int applied_width = qMax(0, widths.at(i));
|
||||
tbgrid_ -> setColumnSpacing(COL_OFFSET + i, 0);
|
||||
if (!animate) {
|
||||
// no animation on first call
|
||||
tbgrid_ -> setColumnFixedWidth(COL_OFFSET + i, widths.at(i));
|
||||
} else {
|
||||
GridLayoutAnimation *animation = new GridLayoutAnimation(tbgrid_, form_);
|
||||
animation -> setIndex(COL_OFFSET + i);
|
||||
animation -> setActsOnRows(false);
|
||||
animation -> setStartValue(QVariant(tbgrid_ -> columnMinimumWidth(COL_OFFSET + i)));
|
||||
animation -> setEndValue(QVariant(1.0 * applied_width));
|
||||
animation -> setDuration(500);
|
||||
connect(animation, SIGNAL(finished()), this, SLOT(updateColumnsHelperCells()));
|
||||
animation -> start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
total_applied_width += applied_width;
|
||||
}
|
||||
if (!animate) updateColumnsHelperCells();
|
||||
++ apply_columns_widths_count_;
|
||||
|
||||
// we systematically parameter some cells
|
||||
total_width_helper_cell_ -> split_size = 0;
|
||||
tbgrid_ -> addItem(total_width_helper_cell_, 0, COL_OFFSET, 1, widths.count());
|
||||
removeItem(extra_cells_width_helper_cell_);
|
||||
|
||||
if (total_applied_width < preview_width_) {
|
||||
// preview_width is greater than the sum of cells widths
|
||||
// we add an extra column with a helper cell
|
||||
tbgrid_ -> addItem(extra_cells_width_helper_cell_, ROW_OFFSET - 1, COL_OFFSET + widths.count(), tbtemplate_ -> rowsCount() + 1, 1);
|
||||
tbgrid_ -> addItem(total_width_helper_cell_, 0, COL_OFFSET, 1, widths.count() + 1);
|
||||
tbgrid_ -> setColumnFixedWidth(COL_OFFSET + widths.count(), preview_width_ - total_applied_width);
|
||||
extra_cells_width_helper_cell_ -> label = QString(
|
||||
tr("[%1px]","content of the extra cell added when the total width of cells is less than the preview width")
|
||||
).arg(preview_width_ - total_applied_width);
|
||||
} else if (total_applied_width > preview_width_) {
|
||||
// preview width is smaller than the sum of cells widths
|
||||
// we draw an extra header within th "preview width" cell.
|
||||
tbgrid_ -> addItem(total_width_helper_cell_, 0, COL_OFFSET, 1, widths.count());
|
||||
total_width_helper_cell_ -> split_background_color = QColor(Qt::red);
|
||||
total_width_helper_cell_ -> split_foreground_color = QColor(Qt::black);
|
||||
total_width_helper_cell_ -> split_label = QString(
|
||||
tr("[%1px]", "content of the extra helper cell added when the total width of cells is greather than the preview width")
|
||||
).arg(total_applied_width - preview_width_);
|
||||
total_width_helper_cell_ -> split_size = total_applied_width - preview_width_;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Apply the rows heights currently specified by the edited title block
|
||||
template.
|
||||
@param animate true to animate the change, false otherwise.
|
||||
*/
|
||||
void TitleBlockTemplateView::applyRowsHeights(bool animate) {
|
||||
// the first row is dedicated to a helper cell showing the total width
|
||||
tbgrid_ -> setRowFixedHeight(0, 15);
|
||||
tbgrid_ -> setRowSpacing(0, 0);
|
||||
// the second row is dedicated to helper cells showing the columns width
|
||||
tbgrid_ -> setRowFixedHeight(1, 15);
|
||||
tbgrid_ -> setRowSpacing(1, 0);
|
||||
// the first column is dedicated to helper cells showing the rows height
|
||||
tbgrid_ -> setColumnFixedWidth(0, 45);
|
||||
tbgrid_ -> setColumnSpacing(0, 0);
|
||||
|
||||
QList<int> heights = tbtemplate_ -> rowsHeights();
|
||||
for (int i = 0 ; i < heights.count() ; ++ i) {
|
||||
tbgrid_ -> setRowSpacing(ROW_OFFSET + i, 0);
|
||||
if (!animate) {
|
||||
// no animation on first call
|
||||
tbgrid_ -> setRowFixedHeight(ROW_OFFSET + i, heights.at(i));
|
||||
} else {
|
||||
GridLayoutAnimation *animation = new GridLayoutAnimation(tbgrid_, form_);
|
||||
animation -> setIndex(ROW_OFFSET + i);
|
||||
animation -> setActsOnRows(true);
|
||||
animation -> setStartValue(QVariant(tbgrid_ -> rowMinimumHeight(ROW_OFFSET + i)));
|
||||
animation -> setEndValue(QVariant(1.0 * heights.at(i)));
|
||||
animation -> setDuration(500);
|
||||
connect(animation, SIGNAL(finished()), this, SLOT(updateRowsHelperCells()));
|
||||
animation -> start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
|
||||
}
|
||||
if (!animate) updateRowsHelperCells();
|
||||
++ apply_rows_heights_count_;
|
||||
}
|
||||
|
||||
/**
|
||||
Update the content (type and value) of rows helper cells.
|
||||
*/
|
||||
void TitleBlockTemplateView::updateRowsHelperCells() {
|
||||
int row_count = tbtemplate_ -> rowsCount();
|
||||
QList<int> heights = tbtemplate_ -> rowsHeights();
|
||||
for (int i = 0 ; i < row_count ; ++ i) {
|
||||
HelperCell *current_row_cell = static_cast<HelperCell *>(tbgrid_ -> itemAt(ROW_OFFSET + i, 0));
|
||||
current_row_cell -> setType(QET::Absolute); // rows always have absolute heights
|
||||
current_row_cell -> label = QString(tr("%1px", "format displayed in rows helper cells")).arg(heights.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Update the content (type and value) of columns helper cells.
|
||||
*/
|
||||
void TitleBlockTemplateView::updateColumnsHelperCells() {
|
||||
int col_count = tbtemplate_ -> columnsCount();
|
||||
for (int i = 0 ; i < col_count ; ++ i) {
|
||||
TitleBlockDimension current_col_dim = tbtemplate_ -> columnDimension(i);
|
||||
HelperCell *current_col_cell = static_cast<HelperCell *>(tbgrid_ -> itemAt(1, COL_OFFSET + i));
|
||||
current_col_cell -> setType(current_col_dim.type);
|
||||
current_col_cell -> label = current_col_dim.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Add the cells (both helper cells and regular visual cells) to the scene to
|
||||
get a visual representation of the edited title block template.
|
||||
*/
|
||||
void TitleBlockTemplateView::addCells() {
|
||||
int col_count = tbtemplate_ -> columnsCount();
|
||||
int row_count = tbtemplate_ -> rowsCount();
|
||||
if (row_count < 1 || col_count < 1) return;
|
||||
|
||||
// we add a big cell to show the total width
|
||||
total_width_helper_cell_ = new SplittedHelperCell();
|
||||
total_width_helper_cell_ -> setType(QET::Absolute);
|
||||
updateTotalWidthLabel();
|
||||
total_width_helper_cell_ -> orientation = Qt::Horizontal;
|
||||
total_width_helper_cell_ -> setActions(QList<QAction *>() << change_preview_width_);
|
||||
connect(total_width_helper_cell_, SIGNAL(contextMenuTriggered(HelperCell *)), this, SLOT(updateLastContextMenuCell(HelperCell *)));
|
||||
connect(total_width_helper_cell_, SIGNAL(doubleClicked(HelperCell*)), this, SLOT(changePreviewWidth()));
|
||||
tbgrid_ -> addItem(total_width_helper_cell_, 0, COL_OFFSET, 1, col_count);
|
||||
|
||||
// we also initialize an extra helper cells that shows the preview width is
|
||||
// too long for the current cells widths
|
||||
extra_cells_width_helper_cell_ = new HelperCell();
|
||||
extra_cells_width_helper_cell_ -> background_color = QColor(Qt::red);
|
||||
|
||||
// we add one cell per column to show their respective width
|
||||
for (int i = 0 ; i < col_count ; ++ i) {
|
||||
TitleBlockDimension current_col_dim = tbtemplate_ -> columnDimension(i);
|
||||
HelperCell *current_col_cell = new HelperCell();
|
||||
current_col_cell -> setType(current_col_dim.type);
|
||||
current_col_cell -> label = current_col_dim.toString();
|
||||
current_col_cell -> setActions(columnsActions());
|
||||
current_col_cell -> orientation = Qt::Horizontal;
|
||||
current_col_cell -> index = i;
|
||||
connect(current_col_cell, SIGNAL(contextMenuTriggered(HelperCell *)), this, SLOT(updateLastContextMenuCell(HelperCell *)));
|
||||
connect(current_col_cell, SIGNAL(doubleClicked(HelperCell*)), this, SLOT(editColumn(HelperCell *)));
|
||||
tbgrid_ -> addItem(current_col_cell, 1, COL_OFFSET + i, 1, 1);
|
||||
}
|
||||
|
||||
// we add one cell per row to show their respective height
|
||||
QList<int> heights = tbtemplate_ -> rowsHeights();
|
||||
for (int i = 0 ; i < row_count ; ++ i) {
|
||||
HelperCell *current_row_cell = new HelperCell();
|
||||
current_row_cell -> setType(QET::Absolute); // rows always have absolute heights
|
||||
current_row_cell -> label = QString(tr("%1px")).arg(heights.at(i));
|
||||
current_row_cell -> orientation = Qt::Vertical;
|
||||
current_row_cell -> index = i;
|
||||
current_row_cell -> setActions(rowsActions());
|
||||
connect(current_row_cell, SIGNAL(contextMenuTriggered(HelperCell *)), this, SLOT(updateLastContextMenuCell(HelperCell *)));
|
||||
connect(current_row_cell, SIGNAL(doubleClicked(HelperCell*)), this, SLOT(editRow(HelperCell *)));
|
||||
tbgrid_ -> addItem(current_row_cell, ROW_OFFSET + i, 0, 1, 1);
|
||||
}
|
||||
|
||||
// eventually we add the cells composing the titleblock template
|
||||
for (int i = 0 ; i < col_count ; ++ i) {
|
||||
for (int j = 0 ; j < row_count ; ++ j) {
|
||||
TitleBlockCell *cell = tbtemplate_ -> cell(j, i);
|
||||
if (cell -> spanner_cell) continue;
|
||||
TitleBlockTemplateVisualCell *cell_item = new TitleBlockTemplateVisualCell();
|
||||
cell_item -> setTemplateCell(tbtemplate_, cell);
|
||||
tbgrid_ -> addItem(cell_item, ROW_OFFSET + j, COL_OFFSET + i, cell -> row_span + 1, cell -> col_span + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Refresh the regular cells.
|
||||
*/
|
||||
void TitleBlockTemplateView::refresh() {
|
||||
int col_count = tbtemplate_ -> columnsCount();
|
||||
int row_count = tbtemplate_ -> rowsCount();
|
||||
if (row_count < 1 || col_count < 1) return;
|
||||
|
||||
for (int i = 0 ; i < col_count ; ++ i) {
|
||||
for (int j = 0 ; j < row_count ; ++ j) {
|
||||
if (QGraphicsLayoutItem *item = tbgrid_ -> itemAt(ROW_OFFSET + j, COL_OFFSET + i)) {
|
||||
if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(item)) {
|
||||
qgi -> update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Ask the user a new width for the preview
|
||||
*/
|
||||
void TitleBlockTemplateView::changePreviewWidth() {
|
||||
TitleBlockDimensionWidget dialog(false, this);
|
||||
dialog.setWindowTitle(tr("Changer la largeur de l'aper\347u"));
|
||||
dialog.label() -> setText(tr("Largeur de l'aper\347u :"));
|
||||
dialog.setValue(TitleBlockDimension(preview_width_));
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
setPreviewWidth(dialog.value().value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Fill the layout with empty cells where needed.
|
||||
*/
|
||||
void TitleBlockTemplateView::fillWithEmptyCells() {
|
||||
int col_count = tbtemplate_ -> columnsCount();
|
||||
int row_count = tbtemplate_ -> rowsCount();
|
||||
if (row_count < 1 || col_count < 1) return;
|
||||
|
||||
for (int i = 0 ; i < col_count ; ++ i) {
|
||||
for (int j = 0 ; j < row_count ; ++ j) {
|
||||
if (tbgrid_ -> itemAt(ROW_OFFSET + j, COL_OFFSET + i)) continue;
|
||||
qDebug() << Q_FUNC_INFO << "looks like there is nothing there (" << j << "," << i << ")";
|
||||
TitleBlockTemplateVisualCell *cell_item = new TitleBlockTemplateVisualCell();
|
||||
if (TitleBlockCell *target_cell = tbtemplate_ -> cell(j, i)) {
|
||||
qDebug() << Q_FUNC_INFO << "target_cell" << target_cell;
|
||||
cell_item -> setTemplateCell(tbtemplate_, target_cell);
|
||||
}
|
||||
tbgrid_ -> addItem(cell_item, ROW_OFFSET + j, COL_OFFSET + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Load the \a tbt title block template.
|
||||
If a different template was previously loaded, it is deleted.
|
||||
|
||||
*/
|
||||
void TitleBlockTemplateView::loadTemplate(TitleBlockTemplate *tbt) {
|
||||
if (tbgrid_) {
|
||||
scene() -> removeItem(form_);
|
||||
// also deletes TemplateCellPreview because, according to the
|
||||
// documentation, QGraphicsGridLayout takes ownership of the items.
|
||||
form_ -> deleteLater();
|
||||
}
|
||||
if (tbtemplate_ && tbtemplate_ != tbt) {
|
||||
delete tbtemplate_;
|
||||
}
|
||||
|
||||
tbtemplate_ = tbt;
|
||||
|
||||
// initialize a grid layout with no margin
|
||||
tbgrid_ = new QGraphicsGridLayout();
|
||||
tbgrid_ -> setContentsMargins(0, 0, 0, 0);
|
||||
// add cells defined by the title block template in this layout
|
||||
addCells();
|
||||
// fill potential holes in the grid with empty cells
|
||||
fillWithEmptyCells();
|
||||
// apply rows and columns dimensions
|
||||
applyColumnsWidths(false);
|
||||
applyRowsHeights(false);
|
||||
|
||||
// assign the layout to a basic QGraphicsWidget
|
||||
form_ = new QGraphicsWidget();
|
||||
form_ -> setLayout(tbgrid_);
|
||||
scene() -> addItem(form_);
|
||||
adjustSceneRect();
|
||||
}
|
||||
|
||||
/**
|
||||
@return the list of rows-specific actions.
|
||||
*/
|
||||
QList<QAction *> TitleBlockTemplateView::rowsActions() const {
|
||||
return QList<QAction *>() << add_row_before_<< edit_row_dim_ << add_row_after_ << delete_row_;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the list of columns-specific actions.
|
||||
*/
|
||||
QList<QAction *> TitleBlockTemplateView::columnsActions() const {
|
||||
return QList<QAction *>() << add_column_before_ << edit_column_dim_ << add_column_after_ << delete_column_;
|
||||
}
|
||||
|
||||
/**
|
||||
Update the displayed layout. Call this function to refresh the display
|
||||
after the rendered title block template has been "deeply" modified, e.g.
|
||||
rows/columns have been added/modified or cells were merged/splitted.
|
||||
*/
|
||||
void TitleBlockTemplateView::updateLayout() {
|
||||
// TODO we should try to update the grid instead of deleting-and-reloading it
|
||||
loadTemplate(tbtemplate_);
|
||||
}
|
||||
|
||||
/**
|
||||
Update the displayed layout. Call this function when the dimensions of
|
||||
rows changed.
|
||||
*/
|
||||
void TitleBlockTemplateView::rowsDimensionsChanged() {
|
||||
applyRowsHeights();
|
||||
}
|
||||
|
||||
/**
|
||||
Update the displayed layout. Call this function when the dimensions of
|
||||
columns changed.
|
||||
*/
|
||||
void TitleBlockTemplateView::columnsDimensionsChanged() {
|
||||
applyColumnsWidths();
|
||||
}
|
||||
|
||||
/**
|
||||
Set the new preview width to width
|
||||
@param width new preview width
|
||||
*/
|
||||
void TitleBlockTemplateView::setPreviewWidth(int width) {
|
||||
if (preview_width_ == width) return;
|
||||
preview_width_ = width;
|
||||
applyColumnsWidths();
|
||||
updateTotalWidthLabel();
|
||||
//adjustSceneRect();
|
||||
centerOn(form_);
|
||||
/// TODO center again the preview()
|
||||
}
|
||||
|
||||
/**
|
||||
Update the label of the helper cell that indicates the preview width.
|
||||
*/
|
||||
void TitleBlockTemplateView::updateTotalWidthLabel() {
|
||||
if (!total_width_helper_cell_) return;
|
||||
total_width_helper_cell_ -> label = QString(
|
||||
tr(
|
||||
"Largeur totale pour cet aper\347u : %1px",
|
||||
"displayed at the top of the preview when editing a title block template"
|
||||
)
|
||||
).arg(preview_width_);
|
||||
}
|
||||
|
||||
/**
|
||||
Emit the gridModificationRequested() signal with \a command after having set
|
||||
its view component.
|
||||
@see TitleBlockTemplateCommand::setView()
|
||||
@param command A command object modifying the rendered title block template.
|
||||
*/
|
||||
void TitleBlockTemplateView::requestGridModification(TitleBlockTemplateCommand *command) {
|
||||
if (!command) return;
|
||||
command -> setView(this);
|
||||
emit(gridModificationRequested(command));
|
||||
}
|
||||
|
||||
/**
|
||||
@return the last index selected when triggering the context menu.
|
||||
@see updateLastContextMenuCell
|
||||
*/
|
||||
int TitleBlockTemplateView::lastContextMenuCellIndex() const {
|
||||
if (last_context_menu_cell_) {
|
||||
return(last_context_menu_cell_ -> index);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
@param item an item supposed to be contained in the grid layout.
|
||||
@return the flat index if this item, or -1 if it could not be found.
|
||||
*/
|
||||
int TitleBlockTemplateView::indexOf(QGraphicsLayoutItem *item) {
|
||||
for (int i = 0 ; i < tbgrid_ -> count() ; ++i) {
|
||||
if (item == tbgrid_ -> itemAt(i)) return(i);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
Removes an item from the grid layout
|
||||
@param item an item supposed to be contained in the grid layout.
|
||||
*/
|
||||
void TitleBlockTemplateView::removeItem(QGraphicsLayoutItem *item) {
|
||||
int index = indexOf(item);
|
||||
if (index != -1) {
|
||||
tbgrid_ -> removeAt(index);
|
||||
// trick: we also have to remove the item from the scene
|
||||
if (QGraphicsScene *current_scene = scene()) {
|
||||
if (QGraphicsItem *qgi = item -> graphicsItem()) {
|
||||
current_scene -> removeItem(qgi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param a list of QGraphicsItem
|
||||
@return the corresponding TitleBlockTemplateCellsSet
|
||||
*/
|
||||
TitleBlockTemplateCellsSet TitleBlockTemplateView::makeCellsSetFromGraphicsItems(const QList<QGraphicsItem *> &items) const {
|
||||
TitleBlockTemplateCellsSet set(this);
|
||||
foreach (QGraphicsItem *item, items) {
|
||||
if (TitleBlockTemplateVisualCell *cell_view = dynamic_cast<TitleBlockTemplateVisualCell *>(item)) {
|
||||
if (cell_view -> cell() && cell_view -> cell() -> num_row != -1) {
|
||||
set << cell_view;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(set);
|
||||
}
|
||||
|
||||
/**
|
||||
Stores \a last_context_menu_cell as being the last helper cell the context
|
||||
menu was triggered on.
|
||||
*/
|
||||
void TitleBlockTemplateView::updateLastContextMenuCell(HelperCell *last_context_menu_cell) {
|
||||
last_context_menu_cell_ = last_context_menu_cell;
|
||||
}
|
||||
|
||||
/**
|
||||
Adjusts the bounding rect of the scene.
|
||||
*/
|
||||
void TitleBlockTemplateView::adjustSceneRect() {
|
||||
QRectF old_scene_rect = sceneRect();
|
||||
|
||||
// rectangle including everything on the scene
|
||||
QRectF bounding_rect = scene() -> itemsBoundingRect();
|
||||
setSceneRect(bounding_rect);
|
||||
|
||||
// met a jour la scene
|
||||
scene() -> update(old_scene_rect.united(bounding_rect));
|
||||
}
|
||||
|
122
sources/titleblock/templateview.h
Normal file
122
sources/titleblock/templateview.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_TEMPLATE_VIEW_H
|
||||
#define TITLEBLOCK_SLASH_TEMPLATE_VIEW_H
|
||||
#include <QGraphicsView>
|
||||
#include "titleblocktemplate.h"
|
||||
class HelperCell;
|
||||
class SplittedHelperCell;
|
||||
class TitleBlockTemplateCommand;
|
||||
class TitleBlockTemplateCellsSet;
|
||||
|
||||
/**
|
||||
This QGraphicsView subclass is used in the title block template editor to
|
||||
offer a graphical preview of the template being edited, but also to handle
|
||||
cell selection and various actions.
|
||||
*/
|
||||
class TitleBlockTemplateView : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
|
||||
// constructors, destructor
|
||||
public:
|
||||
TitleBlockTemplateView(QWidget * = 0);
|
||||
TitleBlockTemplateView(QGraphicsScene *, QWidget * = 0);
|
||||
virtual ~TitleBlockTemplateView();
|
||||
private:
|
||||
TitleBlockTemplateView(const TitleBlockTemplateView &);
|
||||
|
||||
// methods and slots
|
||||
public:
|
||||
TitleBlockTemplate *titleBlockTemplate() const;
|
||||
virtual QList<TitleBlockCell *> selectedCells() const;
|
||||
virtual TitleBlockTemplateCellsSet selectedCellsSet() const;
|
||||
virtual TitleBlockTemplateCellsSet cells(const QRectF &) const;
|
||||
|
||||
public slots:
|
||||
void setTitleBlockTemplate(TitleBlockTemplate *);
|
||||
void selectionChanged();
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void addColumnBefore();
|
||||
void addRowBefore();
|
||||
void addColumnAfter();
|
||||
void addRowAfter();
|
||||
void editColumn(HelperCell * = 0);
|
||||
void editRow(HelperCell * = 0);
|
||||
void deleteColumn();
|
||||
void deleteRow();
|
||||
void mergeSelectedCells();
|
||||
void splitSelectedCell();
|
||||
void refresh();
|
||||
void changePreviewWidth();
|
||||
void updateLayout();
|
||||
void rowsDimensionsChanged();
|
||||
void columnsDimensionsChanged();
|
||||
|
||||
protected slots:
|
||||
virtual void applyColumnsWidths(bool = true);
|
||||
virtual void applyRowsHeights(bool = true);
|
||||
virtual void updateRowsHelperCells();
|
||||
virtual void updateColumnsHelperCells();
|
||||
|
||||
protected:
|
||||
virtual void drawBackground(QPainter *, const QRectF &);
|
||||
virtual void addCells();
|
||||
virtual void loadTemplate(TitleBlockTemplate *);
|
||||
virtual void init();
|
||||
virtual void wheelEvent(QWheelEvent *);
|
||||
virtual qreal zoomFactor() const;
|
||||
virtual void fillWithEmptyCells();
|
||||
|
||||
signals:
|
||||
void selectedCellsChanged(QList<TitleBlockCell *>);
|
||||
void gridModificationRequested(TitleBlockTemplateCommand *);
|
||||
|
||||
private:
|
||||
QList<QAction *> rowsActions() const;
|
||||
QList<QAction *> columnsActions() const;
|
||||
void setPreviewWidth(int);
|
||||
void updateTotalWidthLabel();
|
||||
void requestGridModification(TitleBlockTemplateCommand *);
|
||||
int lastContextMenuCellIndex() const;
|
||||
int indexOf(QGraphicsLayoutItem *);
|
||||
void removeItem(QGraphicsLayoutItem *);
|
||||
TitleBlockTemplateCellsSet makeCellsSetFromGraphicsItems(const QList<QGraphicsItem *> &) const;
|
||||
|
||||
private slots:
|
||||
void updateLastContextMenuCell(HelperCell *);
|
||||
void adjustSceneRect();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
TitleBlockTemplate *tbtemplate_;
|
||||
QGraphicsGridLayout *tbgrid_;
|
||||
QGraphicsWidget *form_;
|
||||
int preview_width_;
|
||||
SplittedHelperCell *total_width_helper_cell_;
|
||||
HelperCell *extra_cells_width_helper_cell_;
|
||||
QAction *add_column_before_, *add_row_before_;
|
||||
QAction *add_column_after_, *add_row_after_;
|
||||
QAction *edit_column_dim_, *edit_row_dim_;
|
||||
QAction *delete_column_, *delete_row_;
|
||||
QAction *change_preview_width_;
|
||||
HelperCell *last_context_menu_cell_;
|
||||
int apply_columns_widths_count_;
|
||||
int apply_rows_heights_count_;
|
||||
};
|
||||
#endif
|
136
sources/titleblock/templatevisualcell.cpp
Normal file
136
sources/titleblock/templatevisualcell.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 "templatevisualcell.h"
|
||||
#include "titleblocktemplate.h"
|
||||
#include "diagramcontext.h"
|
||||
|
||||
/**
|
||||
Constructor
|
||||
@param parent Parent QGraphicsItem
|
||||
*/
|
||||
TitleBlockTemplateVisualCell::TitleBlockTemplateVisualCell(QGraphicsItem *parent) :
|
||||
QGraphicsLayoutItem(),
|
||||
QGraphicsItem(parent),
|
||||
template_(0),
|
||||
cell_(0)
|
||||
{
|
||||
setGraphicsItem(this);
|
||||
setFlag(QGraphicsItem::ItemIsSelectable, true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
TitleBlockTemplateVisualCell::~TitleBlockTemplateVisualCell() {
|
||||
}
|
||||
|
||||
/**
|
||||
Ensure geometry changes are handled for both QGraphicsObject and
|
||||
QGraphicsLayoutItem.
|
||||
@param g New geometry
|
||||
*/
|
||||
void TitleBlockTemplateVisualCell::setGeometry(const QRectF &g) {
|
||||
prepareGeometryChange();
|
||||
QGraphicsLayoutItem::setGeometry(g);
|
||||
setPos(g.topLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
@param which Size hint to be modified
|
||||
@param constraint New value for the size hint
|
||||
@return the size hint for \a which using the width or height of \a constraint
|
||||
*/
|
||||
QSizeF TitleBlockTemplateVisualCell::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const {
|
||||
Q_UNUSED(which);
|
||||
return constraint;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the bounding rect of this helper cell
|
||||
*/
|
||||
QRectF TitleBlockTemplateVisualCell::boundingRect() const {
|
||||
return QRectF(QPointF(0,0), geometry().size());
|
||||
}
|
||||
|
||||
/**
|
||||
Handles the helper cell visual rendering
|
||||
@param painter QPainter to be used for the rendering
|
||||
@param option Rendering options
|
||||
@param widget QWidget being painted, if any
|
||||
*/
|
||||
void TitleBlockTemplateVisualCell::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
|
||||
Q_UNUSED(option);
|
||||
Q_UNUSED(widget);
|
||||
|
||||
QRectF drawing_rectangle(QPointF(0, 0), geometry().size() /*- QSizeF(1, 1)*/);
|
||||
|
||||
if (template_ && cell_) {
|
||||
template_ -> renderCell(*painter, *cell_, DiagramContext(), drawing_rectangle.toRect());
|
||||
}
|
||||
if (isSelected()) {
|
||||
QBrush selection_brush = QApplication::palette().highlight();
|
||||
QColor selection_color = selection_brush.color();
|
||||
selection_color.setAlpha(127);
|
||||
selection_brush.setColor(selection_color);
|
||||
painter -> setPen(Qt::NoPen);
|
||||
painter -> setBrush(selection_brush);
|
||||
painter -> drawRect(drawing_rectangle/*.adjusted(1, 1, -1, -1)*/);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Set the previewed title block cell.
|
||||
@param tbt Parent title block template of the previewed cell
|
||||
@param cell Previewed cell
|
||||
*/
|
||||
void TitleBlockTemplateVisualCell::setTemplateCell(TitleBlockTemplate *tbt, TitleBlockCell *cell) {
|
||||
template_ = tbt;
|
||||
cell_ = cell;
|
||||
}
|
||||
|
||||
/**
|
||||
@return the parent title block template of the previewed cell
|
||||
*/
|
||||
TitleBlockTemplate *TitleBlockTemplateVisualCell::titleBlockTemplate() const {
|
||||
return(template_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the previewed title block cell
|
||||
*/
|
||||
TitleBlockCell *TitleBlockTemplateVisualCell::cell() const {
|
||||
return(cell_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the title block cell previewed by this object, plus the cells it
|
||||
spans over, if any
|
||||
*/
|
||||
QSet<TitleBlockCell *> TitleBlockTemplateVisualCell::cells() const {
|
||||
QSet<TitleBlockCell *> set;
|
||||
if (cell_) {
|
||||
if (template_) {
|
||||
set = template_ -> spannedCells(cell_);
|
||||
}
|
||||
|
||||
// the TitleBlockCell rendered by this object
|
||||
set << cell_;
|
||||
}
|
||||
return(set);
|
||||
}
|
55
sources/titleblock/templatevisualcell.h
Normal file
55
sources/titleblock/templatevisualcell.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2006-2011 Xavier Guerrin
|
||||
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 TITLEBLOCK_SLASH_QET_TEMPLATE_VISUAL_CELL_H
|
||||
#define TITLEBLOCK_SLASH_QET_TEMPLATE_VISUAL_CELL_H
|
||||
#include <QtGui>
|
||||
#include "qet.h"
|
||||
class TitleBlockTemplate;
|
||||
#include "titleblockcell.h"
|
||||
|
||||
/**
|
||||
This class implements a preview widget for cells that compose a title
|
||||
block template.
|
||||
*/
|
||||
class TitleBlockTemplateVisualCell : public QGraphicsLayoutItem, public QGraphicsItem {
|
||||
// constructor, destructor
|
||||
public:
|
||||
TitleBlockTemplateVisualCell(QGraphicsItem * parent = 0);
|
||||
virtual ~TitleBlockTemplateVisualCell();
|
||||
private:
|
||||
TitleBlockTemplateVisualCell(const TitleBlockTemplateVisualCell &);
|
||||
|
||||
// methods
|
||||
public:
|
||||
virtual void setGeometry(const QRectF &);
|
||||
virtual QSizeF sizeHint(Qt::SizeHint, const QSizeF & = QSizeF()) const;
|
||||
virtual QRectF boundingRect() const;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
|
||||
public slots:
|
||||
void setTemplateCell(TitleBlockTemplate *, TitleBlockCell *);
|
||||
TitleBlockTemplate *titleBlockTemplate() const;
|
||||
TitleBlockCell *cell() const;
|
||||
QSet<TitleBlockCell *> cells() const;
|
||||
|
||||
// attributes
|
||||
private:
|
||||
TitleBlockTemplate *template_; ///< Title block template of the previewed cell
|
||||
TitleBlockCell *cell_; ///< Previewed cell
|
||||
};
|
||||
#endif
|
144
sources/titleblockcell.cpp
Normal file
144
sources/titleblockcell.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
#include "titleblockcell.h"
|
||||
#include "titleblocktemplate.h"
|
||||
/**
|
||||
Constructor
|
||||
*/
|
||||
TitleBlockCell::TitleBlockCell() {
|
||||
cell_type = TitleBlockCell::EmptyCell;
|
||||
num_row = num_col = -1;
|
||||
row_span = col_span = 0;
|
||||
spanner_cell = 0;
|
||||
display_label = true;
|
||||
alignment = Qt::AlignCenter | Qt::AlignVCenter;
|
||||
font_size = 9;
|
||||
hadjust = false;
|
||||
logo_reference = QString("");
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
TitleBlockCell::~TitleBlockCell() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return A string representing the titleblock cell
|
||||
*/
|
||||
QString TitleBlockCell::toString() const {
|
||||
if (cell_type == TitleBlockCell::EmptyCell) return("TitleBlockCell{null}");
|
||||
QString span_desc = (row_span > 0 || col_span > 0) ? QString("+%1,%2").arg(row_span).arg(col_span) : QET::pointerString(spanner_cell);
|
||||
QString base_desc = QString("TitleBlockCell{ [%1, %2] %3 }").arg(num_row).arg(num_col).arg(span_desc);
|
||||
return(base_desc);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the type of this cell
|
||||
*/
|
||||
TitleBlockCell::TemplateCellType TitleBlockCell::type() const {
|
||||
return(cell_type);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the horizontal alignment of this cell
|
||||
*/
|
||||
int TitleBlockCell::horizontalAlign() const {
|
||||
return(alignment & Qt::AlignHorizontal_Mask);
|
||||
}
|
||||
|
||||
/**
|
||||
@return the vertical alignment of this cell
|
||||
*/
|
||||
int TitleBlockCell::verticalAlign() const {
|
||||
return(alignment & Qt::AlignVertical_Mask);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the new value \a attr_value to the attribute named \a attribute.
|
||||
@param attribute Name of the cell attribute which value is to be changed
|
||||
@param attr_value New value of the changed attribute
|
||||
*/
|
||||
void TitleBlockCell::setAttribute(const QString &attribute, const QVariant &attr_value) {
|
||||
if (attribute == "type") {
|
||||
int new_type = attr_value.toInt();
|
||||
if (new_type <= TitleBlockCell::LogoCell) {
|
||||
cell_type = static_cast<TitleBlockCell::TemplateCellType>(new_type);
|
||||
}
|
||||
} else if (attribute == "name") {
|
||||
value_name = attr_value.toString();
|
||||
} else if (attribute == "logo") {
|
||||
logo_reference = attr_value.toString();
|
||||
} else if (attribute == "label") {
|
||||
label = qvariant_cast<NamesList>(attr_value);
|
||||
} else if (attribute == "displaylabel") {
|
||||
display_label = attr_value.toBool();
|
||||
} else if (attribute == "value") {
|
||||
value = qvariant_cast<NamesList>(attr_value);
|
||||
} else if (attribute == "alignment") {
|
||||
alignment = attr_value.toInt();
|
||||
} else if (attribute == "fontsize") {
|
||||
font_size = attr_value.toInt();
|
||||
} else if (attribute == "horizontal_adjust") {
|
||||
hadjust = attr_value.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param attribute Name of the cell attribute which value is wanted
|
||||
@return the value of the required attribute
|
||||
*/
|
||||
QVariant TitleBlockCell::attribute(const QString &attribute) {
|
||||
if (attribute == "type") {
|
||||
return(type());
|
||||
} else if (attribute == "name") {
|
||||
return(value_name);
|
||||
} else if (attribute == "logo") {
|
||||
return(logo_reference);
|
||||
} else if (attribute == "label") {
|
||||
return(qVariantFromValue(label));
|
||||
} else if (attribute == "displaylabel") {
|
||||
return(display_label);
|
||||
} else if (attribute == "value") {
|
||||
return(qVariantFromValue(value));
|
||||
} else if (attribute == "alignment") {
|
||||
return(alignment);
|
||||
} else if (attribute == "fontsize") {
|
||||
return(TitleBlockTemplate::fontForCell(*this).pointSizeF());
|
||||
} else if (attribute == "horizontal_adjust") {
|
||||
return(hadjust);
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
@param attribute Name of the cell attribute which we want the human, translated name
|
||||
@return the human, translated name for this attribute.
|
||||
*/
|
||||
QString TitleBlockCell::attributeName(const QString &attribute) {
|
||||
if (attribute == "type") {
|
||||
return(QObject::tr("type", "cell property human name"));
|
||||
} else if (attribute == "name") {
|
||||
return(QObject::tr("nom", "cell property human name"));
|
||||
} else if (attribute == "logo") {
|
||||
return(QObject::tr("logo", "cell property human name"));
|
||||
} else if (attribute == "label") {
|
||||
return(QObject::tr("label", "cell property human name"));
|
||||
} else if (attribute == "displaylabel") {
|
||||
return(QObject::tr("affichage du label", "cell property human name"));
|
||||
} else if (attribute == "value") {
|
||||
return(QObject::tr("valeur affichée", "cell property human name"));
|
||||
} else if (attribute == "alignment") {
|
||||
return(QObject::tr("alignement du texte", "cell property human name"));
|
||||
} else if (attribute == "fontsize") {
|
||||
return(QObject::tr("taille du texte", "cell property human name"));
|
||||
} else if (attribute == "horizontal_adjust") {
|
||||
return(QObject::tr("ajustement horizontal", "cell property human name"));
|
||||
}
|
||||
return(QString());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if this cell spans over other cells, false otherwise.
|
||||
*/
|
||||
bool TitleBlockCell::spans() const {
|
||||
return(row_span || col_span);
|
||||
}
|
@ -17,27 +17,51 @@
|
||||
*/
|
||||
#ifndef TITLEBLOCK_CELL_H
|
||||
#define TITLEBLOCK_CELL_H
|
||||
#include "nameslist.h"
|
||||
|
||||
/**
|
||||
This class is a container for the various parameters of an titleblock cell
|
||||
This class is a container for the various parameters of a titleblock cell
|
||||
@see TitleBlockColumnLength
|
||||
*/
|
||||
class TitleBlockCell {
|
||||
public:
|
||||
enum TemplateCellType {
|
||||
EmptyCell,
|
||||
TextCell,
|
||||
LogoCell
|
||||
};
|
||||
|
||||
// Constructor, destructor
|
||||
public:
|
||||
TitleBlockCell();
|
||||
virtual ~TitleBlockCell();
|
||||
|
||||
// methods
|
||||
public:
|
||||
QString toString() const;
|
||||
bool is_null;
|
||||
int num_row;
|
||||
int num_col;
|
||||
int row_span;
|
||||
int col_span;
|
||||
TitleBlockCell *spanner_cell;
|
||||
QString value_name;
|
||||
QString value;
|
||||
QString label;
|
||||
bool display_label;
|
||||
int alignment;
|
||||
int font_size;
|
||||
bool hadjust;
|
||||
QString logo_reference;
|
||||
TemplateCellType type() const;
|
||||
int horizontalAlign() const;
|
||||
int verticalAlign() const;
|
||||
void setAttribute(const QString &, const QVariant &);
|
||||
QVariant attribute(const QString &);
|
||||
static QString attributeName(const QString &);
|
||||
bool spans() const;
|
||||
|
||||
// attributes
|
||||
public:
|
||||
TemplateCellType cell_type; ///< Cell type: empty, text, logo?
|
||||
int num_row; ///< y coordinate of the cell within its parent title block template grid
|
||||
int num_col; ///< x coordinate of the cell within its parent title block template grid
|
||||
int row_span; ///< number of extra rows spanned by this cell
|
||||
int col_span; ///< number of extra columns spanned by this cell
|
||||
TitleBlockCell *spanner_cell; ///< Cell spanning this cell, if any
|
||||
QString value_name; ///< name of the cell; not displayed when the title block template is rendered
|
||||
NamesList value; ///< Text displayed by the cell
|
||||
NamesList label; ///< Label displayed by the cell
|
||||
bool display_label; ///< Whether to display the label or not
|
||||
int alignment; ///< Where the label+text should be displayed within the visual cell
|
||||
int font_size; ///< Font size the text should be rendered with
|
||||
bool hadjust; ///< Whether to reduce the font size if the text does not fit in the cell
|
||||
QString logo_reference; ///< Logo displayed by this cell, it it is a logo cell
|
||||
};
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,47 +21,71 @@
|
||||
#include <QtSvg>
|
||||
#include "diagramcontext.h"
|
||||
#include "titleblockcell.h"
|
||||
#include "dimension.h"
|
||||
#include "qet.h"
|
||||
|
||||
/**
|
||||
This struct is a simple container associating a length with its type.
|
||||
@see TitleBlockColumnLength
|
||||
*/
|
||||
struct TitleBlockColDimension {
|
||||
TitleBlockColDimension(int v, QET::TitleBlockColumnLength t = QET::Absolute) {
|
||||
value = v;
|
||||
type = t;
|
||||
}
|
||||
QET::TitleBlockColumnLength type;
|
||||
int value;
|
||||
};
|
||||
|
||||
/**
|
||||
This class represents an titleblock templ)ate for an electric diagram.
|
||||
This class represents an title block template for an electric diagram.
|
||||
It can read from an XML document the layout of the table that graphically
|
||||
represents the titleblock, and can produce a graphical rendering of it from a
|
||||
represents the title block, and can produce a graphical rendering of it from a
|
||||
diagram context (object embedding the informations of the diagram we want to
|
||||
represent the titleblock.
|
||||
represent the title block.
|
||||
*/
|
||||
class TitleBlockTemplate : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
// constructors, destructor
|
||||
public:
|
||||
TitleBlockTemplate(QObject * = 0);
|
||||
virtual ~TitleBlockTemplate();
|
||||
private:
|
||||
TitleBlockTemplate(const TitleBlockTemplate &);
|
||||
|
||||
// methodes
|
||||
// methods
|
||||
public:
|
||||
TitleBlockCell *createCell(const TitleBlockCell * = 0);
|
||||
static QFont fontForCell(const TitleBlockCell &);
|
||||
bool loadFromXmlFile(const QString &);
|
||||
bool loadFromXmlElement(const QDomElement &);
|
||||
bool saveToXmlElement(QDomElement &) const;
|
||||
TitleBlockTemplate *clone() const;
|
||||
QString name() const;
|
||||
int rowDimension(int);
|
||||
void setRowDimension(int, const TitleBlockDimension &);
|
||||
TitleBlockDimension columnDimension(int);
|
||||
void setColumnDimension(int, const TitleBlockDimension &);
|
||||
int columnsCount() const;
|
||||
int rowsCount() const;
|
||||
QList<int> columnsWidth(int) const;
|
||||
QList<int> rowsHeights() const;
|
||||
int height() const;
|
||||
|
||||
bool moveRow(int, int);
|
||||
void addRow(int = -1);
|
||||
bool insertRow(int, const QList<TitleBlockCell *> &, int = -1);
|
||||
QList<TitleBlockCell *> takeRow(int);
|
||||
QList<TitleBlockCell *> createRow();
|
||||
|
||||
bool moveColumn(int, int);
|
||||
void addColumn(int = -1);
|
||||
bool insertColumn(const TitleBlockDimension &, const QList<TitleBlockCell *> &, int = -1);
|
||||
QList<TitleBlockCell *> takeColumn(int);
|
||||
QList<TitleBlockCell *> createColumn();
|
||||
|
||||
TitleBlockCell *cell(int, int) const;
|
||||
QSet<TitleBlockCell *> spannedCells(const TitleBlockCell *) const;
|
||||
bool addLogo(const QString &, QByteArray *, const QString & = "svg", const QString & = "xml");
|
||||
bool addLogoFromFile(const QString &, const QString & = QString());
|
||||
bool removeLogo(const QString &);
|
||||
bool renameLogo(const QString &, const QString &);
|
||||
void setLogoStorage(const QString &, const QString &);
|
||||
QList<QString> logos() const;
|
||||
QString logoType(const QString &) const;
|
||||
QSvgRenderer *vectorLogo(const QString &) const;
|
||||
QPixmap bitmapLogo(const QString &) const;
|
||||
|
||||
void render(QPainter &, const DiagramContext &, int) const;
|
||||
void renderCell(QPainter &, const TitleBlockCell &, const DiagramContext &, const QRect &) const;
|
||||
QString toString() const;
|
||||
|
||||
protected:
|
||||
@ -69,6 +93,13 @@ class TitleBlockTemplate : public QObject {
|
||||
bool loadLogo(const QDomElement &);
|
||||
bool loadGrid(const QDomElement &);
|
||||
bool loadCells(const QDomElement &);
|
||||
void loadCell(const QDomElement &);
|
||||
void saveLogos(QDomElement &) const;
|
||||
void saveLogo(const QString &, QDomElement &) const;
|
||||
void saveGrid(QDomElement &) const;
|
||||
void saveCells(QDomElement &) const;
|
||||
void saveCell(TitleBlockCell *, QDomElement &) const;
|
||||
QList<TitleBlockCell *> createCellsList(int);
|
||||
|
||||
private:
|
||||
void parseRows(const QString &);
|
||||
@ -79,15 +110,26 @@ class TitleBlockTemplate : public QObject {
|
||||
int lengthRange(int, int, const QList<int> &) const;
|
||||
QString finalTextForCell(const TitleBlockCell &, const DiagramContext &) const;
|
||||
void renderTextCell(QPainter &, const QString &, const TitleBlockCell &, const QRectF &) const;
|
||||
void applyCellSpans();
|
||||
void forgetSpanning();
|
||||
bool checkCellSpan(TitleBlockCell *);
|
||||
void applyCellSpan(TitleBlockCell *);
|
||||
void applyRowColNums();
|
||||
void rowColsChanged();
|
||||
|
||||
// attributs
|
||||
// attributes
|
||||
private:
|
||||
QDomDocument xml_description_;
|
||||
QString name_;
|
||||
QHash<QString, QSvgRenderer *> vector_logos_;
|
||||
QHash<QString, QPixmap *> bitmap_logos_;
|
||||
QList<int> rows_heights_;
|
||||
QList<TitleBlockColDimension> columns_width_;
|
||||
QVector< QVector<TitleBlockCell> > cells_;
|
||||
QString name_; ///< name identifying the Title Block Template within its parent project
|
||||
|
||||
QHash<QString, QByteArray > data_logos_; ///< Logos raw data
|
||||
QHash<QString, QString> storage_logos_; ///< Logos applied storage type (e.g. "xml" or "base64")
|
||||
QHash<QString, QString> type_logos_; ///< Logos types (e.g. "png", "jpeg", "svg")
|
||||
QHash<QString, QSvgRenderer *> vector_logos_; ///< Rendered objects for vector logos
|
||||
QHash<QString, QPixmap> bitmap_logos_; ///< Pixmaps for bitmap logos
|
||||
|
||||
QList<int> rows_heights_; ///< rows heights -- simple integers
|
||||
QList<TitleBlockDimension> columns_width_; ///< columns widths -- @see TitleBlockColDimension
|
||||
QList<TitleBlockCell *> registered_cells_; ///< Cells objects created rattached to this template, but not mandatorily used
|
||||
QList< QList<TitleBlockCell *> > cells_; ///< Cells grid
|
||||
};
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user