From 7167ce41b61d2ba2cdb526777a4233eb84a3b66a Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Sat, 6 Dec 2014 17:33:25 -0500 Subject: Imported Upstream version 2.99.6 --- Plugins/HtmlExport/HtmlExport.pro | 29 ++ Plugins/HtmlExport/htmlexport.cpp | 615 +++++++++++++++++++++++++++++++++ Plugins/HtmlExport/htmlexport.css | 59 ++++ Plugins/HtmlExport/htmlexport.h | 74 ++++ Plugins/HtmlExport/htmlexport.json | 7 + Plugins/HtmlExport/htmlexport.qrc | 8 + Plugins/HtmlExport/htmlexport.ui | 129 +++++++ Plugins/HtmlExport/htmlexport_global.h | 12 + 8 files changed, 933 insertions(+) create mode 100644 Plugins/HtmlExport/HtmlExport.pro create mode 100644 Plugins/HtmlExport/htmlexport.cpp create mode 100644 Plugins/HtmlExport/htmlexport.css create mode 100644 Plugins/HtmlExport/htmlexport.h create mode 100644 Plugins/HtmlExport/htmlexport.json create mode 100644 Plugins/HtmlExport/htmlexport.qrc create mode 100644 Plugins/HtmlExport/htmlexport.ui create mode 100644 Plugins/HtmlExport/htmlexport_global.h (limited to 'Plugins/HtmlExport') diff --git a/Plugins/HtmlExport/HtmlExport.pro b/Plugins/HtmlExport/HtmlExport.pro new file mode 100644 index 0000000..ff0a68e --- /dev/null +++ b/Plugins/HtmlExport/HtmlExport.pro @@ -0,0 +1,29 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-06-20T22:57:37 +# +#------------------------------------------------- + +include($$PWD/../../SQLiteStudio3/plugins.pri) + +QT -= gui + +TARGET = HtmlExport +TEMPLATE = lib + +DEFINES += HTMLEXPORT_LIBRARY + +SOURCES += htmlexport.cpp + +HEADERS += htmlexport.h\ + htmlexport_global.h + +OTHER_FILES += \ + htmlexport.json \ + htmlexport.css + +RESOURCES += \ + htmlexport.qrc + +FORMS += \ + htmlexport.ui diff --git a/Plugins/HtmlExport/htmlexport.cpp b/Plugins/HtmlExport/htmlexport.cpp new file mode 100644 index 0000000..75b3868 --- /dev/null +++ b/Plugins/HtmlExport/htmlexport.cpp @@ -0,0 +1,615 @@ +#include "htmlexport.h" +#include "services/pluginmanager.h" +#include "common/unused.h" +#include +#include +#include +#include +#include + +QString HtmlExport::getFormatName() const +{ + return "HTML"; +} + +ExportManager::StandardConfigFlags HtmlExport::standardOptionsToEnable() const +{ + return ExportManager::CODEC; +} + +QString HtmlExport::getExportConfigFormName() const +{ + return "HtmlExportConfig"; +} + +void HtmlExport::validateOptions() +{ + bool header = cfg.HtmlExport.PrintHeader.get(); + EXPORT_MANAGER->updateVisibilityAndEnabled(cfg.HtmlExport.PrintDataTypes, true, header); +} + +QString HtmlExport::defaultFileExtension() const +{ + return "html"; +} + +CfgMain* HtmlExport::getConfig() +{ + return &cfg; +} + +bool HtmlExport::beforeExportQueryResults(const QString& query, QList& columns, const QHash providedData) +{ + UNUSED(query); + UNUSED(providedData); + + if (!beginDoc(tr("SQL query results"))) + return false; + + columnTypes = QueryExecutor::resolveColumnTypes(db, columns, true); + + writeln(""); + incrIndent(); + if (printHeader) + { + writeln(""); + incrIndent(); + if (printRownum) + { + writeln(""); + } + + QString column; + int i = 0; + for (const QueryExecutor::ResultColumnPtr& col : columns) + { + writeln(""); + i++; + } + decrIndent(); + writeln(""); + } + + currentDataRow = 0; + return true; +} + +bool HtmlExport::exportQueryResultsRow(SqlResultsRowPtr row) +{ + return exportDataRow(row); +} + +bool HtmlExport::afterExportQueryResults() +{ + decrIndent(); + writeln("
"); + incrIndent(); + writeln("#"); + decrIndent(); + writeln(""); + incrIndent(); + column = QString("%1").arg(col->displayName); + if (printDatatypes) + { + if (!columnTypes[i].isNull()) + column.append("
" + columnTypes[i].toFullTypeString()); + else + column.append("
" + tr("no type")); + } + writeln(column); + decrIndent(); + writeln("
"); + writeln("

