QGIS API Documentation  3.13.0-Master (740be229cb)
qgssubstitutionlistwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssubstitutionlistwidget.cpp
3  -----------------------------
4  begin : August 2016
5  copyright : (C) 2016 Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7 
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
21 #include "qgsgui.h"
22 
23 #include <QDialogButtonBox>
24 #include <QCheckBox>
25 #include <QFileDialog>
26 #include <QMessageBox>
27 #include <QTextStream>
28 
30  : QgsPanelWidget( parent )
31 {
32  setupUi( this );
34 
35  connect( mButtonAdd, &QToolButton::clicked, this, &QgsSubstitutionListWidget::mButtonAdd_clicked );
36  connect( mButtonRemove, &QToolButton::clicked, this, &QgsSubstitutionListWidget::mButtonRemove_clicked );
37  connect( mButtonExport, &QToolButton::clicked, this, &QgsSubstitutionListWidget::mButtonExport_clicked );
38  connect( mButtonImport, &QToolButton::clicked, this, &QgsSubstitutionListWidget::mButtonImport_clicked );
39  connect( mTableSubstitutions, &QTableWidget::cellChanged, this, &QgsSubstitutionListWidget::tableChanged );
40 }
41 
43 {
44  mTableSubstitutions->blockSignals( true );
45  mTableSubstitutions->clearContents();
46  const auto constReplacements = substitutions.replacements();
47  for ( const QgsStringReplacement &replacement : constReplacements )
48  {
49  addSubstitution( replacement );
50  }
51  mTableSubstitutions->blockSignals( false );
52 }
53 
55 {
56  QList< QgsStringReplacement > result;
57  for ( int i = 0; i < mTableSubstitutions->rowCount(); ++i )
58  {
59  if ( !mTableSubstitutions->item( i, 0 ) )
60  continue;
61 
62  if ( mTableSubstitutions->item( i, 0 )->text().isEmpty() )
63  continue;
64 
65  QCheckBox *chkCaseSensitive = qobject_cast<QCheckBox *>( mTableSubstitutions->cellWidget( i, 2 ) );
66  QCheckBox *chkWholeWord = qobject_cast<QCheckBox *>( mTableSubstitutions->cellWidget( i, 3 ) );
67 
68  QgsStringReplacement replacement( mTableSubstitutions->item( i, 0 )->text(),
69  mTableSubstitutions->item( i, 1 )->text(),
70  chkCaseSensitive->isChecked(),
71  chkWholeWord->isChecked() );
72  result << replacement;
73  }
74  return QgsStringReplacementCollection( result );
75 }
76 
77 void QgsSubstitutionListWidget::mButtonAdd_clicked()
78 {
79  addSubstitution( QgsStringReplacement( QString(), QString(), false, true ) );
80  mTableSubstitutions->setFocus();
81  mTableSubstitutions->setCurrentCell( mTableSubstitutions->rowCount() - 1, 0 );
82 }
83 
84 void QgsSubstitutionListWidget::mButtonRemove_clicked()
85 {
86  int currentRow = mTableSubstitutions->currentRow();
87  mTableSubstitutions->removeRow( currentRow );
88  tableChanged();
89 }
90 
91 void QgsSubstitutionListWidget::tableChanged()
92 {
94 }
95 
96 void QgsSubstitutionListWidget::mButtonExport_clicked()
97 {
98  QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Substitutions" ), QDir::homePath(),
99  tr( "XML files (*.xml *.XML)" ) );
100  if ( fileName.isEmpty() )
101  {
102  return;
103  }
104 
105  // ensure the user never omitted the extension from the file name
106  if ( !fileName.endsWith( QLatin1String( ".xml" ), Qt::CaseInsensitive ) )
107  {
108  fileName += QLatin1String( ".xml" );
109  }
110 
111  QDomDocument doc;
112  QDomElement root = doc.createElement( QStringLiteral( "substitutions" ) );
113  root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0" ) );
115  collection.writeXml( root, doc );
116  doc.appendChild( root );
117 
118  QFile file( fileName );
119  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
120  {
121  QMessageBox::warning( nullptr, tr( "Export Substitutions" ),
122  tr( "Cannot write file %1:\n%2" ).arg( fileName, file.errorString() ),
123  QMessageBox::Ok,
124  QMessageBox::Ok );
125  return;
126  }
127 
128  QTextStream out( &file );
129  doc.save( out, 4 );
130 }
131 
132 void QgsSubstitutionListWidget::mButtonImport_clicked()
133 {
134  QString fileName = QFileDialog::getOpenFileName( this, tr( "Load Substitutions" ), QDir::homePath(),
135  tr( "XML files (*.xml *.XML)" ) );
136  if ( fileName.isEmpty() )
137  {
138  return;
139  }
140 
141  QFile file( fileName );
142  if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
143  {
144  QMessageBox::warning( nullptr, tr( "Import Substitutions" ),
145  tr( "Cannot read file %1:\n%2" ).arg( fileName, file.errorString() ),
146  QMessageBox::Ok,
147  QMessageBox::Ok );
148  return;
149  }
150 
151  QDomDocument doc;
152  QString errorStr;
153  int errorLine;
154  int errorColumn;
155 
156  if ( !doc.setContent( &file, true, &errorStr, &errorLine, &errorColumn ) )
157  {
158  QMessageBox::warning( nullptr, tr( "Import substitutions" ),
159  tr( "Parse error at line %1, column %2:\n%3" )
160  .arg( errorLine )
161  .arg( errorColumn )
162  .arg( errorStr ),
163  QMessageBox::Ok,
164  QMessageBox::Ok );
165  return;
166  }
167 
168  QDomElement root = doc.documentElement();
169  if ( root.tagName() != QLatin1String( "substitutions" ) )
170  {
171  QMessageBox::warning( nullptr, tr( "Import Substitutions" ),
172  tr( "The selected file is not a substitution list." ),
173  QMessageBox::Ok,
174  QMessageBox::Ok );
175  return;
176  }
177 
179  collection.readXml( root );
180  setSubstitutions( collection );
181  tableChanged();
182 }
183 
184 void QgsSubstitutionListWidget::addSubstitution( const QgsStringReplacement &substitution )
185 {
186  int row = mTableSubstitutions->rowCount();
187  mTableSubstitutions->insertRow( row );
188 
189  Qt::ItemFlags itemFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable
190  | Qt::ItemIsEditable;
191 
192  QTableWidgetItem *matchItem = new QTableWidgetItem( substitution.match() );
193  matchItem->setFlags( itemFlags );
194  mTableSubstitutions->setItem( row, 0, matchItem );
195  QTableWidgetItem *replaceItem = new QTableWidgetItem( substitution.replacement() );
196  replaceItem->setFlags( itemFlags );
197  mTableSubstitutions->setItem( row, 1, replaceItem );
198 
199  QCheckBox *caseSensitiveChk = new QCheckBox( this );
200  caseSensitiveChk->setChecked( substitution.caseSensitive() );
201  mTableSubstitutions->setCellWidget( row, 2, caseSensitiveChk );
202  connect( caseSensitiveChk, &QAbstractButton::toggled, this, &QgsSubstitutionListWidget::tableChanged );
203 
204  QCheckBox *wholeWordChk = new QCheckBox( this );
205  wholeWordChk->setChecked( substitution.wholeWordOnly() );
206  mTableSubstitutions->setCellWidget( row, 3, wholeWordChk );
207  connect( wholeWordChk, &QAbstractButton::toggled, this, &QgsSubstitutionListWidget::tableChanged );
208 }
209 
210 
211 //
212 // QgsSubstitutionListDialog
213 //
214 
215 
217  : QDialog( parent )
218 
219 {
220  setWindowTitle( tr( "Substitutions" ) );
221  QVBoxLayout *vLayout = new QVBoxLayout();
222  mWidget = new QgsSubstitutionListWidget();
223  vLayout->addWidget( mWidget );
224  QDialogButtonBox *bbox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal );
225  connect( bbox, &QDialogButtonBox::accepted, this, &QDialog::accept );
226  connect( bbox, &QDialogButtonBox::rejected, this, &QDialog::reject );
227  vLayout->addWidget( bbox );
228  setLayout( vLayout );
229 }
230 
232 {
233  mWidget->setSubstitutions( substitutions );
234 }
235 
237 {
238  return mWidget->substitutions();
239 }
QgsStringReplacementCollection substitutions() const
Returns the list of substitutions currently defined by the widget.
void setSubstitutions(const QgsStringReplacementCollection &substitutions)
Sets the list of substitutions to show in the widget.
A representation of a single string replacement.
bool caseSensitive() const
Returns true if match is case sensitive.
Base class for any widget that can be shown as a inline panel.
void writeXml(QDomElement &elem, QDomDocument &doc) const
Writes the collection state to an XML element.
QgsStringReplacementCollection substitutions
QList< QgsStringReplacement > replacements() const
Returns the list of string replacements in this collection.
QString match() const
Returns the string matched by this object.
QString replacement() const
Returns the string to replace matches with.
QgsSubstitutionListDialog(QWidget *parent=nullptr)
Constructor for QgsSubstitutionListDialog.
A widget which allows users to specify a list of substitutions to apply to a string, with options for exporting and importing substitution lists.
QgsSubstitutionListWidget(QWidget *parent=nullptr)
Constructor for QgsSubstitutionListWidget.
void substitutionsChanged(const QgsStringReplacementCollection &substitutions)
Emitted when the substitution definitions change.
bool wholeWordOnly() const
Returns true if match only applies to whole words, or false if partial word matches are permitted...
A collection of string replacements (specified using QgsStringReplacement objects).
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:133
void setSubstitutions(const QgsStringReplacementCollection &substitutions)
Sets the list of substitutions to show in the dialog.
void readXml(const QDomElement &elem)
Reads the collection state from an XML element.
QgsStringReplacementCollection substitutions() const
Returns the list of substitutions currently defined by the dialog.