#include "mainwindow.h" #include "ui_mainwindow.h" //#include "QueryResultModel.h" //#include "QueryExplainModel.h" #include #include #include #include #include #include #include #include #include #include #include "util.h" //#include namespace pg = Pgsql; const char * test_query = //"SELECT id, program, version, lic_bedrijf, lic_plaats, " //"lic_number, callstack_crc_1, callstack_crc_2, callstack_crc_3, exception_class, " //"exception_message \nFROM foutrapport" "SELECT f1.id, f1.program, f1.version, f1.lic_number, f1.callstack_crc_1, f1.callstack_crc_2, array_agg(f2.id) \n" "FROM foutrapport f1 JOIN foutrapport f2 USING (callstack_crc_2) \n" "WHERE f1.actief \n" "GROUP BY f1.id" ; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); m_timeElapsedLabel = new QLabel(this); statusBar()->addPermanentWidget(m_timeElapsedLabel); // { // QVBoxLayout *layout = new QVBoxLayout; // layout->addWidget(m_queryTab); // layout->setMargin(4); // ui->tab_2->setLayout(layout); // } } MainWindow::~MainWindow() { // m_dbConnection.closeConnection(); // m_dbConnection.setStateCallback(nullptr); delete ui; } void MainWindow::newSqlPage() { QueryTab *qt = new QueryTab(this); qt->setConfig(m_config); // QVBoxLayout *layout = new QVBoxLayout; // layout->addWidget(qt); // layout->setMargin(4); ui->tabWidget->addTab(qt, "Tab"); } QueryTab *MainWindow::GetActiveQueryTab() { QWidget *widget = ui->tabWidget->currentWidget(); QueryTab *qt = dynamic_cast(widget); return qt; } void MainWindow::setConfig(const ConnectionConfig &config) { m_config = config; QString title = "pglab - "; title += m_config.name().c_str(); setWindowTitle(title); newSqlPage(); } void MainWindow::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 MainWindow::processCallableQueue() { if (!m_taskQueue.empty()) { auto c = m_taskQueue.pop(); c(); if (!m_taskQueue.empty()) { QTimer::singleShot(0, this, SLOT(processCallableQueue())); } } } void MainWindow::startTimer() { m_startTime = std::chrono::steady_clock::now(); m_timer = std::make_unique(nullptr); m_timer->setTimerType(Qt::CoarseTimer); connect(m_timer.get(), SIGNAL(timeout()), this, SLOT(updateTimer())); m_timer->start(18); } void MainWindow::updateTimer() { auto nu = std::chrono::steady_clock::now(); std::chrono::duration diff = nu - m_startTime; elapsedTime = diff; m_timeElapsedLabel->setText(msfloatToHumanReadableString(diff.count())); if (m_timer) { int ms = diff.count(); int interval = 18; if (ms >= 10000) { int rem = ms % 1000; interval = 1000 - rem; } else if (ms >= 1000) { interval = 100; } m_timer->start(interval); } } void MainWindow::endTimer() { if (m_timer) { m_timer.reset(); updateTimer(); } } void MainWindow::on_actionLoad_SQL_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { tab->open(); } } void MainWindow::on_actionSave_SQL_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { tab->save(); } } void MainWindow::on_actionSave_SQL_as_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { tab->saveAs(); } } void MainWindow::on_actionSave_copy_of_SQL_as_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { tab->saveCopyAs(); } } void MainWindow::on_actionExport_data_triggered() { QString home_dir = QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory); QString file_name = QFileDialog::getSaveFileName(this, tr("Export data"), home_dir, tr("CSV file (*.csv)")); } void MainWindow::on_actionClose_triggered() { close(); } void MainWindow::on_actionAbout_triggered() { // } #if false void Copy( ) { QString selected_text; // You need a pair of indexes to find the row changes QModelIndex previous = indexes.first(); indexes.removeFirst(); foreach(current, indexes) { QVariant data = model->data(current); QString text = data.toString(); // At this point `text` contains the text in one cell selected_text.append(text); // If you are at the start of the row the row number of the previous index // isn't the same. Text is followed by a row separator, which is a newline. if (current.row() != previous.row()) { selected_text.append('\n'); } // Otherwise it's the same row, so append a column separator, which is a tab. else { selected_text.append('\t'); } previous = current; } QApplication.clipboard().setText(selected_text); } #endif void MainWindow::on_actionExecute_SQL_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { tab->execute(); } } void MainWindow::on_actionExplain_Analyze_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { tab->explainAnalyze(); } } void MainWindow::on_actionCancel_triggered() { QueryTab *tab = GetActiveQueryTab(); if (tab) { tab->cancel(); } } void MainWindow::closeEvent(QCloseEvent *event) { // TODO collect which files need saving // if (!m_queryTextChanged || continueWithoutSaving()) { // event->accept(); // } // else { // event->ignore(); // } } void MainWindow::showEvent(QShowEvent *event) { if (!event->spontaneous()) { // m_queryTextChanged = false; } event->accept(); } void MainWindow::on_actionNew_SQL_triggered() { newSqlPage(); }