Skip to content

Commit 4bc4c00

Browse files
committed
json data export,
schema context menu select and join
1 parent 0a9bd4d commit 4bc4c00

18 files changed

+361
-41
lines changed

mugi-query.pro

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ HEADERS += \
134134
src/timezones.h \
135135
src/drivernames.h \
136136
src/widget/datetimerangewidget.h \
137-
src/datetimerangewidgetmanager.h
137+
src/datetimerangewidgetmanager.h \
138+
src/model/queryhistorymodel.h
138139

139140
SOURCES += \
140141
src/action.cpp \
@@ -224,7 +225,8 @@ SOURCES += \
224225
src/datasavedialogstate.cpp \
225226
src/timezones.cpp \
226227
src/widget/datetimerangewidget.cpp \
227-
src/datetimerangewidgetmanager.cpp
228+
src/datetimerangewidgetmanager.cpp \
229+
src/model/queryhistorymodel.cpp
228230

229231
FORMS += \
230232
src/widget/databasehistorydialog.ui \

src/dataformat.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
void DataFormat::initComboBox(QComboBox *comboBox, bool onlySql)
88
{
9-
static QStringList items = {"Csv", "Tsv", "Sql insert", "Sql update"};
9+
static QStringList items = {"Csv", "Tsv", "Json", "Sql insert", "Sql update"};
1010
comboBox->clear();
11-
comboBox->addItems(onlySql ? items.mid(2) : items);
11+
comboBox->addItems(onlySql ? items.mid(3) : items);
1212
}
1313

1414
DataFormat::Format DataFormat::value(QComboBox *comboBox)
1515
{
16-
static QStringList items = {"Csv", "Tsv", "Sql insert", "Sql update"};
16+
static QStringList items = {"Csv", "Tsv", "Json", "Sql insert", "Sql update"};
1717
QString text = comboBox->currentText();
1818
return static_cast<DataFormat::Format>(items.indexOf(text));
1919
}
@@ -22,25 +22,25 @@ QString DataFormat::extension(DataFormat::Format format) {
2222
static QMap<DataFormat::Format,QString> exts = {
2323
{Csv, ".csv"},
2424
{Tsv, ".txt"},
25+
{Json, ".json"},
2526
{SqlInsert, ".sql"},
2627
{SqlUpdate, ".sql"},
2728
};
2829
return exts[format];
2930
}
3031

3132
QString DataFormat::extensionsRegExp(){
32-
return "[.](csv|txt|sql)$";
33+
return "[.](csv|txt|sql|json)$";
3334
}
3435

3536
QString DataFormat::fileDialogFilter(Format format)
3637
{
37-
QString filter;
38-
if (format == DataFormat::Csv) {
39-
filter = "csv files (*.csv)";
40-
} else if (format == DataFormat::Tsv) {
41-
filter = "txt files (*.txt)";
42-
} else {
43-
filter = "sql files (*.sql)";
44-
}
45-
return filter;
38+
static QMap<DataFormat::Format,QString> filter = {
39+
{Csv, "csv files (*.csv)"},
40+
{Tsv, "txt files (*.txt)"},
41+
{Json, "json files (*.json)"},
42+
{SqlInsert, "sql files (*.sql)"},
43+
{SqlUpdate, "sql files (*.sql)"},
44+
};
45+
return filter[format];
4646
}

src/dataformat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace DataFormat
99
enum Format {
1010
Csv,
1111
Tsv,
12+
Json,
1213
SqlInsert,
1314
SqlUpdate
1415
};

src/datastreamer.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
#include <QDebug>
44
#include <QTextStream>
55
#include <QSqlQueryModel>
6+
#include <QJsonObject>
7+
#include <QJsonArray>
8+
#include <QJsonDocument>
9+
#include <QTextCodec>
610

711
#include <QDate>
812
#include <QDateTime>
@@ -87,6 +91,13 @@ QString spaced(const QString& s) {
8791
return " " + s + " ";
8892
}
8993

94+
QString jsonToString(const QJsonObject& v) {
95+
QJsonDocument document;
96+
document.setObject(v);
97+
QTextCodec* codec = QTextCodec::codecForName("UTF-8");
98+
return codec->toUnicode(document.toJson());
99+
}
100+
90101
}
91102

