QGIS API Documentation  3.27.0-Master (597e8eebd4)
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 
16 #include "qgstableeditordialog.h"
17 #include "qgstableeditorwidget.h"
18 #include "qgsmessagebar.h"
19 #include "qgsgui.h"
20 #include "qgsdockwidget.h"
21 #include "qgspanelwidgetstack.h"
23 #include "qgssettings.h"
24 
25 #include <QClipboard>
26 #include <QMessageBox>
27 
29  : QMainWindow( parent )
30 {
31  setupUi( this );
32  setWindowTitle( tr( "Table Designer" ) );
33 
34  setAttribute( Qt::WA_DeleteOnClose );
35  setDockOptions( dockOptions() | QMainWindow::GroupedDragging );
36 
38 
39  QGridLayout *viewLayout = new QGridLayout();
40  viewLayout->setSpacing( 0 );
41  viewLayout->setContentsMargins( 0, 0, 0, 0 );
42  centralWidget()->layout()->setSpacing( 0 );
43  centralWidget()->layout()->setContentsMargins( 0, 0, 0, 0 );
44 
45  mMessageBar = new QgsMessageBar( centralWidget() );
46  mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
47  static_cast< QGridLayout * >( centralWidget()->layout() )->addWidget( mMessageBar, 0, 0, 1, 1, Qt::AlignTop );
48 
49  mTableWidget = new QgsTableEditorWidget();
50  mTableWidget->setContentsMargins( 0, 0, 0, 0 );
51  viewLayout->addWidget( mTableWidget, 0, 0 );
52  mViewFrame->setLayout( viewLayout );
53  mViewFrame->setContentsMargins( 0, 0, 0, 0 );
54 
55  mTableWidget->setFocus();
56  mTableWidget->setTableContents( QgsTableContents() << ( QgsTableRow() << QgsTableCell() ) );
57 
58  connect( mTableWidget, &QgsTableEditorWidget::tableChanged, this, [ = ]
59  {
60  if ( !mBlockSignals )
61  emit tableChanged();
62  } );
63 
64  const int minDockWidth( fontMetrics().boundingRect( QStringLiteral( "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) ).width() );
65 
66  mPropertiesDock = new QgsDockWidget( tr( "Cell Contents" ), this );
67  mPropertiesDock->setObjectName( QStringLiteral( "FormattingDock" ) );
68  mPropertiesStack = new QgsPanelWidgetStack();
69  mPropertiesDock->setWidget( mPropertiesStack );
70  mPropertiesDock->setMinimumWidth( minDockWidth );
71 
72  mFormattingWidget = new QgsTableEditorFormattingWidget();
73  mFormattingWidget->setDockMode( true );
74  mPropertiesStack->setMainPanel( mFormattingWidget );
75 
76  mPropertiesDock->setFeatures( QDockWidget::NoDockWidgetFeatures );
77 
79 
83 
84  connect( mFormattingWidget, &QgsTableEditorFormattingWidget::textFormatChanged, this, [ = ]
85  {
86  mTableWidget->setSelectionTextFormat( mFormattingWidget->textFormat() );
87  } );
88 
89  connect( mFormattingWidget, &QgsTableEditorFormattingWidget::numberFormatChanged, this, [ = ]
90  {
91  mTableWidget->setSelectionNumericFormat( mFormattingWidget->numericFormat() );
92  } );
95 
96  connect( mTableWidget, &QgsTableEditorWidget::activeCellChanged, this, [ = ]
97  {
98  mFormattingWidget->setBackgroundColor( mTableWidget->selectionBackgroundColor() );
99  mFormattingWidget->setNumericFormat( mTableWidget->selectionNumericFormat(), mTableWidget->hasMixedSelectionNumericFormat() );
100  mFormattingWidget->setRowHeight( mTableWidget->selectionRowHeight() );
101  mFormattingWidget->setColumnWidth( mTableWidget->selectionColumnWidth() );
102  mFormattingWidget->setTextFormat( mTableWidget->selectionTextFormat() );
103  mFormattingWidget->setHorizontalAlignment( mTableWidget->selectionHorizontalAlignment() );
104  mFormattingWidget->setVerticalAlignment( mTableWidget->selectionVerticalAlignment() );
105  mFormattingWidget->setCellProperty( mTableWidget->selectionCellProperty() );
106 
107  updateActionNamesFromSelection();
108 
109  mFormattingWidget->setEnabled( !mTableWidget->isHeaderCellSelected() );
110  } );
111  updateActionNamesFromSelection();
112 
113  addDockWidget( Qt::RightDockWidgetArea, mPropertiesDock );
114 
115  mActionImportFromClipboard->setEnabled( !QApplication::clipboard()->text().isEmpty() );
116  connect( QApplication::clipboard(), &QClipboard::dataChanged, this, [ = ]() { mActionImportFromClipboard->setEnabled( !QApplication::clipboard()->text().isEmpty() ); } );
117 
118  connect( mActionImportFromClipboard, &QAction::triggered, this, &QgsTableEditorDialog::setTableContentsFromClipboard );
119  connect( mActionClose, &QAction::triggered, this, &QMainWindow::close );
120  connect( mActionInsertRowsAbove, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertRowsAbove );
121  connect( mActionInsertRowsBelow, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertRowsBelow );
122  connect( mActionInsertColumnsBefore, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertColumnsBefore );
123  connect( mActionInsertColumnsAfter, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::insertColumnsAfter );
124  connect( mActionDeleteRows, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::deleteRows );
125  connect( mActionDeleteColumns, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::deleteColumns );
126  connect( mActionSelectRow, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::expandRowSelection );
127  connect( mActionSelectColumn, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::expandColumnSelection );
128  connect( mActionSelectAll, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::selectAll );
129  connect( mActionClear, &QAction::triggered, mTableWidget, &QgsTableEditorWidget::clearSelectedCells );
130  connect( mActionIncludeHeader, &QAction::toggled, this, [ = ]( bool checked )
131  {
132  mTableWidget->setIncludeTableHeader( checked );
133  emit includeHeaderChanged( checked );
134  } );
135 
136  // restore the toolbar and dock widgets positions using Qt settings API
137  const QgsSettings settings;
138 
139  const QByteArray state = settings.value( QStringLiteral( "LayoutDesigner/tableEditorState" ), QByteArray(), QgsSettings::App ).toByteArray();
140  if ( !state.isEmpty() && !restoreState( state ) )
141  {
142  QgsDebugMsg( QStringLiteral( "restore of table editor dialog UI state failed" ) );
143  }
144 }
145 
146 void QgsTableEditorDialog::closeEvent( QCloseEvent * )
147 {
148  QgsSettings settings;
149  // store the toolbar/dock widget settings using Qt settings API
150  settings.setValue( QStringLiteral( "LayoutDesigner/tableEditorState" ), saveState(), QgsSettings::App );
151 }
152 
154 {
155  if ( QApplication::clipboard()->text().isEmpty() )
156  return false;
157 
158  if ( QMessageBox::question( this, tr( "Import Content From Clipboard" ),
159  tr( "Importing content from clipboard will overwrite current table content. Are you sure?" ) ) != QMessageBox::Yes )
160  return false;
161 
162  QgsTableContents contents;
163  const QStringList lines = QApplication::clipboard()->text().split( '\n' );
164  for ( const QString &line : lines )
165  {
166  if ( !line.isEmpty() )
167  {
168  QgsTableRow row;
169  const QStringList cells = line.split( '\t' );
170  for ( const QString &text : cells )
171  {
172  const QgsTableCell cell( text );
173  row << cell;
174  }
175  contents << row;
176  }
177  }
178 
179  if ( !contents.isEmpty() )
180  {
181  setTableContents( contents );
182  emit tableChanged();
183  return true;
184  }
185 
186  return false;
187 }
188 
190 {
191  mBlockSignals = true;
192  mTableWidget->setTableContents( contents );
193  mTableWidget->resizeRowsToContents();
194  mTableWidget->resizeColumnsToContents();
195  mBlockSignals = false;
196 }
197 
199 {
200  return mTableWidget->tableContents();
201 }
202 
204 {
205  return mTableWidget->tableRowHeight( row );
206 }
207 
209 {
210  return mTableWidget->tableColumnWidth( column );
211 }
212 
213 void QgsTableEditorDialog::setTableRowHeight( int row, double height )
214 {
215  mTableWidget->setTableRowHeight( row, height );
216 }
217 
218 void QgsTableEditorDialog::setTableColumnWidth( int column, double width )
219 {
220  mTableWidget->setTableColumnWidth( column, width );
221 }
222 
224 {
225  return mActionIncludeHeader->isChecked();
226 }
227 
229 {
230  mActionIncludeHeader->setChecked( included );
231 }
232 
234 {
235  return mTableWidget->tableHeaders();
236 }
237 
238 void QgsTableEditorDialog::setTableHeaders( const QVariantList &headers )
239 {
240  mTableWidget->setTableHeaders( headers );
241 }
242 
244 {
245  mFormattingWidget->registerExpressionContextGenerator( generator );
246 }
247 
248 void QgsTableEditorDialog::updateActionNamesFromSelection()
249 {
250  const int rowCount = mTableWidget->rowsAssociatedWithSelection().size();
251  const int columnCount = mTableWidget->columnsAssociatedWithSelection().size();
252 
253  mActionInsertRowsAbove->setEnabled( rowCount > 0 );
254  mActionInsertRowsBelow->setEnabled( rowCount > 0 );
255  mActionDeleteRows->setEnabled( rowCount > 0 );
256  mActionSelectRow->setEnabled( rowCount > 0 );
257  if ( rowCount == 0 )
258  {
259  mActionInsertRowsAbove->setText( tr( "Rows Above" ) );
260  mActionInsertRowsBelow->setText( tr( "Rows Below" ) );
261  mActionDeleteRows->setText( tr( "Delete Rows" ) );
262  mActionSelectRow->setText( tr( "Select Rows" ) );
263  }
264  else if ( rowCount == 1 )
265  {
266  mActionInsertRowsAbove->setText( tr( "Row Above" ) );
267  mActionInsertRowsBelow->setText( tr( "Row Below" ) );
268  mActionDeleteRows->setText( tr( "Delete Row" ) );
269  mActionSelectRow->setText( tr( "Select Row" ) );
270  }
271  else
272  {
273  mActionInsertRowsAbove->setText( tr( "%n Row(s) Above", nullptr, rowCount ) );
274  mActionInsertRowsBelow->setText( tr( "%n Row(s) Below", nullptr, rowCount ) );
275  mActionDeleteRows->setText( tr( "Delete %n Row(s)", nullptr, rowCount ) );
276  mActionSelectRow->setText( tr( "Select %n Row(s)", nullptr, rowCount ) );
277  }
278 
279  mActionInsertColumnsBefore->setEnabled( columnCount > 0 );
280  mActionInsertColumnsAfter->setEnabled( columnCount > 0 );
281  mActionDeleteColumns->setEnabled( columnCount > 0 );
282  mActionSelectColumn->setEnabled( columnCount > 0 );
283  if ( columnCount == 0 )
284  {
285  mActionInsertColumnsBefore->setText( tr( "Columns Before" ) );
286  mActionInsertColumnsAfter->setText( tr( "Columns After" ) );
287  mActionDeleteColumns->setText( tr( "Delete Columns" ) );
288  mActionSelectColumn->setText( tr( "Select Columns" ) );
289  }
290  else if ( columnCount == 1 )
291  {
292  mActionInsertColumnsBefore->setText( tr( "Column Before" ) );
293  mActionInsertColumnsAfter->setText( tr( "Column After" ) );
294  mActionDeleteColumns->setText( tr( "Delete Column" ) );
295  mActionSelectColumn->setText( tr( "Select Column" ) );
296  }
297  else
298  {
299  mActionInsertColumnsBefore->setText( tr( "%n Column(s) Before", nullptr, columnCount ) );
300  mActionInsertColumnsAfter->setText( tr( "%n Column(s) After", nullptr, columnCount ) );
301  mActionDeleteColumns->setText( tr( "Delete %n Column(s)", nullptr, columnCount ) );
302  mActionSelectColumn->setText( tr( "Select %n Column(s)", nullptr, columnCount ) );
303  }
304 }
305 
306 #include "qgstableeditordialog.h"
QgsDockWidget subclass with more fine-grained control over how the widget is closed or opened.
Definition: qgsdockwidget.h:32
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:180
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
A stack widget to manage panels in the interface.
void setMainPanel(QgsPanelWidget *panel SIP_TRANSFER)
Sets the main panel widget for the stack and selects it for the user.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
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.
Definition: qgstablecell.h:36
void setIncludeTableHeader(bool included)
Sets whether the table includes a header row.
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
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...
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.
QgsTextFormat textFormat() const
Returns the current text format shown in the widget.
void setVerticalAlignment(Qt::Alignment alignment)
Sets the vertical alignment to show in the widget.
void setTextFormat(const QgsTextFormat &format)
Sets the text format to show in the widget.
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void setBackgroundColor(const QColor &color)
Sets the cell background color to show in the widget.
void backgroundColorChanged(const QColor &color)
Emitted whenever the cell background color is changed in the widget.
QgsNumericFormat * numericFormat()
Returns the current numeric format shown in the widget, or a nullptr if no numeric format is set.
void setCellProperty(const QgsProperty &property)
Sets the cell content's property to show in the widget.
void numberFormatChanged()
Emitted whenever the numeric format shown in the widget is changed.
void setColumnWidth(double width)
Sets the column width to show in the widget, or 0 for automatic width.
void setHorizontalAlignment(Qt::Alignment alignment)
Sets the horizontal alignment to show in the widget.
void setNumericFormat(QgsNumericFormat *format, bool isMixedFormat)
Sets the numeric format to show in the widget, or nullptr if no numeric format is set.
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.
void setRowHeight(double height)
Sets the row height to show in the widget, or 0 for automatic height.
A reusable widget for editing simple spreadsheet-style tables.
void setSelectionVerticalAlignment(Qt::Alignment alignment)
Sets the vertical alignment for the currently selected cells.
QgsProperty selectionCellProperty()
Returns the QgsProperty used for the contents of the currently selected cells.
QVariantList tableHeaders() const
Returns the table header values.
void setSelectionTextFormat(const QgsTextFormat &format)
Sets the text format for the selected cells.
void setTableHeaders(const QVariantList &headers)
Sets the table headers.
bool isHeaderCellSelected()
Returns true if any header cells are selected.
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.
Qt::Alignment selectionHorizontalAlignment()
Returns the horizontal alignment for the currently selected cells.
QgsTextFormat selectionTextFormat()
Returns the text format for the currently selected cells.
void insertColumnsAfter()
Inserts new columns after the current selection.
double selectionRowHeight()
Returns the height (in millimeters) of the rows associated with the current selection,...
void clearSelectedCells()
Clears the contents of the currently selected cells.
bool hasMixedSelectionNumericFormat()
Returns true if the current selection has a mix of numeric formats.
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.
double tableRowHeight(int row)
Returns the configured row height for the specified row, or 0 if an automatic height should be used f...
QColor selectionBackgroundColor()
Returns the background color for the currently selected cells.
Qt::Alignment selectionVerticalAlignment()
Returns the horizontal alignment for the currently selected cells.
void insertRowsAbove()
Inserts new rows above the current selection.
void setTableColumnWidth(int column, double width)
Sets the configured column width for the specified column.
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 ...
double selectionColumnWidth()
Returns the width (in millimeters) of the columns associated with the current selection,...
void expandRowSelection()
Expands out the selection to include whole rows associated with the current selected cells.
double tableColumnWidth(int column)
Returns the configured column width for the specified column, or 0 if an automatic width should be us...
void setIncludeTableHeader(bool included)
Sets whether the table includes a header row.
QgsNumericFormat * selectionNumericFormat()
Returns the numeric format used for the currently selected cells, or nullptr if the selection has no ...
void setTableRowHeight(int row, double height)
Sets the configured row height for the specified row.
QgsTableContents tableContents() const
Returns the current contents of the editor widget table.
void deleteColumns()
Deletes all columns associated with the current selected cells.
void setTableContents(const QgsTableContents &contents)
Sets the contents to show in the editor widget.
void tableChanged()
Emitted whenever the table contents are changed.
void insertColumnsBefore()
Inserts new columns before the current selection.
void setSelectionNumericFormat(QgsNumericFormat *format)
Sets the numeric format to use for the currently selected cells.
void expandColumnSelection()
Expands out the selection to include whole columns associated with the current selected cells.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QVector< QgsTableRow > QgsTableContents
A set of table rows.
Definition: qgstablecell.h:220
QVector< QgsTableCell > QgsTableRow
A row of table cells.
Definition: qgstablecell.h:211