[qet] [1405] Began implementing a WYSIWYG title block template editor. |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/qet Archives
]
Revision: 1405
Author: xavier
Date: 2011-12-25 18:45:39 +0100 (Sun, 25 Dec 2011)
Log Message:
-----------
Began implementing a WYSIWYG title block template editor.
Modified Paths:
--------------
branches/0.3/qelectrotech.pro
branches/0.3/sources/qetapp.cpp
branches/0.3/sources/titleblockcell.h
branches/0.3/sources/titleblocktemplate.cpp
branches/0.3/sources/titleblocktemplate.h
Added Paths:
-----------
branches/0.3/sources/titleblock/
branches/0.3/sources/titleblock/dimension.cpp
branches/0.3/sources/titleblock/dimension.h
branches/0.3/sources/titleblock/dimensionwidget.cpp
branches/0.3/sources/titleblock/dimensionwidget.h
branches/0.3/sources/titleblock/gridlayoutanimation.cpp
branches/0.3/sources/titleblock/gridlayoutanimation.h
branches/0.3/sources/titleblock/helpercell.cpp
branches/0.3/sources/titleblock/helpercell.h
branches/0.3/sources/titleblock/qettemplateeditor.cpp
branches/0.3/sources/titleblock/qettemplateeditor.h
branches/0.3/sources/titleblock/splittedhelpercell.cpp
branches/0.3/sources/titleblock/splittedhelpercell.h
branches/0.3/sources/titleblock/templatecellsset.cpp
branches/0.3/sources/titleblock/templatecellsset.h
branches/0.3/sources/titleblock/templatecellwidget.cpp
branches/0.3/sources/titleblock/templatecellwidget.h
branches/0.3/sources/titleblock/templatecommands.cpp
branches/0.3/sources/titleblock/templatecommands.h
branches/0.3/sources/titleblock/templatelogomanager.cpp
branches/0.3/sources/titleblock/templatelogomanager.h
branches/0.3/sources/titleblock/templateview.cpp
branches/0.3/sources/titleblock/templateview.h
branches/0.3/sources/titleblock/templatevisualcell.cpp
branches/0.3/sources/titleblock/templatevisualcell.h
branches/0.3/sources/titleblockcell.cpp
Modified: branches/0.3/qelectrotech.pro
===================================================================
--- branches/0.3/qelectrotech.pro 2011-12-24 18:37:00 UTC (rev 1404)
+++ branches/0.3/qelectrotech.pro 2011-12-25 17:45:39 UTC (rev 1405)
@@ -54,11 +54,11 @@
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
Modified: branches/0.3/sources/qetapp.cpp
===================================================================
--- branches/0.3/sources/qetapp.cpp 2011-12-24 18:37:00 UTC (rev 1404)
+++ branches/0.3/sources/qetapp.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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 @@
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();
}
/**
Added: branches/0.3/sources/titleblock/dimension.cpp
===================================================================
--- branches/0.3/sources/titleblock/dimension.cpp (rev 0)
+++ branches/0.3/sources/titleblock/dimension.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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);
+}
Added: branches/0.3/sources/titleblock/dimension.h
===================================================================
--- branches/0.3/sources/titleblock/dimension.h (rev 0)
+++ branches/0.3/sources/titleblock/dimension.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/dimensionwidget.cpp
===================================================================
--- branches/0.3/sources/titleblock/dimensionwidget.cpp (rev 0)
+++ branches/0.3/sources/titleblock/dimensionwidget.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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();
+}
Added: branches/0.3/sources/titleblock/dimensionwidget.h
===================================================================
--- branches/0.3/sources/titleblock/dimensionwidget.h (rev 0)
+++ branches/0.3/sources/titleblock/dimensionwidget.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/gridlayoutanimation.cpp
===================================================================
--- branches/0.3/sources/titleblock/gridlayoutanimation.cpp (rev 0)
+++ branches/0.3/sources/titleblock/gridlayoutanimation.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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());
+ }
+}
Added: branches/0.3/sources/titleblock/gridlayoutanimation.h
===================================================================
--- branches/0.3/sources/titleblock/gridlayoutanimation.h (rev 0)
+++ branches/0.3/sources/titleblock/gridlayoutanimation.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/helpercell.cpp
===================================================================
--- branches/0.3/sources/titleblock/helpercell.cpp (rev 0)
+++ branches/0.3/sources/titleblock/helpercell.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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));
+}
Added: branches/0.3/sources/titleblock/helpercell.h
===================================================================
--- branches/0.3/sources/titleblock/helpercell.h (rev 0)
+++ branches/0.3/sources/titleblock/helpercell.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/qettemplateeditor.cpp
===================================================================
--- branches/0.3/sources/titleblock/qettemplateeditor.cpp (rev 0)
+++ branches/0.3/sources/titleblock/qettemplateeditor.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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();
+}
Added: branches/0.3/sources/titleblock/qettemplateeditor.h
===================================================================
--- branches/0.3/sources/titleblock/qettemplateeditor.h (rev 0)
+++ branches/0.3/sources/titleblock/qettemplateeditor.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/splittedhelpercell.cpp
===================================================================
--- branches/0.3/sources/titleblock/splittedhelpercell.cpp (rev 0)
+++ branches/0.3/sources/titleblock/splittedhelpercell.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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);
+}
Added: branches/0.3/sources/titleblock/splittedhelpercell.h
===================================================================
--- branches/0.3/sources/titleblock/splittedhelpercell.h (rev 0)
+++ branches/0.3/sources/titleblock/splittedhelpercell.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/templatecellsset.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatecellsset.cpp (rev 0)
+++ branches/0.3/sources/titleblock/templatecellsset.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -0,0 +1,212 @@
+/*
+ Copyright 2006-2011 Xavier Guerrin
+ This file is part of QElectroTech.
+
+ QElectroTech is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ QElectroTech is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "templatecellsset.h"
+#include "templatevisualcell.h"
+#include "templateview.h"
+#include "titleblockcell.h"
+
+/**
+ Constructor
+ @param parent_view View this set of cells are rattached to
+*/
+TitleBlockTemplateCellsSet::TitleBlockTemplateCellsSet(const TitleBlockTemplateView *parent_view) :
+ parent_view_(parent_view)
+{
+}
+
+/**
+ Copy constructor
+ @param copy TitleBlockTemplateCellsSet object to copy
+*/
+TitleBlockTemplateCellsSet::TitleBlockTemplateCellsSet(const TitleBlockTemplateCellsSet ©) :
+ QList<TitleBlockTemplateVisualCell *>(copy),
+ parent_view_(copy.parent_view_)
+{
+}
+
+/**
+ Destructor
+*/
+TitleBlockTemplateCellsSet::~TitleBlockTemplateCellsSet() {
+}
+
+/**
+ @return a QPainterPath composed of the rectangles from cells within this set
+*/
+QPainterPath TitleBlockTemplateCellsSet::painterPath() const {
+ QPainterPath cells_path;
+ foreach (TitleBlockTemplateVisualCell *cell, *this) {
+ cells_path.addRect(cell -> geometry());
+ }
+ return(cells_path);
+}
+
+/**
+ @return true if the cells within this set are composing a rectangle shape,
+ false otherwise.
+*/
+bool TitleBlockTemplateCellsSet::isRectangle() const {
+ if (!count()) return(false);
+ if (count() == 1) return(true);
+
+ QPolygonF points = painterPath().simplified().toFillPolygon();
+ if (points.isClosed()) points.pop_back();
+
+ return(points.count() == 4 || points.count() == 5);
+}
+
+/**
+ @return true if all cells within this set are selected
+*/
+bool TitleBlockTemplateCellsSet::allCellsAreSelected() const {
+ foreach (TitleBlockTemplateVisualCell *cell, *this) {
+ if (!cell -> isSelected()) {
+ return(false);
+ }
+ }
+ return(true);
+}
+
+/**
+ @return true if this set includes at least one cell which is spanned by a
+ cell not present in this set, false otherwise.
+*/
+bool TitleBlockTemplateCellsSet::hasExternalSpan() const {
+ // fetches all cells concerned by this set
+ QSet<TitleBlockCell *> all_cells = cells(true);
+
+ // look for cells spanned by cells that do not belong to this set
+ foreach (TitleBlockCell *cell, all_cells) {
+ if (cell -> spanner_cell && !all_cells.contains(cell -> spanner_cell)) {
+ return(true);
+ }
+ }
+ return(false);
+}
+
+/**
+ @return the top left cell within this set, or 0 if this set is empty
+*/
+TitleBlockTemplateVisualCell *TitleBlockTemplateCellsSet::topLeftCell() const {
+ if (empty()) return(0);
+ if (count() == 1) return(first());
+
+ // look for cells at the top
+ QMultiMap<int, TitleBlockTemplateVisualCell *> top_cells;
+ foreach (TitleBlockTemplateVisualCell *cell_view, *this) {
+ if (TitleBlockCell *cell = cell_view -> cell()) {
+ top_cells.insertMulti(cell -> num_row, cell_view);
+ }
+ }
+ QList<TitleBlockTemplateVisualCell *> candidates = top_cells.values(top_cells.keys().first());
+ if (candidates.count() == 1) return(candidates.first());
+
+ // look for the cell at the left
+ int lowest_num_col = 100000;
+ TitleBlockTemplateVisualCell *candidate = 0;
+ foreach (TitleBlockTemplateVisualCell *cell_view, candidates) {
+ if (TitleBlockCell *cell = cell_view -> cell()) {
+ if (cell -> num_col < lowest_num_col) {
+ lowest_num_col = cell -> num_col;
+ candidate = cell_view;
+ }
+ }
+ }
+ return(candidate);
+}
+
+/**
+ @return the bottom right cell within this set, or 0 if this set is empty
+*/
+TitleBlockTemplateVisualCell *TitleBlockTemplateCellsSet::bottomRightCell() const {
+ if (empty()) return(0);
+ if (count() == 1) return(first());
+
+ // look for cells at the bottom
+ QMultiMap<qreal, TitleBlockTemplateVisualCell *> bottom_cells;
+ foreach (TitleBlockTemplateVisualCell *cell_view, *this) {
+ bottom_cells.insertMulti(cell_view -> geometry().bottom(), cell_view);
+ }
+ QList<TitleBlockTemplateVisualCell *> candidates = bottom_cells.values(bottom_cells.keys().last());
+ if (candidates.count() == 1) return(candidates.first());
+
+ // look for the cell at the right
+ qreal highest_right = -100000;
+ TitleBlockTemplateVisualCell *candidate = 0;
+ foreach (TitleBlockTemplateVisualCell *cell_view, candidates) {
+ qreal right = cell_view -> geometry().right();
+ if (right > highest_right) {
+ highest_right = right;
+ candidate = cell_view;
+ }
+ }
+ return(candidate);
+}
+
+/**
+ @return the merge area, i.e. the rectangle delimited by the top left cell
+ and the bottom right cell within this cells set.
+*/
+QRectF TitleBlockTemplateCellsSet::mergeAreaRect() const {
+ QRectF merge_area;
+ if (!parent_view_) return(merge_area);
+
+ TitleBlockTemplateVisualCell *top_left_cell = topLeftCell();
+ if (!top_left_cell) return(merge_area);
+ TitleBlockTemplateVisualCell *bottom_right_cell = bottomRightCell();
+ if (!bottom_right_cell) return(merge_area);
+
+ merge_area.setTopLeft(top_left_cell -> geometry().topLeft());
+ merge_area.setBottomRight(bottom_right_cell -> geometry().bottomRight());
+ return(merge_area);
+}
+
+/**
+ @param rect (Optional) The merge area to be considered; if a null QRectF is
+ provided, this method will use mergeAreaRect().
+ @return the cells contained in the merge area of this cells set
+*/
+TitleBlockTemplateCellsSet TitleBlockTemplateCellsSet::mergeArea(const QRectF &rect) const {
+ TitleBlockTemplateCellsSet merge_area(parent_view_);
+ if (!parent_view_) return(merge_area);
+
+ QRectF merge_area_rect = rect.isNull() ? mergeAreaRect() : rect;
+
+ merge_area = parent_view_ -> cells(merge_area_rect);
+ return(merge_area);
+}
+
+/**
+ @return the list of cells rendered by the current selection
+ @param include_spanned whether to include spanned cells or not
+*/
+QSet<TitleBlockCell *> TitleBlockTemplateCellsSet::cells(bool include_spanned) const {
+ QSet<TitleBlockCell *> set;
+ foreach (TitleBlockTemplateVisualCell *cell_view, *this) {
+ if (TitleBlockCell *cell = cell_view -> cell()) {
+ if (include_spanned) {
+ foreach (TitleBlockCell *cell, cell_view -> cells()) {
+ set << cell;
+ }
+ } else {
+ set << cell;
+ }
+ }
+ }
+ return(set);
+}
Added: branches/0.3/sources/titleblock/templatecellsset.h
===================================================================
--- branches/0.3/sources/titleblock/templatecellsset.h (rev 0)
+++ branches/0.3/sources/titleblock/templatecellsset.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/templatecellwidget.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatecellwidget.cpp (rev 0)
+++ branches/0.3/sources/titleblock/templatecellwidget.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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("\xC9dition d'une cellule : %1", "label of and undo command when editing a cell")
+ .arg(TitleBlockCell::attributeName(attribute))
+ );
+ emit(cellModified(command));
+}
Added: branches/0.3/sources/titleblock/templatecellwidget.h
===================================================================
--- branches/0.3/sources/titleblock/templatecellwidget.h (rev 0)
+++ branches/0.3/sources/titleblock/templatecellwidget.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/templatecommands.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatecommands.cpp (rev 0)
+++ branches/0.3/sources/titleblock/templatecommands.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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\xE9paration 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();
+}
Added: branches/0.3/sources/titleblock/templatecommands.h
===================================================================
--- branches/0.3/sources/titleblock/templatecommands.h (rev 0)
+++ branches/0.3/sources/titleblock/templatecommands.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/templatelogomanager.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatelogomanager.cpp (rev 0)
+++ branches/0.3/sources/titleblock/templatelogomanager.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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();
+ }
+}
Added: branches/0.3/sources/titleblock/templatelogomanager.h
===================================================================
--- branches/0.3/sources/titleblock/templatelogomanager.h (rev 0)
+++ branches/0.3/sources/titleblock/templatelogomanager.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/templateview.cpp
===================================================================
--- branches/0.3/sources/titleblock/templateview.cpp (rev 0)
+++ branches/0.3/sources/titleblock/templateview.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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));
+}
+
Added: branches/0.3/sources/titleblock/templateview.h
===================================================================
--- branches/0.3/sources/titleblock/templateview.h (rev 0)
+++ branches/0.3/sources/titleblock/templateview.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblock/templatevisualcell.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatevisualcell.cpp (rev 0)
+++ branches/0.3/sources/titleblock/templatevisualcell.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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);
+}
Added: branches/0.3/sources/titleblock/templatevisualcell.h
===================================================================
--- branches/0.3/sources/titleblock/templatevisualcell.h (rev 0)
+++ branches/0.3/sources/titleblock/templatevisualcell.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Added: branches/0.3/sources/titleblockcell.cpp
===================================================================
--- branches/0.3/sources/titleblockcell.cpp (rev 0)
+++ branches/0.3/sources/titleblockcell.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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\xE9e", "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);
+}
Modified: branches/0.3/sources/titleblockcell.h
===================================================================
--- branches/0.3/sources/titleblockcell.h 2011-12-24 18:37:00 UTC (rev 1404)
+++ branches/0.3/sources/titleblockcell.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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
Modified: branches/0.3/sources/titleblocktemplate.cpp
===================================================================
--- branches/0.3/sources/titleblocktemplate.cpp 2011-12-24 18:37:00 UTC (rev 1404)
+++ branches/0.3/sources/titleblocktemplate.cpp 2011-12-25 17:45:39 UTC (rev 1405)
@@ -19,6 +19,8 @@
#include "qet.h"
#include "qetapp.h"
#include "nameslist.h"
+// uncomment the line below to get more debug information
+//#define TITLEBLOCK_TEMPLATE_DEBUG
/**
Constructor
@@ -34,31 +36,65 @@
*/
TitleBlockTemplate::~TitleBlockTemplate() {
loadLogos(QDomElement(), true);
+ qDeleteAll(registered_cells_);
}
/**
+ Create a new cell and associate it with this template, which means that it
+ will be deleted when this template is destroyed.
+ @param existing_cell (optional) An existing cell that will be copied
+ @return A pointer to the newly created cell
+*/
+TitleBlockCell *TitleBlockTemplate::createCell(const TitleBlockCell *existing_cell) {
+ TitleBlockCell *new_cell = existing_cell ? new TitleBlockCell(*existing_cell) : new TitleBlockCell();
+ registered_cells_ << new_cell;
+ return(new_cell);
+}
+
+/**
+ @param count Number of cells expected in the list
+ @return a list containing count newly created (and registered) cells
+ @see createCell()
+*/
+QList<TitleBlockCell *> TitleBlockTemplate::createCellsList(int count) {
+ QList<TitleBlockCell *> new_list;
+ for (int i = 0 ; i < count ; ++ i) new_list << createCell();
+ return(new_list);
+}
+
+/**
+ @param cell An existing cell
+ @return The font that should be used to render this cell according to its properties.
+*/
+QFont TitleBlockTemplate::fontForCell(const TitleBlockCell &cell) {
+ return(QETApp::diagramTextsFont(cell.font_size));
+}
+
+/**
+ Load a titleblock template from an XML file.
@param filepath A file path to read the template from.
@return true if the reading succeeds, false otherwise.
*/
bool TitleBlockTemplate::loadFromXmlFile(const QString &filepath) {
- // opens the file
+ // open the file
QFile template_file(filepath);
if (!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- return(false);
+ return(false);
}
#ifdef TITLEBLOCK_TEMPLATE_DEBUG
qDebug() << Q_FUNC_INFO << filepath << "opened";
#endif
- // parses its content as XML
- bool xml_parsing = xml_description_.setContent(&template_file);
+ // parse its content as XML
+ QDomDocument xml_doc;
+ bool xml_parsing = xml_doc.setContent(&template_file);
if (!xml_parsing) {
return(false);
}
#ifdef TITLEBLOCK_TEMPLATE_DEBUG
qDebug() << Q_FUNC_INFO << filepath << "opened and parsed";
#endif
- return(loadFromXmlElement(xml_description_.documentElement()));
+ return(loadFromXmlElement(xml_doc.documentElement()));
}
/**
@@ -77,11 +113,79 @@
loadLogos(xml_element, true);
loadGrid(xml_element);
+
return(true);
}
/**
- Imports the logos from a given XML titleblock template.
+ Save the title block template as XML.
+ @param xml_element The XMl element this title block template should be saved to.
+ @return true if the export succeeds, false otherwise
+*/
+bool TitleBlockTemplate::saveToXmlElement(QDomElement &xml_element) const {
+ // we are supposed to have at least one row/column and a name
+ if (!columnsCount() || !rowsCount() || name_.isEmpty()) return(false);
+
+ xml_element.setTagName("titleblocktemplate");
+ xml_element.setAttribute("name", name_);
+ saveLogos(xml_element);
+ saveGrid(xml_element);
+ return(true);
+}
+
+/**
+ @return a deep copy of the current title block template (i.e. title block
+ cells are duplicated too and associated with their parent template).
+*/
+TitleBlockTemplate *TitleBlockTemplate::clone() const {
+ TitleBlockTemplate *copy = new TitleBlockTemplate();
+ copy -> name_ = name_;
+
+ // this does not really duplicates pixmaps, only the objects that hold a key to the implicitly shared pixmaps
+ foreach (QString logo_key, bitmap_logos_.keys()) {
+ copy -> bitmap_logos_[logo_key] = QPixmap(bitmap_logos_[logo_key]);
+#ifdef TITLEBLOCK_TEMPLATE_DEBUG
+ qDebug() << Q_FUNC_INFO << "copying " << bitmap_logos_[logo_key] -> cacheKey() << "to" << copy -> bitmap_logos_[logo_key] -> cacheKey();
+#endif
+ }
+
+ // we have to create new QSvgRenderer objects from the data (no copy constructor)
+ foreach (QString logo_key, vector_logos_.keys()) {
+ copy -> vector_logos_[logo_key] = new QSvgRenderer(data_logos_[logo_key]);
+ }
+
+ copy -> data_logos_ = data_logos_;
+ copy -> storage_logos_ = storage_logos_;
+ copy -> type_logos_ = type_logos_;
+ copy -> rows_heights_ = rows_heights_;
+ copy -> columns_width_ = columns_width_;
+
+ // copy cells basically
+ copy -> cells_ = cells_;
+ for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
+ for (int i = 0 ; i < columns_width_.count() ; ++ i) {
+ copy -> cells_[i][j] = copy -> createCell(cells_[i][j]);
+ }
+ }
+
+ // ensure the copy has no spanner_cell attribute pointing to a cell from the original object
+ for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
+ for (int i = 0 ; i < columns_width_.count() ; ++ i) {
+ TitleBlockCell *current_cell = copy -> cells_[i][j];
+ if (TitleBlockCell *original_cell = current_cell -> spanner_cell) {
+ int original_cell_row = original_cell -> num_row;
+ int original_cell_col = original_cell -> num_col;
+ TitleBlockCell *copy_cell = copy -> cells_[original_cell_col][original_cell_row];
+ current_cell -> spanner_cell = copy_cell;
+ }
+ }
+ }
+
+ return(copy);
+}
+
+/**
+ Import the logos from a given XML titleblock template.
@param xml_element An XML element representing an titleblock template.
@param reset true to delete all previously known logos before, false
otherwise.
@@ -91,8 +195,12 @@
if (reset) {
qDeleteAll(vector_logos_.begin(), vector_logos_.end());
vector_logos_.clear();
- qDeleteAll(bitmap_logos_.begin(), bitmap_logos_.end());
+
+ // Note: QPixmap are only a key to access the implicitly shared pixmap
bitmap_logos_.clear();
+
+ data_logos_.clear();
+ storage_logos_.clear();
}
// we look for //logos/logo elements
@@ -110,7 +218,7 @@
}
/**
- Imports the logo from a given XML logo description.
+ Import the logo from a given XML logo description.
@param xml_element An XML element representing a logo within an titleblock
template.
@return true if the reading succeeds, false otherwise.
@@ -128,7 +236,6 @@
// we convert the available data to that format.
QByteArray logo_data;
if (logo_storage == "xml") {
- // only svg uses xml storage
QDomNodeList svg_nodes = xml_element.elementsByTagName("svg");
if (svg_nodes.isEmpty()) {
return(false);
@@ -141,35 +248,16 @@
} else {
return(false);
}
+#ifdef TITLEBLOCK_TEMPLATE_DEBUG
+ qDebug() << Q_FUNC_INFO << logo_name << logo_type << logo_storage;
+#endif
+ addLogo(logo_name, &logo_data, logo_type, logo_storage);
- // we can now create our image object from the byte array
- if (logo_type == "svg") {
- // SVG format is handled by the QSvgRenderer class
- QSvgRenderer *svg = new QSvgRenderer(logo_data);
- vector_logos_.insert(logo_name, svg);
-
- /*QSvgWidget *test_svgwidget = new QSvgWidget();
- test_svgwidget -> load(logo_data);
- test_svgwidget -> show();*/
- } else {
- // bitmap formats are handled by the QPixmap class
- QPixmap *logo_pixmap = new QPixmap();
- logo_pixmap -> loadFromData(logo_data);
- if (!logo_pixmap -> width() || !logo_pixmap -> height()) {
- return(false);
- }
- bitmap_logos_.insert(logo_name, logo_pixmap);
-
- /*QLabel *test_label = new QLabel();
- test_label -> setPixmap(*logo_pixmap);
- test_label -> show();*/
- }
-
return(true);
}
/**
- Imports the grid from a given XML titleblock template.
+ Import the grid from a given XML titleblock template.
@param xml_element An XML element representing an titleblock template.
@return true if the reading succeeds, false otherwise.
*/
@@ -189,12 +277,15 @@
parseRows(grid_element.attribute("rows"));
parseColumns(grid_element.attribute("cols"));
+ initCells();
loadCells(grid_element);
+ applyRowColNums();
+ applyCellSpans();
return(true);
}
/**
- Parses the rows heights
+ Parse the rows heights
@param rows_string A string describing the rows heights of the titleblock
*/
void TitleBlockTemplate::parseRows(const QString &rows_string) {
@@ -216,7 +307,7 @@
}
/**
- Parses the columns widths
+ Parse the columns widths
@param cols_string A string describing the columns widths of the titleblock
*/
void TitleBlockTemplate::parseColumns(const QString &cols_string) {
@@ -230,11 +321,11 @@
foreach (QString cols_description, cols_descriptions) {
if (abs_col_size_format.exactMatch(cols_description)) {
int col_size = abs_col_size_format.capturedTexts().at(1).toInt(&conv_ok);
- if (conv_ok) columns_width_ << TitleBlockColDimension(col_size, QET::Absolute);
+ if (conv_ok) columns_width_ << TitleBlockDimension(col_size, QET::Absolute);
} else if (rel_col_size_format.exactMatch(cols_description)) {
int col_size = rel_col_size_format.capturedTexts().at(2).toInt(&conv_ok);
QET::TitleBlockColumnLength col_type = rel_col_size_format.capturedTexts().at(1) == "t" ? QET::RelativeToTotalLength : QET::RelativeToRemainingLength;
- if (conv_ok) columns_width_ << TitleBlockColDimension(col_size, col_type );
+ if (conv_ok) columns_width_ << TitleBlockDimension(col_size, col_type );
}
}
#ifdef TITLEBLOCK_TEMPLATE_DEBUG
@@ -248,80 +339,222 @@
Analyze an XML element, looking for grid cells. The grid cells are checked
and stored in this object.
@param xml_element XML element to analyze
+ @return systematically true
*/
bool TitleBlockTemplate::loadCells(const QDomElement &xml_element) {
- initCells();
// we are interested by the "logo" and "field" elements
QDomElement grid_element;
for (QDomNode n = xml_element.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
if (!n.isElement()) continue;
QDomElement cell_element = n.toElement();
if (cell_element.tagName() == "field" || cell_element.tagName() == "logo") {
- TitleBlockCell *loaded_cell;
- if (!checkCell(cell_element, &loaded_cell)) continue;
-
- if (cell_element.tagName() == "logo") {
- if (cell_element.hasAttribute("resource") && !cell_element.attribute("resource").isEmpty()) {
- loaded_cell -> logo_reference = cell_element.attribute("resource");
- }
- } else if (cell_element.tagName() == "field") {
- if (cell_element.hasAttribute("name") && !cell_element.attribute("name").isEmpty()) {
- loaded_cell -> value_name = cell_element.attribute("name");
- }
-
- QHash<QString, QString> names_options;
- names_options["TagName"] = "translation";
-
- names_options["ParentTagName"] = "value";
- NamesList value_nameslist;
- value_nameslist.fromXml(cell_element, names_options);
- if (!value_nameslist.name().isEmpty()) {
- loaded_cell -> value = value_nameslist.name();
- }
-
- names_options["ParentTagName"] = "label";
- NamesList label_nameslist;
- label_nameslist.fromXml(cell_element, names_options);
- if (!label_nameslist.name().isEmpty()) {
- loaded_cell -> label = label_nameslist.name();
- }
-
- if (cell_element.hasAttribute("displaylabel") && cell_element.attribute("displaylabel").compare("false", Qt::CaseInsensitive) == 0) {
- loaded_cell -> display_label = false;
- }
- int fontsize;
- if (QET::attributeIsAnInteger(cell_element, "fontsize", &fontsize)) {
- loaded_cell -> font_size = fontsize;
- } else {
- loaded_cell -> font_size = -1;
- }
-
- // horiwontal and vertical alignments
- loaded_cell -> alignment = 0;
-
- QString halignment = cell_element.attribute("align", "left");
- if (halignment == "right") loaded_cell -> alignment |= Qt::AlignRight;
- else if (halignment == "center") loaded_cell -> alignment |= Qt::AlignHCenter;
- else loaded_cell -> alignment |= Qt::AlignLeft;
-
- QString valignment = cell_element.attribute("valign", "center");
- if (valignment == "bottom") loaded_cell -> alignment |= Qt::AlignBottom;
- else if (valignment == "top") loaded_cell -> alignment |= Qt::AlignTop;
- else loaded_cell -> alignment |= Qt::AlignVCenter;
-
- // horizontal text adjustment
- loaded_cell -> hadjust = cell_element.attribute("hadjust", "true") == "true";
+ loadCell(cell_element);
+ }
+ }
+ return(true);
+}
+
+/**
+ Load a cell into this template.
+ @param cell_element XML element describing a cell within a title block template
+*/
+void TitleBlockTemplate::loadCell(const QDomElement &cell_element) {
+ TitleBlockCell *loaded_cell;
+ if (!checkCell(cell_element, &loaded_cell)) return;
+
+ // common properties
+ if (cell_element.hasAttribute("name") && !cell_element.attribute("name").isEmpty()) {
+ loaded_cell -> value_name = cell_element.attribute("name");
+ }
+
+ // specific properties
+ if (cell_element.tagName() == "logo") {
+ if (cell_element.hasAttribute("resource") && !cell_element.attribute("resource").isEmpty()) {
+ loaded_cell -> cell_type = TitleBlockCell::LogoCell;
+ loaded_cell -> logo_reference = cell_element.attribute("resource");
+ }
+ } else if (cell_element.tagName() == "field") {
+ loaded_cell -> cell_type = TitleBlockCell::TextCell;
+
+ QHash<QString, QString> names_options;
+ names_options["TagName"] = "translation";
+
+ names_options["ParentTagName"] = "value";
+ NamesList value_nameslist;
+ value_nameslist.fromXml(cell_element, names_options);
+ if (!value_nameslist.name().isEmpty()) {
+ loaded_cell -> value = value_nameslist;
+ }
+
+ names_options["ParentTagName"] = "label";
+ NamesList label_nameslist;
+ label_nameslist.fromXml(cell_element, names_options);
+ if (!label_nameslist.name().isEmpty()) {
+ loaded_cell -> label = label_nameslist;
+ }
+
+ if (cell_element.hasAttribute("displaylabel")) {
+ if (cell_element.attribute("displaylabel").compare("false", Qt::CaseInsensitive) == 0) {
+ loaded_cell -> display_label = false;
}
}
+ int fontsize;
+ if (QET::attributeIsAnInteger(cell_element, "fontsize", &fontsize)) {
+ loaded_cell -> font_size = fontsize;
+ } else {
+ loaded_cell -> font_size = -1;
+ }
+
+ // horizontal and vertical alignments
+ loaded_cell -> alignment = 0;
+
+ QString halignment = cell_element.attribute("align", "left");
+ if (halignment == "right") loaded_cell -> alignment |= Qt::AlignRight;
+ else if (halignment == "center") loaded_cell -> alignment |= Qt::AlignHCenter;
+ else loaded_cell -> alignment |= Qt::AlignLeft;
+
+ QString valignment = cell_element.attribute("valign", "center");
+ if (valignment == "bottom") loaded_cell -> alignment |= Qt::AlignBottom;
+ else if (valignment == "top") loaded_cell -> alignment |= Qt::AlignTop;
+ else loaded_cell -> alignment |= Qt::AlignVCenter;
+
+ // horizontal text adjustment
+ loaded_cell -> hadjust = cell_element.attribute("hadjust", "true") == "true";
}
+}
+
+/**
+ Export this template's logos as XML
+ @param xml_element XML Element under which the \<logos\> element will be attached
+*/
+void TitleBlockTemplate::saveLogos(QDomElement &xml_element) const {
+ QDomElement logos_element = xml_element.ownerDocument().createElement("logos");
+ foreach(QString logo_name, type_logos_.keys()) {
+ QDomElement logo_element = xml_element.ownerDocument().createElement("logo");
+ saveLogo(logo_name, logo_element);
+ logos_element.appendChild(logo_element);
+ }
+ xml_element.appendChild(logos_element);
+}
+
+/**
+ Export a specific logo as XML
+ @param logo_name Name of the logo to be exported
+ @param xml_element XML element in which the logo will be exported
+*/
+void TitleBlockTemplate::saveLogo(const QString &logo_name, QDomElement &xml_element) const {
+ if (!type_logos_.contains(logo_name)) return;
- return(true);
+ xml_element.setAttribute("name", logo_name);
+ xml_element.setAttribute("type", type_logos_[logo_name]);
+ xml_element.setAttribute("storage", storage_logos_[logo_name]);
+
+ if (storage_logos_[logo_name] == "xml" && type_logos_[logo_name] == "svg") {
+ QDomDocument svg_logo;
+ svg_logo.setContent(data_logos_[logo_name]);
+ QDomNode svg_logo_element = xml_element.ownerDocument().importNode(svg_logo.documentElement(), true);
+ xml_element.appendChild(svg_logo_element.toElement());
+ } else if (storage_logos_[logo_name] == "base64") {
+ QDomText base64_logo = xml_element.ownerDocument().createTextNode(data_logos_[logo_name].toBase64());
+ xml_element.appendChild(base64_logo);
+ }
}
/**
+ Export this template's cells grid as XML
+ @param xml_element XML element under which the \<grid\> element will be attached
+*/
+void TitleBlockTemplate::saveGrid(QDomElement &xml_element) const {
+ QDomElement grid_element = xml_element.ownerDocument().createElement("grid");
+
+ QString rows_attr, cols_attr;
+ foreach(int row_height, rows_heights_) rows_attr += QString("%1;").arg(row_height);
+ foreach(TitleBlockDimension col_width, columns_width_) cols_attr += col_width.toShortString();
+ grid_element.setAttribute("rows", rows_attr);
+ grid_element.setAttribute("cols", cols_attr);
+
+ saveCells(grid_element);
+
+ xml_element.appendChild(grid_element);
+}
+
+/**
+ Export this template's cells as XML (without the grid-related information, usch as rows and cols)
+ @param xml_element XML element under which the \<cell\> elements will be attached
+*/
+void TitleBlockTemplate::saveCells(QDomElement &xml_element) const {
+ for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
+ for (int i = 0 ; i < columns_width_.count() ; ++ i) {
+ if (cells_[i][j] -> cell_type != TitleBlockCell::EmptyCell) {
+ saveCell(cells_[i][j], xml_element);
+ }
+ }
+ }
+}
+
+/**
+ Export a specific cell as XML
+ @param cell Cell to be exported as XML
+ @param xml_element XML element under which the \<cell\> element will be attached
+*/
+void TitleBlockTemplate::saveCell(TitleBlockCell *cell, QDomElement &xml_element) const {
+ if (!cell || cell -> cell_type == TitleBlockCell::EmptyCell) return;
+ if (cell -> spanner_cell) return;
+
+ QDomElement cell_elmt = xml_element.ownerDocument().createElement("cell");
+ cell_elmt.setAttribute("name", cell -> value_name);
+ cell_elmt.setAttribute("row", cell -> num_row);
+ cell_elmt.setAttribute("col", cell -> num_col);
+ if (cell -> row_span) cell_elmt.setAttribute("rowspan", cell -> row_span);
+ if (cell -> col_span) cell_elmt.setAttribute("colspan", cell -> col_span);
+
+ if (cell -> type() == TitleBlockCell::LogoCell) {
+ cell_elmt.setTagName("logo");
+ cell_elmt.setAttribute("resource", cell -> logo_reference);
+ } else {
+ cell_elmt.setTagName("field");
+
+ QDomDocument parent_document = xml_element.ownerDocument();
+
+ QHash<QString, QString> names_options;
+ names_options["TagName"] = "translation";
+ names_options["ParentTagName"] = "value";
+ cell_elmt.appendChild(cell -> value.toXml(parent_document, names_options));
+ names_options["ParentTagName"] = "label";
+ cell_elmt.appendChild(cell -> label.toXml(parent_document, names_options));
+
+ cell_elmt.setAttribute("displaylabel", cell -> display_label ? "true" : "false");
+ if (cell -> font_size != -1) {
+ cell_elmt.setAttribute("fontsize", cell -> font_size);
+ }
+
+ if (cell -> alignment & Qt::AlignRight) {
+ cell_elmt.setAttribute("align", "right");
+ } else if (cell -> alignment & Qt::AlignHCenter) {
+ cell_elmt.setAttribute("align", "center");
+ } else {
+ cell_elmt.setAttribute("align", "left");
+ }
+
+ if (cell -> alignment & Qt::AlignBottom) {
+ cell_elmt.setAttribute("valign", "bottom");
+ } else if (cell -> alignment & Qt::AlignTop) {
+ cell_elmt.setAttribute("valign", "top");
+ } else {
+ cell_elmt.setAttribute("valign", "center");
+ }
+
+ if (cell -> hadjust) cell_elmt.setAttribute("hadjust", "true");
+ }
+
+ xml_element.appendChild(cell_elmt);
+}
+
+/**
+ Load the essential attributes of a cell: row and column indices and spans.
@param xml_element XML element representing a cell, i.e. either an titleblock
logo or an titleblock field.
- @param titleblock_cell_ptr Pointer to an TitleBlockCell object pointer - if non-zero and if
+ @param titleblock_cell_ptr Pointer to a TitleBlockCell object pointer - if non-zero and if
this method returns true, will be filled with the created TitleBlockCell
@return TRUE if the cell appears to be ok, FALSE otherwise
*/
@@ -350,10 +583,13 @@
#ifdef TITLEBLOCK_TEMPLATE_DEBUG
qDebug() << Q_FUNC_INFO << "cell access" << col_num << row_num;
#endif
- TitleBlockCell *cell_ptr = &(cells_[col_num][row_num]);
- if (!cell_ptr -> is_null || cell_ptr -> spanner_cell) {
+ TitleBlockCell *cell_ptr = cells_[col_num][row_num];
+ if (cell_ptr -> cell_type != TitleBlockCell::EmptyCell || cell_ptr -> spanner_cell) {
return(false);
}
+ // ensure the num_row and num_col attributes are alright
+ cell_ptr -> num_row = row_num;
+ cell_ptr -> num_col = col_num;
// parse the rowspan and colspan attributes
if (QET::attributeIsAnInteger(xml_element, "rowspan", &row_span) && row_span > 0) {
@@ -367,69 +603,35 @@
}
// check if we can span on the required area
- if (has_row_span || has_col_span) {
- for (int i = col_num ; i <= col_num + col_span ; ++ i) {
- for (int j = row_num ; j <= row_num + row_span ; ++ j) {
- if (i == col_num && j == row_num) continue;
-#ifdef TITLEBLOCK_TEMPLATE_DEBUG
- qDebug() << Q_FUNC_INFO << "span check" << i << j;
-#endif
- TitleBlockCell *current_cell = &(cells_[i][j]);
- if (!current_cell -> is_null || current_cell -> spanner_cell) {
- return(false);
- }
- }
- }
- }
+ //if (!checkCellSpan(cell_ptr)) return(false);
// at this point, the cell is ok - we fill the adequate cells in the matrix
#ifdef TITLEBLOCK_TEMPLATE_DEBUG
qDebug() << Q_FUNC_INFO << "cell writing";
#endif
- cell_ptr -> num_row = row_num;
- cell_ptr -> num_col = col_num;
if (has_row_span) cell_ptr -> row_span = row_span;
if (has_col_span) cell_ptr -> col_span = col_span;
- cell_ptr -> is_null = false;
if (titleblock_cell_ptr) *titleblock_cell_ptr = cell_ptr;
- if (has_row_span || has_col_span) {
- for (int i = col_num ; i <= col_num + col_span ; ++ i) {
- for (int j = row_num ; j <= row_num + row_span ; ++ j) {
- if (i == col_num && j == row_num) continue;
-#ifdef TITLEBLOCK_TEMPLATE_DEBUG
- qDebug() << Q_FUNC_INFO << "span cells writing" << i << j;
-#endif
- TitleBlockCell *current_cell = &(cells_[i][j]);
- current_cell -> num_row = j;
- current_cell -> num_col = i;
- current_cell -> is_null = false;
- current_cell -> spanner_cell = cell_ptr;
- }
- }
- }
+ //applyCellSpan(cell_ptr);
return(true);
}
/**
- Initializes the internal cells grid with the row and column counts.
+ Initialize the internal cells grid with the row and column counts.
Note that this method does nothing if one of the internal lists
columns_width_ and rows_heights_ is empty.
*/
void TitleBlockTemplate::initCells() {
if (columns_width_.count() < 1 || rows_heights_.count() < 1) return;
- cells_.resize(columns_width_.count());
- int row_count = rows_heights_.count();
+ cells_.clear();
+ qDeleteAll(registered_cells_);
+ registered_cells_.clear();
for (int i = 0 ; i < columns_width_.count() ; ++ i) {
- cells_[i].resize(row_count);
- // ensure every cell is a null cell
- for (int j = 0 ; j < row_count ; ++ j) {
- cells_[i][j] = TitleBlockCell();
- }
+ cells_ << createColumn();
}
-
#ifdef TITLEBLOCK_TEMPLATE_DEBUG
qDebug() << Q_FUNC_INFO << toString();
#endif
@@ -443,7 +645,7 @@
QString str = "\n";
for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
for (int i = 0 ; i < columns_width_.count() ; ++ i) {
- str += cells_[i][j].toString() + " ";
+ str += cells_[i][j] -> toString() + " ";
}
str += "\n";
}
@@ -458,6 +660,68 @@
}
/**
+ @param i row index
+ @return the height of the row at index i
+*/
+int TitleBlockTemplate::rowDimension(int i) {
+ int index = (i == -1) ? rows_heights_.count() - 1 : i;
+ if (index >= 0 || index < rows_heights_.count()) {
+ return(rows_heights_.at(index));
+ }
+ return(-1);
+}
+
+/**
+ Set the height of a row
+ @param i row index
+ @param dimension New height of the row at index i
+*/
+void TitleBlockTemplate::setRowDimension(int i, const TitleBlockDimension &dimension) {
+ int index = (i == -1) ? rows_heights_.count() - 1 : i;
+ if (index >= 0 || index < rows_heights_.count()) {
+ rows_heights_[index] = dimension.value;
+ }
+}
+
+/**
+ @param i column index
+ @return the width of the column at index i
+*/
+TitleBlockDimension TitleBlockTemplate::columnDimension(int i) {
+ int index = (i == -1) ? columns_width_.count() - 1 : i;
+ if (index >= 0 || index < columns_width_.count()) {
+ return(columns_width_.at(index));
+ }
+ return(TitleBlockDimension(-1));
+}
+
+/**
+ Set the width of a column
+ @param i column index
+ @param dimension New width of the column at index i
+*/
+void TitleBlockTemplate::setColumnDimension(int i, const TitleBlockDimension &dimension) {
+ int index = (i == -1) ? columns_width_.count() - 1 : i;
+ if (index >= 0 || index < columns_width_.count()) {
+ columns_width_[index] = dimension;
+ }
+}
+
+/**
+ @return the number of columns in this template
+*/
+int TitleBlockTemplate::columnsCount() const {
+ return(columns_width_.count());
+}
+
+/**
+ @return the number of rows in this template
+*/
+int TitleBlockTemplate::rowsCount() const {
+ return(rows_heights_.count());
+}
+
+/**
@param total_width The total width of the titleblock to render
@return the list of the columns widths for this rendering
*/
@@ -469,7 +733,7 @@
int abs_widths_sum = 0;
for (int i = 0 ; i < columns_width_.count() ; ++ i) {
- TitleBlockColDimension icd = columns_width_.at(i);
+ TitleBlockDimension icd = columns_width_.at(i);
if (icd.type == QET::Absolute) {
abs_widths_sum += icd.value;
final_widths[i] = icd.value;
@@ -485,7 +749,7 @@
// we do a second iteration to build the final widths list
for (int i = 0 ; i < columns_width_.count() ; ++ i) {
- TitleBlockColDimension icd = columns_width_.at(i);
+ TitleBlockDimension icd = columns_width_.at(i);
if (icd.type == QET::RelativeToRemainingLength) {
final_widths[i] = int(remaining_width * icd.value / 100);
}
@@ -493,6 +757,16 @@
return(final_widths.toList());
}
+/**
+ @return the heights of all the rows in this template
+*/
+QList<int> TitleBlockTemplate::rowsHeights() const {
+ return(rows_heights_);
+}
+
+/**
+ @return the total height of this template
+*/
int TitleBlockTemplate::height() const {
int height = 0;
foreach(int row_height, rows_heights_) {
@@ -502,6 +776,328 @@
}
/**
+ Move a row within this template.
+ @param from Index of the moved row
+ @param to Arrival index of the moved row
+*/
+bool TitleBlockTemplate::moveRow(int from, int to) {
+ // checks from and to
+ if (from >= rows_heights_.count()) return(false);
+ if (to >= rows_heights_.count()) return(false);
+ for (int j = 0 ; j < columns_width_.count() ; ++ j) {
+ cells_[j].move(from, to);
+ }
+ rows_heights_.move(from, to);
+ rowColsChanged();
+ return(true);
+}
+
+/**
+ Add a new 25px-wide row at the provided index.
+ @param i Index of the added row, -1 meaning "last position"
+*/
+void TitleBlockTemplate::addRow(int i) {
+ insertRow(25, createRow(), i);
+}
+
+/**
+ @param dimension Size of the row to be added (always absolute, in pixels)
+ @param column Row to be added
+ @param i Index of the column after insertion, -1 meaning "last position"
+*/
+bool TitleBlockTemplate::insertRow(int dimension, const QList<TitleBlockCell *> &row, int i) {
+ int index = (i == -1) ? rows_heights_.count() : i;
+
+ for (int j = 0 ; j < columns_width_.count() ; ++ j) {
+ cells_[j].insert(index, row[j]);
+ }
+ rows_heights_.insert(index, dimension);
+ rowColsChanged();
+ return(true);
+}
+
+/**
+ Removes the row at index i
+ @param i Index of the column to be removed
+ @return the removed column
+*/
+QList<TitleBlockCell *> TitleBlockTemplate::takeRow(int i) {
+ QList<TitleBlockCell *> row;
+ int index = (i == -1) ? rows_heights_.count() - 1 : i;
+ if (index < 0 || index >= rows_heights_.count()) return(row);
+ for (int j = 0 ; j < columns_width_.count() ; ++ j) {
+ row << cells_[j].takeAt(index);
+ }
+ rows_heights_.removeAt(index);
+ rowColsChanged();
+ return(row);
+}
+
+/**
+ @return a new row that fits the current grid
+*/
+QList<TitleBlockCell *> TitleBlockTemplate::createRow() {
+ return(createCellsList(columns_width_.count()));
+
+}
+
+/**
+ Move the column at index "from" to index "to".
+ @param from Source index of the moved column
+ @param to Target index of the moved column
+*/
+bool TitleBlockTemplate::moveColumn(int from, int to) {
+ // checks from and to
+ if (from >= columns_width_.count()) return(false);
+ if (to >= columns_width_.count()) return(false);
+ cells_.move(from, to);
+ columns_width_.move(from, to);
+ rowColsChanged();
+ return(true);
+}
+
+/**
+ Add a new 50px-wide column at the provided index.
+ @param i Index of the added column, -1 meaning "last position"
+*/
+void TitleBlockTemplate::addColumn(int i) {
+ insertColumn(TitleBlockDimension(50, QET::Absolute), createColumn(), i);
+}
+
+/**
+ @param dimension Size of the column to be added
+ @param column Column to be added
+ @param i Index of the column after insertion, -1 meaning "last position"
+*/
+bool TitleBlockTemplate::insertColumn(const TitleBlockDimension &dimension, const QList<TitleBlockCell *> &column, int i) {
+ int index = (i == -1) ? columns_width_.count() : i;
+ cells_.insert(index, column);
+ columns_width_.insert(index, dimension);
+ rowColsChanged();
+ return(true);
+}
+
+/**
+ Removes the column at index i
+ @param i Index of the column to be removed
+ @return the removed column
+*/
+QList<TitleBlockCell *> TitleBlockTemplate::takeColumn(int i) {
+ int index = (i == -1) ? columns_width_.count() - 1 : i;
+ if (index < 0 || index >= columns_width_.count()) {
+ return(QList<TitleBlockCell *>());
+ }
+ QList<TitleBlockCell *> column = cells_.takeAt(i);
+ columns_width_.removeAt(i);
+ rowColsChanged();
+ return(column);
+}
+
+/**
+ @return a new column that fits the current grid
+*/
+QList<TitleBlockCell *> TitleBlockTemplate::createColumn() {
+ return(createCellsList(rows_heights_.count()));
+}
+
+/**
+ @param row A row number (starting from 0)
+ @param col A column number (starting from 0)
+ @return the cell located at (row, col)
+*/
+TitleBlockCell *TitleBlockTemplate::cell(int row, int col) const {
+ if (row >= rows_heights_.count()) return(0);
+ if (col >= columns_width_.count()) return(0);
+
+ return(cells_[col][row]);
+}
+
+/**
+ @param cell A cell belonging to this title block template
+ @return the set of cells spanned by the provided cell
+ Note the returned set does not include the spanning, provided cell
+*/
+QSet<TitleBlockCell *> TitleBlockTemplate::spannedCells(const TitleBlockCell *given_cell) const {
+ QSet<TitleBlockCell *> set;
+ if (!given_cell || !given_cell -> spans()) return(set);
+
+ for (int i = given_cell -> num_col ; i <= given_cell -> num_col + given_cell -> col_span ; ++ i) {
+ for (int j = given_cell -> num_row ; j <= given_cell -> num_row + given_cell -> row_span ; ++ j) {
+ if (i == given_cell -> num_col && j == given_cell -> num_row) continue;
+ TitleBlockCell *current_cell = cell(j, i);
+ if (current_cell) set << current_cell;
+ }
+ }
+ return(set);
+}
+
+/**
+ @param logo_name Logo name to be added / replaced
+ @param logo_data Logo data
+*/
+bool TitleBlockTemplate::addLogo(const QString &logo_name, QByteArray *logo_data, const QString &logo_type, const QString &logo_storage) {
+ if (data_logos_.contains(logo_name)) {
+ // we are replacing the logo
+ removeLogo(logo_name);
+ }
+
+ // we can now create our image object from the byte array
+ if (logo_type == "svg") {
+ // SVG format is handled by the QSvgRenderer class
+ QSvgRenderer *svg = new QSvgRenderer();
+ if (!svg -> load(*logo_data)) {
+ return(false);
+ }
+ vector_logos_.insert(logo_name, svg);
+
+ // we also memorize the way to store them in the final XML output
+ QString final_logo_storage = logo_storage;
+ if (logo_storage != "xml" && logo_storage != "base64") {
+ final_logo_storage = "xml";
+ }
+ storage_logos_.insert(logo_name, logo_storage);
+ } else {
+
+ // bitmap formats are handled by the QPixmap class
+ QPixmap logo_pixmap;
+ logo_pixmap.loadFromData(*logo_data);
+ if (!logo_pixmap.width() || !logo_pixmap.height()) {
+ return(false);
+ }
+ bitmap_logos_.insert(logo_name, logo_pixmap);
+
+ // bitmap logos can only be stored using a base64 encoding
+ storage_logos_.insert(logo_name, "base64");
+ }
+
+ // we systematically store the raw data
+ data_logos_.insert(logo_name, *logo_data);
+ type_logos_.insert(logo_name, logo_type);
+
+ return(true);
+}
+
+/**
+ @param filepath Path of the image file to add as a logo
+ @param logo_name Name used to store the logo; if none is provided, the
+ basename of the first argument is used.
+ @return true if the logo could be deleted, false otherwise
+*/
+bool TitleBlockTemplate::addLogoFromFile(const QString &filepath, const QString &name) {
+ QFileInfo filepath_info(filepath);
+ QString filename = name.isEmpty() ? filepath_info.fileName() : name;
+ QString filetype = filepath_info.suffix();
+
+ // we read the provided logo
+ QFile logo_file(filepath);
+ if (!logo_file.open(QIODevice::ReadOnly)) return(false);
+ QByteArray file_content = logo_file.readAll();
+
+ // first, we try to add it as an SVG image
+ if (addLogo(filename, &file_content, "svg", "xml")) return(true);
+
+ // we then try to add it as a bitmap image
+ return addLogo(filename, &file_content, filepath_info.suffix(), "base64");
+}
+
+/**
+ @param logo_name Name of the logo to remove
+ @return true if the logo could be deleted, false otherwise
+*/
+bool TitleBlockTemplate::removeLogo(const QString &logo_name) {
+ if (!data_logos_.contains(logo_name)) {
+ return(false);
+ }
+
+ /// TODO check existing cells using this logo.
+ if (vector_logos_.contains(logo_name)) {
+ delete vector_logos_.take(logo_name);
+ }
+ if (bitmap_logos_.contains(logo_name)) {
+ bitmap_logos_.remove(logo_name);
+ }
+ data_logos_.remove(logo_name);
+ storage_logos_.remove(logo_name);
+ return(true);
+}
+
+/**
+ Rename the \a logo_name logo to \a new_name
+ @param logo_name Name of the logo to be renamed
+ @param new_name New name of the renamed logo
+*/
+bool TitleBlockTemplate::renameLogo(const QString &logo_name, const QString &new_name) {
+ if (!data_logos_.contains(logo_name) || data_logos_.contains(new_name)) {
+ return(false);
+ }
+
+ /// TODO check existing cells using this logo.
+ if (vector_logos_.contains(logo_name)) {
+ vector_logos_.insert(new_name, vector_logos_.take(logo_name));
+ }
+ if (bitmap_logos_.contains(logo_name)) {
+ bitmap_logos_.insert(new_name, bitmap_logos_.take(logo_name));
+ }
+ data_logos_.insert(new_name, data_logos_.take(logo_name));
+ storage_logos_.insert(new_name, storage_logos_.take(logo_name));
+ return(true);
+}
+
+/**
+ Set the kind of storage for the \a logo_name logo.
+ @param logo_name Name of the logo which kind of storage is to be changed
+ @param storage The kind of storage to use for the logo, e.g. "xml" or "base64".
+*/
+void TitleBlockTemplate::setLogoStorage(const QString &logo_name, const QString &storage) {
+ if (storage_logos_.contains(logo_name)) {
+ storage_logos_[logo_name] = storage;
+ }
+}
+
+/**
+ @return The names of logos embedded within this title block template.
+*/
+QList<QString> TitleBlockTemplate::logos() const {
+ return(data_logos_.keys());
+}
+
+/**
+ @param logo_name Name of a logo embedded within this title block template.
+ @return the kind of storage used for the required logo, or a null QString
+ if no such logo was found in this template.
+*/
+QString TitleBlockTemplate::logoType(const QString &logo_name) const {
+ if (type_logos_.contains(logo_name)) {
+ return type_logos_[logo_name];
+ }
+ return(QString());
+}
+
+/**
+ @param logo_name Name of a vector logo embedded within this title block template.
+ @return the rendering object for the required vector logo, or 0 if no such
+ vector logo was found in this template.
+*/
+QSvgRenderer *TitleBlockTemplate::vectorLogo(const QString &logo_name) const {
+ if (vector_logos_.contains(logo_name)) {
+ return vector_logos_[logo_name];
+ }
+ return(0);
+}
+
+/**
+ @param logo_name Name of a logo embedded within this title block template.
+ @return the pixmap for the required bitmap logo, or a null pixmap if no
+ such bitmap logo was found in this template.
+*/
+QPixmap TitleBlockTemplate::bitmapLogo(const QString &logo_name) const {
+ if (bitmap_logos_.contains(logo_name)) {
+ return bitmap_logos_[logo_name];
+ }
+ return(QPixmap());
+}
+
+/**
Render the titleblock.
@param painter Painter to use to render the titleblock
@param diagram_context Diagram context to use to generate the titleblock strings
@@ -521,38 +1117,56 @@
// run through each inidividual cell
for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
for (int i = 0 ; i < columns_width_.count() ; ++ i) {
- if (cells_[i][j].spanner_cell || cells_[i][j].is_null) continue;
+ if (cells_[i][j] -> spanner_cell || cells_[i][j] -> cell_type == TitleBlockCell::EmptyCell) continue;
// calculate the border rect of the current cell
- int x = lengthRange(0, cells_[i][j].num_col, widths);
- int y = lengthRange(0, cells_[i][j].num_row, rows_heights_);
- int w = lengthRange(cells_[i][j].num_col, cells_[i][j].num_col + 1 + cells_[i][j].col_span, widths);
- int h = lengthRange(cells_[i][j].num_row, cells_[i][j].num_row + 1 + cells_[i][j].row_span, rows_heights_);
+ int x = lengthRange(0, cells_[i][j] -> num_col, widths);
+ int y = lengthRange(0, cells_[i][j] -> num_row, rows_heights_);
+ int w = lengthRange(cells_[i][j] -> num_col, cells_[i][j] -> num_col + 1 + cells_[i][j] -> col_span, widths);
+ int h = lengthRange(cells_[i][j] -> num_row, cells_[i][j] -> num_row + 1 + cells_[i][j] -> row_span, rows_heights_);
QRect cell_rect(x, y, w, h);
- // draw the border rect of the current cell
- painter.drawRect(cell_rect);
-
- // render the inner content of the current cell
- if (!cells_[i][j].logo_reference.isEmpty()) {
- // the current cell appear to be a logo - we first look for the
- // logo reference in our vector logos list, since they offer a
- // potentially better (or, at least, not resolution-limited) rendering
- if (vector_logos_.contains(cells_[i][j].logo_reference)) {
- vector_logos_[cells_[i][j].logo_reference] -> render(&painter, cell_rect);
- } else if (bitmap_logos_.contains(cells_[i][j].logo_reference)) {
- painter.drawPixmap(cell_rect, *(bitmap_logos_[cells_[i][j].logo_reference]));
- }
- } else {
- QString final_text = finalTextForCell(cells_[i][j], diagram_context);
- renderTextCell(painter, final_text, cells_[i][j], cell_rect);
+ renderCell(painter, *cells_[i][j], diagram_context, cell_rect);
+ }
+ }
+}
+
+/**
+ Render a titleblock cell.
+ @param painter Painter to use to render the titleblock
+ @param diagram_context Diagram context to use to generate the titleblock strings
+ @param rect Rectangle the cell must be rendered into.
+*/
+void TitleBlockTemplate::renderCell(QPainter &painter, const TitleBlockCell &cell, const DiagramContext &diagram_context, const QRect &cell_rect) const {
+ // draw the border rect of the current cell
+ QPen pen(QBrush(), 0.0, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
+ pen.setColor(Qt::black);
+ painter.setPen(pen);
+ painter.setBrush(Qt::white);
+ painter.drawRect(cell_rect);
+
+ painter.save();
+ // render the inner content of the current cell
+ if (cell.type() == TitleBlockCell::LogoCell) {
+ if (!cell.logo_reference.isEmpty()) {
+ // the current cell appears to be a logo - we first look for the
+ // logo reference in our vector logos list, since they offer a
+ // potentially better (or, at least, not resolution-limited) rendering
+ if (vector_logos_.contains(cell.logo_reference)) {
+ vector_logos_[cell.logo_reference] -> render(&painter, cell_rect);
+ } else if (bitmap_logos_.contains(cell.logo_reference)) {
+ painter.drawPixmap(cell_rect, bitmap_logos_[cell.logo_reference]);
}
-
- // draw again the border rect of the current cell, without the brush this time
- painter.setBrush(Qt::NoBrush);
- painter.drawRect(cell_rect);
}
+ } else if (cell.type() == TitleBlockCell::TextCell) {
+ QString final_text = finalTextForCell(cell, diagram_context);
+ renderTextCell(painter, final_text, cell, cell_rect);
}
+ painter.restore();
+
+ // draw again the border rect of the current cell, without the brush this time
+ painter.setBrush(Qt::NoBrush);
+ painter.drawRect(cell_rect);
}
/**
@@ -561,14 +1175,15 @@
@return the final text that has to be drawn in the given cell
*/
QString TitleBlockTemplate::finalTextForCell(const TitleBlockCell &cell, const DiagramContext &diagram_context) const {
- QString cell_text = cell.value;
+ QString cell_text = cell.value.name();
+ QString cell_label = cell.label.name();
foreach (QString key, diagram_context.keys()) {
cell_text.replace("%{" + key + "}", diagram_context[key].toString());
cell_text.replace("%" + key, diagram_context[key].toString());
}
if (cell.display_label && !cell.label.isEmpty()) {
- cell_text = QString(tr(" %1 : %2", "titleblock content - please let the blank space at the beginning")).arg(cell.label).arg(cell_text);
+ cell_text = QString(tr(" %1 : %2", "titleblock content - please let the blank space at the beginning")).arg(cell_label).arg(cell_text);
} else {
cell_text = QString(tr(" %1")).arg(cell_text);
}
@@ -586,7 +1201,7 @@
@param cell_rect Rectangle delimiting the cell area
*/
void TitleBlockTemplate::renderTextCell(QPainter &painter, const QString &text, const TitleBlockCell &cell, const QRectF &cell_rect) const {
- QFont text_font = cell.font_size == -1 ? QETApp::diagramTextsFont() : QETApp::diagramTextsFont(cell.font_size);
+ QFont text_font = TitleBlockTemplate::fontForCell(cell);
painter.setFont(text_font);
if (cell.hadjust) {
@@ -617,13 +1232,113 @@
}
/**
+ Set the spanner_cell attribute of every cell to 0.
+*/
+void TitleBlockTemplate::forgetSpanning() {
+ for (int i = 0 ; i < columns_width_.count() ; ++ i) {
+ for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
+ cells_[i][j] -> spanner_cell = 0;
+ }
+ }
+}
+
+/**
+ Forget any previously applied span, then apply again all spans defined
+ by existing cells.
+*/
+void TitleBlockTemplate::applyCellSpans() {
+ forgetSpanning();
+ for (int i = 0 ; i < columns_width_.count() ; ++ i) {
+ for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
+ if (checkCellSpan(cells_[i][j])) {
+ applyCellSpan(cells_[i][j]);
+ }
+ }
+ }
+}
+
+/**
+ Check whether a given cell can be spanned according to its row_span and col_span attributes
+ @param cell Cell we want to check
+ @return true if the spanned
+*/
+bool TitleBlockTemplate::checkCellSpan(TitleBlockCell *cell/*, int policy = TitleBlockTemplate::???*/) {
+ if (!cell) return(false);
+ if (!cell -> row_span && !cell -> col_span) return(true);
+
+ // ensure the cell can span as far as required
+ if (cell -> num_col + cell -> col_span >= columnsCount()) return(false);
+ if (cell -> num_row + cell -> row_span >= rowsCount()) return(false);
+
+ // ensure cells that will be spanned are free/empty
+ for (int i = cell -> num_col ; i <= cell -> num_col + cell -> col_span ; ++ i) {
+ for (int j = cell -> num_row ; j <= cell -> num_row + cell -> row_span ; ++ j) {
+ if (i == cell -> num_col && j == cell -> num_row) continue;
+#ifdef TITLEBLOCK_TEMPLATE_DEBUG
+ qDebug() << Q_FUNC_INFO << "span check" << i << j;
+#endif
+ TitleBlockCell *current_cell = cells_[i][j];
+ if (current_cell -> cell_type != TitleBlockCell::EmptyCell || (current_cell -> spanner_cell && current_cell -> spanner_cell != cell)) {
+ return(false);
+ }
+ }
+ }
+ return(true);
+}
+
+/**
+ Ensure the spans of the provided cell are applied within the grid structure.
+ Note: this function does not check whether the spans of the provided cell make sense.
+ @param cell Potentially spanning cell
+*/
+void TitleBlockTemplate::applyCellSpan(TitleBlockCell *cell) {
+ if (!cell || (!cell -> row_span && !cell -> col_span)) return;
+
+ // goes through every spanned cell
+ for (int i = cell -> num_col ; i <= cell -> num_col + cell -> col_span ; ++ i) {
+ for (int j = cell -> num_row ; j <= cell -> num_row + cell -> row_span ; ++ j) {
+ // avoid the spanning cell itself
+ if (i == cell -> num_col && j == cell -> num_row) continue;
+#ifdef TITLEBLOCK_TEMPLATE_DEBUG
+ qDebug() << Q_FUNC_INFO << "marking cell at" << j << i << "as spanned by cell at" << cell -> num_row << cell -> num_col;
+#endif
+ // marks all spanned cells with the spanning cell
+ cells_[i][j] -> spanner_cell = cell;
+ }
+ }
+}
+
+/**
+ Ensure all cells have the right col+row numbers.
+*/
+void TitleBlockTemplate::applyRowColNums() {
+ for (int i = 0 ; i < columns_width_.count() ; ++ i) {
+ for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
+ cells_[i][j] -> num_col = i;
+ cells_[i][j] -> num_row = j;
+ }
+ }
+}
+
+/**
+ Take care of consistency and span-related problematics when
+ adding/moving/deleting rows and columns.
+*/
+void TitleBlockTemplate::rowColsChanged() {
+ applyRowColNums();
+ applyCellSpans();
+}
+
+/**
@return the width between two borders
@param start start border number
@param end end border number
*/
int TitleBlockTemplate::lengthRange(int start, int end, const QList<int> &lengths_list) const {
if (start > end || start >= lengths_list.count() || end > lengths_list.count()) {
+#ifdef TITLEBLOCK_TEMPLATE_DEBUG
qDebug() << Q_FUNC_INFO << "wont use" << start << "and" << end;
+#endif
return(0);
}
@@ -634,24 +1349,3 @@
return(length);
}
-
-
-/**
- Constructor
-*/
-TitleBlockCell::TitleBlockCell() {
- num_row = num_col = -1;
- row_span = col_span = 0;
- display_label = is_null = true;
- spanner_cell = 0;
-}
-
-/**
- @return A string representing the titleblock cell
-*/
-QString TitleBlockCell::toString() const {
- if (is_null) return("TitleBlockCell{null}");
- QString span_desc = (row_span > 0 || col_span > 0) ? QString("+%3,%4").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);
-}
Modified: branches/0.3/sources/titleblocktemplate.h
===================================================================
--- branches/0.3/sources/titleblocktemplate.h 2011-12-24 18:37:00 UTC (rev 1404)
+++ branches/0.3/sources/titleblocktemplate.h 2011-12-25 17:45:39 UTC (rev 1405)
@@ -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 @@
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 @@
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