diff options
Diffstat (limited to 'src/export-import')
-rw-r--r-- | src/export-import/CsvData.h | 36 | ||||
-rw-r--r-- | src/export-import/CsvDialog.cpp | 176 | ||||
-rw-r--r-- | src/export-import/CsvDialog.h | 62 | ||||
-rw-r--r-- | src/export-import/CsvExportDialog.cpp | 137 | ||||
-rw-r--r-- | src/export-import/CsvExportDialog.h | 52 | ||||
-rw-r--r-- | src/export-import/CsvImportDialog.cpp | 155 | ||||
-rw-r--r-- | src/export-import/CsvImportDialog.h | 64 |
7 files changed, 682 insertions, 0 deletions
diff --git a/src/export-import/CsvData.h b/src/export-import/CsvData.h new file mode 100644 index 0000000..c6ea9ad --- /dev/null +++ b/src/export-import/CsvData.h @@ -0,0 +1,36 @@ +#ifndef CSVDATA_H +#define CSVDATA_H + +#include <QtCore> + +enum FieldSeparationMode +{ + EFieldSeparatorAnyCharacter = 0, + EFieldSeparatorAnyCombination, + EFieldSeparatorExactString +}; + +struct CsvParams +{ + QString fieldSeparators; + QChar textDelimiter; + QChar commentChar; +}; + +struct CsvImportData: public CsvParams +{ + QTextCodec* textCodec; + int fromLine; + bool firstLineIsHeader; + FieldSeparationMode fieldSeparationMode; + int colsToImport; // 0 = All columns +}; + +struct CsvExportData: public CsvParams +{ + QList<int> usedCols; // Empty = use all columns + bool quoteAllFields; + bool writeColumnNames; +}; + +#endif diff --git a/src/export-import/CsvDialog.cpp b/src/export-import/CsvDialog.cpp new file mode 100644 index 0000000..b19d029 --- /dev/null +++ b/src/export-import/CsvDialog.cpp @@ -0,0 +1,176 @@ +#include "CsvDialog.h" + +QChar CsvDialog::SpaceChar(0x2423); +QChar CsvDialog::TabChar(0x21A6); +QString CsvDialog::ExtendedTab(QString(QChar(0x21A6)) + "\t"); + +CsvDialog::CsvDialog(QWidget* parent): + QDialog(parent) +{ + resize(600, 550); +} + +void CsvDialog::init() +{ + setLayout(createMainLayout()); + updatePreview(); + connectControlsToPreview(); +} + +void CsvDialog::connectControlsToPreview() +{ + connect(separatorsEdit, SIGNAL(textChanged(QString)), SLOT(updatePreview()) ); + connect(textDelimiterCB, SIGNAL(stateChanged(int)), SLOT(updatePreview()) ); + connect(textDelimiterCombo, SIGNAL(editTextChanged(QString)), SLOT(updatePreview()) ); + connect(commentCharCombo, SIGNAL(editTextChanged(QString)), SLOT(updatePreview()) ); +} + +QLayout* CsvDialog::createMainLayout() +{ + QVBoxLayout* lt = new QVBoxLayout; + lt->addLayout(createTopLayout()); + lt->addWidget(new QLabel(tr("Preview:"))); + lt->addLayout(createPreviewLt()); + lt->addWidget(createButtonBox()); + return lt; +} + +QLayout* CsvDialog::createTopLayout() +{ + QHBoxLayout* lt = new QHBoxLayout; + lt->addWidget(createLeftGroup()); + lt->addWidget(createSeparatorsGroup()); + return lt; +} + +QWidget* CsvDialog::createCharSetCombo() +{ + charSetCombo = new QComboBox; + charSetCombo->setEditable(false); + QList<QByteArray> codecNames = QTextCodec::availableCodecs(); + qSort( codecNames ); + for( int i=0; i<codecNames.size(); i++) + charSetCombo->addItem(codecNames[i], + QTextCodec::codecForName(codecNames[i] )->mibEnum()); + int utf8Ix = codecNames.indexOf( "UTF-8" ); + charSetCombo->setCurrentIndex( utf8Ix ); + return charSetCombo; +} + +QGroupBox* CsvDialog::createLeftGroup() +{ + QGroupBox* group = new QGroupBox(getLeftGroupTitle()); + group->setLayout(createLeftGroupLayout()); + return group; +} + +QGroupBox* CsvDialog::createSeparatorsGroup() +{ + QGroupBox* group = new QGroupBox(tr("Separators")); + group->setLayout(createSeparatorsLayout()); + return group; +} + +QDialogButtonBox* CsvDialog::createButtonBox() +{ + QDialogButtonBox* buttonBox = new QDialogButtonBox( + QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); + return buttonBox; +} + +QWidget* CsvDialog::createFieldSeparatorWidget(const QString& additionalSeparators) +{ + separatorsEdit = new QLineEdit(QString(TabChar) + "&" + additionalSeparators); + connect(separatorsEdit, SIGNAL(textChanged(const QString&)), + SLOT(showInvisibleInSeparatorsEdit())); + + QPushButton* addSeparatorBtn = new QPushButton(tr("Ta&b")); + addSeparatorBtn->setMinimumWidth(40); + connect(addSeparatorBtn, SIGNAL(clicked()), SLOT(insertTabToSeparators())); + + QHBoxLayout* lt = new QHBoxLayout; + lt->addWidget(separatorsEdit); + lt->addWidget(addSeparatorBtn); + lt->setContentsMargins(QMargins()); + + // Workaround for a bug in QFormLayout::addRow(text, layout) + QWidget* widget = new QWidget; + widget->setLayout(lt); + return widget; +} + +QWidget* CsvDialog::createTextDelimiterBox() +{ + textDelimiterCB = new QCheckBox(tr("&Text delimiter:")); + textDelimiterCB->setChecked(true); + return textDelimiterCB; +} + +QWidget* CsvDialog::createTextDelimiterCombo() +{ + return textDelimiterCombo = createEditableCombo(QStringList() << "\"" << "\'"); +} + +QWidget* CsvDialog::createCommentCharCombo() +{ + return commentCharCombo = createEditableCombo(QStringList() << "#" << ";"); +} + +QComboBox* CsvDialog::createEditableCombo(const QStringList& items) +{ + QComboBox* combo = new QComboBox; + combo->setEditable(true); + combo->setInsertPolicy(QComboBox::NoInsert); + combo->setValidator(new QRegExpValidator(QRegExp("\\S{1}"), this)); + combo->addItems(items); + return combo; +} + +QChar CsvDialog::getTextDelimiterChar() const +{ + if(textDelimiterCB->isChecked() && !textDelimiterCombo->currentText().isEmpty()) + return textDelimiterCombo->currentText()[0]; + else + return QChar(0); +} + +void CsvDialog::showInvisibleInSeparatorsEdit() +{ + separatorsEdit->setText(setCharVisibility(separatorsEdit->text(), true)); +} + +void CsvDialog::insertTabToSeparators() +{ + separatorsEdit->insert(TabChar); +} + +QTextCodec* CsvDialog::getTextCodec() +{ + return QTextCodec::codecForMib( + charSetCombo->itemData(charSetCombo->currentIndex()).toInt()); +} + +/// Convert invisible chars like space and tab to visible equivalents or vice versa. +QString CsvDialog::setCharVisibility(const QString& input, bool visible) +{ + QString res = input; + if(visible) + { + res.replace(' ', SpaceChar); + res.replace('\t', ExtendedTab); + } + else + { + res.replace(SpaceChar, ' '); + res.replace(ExtendedTab, "\t"); + res.replace(TabChar, '\t'); + } + return res; +} + +void CsvDialog::updateTextDelimiterCombo() +{ + textDelimiterCombo->setEnabled( textDelimiterCB->isChecked() ); +} diff --git a/src/export-import/CsvDialog.h b/src/export-import/CsvDialog.h new file mode 100644 index 0000000..f50cd62 --- /dev/null +++ b/src/export-import/CsvDialog.h @@ -0,0 +1,62 @@ +#ifndef CSV_DIALOG_H +#define CSV_DIALOG_H + +#include <QtCore> +#include <QtWidgets> + +class CsvDialog: public QDialog +{ + Q_OBJECT + +public: + CsvDialog(QWidget* parent); + +protected: + static QString setCharVisibility(const QString& input, bool visible); + +protected: + void init(); + virtual QLayout* createLeftGroupLayout() = 0; + virtual QString getLeftGroupTitle() = 0; + QWidget* createCharSetCombo(); + virtual QLayout* createSeparatorsLayout() = 0; + QWidget* createFieldSeparatorWidget(const QString& additionalSeparators = ""); + QWidget* createTextDelimiterBox(); + QWidget* createTextDelimiterCombo(); + QWidget* createCommentCharCombo(); + QComboBox* createEditableCombo(const QStringList& items); + virtual QLayout* createPreviewLt() = 0; + QDialogButtonBox* createButtonBox(); + QTextCodec* getTextCodec(); + QChar getTextDelimiterChar() const; + +protected slots: + virtual void updatePreview() = 0; + void updateTextDelimiterCombo(); + +private: + QLayout* createMainLayout(); + void connectControlsToPreview(); + QLayout* createTopLayout(); + QGroupBox* createLeftGroup(); + QGroupBox* createSeparatorsGroup(); + void doUpdatePreview() { updatePreview(); } + +private slots: + void showInvisibleInSeparatorsEdit(); + void insertTabToSeparators(); + +protected: + static QChar SpaceChar; + static QChar TabChar; + static QString ExtendedTab; + +protected: + QComboBox* charSetCombo; + QLineEdit* separatorsEdit; + QCheckBox* textDelimiterCB; + QComboBox* textDelimiterCombo; + QComboBox* commentCharCombo; +}; + +#endif diff --git a/src/export-import/CsvExportDialog.cpp b/src/export-import/CsvExportDialog.cpp new file mode 100644 index 0000000..9e4dc90 --- /dev/null +++ b/src/export-import/CsvExportDialog.cpp @@ -0,0 +1,137 @@ +#include "CsvExportDialog.h" + +#include "../strings.h" +#include "../dictionary/Dictionary.h" +#include "../dictionary/DicCsvWriter.h" + +CsvExportDialog::CsvExportDialog(QWidget* parent, const Dictionary* dict): + CsvDialog(parent), + dictionary(dict), + dicWriter(new DicCsvWriter(dict)) +{ + init(); + setWindowTitle(tr("Export to CSV")); + + connect( textDelimiterCB, SIGNAL(stateChanged(int)), this, SLOT(updateTextDelimiterCombo()) ); + connect( showInvisibleCharsCB, SIGNAL(stateChanged(int)), this, SLOT(UpdateCharVisibility()) ); + connect( textDelimiterCB, SIGNAL(stateChanged(int)), this, SLOT(UpdateQuoteAllFieldsCB()) ); + + connect( usedColsEdit, SIGNAL(textChanged(QString)), this, SLOT(updatePreview()) ); + connect( quoteAllFieldsCB, SIGNAL(stateChanged(int)), this, SLOT(updatePreview()) ); + connect( writeColumnNamesCB, SIGNAL(stateChanged(int)), this, SLOT(updatePreview()) ); +} + +CsvExportDialog::~CsvExportDialog() +{ + delete dicWriter; +} + +QLayout* CsvExportDialog::createLeftGroupLayout() +{ + QFormLayout* lt = new QFormLayout; + lt->addRow(tr("C&haracter set:"), createCharSetCombo()); + lt->addRow(tr("Used &columns:"), createUsedColsEdit()); + lt->addRow(createWriteColumnNamesBox()); + return lt; +} + +QWidget* CsvExportDialog::createUsedColsEdit() +{ + usedColsEdit = new QLineEdit("123"); + usedColsEdit->setValidator(new QRegExpValidator(QRegExp("[1-9]+"), this)); + return usedColsEdit; +} + +QWidget* CsvExportDialog::createWriteColumnNamesBox() +{ + writeColumnNamesCB = new QCheckBox(tr("Write column &names")); + writeColumnNamesCB->setChecked( true ); + return writeColumnNamesCB; +} + +QLayout* CsvExportDialog::createSeparatorsLayout() +{ + quoteAllFieldsCB = new QCheckBox(tr("&Quote all fields")); + + QFormLayout* lt = new QFormLayout; + lt->addRow(tr("Field &separator:"), createFieldSeparatorWidget(SpaceChar)); + lt->addRow(createTextDelimiterBox(), createTextDelimiterCombo()); + lt->addRow(quoteAllFieldsCB); + lt->addRow(tr("Co&mment character:"), createCommentCharCombo()); + return lt; +} + +QLayout* CsvExportDialog::createPreviewLt() +{ + QVBoxLayout* lt = new QVBoxLayout; + lt->addWidget(createPreview()); + lt->addWidget(createShowInvisibleBox()); + return lt; +} + +QWidget* CsvExportDialog::createPreview() +{ + csvPreview = new QTextEdit; + csvPreview->setReadOnly(true); + csvPreview->setLineWrapMode( QTextEdit::NoWrap ); + csvPreview->setFontPointSize( 10 ); + return csvPreview; +} + +QCheckBox* CsvExportDialog::createShowInvisibleBox() +{ + showInvisibleCharsCB = new QCheckBox(tr("Show &invisible characters")); + showInvisibleCharsCB->setChecked( false ); + return showInvisibleCharsCB; +} + +void CsvExportDialog::UpdateQuoteAllFieldsCB() +{ + quoteAllFieldsCB->setEnabled( textDelimiterCB->isChecked() ); +} + +void CsvExportDialog::updatePreview() +{ + CsvExportData params; + params.usedCols = getUsedColumns(); + params.fieldSeparators = setCharVisibility( separatorsEdit->text(), false ); + params.textDelimiter = getTextDelimiterChar(); + params.quoteAllFields = quoteAllFieldsCB->isChecked(); + params.commentChar = commentCharCombo->currentText()[0]; + params.writeColumnNames = writeColumnNamesCB->isChecked(); + + QString csvString = dicWriter->toCsvString( params ); + csvPreview->setPlainText( + setCharVisibility(csvString, showInvisibleCharsCB->isChecked())); +} + +QList<int> CsvExportDialog::getUsedColumns() +{ + QList<int> res; + for(int i = 0; i < usedColsEdit->text().length(); i++) + { + int col = usedColsEdit->text()[i].digitValue(); + if(col > 0 && col <= dictionary->fieldsNum()) + res << col - 1; + } + return res; +} + +void CsvExportDialog::SaveCSVToFile( const QString& aFilePath ) +{ + QFile file( aFilePath ); + if( !file.open( QIODevice::WriteOnly | QFile::Text ) ) // \r\n --> \n + { + QMessageBox::warning( this, Strings::errorTitle(), tr("Cannot save to file:\n %1.").arg(aFilePath) ); + return; + } + QTextStream outStream( &file ); + outStream.setCodec( getTextCodec() ); + outStream << setCharVisibility( csvPreview->toPlainText(), false ); +} + +void CsvExportDialog::UpdateCharVisibility() +{ + csvPreview->setPlainText( + setCharVisibility(csvPreview->toPlainText(), showInvisibleCharsCB->isChecked()) ); +} diff --git a/src/export-import/CsvExportDialog.h b/src/export-import/CsvExportDialog.h new file mode 100644 index 0000000..d99c421 --- /dev/null +++ b/src/export-import/CsvExportDialog.h @@ -0,0 +1,52 @@ +#ifndef CSVEXPORTDIALOG_H +#define CSVEXPORTDIALOG_H + +#include <QtCore> +#include <QtWidgets> + +#include "CsvDialog.h" + +class Dictionary; +class DicCsvWriter; + +class CsvExportDialog: public CsvDialog +{ + Q_OBJECT + +public: + CsvExportDialog(QWidget* parent, const Dictionary* dict ); + ~CsvExportDialog(); + + void SaveCSVToFile( const QString& aFilePath ); + +protected: + QLayout* createLeftGroupLayout(); + QString getLeftGroupTitle() { return tr("Output"); } + QLayout* createSeparatorsLayout(); + QLayout* createPreviewLt(); + +protected slots: + void updatePreview(); + +private slots: + void UpdateQuoteAllFieldsCB(); + void UpdateCharVisibility(); + +private: + QWidget* createUsedColsEdit(); + QWidget* createWriteColumnNamesBox(); + QList<int> getUsedColumns(); + QWidget* createPreview(); + QCheckBox* createShowInvisibleBox(); + +private: + const Dictionary* dictionary; // not own, created here + DicCsvWriter* dicWriter; + QLineEdit* usedColsEdit; + QCheckBox* writeColumnNamesCB; + QCheckBox* quoteAllFieldsCB; + QTextEdit* csvPreview; + QCheckBox* showInvisibleCharsCB; +}; + +#endif diff --git a/src/export-import/CsvImportDialog.cpp b/src/export-import/CsvImportDialog.cpp new file mode 100644 index 0000000..51c3c87 --- /dev/null +++ b/src/export-import/CsvImportDialog.cpp @@ -0,0 +1,155 @@ +#include "CsvImportDialog.h" + +#include "../main-view/DictTableView.h" +#include "../main-view/DictTableModel.h" +#include "../dictionary/Dictionary.h" +#include "../dictionary/DicCsvReader.h" + +CsvImportDialog::CsvImportDialog(QWidget* parent, QString filePath, const AppModel* appModel): + CsvDialog(parent), + filePath(filePath), + dictionary(NULL), + appModel(appModel) +{ + init(); + setWindowTitle(tr("Import from CSV")); + + connect( textDelimiterCB, SIGNAL(stateChanged(int)), this, SLOT(updateTextDelimiterCombo()) ); + connect( commentCharCB, SIGNAL(stateChanged(int)), this, SLOT(UpdateCommentCharacterCombo()) ); + connect( this, SIGNAL(rejected()), this, SLOT(DeleteDictionary()) ); + + connect( charSetCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()) ); + connect( fromLineSpin, SIGNAL(valueChanged(int)), this, SLOT(updatePreview()) ); + connect( firstLineIsHeaderCB, SIGNAL(stateChanged(int)), this, SLOT(updatePreview()) ); + connect( anyCharacterRB, SIGNAL(toggled(bool)), this, SLOT(updatePreview()) ); + connect( anyCombinationRB, SIGNAL(toggled(bool)), this, SLOT(updatePreview()) ); + connect( exactStringRB, SIGNAL(toggled(bool)), this, SLOT(updatePreview()) ); + connect( commentCharCB, SIGNAL(stateChanged(int)), this, SLOT(updatePreview()) ); + connect( colsToImportSpin, SIGNAL(valueChanged(int)), this, SLOT(updatePreview()) ); +} + +CsvImportDialog::~CsvImportDialog() +{ + delete iPreviewModel; + delete dicReader; +} + +QLayout* CsvImportDialog::createLeftGroupLayout() +{ + QFormLayout* lt = new QFormLayout; + lt->addRow(tr("C&haracter set:"), createCharSetCombo()); + lt->addRow(tr("From &line:"), createFromLineSpin()); + lt->addRow(tr("Number of colum&ns:"), createColsToImportSpin()); + lt->addRow(createFirstLineIsHeaderCB()); + return lt; +} + +QWidget* CsvImportDialog::createFromLineSpin() +{ + fromLineSpin = new QSpinBox(); + fromLineSpin->setRange(1, 100); + return fromLineSpin; +} + +QWidget* CsvImportDialog::createColsToImportSpin() +{ + colsToImportSpin = new QSpinBox(); + colsToImportSpin->setRange(0, 9); + colsToImportSpin->setSpecialValueText(tr("All")); + return colsToImportSpin; +} + +QWidget* CsvImportDialog::createFirstLineIsHeaderCB() +{ + firstLineIsHeaderCB = new QCheckBox(tr("&First line has field names")); + firstLineIsHeaderCB->setChecked(false); + return firstLineIsHeaderCB; +} + +QLayout* CsvImportDialog::createSeparatorsLayout() +{ + createSeparationRadioButtons(); + + QFormLayout* lt = new QFormLayout; + lt->addRow(tr("Field &separator:"), + createFieldSeparatorWidget()); + lt->addRow(tr("Separation mode:"), anyCharacterRB); + // The label is a workaround to make enough space for the radio button text + lt->addRow(" ", anyCombinationRB); + lt->addRow(NULL, exactStringRB); + lt->addRow(createTextDelimiterBox(), createTextDelimiterCombo()); + lt->addRow(createCommentCharBox(), createCommentCharCombo()); + return lt; +} + +void CsvImportDialog::createSeparationRadioButtons() +{ + anyCharacterRB = new QRadioButton(tr("An&y character")); + anyCharacterRB->setToolTip(tr("Fields are separated by any separator character")); + anyCombinationRB = new QRadioButton(tr("A co&mbination of characters")); + anyCombinationRB->setToolTip(tr("Fields are separated by a combination of separator characters, in any order")); + anyCombinationRB->setChecked( true ); + exactStringRB = new QRadioButton(tr("E&xact string")); + exactStringRB->setToolTip(tr("Fields are separated by the exact string of separators, in the above defined order")); +} + +QWidget* CsvImportDialog::createCommentCharBox() +{ + commentCharCB = new QCheckBox(tr("&Comment character:")); + commentCharCB->setChecked(true); + return commentCharCB; +} + +QLayout* CsvImportDialog::createPreviewLt() +{ + QVBoxLayout* lt = new QVBoxLayout; + lt->addWidget(createPreview()); + return lt; +} + +QWidget* CsvImportDialog::createPreview() +{ + dictionary = new Dictionary( filePath + Dictionary::DictFileExtension, true, appModel ); + dicReader = new DicCsvReader( dictionary ); + iPreviewModel = new DictTableModel( dictionary ); + previewTable = new DictTableView(iPreviewModel); + return previewTable; +} + +void CsvImportDialog::UpdateCommentCharacterCombo() +{ + commentCharCombo->setEnabled( commentCharCB->isChecked() ); +} + +void CsvImportDialog::updatePreview() +{ + CsvImportData params; + params.textCodec = getTextCodec(); + params.fromLine = fromLineSpin->value(); + params.fieldSeparators = setCharVisibility(separatorsEdit->text(), false); + params.fieldSeparationMode = getSeparationMode(); + params.commentChar = commentCharCB->isChecked()? + commentCharCombo->currentText()[0]: QChar(0); + params.textDelimiter = getTextDelimiterChar(); + params.colsToImport = colsToImportSpin->value(); + params.firstLineIsHeader = firstLineIsHeaderCB->isChecked(); + + dicReader->readDict( filePath, params ); + iPreviewModel->resetData(); +} + +FieldSeparationMode CsvImportDialog::getSeparationMode() +{ + if(anyCharacterRB->isChecked()) + return EFieldSeparatorAnyCharacter; + else if (anyCombinationRB->isChecked()) + return EFieldSeparatorAnyCombination; + else + return EFieldSeparatorExactString; +} + +void CsvImportDialog::DeleteDictionary() +{ +delete dictionary; +dictionary = NULL; +} diff --git a/src/export-import/CsvImportDialog.h b/src/export-import/CsvImportDialog.h new file mode 100644 index 0000000..bc3a9d1 --- /dev/null +++ b/src/export-import/CsvImportDialog.h @@ -0,0 +1,64 @@ +#ifndef CSVIMPORTDIALOG_H +#define CSVIMPORTDIALOG_H + +#include <QtCore> +#include <QtWidgets> + +#include "CsvData.h" +#include "CsvDialog.h" + +class DictTableView; +class Dictionary; +class DicCsvReader; +class DictTableModel; +class AppModel; + +class CsvImportDialog: public CsvDialog +{ + Q_OBJECT + +public: + CsvImportDialog(QWidget* parent, QString filePath, const AppModel* appModel ); + ~CsvImportDialog(); + + Dictionary* getDictionary() { return dictionary; } + +protected: + QLayout* createLeftGroupLayout(); + QString getLeftGroupTitle() { return tr("Input"); } + QLayout* createSeparatorsLayout(); + QLayout* createPreviewLt(); + +protected slots: + void updatePreview(); + +private slots: + void UpdateCommentCharacterCombo(); + void DeleteDictionary(); + +private: + QWidget* createFromLineSpin(); + QWidget* createColsToImportSpin(); + QWidget* createFirstLineIsHeaderCB(); + void createSeparationRadioButtons(); + FieldSeparationMode getSeparationMode(); + QWidget* createCommentCharBox(); + QWidget* createPreview(); + +private: + QString filePath; + Dictionary* dictionary; // not own, created here + const AppModel* appModel; + DicCsvReader* dicReader; + DictTableModel* iPreviewModel; + QSpinBox* fromLineSpin; // 1-based + QSpinBox* colsToImportSpin; // 1-based; 0 = all + QCheckBox* firstLineIsHeaderCB; + QRadioButton* anyCharacterRB; + QRadioButton* anyCombinationRB; + QRadioButton* exactStringRB; + QCheckBox* commentCharCB; + DictTableView* previewTable; +}; + +#endif |