diff options
Diffstat (limited to 'Plugins/RegExpImport')
| -rw-r--r-- | Plugins/RegExpImport/RegExpImport.pro | 28 | ||||
| -rw-r--r-- | Plugins/RegExpImport/regexpimport.cpp | 209 | ||||
| -rw-r--r-- | Plugins/RegExpImport/regexpimport.h | 52 | ||||
| -rw-r--r-- | Plugins/RegExpImport/regexpimport.json | 7 | ||||
| -rw-r--r-- | Plugins/RegExpImport/regexpimport.qrc | 5 | ||||
| -rw-r--r-- | Plugins/RegExpImport/regexpimport.ui | 99 | ||||
| -rw-r--r-- | Plugins/RegExpImport/regexpimport_global.h | 12 |
7 files changed, 412 insertions, 0 deletions
diff --git a/Plugins/RegExpImport/RegExpImport.pro b/Plugins/RegExpImport/RegExpImport.pro new file mode 100644 index 0000000..99c884e --- /dev/null +++ b/Plugins/RegExpImport/RegExpImport.pro @@ -0,0 +1,28 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-07-20T12:19:38 +# +#------------------------------------------------- + +include($$PWD/../../SQLiteStudio3/plugins.pri) + +QT -= gui + +TARGET = RegExpImport +TEMPLATE = lib + +DEFINES += REGEXPIMPORT_LIBRARY + +SOURCES += regexpimport.cpp + +HEADERS += regexpimport.h\ + regexpimport_global.h + +OTHER_FILES += \ + regexpimport.json + +FORMS += \ + regexpimport.ui + +RESOURCES += \ + regexpimport.qrc diff --git a/Plugins/RegExpImport/regexpimport.cpp b/Plugins/RegExpImport/regexpimport.cpp new file mode 100644 index 0000000..cd761b1 --- /dev/null +++ b/Plugins/RegExpImport/regexpimport.cpp @@ -0,0 +1,209 @@ +#include "regexpimport.h" +#include "services/notifymanager.h" +#include "common/utils.h" +#include "services/importmanager.h" +#include "sqlitestudio.h" +#include <QRegularExpression> +#include <QFile> +#include <QTextStream> + +RegExpImport::RegExpImport() +{ +} + +bool RegExpImport::init() +{ + Q_INIT_RESOURCE(regexpimport); + return GenericPlugin::init(); +} + +void RegExpImport::deinit() +{ + Q_CLEANUP_RESOURCE(regexpimport); +} + +QString RegExpImport::getDataSourceTypeName() const +{ + return "RegExp"; +} + +ImportManager::StandardConfigFlags RegExpImport::standardOptionsToEnable() const +{ + return ImportManager::CODEC|ImportManager::FILE_NAME; +} + +QString RegExpImport::getFileFilter() const +{ + return tr("Text files (*.txt);;All files (*)"); +} + +bool RegExpImport::beforeImport(const ImportManager::StandardImportConfig& config) +{ + safe_delete(re); + safe_delete(file); + safe_delete(stream); + groups.clear(); + buffer.clear(); + columns.clear(); + + + file = new QFile(config.inputFileName); + if (!file->open(QFile::ReadOnly) || !file->isReadable()) + { + notifyError(tr("Cannot read file %1").arg(config.inputFileName)); + safe_delete(file); + return false; + } + + stream = new QTextStream(file); + stream->setCodec(config.codec.toLatin1().data()); + + + static const QString intColTemplate = QStringLiteral("column%1"); + re = new QRegularExpression(cfg.RegExpImport.Pattern.get()); + QString colName; + if (cfg.RegExpImport.GroupsMode.get() == "all") + { + for (int i = 1; i <= re->captureCount(); i++) + { + groups << i; + colName = intColTemplate.arg(i); + columns << generateUniqueName(colName, columns); + } + } + else + { + QStringList entries = cfg.RegExpImport.CustomGroupList.get().split(QRegularExpression(",\\s*")); + int i; + bool ok; + for (const QString& entry : entries) + { + i = entry.toInt(&ok); + if (ok) + { + groups << i; + colName = intColTemplate.arg(i); + } + else + { + groups << entry; + colName = entry; + } + columns << generateUniqueName(colName, columns); + } + } + return true; +} + +void RegExpImport::afterImport() +{ + safe_delete(re); + safe_delete(file); + safe_delete(stream); + buffer.clear(); + groups.clear(); +} + +QList<ImportPlugin::ColumnDefinition> RegExpImport::getColumns() const +{ + QList<ImportPlugin::ColumnDefinition> columnList; + for (const QString& colName : columns) + columnList << ImportPlugin::ColumnDefinition(colName, QString()); + + return columnList; +} + +QList<QVariant> RegExpImport::next() +{ + QRegularExpressionMatch match = re->match(buffer); + QString line; + while (!match.hasMatch() && !(line = stream->readLine()).isNull()) + { + buffer += line; + match = re->match(buffer); + } + + if (!match.hasMatch()) + return QList<QVariant>(); + + QList<QVariant> values; + for (const QVariant& group : groups) + { + if (group.type() == QVariant::Int) + values << match.captured(group.toInt()); + else + values << match.captured(group.toString()); + } + + buffer = buffer.mid(match.capturedEnd()); + + return values; +} + +CfgMain* RegExpImport::getConfig() +{ + return &cfg; +} + +QString RegExpImport::getImportConfigFormName() const +{ + return "RegExpImportConfig"; +} + +bool RegExpImport::validateOptions() +{ + QString reMsg; + QString pattern = cfg.RegExpImport.Pattern.get(); + bool reOk = true; + if (pattern.isEmpty()) + { + reOk = false; + reMsg = tr("Enter the regular expression pattern."); + } + + QRegularExpression localRe(pattern); + if (reOk) + { + reOk &= localRe.isValid(); + if (!reOk) + reMsg = tr("Invalid pattern: %1").arg(localRe.errorString()); + } + + QString groupMsg; + bool groupsOk = true; + bool isCustom = (cfg.RegExpImport.GroupsMode.get() == "custom"); + if (isCustom && reOk) + { + QStringList entries = cfg.RegExpImport.CustomGroupList.get().split(QRegularExpression(",\\s*")); + QStringList namedCaptureGroups = localRe.namedCaptureGroups(); + int captureCount = localRe.captureCount(); + int i; + bool ok; + for (const QString& entry : entries) + { + i = entry.toInt(&ok); + if (ok) + { + if (i < 0 || i > captureCount) + { + groupMsg = tr("Requested capture index %1 is out of range.").arg(i); + groupsOk = false; + break; + } + } + else if (!namedCaptureGroups.contains(entry)) + { + groupMsg = tr("<p>Requested capture group name '%1', but it's not defined in the pattern: <pre>%2</pre></p>") + .arg(entry, pattern.toHtmlEscaped()); + groupsOk = false; + break; + } + } + } + + IMPORT_MANAGER->handleValidationFromPlugin(reOk, cfg.RegExpImport.Pattern, reMsg); + IMPORT_MANAGER->handleValidationFromPlugin(groupsOk, cfg.RegExpImport.CustomGroupList, groupMsg); + IMPORT_MANAGER->updateVisibilityAndEnabled(cfg.RegExpImport.CustomGroupList, true, isCustom); + + return reOk && groupsOk; +} diff --git a/Plugins/RegExpImport/regexpimport.h b/Plugins/RegExpImport/regexpimport.h new file mode 100644 index 0000000..3603401 --- /dev/null +++ b/Plugins/RegExpImport/regexpimport.h @@ -0,0 +1,52 @@ +#ifndef REGEXPIMPORT_H +#define REGEXPIMPORT_H + +#include "regexpimport_global.h" +#include "plugins/genericplugin.h" +#include "plugins/importplugin.h" +#include "config_builder.h" + +class QRegularExpression; +class QFile; +class QTextStream; + +CFG_CATEGORIES(RegExpImportConfig, + CFG_CATEGORY(RegExpImport, + CFG_ENTRY(QString, Pattern, QString()) + CFG_ENTRY(QString, GroupsMode, "all") // all / custom + CFG_ENTRY(QString, CustomGroupList, QString()) + ) +) + +class REGEXPIMPORTSHARED_EXPORT RegExpImport : public GenericPlugin, public ImportPlugin +{ + Q_OBJECT + SQLITESTUDIO_PLUGIN("regexpimport.json") + + public: + RegExpImport(); + + bool init(); + void deinit(); + QString getDataSourceTypeName() const; + ImportManager::StandardConfigFlags standardOptionsToEnable() const; + QString getFileFilter() const; + bool beforeImport(const ImportManager::StandardImportConfig& config); + void afterImport(); + QList<ColumnDefinition> getColumns() const; + QList<QVariant> next(); + CfgMain* getConfig(); + QString getImportConfigFormName() const; + bool validateOptions(); + + private: + CFG_LOCAL(RegExpImportConfig, cfg) + QRegularExpression* re = nullptr; + QList<QVariant> groups; + QStringList columns; + QFile* file = nullptr; + QTextStream* stream = nullptr; + QString buffer; +}; + +#endif // REGEXPIMPORT_H diff --git a/Plugins/RegExpImport/regexpimport.json b/Plugins/RegExpImport/regexpimport.json new file mode 100644 index 0000000..8a0f746 --- /dev/null +++ b/Plugins/RegExpImport/regexpimport.json @@ -0,0 +1,7 @@ +{ + "type": "ImportPlugin", + "title": "RegExp import", + "description": "Importing data from text files using regular expression.", + "version": 10000, + "author": "SalSoft" +} diff --git a/Plugins/RegExpImport/regexpimport.qrc b/Plugins/RegExpImport/regexpimport.qrc new file mode 100644 index 0000000..9ece86e --- /dev/null +++ b/Plugins/RegExpImport/regexpimport.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/forms"> + <file>regexpimport.ui</file> + </qresource> +</RCC> diff --git a/Plugins/RegExpImport/regexpimport.ui b/Plugins/RegExpImport/regexpimport.ui new file mode 100644 index 0000000..d1287cb --- /dev/null +++ b/Plugins/RegExpImport/regexpimport.ui @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>RegExpImportConfig</class> + <widget class="QWidget" name="RegExpImportConfig"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>133</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0" colspan="2"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Capture groups</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0" colspan="2"> + <widget class="ConfigRadioButton" name="allGroupsRadio"> + <property name="text"> + <string>Treat all RegExp capture groups as columns</string> + </property> + <property name="assignedValue" stdset="0"> + <string>all</string> + </property> + <property name="cfg" stdset="0"> + <string>RegExpImport.GroupsMode</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="ConfigRadioButton" name="customGroupsRadio"> + <property name="text"> + <string>Import only following groups:</string> + </property> + <property name="assignedValue" stdset="0"> + <string>custom</string> + </property> + <property name="cfg" stdset="0"> + <string>RegExpImport.GroupsMode</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="groupsEdit"> + <property name="toolTip"> + <string><p>Enter comma separated list of capture group indexes. The 0 index refers to the entire matched string.</p> +<p>If you used named groups in the pattern, you can use names instead of indexes. You can mix indexes and names in this list.</p></string> + </property> + <property name="placeholderText"> + <string>Example: 1, 3, 4</string> + </property> + <property name="cfg" stdset="0"> + <string>RegExpImport.CustomGroupList</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Pattern:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="lineEdit"> + <property name="toolTip"> + <string><p>Use Regular Expression groups to enclose parts of the expression that you want to import. If you want to use a group, that you don't want to import, then use "import only following groups" option below. + +You can use named groups and refer to them in group list below. To name a group use: <pre>(?&lt;myGroupName&gt;\s+\d+\s+)</pre></p></string> + </property> + <property name="placeholderText"> + <string>Example: (\d+)\s+((\d+)\w+)\s+(\w+)</string> + </property> + <property name="cfg" stdset="0"> + <string>RegExpImport.Pattern</string> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>ConfigRadioButton</class> + <extends>QRadioButton</extends> + <header>common/configradiobutton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/Plugins/RegExpImport/regexpimport_global.h b/Plugins/RegExpImport/regexpimport_global.h new file mode 100644 index 0000000..c09b742 --- /dev/null +++ b/Plugins/RegExpImport/regexpimport_global.h @@ -0,0 +1,12 @@ +#ifndef REGEXPIMPORT_GLOBAL_H +#define REGEXPIMPORT_GLOBAL_H + +#include <QtCore/qglobal.h> + +#if defined(REGEXPIMPORT_LIBRARY) +# define REGEXPIMPORTSHARED_EXPORT Q_DECL_EXPORT +#else +# define REGEXPIMPORTSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // REGEXPIMPORT_GLOBAL_H |
