From b6d986051b047d6915d4c220b22dad8b9ab22430 Mon Sep 17 00:00:00 2001 From: Eelke Klein Date: Wed, 25 Jan 2017 06:54:21 +0100 Subject: [PATCH] Query tab will now show multiple data tabs if it get's multiple results with tuples. --- asyncdbconnection.cpp | 5 +- asyncdbconnection.h | 4 +- databaseinspectorwidget.cpp | 14 +++ databaseinspectorwidget.h | 22 ++++ ...rviewform.ui => databaseinspectorwidget.ui | 8 +- databaseoverviewform.cpp | 14 --- icons/desktop.ini | 1 + icons/information.png | Bin 0 -> 2112 bytes icons/lightbulb_off.png | Bin 0 -> 1456 bytes icons/page_white_delete.png | Bin 0 -> 1255 bytes mainwindow.cpp | 18 +++- mainwindow.h | 3 + mainwindow.ui | 51 ++++++++- pglab.pro | 19 +++- querytab.cpp | 69 ++++++++---- querytab.h | 25 ++++- querytab.ui | 55 ---------- resources.qrc | 3 + tuplesresultwidget.cpp | 26 +++++ tuplesresultwidget.h | 26 +++++ tuplesresultwidget.ui | 99 ++++++++++++++++++ 21 files changed, 349 insertions(+), 113 deletions(-) create mode 100644 databaseinspectorwidget.cpp create mode 100644 databaseinspectorwidget.h rename databaseoverviewform.ui => databaseinspectorwidget.ui (93%) delete mode 100644 databaseoverviewform.cpp create mode 100644 icons/information.png create mode 100644 icons/lightbulb_off.png create mode 100644 icons/page_white_delete.png create mode 100644 tuplesresultwidget.cpp create mode 100644 tuplesresultwidget.h create mode 100644 tuplesresultwidget.ui diff --git a/asyncdbconnection.cpp b/asyncdbconnection.cpp index 2bc6c30..0eb8b0a 100644 --- a/asyncdbconnection.cpp +++ b/asyncdbconnection.cpp @@ -250,6 +250,7 @@ void ASyncDBConnection::Thread::doNewCommand() } } if (!command.empty() && m_connection.sendQuery(command)) { + m_timer.start(); doStateCallback(State::QuerySend); } else { @@ -290,9 +291,11 @@ void ASyncDBConnection::Thread::waitForResult() while ( ! finished && ! m_connection.isBusy()) { auto res(m_connection.getResult()); { + qint64 ms = m_timer.restart(); std::lock_guard lg(m_commandQueue.m_mutex); - m_commandQueue.m_queue.front().on_result(res); + m_commandQueue.m_queue.front().on_result(res, ms); if (res == nullptr) { + m_timer.invalidate(); m_commandQueue.m_queue.pop(); doStateCallback(State::Connected); finished = true; diff --git a/asyncdbconnection.h b/asyncdbconnection.h index e147dfa..03a6162 100644 --- a/asyncdbconnection.h +++ b/asyncdbconnection.h @@ -4,6 +4,7 @@ #include "PgsqlConn.h" #include "win32event.h" #include "connectionconfig.h" +#include #include #include #include @@ -21,7 +22,7 @@ public: Terminating }; - using on_result_callback = std::function)>; + using on_result_callback = std::function, qint64)>; using on_state_callback = std::function; using on_notice_callback = std::function; @@ -102,6 +103,7 @@ private: bool terminateRequested = false; ///< is set when the thread should stop bool m_terminated = true; Pgsql::Canceller m_canceller; + QElapsedTimer m_timer; bool makeConnection(); diff --git a/databaseinspectorwidget.cpp b/databaseinspectorwidget.cpp new file mode 100644 index 0000000..93d7f38 --- /dev/null +++ b/databaseinspectorwidget.cpp @@ -0,0 +1,14 @@ +#include "databaseinspectorwidget.h" +#include "ui_databaseinspectorwidget.h" + +DatabaseInspectorWidget::DatabaseInspectorWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::DatabaseInspectorWidget) +{ + ui->setupUi(this); +} + +DatabaseInspectorWidget::~DatabaseInspectorWidget() +{ + delete ui; +} diff --git a/databaseinspectorwidget.h b/databaseinspectorwidget.h new file mode 100644 index 0000000..98f810f --- /dev/null +++ b/databaseinspectorwidget.h @@ -0,0 +1,22 @@ +#ifndef DATABASEINSPECTORWIDGET_H +#define DATABASEINSPECTORWIDGET_H + +#include + +namespace Ui { +class DatabaseInspectorWidget; +} + +class DatabaseInspectorWidget : public QWidget +{ + Q_OBJECT + +public: + explicit DatabaseInspectorWidget(QWidget *parent = 0); + ~DatabaseInspectorWidget(); + +private: + Ui::DatabaseInspectorWidget *ui; +}; + +#endif // DATABASEINSPECTORWIDGET_H diff --git a/databaseoverviewform.ui b/databaseinspectorwidget.ui similarity index 93% rename from databaseoverviewform.ui rename to databaseinspectorwidget.ui index 8e1fcf6..74e83a1 100644 --- a/databaseoverviewform.ui +++ b/databaseinspectorwidget.ui @@ -1,13 +1,13 @@ - DatabaseOverviewForm - + DatabaseInspectorWidget + 0 0 - 733 - 618 + 599 + 536 diff --git a/databaseoverviewform.cpp b/databaseoverviewform.cpp deleted file mode 100644 index cbc4c58..0000000 --- a/databaseoverviewform.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "databaseoverviewform.h" -#include "ui_databaseoverviewform.h" - -DatabaseOverviewForm::DatabaseOverviewForm(QWidget *parent) : - QWidget(parent), - ui(new Ui::DatabaseOverviewForm) -{ - ui->setupUi(this); -} - -DatabaseOverviewForm::~DatabaseOverviewForm() -{ - delete ui; -} diff --git a/icons/desktop.ini b/icons/desktop.ini index a0f2f95..17ade64 100644 --- a/icons/desktop.ini +++ b/icons/desktop.ini @@ -11,3 +11,4 @@ folder.png=@folder.png,0 script_save.png=@script_save.png,0 lightbulb.png=@lightbulb.png,0 table_save.png=@table_save.png,0 +lightbulb_off.png=@lightbulb_off.png,0 diff --git a/icons/information.png b/icons/information.png new file mode 100644 index 0000000000000000000000000000000000000000..93c67f2bf0e6e07da700bc508b7b9f55e5c6f89a GIT binary patch literal 2112 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 RtHJ;P002ovPDHLkV1kcYSq%UH literal 0 HcmV?d00001 diff --git a/mainwindow.cpp b/mainwindow.cpp index a84761b..962a536 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -26,7 +26,7 @@ MainWindow::MainWindow(QWidget *parent) ui->setupUi(this); ui->tabWidget->setDocumentMode(true); - ui->tabWidget->setTabsClosable(true); + //ui->tabWidget->setTabsClosable(true); } MainWindow::~MainWindow() @@ -40,6 +40,7 @@ QueryTab* MainWindow::newSqlPage() qt->setConfig(m_config); ui->tabWidget->addTab(qt, "Tab"); ui->tabWidget->setCurrentWidget(qt); + qt->newdoc(); return qt; } @@ -125,7 +126,8 @@ void MainWindow::on_actionExport_data_triggered() void MainWindow::on_actionClose_triggered() { - close(); + //close(); + on_tabWidget_tabCloseRequested(ui->tabWidget->currentIndex()); } void MainWindow::on_actionAbout_triggered() @@ -172,11 +174,20 @@ void MainWindow::on_actionExecute_SQL_triggered() } } +void MainWindow::on_actionExplain_triggered() +{ + QueryTab *tab = GetActiveQueryTab(); + if (tab) { + tab->explain(false); + } +} + + void MainWindow::on_actionExplain_Analyze_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { - tab->explainAnalyze(); + tab->explain(true); } } @@ -221,3 +232,4 @@ void MainWindow::on_tabWidget_tabCloseRequested(int index) ui->tabWidget->removeTab(index); } } + diff --git a/mainwindow.h b/mainwindow.h index 57f6fa1..230ce7c 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -45,6 +45,7 @@ public: private: + Ui::MainWindow *ui; TSQueue m_taskQueue; @@ -56,6 +57,7 @@ private: void closeEvent(QCloseEvent *event); void showEvent(QShowEvent *event); QueryTab *newSqlPage(); + private slots: void processCallableQueue(); @@ -72,6 +74,7 @@ private slots: void on_actionSave_copy_of_SQL_as_triggered(); void on_actionNew_SQL_triggered(); void on_tabWidget_tabCloseRequested(int index); + void on_actionExplain_triggered(); }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index d773752..9e066de 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -45,7 +45,7 @@ 0 0 993 - 25 + 22 @@ -67,7 +67,18 @@ + + + Query + + + + + + + + @@ -81,10 +92,14 @@ + + + + @@ -121,11 +136,24 @@ + + + :/icons/page_white_delete.png + + Close + + Ctrl+F4 + + + + :/icons/information.png + + About @@ -137,7 +165,10 @@ - Execute SQL + Execute queries + + + Execute the (selected) queries F5 @@ -191,6 +222,22 @@ Ctrl+N + + + + :/icons/lightbulb_off.png + + + + Explain + + + Explain the (selected) query + + + F7 + + diff --git a/pglab.pro b/pglab.pro index af58e7e..88a3345 100644 --- a/pglab.pro +++ b/pglab.pro @@ -35,11 +35,15 @@ SOURCES += main.cpp\ connectionlistmodel.cpp \ connectionconfig.cpp \ backuprestore.cpp \ - databaseoverviewform.cpp \ dbschema_database.cpp \ querytab.cpp \ stopwatch.cpp \ - util.cpp + util.cpp \ + databaseinspectorwidget.cpp \ + pgtype.cpp \ + pgsqldatabasecatalogue.cpp \ + pgtypecontainer.cpp \ + tuplesresultwidget.cpp HEADERS += mainwindow.h \ serverproperties.h \ @@ -60,17 +64,22 @@ HEADERS += mainwindow.h \ connectionconfig.h \ scopeguard.h \ expected.h \ - databaseoverviewform.h \ dbschema_database.h \ querytab.h \ stopwatch.h \ - util.h + util.h \ + databaseinspectorwidget.h \ + pgtype.h \ + pgsqldatabasecatalogue.h \ + pgtypecontainer.h \ + tuplesresultwidget.h FORMS += mainwindow.ui \ serverproperties.ui \ databasewindow.ui \ connectionmanagerwindow.ui \ - databaseoverviewform.ui \ + databaseinspectorwidget.ui \ + tuplesresultwidget.ui \ querytab.ui RESOURCES += \ diff --git a/querytab.cpp b/querytab.cpp index b52da2a..e23af9d 100644 --- a/querytab.cpp +++ b/querytab.cpp @@ -40,9 +40,9 @@ QueryTab::QueryTab(MainWindow *win, QWidget *parent) : highlighter.reset(new SqlHighlighter(ui->queryEdit->document())); connect(ui->queryEdit, &QPlainTextEdit::textChanged, this, &QueryTab::queryTextChanged); - m_stopwatch.setOutputLabel(ui->lblElapsedTime); - ui->lblElapsedTime->clear(); - ui->lblRowCount->clear(); +// m_stopwatch.setOutputLabel(ui->lblElapsedTime); +// ui->lblElapsedTime->clear(); +// ui->lblRowCount->clear(); } QueryTab::~QueryTab() @@ -167,14 +167,14 @@ void QueryTab::execute() std::string cmd = getCommand(); m_stopwatch.start(); m_dbConnection.send(cmd, - [this](std::shared_ptr res) + [this](std::shared_ptr res, qint64 elapsedms) { - m_win->QueueTask([this, res]() { query_ready(res); }); + m_win->QueueTask([this, res, elapsedms]() { query_ready(res, elapsedms); }); }); } } -void QueryTab::explainAnalyze() +void QueryTab::explain(bool analyze) { ui->explainTreeView->setModel(nullptr); explainModel.reset(); @@ -182,10 +182,14 @@ void QueryTab::explainAnalyze() addLog("Explain clicked"); + std::string analyze_str; + if (analyze) { + analyze_str = "ANALYZE, "; + } m_stopwatch.start(); - std::string cmd = "EXPLAIN (ANALYZE, VERBOSE, BUFFERS, FORMAT JSON) " + getCommand(); + std::string cmd = "EXPLAIN (" + analyze_str + "VERBOSE, BUFFERS, FORMAT JSON) " + getCommand(); m_dbConnection.send(cmd, - [this](std::shared_ptr res) + [this](std::shared_ptr res, qint64 ) { if (res) { // Process explain data seperately @@ -216,7 +220,9 @@ void QueryTab::cancel() void QueryTab::setFileName(const QString &filename) { m_fileName = filename; - setTabCaption(m_fileName); + QFileInfo fileInfo(filename); + QString fn(fileInfo.fileName()); + setTabCaption(fn, m_fileName); } bool QueryTab::continueWithoutSavingWarning() @@ -403,7 +409,7 @@ std::string QueryTab::getCommand() const return command.toUtf8().data(); } -void QueryTab::setTabCaption(const QString &caption) +void QueryTab::setTabCaption(const QString &caption, const QString &tooltip) { QWidget * w = parentWidget(); QWidget * p = w->parentWidget(); @@ -412,32 +418,45 @@ void QueryTab::setTabCaption(const QString &caption) int i = tabwidget->indexOf(this); if (i >= 0) { tabwidget->setTabText(i, caption); + tabwidget->setTabToolTip(i, tooltip); } } } -void QueryTab::query_ready(std::shared_ptr dbres) +void QueryTab::query_ready(std::shared_ptr dbres, qint64 elapsedms) { - m_stopwatch.stop(); if (dbres) { addLog("query_ready with result"); auto st = dbres->resultStatus(); if (st == PGRES_TUPLES_OK) { //int n_rows = dbres->getRows(); - QString rowcount_str = QString("rows: %1").arg(dbres->getRows()); - ui->lblRowCount->setText(rowcount_str); - resultModel.reset(new QueryResultModel(nullptr , dbres)); - ui->ResultView->setModel(resultModel.get()); - ui->tabWidget->setCurrentWidget(ui->dataTab); + //QString rowcount_str = QString("rows: %1").arg(dbres->getRows()); + + auto result_model = std::make_shared(nullptr , dbres); + TuplesResultWidget *trw = new TuplesResultWidget; + trw->setResult(result_model, elapsedms); + resultList.push_back(trw); + ui->tabWidget->addTab(trw, "Data"); +// ui->lblRowCount->setText(rowcount_str); +// resultModel.reset(new QueryResultModel(nullptr , dbres)); +// ui->ResultView->setModel(resultModel.get()); +// ui->tabWidget->setCurrentWidget(ui->dataTab); //statusBar()->showMessage(tr("Query ready.")); } else { if (st == PGRES_COMMAND_OK) { // statusBar()->showMessage(tr("Command OK.")); - QString msg = tr("Query returned succesfully: %1 rows affected, %2 execution time.") - .arg(QString::number(dbres->tuplesAffected())) - .arg(m_stopwatch.elapsed()); //msfloatToHumanReadableString(elapsedTime.count())); + int tuples_affected = dbres->tuplesAffected(); + QString msg; + if (tuples_affected >= 0) + msg = tr("Query returned succesfully: %1 rows affected, execution time %2") + .arg(QString::number(tuples_affected)) + .arg(msfloatToHumanReadableString(elapsedms)); + else + msg = tr("Query returned succesfully, execution time %1") + .arg(msfloatToHumanReadableString(elapsedms)); + ui->messagesEdit->append(msg); ui->tabWidget->setCurrentWidget(ui->messageTab); @@ -476,6 +495,7 @@ void QueryTab::query_ready(std::shared_ptr dbres) } } else { + m_stopwatch.stop(); addLog("query_ready with NO result"); // statusBar()->showMessage(tr("Query cancelled.")); } @@ -483,7 +503,10 @@ void QueryTab::query_ready(std::shared_ptr dbres) void QueryTab::clearResult() { - ui->ResultView->setModel(nullptr); - resultModel.reset(); - ui->lblRowCount->clear(); +// ui->ResultView->setModel(nullptr); +// resultModel.reset(); + for (auto e : resultList) + delete e; + resultList.clear(); +// ui->lblRowCount->clear(); } diff --git a/querytab.h b/querytab.h index a57c8a9..402d244 100644 --- a/querytab.h +++ b/querytab.h @@ -5,12 +5,13 @@ #include "queryresultmodel.h" #include "queryexplainmodel.h" #include "stopwatch.h" +#include "tuplesresultwidget.h" #include #include namespace Ui { -class QueryTab; + class QueryTab; } class MainWindow; @@ -38,11 +39,22 @@ public: void saveCopyAs(); void execute(); - void explainAnalyze(); + void explain(bool analyze); void cancel(); bool canClose(); private: + +// struct ResultTab { +// public: +// std::shared_ptr resultModel; +// std::shared_ptr tuplesResult; +//// ResultTab(std::shared_ptr rm, Ui::TuplesResult *tr) +//// : resultModel(rm), tuplesResult(tr) +//// {} +// }; + using ResultTabContainer = std::vector; + Ui::QueryTab *ui; MainWindow *m_win; std::unique_ptr highlighter; @@ -58,17 +70,20 @@ private: QString promptUserForSaveSqlFilename(); + + ASyncDBConnection m_dbConnection; - std::unique_ptr resultModel; + std::unique_ptr explainModel; + ResultTabContainer resultList; void addLog(QString s); std::string getCommand() const; void explain_ready(ExplainRoot::SPtr explain); - void query_ready(std::shared_ptr dbres); + void query_ready(std::shared_ptr dbres, qint64 elapsedms); - void setTabCaption(const QString &caption); + void setTabCaption(const QString &caption, const QString &tooltip); void clearResult(); private slots: diff --git a/querytab.ui b/querytab.ui index e8f75fe..101518b 100644 --- a/querytab.ui +++ b/querytab.ui @@ -65,61 +65,6 @@ - - - Data - - - - - - - Source Sans Pro - 10 - - - - QAbstractItemView::NoEditTriggers - - - true - - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - - - false - - - 20 - - - - - - - - - - 0ms - - - - - - - TextLabel - - - - - - - - Explain diff --git a/resources.qrc b/resources.qrc index 4d3c217..e1c3cf0 100644 --- a/resources.qrc +++ b/resources.qrc @@ -10,5 +10,8 @@ icons/lightbulb.png icons/table_save.png icons/page_white_add.png + icons/page_white_delete.png + icons/lightbulb_off.png + icons/information.png diff --git a/tuplesresultwidget.cpp b/tuplesresultwidget.cpp new file mode 100644 index 0000000..4cf1582 --- /dev/null +++ b/tuplesresultwidget.cpp @@ -0,0 +1,26 @@ +#include "tuplesresultwidget.h" +#include "ui_tuplesresultwidget.h" +#include "util.h" + +TuplesResultWidget::TuplesResultWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::TuplesResultWidget) +{ + ui->setupUi(this); + ui->lblRowCount->setText(QString()); +} + +TuplesResultWidget::~TuplesResultWidget() +{ + delete ui; +} + +void TuplesResultWidget::setResult(std::shared_ptr res, float ms) +{ + resultModel = res; + ui->ResultView->setModel(resultModel.get()); + + QString rowcount_str = QString("rows: %1").arg(resultModel->rowCount()); + ui->lblRowCount->setText(rowcount_str); + ui->lblElapsedTime->setText(msfloatToHumanReadableString(ms)); +} diff --git a/tuplesresultwidget.h b/tuplesresultwidget.h new file mode 100644 index 0000000..15cd447 --- /dev/null +++ b/tuplesresultwidget.h @@ -0,0 +1,26 @@ +#ifndef TUPLESRESULTWIDGET_H +#define TUPLESRESULTWIDGET_H + +#include "queryresultmodel.h" +#include + +namespace Ui { +class TuplesResultWidget; +} + +class TuplesResultWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TuplesResultWidget(QWidget *parent = 0); + ~TuplesResultWidget(); + + void setResult(std::shared_ptr res, float ms); +private: + Ui::TuplesResultWidget *ui; + + std::shared_ptr resultModel; +}; + +#endif // TUPLESRESULTWIDGET_H diff --git a/tuplesresultwidget.ui b/tuplesresultwidget.ui new file mode 100644 index 0000000..34c08e2 --- /dev/null +++ b/tuplesresultwidget.ui @@ -0,0 +1,99 @@ + + + TuplesResultWidget + + + + 0 + 0 + 400 + 300 + + + + Form + + + + 4 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + Source Sans Pro + 10 + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + false + + + 20 + + + 16 + + + + + + + + 4 + + + 0 + + + 4 + + + 0 + + + + + 0ms + + + + + + + TextLabel + + + + + + + + + + +