Connection manager can now open a query window for selected connection.
Query window has now buttons with icons made in the designer for better looks. Depending on received responses from the database the tabcontrol with the message, data and explain tab now switches to the appropriate tab.
This commit is contained in:
parent
88fcc0338d
commit
d19741f111
26 changed files with 408 additions and 116 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,3 +4,4 @@ DIST/
|
||||||
Makefile
|
Makefile
|
||||||
Makefile.Debug
|
Makefile.Debug
|
||||||
Makefile.Release
|
Makefile.Release
|
||||||
|
desktop.ini
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,13 @@ bool Connection::connectStart(const char* params)
|
||||||
return conn != nullptr;
|
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()
|
PostgresPollingStatusType Connection::connectPoll()
|
||||||
{
|
{
|
||||||
return PQconnectPoll(conn);
|
return PQconnectPoll(conn);
|
||||||
|
|
|
||||||
24
PgsqlConn.h
24
PgsqlConn.h
|
|
@ -19,18 +19,18 @@ namespace Pgsql {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ConnectionParams {
|
// class ConnectionParams {
|
||||||
public:
|
// public:
|
||||||
std::string host;
|
// std::string host;
|
||||||
std::string hostaddr;
|
// std::string hostaddr;
|
||||||
unsigned short port = 5432;
|
// unsigned short port = 5432;
|
||||||
std::string dbname;
|
// std::string dbname;
|
||||||
std::string user;
|
// std::string user;
|
||||||
std::string password;
|
// std::string password;
|
||||||
int connect_timeout = -1; ///< -1 omit (ie uses default)
|
// int connect_timeout = -1; ///< -1 omit (ie uses default)
|
||||||
std::string application_name;
|
// std::string application_name;
|
||||||
|
|
||||||
};
|
// };
|
||||||
|
|
||||||
class ErrorDetails {
|
class ErrorDetails {
|
||||||
public:
|
public:
|
||||||
|
|
@ -172,6 +172,8 @@ namespace Pgsql {
|
||||||
{
|
{
|
||||||
return connectStart(params.toUtf8().data());
|
return connectStart(params.toUtf8().data());
|
||||||
}
|
}
|
||||||
|
bool connectStart(const char * const *keywords,
|
||||||
|
const char * const *values);
|
||||||
|
|
||||||
PostgresPollingStatusType connectPoll();
|
PostgresPollingStatusType connectPoll();
|
||||||
ConnStatusType status();
|
ConnStatusType status();
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
if (m_thread.joinable()) {
|
||||||
m_threadData.stop();
|
m_threadData.stop();
|
||||||
m_thread.join();
|
m_thread.join();
|
||||||
}
|
}
|
||||||
m_threadData.m_initString = connstring;
|
m_threadData.m_config = config;
|
||||||
m_thread = std::thread([this] () { m_threadData.run(); });
|
m_thread = std::thread([this] () { m_threadData.run(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,7 +110,10 @@ bool ASyncDBConnection::Thread::makeConnection()
|
||||||
while (!terminateRequested) {
|
while (!terminateRequested) {
|
||||||
|
|
||||||
// start connecting
|
// 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();
|
auto start = std::chrono::steady_clock::now();
|
||||||
if (ok && m_connection.status() != CONNECTION_BAD) {
|
if (ok && m_connection.status() != CONNECTION_BAD) {
|
||||||
int sock = m_connection.socket();
|
int sock = m_connection.socket();
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "PgsqlConn.h"
|
#include "PgsqlConn.h"
|
||||||
#include "win32event.h"
|
#include "win32event.h"
|
||||||
|
#include "connectionconfig.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
@ -26,7 +27,8 @@ public:
|
||||||
|
|
||||||
ASyncDBConnection();
|
ASyncDBConnection();
|
||||||
|
|
||||||
void setupConnection(const std::string &connstring);
|
// void setupConnection(const std::string &connstring);
|
||||||
|
void setupConnection(const ConnectionConfig &config);
|
||||||
void closeConnection();
|
void closeConnection();
|
||||||
|
|
||||||
void setStateCallback(on_state_callback state_callback);
|
void setStateCallback(on_state_callback state_callback);
|
||||||
|
|
@ -77,7 +79,8 @@ private:
|
||||||
{}
|
{}
|
||||||
} m_commandQueue;
|
} m_commandQueue;
|
||||||
|
|
||||||
std::string m_initString;
|
// std::string m_initString;
|
||||||
|
ConnectionConfig m_config;
|
||||||
|
|
||||||
Thread();
|
Thread();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ std::vector<const char*> ConnectionConfig::s_keywords = {
|
||||||
|
|
||||||
ConnectionConfig::ConnectionConfig()
|
ConnectionConfig::ConnectionConfig()
|
||||||
: m_applicationName(QCoreApplication::applicationName().toUtf8().data())
|
: m_applicationName(QCoreApplication::applicationName().toUtf8().data())
|
||||||
, m_values(s_keywords.size(), nullptr)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void ConnectionConfig::setName(std::string desc)
|
void ConnectionConfig::setName(std::string desc)
|
||||||
|
|
@ -69,7 +68,6 @@ const std::string& ConnectionConfig::name() const
|
||||||
void ConnectionConfig::setHost(std::string host)
|
void ConnectionConfig::setHost(std::string host)
|
||||||
{
|
{
|
||||||
m_host = std::move(host);
|
m_host = std::move(host);
|
||||||
m_values[0] = valuePtr(m_host);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::host() const
|
const std::string& ConnectionConfig::host() const
|
||||||
|
|
@ -80,7 +78,6 @@ const std::string& ConnectionConfig::host() const
|
||||||
void ConnectionConfig::setHostAddr(std::string v)
|
void ConnectionConfig::setHostAddr(std::string v)
|
||||||
{
|
{
|
||||||
m_hostaddr = std::move(v);
|
m_hostaddr = std::move(v);
|
||||||
m_values[1] = valuePtr(m_hostaddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::hostAddr() const
|
const std::string& ConnectionConfig::hostAddr() const
|
||||||
|
|
@ -91,7 +88,6 @@ const std::string& ConnectionConfig::hostAddr() const
|
||||||
void ConnectionConfig::setPort(unsigned short port)
|
void ConnectionConfig::setPort(unsigned short port)
|
||||||
{
|
{
|
||||||
m_port = std::to_string(port);
|
m_port = std::to_string(port);
|
||||||
m_values[2] = valuePtr(m_port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short ConnectionConfig::port() const
|
unsigned short ConnectionConfig::port() const
|
||||||
|
|
@ -102,7 +98,6 @@ unsigned short ConnectionConfig::port() const
|
||||||
void ConnectionConfig::setUser(std::string v)
|
void ConnectionConfig::setUser(std::string v)
|
||||||
{
|
{
|
||||||
m_user = std::move(v);
|
m_user = std::move(v);
|
||||||
m_values[3] = valuePtr(m_user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::user() const
|
const std::string& ConnectionConfig::user() const
|
||||||
|
|
@ -113,7 +108,6 @@ const std::string& ConnectionConfig::user() const
|
||||||
void ConnectionConfig::setPassword(std::string v)
|
void ConnectionConfig::setPassword(std::string v)
|
||||||
{
|
{
|
||||||
m_password = std::move(v);
|
m_password = std::move(v);
|
||||||
m_values[4] = valuePtr(m_password);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::password() const
|
const std::string& ConnectionConfig::password() const
|
||||||
|
|
@ -124,7 +118,6 @@ const std::string& ConnectionConfig::password() const
|
||||||
void ConnectionConfig::setDbname(std::string v)
|
void ConnectionConfig::setDbname(std::string v)
|
||||||
{
|
{
|
||||||
m_dbname = std::move(v);
|
m_dbname = std::move(v);
|
||||||
m_values[5] = valuePtr(m_dbname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::dbname() const
|
const std::string& ConnectionConfig::dbname() const
|
||||||
|
|
@ -135,7 +128,6 @@ const std::string& ConnectionConfig::dbname() const
|
||||||
void ConnectionConfig::setSslMode(SslMode m)
|
void ConnectionConfig::setSslMode(SslMode m)
|
||||||
{
|
{
|
||||||
m_sslMode = SslModeToString(m);
|
m_sslMode = SslModeToString(m);
|
||||||
m_values[6] = valuePtr(m_sslMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SslMode ConnectionConfig::sslMode() const
|
SslMode ConnectionConfig::sslMode() const
|
||||||
|
|
@ -146,7 +138,6 @@ SslMode ConnectionConfig::sslMode() const
|
||||||
void ConnectionConfig::setSslCert(std::string v)
|
void ConnectionConfig::setSslCert(std::string v)
|
||||||
{
|
{
|
||||||
m_sslCert = std::move(v);
|
m_sslCert = std::move(v);
|
||||||
m_values[7] = valuePtr(m_sslCert);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::sslCert() const
|
const std::string& ConnectionConfig::sslCert() const
|
||||||
|
|
@ -157,7 +148,6 @@ const std::string& ConnectionConfig::sslCert() const
|
||||||
void ConnectionConfig::setSslKey(std::string v)
|
void ConnectionConfig::setSslKey(std::string v)
|
||||||
{
|
{
|
||||||
m_sslKey = std::move(v);
|
m_sslKey = std::move(v);
|
||||||
m_values[8] = valuePtr(m_sslKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::sslKey() const
|
const std::string& ConnectionConfig::sslKey() const
|
||||||
|
|
@ -168,7 +158,6 @@ const std::string& ConnectionConfig::sslKey() const
|
||||||
void ConnectionConfig::setSslRootCert(std::string v)
|
void ConnectionConfig::setSslRootCert(std::string v)
|
||||||
{
|
{
|
||||||
m_sslRootCert = std::move(v);
|
m_sslRootCert = std::move(v);
|
||||||
m_values[9] = valuePtr(m_sslRootCert);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::sslRootCert() const
|
const std::string& ConnectionConfig::sslRootCert() const
|
||||||
|
|
@ -179,7 +168,6 @@ const std::string& ConnectionConfig::sslRootCert() const
|
||||||
void ConnectionConfig::setSslCrl(std::string v)
|
void ConnectionConfig::setSslCrl(std::string v)
|
||||||
{
|
{
|
||||||
m_sslCrl = std::move(v);
|
m_sslCrl = std::move(v);
|
||||||
m_values[10] = valuePtr(m_sslCrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& ConnectionConfig::sslCrl() const
|
const std::string& ConnectionConfig::sslCrl() const
|
||||||
|
|
@ -195,6 +183,18 @@ const char * const * ConnectionConfig::getKeywords() const
|
||||||
|
|
||||||
const char * const * ConnectionConfig::getValues() 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[11] = "utf8";
|
||||||
m_values[12] = valuePtr(m_applicationName);
|
m_values[12] = valuePtr(m_applicationName);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,11 @@ ConnectionListModel::ConnectionListModel(QObject *parent)
|
||||||
|
|
||||||
int ConnectionListModel::rowCount(const QModelIndex &parent) const
|
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
|
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
|
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);
|
emit dataChanged(idx, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expected<ConnectionConfig> ConnectionListModel::get(int row)
|
||||||
|
{
|
||||||
|
if (row >= 0 && row < m_connections.size()) {
|
||||||
|
return m_connections.at(row).m_config;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Expected<ConnectionConfig>::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
|
/// \todo should return an expected as creation of the folder can fail
|
||||||
QString ConnectionListModel::iniFileName()
|
QString ConnectionListModel::iniFileName()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include "connectionconfig.h"
|
#include "connectionconfig.h"
|
||||||
|
#include "expected.h"
|
||||||
|
|
||||||
|
|
||||||
class ConnectionListModel : public QAbstractListModel {
|
class ConnectionListModel : public QAbstractListModel {
|
||||||
|
|
@ -23,9 +24,12 @@ public:
|
||||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
|
||||||
void add(const ConnectionConfig &cfg);
|
void add(const ConnectionConfig &cfg);
|
||||||
|
Expected<ConnectionConfig> get(int row);
|
||||||
|
virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class LijstElem {
|
class LijstElem {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#include "connectionmanagerwindow.h"
|
#include "connectionmanagerwindow.h"
|
||||||
#include "ui_connectionmanagerwindow.h"
|
#include "ui_connectionmanagerwindow.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
#include <QDataWidgetMapper>
|
#include <QDataWidgetMapper>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
#include "connectionlistmodel.h"
|
#include "connectionlistmodel.h"
|
||||||
|
|
@ -42,24 +44,15 @@ void ConnectionManagerWindow::on_currentChanged(const QModelIndex ¤t,
|
||||||
const QModelIndex &previous)
|
const QModelIndex &previous)
|
||||||
{
|
{
|
||||||
int currow = current.row();
|
int currow = current.row();
|
||||||
// int prevrow = previous.row();
|
|
||||||
|
|
||||||
m_mapper->setCurrentIndex(currow);
|
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()
|
void ConnectionManagerWindow::on_actionDelete_connection_triggered()
|
||||||
{
|
{
|
||||||
auto ci = ui->listView->selectionModel()->currentIndex();
|
auto ci = ui->listView->selectionModel()->currentIndex();
|
||||||
if (ci.isValid()) {
|
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->addMapping(ui->edtDbname, 6);
|
||||||
m_mapper->toFirst();
|
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();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ private slots:
|
||||||
void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
void on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
void on_actionDelete_connection_triggered();
|
void on_actionDelete_connection_triggered();
|
||||||
|
|
||||||
|
void on_actionConnect_triggered();
|
||||||
|
|
||||||
|
void on_actionQuit_application_triggered();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ConnectionManagerWindow *ui;
|
Ui::ConnectionManagerWindow *ui;
|
||||||
ConnectionListModel *m_listModel = nullptr;
|
ConnectionListModel *m_listModel = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,13 @@
|
||||||
<height>25</height>
|
<height>25</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QMenu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionQuit_application"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
<widget class="QToolBar" name="toolBar">
|
<widget class="QToolBar" name="toolBar">
|
||||||
|
|
@ -250,6 +257,11 @@
|
||||||
<string>Connect</string>
|
<string>Connect</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionQuit_application">
|
||||||
|
<property name="text">
|
||||||
|
<string>Quit application</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="resources.qrc"/>
|
<include location="resources.qrc"/>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,103 @@
|
||||||
#include "databasewindow.h"
|
#include "databasewindow.h"
|
||||||
#include "ui_databasewindow.h"
|
#include "ui_databasewindow.h"
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
DatabaseWindow::DatabaseWindow(QWidget *parent) :
|
DatabaseWindow::DatabaseWindow(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
ui(new Ui::DatabaseWindow)
|
ui(new Ui::DatabaseWindow)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
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()
|
DatabaseWindow::~DatabaseWindow()
|
||||||
{
|
{
|
||||||
|
m_dbConnection.closeConnection();
|
||||||
|
m_dbConnection.setStateCallback(nullptr);
|
||||||
delete ui;
|
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));
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
#ifndef DATABASEWINDOW_H
|
#ifndef DATABASEWINDOW_H
|
||||||
#define DATABASEWINDOW_H
|
#define DATABASEWINDOW_H
|
||||||
|
|
||||||
|
#include "asyncdbconnection.h"
|
||||||
|
#include "tsqueue.h"
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class DatabaseWindow;
|
class DatabaseWindow;
|
||||||
}
|
}
|
||||||
|
|
@ -15,8 +18,26 @@ public:
|
||||||
explicit DatabaseWindow(QWidget *parent = 0);
|
explicit DatabaseWindow(QWidget *parent = 0);
|
||||||
~DatabaseWindow();
|
~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:
|
private:
|
||||||
Ui::DatabaseWindow *ui;
|
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
|
#endif // DATABASEWINDOW_H
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Tab 1</string>
|
<string>Tab 1</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="tableView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_2">
|
<widget class="QWidget" name="tab_2">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
|
|
||||||
77
expected.h
77
expected.h
|
|
@ -4,77 +4,78 @@
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Expected {
|
class Expected {
|
||||||
union {
|
union {
|
||||||
T ham;
|
T m_value;
|
||||||
std::exception_ptr spam;
|
std::exception_ptr m_error;
|
||||||
};
|
};
|
||||||
bool gotHam;
|
bool m_valid;
|
||||||
Expected() {} // internal use
|
Expected() {} // internal use
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Expected(const T& rhs)
|
Expected(const T& rhs)
|
||||||
: ham(rhs), gotHam(true)
|
: m_value(rhs), m_valid(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Expected(T&& rhs)
|
Expected(T&& rhs)
|
||||||
: ham(std::move(rhs))
|
: m_value(std::move(rhs))
|
||||||
, gotHam(true)
|
, m_valid(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
Expected(const Expected& ths)
|
Expected(const Expected& ths)
|
||||||
: gotHam(rhs.gotHam)
|
: m_valid(rhs.valid)
|
||||||
{
|
{
|
||||||
if (gotHam) {
|
if (m_valid) {
|
||||||
new (&ham) T(rhs.ham);
|
new (&m_value) T(rhs.ham);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
new (&spam) std::exception_ptr(rhs.spam);
|
new (&m_error) std::exception_ptr(rhs.spam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected(Expected &&rhs)
|
Expected(Expected &&rhs)
|
||||||
: gotHam(rhs.getHam)
|
: m_valid(rhs.m_valid)
|
||||||
{
|
{
|
||||||
if (gotHam) {
|
if (m_valid) {
|
||||||
new (&ham) T(std::move(rhs.ham));
|
new (&m_value) T(std::move(rhs.m_value));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
new (&spam) std::exception_ptr(std::move(rhs.spam));
|
new (&m_error) std::exception_ptr(std::move(rhs.m_error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~Expected()
|
~Expected()
|
||||||
{
|
{
|
||||||
if (gotHam) {
|
if (m_valid) {
|
||||||
ham.~T();
|
m_value.~T();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using std::exception_ptr;
|
using std::exception_ptr;
|
||||||
spam.~exception_ptr();
|
m_error.~exception_ptr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Expected& rhs)
|
void swap(Expected& rhs)
|
||||||
{
|
{
|
||||||
if (gotHam) {
|
if (m_valid) {
|
||||||
if (rhs.gotHam) {
|
if (rhs.m_valid) {
|
||||||
using std::swamp;
|
using std::swamp;
|
||||||
swap(ham, rhs.ham);
|
swap(m_value, rhs.m_value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto t = std::move(rhs.spam);
|
auto t = std::move(rhs.m_error);
|
||||||
new(&rhs.ham) T(std::move(ham));
|
new(&rhs.m_value) T(std::move(m_value));
|
||||||
new(&spam) std::exception_ptr(t);
|
new(&m_error) std::exception_ptr(t);
|
||||||
std::swap(gotHam, rhs.getHam);
|
std::swap(m_valid, rhs.getHam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (rhs.gotHam) {
|
if (rhs.m_valid) {
|
||||||
rhs.swap(*this);
|
rhs.swap(*this);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
spam.swap(rhs.spam);
|
m_error.swap(rhs.m_error);
|
||||||
std::swap(gotHam, rhs.gotHam);
|
std::swap(m_valid, rhs.m_valid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -91,8 +92,8 @@ public:
|
||||||
static Expected<T> fromException(std::exception_ptr p)
|
static Expected<T> fromException(std::exception_ptr p)
|
||||||
{
|
{
|
||||||
Expected<T> result;
|
Expected<T> result;
|
||||||
result.gotHam = false;
|
result.m_valid = false;
|
||||||
new (&result.spam) std::exception_ptr(std::move(p));
|
new (&result.m_error) std::exception_ptr(std::move(p));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,31 +104,31 @@ public:
|
||||||
|
|
||||||
bool valid() const
|
bool valid() const
|
||||||
{
|
{
|
||||||
return gotHam;
|
return m_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& get()
|
T& get()
|
||||||
{
|
{
|
||||||
if (!gotHam) {
|
if (!m_valid) {
|
||||||
std::rethrow_exception(spam);
|
std::rethrow_exception(m_error);
|
||||||
}
|
}
|
||||||
return ham;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& get() const
|
const T& get() const
|
||||||
{
|
{
|
||||||
if (!gotHam) {
|
if (!m_valid) {
|
||||||
std::rethrow_exception(spam);
|
std::rethrow_exception(m_error);
|
||||||
}
|
}
|
||||||
return ham;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class E>
|
template <class E>
|
||||||
bool hasException() const
|
bool hasException() const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (!gotHam) {
|
if (!m_valid) {
|
||||||
std::rethrow_exception(spam);
|
std::rethrow_exception(m_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const E& object) {
|
catch (const E& object) {
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,12 @@
|
||||||
server_go.png=@server_go.png,0
|
server_go.png=@server_go.png,0
|
||||||
server_add.png=@server_add.png,0
|
server_add.png=@server_add.png,0
|
||||||
server_delete.png=@server_delete.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
|
||||||
|
|
|
||||||
BIN
icons/folder.png
Normal file
BIN
icons/folder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/lightbulb.png
Normal file
BIN
icons/lightbulb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
icons/script_delete.png
Normal file
BIN
icons/script_delete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
icons/script_go.png
Normal file
BIN
icons/script_go.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
icons/script_save.png
Normal file
BIN
icons/script_save.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/table_save.png
Normal file
BIN
icons/table_save.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -93,21 +93,18 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
font.setPointSize(10);
|
font.setPointSize(10);
|
||||||
ui->queryEdit->setFont(font);
|
ui->queryEdit->setFont(font);
|
||||||
highlighter.reset(new SqlHighlighter(ui->queryEdit->document()));
|
highlighter.reset(new SqlHighlighter(ui->queryEdit->document()));
|
||||||
ui->queryEdit->setPlainText(test_query);
|
// ui->queryEdit->setPlainText(test_query);
|
||||||
ui->connectionStringEdit->setText("user=postgres dbname=foutrapport password=admin");
|
// ui->connectionStringEdit->setText("user=postgres dbname=foutrapport password=admin");
|
||||||
|
|
||||||
QAction *action;
|
// QAction *action;
|
||||||
action = ui->mainToolBar->addAction("connect");
|
// action = ui->mainToolBar->addAction("connect");
|
||||||
connect(action, &QAction::triggered, this, &MainWindow::startConnect);
|
// connect(action, &QAction::triggered, this, &MainWindow::startConnect);
|
||||||
|
|
||||||
action = ui->mainToolBar->addAction("execute");
|
// action = ui->mainToolBar->addAction("explain");
|
||||||
connect(action, &QAction::triggered, this, &MainWindow::performQuery);
|
// connect(action, &QAction::triggered, this, &MainWindow::performExplain);
|
||||||
|
|
||||||
action = ui->mainToolBar->addAction("explain");
|
// action = ui->mainToolBar->addAction("cancel");
|
||||||
connect(action, &QAction::triggered, this, &MainWindow::performExplain);
|
// 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)
|
m_dbConnection.setStateCallback([this](ASyncDBConnection::State st)
|
||||||
{
|
{
|
||||||
|
|
@ -130,6 +127,15 @@ MainWindow::~MainWindow()
|
||||||
delete ui;
|
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)
|
void MainWindow::QueueTask(TSQueue::t_Callable c)
|
||||||
{
|
{
|
||||||
m_taskQueue.add(c);
|
m_taskQueue.add(c);
|
||||||
|
|
@ -175,8 +181,9 @@ void MainWindow::connectionStateChanged(ASyncDBConnection::State state)
|
||||||
|
|
||||||
void MainWindow::startConnect()
|
void MainWindow::startConnect()
|
||||||
{
|
{
|
||||||
std::string connstr = ui->connectionStringEdit->text().toUtf8().data();
|
// std::string connstr = ui->connectionStringEdit->text().toUtf8().data();
|
||||||
m_dbConnection.setupConnection(connstr);
|
// m_dbConnection.setupConnection(connstr);
|
||||||
|
m_dbConnection.setupConnection(m_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::performQuery()
|
void MainWindow::performQuery()
|
||||||
|
|
@ -206,6 +213,7 @@ void MainWindow::query_ready(std::shared_ptr<Pgsql::Result> dbres)
|
||||||
if (st == PGRES_TUPLES_OK) {
|
if (st == PGRES_TUPLES_OK) {
|
||||||
resultModel.reset(new QueryResultModel(nullptr , dbres));
|
resultModel.reset(new QueryResultModel(nullptr , dbres));
|
||||||
ui->ResultView->setModel(resultModel.get());
|
ui->ResultView->setModel(resultModel.get());
|
||||||
|
ui->tabWidget->setCurrentWidget(ui->dataTab);
|
||||||
statusBar()->showMessage(tr("Query ready."));
|
statusBar()->showMessage(tr("Query ready."));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -239,6 +247,7 @@ void MainWindow::query_ready(std::shared_ptr<Pgsql::Result> dbres)
|
||||||
else {
|
else {
|
||||||
statusBar()->showMessage(tr("No tuples returned, possibly an error..."));
|
statusBar()->showMessage(tr("No tuples returned, possibly an error..."));
|
||||||
}
|
}
|
||||||
|
ui->tabWidget->setCurrentWidget(ui->messageTab);
|
||||||
receiveNotice(dbres->diagDetails());
|
receiveNotice(dbres->diagDetails());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -303,10 +312,12 @@ void MainWindow::explain_ready(ExplainRoot::SPtr explain)
|
||||||
ui->explainTreeView->setColumnWidth(4, 80);
|
ui->explainTreeView->setColumnWidth(4, 80);
|
||||||
ui->explainTreeView->setColumnWidth(5, 80);
|
ui->explainTreeView->setColumnWidth(5, 80);
|
||||||
ui->explainTreeView->setColumnWidth(6, 600);
|
ui->explainTreeView->setColumnWidth(6, 600);
|
||||||
|
ui->tabWidget->setCurrentWidget(ui->explainTab);
|
||||||
statusBar()->showMessage(tr("Explain ready."));
|
statusBar()->showMessage(tr("Explain ready."));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addLog("Explain no result");
|
addLog("Explain no result");
|
||||||
|
ui->tabWidget->setCurrentWidget(ui->messageTab);
|
||||||
statusBar()->showMessage(tr("Explain failed."));
|
statusBar()->showMessage(tr("Explain failed."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -321,10 +332,6 @@ void MainWindow::receiveNotice(Pgsql::ErrorDetails notice)
|
||||||
QTextCursor cursor = ui->messagesEdit->textCursor();
|
QTextCursor cursor = ui->messagesEdit->textCursor();
|
||||||
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
|
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
|
||||||
|
|
||||||
|
|
||||||
// QString msg;
|
|
||||||
// cursor.insertText("TEST\r\n");
|
|
||||||
|
|
||||||
QTextTable *table = cursor.insertTable(4, 2);
|
QTextTable *table = cursor.insertTable(4, 2);
|
||||||
if (table) {
|
if (table) {
|
||||||
table->cellAt(1, 0).firstCursorPosition().insertText("State");
|
table->cellAt(1, 0).firstCursorPosition().insertText("State");
|
||||||
|
|
@ -466,3 +473,18 @@ void Copy( )
|
||||||
QApplication.clipboard().setText(selected_text);
|
QApplication.clipboard().setText(selected_text);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void MainWindow::on_actionExecute_SQL_triggered()
|
||||||
|
{
|
||||||
|
performQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionExplain_Analyze_triggered()
|
||||||
|
{
|
||||||
|
performExplain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionCancel_triggered()
|
||||||
|
{
|
||||||
|
cancel_query();
|
||||||
|
}
|
||||||
|
|
|
||||||
20
mainwindow.h
20
mainwindow.h
|
|
@ -2,6 +2,7 @@
|
||||||
#define MAINWINDOW_H
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
#include "asyncdbconnection.h"
|
#include "asyncdbconnection.h"
|
||||||
|
#include "connectionconfig.h"
|
||||||
#include "tsqueue.h"
|
#include "tsqueue.h"
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
@ -9,6 +10,8 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include "PgsqlConn.h"
|
#include "PgsqlConn.h"
|
||||||
|
#include <deque>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class ExplainRoot;
|
class ExplainRoot;
|
||||||
class QueryResultModel;
|
class QueryResultModel;
|
||||||
|
|
@ -20,28 +23,18 @@ namespace Ui {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Pgsql {
|
namespace Pgsql {
|
||||||
|
|
||||||
class Connection;
|
class Connection;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
class TaskQueue {
|
|
||||||
public:
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QWidget *parent = 0);
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
void setConfig(const ConnectionConfig &config);
|
||||||
/* Meant to be called from other threads to pass a code block
|
/* 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.
|
* that has to be executed in the context of the thread of the window.
|
||||||
*/
|
*/
|
||||||
|
|
@ -52,6 +45,8 @@ private:
|
||||||
QLabel *m_timeElapsedLabel;
|
QLabel *m_timeElapsedLabel;
|
||||||
std::unique_ptr<QTimer> m_timer;
|
std::unique_ptr<QTimer> m_timer;
|
||||||
std::chrono::time_point<std::chrono::steady_clock> m_startTime;
|
std::chrono::time_point<std::chrono::steady_clock> m_startTime;
|
||||||
|
ConnectionConfig m_config;
|
||||||
|
|
||||||
|
|
||||||
void startTimer();
|
void startTimer();
|
||||||
void endTimer();
|
void endTimer();
|
||||||
|
|
@ -88,6 +83,9 @@ private slots:
|
||||||
void on_actionExport_data_triggered();
|
void on_actionExport_data_triggered();
|
||||||
void on_actionClose_triggered();
|
void on_actionClose_triggered();
|
||||||
void on_actionAbout_triggered();
|
void on_actionAbout_triggered();
|
||||||
|
void on_actionExecute_SQL_triggered();
|
||||||
|
void on_actionExplain_Analyze_triggered();
|
||||||
|
void on_actionCancel_triggered();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>MainWindow</string>
|
<string>pglab - database</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
|
@ -27,9 +27,6 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>8</number>
|
<number>8</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="connectionStringEdit"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSplitter" name="splitter">
|
<widget class="QSplitter" name="splitter">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
@ -211,19 +208,38 @@
|
||||||
<attribute name="toolBarBreak">
|
<attribute name="toolBarBreak">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<addaction name="actionLoad_SQL"/>
|
||||||
|
<addaction name="actionSave_SQL"/>
|
||||||
|
<addaction name="actionExport_data"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionExecute_SQL"/>
|
||||||
|
<addaction name="actionExplain_Analyze"/>
|
||||||
|
<addaction name="actionCancel"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusBar"/>
|
<widget class="QStatusBar" name="statusBar"/>
|
||||||
<action name="actionLoad_SQL">
|
<action name="actionLoad_SQL">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resources.qrc">
|
||||||
|
<normaloff>:/icons/folder.png</normaloff>:/icons/folder.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Load SQL</string>
|
<string>Load SQL</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionSave_SQL">
|
<action name="actionSave_SQL">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resources.qrc">
|
||||||
|
<normaloff>:/icons/script_save.png</normaloff>:/icons/script_save.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save SQL</string>
|
<string>Save SQL</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionExport_data">
|
<action name="actionExport_data">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resources.qrc">
|
||||||
|
<normaloff>:/icons/table_save.png</normaloff>:/icons/table_save.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Export data</string>
|
<string>Export data</string>
|
||||||
</property>
|
</property>
|
||||||
|
|
@ -238,8 +254,39 @@
|
||||||
<string>About</string>
|
<string>About</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionExecute_SQL">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normalon>:/icons/script_go.png</normalon>
|
||||||
|
</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Execute SQL</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionCancel">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normalon>:/icons/script_delete.png</normalon>
|
||||||
|
</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionExplain_Analyze">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="resources.qrc">
|
||||||
|
<normaloff>:/icons/lightbulb.png</normaloff>:/icons/lightbulb.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Explain Analyze</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="resources.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource>
|
<qresource prefix="/">
|
||||||
<file>icons/server_add.png</file>
|
<file>icons/server_add.png</file>
|
||||||
<file>icons/server_delete.png</file>
|
<file>icons/server_delete.png</file>
|
||||||
<file>icons/server_go.png</file>
|
<file>icons/server_go.png</file>
|
||||||
|
<file>icons/script_delete.png</file>
|
||||||
|
<file>icons/script_go.png</file>
|
||||||
|
<file>icons/folder.png</file>
|
||||||
|
<file>icons/script_save.png</file>
|
||||||
|
<file>icons/lightbulb.png</file>
|
||||||
|
<file>icons/table_save.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue