aboutsummaryrefslogtreecommitdiffstats
path: root/Plugins/RegExpImport
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/RegExpImport')
-rw-r--r--Plugins/RegExpImport/RegExpImport.pro28
-rw-r--r--Plugins/RegExpImport/regexpimport.cpp209
-rw-r--r--Plugins/RegExpImport/regexpimport.h52
-rw-r--r--Plugins/RegExpImport/regexpimport.json7
-rw-r--r--Plugins/RegExpImport/regexpimport.qrc5
-rw-r--r--Plugins/RegExpImport/regexpimport.ui99
-rw-r--r--Plugins/RegExpImport/regexpimport_global.h12
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>&lt;p&gt;Enter comma separated list of capture group indexes. The 0 index refers to the entire matched string.&lt;/p&gt;
+&lt;p&gt;If you used named groups in the pattern, you can use names instead of indexes. You can mix indexes and names in this list.&lt;/p&gt;</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>&lt;p&gt;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 &quot;import only following groups&quot; option below.
+
+You can use named groups and refer to them in group list below. To name a group use: &lt;pre&gt;(?&amp;lt;myGroupName&amp;gt;\s+\d+\s+)&lt;/pre&gt;&lt;/p&gt;</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