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:
xavier 2011-12-25 17:45:39 +00:00
parent 271242d207
commit 5b2a2249af
30 changed files with 5523 additions and 242 deletions

View File

@ -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

View File

@ -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();
}
/**

View 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);
}

View 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

View 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();
}

View 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

View 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());
}
}

View 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

View 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));
}

View 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

View 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();
}

View 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

View 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);
}

View 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

View 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 &copy) :
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);
}

View 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

View 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));
}

View 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

View 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();
}

View 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

View 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();
}
}

View 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

View 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));
}

View 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

View 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);
}

View 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
View 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);
}

View File

@ -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

View File

@ -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