diff --git a/.gitignore b/.gitignore index 6433272..d09de83 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ release/ DIST/ Makefile Makefile.Debug -Makefile.Release \ No newline at end of file +Makefile.Release +desktop.ini diff --git a/PgsqlConn.cpp b/PgsqlConn.cpp index a0037cf..8a73292 100644 --- a/PgsqlConn.cpp +++ b/PgsqlConn.cpp @@ -236,6 +236,13 @@ bool Connection::connectStart(const char* params) return conn != nullptr; } +bool Connection::connectStart(const char * const *keywords, + const char * const *values) +{ + conn = PQconnectStartParams(keywords, values, 0); + return conn != nullptr; +} + PostgresPollingStatusType Connection::connectPoll() { return PQconnectPoll(conn); diff --git a/PgsqlConn.h b/PgsqlConn.h index 1826f96..c92797d 100644 --- a/PgsqlConn.h +++ b/PgsqlConn.h @@ -19,18 +19,18 @@ namespace Pgsql { */ - class ConnectionParams { - public: - std::string host; - std::string hostaddr; - unsigned short port = 5432; - std::string dbname; - std::string user; - std::string password; - int connect_timeout = -1; ///< -1 omit (ie uses default) - std::string application_name; +// class ConnectionParams { +// public: +// std::string host; +// std::string hostaddr; +// unsigned short port = 5432; +// std::string dbname; +// std::string user; +// std::string password; +// int connect_timeout = -1; ///< -1 omit (ie uses default) +// std::string application_name; - }; +// }; class ErrorDetails { public: @@ -172,6 +172,8 @@ namespace Pgsql { { return connectStart(params.toUtf8().data()); } + bool connectStart(const char * const *keywords, + const char * const *values); PostgresPollingStatusType connectPoll(); ConnStatusType status(); diff --git a/asyncdbconnection.cpp b/asyncdbconnection.cpp index da5e3cc..dd685bd 100644 --- a/asyncdbconnection.cpp +++ b/asyncdbconnection.cpp @@ -7,13 +7,23 @@ ASyncDBConnection::ASyncDBConnection() } -void ASyncDBConnection::setupConnection(const std::string &connstring) +//void ASyncDBConnection::setupConnection(const std::string &connstring) +//{ +// if (m_thread.joinable()) { +// m_threadData.stop(); +// m_thread.join(); +// } +// m_threadData.m_initString = connstring; +// m_thread = std::thread([this] () { m_threadData.run(); }); +//} + +void ASyncDBConnection::setupConnection(const ConnectionConfig &config) { if (m_thread.joinable()) { m_threadData.stop(); m_thread.join(); } - m_threadData.m_initString = connstring; + m_threadData.m_config = config; m_thread = std::thread([this] () { m_threadData.run(); }); } @@ -100,7 +110,10 @@ bool ASyncDBConnection::Thread::makeConnection() while (!terminateRequested) { // start connecting - bool ok = m_connection.connectStart(m_initString + " client_encoding=utf8"); + //bool ok = m_connection.connectStart(m_initString + " client_encoding=utf8"); + auto keywords = m_config.getKeywords(); + auto values = m_config.getValues(); + bool ok = m_connection.connectStart(keywords, values); auto start = std::chrono::steady_clock::now(); if (ok && m_connection.status() != CONNECTION_BAD) { int sock = m_connection.socket(); diff --git a/asyncdbconnection.h b/asyncdbconnection.h index e9b9425..2e78dc8 100644 --- a/asyncdbconnection.h +++ b/asyncdbconnection.h @@ -3,6 +3,7 @@ #include "PgsqlConn.h" #include "win32event.h" +#include "connectionconfig.h" #include #include #include @@ -26,7 +27,8 @@ public: ASyncDBConnection(); - void setupConnection(const std::string &connstring); +// void setupConnection(const std::string &connstring); + void setupConnection(const ConnectionConfig &config); void closeConnection(); void setStateCallback(on_state_callback state_callback); @@ -77,7 +79,8 @@ private: {} } m_commandQueue; - std::string m_initString; +// std::string m_initString; + ConnectionConfig m_config; Thread(); diff --git a/connectionconfig.cpp b/connectionconfig.cpp index bce1b6b..68fc714 100644 --- a/connectionconfig.cpp +++ b/connectionconfig.cpp @@ -53,7 +53,6 @@ std::vector ConnectionConfig::s_keywords = { ConnectionConfig::ConnectionConfig() : m_applicationName(QCoreApplication::applicationName().toUtf8().data()) - , m_values(s_keywords.size(), nullptr) {} void ConnectionConfig::setName(std::string desc) @@ -69,7 +68,6 @@ const std::string& ConnectionConfig::name() const void ConnectionConfig::setHost(std::string host) { m_host = std::move(host); - m_values[0] = valuePtr(m_host); } const std::string& ConnectionConfig::host() const @@ -80,7 +78,6 @@ const std::string& ConnectionConfig::host() const void ConnectionConfig::setHostAddr(std::string v) { m_hostaddr = std::move(v); - m_values[1] = valuePtr(m_hostaddr); } const std::string& ConnectionConfig::hostAddr() const @@ -91,7 +88,6 @@ const std::string& ConnectionConfig::hostAddr() const void ConnectionConfig::setPort(unsigned short port) { m_port = std::to_string(port); - m_values[2] = valuePtr(m_port); } unsigned short ConnectionConfig::port() const @@ -102,7 +98,6 @@ unsigned short ConnectionConfig::port() const void ConnectionConfig::setUser(std::string v) { m_user = std::move(v); - m_values[3] = valuePtr(m_user); } const std::string& ConnectionConfig::user() const @@ -113,7 +108,6 @@ const std::string& ConnectionConfig::user() const void ConnectionConfig::setPassword(std::string v) { m_password = std::move(v); - m_values[4] = valuePtr(m_password); } const std::string& ConnectionConfig::password() const @@ -124,7 +118,6 @@ const std::string& ConnectionConfig::password() const void ConnectionConfig::setDbname(std::string v) { m_dbname = std::move(v); - m_values[5] = valuePtr(m_dbname); } const std::string& ConnectionConfig::dbname() const @@ -135,7 +128,6 @@ const std::string& ConnectionConfig::dbname() const void ConnectionConfig::setSslMode(SslMode m) { m_sslMode = SslModeToString(m); - m_values[6] = valuePtr(m_sslMode); } SslMode ConnectionConfig::sslMode() const @@ -146,7 +138,6 @@ SslMode ConnectionConfig::sslMode() const void ConnectionConfig::setSslCert(std::string v) { m_sslCert = std::move(v); - m_values[7] = valuePtr(m_sslCert); } const std::string& ConnectionConfig::sslCert() const @@ -157,7 +148,6 @@ const std::string& ConnectionConfig::sslCert() const void ConnectionConfig::setSslKey(std::string v) { m_sslKey = std::move(v); - m_values[8] = valuePtr(m_sslKey); } const std::string& ConnectionConfig::sslKey() const @@ -168,7 +158,6 @@ const std::string& ConnectionConfig::sslKey() const void ConnectionConfig::setSslRootCert(std::string v) { m_sslRootCert = std::move(v); - m_values[9] = valuePtr(m_sslRootCert); } const std::string& ConnectionConfig::sslRootCert() const @@ -179,7 +168,6 @@ const std::string& ConnectionConfig::sslRootCert() const void ConnectionConfig::setSslCrl(std::string v) { m_sslCrl = std::move(v); - m_values[10] = valuePtr(m_sslCrl); } const std::string& ConnectionConfig::sslCrl() const @@ -195,6 +183,18 @@ const char * const * ConnectionConfig::getKeywords() const const char * const * ConnectionConfig::getValues() const { + m_values.resize(s_keywords.size(), nullptr); + m_values[0] = valuePtr(m_host); + m_values[1] = valuePtr(m_hostaddr); + m_values[2] = valuePtr(m_port); + m_values[3] = valuePtr(m_user); + m_values[4] = valuePtr(m_password); + m_values[5] = valuePtr(m_dbname); + m_values[6] = valuePtr(m_sslMode); + m_values[7] = valuePtr(m_sslCert); + m_values[8] = valuePtr(m_sslKey); + m_values[9] = valuePtr(m_sslRootCert); + m_values[10] = valuePtr(m_sslCrl); m_values[11] = "utf8"; m_values[12] = valuePtr(m_applicationName); diff --git a/connectionlistmodel.cpp b/connectionlistmodel.cpp index 30f567c..7b7e02c 100644 --- a/connectionlistmodel.cpp +++ b/connectionlistmodel.cpp @@ -66,7 +66,11 @@ ConnectionListModel::ConnectionListModel(QObject *parent) int ConnectionListModel::rowCount(const QModelIndex &parent) const { - return m_connections.size(); + int result = 0; + if (parent == QModelIndex()) { + result = m_connections.size(); + } + return result; } int ConnectionListModel::columnCount(const QModelIndex &/*parent*/) const @@ -150,7 +154,12 @@ bool ConnectionListModel::setData(const QModelIndex &index, const QVariant &valu Qt::ItemFlags ConnectionListModel::flags(const QModelIndex &index) const { - return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled; + Qt::ItemFlags result; + int row = index.row(); + if (row >= 0 && row < m_connections.size()) { + result = Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled; + } + return result; } @@ -176,6 +185,28 @@ void ConnectionListModel::add(const ConnectionConfig &cfg) emit dataChanged(idx, idx); } +Expected ConnectionListModel::get(int row) +{ + if (row >= 0 && row < m_connections.size()) { + return m_connections.at(row).m_config; + } + else { + return Expected::fromException(std::out_of_range("Invalid row")); + } +} + +//void ConnectionListModel::del(const int idx) +bool ConnectionListModel::removeRows(int row, int count, const QModelIndex &parent) +{ + bool result = false; + if (row >= 0 && row < m_connections.size()) { + auto f = m_connections.begin() + row; + m_connections.erase(f, f + count); + result = true; + } + return result; +} + /// \todo should return an expected as creation of the folder can fail QString ConnectionListModel::iniFileName() { diff --git a/connectionlistmodel.h b/connectionlistmodel.h index 8dfce0e..4397b63 100644 --- a/connectionlistmodel.h +++ b/connectionlistmodel.h @@ -8,6 +8,7 @@ #include #include "connectionconfig.h" +#include "expected.h" class ConnectionListModel : public QAbstractListModel { @@ -23,9 +24,12 @@ public: virtual Qt::ItemFlags flags(const QModelIndex &index) const override; void add(const ConnectionConfig &cfg); + Expected get(int row); + virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; void load(); void save(); + private: class LijstElem { public: diff --git a/connectionmanagerwindow.cpp b/connectionmanagerwindow.cpp index b7db899..c36850a 100644 --- a/connectionmanagerwindow.cpp +++ b/connectionmanagerwindow.cpp @@ -1,6 +1,8 @@ #include "connectionmanagerwindow.h" #include "ui_connectionmanagerwindow.h" +#include "mainwindow.h" #include +#include #include #include "connectionlistmodel.h" @@ -42,24 +44,15 @@ void ConnectionManagerWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { int currow = current.row(); -// int prevrow = previous.row(); m_mapper->setCurrentIndex(currow); -// ui->lineEdit->setText(QString::number(currow)); -// ui->lineEdit_2->setText(QString::number(prevrow)); - -// if(selection.indexes().isEmpty()) { -// clearMyView(); -// } else { -// displayModelIndexInMyView(selection.indexes().first()); -// } } void ConnectionManagerWindow::on_actionDelete_connection_triggered() { auto ci = ui->listView->selectionModel()->currentIndex(); if (ci.isValid()) { - //m_listModel->removeRow(ci.row()); + m_listModel->removeRow(ci.row()); } } @@ -76,3 +69,27 @@ void ConnectionManagerWindow::setupWidgetMappings() m_mapper->addMapping(ui->edtDbname, 6); m_mapper->toFirst(); } + +void ConnectionManagerWindow::on_actionConnect_triggered() +{ + // Open a window for this connection, maybe we should first check the connection? + auto ci = ui->listView->selectionModel()->currentIndex(); + auto cc = m_listModel->get(ci.row()); + if (cc.valid()) { + auto w = new MainWindow; + w->setAttribute( Qt::WA_DeleteOnClose ); + w->setConfig(cc.get()); + w->show(); + } +} + +void ConnectionManagerWindow::on_actionQuit_application_triggered() +{ + auto res = QMessageBox::question(this, "pglab", + tr("Close ALL windows?"), QMessageBox::Yes, QMessageBox::No); + if (res == QMessageBox::Yes) { + QApplication::quit(); + } + + //closeAllWindows(); +} diff --git a/connectionmanagerwindow.h b/connectionmanagerwindow.h index b6145be..da73943 100644 --- a/connectionmanagerwindow.h +++ b/connectionmanagerwindow.h @@ -25,6 +25,10 @@ private slots: void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous); void on_actionDelete_connection_triggered(); + void on_actionConnect_triggered(); + + void on_actionQuit_application_triggered(); + private: Ui::ConnectionManagerWindow *ui; ConnectionListModel *m_listModel = nullptr; diff --git a/connectionmanagerwindow.ui b/connectionmanagerwindow.ui index 671dd7c..33042f3 100644 --- a/connectionmanagerwindow.ui +++ b/connectionmanagerwindow.ui @@ -197,6 +197,13 @@ 25 + + + File + + + + @@ -250,6 +257,11 @@ Connect + + + Quit application + + diff --git a/databasewindow.cpp b/databasewindow.cpp index 1dda978..949a7fd 100644 --- a/databasewindow.cpp +++ b/databasewindow.cpp @@ -1,14 +1,103 @@ -#include "databasewindow.h" +#include "databasewindow.h" #include "ui_databasewindow.h" +#include DatabaseWindow::DatabaseWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::DatabaseWindow) { ui->setupUi(this); + + m_dbConnection.setStateCallback([this](ASyncDBConnection::State st) + { + QueueTask([this, st]() { connectionStateChanged(st); }); + }); + + m_dbConnection.setNoticeCallback([this](Pgsql::ErrorDetails details) + { + QueueTask([this, details]() { receiveNotice(details); }); + }); } DatabaseWindow::~DatabaseWindow() { + m_dbConnection.closeConnection(); + m_dbConnection.setStateCallback(nullptr); delete ui; } + +void DatabaseWindow::setConfig(const ConnectionConfig &config) +{ + m_config = config; + QString title = "pglab - "; + title += m_config.name().c_str(); + setWindowTitle(title); + QueueTask([this]() { startConnect(); }); +} + +void DatabaseWindow::QueueTask(TSQueue::t_Callable c) +{ + m_taskQueue.add(c); + // Theoretically this needs to be only called if the queue was empty because otherwise it already would + // be busy emptying the queue. For now however I think it is safer to call it just to make sure. + QMetaObject::invokeMethod(this, "processCallableQueue", Qt::QueuedConnection); // queues on main thread +} + +void DatabaseWindow::processCallableQueue() +{ + if (!m_taskQueue.empty()) { + auto c = m_taskQueue.pop(); + c(); + if (!m_taskQueue.empty()) { + QTimer::singleShot(0, this, SLOT(processCallableQueue())); + } + } +} + +void DatabaseWindow::startConnect() +{ + m_dbConnection.setupConnection(m_config); +} + +void DatabaseWindow::connectionStateChanged(ASyncDBConnection::State state) +{ + QString status_str; + switch (state) { + case ASyncDBConnection::State::NotConnected: + status_str = tr("Geen verbinding"); + break; + case ASyncDBConnection::State::Connecting: + status_str = tr("Verbinden"); + break; + case ASyncDBConnection::State::Connected: + status_str = tr("Verbonden"); + break; + case ASyncDBConnection::State::QuerySend: + status_str = tr("Query verstuurd"); + break; + case ASyncDBConnection::State::CancelSend: + status_str = tr("Query geannuleerd"); + break; + } +// addLog(status_str); + statusBar()->showMessage(status_str); +} + + +void DatabaseWindow::receiveNotice(Pgsql::ErrorDetails notice) +{ +// QTextCursor cursor = ui->messagesEdit->textCursor(); +// cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); + +// QTextTable *table = cursor.insertTable(4, 2); +// if (table) { +// table->cellAt(1, 0).firstCursorPosition().insertText("State"); +// table->cellAt(1, 1).firstCursorPosition().insertText(QString::fromStdString(notice.state)); +// table->cellAt(2, 0).firstCursorPosition().insertText("Primary"); +// table->cellAt(2, 1).firstCursorPosition().insertText(QString::fromStdString(notice.messagePrimary)); +// table->cellAt(3, 0).firstCursorPosition().insertText("Detail"); +// table->cellAt(3, 1).firstCursorPosition().insertText(QString::fromStdString(notice.messageDetail)); +// } + +} + diff --git a/databasewindow.h b/databasewindow.h index 98ddda3..6addd3d 100644 --- a/databasewindow.h +++ b/databasewindow.h @@ -1,8 +1,11 @@ -#ifndef DATABASEWINDOW_H +#ifndef DATABASEWINDOW_H #define DATABASEWINDOW_H +#include "asyncdbconnection.h" +#include "tsqueue.h" #include + namespace Ui { class DatabaseWindow; } @@ -15,8 +18,26 @@ public: explicit DatabaseWindow(QWidget *parent = 0); ~DatabaseWindow(); + void setConfig(const ConnectionConfig &config); + /* Meant to be called from other threads to pass a code block + * that has to be executed in the context of the thread of the window. + */ + void QueueTask(TSQueue::t_Callable c); + private: Ui::DatabaseWindow *ui; + TSQueue m_taskQueue; + ASyncDBConnection m_dbConnection; + ConnectionConfig m_config; + + + void connectionStateChanged(ASyncDBConnection::State state); + void receiveNotice(Pgsql::ErrorDetails notice); + + void startConnect(); +private slots: + + void processCallableQueue(); }; #endif // DATABASEWINDOW_H diff --git a/databasewindow.ui b/databasewindow.ui index 62d1c1d..516bae8 100644 --- a/databasewindow.ui +++ b/databasewindow.ui @@ -21,6 +21,11 @@ Tab 1 + + + + + diff --git a/expected.h b/expected.h index 18de30d..9beedf6 100644 --- a/expected.h +++ b/expected.h @@ -4,77 +4,78 @@ template class Expected { union { - T ham; - std::exception_ptr spam; + T m_value; + std::exception_ptr m_error; }; - bool gotHam; + bool m_valid; Expected() {} // internal use public: Expected(const T& rhs) - : ham(rhs), gotHam(true) + : m_value(rhs), m_valid(true) {} Expected(T&& rhs) - : ham(std::move(rhs)) - , gotHam(true) + : m_value(std::move(rhs)) + , m_valid(true) {} + Expected(const Expected& ths) - : gotHam(rhs.gotHam) + : m_valid(rhs.valid) { - if (gotHam) { - new (&ham) T(rhs.ham); + if (m_valid) { + new (&m_value) T(rhs.ham); } else { - new (&spam) std::exception_ptr(rhs.spam); + new (&m_error) std::exception_ptr(rhs.spam); } } Expected(Expected &&rhs) - : gotHam(rhs.getHam) + : m_valid(rhs.m_valid) { - if (gotHam) { - new (&ham) T(std::move(rhs.ham)); + if (m_valid) { + new (&m_value) T(std::move(rhs.m_value)); } else { - new (&spam) std::exception_ptr(std::move(rhs.spam)); + new (&m_error) std::exception_ptr(std::move(rhs.m_error)); } } ~Expected() { - if (gotHam) { - ham.~T(); + if (m_valid) { + m_value.~T(); } else { using std::exception_ptr; - spam.~exception_ptr(); + m_error.~exception_ptr(); } } void swap(Expected& rhs) { - if (gotHam) { - if (rhs.gotHam) { + if (m_valid) { + if (rhs.m_valid) { using std::swamp; - swap(ham, rhs.ham); + swap(m_value, rhs.m_value); } else { - auto t = std::move(rhs.spam); - new(&rhs.ham) T(std::move(ham)); - new(&spam) std::exception_ptr(t); - std::swap(gotHam, rhs.getHam); + auto t = std::move(rhs.m_error); + new(&rhs.m_value) T(std::move(m_value)); + new(&m_error) std::exception_ptr(t); + std::swap(m_valid, rhs.getHam); } } else { - if (rhs.gotHam) { + if (rhs.m_valid) { rhs.swap(*this); } else { - spam.swap(rhs.spam); - std::swap(gotHam, rhs.gotHam); + m_error.swap(rhs.m_error); + std::swap(m_valid, rhs.m_valid); } } } @@ -91,8 +92,8 @@ public: static Expected fromException(std::exception_ptr p) { Expected result; - result.gotHam = false; - new (&result.spam) std::exception_ptr(std::move(p)); + result.m_valid = false; + new (&result.m_error) std::exception_ptr(std::move(p)); return result; } @@ -103,31 +104,31 @@ public: bool valid() const { - return gotHam; + return m_valid; } T& get() { - if (!gotHam) { - std::rethrow_exception(spam); + if (!m_valid) { + std::rethrow_exception(m_error); } - return ham; + return m_value; } const T& get() const { - if (!gotHam) { - std::rethrow_exception(spam); + if (!m_valid) { + std::rethrow_exception(m_error); } - return ham; + return m_value; } template bool hasException() const { try { - if (!gotHam) { - std::rethrow_exception(spam); + if (!m_valid) { + std::rethrow_exception(m_error); } } catch (const E& object) { diff --git a/icons/desktop.ini b/icons/desktop.ini index dd2bbf0..a0f2f95 100644 --- a/icons/desktop.ini +++ b/icons/desktop.ini @@ -2,3 +2,12 @@ server_go.png=@server_go.png,0 server_add.png=@server_add.png,0 server_delete.png=@server_delete.png,0 +script_lightning.png=@script_lightning.png,0 +script_delete.png=@script_delete.png,0 +script_go.png=@script_go.png,0 +database.png=@database.png,0 +script.png=@script.png,0 +folder.png=@folder.png,0 +script_save.png=@script_save.png,0 +lightbulb.png=@lightbulb.png,0 +table_save.png=@table_save.png,0 diff --git a/icons/folder.png b/icons/folder.png new file mode 100644 index 0000000..f37bb3e Binary files /dev/null and b/icons/folder.png differ diff --git a/icons/lightbulb.png b/icons/lightbulb.png new file mode 100644 index 0000000..17181a9 Binary files /dev/null and b/icons/lightbulb.png differ diff --git a/icons/script_delete.png b/icons/script_delete.png new file mode 100644 index 0000000..9dfe0e6 Binary files /dev/null and b/icons/script_delete.png differ diff --git a/icons/script_go.png b/icons/script_go.png new file mode 100644 index 0000000..d3b52c9 Binary files /dev/null and b/icons/script_go.png differ diff --git a/icons/script_save.png b/icons/script_save.png new file mode 100644 index 0000000..fec5c79 Binary files /dev/null and b/icons/script_save.png differ diff --git a/icons/table_save.png b/icons/table_save.png new file mode 100644 index 0000000..0440ef9 Binary files /dev/null and b/icons/table_save.png differ diff --git a/mainwindow.cpp b/mainwindow.cpp index a940e0c..4982322 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -93,21 +93,18 @@ MainWindow::MainWindow(QWidget *parent) font.setPointSize(10); ui->queryEdit->setFont(font); highlighter.reset(new SqlHighlighter(ui->queryEdit->document())); - ui->queryEdit->setPlainText(test_query); - ui->connectionStringEdit->setText("user=postgres dbname=foutrapport password=admin"); +// ui->queryEdit->setPlainText(test_query); +// ui->connectionStringEdit->setText("user=postgres dbname=foutrapport password=admin"); - QAction *action; - action = ui->mainToolBar->addAction("connect"); - connect(action, &QAction::triggered, this, &MainWindow::startConnect); +// QAction *action; +// action = ui->mainToolBar->addAction("connect"); +// connect(action, &QAction::triggered, this, &MainWindow::startConnect); - action = ui->mainToolBar->addAction("execute"); - connect(action, &QAction::triggered, this, &MainWindow::performQuery); +// action = ui->mainToolBar->addAction("explain"); +// connect(action, &QAction::triggered, this, &MainWindow::performExplain); - action = ui->mainToolBar->addAction("explain"); - connect(action, &QAction::triggered, this, &MainWindow::performExplain); - - action = ui->mainToolBar->addAction("cancel"); - connect(action, &QAction::triggered, this, &MainWindow::cancel_query); +// action = ui->mainToolBar->addAction("cancel"); +// connect(action, &QAction::triggered, this, &MainWindow::cancel_query); m_dbConnection.setStateCallback([this](ASyncDBConnection::State st) { @@ -130,6 +127,15 @@ MainWindow::~MainWindow() delete ui; } +void MainWindow::setConfig(const ConnectionConfig &config) +{ + m_config = config; + QString title = "pglab - "; + title += m_config.name().c_str(); + setWindowTitle(title); + QueueTask([this]() { startConnect(); }); +} + void MainWindow::QueueTask(TSQueue::t_Callable c) { m_taskQueue.add(c); @@ -175,8 +181,9 @@ void MainWindow::connectionStateChanged(ASyncDBConnection::State state) void MainWindow::startConnect() { - std::string connstr = ui->connectionStringEdit->text().toUtf8().data(); - m_dbConnection.setupConnection(connstr); +// std::string connstr = ui->connectionStringEdit->text().toUtf8().data(); +// m_dbConnection.setupConnection(connstr); + m_dbConnection.setupConnection(m_config); } void MainWindow::performQuery() @@ -206,6 +213,7 @@ void MainWindow::query_ready(std::shared_ptr dbres) if (st == PGRES_TUPLES_OK) { resultModel.reset(new QueryResultModel(nullptr , dbres)); ui->ResultView->setModel(resultModel.get()); + ui->tabWidget->setCurrentWidget(ui->dataTab); statusBar()->showMessage(tr("Query ready.")); } else { @@ -239,6 +247,7 @@ void MainWindow::query_ready(std::shared_ptr dbres) else { statusBar()->showMessage(tr("No tuples returned, possibly an error...")); } + ui->tabWidget->setCurrentWidget(ui->messageTab); receiveNotice(dbres->diagDetails()); } } @@ -303,10 +312,12 @@ void MainWindow::explain_ready(ExplainRoot::SPtr explain) ui->explainTreeView->setColumnWidth(4, 80); ui->explainTreeView->setColumnWidth(5, 80); ui->explainTreeView->setColumnWidth(6, 600); + ui->tabWidget->setCurrentWidget(ui->explainTab); statusBar()->showMessage(tr("Explain ready.")); } else { addLog("Explain no result"); + ui->tabWidget->setCurrentWidget(ui->messageTab); statusBar()->showMessage(tr("Explain failed.")); } } @@ -321,10 +332,6 @@ void MainWindow::receiveNotice(Pgsql::ErrorDetails notice) QTextCursor cursor = ui->messagesEdit->textCursor(); cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); - -// QString msg; -// cursor.insertText("TEST\r\n"); - QTextTable *table = cursor.insertTable(4, 2); if (table) { table->cellAt(1, 0).firstCursorPosition().insertText("State"); @@ -466,3 +473,18 @@ void Copy( ) QApplication.clipboard().setText(selected_text); } #endif + +void MainWindow::on_actionExecute_SQL_triggered() +{ + performQuery(); +} + +void MainWindow::on_actionExplain_Analyze_triggered() +{ + performExplain(); +} + +void MainWindow::on_actionCancel_triggered() +{ + cancel_query(); +} diff --git a/mainwindow.h b/mainwindow.h index c0b9e0c..241b00e 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -2,6 +2,7 @@ #define MAINWINDOW_H #include "asyncdbconnection.h" +#include "connectionconfig.h" #include "tsqueue.h" #include #include @@ -9,6 +10,8 @@ #include #include #include "PgsqlConn.h" +#include +#include class ExplainRoot; class QueryResultModel; @@ -20,28 +23,18 @@ namespace Ui { } namespace Pgsql { - class Connection; - } -#include -#include - -class TaskQueue { -public: - -private: -}; class MainWindow : public QMainWindow { Q_OBJECT - public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); + void setConfig(const ConnectionConfig &config); /* Meant to be called from other threads to pass a code block * that has to be executed in the context of the thread of the window. */ @@ -52,6 +45,8 @@ private: QLabel *m_timeElapsedLabel; std::unique_ptr m_timer; std::chrono::time_point m_startTime; + ConnectionConfig m_config; + void startTimer(); void endTimer(); @@ -88,6 +83,9 @@ private slots: void on_actionExport_data_triggered(); void on_actionClose_triggered(); void on_actionAbout_triggered(); + void on_actionExecute_SQL_triggered(); + void on_actionExplain_Analyze_triggered(); + void on_actionCancel_triggered(); }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index aed18b7..9731ea7 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -11,7 +11,7 @@ - MainWindow + pglab - database @@ -27,9 +27,6 @@ 8 - - - @@ -211,19 +208,38 @@ false + + + + + + + + + + :/icons/folder.png:/icons/folder.png + Load SQL + + + :/icons/script_save.png:/icons/script_save.png + Save SQL + + + :/icons/table_save.png:/icons/table_save.png + Export data @@ -238,8 +254,39 @@ About + + + + :/icons/script_go.png + + + + Execute SQL + + + + + + :/icons/script_delete.png + + + + Cancel + + + + + + :/icons/lightbulb.png:/icons/lightbulb.png + + + Explain Analyze + + - + + + diff --git a/resources.qrc b/resources.qrc index 5cecd03..ad70bd6 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,7 +1,13 @@  - + icons/server_add.png icons/server_delete.png icons/server_go.png + icons/script_delete.png + icons/script_go.png + icons/folder.png + icons/script_save.png + icons/lightbulb.png + icons/table_save.png