92103
QStringList DataStreamer::variantListToStringList(const QVariantList& values,
@@ -165,6 +176,9 @@ QString DataStreamer::variantToString(const QVariant& value,
165176
error = QString("DataStreamer::variantToString(format == %2) is not defined for value.type() == %1").arg(value.type()).arg(format);
166177
return QString();
167178
}
179+
180+
} else if (format == DataFormat::Json) {
181+
return variantToJson(value).toString();
168182
} else if (format == DataFormat::SqlInsert || format == DataFormat::SqlUpdate) {
169183
if (value.isNull()) {
170184
return "null";
@@ -214,6 +228,88 @@ QSqlRecord createDataRecord(const QList<Field>& fields) {
214228
return record;
215229
}
216230

231+
QJsonValue DataStreamer::variantToJson(const QVariant& v) {
232+
QVariant::Type type = v.type();
233+
if (v.isNull()) {
234+
return QJsonValue();
235+
} else if (type == QVariant::Int) {
236+
return v.toInt();
237+
} else if (type == QVariant::Double) {
238+
return v.toDouble();
239+
} else if (type == QVariant::String) {
240+
return v.toString();
241+
} else if (type == QVariant::Date || type == QVariant::DateTime) {
242+
return v.toDateTime().toString(Qt::ISODateWithMs);
243+
} else if (type == QVariant::Time) {
244+
return v.toTime().toString("hh:mm:ss.zzz");
245+
} else if (type == QVariant::ByteArray) {
246+
QJsonArray res;
247+
QByteArray d = v.toByteArray();
248+
for(int i=0;i<d.size();i++) {
249+
res.append((uint8_t) d[i]);
250+
}
251+
return res;
252+
}
253+
return QJsonValue();
254+
}
255+
256+
QString DataStreamer::streamJson(const QSqlDatabase& db,
257+
QAbstractItemModel* model,
258+
int rowCount,
259+
const QString &table,
260+
const QList<Field>& fields,
261+
int dataColumns,
262+
int minYear,
263+
bool inLocal,
264+
bool outUtc,
265+
const QLocale& locale,
266+
bool* hasMore,
267+
QString& error) {
268+
269+
QJsonArray data;
270+
QMap<QString,QVariant::Type> m = SqlDataTypes::mapToVariant();
271+
*hasMore = false;
272+
int nonEmpty = 0;
273+
for(int r=0;r<model->rowCount();r++) {
274+
bool empty = true;
275+
QJsonObject record;
276+
for(int c=0;c<fields.size();c++) {
277+
const Field& field = fields[c];
278+
if (field.name().isEmpty()) {
279+
continue;
280+
}
281+
QModelIndex index = model->index(r,c);
282+
bool ok = false;
283+
284+
QVariant::Type type = m[field.type()];
285+
286+
QVariant v = SqlDataTypes::tryConvert(model->data(index),type,
287+
locale, minYear, inLocal, outUtc, &ok);
288+
if (!v.isNull()) {
289+
empty = false;
290+
}
291+
record[field.name()] = variantToJson(v);
292+
}
293+
294+
if (empty) {
295+
continue;
296+
}
297+
298+
if (nonEmpty == rowCount) {
299+
*hasMore = true;
300+
break;
301+
}
302+
303+
data.append(record);
304+
nonEmpty++;
305+
}
306+
307+
QJsonObject root;
308+
root["table"] = table;
309+
root["data"] = data;
310+
return jsonToString(root);
311+
}
312+
217313
QString DataStreamer::stream(DataFormat::Format format,
218314
const QSqlDatabase& db,
219315
QAbstractItemModel* model,
@@ -228,6 +324,12 @@ QString DataStreamer::stream(DataFormat::Format format,
228324
bool* hasMore,
229325
QString& error) {
230326

327+
#if 0
328+
if (format == DataFormat::Json) {
329+
return streamJson(db, model, rowCount, table, fields, dataColumns, minYear, inLocal, outUtc, locale, hasMore, error);
330+
}
331+
#endif
332+
231333
QSqlDriver* driver = db.driver();
232334

233335
QString result;
@@ -470,6 +572,24 @@ void DataStreamer::stream(const QSqlDatabase& db, QTextStream &stream, QSqlQuery
470572
}
471573
}
472574

575+
} else if (format == DataFormat::Json) {
576+
577+
QJsonArray rows;
578+
QStringList names = filterHeader(model,data);
579+
for(int r=0; r<rowCount; r++) {
580+
QJsonObject row;
581+
QVariantList values = filterData(model,r,data);
582+
for(int i=0;i<values.size();i++) {
583+
row[names[i]] = variantToJson(values[i]);
584+
}
585+
rows.append(row);
586+
}
587+
588+
QJsonObject root;
589+
root["table"] = table;
590+
root["data"] = rows;
591+
stream << jsonToString(root);
592+
473593
} else if (format == DataFormat::SqlInsert) {
474594

475595
QSqlDriver* driver = db.driver();

src/datastreamer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <QVariant>
55
#include <QString>
6+
#include <QJsonValue>
67

78
class QSqlQueryModel;
89
class QTextStream;
@@ -36,6 +37,8 @@ class DataStreamer
3637
static QString stream(DataFormat::Format format, const QSqlDatabase &db, QAbstractItemModel *model, int rowCount, const QString &table, const QList<Field> &fields, int dataColumns, int minYear, bool inLocal, bool outUtc, const QLocale &locale, bool *hasMore, QString &error);
3738

3839
static QStringList createIndexStatements(const QSqlDatabase &db, const QString &table, const QList<Field> &fields);
40+
static QString streamJson(const QSqlDatabase &db, QAbstractItemModel *model, int rowCount, const QString &table, const QList<Field> &fields, int dataColumns, int minYear, bool inLocal, bool outUtc, const QLocale &locale, bool *hasMore, QString &error);
41+
static QJsonValue variantToJson(const QVariant &v);
3942
};
4043

4144

src/model/queryhistorymodel.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "queryhistorymodel.h"
2+
3+
QueryHistoryModel::QueryHistoryModel(QObject *parent) : QSqlQueryModel(parent)
4+
{
5+
6+
}

src/model/queryhistorymodel.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef HISTORYMODEL_H
2+
#define HISTORYMODEL_H
3+
4+
#include <QObject>
5+
#include <QSqlQueryModel>
6+
7+
class QueryHistoryModel : public QSqlQueryModel
8+
{
9+
Q_OBJECT
10+
public:
11+
enum cols {
12+
col_date,
13+
col_connectionName,
14+
col_query
15+
};
16+
QueryHistoryModel(QObject *parent = nullptr);
17+
};
18+
19+
#endif // HISTORYMODEL_H

src/model/relationsmodel.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
#include <QApplication>
88
#include <QMessageBox>
99
#include <QDebug>
10+
#include <QSqlDatabase>
11+
#include "settings.h"
12+
#include <QDir>
1013

1114
RelationsModel::RelationsModel(QObject *parent) : QStandardItemModel(0,2,parent), mChanged(false)
1215
{
@@ -88,3 +91,18 @@ void RelationsModel::save(const QString &path)
8891

8992
mChanged = false;
9093
}
94+
95+
QString RelationsModel::path(const QString &connectionName)
96+
{
97+
QSqlDatabase db = QSqlDatabase::database(connectionName);
98+
99+
QStringList props;
100+
props << "relations" << db.driverName() << db.hostName()
101+
<< db.userName() << db.databaseName();
102+
103+
QString name = props.join(" ")
104+
.replace(QRegExp("[^a-z0-9._ -]",Qt::CaseInsensitive)," ")
105+
.replace(QRegExp("[ ]+")," ") + ".txt";
106+
107+
return QDir(Settings::instance()->dir()).filePath(name);
108+
}

src/model/relationsmodel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class RelationsModel : public QStandardItemModel
1616

1717
void load(const QString& path);
1818
void save(const QString& path);
19+
20+
static QString path(const QString& connectionName);
21+
1922
protected:
2023
bool mChanged;
2124
};

src/widget/dataimportwidget.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,12 @@ QString DataImportWidget::queries(bool preview) {
724724

725725
QList<Field> fields = this->fields();
726726

727-
if (newTable) {
727+
DataFormat::Format format =
728+
newTable ?
729+
DataFormat::SqlInsert :
730+
DataFormat::value(ui->format);
731+
732+
if (newTable && (format == DataFormat::SqlInsert) || (format == DataFormat::SqlUpdate)) {
728733
schemaQueries.append(DataStreamer::createTableStatement(db,table,fields,false));
729734
schemaQueries.append(DataStreamer::createIndexStatements(db,table,fields));
730735
}
@@ -734,11 +739,6 @@ QString DataImportWidget::queries(bool preview) {
734739

735740
int rowCount = preview ? 5 : model->rowCount();
736741

737-
DataFormat::Format format =
738-
newTable ?
739-
DataFormat::SqlInsert :
740-
DataFormat::value(ui->format);
741-
742742
int dataColumns =
743743
format == DataFormat::SqlInsert ?
744744
fields.size() :

src/widget/joinhelperwidget.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ JoinHelperWidget::~JoinHelperWidget()
147147
delete ui;
148148
}
149149

150+
#if 0
150151
QString JoinHelperWidget::relationsPath() const
151152
{
152153
QSqlDatabase db = QSqlDatabase::database(mConnectionName);
@@ -161,7 +162,7 @@ QString JoinHelperWidget::relationsPath() const
161162

162163
return QDir(Settings::instance()->dir()).filePath(name);
163164
}
164-
165+
#endif
165166

166167
namespace {
167168

@@ -205,15 +206,15 @@ void JoinHelperWidget::findPath()
205206
void JoinHelperWidget::saveRelationsModel() {
206207
RelationsModel* model = qobject_cast<RelationsModel*>(ui->relations->model());
207208
if (model->changed()) {
208-
model->save(relationsPath());
209+
model->save(RelationsModel::path(mConnectionName));
209210
}
210211
}
211212

212213
void JoinHelperWidget::loadRelationsModel()
213214
{
214215
RelationsModel* model = qobject_cast<RelationsModel*>(ui->relations->model());
215216
mRelationsAppender->setActive(false);
216-
model->load(relationsPath());
217+
model->load(RelationsModel::path(mConnectionName));
217218
model->insertRow(model->rowCount());
218219
mRelationsAppender->setActive(true);
219220
}

src/widget/joinhelperwidget.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class JoinHelperWidget : public QWidget
3232
public slots:
3333
void onTablesDataChanged(QModelIndex, QModelIndex);
3434
protected:
35-
QString relationsPath() const;
35+
//QString relationsPath() const;
3636
void findPath();
3737

3838
void loadRelationsModel();

0 commit comments

Comments
 (0)