"); + return true; +} + +bool HtmlExport::exportTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateTablePtr createTable, const QHash providedData) +{ + UNUSED(database); + UNUSED(ddl); + UNUSED(columnNames); + UNUSED(providedData); + + if (isTableExport()) + { + if (!beginDoc(tr("Exported table: %1").arg(table))) + return false; + } + + int colCount = createTable->columns.size(); + int colSpan = printRownum ? colCount + 1 : colCount; + + writeln(""); + incrIndent(); + + writeln(""); + incrIndent(); + writeln(QString("").arg(colSpan).arg(tr("Table: %1").arg(table))); + decrIndent(); + writeln(""); + + if (printHeader) + { + writeln(""); + incrIndent(); + if (printRownum) + { + writeln(""); + } + + QString column; + for (SqliteCreateTable::Column* col : createTable->columns) + { + writeln(""); + } + decrIndent(); + writeln(""); + } + + columnTypes.clear(); + for (SqliteCreateTable::Column* col : createTable->columns) + { + if (col->type) + columnTypes << col->type->toDataType(); + else + columnTypes << DataType(); + } + + currentDataRow = 0; + return true; +} + +bool HtmlExport::exportDataRow(SqlResultsRowPtr data) +{ + currentDataRow++; + + writeln(""); + incrIndent(); + if (printRownum) + { + writeln(""); + } + + QString align; + QString cellValue; + QString cellStyle; + int i = 0; + for (const QVariant& value : data->valueList()) + { + if (columnTypes[i].isNumeric()) + align = "right"; + else + align = "left"; + + if (value.isNull()) + { + cellValue = "NULL"; + cellStyle = " class=\"null\""; + } + else + { + cellStyle = ""; + if (value.toString().trimmed().isEmpty()) + cellValue = " "; + else + { + cellValue = value.toString(); + cellValue.truncate(byteLengthLimit); + cellValue = escape(cellValue); + } + } + writeln(QString(""); + i++; + } + decrIndent(); + writeln(""); + return true; +} + +bool HtmlExport::exportVirtualTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateVirtualTablePtr createTable, const QHash providedData) +{ + UNUSED(database); + UNUSED(ddl); + UNUSED(columnNames); + UNUSED(createTable); + UNUSED(providedData); + + if (isTableExport()) + { + if (!beginDoc(tr("Exported table: %1").arg(table))) + return false; + } + + int colCount = columnNames.size(); + int colSpan = printRownum ? colCount + 1 : colCount; + + writeln("
%2
"); + incrIndent(); + writeln("#"); + decrIndent(); + writeln(""); + incrIndent(); + column = QString("%1").arg(col->name); + if (printDatatypes) + { + if (col->type) + column.append("
" + col->type->toDataType().toFullTypeString()); + else + column.append("
" + tr("no type")); + } + writeln(column); + decrIndent(); + writeln("
"); + incrIndent(); + writeln(QString("%1").arg(currentDataRow)); + decrIndent(); + writeln("").arg(align, cellStyle)); + incrIndent(); + writeln(cellValue); + decrIndent(); + writeln("
"); + incrIndent(); + + writeln(""); + incrIndent(); + writeln(QString("").arg(colSpan).arg(tr("Table: %1").arg(table), tr("virtual"))); + decrIndent(); + writeln(""); + + if (printHeader) + { + writeln(""); + incrIndent(); + if (printRownum) + { + writeln(""); + } + + QString column; + for (const QString& col : columnNames) + { + writeln(""); + } + decrIndent(); + writeln(""); + } + + columnTypes.clear(); + for (int i = 0, total = columnNames.size(); i < total; ++i) + columnTypes << DataType(); + + currentDataRow = 0; + return true; +} + +bool HtmlExport::exportTableRow(SqlResultsRowPtr data) +{ + return exportDataRow(data); +} + +bool HtmlExport::afterExportTable() +{ + decrIndent(); + writeln("
%2 (%3)
"); + incrIndent(); + writeln("#"); + decrIndent(); + writeln(""); + incrIndent(); + writeln(QString("%1").arg(col)); + decrIndent(); + writeln("
"); + writeln("

"); + return true; +} + +bool HtmlExport::beforeExportDatabase(const QString& database) +{ + if (!beginDoc(tr("Exported database: %1").arg(database))) + return false; + + return true; +} + +bool HtmlExport::exportIndex(const QString& database, const QString& name, const QString& ddl, SqliteCreateIndexPtr createIndex) +{ + UNUSED(database); + UNUSED(ddl); + + writeln(""); + incrIndent(); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Index: %1").arg("" + name + ""))); + decrIndent(); + writeln(""); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("For table:"))); + writeln(QString("").arg(createIndex->table)); + decrIndent(); + writeln(""); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Unique:"))); + writeln(QString("").arg(createIndex->uniqueKw ? tr("Yes") : tr("No"))); + decrIndent(); + writeln(""); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Column"))); + writeln(QString("").arg(tr("Collating"))); + writeln(QString("").arg(tr("Sort order"))); + decrIndent(); + writeln(""); + + for (SqliteIndexedColumn* idxCol : createIndex->indexedColumns) + { + writeln(""); + incrIndent(); + writeln(QString("").arg(escape(idxCol->name))); + writeln(QString("").arg(idxCol->collate.isNull() ? " " : escape(idxCol->collate))); + writeln(QString("").arg(idxCol->sortOrder == SqliteSortOrder::null ? " " : sqliteSortOrder(idxCol->sortOrder))); + decrIndent(); + writeln(""); + } + + decrIndent(); + writeln("
%1
%1%1
%1%1
%1%1%1
%1%1%1
"); + writeln("

"); + return true; +} + +bool HtmlExport::exportTrigger(const QString& database, const QString& name, const QString& ddl, SqliteCreateTriggerPtr createTrigger) +{ + UNUSED(database); + UNUSED(ddl); + + writeln(""); + incrIndent(); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Trigger: %1").arg("" + name + ""))); + decrIndent(); + writeln(""); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Activated:"))); + writeln(QString("").arg(SqliteCreateTrigger::time(createTrigger->eventTime))); + decrIndent(); + writeln(""); + + QString event = createTrigger->event ? SqliteCreateTrigger::Event::typeToString(createTrigger->event->type) : ""; + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Action:"))); + writeln(QString("").arg(event)); + decrIndent(); + writeln(""); + + QString onObj; + if (createTrigger->eventTime == SqliteCreateTrigger::Time::INSTEAD_OF) + onObj = tr("On view:"); + else + onObj = tr("On table:"); + + writeln(""); + incrIndent(); + writeln(QString("").arg(onObj)); + writeln(QString("").arg(createTrigger->table)); + decrIndent(); + writeln(""); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Activate condition:"))); + writeln(QString("").arg(createTrigger->precondition ? escape(createTrigger->precondition->detokenize()) : "")); + decrIndent(); + writeln(""); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("Code executed:"))); + decrIndent(); + writeln(""); + + QStringList queryStrings; + for (SqliteQuery* q : createTrigger->queries) + queryStrings << escape(q->detokenize()); + + writeln(""); + incrIndent(); + writeln(""); + decrIndent(); + writeln(""); + + decrIndent(); + writeln("
%1
%1%1
%1%1
%1%1
%1%1
%1
"); + incrIndent(); + writeln(QString("
%1
").arg(queryStrings.join("
"))); + decrIndent(); + writeln("
"); + writeln("

