mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-09-13 20:23:04 +02:00
The title block template editor now supports pasting multiple cells.
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/branches/0.3@1597 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
parent
e31a8a375e
commit
8b1e7904c4
@ -59,7 +59,6 @@ bool ModifyTitleBlockCellCommand::mergeWith(const QUndoCommand *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);
|
||||
}
|
||||
@ -208,6 +207,14 @@ void TitleBlockTemplateCommand::refreshView() {
|
||||
view_ -> refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
@ -933,21 +940,80 @@ void PasteTemplateCellsCommand::updateText() {
|
||||
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
|
||||
foreach (TitleBlockCell *cell, erased_cells_.keys()) {
|
||||
cell -> loadContentFromCell(pasted_cells_.value(cell));
|
||||
// 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()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (span_management) {
|
||||
refreshLayout();
|
||||
} else {
|
||||
refreshView();
|
||||
}
|
||||
refreshView();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,6 +78,7 @@ class TitleBlockTemplateCommand : public QUndoCommand {
|
||||
TitleBlockTemplateView *view() const;
|
||||
void setView(TitleBlockTemplateView *);
|
||||
void refreshView();
|
||||
void refreshLayout();
|
||||
|
||||
// attributes
|
||||
protected:
|
||||
@ -300,6 +301,8 @@ class PasteTemplateCellsCommand : public TitleBlockTemplateCommand {
|
||||
|
||||
// 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
|
||||
|
@ -160,6 +160,10 @@ QList<TitleBlockCell *> TitleBlockTemplateView::copy() {
|
||||
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 @@ QList<TitleBlockCell> TitleBlockTemplateView::pastedCells() {
|
||||
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 @@ QList<TitleBlockCell> TitleBlockTemplateView::pastedCells() {
|
||||
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?
|
||||
}
|
||||
|
||||
/**
|
||||
@ -768,6 +795,25 @@ bool TitleBlockTemplateView::event(QEvent *event) {
|
||||
return(QGraphicsView::event(event));
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
|
@ -97,6 +97,7 @@ class TitleBlockTemplateView : public QGraphicsView {
|
||||
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 *>);
|
||||
|
@ -1021,6 +1021,35 @@ QSet<TitleBlockCell *> TitleBlockTemplate::spannedCells(const TitleBlockCell *gi
|
||||
return(set);
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
@ -1333,6 +1362,21 @@ void TitleBlockTemplate::forgetSpanning() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
|
@ -83,6 +83,8 @@ class TitleBlockTemplate : public QObject {
|
||||
|
||||
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 @@ class TitleBlockTemplate : public QObject {
|
||||
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 @@ class TitleBlockTemplate : public QObject {
|
||||
int lengthRange(int, int, const QList<int> &) const;
|
||||
QString finalTextForCell(const TitleBlockCell &, const DiagramContext &) const;
|
||||
void renderTextCell(QPainter &, const QString &, const TitleBlockCell &, const QRectF &) const;
|
||||
void applyCellSpans();
|
||||
void forgetSpanning();
|
||||
bool checkCellSpan(TitleBlockCell *);
|
||||
void applyCellSpan(TitleBlockCell *);
|
||||
void applyRowColNums();
|
||||
void rowColsChanged();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user