#include "BackupDialog.h" #include "BackupFormatModel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 # include // for CreateProcess flags #endif QPlainTextEdit* createStdOutput(QWidget *parent) { auto stdOutput = new QPlainTextEdit(parent); stdOutput->setObjectName(QString::fromUtf8("stdOutput")); QPalette palette; QBrush brush(QColor(255, 255, 255, 255)); brush.setStyle(Qt::SolidPattern); palette.setBrush(QPalette::Active, QPalette::Text, brush); QBrush brush1(QColor(0, 0, 0, 255)); brush1.setStyle(Qt::SolidPattern); palette.setBrush(QPalette::Active, QPalette::Base, brush1); palette.setBrush(QPalette::Inactive, QPalette::Text, brush); palette.setBrush(QPalette::Inactive, QPalette::Base, brush1); QBrush brush2(QColor(120, 120, 120, 255)); brush2.setStyle(Qt::SolidPattern); palette.setBrush(QPalette::Disabled, QPalette::Text, brush2); QBrush brush3(QColor(240, 240, 240, 255)); brush3.setStyle(Qt::SolidPattern); palette.setBrush(QPalette::Disabled, QPalette::Base, brush3); stdOutput->setPalette(palette); QFont font; font.setFamily(QString::fromUtf8("Source Code Pro")); font.setPointSize(10); stdOutput->setFont(font); stdOutput->setLineWrapMode(QPlainTextEdit::NoWrap); stdOutput->setReadOnly(true); return stdOutput; } BackupDialog::BackupDialog(QWidget *parent) : QDialog(parent) { btnStart = new QPushButton(this); btnStart->setObjectName(QString::fromUtf8("btnStart")); btnStart->setGeometry(QRect(270, 630, 75, 23)); tabWidget = new QTabWidget(this); tabWidget->setObjectName(QString::fromUtf8("tabWidget")); tabWidget->setGeometry(QRect(30, 90, 601, 501)); tab = new QWidget(); tab->setObjectName(QString::fromUtf8("tab")); verticalLayout = new QVBoxLayout(tab); verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); formLayout = new QFormLayout(); formLayout->setObjectName(QString::fromUtf8("formLayout")); label = new QLabel(tab); label->setObjectName(QString::fromUtf8("label")); formLayout->setWidget(0, QFormLayout::LabelRole, label); widget = new QWidget(tab); widget->setObjectName(QString::fromUtf8("widget")); horizontalLayout = new QHBoxLayout(widget); horizontalLayout->setSpacing(0); horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); horizontalLayout->setContentsMargins(0, 0, 0, 0); editFilename = new QLineEdit(widget); editFilename->setObjectName(QString::fromUtf8("editFilename")); horizontalLayout->addWidget(editFilename); selectDestination = new QPushButton(widget); selectDestination->setObjectName(QString::fromUtf8("selectDestination")); horizontalLayout->addWidget(selectDestination); formLayout->setWidget(0, QFormLayout::FieldRole, widget); label_2 = new QLabel(tab); label_2->setObjectName(QString::fromUtf8("label_2")); formLayout->setWidget(1, QFormLayout::LabelRole, label_2); backupFormat = new QComboBox(tab); backupFormat->setObjectName(QString::fromUtf8("backupFormat")); backupFormat->setModelColumn(0); formLayout->setWidget(1, QFormLayout::FieldRole, backupFormat); label_3 = new QLabel(tab); label_3->setObjectName(QString::fromUtf8("label_3")); formLayout->setWidget(2, QFormLayout::LabelRole, label_3); jobs = new QSpinBox(tab); jobs->setObjectName(QString::fromUtf8("jobs")); formLayout->setWidget(2, QFormLayout::FieldRole, jobs); chkbxVerbose = new QCheckBox(tab); chkbxVerbose->setObjectName(QString::fromUtf8("chkbxVerbose")); formLayout->setWidget(3, QFormLayout::FieldRole, chkbxVerbose); label_5 = new QLabel(tab); label_5->setObjectName(QString::fromUtf8("label_5")); formLayout->setWidget(4, QFormLayout::LabelRole, label_5); compression = new QSpinBox(tab); compression->setObjectName(QString::fromUtf8("compression")); compression->setMinimum(-1); compression->setMaximum(9); compression->setValue(-1); formLayout->setWidget(4, QFormLayout::FieldRole, compression); chkbxIncludeBlobs = new QCheckBox(tab); chkbxIncludeBlobs->setObjectName(QString::fromUtf8("chkbxIncludeBlobs")); formLayout->setWidget(6, QFormLayout::FieldRole, chkbxIncludeBlobs); chkbxClean = new QCheckBox(tab); chkbxClean->setObjectName(QString::fromUtf8("chkbxClean")); formLayout->setWidget(7, QFormLayout::FieldRole, chkbxClean); chkbxCreate = new QCheckBox(tab); chkbxCreate->setObjectName(QString::fromUtf8("chkbxCreate")); formLayout->setWidget(8, QFormLayout::FieldRole, chkbxCreate); noOwner = new QCheckBox(tab); noOwner->setObjectName(QString::fromUtf8("noOwner")); formLayout->setWidget(9, QFormLayout::FieldRole, noOwner); oids = new QCheckBox(tab); oids->setObjectName(QString::fromUtf8("oids")); formLayout->setWidget(10, QFormLayout::FieldRole, oids); what = new QComboBox(tab); what->addItem(QString()); what->addItem(QString()); what->addItem(QString()); what->setObjectName(QString::fromUtf8("what")); formLayout->setWidget(5, QFormLayout::FieldRole, what); label_4 = new QLabel(tab); label_4->setObjectName(QString::fromUtf8("label_4")); formLayout->setWidget(5, QFormLayout::LabelRole, label_4); noAcl = new QCheckBox(tab); noAcl->setObjectName(QString::fromUtf8("noAcl")); formLayout->setWidget(11, QFormLayout::FieldRole, noAcl); verticalLayout->addLayout(formLayout); tabWidget->addTab(tab, QString()); tab_2 = new QWidget(); tab_2->setObjectName(QString::fromUtf8("tab_2")); verticalLayout_2 = new QVBoxLayout(tab_2); verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2")); stdOutput = createStdOutput(this); verticalLayout_2->addWidget(stdOutput); tabWidget->addTab(tab_2, QString()); tabWidget->setCurrentIndex(0); QMetaObject::connectSlotsByName(this); auto format_model = new BackupFormatModel(this); backupFormat->setModel(format_model); retranslateUi(); } BackupDialog::~BackupDialog() { } void BackupDialog::retranslateUi() { setWindowTitle(QApplication::translate("BackupDialog", "Dialog", nullptr)); label->setText(QApplication::translate("BackupDialog", "Filename", nullptr)); selectDestination->setText(QApplication::translate("BackupDialog", "...", nullptr)); label_2->setText(QApplication::translate("BackupDialog", "Format", nullptr)); label_3->setText(QApplication::translate("BackupDialog", "Jobs:", nullptr)); chkbxVerbose->setText(QApplication::translate("BackupDialog", "Verbose (-v)", nullptr)); label_5->setText(QApplication::translate("BackupDialog", "Compression (-Z)", nullptr)); #ifndef QT_NO_TOOLTIP compression->setToolTip(QApplication::translate("BackupDialog", "-1 means default, 0-9 is no compression to max compression", nullptr)); #endif // QT_NO_TOOLTIP label_4->setText(QApplication::translate("BackupDialog", "What", nullptr)); what->setItemText(0, QApplication::translate("BackupDialog", "data + schema", nullptr)); what->setItemText(1, QApplication::translate("BackupDialog", "data only (-a)", nullptr)); what->setItemText(2, QApplication::translate("BackupDialog", "schema-only (-s)", nullptr)); chkbxIncludeBlobs->setText(QApplication::translate("BackupDialog", "Include blobs (-b)", nullptr)); chkbxClean->setText(QApplication::translate("BackupDialog", "Clean (-c)", nullptr)); chkbxCreate->setText(QApplication::translate("BackupDialog", "Create (-C)", nullptr)); noOwner->setText(QApplication::translate("BackupDialog", "No owner (-O)", nullptr)); oids->setText(QApplication::translate("BackupDialog", "Oids (-o)", nullptr)); noAcl->setText(QApplication::translate("BackupDialog", "No privileges/acl (-x)", nullptr)); btnStart->setText(QApplication::translate("BackupDialog", "START", nullptr)); tabWidget->setTabText(tabWidget->indexOf(tab), QApplication::translate("BackupDialog", "Tab 1", nullptr)); stdOutput->setPlainText(QApplication::translate("BackupDialog", "Test text.", nullptr)); tabWidget->setTabText(tabWidget->indexOf(tab_2), QApplication::translate("BackupDialog", "Tab 2", nullptr)); } // retranslateUi void BackupDialog::setConfig(const ConnectionConfig &cfg) { m_config = cfg; } void BackupDialog::ConnectTo(QProcess *process) { disconnectCurrentProcess(); m_process = process; if (process) { process->setProcessChannelMode(QProcess::MergedChannels); process->setReadChannel(QProcess::StandardOutput); connect(process, SIGNAL(readyRead()), this, SLOT(on_process_readyRead())); connect(process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(on_process_errorOccurred(QProcess::ProcessError))); connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(on_process_finished(int, QProcess::ExitStatus))); } } void BackupDialog::disconnectCurrentProcess() { if (m_process) { disconnect(m_process, SIGNAL(readyRead()), this, SLOT(on_process_readyRead())); disconnect(m_process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(on_process_errorOccurred(QProcess::ProcessError))); disconnect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(on_process_finished(int, QProcess::ExitStatus))); m_process = nullptr; } } void BackupDialog::writeOutput(const QString &s) { stdOutput->appendPlainText(s); QScrollBar *bar = stdOutput->verticalScrollBar(); bar->setValue(bar->maximum()); } void BackupDialog::on_process_readyRead() { QByteArray data = m_process->readAllStandardOutput(); writeOutput(QString::fromUtf8(data)); } void BackupDialog::on_process_errorOccurred(QProcess::ProcessError error) { QString msg; switch (error) { case 0: msg = tr("Failed to start"); break; case 1: msg = tr("Crashed"); break; case 2: msg = tr("Timedout"); break; case 3: msg = tr("Read error"); break; case 4: msg = tr("Write error"); break; case 5: msg = tr("Unknown error"); break; default: msg = tr("Unexpected error"); } auto res = QMessageBox::critical(this, "pglab", msg, QMessageBox::Close); if (res == QMessageBox::Yes) { QApplication::quit(); } } void BackupDialog::on_process_finished(int exitCode, QProcess::ExitStatus ) { writeOutput(tr("Completed, with exitcode %1\n").arg(exitCode)); } void BackupDialog::setParams(QStringList &args) { QString short_args("-"); if (chkbxVerbose->checkState() == Qt::Checked) short_args += "v"; if (chkbxClean->checkState() == Qt::Checked) short_args += "c"; if (chkbxCreate->checkState() == Qt::Checked) short_args += "C"; if (chkbxIncludeBlobs->checkState() == Qt::Checked) short_args += "b"; switch (what->currentIndex()) { case 1: short_args += "a"; break; case 2: short_args += "s"; break; } if (oids->checkState() == Qt::Checked) short_args += "o"; if (noAcl->checkState() == Qt::Checked) short_args += "x"; if (short_args.length() > 1) // larger then one because always includes '-' args << short_args; // Todo check path exists and name is valid? QFileInfo fi(QDir::fromNativeSeparators(editFilename->text())); QDir dir(fi.absolutePath()); if (!dir.exists()) dir.mkdir(fi.absolutePath()); args << "-f" << editFilename->text(); // R"-(c:\temp\backup.sql)-"; int format_index = backupFormat->currentIndex(); auto format_model_base = backupFormat->model(); auto *bfm = dynamic_cast(format_model_base); if (bfm) { QVariant v = bfm->data(bfm->index(format_index, 1)); QString format("-F"); format += v.toString(); args << format; } int j = jobs->value(); if (j > 0) args << "-j" << QString::number(j); int comp = compression->value(); if (comp >= 0) args << "-Z" << QString::number(comp); } void BackupDialog::on_btnStart_clicked() { stdOutput->clear(); //QString program = R"-(C:\Prog\bigsql\pg96\bin\pg_dump.exe)-"; QString program = "C:/Prog/bigsql/pg11/bin/pg_dump.exe"; QStringList arguments; setParams(arguments); // Database connection paramters are passed through the environment as this is far less visible to others. Commandline // parameters can often be viewed even if the user is not the owner of the process. // We use the systemEnvironment as a sane default. Then we let the connection overwrite all PG variables in it. QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); m_config.writeToEnvironment(env); //env.insert("SESSIONNAME", "Console"); auto p = new QProcess(this); ConnectTo(p); p->setProcessEnvironment(env); #ifdef WIN32 // p->setCreateProcessArgumentsModifier([] (QProcess::CreateProcessArguments *args) // { // args->flags |= CREATE_NEW_CONSOLE; // args->flags &= ~DETACHED_PROCESS; // args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES; // }); #endif p->start(program, arguments); } void BackupDialog::on_backupFormat_currentIndexChanged(int /*index*/) { int format_index = backupFormat->currentIndex(); auto format_model_base = backupFormat->model(); auto *bfm = dynamic_cast(format_model_base); if (bfm) { QVariant v = bfm->data(bfm->index(format_index, 1)); QString format = v.toString(); bool comp_enable = (format == "c" || format == "d"); compression->setEnabled(comp_enable); if (!comp_enable) compression->setValue(-1); bool jobs_enable = (format == "d"); jobs->setEnabled(jobs_enable); if (!jobs_enable) jobs->setValue(0); } } void BackupDialog::on_selectDestination_clicked() { QString home_dir = QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory); QString fn = QFileDialog::getSaveFileName(this, tr("Save backup"), home_dir, tr("Backup file (*.backup)")); if (!fn.isEmpty()) { editFilename->setText(QDir::toNativeSeparators(fn)); } }