[qet] [1597] The title block template editor now supports pasting multiple cells. |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/qet Archives
]
Revision: 1597
Author: xavier
Date: 2012-03-25 18:34:53 +0200 (Sun, 25 Mar 2012)
Log Message:
-----------
The title block template editor now supports pasting multiple cells.
Modified Paths:
--------------
branches/0.3/sources/titleblock/templatecommands.cpp
branches/0.3/sources/titleblock/templatecommands.h
branches/0.3/sources/titleblock/templateview.cpp
branches/0.3/sources/titleblock/templateview.h
branches/0.3/sources/titleblocktemplate.cpp
branches/0.3/sources/titleblocktemplate.h
Modified: branches/0.3/sources/titleblock/templatecommands.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatecommands.cpp 2012-03-25 16:34:49 UTC (rev 1596)
+++ branches/0.3/sources/titleblock/templatecommands.cpp 2012-03-25 16:34:53 UTC (rev 1597)
@@ -59,7 +59,6 @@
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);
}
@@ -209,6 +208,14 @@
}
/**
+ Refresh the view, including layout reloading, if any.
+*/
+void TitleBlockTemplateCommand::refreshLayout() {
+ if (!view_) return;
+ view_ -> updateLayout();
+}
+
+/**
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
@@ -933,21 +940,80 @@
Undo a paste action.
*/
void PasteTemplateCellsCommand::undo() {
+ bool span_management = erased_cells_.count() > 1;
foreach (TitleBlockCell *cell, erased_cells_.keys()) {
cell -> loadContentFromCell(erased_cells_.value(cell));
}
- refreshView();
+ if (span_management) {
+ // restore all span parameters as they were before the paste operation.
+ tbtemplate_ -> setAllSpans(spans_before_);
+ tbtemplate_ -> applyCellSpans();
+ refreshLayout();
+ } else {
+ refreshView();
+ }
}
/**
Redo a paste action.
*/
void PasteTemplateCellsCommand::redo() {
- // paste the first cell ony
+ // we only play with spans when pasting more than one cell.
+ bool span_management = erased_cells_.count() > 1;
+
+ if (span_management) {
+ // When pasting several cells, we may modify the span parameters of existing,
+ // non-erased cells. The easiest way to ensure everything can be restored at its
+ // initial state consists in saving the span parameters of every cell.
+ if (spans_before_.isEmpty()) {
+ spans_before_ = tbtemplate_ -> getAllSpans();
+ }
+ }
+
+ // copy data from each pasted cell into each erased cell
foreach (TitleBlockCell *cell, erased_cells_.keys()) {
- cell -> loadContentFromCell(pasted_cells_.value(cell));
+ if (span_management) {
+ // the erased cell may be spanned by another cell
+ if (TitleBlockCell *spanning_cell = cell -> spanner_cell) {
+ // for the moment, we simply cancel the whole spanning
+ tbtemplate_ -> forgetSpanning(spanning_cell);
+ }
+ }
+
+ // copy non-spans data
+ TitleBlockCell pasted_cell = pasted_cells_.value(cell);
+ cell -> loadContentFromCell(pasted_cell);
+
+ if (span_management) {
+ // copy spans data
+ if ((pasted_cell.row_span != cell -> row_span) || (pasted_cell.col_span != cell -> col_span)) {
+ tbtemplate_ -> forgetSpanning(cell);
+
+ // set the new/pasted span parameters
+ cell -> row_span = qBound(0, pasted_cell.row_span, tbtemplate_ -> rowsCount() - 1 - cell -> num_row);
+ cell -> col_span = qBound(0, pasted_cell.col_span, tbtemplate_ -> columnsCount() - 1 - cell -> num_col);
+
+ if (cell -> row_span || cell -> col_span) {
+ // browse newly spanned cells...
+ foreach (TitleBlockCell *spanned_cell, tbtemplate_ -> spannedCells(cell)) {
+ // ... to ensure they are not already spanned by other cells
+ if (spanned_cell -> spanner_cell && spanned_cell -> spanner_cell != cell) {
+ // if so, simply cancel the whole spanning
+ tbtemplate_ -> forgetSpanning(spanned_cell -> spanner_cell);
+ }
+ }
+
+ // set the spanner_cell attribute of newly spanned cells
+ tbtemplate_ -> applyCellSpan(cell);
+ }
+ }
+ }
}
- refreshView();
+ if (span_management) {
+ refreshLayout();
+ } else {
+ refreshView();
+ }
}
/**
Modified: branches/0.3/sources/titleblock/templatecommands.h
===================================================================
--- branches/0.3/sources/titleblock/templatecommands.h 2012-03-25 16:34:49 UTC (rev 1596)
+++ branches/0.3/sources/titleblock/templatecommands.h 2012-03-25 16:34:53 UTC (rev 1597)
@@ -78,6 +78,7 @@
TitleBlockTemplateView *view() const;
void setView(TitleBlockTemplateView *);
void refreshView();
+ void refreshLayout();
// attributes
protected:
@@ -300,6 +301,8 @@
// attributes
public:
+ /// Spans before operation
+ QHash<TitleBlockCell *, QPair<int, int> > spans_before_;
/// Pasted cells
QHash<TitleBlockCell *, TitleBlockCell> pasted_cells_;
/// Existing cells impacted by the paste operation
Modified: branches/0.3/sources/titleblock/templateview.cpp
===================================================================
--- branches/0.3/sources/titleblock/templateview.cpp 2012-03-25 16:34:49 UTC (rev 1596)
+++ branches/0.3/sources/titleblock/templateview.cpp 2012-03-25 16:34:53 UTC (rev 1597)
@@ -160,6 +160,10 @@
xml_export.appendChild(tbtpartial);
foreach (TitleBlockCell *cell, copied_cells) {
tbtemplate_ -> exportCellToXml(cell, tbtpartial);
+ tbtpartial.setAttribute("row", cell -> num_row);
+ tbtpartial.setAttribute("col", cell -> num_col);
+ tbtpartial.setAttribute("row_span", cell -> row_span);
+ tbtpartial.setAttribute("col_span", cell -> col_span);
}
QClipboard *clipboard = QApplication::clipboard();
@@ -202,6 +206,24 @@
if (e.tagName() == "empty" || e.tagName() == "field" || e.tagName() == "logo") {
TitleBlockCell cell;
cell.loadContentFromXml(e);
+ int row_num = -1, col_num = -1, row_span = -1, col_span = -1;
+ if (!QET::attributeIsAnInteger(e, "row", &row_num) || row_num < 0) {
+ continue;
+ }
+ if (!QET::attributeIsAnInteger(e, "col", &col_num) || col_num < 0) {
+ continue;
+ }
+ cell.num_row = row_num;
+ cell.num_col = col_num;
+
+ // parse the rowspan and colspan attributes
+ if (QET::attributeIsAnInteger(e, "rowspan", &row_span) && row_span > 0) {
+ cell.row_span = row_span;
+ }
+
+ if (QET::attributeIsAnInteger(e, "colspan", &col_span) && col_span > 0) {
+ cell.col_span = col_span;
+ }
pasted_cells << cell;
}
}
@@ -212,22 +234,27 @@
Import the cells described in the clipboard.
*/
void TitleBlockTemplateView::paste() {
+ if (!tbtemplate_) return;
QList<TitleBlockCell> pasted_cells = pastedCells();
-
- // paste the first cell only
if (!pasted_cells.count()) return;
- // onto the first selected one
+ // the top left cell among the selected ones will be used to position the pasted cells
TitleBlockTemplateVisualCell *selected_cell = selectedCellsSet().topLeftCell();
if (!selected_cell) return;
-
TitleBlockCell *erased_cell = selected_cell -> cell();
if (!erased_cell) return;
+ // change num_row and num_col attributes of pasted cells so they get positionned relatively to selected_cell
+ normalizeCells(pasted_cells, erased_cell -> num_row, erased_cell -> num_col);
+
PasteTemplateCellsCommand *paste_command = new PasteTemplateCellsCommand(tbtemplate_);
- paste_command -> addCell(erased_cell, *erased_cell, pasted_cells.first());
+ foreach (TitleBlockCell cell, pasted_cells) {
+ TitleBlockCell *erased_cell = tbtemplate_ -> cell(cell.num_row, cell.num_col);
+ if (!erased_cell) continue;
+ paste_command -> addCell(erased_cell, *erased_cell, cell);
+ }
+
requestGridModification(paste_command);
- /// TODO paste more cells, using some kind of heuristic to place them?
}
/**
@@ -769,6 +796,25 @@
}
/**
+ Given a cells list, change their position so the top left one is at row \a x and column \a y.
+ @param cells Cells list
+*/
+void TitleBlockTemplateView::normalizeCells(QList<TitleBlockCell> &cells, int x, int y) const {
+ if (!cells.count()) return;
+
+ int min_row = cells.at(0).num_row;
+ int min_col = cells.at(0).num_col;
+ for (int i = 1 ; i < cells.count() ; ++ i) {
+ if (cells.at(i).num_row < min_row) min_row = cells.at(i).num_row;
+ if (cells.at(i).num_col < min_col) min_col = cells.at(i).num_col;
+ }
+ for (int i = 0 ; i < cells.count() ; ++ i) {
+ cells[i].num_row = cells[i].num_row - min_row + x;
+ cells[i].num_col = cells[i].num_col - min_col + y;
+ }
+}
+
+/**
Load the \a tbt title block template.
If a different template was previously loaded, it is deleted.
Modified: branches/0.3/sources/titleblock/templateview.h
===================================================================
--- branches/0.3/sources/titleblock/templateview.h 2012-03-25 16:34:49 UTC (rev 1596)
+++ branches/0.3/sources/titleblock/templateview.h 2012-03-25 16:34:53 UTC (rev 1597)
@@ -97,6 +97,7 @@
virtual qreal zoomFactor() const;
virtual void fillWithEmptyCells();
virtual bool event(QEvent *);
+ virtual void normalizeCells(QList<TitleBlockCell> &, int x = 0, int y = 0) const;
signals:
void selectedCellsChanged(QList<TitleBlockCell *>);
Modified: branches/0.3/sources/titleblocktemplate.cpp
===================================================================
--- branches/0.3/sources/titleblocktemplate.cpp 2012-03-25 16:34:49 UTC (rev 1596)
+++ branches/0.3/sources/titleblocktemplate.cpp 2012-03-25 16:34:53 UTC (rev 1597)
@@ -1022,6 +1022,35 @@
}
/**
+ Export the span parameters of all cell in the current grid.
+*/
+QHash<TitleBlockCell *, QPair<int, int> > TitleBlockTemplate::getAllSpans() const {
+ QHash<TitleBlockCell *, QPair<int, int> > spans;
+ for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
+ for (int i = 0 ; i < columns_width_.count() ; ++ i) {
+ spans.insert(
+ cells_[i][j],
+ QPair<int, int>(
+ cells_[i][j] -> row_span,
+ cells_[i][j] -> col_span
+ )
+ );
+ }
+ }
+ return(spans);
+}
+
+/**
+ Restore a set of span parameters.
+*/
+void TitleBlockTemplate::setAllSpans(const QHash<TitleBlockCell *, QPair<int, int> > &spans) {
+ foreach (TitleBlockCell *cell, spans.keys()) {
+ cell -> row_span = spans[cell].first;
+ cell -> col_span = spans[cell].second;
+ }
+}
+
+/**
@param logo_name Logo name to be added / replaced
@param logo_data Logo data
*/
@@ -1334,6 +1363,21 @@
}
/**
+ Set the spanner_cell attribute of every cell spanned by \a spanning_cell to 0.
+ @param modify_cell (Optional, defaults to true) Whether to set row_span and col_span of \a spanning_cell to 0.
+*/
+void TitleBlockTemplate::forgetSpanning(TitleBlockCell *spanning_cell, bool modify_cell) {
+ if (!spanning_cell) return;
+ foreach (TitleBlockCell *spanned_cell, spannedCells(spanning_cell)) {
+ spanned_cell -> spanner_cell = 0;
+ }
+ if (modify_cell) {
+ spanning_cell -> row_span = 0;
+ spanning_cell -> col_span = 0;
+ }
+}
+
+/**
Forget any previously applied span, then apply again all spans defined
by existing cells.
*/
Modified: branches/0.3/sources/titleblocktemplate.h
===================================================================
--- branches/0.3/sources/titleblocktemplate.h 2012-03-25 16:34:49 UTC (rev 1596)
+++ branches/0.3/sources/titleblocktemplate.h 2012-03-25 16:34:53 UTC (rev 1597)
@@ -83,6 +83,8 @@
TitleBlockCell *cell(int, int) const;
QSet<TitleBlockCell *> spannedCells(const TitleBlockCell *) const;
+ QHash<TitleBlockCell *, QPair<int, int> > getAllSpans() const;
+ void setAllSpans(const QHash<TitleBlockCell *, QPair<int, int> > &);
bool addLogo(const QString &, QByteArray *, const QString & = "svg", const QString & = "xml");
bool addLogoFromFile(const QString &, const QString & = QString());
bool removeLogo(const QString &);
@@ -96,6 +98,13 @@
void render(QPainter &, const DiagramContext &, int) const;
void renderCell(QPainter &, const TitleBlockCell &, const DiagramContext &, const QRect &) const;
QString toString() const;
+ void applyCellSpans();
+ void forgetSpanning();
+ void forgetSpanning(TitleBlockCell *, bool = true);
+ bool checkCellSpan(TitleBlockCell *);
+ void applyCellSpan(TitleBlockCell *);
+ void applyRowColNums();
+ void rowColsChanged();
protected:
void loadInformation(const QDomElement &);
@@ -121,12 +130,6 @@
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();
// attributes
private: