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