QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
qgstableeditordialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstableeditordialog.cpp
3 ------------------------
4 begin : January 2020
5 copyright : (C) 2020 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgsdockwidget.h"
19#include "qgsgui.h"
20#include "qgslayout.h"
24#include "qgsmessagebar.h"
25#include "qgspanelwidgetstack.h"
26#include "qgssettings.h"
29#include "qgsvectorlayer.h"
30
31#include <QClipboard>
32#include <QMessageBox>
33
34#include "moc_qgstableeditordialog.cpp"
35
37 : QMainWindow( parent )
38{
39 setupUi( this );
40 setWindowTitle( tr( "Table Designer" ) );
41
42 setAttribute( Qt::WA_DeleteOnClose );
43 setDockOptions( dockOptions() | QMainWindow::GroupedDragging );
44
46
47 QGridLayout *viewLayout = new QGridLayout();
48 viewLayout->setSpacing( 0 );
49 viewLayout->setContentsMargins( 0, 0, 0, 0 );
50 centralWidget()->layout()->setSpacing( 0 );
51 centralWidget()->layout()->setContentsMargins( 0, 0, 0, 0 );
52
53 mMessageBar = new QgsMessageBar( centralWidget() );
54 mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
55 static_cast<QGridLayout *>( centralWidget()->layout() )->addWidget( mMessageBar, 0, 0, 1, 1, Qt::AlignTop );
56
57 mTableWidget = new QgsTableEditorWidget();
58 mTableWidget->setContentsMargins( 0, 0, 0, 0 );
59 viewLayout->addWidget( mTableWidget, 0, 0 );
60 mViewFrame->setLayout( viewLayout );
61 mViewFrame->setContentsMargins( 0, 0, 0, 0 );
62
63 mTableWidget->setFocus();
64 mTableWidget->setTableContents( QgsTableContents() << ( QgsTableRow() << QgsTableCell() ) );
65
66 connect( mTableWidget, &QgsTableEditorWidget::tableChanged, this, [this] {
67 if ( !mBlockSignals )
68 emit tableChanged();
69 } );
70
71 const int minDockWidth( fontMetrics().boundingRect( QStringLiteral( "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) ).width() );
72
73 mPropertiesDock = new QgsDockWidget( tr( "Cell Contents" ), this );
74 mPropertiesDock->setObjectName( QStringLiteral( "FormattingDock" ) );
75 mPropertiesStack = new QgsPanelWidgetStack();
76 mPropertiesDock->setWidget( mPropertiesStack );
77 mPropertiesDock->setMinimumWidth( minDockWidth );
78
79 mFormattingWidget = new QgsTableEditorFormattingWidget();
80 mFormattingWidget->setDockMode( true );
81 mPropertiesStack->setMainPanel( mFormattingWidget );
82
83 mPropertiesDock->setFeatures( QDockWidget::NoDockWidgetFeatures );
84
86
90
91 connect( mFormattingWidget, &QgsTableEditorFormattingWidget::textFormatChanged, this, [this] {
92 mTableWidget->setSelectionTextFormat( mFormattingWidget->textFormat() );
93 } );
94
95 connect( mFormattingWidget, &QgsTableEditorFormattingWidget::numberFormatChanged, this, [this] {
96 mTableWidget->setSelectionNumericFormat( mFormattingWidget->numericFormat() );
97 } );
100
101 connect( mTableWidget, &QgsTableEditorWidget::activeCellChanged, this, [this] {
102 mFormattingWidget->setBackgroundColor( mTableWidget->selectionBackgroundColor() );
103 mFormattingWidget->setNumericFormat( mTableWidget->selectionNumericFormat(), mTableWidget->hasMixedSelectionNumericFormat() );
104 mFormattingWidget->setRowHeight( mTableWidget->selectionRowHeight() );
105 mFormattingWidget->setColumnWidth( mTableWidget->selectionColumnWidth() );
106 mFormattingWidget->setTextFormat( mTableWidget->selectionTextFormat() );
107 mFormattingWidget->setHorizontalAlignment( mTableWidget->selectionHorizontalAlignment() );
108 mFormattingWidget->setVerticalAlignment( mTableWidget->selectionVerticalAlignment() );
109 mFormattingWidget->setCellProperty( mTableWidget->selectionCellProperty() );
110
111 updateActionsFromSelection();
112
113 mFormattingWidget->setEnabled( !mTableWidget->isHeaderCellSelected() );
114 } );
115 updateActionsFromSelection();
116
117 addDockWidget( Qt::RightDockWidgetArea, mPropertiesDock );
118
119 mActionImportFromClipboard->setEnabled( !QApplication::clipboard()->text().isEmpty() );
120 connect( QApplication::clipboard(), &QClipboard::dataChanged, this, [this]() { mActionImportFromClipboard->setEnabled( !QApplication::clipboard()->text().isEmpty() ); } );
121
122 connect( mActionImportFromClipboard, &QAction::triggered, this, &QgsTableEditorDialog::setTableContentsFromClipboard );
123 connect( mActionClose, &QAction::triggered, this, &QMainWindow::close );
124 connect( mActionInsertRowsAbove, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertRowsAbove );
125 connect( mActionInsertRowsBelow, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertRowsBelow );
126 connect( mActionInsertColumnsBefore, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertColumnsBefore );
127 connect( mActionInsertColumnsAfter, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertColumnsAfter );
128 connect( mActionMergeSelected, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::mergeSelectedCells );
129 connect( mActionSplitSelected, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::splitSelectedCells );
130 connect( mActionDeleteRows, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::deleteRows );
131 connect( mActionDeleteColumns, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::deleteColumns );
132 connect( mActionSelectRow, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::expandRowSelection );
133 connect( mActionSelectColumn, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::expandColumnSelection );
134 connect( mActionSelectAll, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::selectAll );
135 connect( mActionClear, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::clearSelectedCells );
136 connect( mActionIncludeHeader, &QAction::toggled, this, [this]( bool checked ) {
137 mTableWidget->setIncludeTableHeader( checked );
138 emit includeHeaderChanged( checked );
139 } );
140
141 // restore the toolbar and dock widgets positions using Qt settings API
142 const QgsSettings settings;
143
144 const QByteArray state = settings.value( QStringLiteral( "LayoutDesigner/tableEditorState" ), QByteArray(), QgsSettings::App ).toByteArray();
145 if ( !state.isEmpty() && !restoreState( state ) )
146 {
147 QgsDebugError( QStringLiteral( "restore of table editor dialog UI state failed" ) );
148 }
149}
150
152{
153 QgsSettings settings;
154 // store the toolbar/dock widget settings using Qt settings API
155 settings.setValue( QStringLiteral( "LayoutDesigner/tableEditorState" ), saveState(), QgsSettings::App );
156}
157
159{
160 return mLayer.data();
161}
162
164{
165 if ( layer != mLayer )
166 {
167 mLayer = layer;
168 mFormattingWidget->setLayer( layer );
169 }
170}
171
173{
174 return mTable;
175}
176
178{
179 if ( mTable == table )
180 return;
181
182 mTable = table;
183
184 if ( QgsLayout *layout = table->layout() )
185 {
186 setLayer( layout->reportContext().layer() );
187 }
189
190 setIncludeTableHeader( table->includeTableHeader() );
191 setTableContents( table->tableContents() );
192
193 int row = 0;
194 const QList<double> rowHeights = table->rowHeights();
195 for ( const double height : rowHeights )
196 {
197 setTableRowHeight( row, height );
198 row++;
199 }
200 int col = 0;
201 const QList<double> columnWidths = table->columnWidths();
202 QVariantList headers;
203 headers.reserve( columnWidths.size() );
204 for ( const double width : columnWidths )
205 {
206 setTableColumnWidth( col, width );
207 headers << ( col < table->headers().count() ? table->headers().value( col ).heading() : QVariant() );
208 col++;
209 }
210 setTableHeaders( headers );
211}
212
213
215{
216 if ( QApplication::clipboard()->text().isEmpty() )
217 return false;
218
219 if ( QMessageBox::question( this, tr( "Import Content From Clipboard" ), tr( "Importing content from clipboard will overwrite current table content. Are you sure?" ) ) != QMessageBox::Yes )
220 return false;
221
222 QgsTableContents contents;
223 const QStringList lines = QApplication::clipboard()->text().split( '\n' );
224 for ( const QString &line : lines )
225 {
226 if ( !line.isEmpty() )
227 {
228 QgsTableRow row;
229 const QStringList cells = line.split( '\t' );
230 for ( const QString &text : cells )
231 {
232 const QgsTableCell cell( text );
233 row << cell;
234 }
235 contents << row;
236 }
237 }
238
239 if ( !contents.isEmpty() )
240 {
241 setTableContents( contents );
242 emit tableChanged();
243 return true;
244 }
245
246 return false;
247}
248
250{
251 mBlockSignals = true;
252 mTableWidget->setTableContents( contents );
253 mTableWidget->resizeRowsToContents();
254 mTableWidget->resizeColumnsToContents();
255 mBlockSignals = false;
256}
257
259{
260 return mTableWidget->tableContents();
261}
262
264{
265 return mTableWidget->tableRowHeight( row );
266}
267
269{
270 return mTableWidget->tableColumnWidth( column );
271}
272
273void QgsTableEditorDialog::setTableRowHeight( int row, double height )
274{
275 mTableWidget->setTableRowHeight( row, height );
276}
277
278void QgsTableEditorDialog::setTableColumnWidth( int column, double width )
279{
280 mTableWidget->setTableColumnWidth( column, width );
281}
282
284{
285 return mActionIncludeHeader->isChecked();
286}
287
289{
290 mActionIncludeHeader->setChecked( included );
291}
292
294{
295 return mTableWidget->tableHeaders();
296}
297
298void QgsTableEditorDialog::setTableHeaders( const QVariantList &headers )
299{
300 mTableWidget->setTableHeaders( headers );
301}
302
304{
305 mFormattingWidget->registerExpressionContextGenerator( generator );
306}
307
308void QgsTableEditorDialog::updateActionsFromSelection()
309{
310 const int rowCount = mTableWidget->rowsAssociatedWithSelection().size();
311 const int columnCount = mTableWidget->columnsAssociatedWithSelection().size();
312
313 mActionInsertRowsAbove->setEnabled( rowCount > 0 );
314 mActionInsertRowsBelow->setEnabled( rowCount > 0 );
315 mActionDeleteRows->setEnabled( rowCount > 0 );
316 mActionSelectRow->setEnabled( rowCount > 0 );
317 if ( rowCount == 0 )
318 {
319 mActionInsertRowsAbove->setText( tr( "Rows Above" ) );
320 mActionInsertRowsBelow->setText( tr( "Rows Below" ) );
321 mActionDeleteRows->setText( tr( "Delete Rows" ) );
322 mActionSelectRow->setText( tr( "Select Rows" ) );
323 }
324 else if ( rowCount == 1 )
325 {
326 mActionInsertRowsAbove->setText( tr( "Row Above" ) );
327 mActionInsertRowsBelow->setText( tr( "Row Below" ) );
328 mActionDeleteRows->setText( tr( "Delete Row" ) );
329 mActionSelectRow->setText( tr( "Select Row" ) );
330 }
331 else
332 {
333 mActionInsertRowsAbove->setText( tr( "%n Row(s) Above", nullptr, rowCount ) );
334 mActionInsertRowsBelow->setText( tr( "%n Row(s) Below", nullptr, rowCount ) );
335 mActionDeleteRows->setText( tr( "Delete %n Row(s)", nullptr, rowCount ) );
336 mActionSelectRow->setText( tr( "Select %n Row(s)", nullptr, rowCount ) );
337 }
338
339 mActionInsertColumnsBefore->setEnabled( columnCount > 0 );
340 mActionInsertColumnsAfter->setEnabled( columnCount > 0 );
341 mActionDeleteColumns->setEnabled( columnCount > 0 );
342 mActionSelectColumn->setEnabled( columnCount > 0 );
343 if ( columnCount == 0 )
344 {
345 mActionInsertColumnsBefore->setText( tr( "Columns Before" ) );
346 mActionInsertColumnsAfter->setText( tr( "Columns After" ) );
347 mActionDeleteColumns->setText( tr( "Delete Columns" ) );
348 mActionSelectColumn->setText( tr( "Select Columns" ) );
349 }
350 else if ( columnCount == 1 )
351 {
352 mActionInsertColumnsBefore->setText( tr( "Column Before" ) );
353 mActionInsertColumnsAfter->setText( tr( "Column After" ) );
354 mActionDeleteColumns->setText( tr( "Delete Column" ) );
355 mActionSelectColumn->setText( tr( "Select Column" ) );
356 }
357 else
358 {
359 mActionInsertColumnsBefore->setText( tr( "%n Column(s) Before", nullptr, columnCount ) );
360 mActionInsertColumnsAfter->setText( tr( "%n Column(s) After", nullptr, columnCount ) );
361 mActionDeleteColumns->setText( tr( "Delete %n Column(s)", nullptr, columnCount ) );
362 mActionSelectColumn->setText( tr( "Select %n Column(s)", nullptr, columnCount ) );
363 }
364
365 mActionMergeSelected->setEnabled( mTableWidget->canMergeSelection() );
366 mActionSplitSelected->setEnabled( mTableWidget->canSplitSelection() );
367}
368
369#include "qgstableeditordialog.h"
A QDockWidget subclass with more fine-grained control over how the widget is closed or opened.
Abstract interface for generating an expression context.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:221
A layout table subclass that displays manually entered (and formatted) content.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition qgslayout.h:50
Base class for all map layer types.
Definition qgsmaplayer.h:80
A bar for displaying non-blocking messages to the user.
A stack widget to manage multiple overlapping stacked panels.
Stores settings for use within QGIS.
Definition qgssettings.h:65
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Encapsulates the contents and formatting of a single table cell.
void setIncludeTableHeader(bool included)
Sets whether the table includes a header row.
void setTable(QgsLayoutItemManualTable *table)
Sets the table associated with the editor.
QgsTableContents tableContents() const
Returns the current contents of the editor widget table.
void setTableHeaders(const QVariantList &headers)
Sets the table headers.
bool includeTableHeader() const
Returns true if the table includes a header row.
QgsTableEditorDialog(QWidget *parent=nullptr)
Constructor for QgsTableEditorDialog with the specified parent widget.
void includeHeaderChanged(bool included)
Emitted whenever the "include table header" setting is changed.
void setTableColumnWidth(int column, double width)
Sets the configured column width for the specified column.
void tableChanged()
Emitted whenever the table contents are changed.
void setTableRowHeight(int row, double height)
Sets the configured row height for the specified row.
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
bool setTableContentsFromClipboard()
Parses the clipboard text into contents to show in the editor widget.
QVariantList tableHeaders() const
Returns the table header values.
void closeEvent(QCloseEvent *) override
QgsMapLayer * layer() const
Returns the (possibly nullptr) layer associated with the expression editor context.
double tableRowHeight(int row)
Returns the configured row height for the specified row, or 0 if an automatic height should be used f...
double tableColumnWidth(int column)
Returns the configured column width for the specified column, or 0 if an automatic width should be us...
QgsLayoutItemManualTable * table() const
Returns the manual table associated with the editor.
void setLayer(QgsMapLayer *layer)
Sets the layer to be used associated with the expression editor context.
void setTableContents(const QgsTableContents &contents)
Sets the contents to show in the editor widget.
A reusable widget for formatting the contents of a QgsTableCell.
void cellPropertyChanged(const QgsProperty &property)
Emitted when the cell contents property shown in the widget is changed.
void textFormatChanged()
Emitted whenever the text format shown in the widget is changed.
void verticalAlignmentChanged(Qt::Alignment alignment)
Emitted when the vertical alignment shown in the widget is changed.
void rowHeightChanged(double height)
Emitted whenever the row height shown in the widget is changed.
void backgroundColorChanged(const QColor &color)
Emitted whenever the cell background color is changed in the widget.
void numberFormatChanged()
Emitted whenever the numeric format shown in the widget is changed.
void horizontalAlignmentChanged(Qt::Alignment alignment)
Emitted when the horizontal alignment shown in the widget is changed.
void columnWidthChanged(double width)
Emitted whenever the column width shown in the widget is changed.
A reusable widget for editing simple spreadsheet-style tables.
void setSelectionVerticalAlignment(Qt::Alignment alignment)
Sets the vertical alignment for the currently selected cells.
void splitSelectedCells()
Splits (un-merges) selected table cells.
void setSelectionBackgroundColor(const QColor &color)
Sets the background color for the currently selected cells.
void activeCellChanged()
Emitted whenever the active (or selected) cell changes in the widget.
void insertColumnsAfter()
Inserts new columns after the current selection.
void clearSelectedCells()
Clears the contents of the currently selected cells.
QList< int > rowsAssociatedWithSelection()
Returns a list of the rows associated with the current table selected cells.
QList< int > columnsAssociatedWithSelection()
Returns a list of the columns associated with the current table selected cells.
void deleteRows()
Deletes all rows associated with the current selected cells.
void setSelectionHorizontalAlignment(Qt::Alignment alignment)
Sets the horizontal alignment for the currently selected cells.
void setSelectionRowHeight(double height)
Sets the row height (in millimeters) for the currently selected rows, or 0 for automatic row height.
void insertRowsBelow()
Inserts new rows below the current selection.
void insertRowsAbove()
Inserts new rows above the current selection.
void setSelectionCellProperty(const QgsProperty &property)
Sets the cell contents QgsProperty for the currently selected cells.
void setSelectionColumnWidth(double height)
Sets the column width (in millimeters) for the currently selected columns, or 0 for automatic column ...
void expandRowSelection()
Expands out the selection to include whole rows associated with the current selected cells.
void deleteColumns()
Deletes all columns associated with the current selected cells.
void tableChanged()
Emitted whenever the table contents are changed.
void insertColumnsBefore()
Inserts new columns before the current selection.
void mergeSelectedCells()
Merges selected table cells.
void expandColumnSelection()
Expands out the selection to include whole columns associated with the current selected cells.
#define QgsDebugError(str)
Definition qgslogger.h:57
QVector< QgsTableRow > QgsTableContents
A set of table rows.
QVector< QgsTableCell > QgsTableRow
A row of table cells.