"); + return true; +} + +bool HtmlExport::exportView(const QString& database, const QString& name, const QString& ddl, SqliteCreateViewPtr view) +{ + UNUSED(database); + UNUSED(ddl); + + writeln(""); + incrIndent(); + + writeln(""); + incrIndent(); + writeln(QString("").arg(tr("View: %1").arg("" + name + ""))); + decrIndent(); + writeln(""); + + writeln(""); + incrIndent(); + writeln(""); + decrIndent(); + writeln(""); + + decrIndent(); + writeln("
%1
"); + incrIndent(); + writeln(QString("
%1
").arg(escape(view->select->detokenize()))); + decrIndent(); + writeln("
"); + writeln("

"); + return true; +} + +bool HtmlExport::afterExport() +{ + static const QString bodyEndTpl = QStringLiteral(""); + static const QString docEnd = QStringLiteral(""); + + writeln("" + tr("Document generated by SQLiteStudio v%1 on %2").arg(SQLITESTUDIO->getVersionString(), QDateTime::currentDateTime().toString()) + ""); + decrIndent(); + writeln(bodyEndTpl); + decrIndent(); + writeln(docEnd); + return true; +} + +bool HtmlExport::beginDoc(const QString& title) +{ + static const QString docStart = QStringLiteral( + R"()" + "\n" + ); + + static const QString metaCodecTpl = QStringLiteral(R"()"); + static const QString titletpl = QStringLiteral(R"(%1)"); + static const QString styleStartTpl = QStringLiteral(R"()"); + static const QString bodyStartTpl = QStringLiteral(R"()"); + + setupConfig(); + + QFile file(":/htmlexport/htmlexport.css"); + if (!file.open(QIODevice::ReadOnly)) + { + qCritical() << "Could not open htmlexport.css resource while exporting to HTML:" << file.errorString(); + return false; + } + + writeln(docStart); + incrIndent(); + writeln(metaCodecTpl.arg(codecName)); + writeln(titletpl.arg(title)); + writeln(styleStartTpl); + incrIndent(); + writeln(indent ? file.readAll() : compressCss(file.readAll())); + decrIndent(); + writeln(styleEndTpl); + writeln(bodyStartTpl); + incrIndent(); + + file.close(); + return true; +} + +void HtmlExport::setupConfig() +{ + codecName = codec->name(); + indentDepth = 0; + newLineStr = ""; + indentStr = ""; + indent = (cfg.HtmlExport.Format.get() == "format"); + if (indent) + newLineStr = "\n"; + + printRownum = cfg.HtmlExport.PrintRowNum.get(); + printHeader = cfg.HtmlExport.PrintHeader.get(); + printDatatypes = printHeader && cfg.HtmlExport.PrintDataTypes.get(); + byteLengthLimit = cfg.HtmlExport.ByteLengthLimit.get(); +} + +void HtmlExport::incrIndent() +{ + if (indent) + { + indentDepth++; + updateIndent(); + } +} + +void HtmlExport::decrIndent() +{ + if (indent) + { + indentDepth--; + updateIndent(); + } +} + +void HtmlExport::updateIndent() +{ + indentStr = QString(" ").repeated(indentDepth); +} + +void HtmlExport::writeln(const QString& str) +{ + QString newStr; + if (str.contains("\n")) + { + QStringList lines = str.split("\n"); + QMutableStringListIterator it(lines); + while (it.hasNext()) + it.next().prepend(indentStr); + + newStr = lines.join("\n") + newLineStr; + } + else + { + newStr = indentStr + str + newLineStr; + } + GenericExportPlugin::write(newStr); +} + +QString HtmlExport::escape(const QString& str) +{ + if (cfg.HtmlExport.DontEscapeHtml.get()) + return str; + + return str.toHtmlEscaped(); +} + +QString HtmlExport::compressCss(QString css) +{ + static const QRegExp spacesLeftRe(R"REGEXP(([^a-zA-Z0-9_\s]+)\s+(\S+))REGEXP"); + static const QRegExp spacesRightRe(R"REGEXP((\S+)\s+([^a-zA-Z0-9_\s]+))REGEXP"); + static const QRegExp spacesBetweenWordsRe(R"REGEXP((\S+)\s{2,}(\S+))REGEXP"); + while (spacesLeftRe.indexIn(css) > -1) + css.replace(spacesLeftRe, R"(\1\2)"); + + while (spacesRightRe.indexIn(css) > -1) + css.replace(spacesRightRe, R"(\1\2)"); + + while (spacesBetweenWordsRe.indexIn(css) > -1) + css.replace(spacesBetweenWordsRe, R"(\1 \2)"); + + return css.trimmed(); +} + +bool HtmlExport::init() +{ + Q_INIT_RESOURCE(htmlexport); + return GenericExportPlugin::init(); +} + +void HtmlExport::deinit() +{ + Q_CLEANUP_RESOURCE(htmlexport); +} diff --git a/Plugins/HtmlExport/htmlexport.css b/Plugins/HtmlExport/htmlexport.css new file mode 100644 index 0000000..72ebf4f --- /dev/null +++ b/Plugins/HtmlExport/htmlexport.css @@ -0,0 +1,59 @@ +table +{ + border-style: solid; + border-width: 1px; + border-color: black; + border-collapse: collapse; +} + +table tr +{ + background-color: white; +} + +table tr.header +{ + background-color: #DDDDDD; +} + +table tr.title +{ + background-color: #EEEEEE; +} + +table tr td +{ + padding: 0px 3px 0px 3px; + border-style: solid; + border-width: 1px; + border-color: #666666; +} + +table tr td.null +{ + color: #999999; + text-align: center; + padding: 0px 3px 0px 3px; + border-style: solid; + border-width: 1px; + border-color: #666666; +} + +table tr td.separator +{ + padding: 0px 3px 0px 3px; + border-style: solid; + border-width: 1px; + border-color: #666666; + background-color: #DDDDDD; +} + +table tr td.rownum +{ + padding: 0px 3px 0px 3px; + border-style: solid; + border-width: 1px; + border-color: #666666; + background-color: #DDDDDD; + text-align: right; +} diff --git a/Plugins/HtmlExport/htmlexport.h b/Plugins/HtmlExport/htmlexport.h new file mode 100644 index 0000000..04a379c --- /dev/null +++ b/Plugins/HtmlExport/htmlexport.h @@ -0,0 +1,74 @@ +#ifndef HTMLEXPORT_H +#define HTMLEXPORT_H + +#include "htmlexport_global.h" +#include "plugins/genericexportplugin.h" +#include "config_builder.h" + +CFG_CATEGORIES(HtmlExportConfig, + CFG_CATEGORY(HtmlExport, + CFG_ENTRY(QString, Format, "compress") + CFG_ENTRY(bool, PrintRowNum, true) + CFG_ENTRY(bool, PrintHeader, true) + CFG_ENTRY(bool, PrintDataTypes, true) + CFG_ENTRY(bool, DontEscapeHtml, false) + CFG_ENTRY(int, ByteLengthLimit, 10000) + ) +) +class HTMLEXPORTSHARED_EXPORT HtmlExport : public GenericExportPlugin +{ + Q_OBJECT + SQLITESTUDIO_PLUGIN("htmlexport.json") + + public: + QString getFormatName() const; + ExportManager::StandardConfigFlags standardOptionsToEnable() const; + QString getExportConfigFormName() const; + CfgMain* getConfig(); + void validateOptions(); + QString defaultFileExtension() const; + bool beforeExportQueryResults(const QString& query, QList& columns, + const QHash providedData); + bool exportQueryResultsRow(SqlResultsRowPtr row); + bool exportTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateTablePtr createTable, + const QHash providedData); + bool exportVirtualTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateVirtualTablePtr createTable, + const QHash providedData); + bool exportTableRow(SqlResultsRowPtr data); + bool beforeExportDatabase(const QString& database); + bool exportIndex(const QString& database, const QString& name, const QString& ddl, SqliteCreateIndexPtr createIndex); + bool exportTrigger(const QString& database, const QString& name, const QString& ddl, SqliteCreateTriggerPtr createTrigger); + bool exportView(const QString& database, const QString& name, const QString& ddl, SqliteCreateViewPtr view); + bool afterExportQueryResults(); + bool afterExportTable(); + bool afterExport(); + bool init(); + void deinit(); + + private: + bool beginDoc(const QString& title); + bool exportDataRow(SqlResultsRowPtr data); + void setupConfig(); + void incrIndent(); + void decrIndent(); + void updateIndent(); + void writeln(const QString& str); + QString escape(const QString& str); + + static QString compressCss(QString css); + + CFG_LOCAL(HtmlExportConfig, cfg) + bool indent = false; + int indentDepth = 0; + QString indentStr; + QString newLineStr; + QString codecName; + int currentDataRow = 0; + QList columnTypes; + bool printRownum = false; + bool printHeader = false; + bool printDatatypes = false; + int byteLengthLimit = 0; +}; + +#endif // HTMLEXPORT_H diff --git a/Plugins/HtmlExport/htmlexport.json b/Plugins/HtmlExport/htmlexport.json new file mode 100644 index 0000000..530a21d --- /dev/null +++ b/Plugins/HtmlExport/htmlexport.json @@ -0,0 +1,7 @@ +{ + "type": "ExportPlugin", + "title": "HTML export", + "description": "Provides HTML format for exporting.", + "version": 10000, + "author": "SalSoft" +} diff --git a/Plugins/HtmlExport/htmlexport.qrc b/Plugins/HtmlExport/htmlexport.qrc new file mode 100644 index 0000000..77f9482 --- /dev/null +++ b/Plugins/HtmlExport/htmlexport.qrc @@ -0,0 +1,8 @@ + + + htmlexport.css + + + htmlexport.ui + + diff --git a/Plugins/HtmlExport/htmlexport.ui b/Plugins/HtmlExport/htmlexport.ui new file mode 100644 index 0000000..a4727a4 --- /dev/null +++ b/Plugins/HtmlExport/htmlexport.ui @@ -0,0 +1,129 @@ + + + HtmlExportConfig + + + + 0 + 0 + 400 + 228 + + + + Form + + + + + + + 100 + 16777215 + + + + 999999999 + + + HtmlExport.ByteLengthLimit + + + + + + + Maximum number of characters per cell: + + + + + + + Include data types in first row + + + HtmlExport.PrintDataTypes + + + + + + + Column names as first row + + + HtmlExport.PrintHeader + + + + + + + Row numbers as first column + + + HtmlExport.PrintRowNum + + + + + + + Output format + + + + + + Format document (new lines, indentation) + + + HtmlExport.Format + + + format + + + + + + + Compress (everything in one line) + + + HtmlExport.Format + + + compress + + + + + + + + + + <p>When enabled, HTML characters such as &lt;, &gt; and &amp; are not escaped in exported values. This allows you for example to export hyper-link enabled documents, but it also may result in incorrect HTML document (unmatched pairs of &lt; and &gt; characters). Be warned.</p> + + + Don't escape HTML characters + + + HtmlExport.DontEscapeHtml + + + + + + + + ConfigRadioButton + QRadioButton +
common/configradiobutton.h
+
+
+ + +
diff --git a/Plugins/HtmlExport/htmlexport_global.h b/Plugins/HtmlExport/htmlexport_global.h new file mode 100644 index 0000000..02671c4 --- /dev/null +++ b/Plugins/HtmlExport/htmlexport_global.h @@ -0,0 +1,12 @@ +#ifndef HTMLEXPORT_GLOBAL_H +#define HTMLEXPORT_GLOBAL_H + +#include + +#if defined(HTMLEXPORT_LIBRARY) +# define HTMLEXPORTSHARED_EXPORT Q_DECL_EXPORT +#else +# define HTMLEXPORTSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // HTMLEXPORT_GLOBAL_H -- cgit v1.2.3