[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:


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/