diff --git a/restruct.pro b/restruct.pro --- a/restruct.pro +++ b/restruct.pro @@ -1,46 +1,53 @@ ###################################################################### # Project started 11.01.2008 at 13:10 ###################################################################### -QT += core gui -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets concurrent +QT += core concurrent TEMPLATE = app TARGET = restruct CONFIG += c++14 isEmpty(INCLUDEPATH): INCLUDEPATH = $$(HOME)/src/include isEmpty(LIBS): LIBS = -L$$(HOME)/src/lib INCLUDEPATH += src isEmpty(LIBPQ_INC) { unix: PREFIX = /usr win32:PREFIX = /build INCLUDEPATH += $${PREFIX}/include/postgresql $${PREFIX}/include/postgresql/internal } else { INCLUDEPATH += $${LIBPQ_INC} $${LIBPQ_INC}/internal win32: INCLUDEPATH += $${LIBPQ_INC}/server/port/win32 } LIBS += -lktools -lsqlproc -lpq +SOURCES += src/updater.cpp \ + src/mainconsole.cpp \ + src/exitcode.cpp + +HEADERS += \ + src/updater.h \ + src/psettings.h \ + src/mainconsole.h \ + src/exitcode.h + RESOURCES += resource/project.qrc -SOURCES += src/restruct.cpp \ - src/mainwindow.cpp \ - src/updater.cpp \ - src/sqlerrordlg.cpp - -HEADERS += src/mainwindow.h \ - src/updater.h \ - src/psettings.h \ - src/sqlerrordlg.h - win32 { + QT += gui widgets + SOURCES += src/main_win.cpp src/mainwindow.cpp + HEADERS += src/mainwindow.h RC_FILE = resource/project.rc LIBS += -luuid -loleaut32 -lgdi32 -luser32 } +unix { + CONFIG += console + SOURCES += src/main_lin.cpp + HEADERS += +} target.path = /bin # install location INSTALLS += target diff --git a/src/exitcode.cpp b/src/exitcode.cpp new file mode 100644 --- /dev/null +++ b/src/exitcode.cpp @@ -0,0 +1,12 @@ +#include "exitcode.h" + +ExitCode::ExitCode(int before, int after) +{ + if (before == after) + _message = QStringLiteral("База данных в актуальном состоянии."); + else if (before == 0) + _message = QStringLiteral("База данных создана и обновлена до версии %1.").arg(after); + else + _message = QStringLiteral("База данных версии %1 обновлена до версии %2.").arg(before).arg(after); + _exitCode = (before & 0xFFFF) | ((after & 0xFFFF) << 16); +} diff --git a/src/exitcode.h b/src/exitcode.h new file mode 100644 --- /dev/null +++ b/src/exitcode.h @@ -0,0 +1,18 @@ +#ifndef EXITCODE_H +#define EXITCODE_H + +#include + +class ExitCode +{ +public: + ExitCode(int before, int after); + + int exitCode() const { return _exitCode; } + QString message() const { return _message; } +private: + int _exitCode; + QString _message; +}; + +#endif // EXITCODE_H diff --git a/src/main_lin.cpp b/src/main_lin.cpp new file mode 100644 --- /dev/null +++ b/src/main_lin.cpp @@ -0,0 +1,16 @@ +#include "mainconsole.h" +#include +#include + +int main(int argc, char* argv[]) +{ + QCoreApplication app(argc, argv); + + MainConsole worker; + + QObject::connect(&worker, SIGNAL(finished()), &app, SLOT(quit())); + QTimer::singleShot(0, &worker, SLOT(run())); + + app.exec(); + return worker.exitCode(); +} diff --git a/src/restruct.cpp b/src/main_win.cpp rename from src/restruct.cpp rename to src/main_win.cpp --- a/src/restruct.cpp +++ b/src/main_win.cpp @@ -1,57 +1,52 @@ #include "mainwindow.h" #include #include #include - -#ifdef Q_OS_WIN32 #include -#endif int main(int argc, char* argv[]) { //int width = 504; //int height = 262; int width = 679; int height = 420; QApplication app(argc, argv); //загрузка русской локализации библиотеки Qt QTranslator translator; translator.load(QStringLiteral("qt_ru")); app.installTranslator(&translator); //создание главного окна MainWindow window; -#ifdef Q_OS_WIN32 //масштабирование для случая увеличенного шрифта HWND hwnd = (HWND)app.desktop()->winId(); int dpi = GetDeviceCaps(GetDC(hwnd), LOGPIXELSY); if (dpi != 96) { width = (width * dpi) / 96; height = (height * dpi) / 96; } //шрифт окна такой же, как в системе подписи к иконкам LOGFONTW lf; SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); int fh = qAbs((lf.lfHeight * 72) / dpi); QString fn((const QChar*)lf.lfFaceName, wcslen(lf.lfFaceName)); window.setStyleSheet( QString("*{ font-family: %1; font-size: %2pt; }").arg(fn).arg(fh)); -#endif //перемещение главного окна в центр экрана window.setMinimumSize(width, height); QRect wg = window.geometry(); wg.setSize(window.minimumSize()); wg.moveCenter(qApp->desktop()->screenGeometry().center()); window.setGeometry(wg); int exitCode = window.exec(); return exitCode; } //!приложение restruct diff --git a/src/mainconsole.cpp b/src/mainconsole.cpp new file mode 100644 --- /dev/null +++ b/src/mainconsole.cpp @@ -0,0 +1,191 @@ +#include "exitcode.h" +#include "mainconsole.h" +#include "psettings.h" +#include "updater.h" +#include +#include +#include +#include + +MainConsole::MainConsole(QObject* a_parent) + : QObject(a_parent) + , _exitCode(0) + , _errorCount(0) + , _os(stdout) + , _updater(new DatabaseUpdater) +{ +} + +MainConsole::~MainConsole() +{ + delete _updater; +} + +void MainConsole::run() +{ + ProgramSettings pset = processArguments(); + if (!pset.helpText.isEmpty()) + { + _os << pset.helpText; + QTimer::singleShot(0, this, &MainConsole::quit); + return; + } + +// connect(_updater, SIGNAL(progress(int)), _progress, SLOT(setValue(int))); + connect(_updater, SIGNAL(error(const QString&)), SLOT(error(const QString&))); + connect(_updater, SIGNAL(message(const QString&)), SLOT(message(const QString&))); + connect(_updater, SIGNAL(sqlError(const QString&, const QString&, const QString&)), + SLOT(sqlError(const QString&, const QString&, const QString&))); + connect(_updater, SIGNAL(logConnectionParameters(const QString&, const QString&, const QString&)), + SLOT(logConnectionParameters(const QString&, const QString&, const QString&))); + connect(&_futureWatcher, SIGNAL(finished()), SLOT(finishExecution())); + + QFuture rc = QtConcurrent::run(_updater, &DatabaseUpdater::run, pset); + _futureWatcher.setFuture(rc); +} + +void MainConsole::quit() +{ + emit finished(); +} + +void MainConsole::finishExecution() +{ + //проверяем число ошибок, т.к. при выполнении без транзакции run() всегда возвращает 0 + if (_errorCount == 0) + { + ExitCode rc(_updater->revisionBefore(), _updater->revisionAfter()); + message(rc.message()); + _exitCode = rc.exitCode(); + } + else + { + message(QStringLiteral("Выполнение прервано в результате ошибки.\nБаза данных не изменилась.")); + _exitCode = -1; + } + emit finished(); +} + +ProgramSettings MainConsole::processArguments() +{ + ProgramSettings result; + + QString USERNAME_VALUE = QStringLiteral("пользователь"); + QString PASSWORD_VALUE = QStringLiteral("пароль"); + QString DATABASE_VALUE = QStringLiteral("база_данных"); + QString HOST_VALUE = QStringLiteral("адрес_сервера"); + QString PORT_VALUE = QStringLiteral("номер_порта"); + QString FILE_VALUE = QStringLiteral("file.dmv"); + QString USERNAME_OPTION = QStringLiteral("U"); + QString PASSWORD_OPTION = QStringLiteral("W"); + QString DATABASE_OPTION = QStringLiteral("d"); + QString DROPDB_OPTION = QStringLiteral("0"); + QString HOST_OPTION = QStringLiteral("h"); + QString PORT_OPTION = QStringLiteral("p"); + QString FILE_OPTION = QStringLiteral("f"); + QString HELP_OPTION = QStringLiteral("help"); + + //обработать аргументы командной строки + QCommandLineParser parser; + QCommandLineOption helpOption(HELP_OPTION, QStringLiteral("Показать справку") ); + parser.addOption(helpOption); + QCommandLineOption usernameOption(USERNAME_OPTION, QStringLiteral("Имя пользователя"), USERNAME_VALUE); + parser.addOption(usernameOption); + QCommandLineOption databaseOption(DATABASE_OPTION, QStringLiteral("Имя базы данных"), DATABASE_VALUE); + parser.addOption(databaseOption); + QCommandLineOption filenameOption(FILE_OPTION, QStringLiteral("Управляющий файл"), FILE_VALUE); + parser.addOption(filenameOption); + QCommandLineOption hostOption(HOST_OPTION, QStringLiteral("Адрес сервера"), HOST_VALUE); + parser.addOption(hostOption); + QCommandLineOption portOption(PORT_OPTION, QStringLiteral("Порт сервера"), PORT_VALUE); + parser.addOption(portOption); + QCommandLineOption passwordOption(PASSWORD_OPTION, QStringLiteral("Пароль"), PASSWORD_VALUE); + parser.addOption(passwordOption); + QCommandLineOption dropdbOption(DROPDB_OPTION, QStringLiteral("Сначала удалить базу данных") ); + parser.addOption(dropdbOption); + parser.addPositionalArgument(FILE_VALUE, QStringLiteral("Управляющий файл"), FILE_VALUE); + + parser.process(*qApp); + + //записать прочитанные значения в структуру ProgramSettings + result.username = parser.value(usernameOption); + result.password = parser.value(passwordOption); + result.database = parser.value(databaseOption); + result.host = parser.value(hostOption); + result.port = parser.value(portOption); + result.dropdb = parser.isSet(dropdbOption); + + if (parser.isSet(filenameOption)) + result.controlFile = parser.value(filenameOption); + else if (parser.positionalArguments().size() > 0) + result.controlFile = parser.positionalArguments().at(0); + + if (parser.isSet(helpOption)) + result.helpText = parser.helpText(); + + return result; +} + +void MainConsole::error(const QString& a_error) +{ + static const QString CONSOLE_RED_BEGIN = QStringLiteral("\x1B[1m\x1B[31m"); + static const QString CONSOLE_RESET = QStringLiteral("\x1B(B\x1B[m"); + _os << CONSOLE_RED_BEGIN << QStringLiteral("ОШИБКА") << CONSOLE_RESET << endl; + message(a_error); + _os << CONSOLE_RESET << endl; + ++_errorCount; +} + +void MainConsole::message(const QString& a_message) +{ + _os << toConsoleText(a_message) << endl; +} + +QString MainConsole::toConsoleText(const QString& a_text) +{ + QString result = a_text; + + static const QString BOLD = QStringLiteral("**"); + static const QString CONSOLE_BOLD_BEGIN = QStringLiteral("\x1B[1m"); + static const QString CONSOLE_RESET = QStringLiteral("\x1B(B\x1B[m"); + static const QString CONSOLE_TAB = QStringLiteral(" "); + static const QChar TAB('\t'); + + bool begin = true; + int pos = result.indexOf(BOLD); + while (pos >= 0) + { + result.replace(pos, BOLD.size(), begin ? CONSOLE_BOLD_BEGIN : CONSOLE_RESET); + begin = !begin; + pos = result.indexOf(BOLD, pos + 1); + } + + if (result.contains(TAB)) + result.replace(TAB, CONSOLE_TAB); + + return result; +} + +void MainConsole::logConnectionParameters(const QString& a_host, const QString& a_database, const QString& a_username) +{ + message(QStringLiteral("Подключение к базе данных\n" + "\tСервер: **%1**\n\tБаза данных: **%2**\n" + "\tПользователь: **%3**") + .arg(a_host, a_database, a_username)); +} + +void MainConsole::sqlError(const QString& a_dbError, const QString& a_commandDescription, const QString& a_command) +{ + QString errorText; + + if (!a_commandDescription.isEmpty()) + errorText.append(QStringLiteral("**Операция:**\n")).append(a_commandDescription).append("\n\n"); + + QString dbError = a_dbError; + errorText.append(QStringLiteral("**Сообщение об ошибке:**\n")).append(dbError.trimmed()).append("\n\n"); + + if (!a_command.isEmpty()) + errorText.append(QStringLiteral("**Текст команды:**\n")).append(a_command); + + error(errorText); +} diff --git a/src/mainconsole.h b/src/mainconsole.h new file mode 100644 --- /dev/null +++ b/src/mainconsole.h @@ -0,0 +1,43 @@ +#ifndef MAINCLASS_H +#define MAINCLASS_H + +#include +#include +#include + +class ProgramSettings; +class DatabaseUpdater; +class QStringList; +class MainConsole : public QObject +{ + Q_OBJECT +public: + MainConsole(QObject* a_parent = 0); + ~MainConsole() override; + int exitCode() const { return _exitCode; } + +signals: + void finished(); + +public slots: + void run(); + void quit(); + void finishExecution(); + void error(const QString& a_error); + void message(const QString& a_message); + void logConnectionParameters(const QString& a_host, const QString& a_database, + const QString& a_username); + void sqlError(const QString& a_dbError, const QString& a_commandDescription, + const QString& a_command); + +private: + int _exitCode; + int _errorCount; + QTextStream _os; + DatabaseUpdater* _updater; + QFutureWatcher _futureWatcher; + ProgramSettings processArguments(); + QString toConsoleText(const QString& a_text); +}; + +#endif // MAINCLASS_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,474 +1,460 @@ +#include "exitcode.h" #include "mainwindow.h" #include "psettings.h" -#include "sqlerrordlg.h" #include "updater.h" #include #include #include -#ifdef Q_OS_WIN32 #include -#endif #include #include #include #include #include #include #include #include #include #include #include #include #include //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) : QDialog(parent, flags) , _exitCode(0) , _actionEventType(QEvent::User) , _errorCount(0) , _updater(new DatabaseUpdater) { setWindowTitle(QStringLiteral("Создание/обновление базы данных")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setSizeGripEnabled(true); QHBoxLayout* mainLayout = new QHBoxLayout; QVBoxLayout* leftLayout = new QVBoxLayout; QVBoxLayout* rightLayout = new QVBoxLayout; QHBoxLayout* bottomRightLayout = new QHBoxLayout; leftLayout->setContentsMargins(0, 2 * style()->pixelMetric(QStyle::PM_LayoutTopMargin), style()->pixelMetric(QStyle::PM_LayoutRightMargin), 0); QLabel* picture = new QLabel; picture->setPixmap(QPixmap(":/picture.png")); //кнопки, скрытые до завершения процесса _btnSave = new QPushButton(QStringLiteral("Сохранить")); _btnClose = new QPushButton(QStringLiteral("Закрыть")); _btnSave->setVisible(false); _btnClose->setVisible(false); _btnClose->setDefault(true); leftLayout->addWidget(picture); leftLayout->addStretch(); leftLayout->addWidget(_btnSave); leftLayout->addWidget(_btnClose); QLabel* label = new QLabel(QStringLiteral("Протокол работы")); rightLayout->addWidget(label); _protocol = new QTextEdit(); _protocol->setReadOnly(true); label->setBuddy(_protocol); rightLayout->addWidget(_protocol); //индикаторы выполнения _progress = new QProgressBar; _progress->setTextVisible(false); _ai = new KActivityIndicator(KActivityIndicator::Gray); _ai->setVisible(false); bottomRightLayout->addWidget(_progress); bottomRightLayout->addWidget(_ai); rightLayout->addLayout(bottomRightLayout); mainLayout->addLayout(leftLayout); mainLayout->addLayout(rightLayout); setLayout(mainLayout); //нажатие Esc не соединяется со слотом, чтобы окно не закрывалось new QShortcut(QKeySequence(Qt::Key_Escape), this); //соединить сигналы со слотами connect(_btnSave, SIGNAL(clicked()), this, SLOT(saveProtocol())); connect(_btnClose, SIGNAL(clicked()), this, SLOT(closeDialog())); //получить незадействованный тип события _actionEventType = QEvent::registerEventType(); } MainWindow::~MainWindow() { delete _updater; } //--------------------------------------------------------------------------- void MainWindow::showEvent(QShowEvent* a_event) { QDialog::showEvent(a_event); qApp->postEvent(this, new QEvent(QEvent::Type(_actionEventType))); } //--------------------------------------------------------------------------- bool MainWindow::event(QEvent* a_event) { if (a_event->type() == _actionEventType) { startExecution(); a_event->accept(); return true; } return QWidget::event(a_event); } //--------------------------------------------------------------------------- void MainWindow::closeEvent(QCloseEvent* a_event) { if (_futureWatcher.isRunning()) a_event->ignore(); else a_event->accept(); } //--------------------------------------------------------------------------- void MainWindow::startExecution() { if (_futureWatcher.isRunning()) return; ProgramSettings pset; processArguments(pset); logon(pset); connect(_updater, SIGNAL(progress(int)), _progress, SLOT(setValue(int))); connect(_updater, SIGNAL(error(const QString&)), this, SLOT(error(const QString&))); connect(_updater, SIGNAL(message(const QString&)), this, SLOT(message(const QString&))); connect(_updater, SIGNAL(sqlError(const QString&, const QString&, const QString&)), this, SLOT(sqlError(const QString&, const QString&, const QString&))); connect(_updater, SIGNAL(logConnectionParameters(const QString&, const QString&, const QString&)), this, SLOT(logConnectionParameters(const QString&, const QString&, const QString&))); connect(&_futureWatcher, SIGNAL(finished()), this, SLOT(finishExecution())); _ai->setVisible(true); _ai->start(); //int rc = _updater.run( pset ); QFuture rc = QtConcurrent::run(_updater, &DatabaseUpdater::run, pset); _futureWatcher.setFuture(rc); } //--------------------------------------------------------------------------- void MainWindow::finishExecution() { _ai->stop(); _ai->setVisible(false); //проверяем число ошибок, т.к. при выполнении без транзакции run() всегда возвращает 0 if (_errorCount == 0) { - int before = _updater->revisionBefore(); - int after = _updater->revisionAfter(); - - if (before == after) - message(QStringLiteral("База данных в актуальном состоянии.")); - else if (before == 0) - message(QStringLiteral("База данных создана и обновлена до версии %1.").arg(after)); - else - message(QStringLiteral("База данных версии %1 обновлена до версии %2.").arg(before).arg(after)); - _exitCode = (before & 0xFFFF) | ((after & 0xFFFF) << 16); + ExitCode rc(_updater->revisionBefore(), _updater->revisionAfter()); + message(rc.message()); + _exitCode = rc.exitCode(); closeDialog(); //при успешном завершении, то окно закрывается автоматически } else { _btnClose->show(); _btnSave->show(); _btnClose->setFocus(); - message(QStringLiteral("Выполнение прервано в результате ошибки." - "
База данных не изменилась.")); + message(QStringLiteral("Выполнение прервано в результате ошибки.\nБаза данных не изменилась.")); _exitCode = -1; } } //--------------------------------------------------------------------------- int MainWindow::executeAction() { ProgramSettings pset; processArguments(pset); logon(pset); _ai->start(); DatabaseUpdater updater; connect(&updater, SIGNAL(progress(int)), _progress, SLOT(setValue(int))); connect(&updater, SIGNAL(error(const QString&)), this, SLOT(error(const QString&))); connect(&updater, SIGNAL(message(const QString&)), this, SLOT(message(const QString&))); connect(&updater, SIGNAL(sqlError(const QString&, const QString&, const QString&)), this, SLOT(sqlError(const QString&, const QString&, const QString&))); connect(&updater, SIGNAL(logConnectionParameters(const QString&, const QString&, const QString&)), this, SLOT(logConnectionParameters(const QString&, const QString&, const QString&))); int rc = updater.run(pset); //проверяем число ошибок, т.к. при выполнении без транзакции run() всегда возвращает 0 if (_errorCount == 0) { int before = updater.revisionBefore(); int after = updater.revisionAfter(); if (before == after) message(QStringLiteral("База данных в актуальном состоянии.")); else if (before == 0) message(QStringLiteral("База данных создана и обновлена до версии %1.").arg(after)); else message(QStringLiteral("База данных версии %1 обновлена до версии %2.").arg(before).arg(after)); rc = (before & 0xFFFF) | ((after & 0xFFFF) << 16); } else { _btnClose->show(); _btnSave->show(); _btnClose->setFocus(); message(QStringLiteral("Выполнение прервано в результате ошибки." "
База данных не изменилась.")); rc = -1; } return rc; } void MainWindow::processArguments(ProgramSettings& a_pset) { QString USERNAME_PARAM("username"); QString PASSWORD_PARAM("password"); QString DATABASE_PARAM("database"); QString DROPDB_PARAM("dropdb"); QString HOST_PARAM("host"); QString PORT_PARAM("port"); QString FILE_PARAM("file"); //заполнить параметры default значениями QHash params; params.insert(USERNAME_PARAM, QString()); params.insert(PASSWORD_PARAM, QString()); params.insert(DATABASE_PARAM, QString()); params.insert(DROPDB_PARAM, QString()); params.insert(HOST_PARAM, QString()); params.insert(PORT_PARAM, QString()); params.insert(FILE_PARAM, QString()); //чтение аргументов QString key; QStringList arguments = QApplication::arguments(); auto end = arguments.cend(); auto begin = arguments.cbegin(); for (auto it = begin + 1; it != end; ++it) //пропускаем первый параметр - имя программы { QString curArg = *it; if (curArg.at(0) == QChar('-')) { //обработка короткого параметра key.clear(); switch (curArg.at(1).toLatin1()) { case 'U': key = USERNAME_PARAM; break; case 'd': key = DATABASE_PARAM; break; case 'f': key = FILE_PARAM; break; case 'h': key = HOST_PARAM; break; case 'p': key = PORT_PARAM; break; case 'W': key = PASSWORD_PARAM; break; case '0': params[ DROPDB_PARAM ] = '1'; break; } } else { //обработка одиночного параметра if (key.isEmpty()) key = FILE_PARAM; params[ key ] = curArg; key.clear(); } } //записать прочитанные значения в структуру ProgramSettings a_pset.username = params.value(USERNAME_PARAM); a_pset.password = params.value(PASSWORD_PARAM); a_pset.database = params.value(DATABASE_PARAM); a_pset.host = params.value(HOST_PARAM); a_pset.port = params.value(PORT_PARAM); a_pset.controlFile = params.value(FILE_PARAM); a_pset.dropdb = !params.value(DROPDB_PARAM).isEmpty(); } //--------------------------------------------------------------------------- void MainWindow::logon(ProgramSettings& a_pset) { if (!a_pset.host.isEmpty() || !a_pset.username.isEmpty()) return; -#if defined(Q_OS_WIN) KLogon* logon = KLogon::create(); if (!logon) return; QString defaultDSN; HKEY k; DWORD cb = 0; QString valuename("System Directory"); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\irs\\b03"), 0, KEY_QUERY_VALUE, &k) == ERROR_SUCCESS && RegQueryValueEx(k, LPCTSTR(valuename.constData()), 0, 0, 0, &cb) == ERROR_SUCCESS && cb > 0) { QString systemdir; systemdir.resize((cb / sizeof(QChar)) - 1); RegQueryValueEx(k, LPCTSTR(valuename.constData()), 0, 0, LPBYTE(systemdir.data()), &cb); RegCloseKey(k); KSettings systemini(systemdir + "/system.ini"); systemini.beginGroup("Database"); defaultDSN = systemini.value("DefaultDSN").toString(); } QString username = QString::fromLocal8Bit(qgetenv("USERNAME")); logon->setParent(winId()); logon->setUsername(username); if (!defaultDSN.isNull()) logon->setDSN(defaultDSN); if (!logon->execute()) emit message(QStringLiteral("Отказ от ввода имени и пароля пользователя")); else { a_pset.host = logon->host(); a_pset.username = logon->username(); a_pset.password = logon->password(); } delete logon; -#else - QString username = QString::fromLocal8Bit(getenv("USER")); -#endif } //--------------------------------------------------------------------------- void MainWindow::logConnectionParameters(const QString& a_host, const QString& a_database, const QString& a_username) { message(QStringLiteral("Подключение к базе данных\n" "\tСервер: **%1**\n\tБаза данных: **%2**\n" "\tПользователь: **%3**") .arg(a_host, a_database, a_username)); } //--------------------------------------------------------------------------- void MainWindow::sqlError(const QString& a_dbError, const QString& a_commandDescription, const QString& a_command) { QString errorHtml; if (!a_commandDescription.isEmpty()) errorHtml.append(QStringLiteral("Операция:
")).append(a_commandDescription).append("
"); QString dbError = a_dbError; errorHtml.append(QStringLiteral("Сообщение об ошибке:
")).append(dbError.trimmed().replace('\n', "
")).append("
"); if (!a_command.isEmpty()) errorHtml.append(QStringLiteral("Текст команды:
")).append(a_command).append("
"); errorHtmlToLog(errorHtml); } //--------------------------------------------------------------------------- void MainWindow::error(const QString& a_error) { QString errorHtml = a_error; errorHtmlToLog(errorHtml.replace('<', "<").replace('>', ">").replace('\n', "
")); } //--------------------------------------------------------------------------- void MainWindow::errorHtmlToLog(const QString& a_errorHtml) { QString errorHtml = a_errorHtml; QTextCursor cursor = _protocol->textCursor(); cursor.insertHtml(QStringLiteral("Ошибка
")); cursor.insertHtml(errorHtml); cursor.insertHtml(QStringLiteral("
")); _protocol->moveCursor(QTextCursor::End); ++_errorCount; } QString MainWindow::toHtml(const QString& a_text) { QString result = a_text; static const QString BOLD = QStringLiteral("**"); static const QString HTML_BOLD_BEGIN = QStringLiteral(""); static const QString HTML_BOLD_END = QStringLiteral(""); static const QString HTML_BR = QStringLiteral("
"); static const QString HTML_NBSP = QStringLiteral("  "); static const QChar NL('\n'); static const QChar TAB('\t'); bool begin = true; int pos = result.indexOf(BOLD); while (pos >= 0) { result.replace(pos, BOLD.size(), begin ? HTML_BOLD_BEGIN : HTML_BOLD_END); begin = !begin; pos = result.indexOf(BOLD, pos + 1); } if (result.contains(NL)) result.replace(NL, HTML_BR); if (result.contains(TAB)) result.replace(TAB, HTML_NBSP); return result; } //--------------------------------------------------------------------------- void MainWindow::message(const QString& a_message) { QString message = a_message; _protocol->textCursor().insertHtml(toHtml(message).append(QStringLiteral("
"))); _protocol->moveCursor(QTextCursor::End); } //--------------------------------------------------------------------------- void MainWindow::closeDialog() { QDialog::done(_exitCode); } //--------------------------------------------------------------------------- void MainWindow::saveProtocol() { QString filename = QFileDialog::getSaveFileName(this, QStringLiteral("Сохранить протокол в файл…"), QString(), QStringLiteral("Текстовые файлы (*.txt);;Все файлы (*.*)")); if (!filename.isEmpty()) { QFile outf(filename); if (outf.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QTextStream os(&outf); os.setGenerateByteOrderMark(true); os.setCodec("UTF-8"); os << _protocol->toPlainText(); } } } //!главное окно приложения diff --git a/src/psettings.h b/src/psettings.h --- a/src/psettings.h +++ b/src/psettings.h @@ -1,19 +1,20 @@ #if !defined PSETTINGS_H #define PSETTINGS_H class ProgramSettings { public: ProgramSettings() : dbVersion(0), dropdb(false) {} QString username; QString password; QString database; QString host; QString port; QString controlFile; QString packageId; + QString helpText; int dbVersion; bool dropdb; }; #endif diff --git a/src/sqlerrordlg.cpp b/src/sqlerrordlg.cpp deleted file mode 100644 --- a/src/sqlerrordlg.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "sqlerrordlg.h" -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -SqlErrorDialog::SqlErrorDialog(QWidget* parent, Qt::WindowFlags flags) - : QDialog(parent, flags) -{ - setWindowTitle(QStringLiteral("Список ошибок")); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - setSizeGripEnabled(true); - setMinimumSize(QSize(512, 428)); - - QVBoxLayout* mainLayout = new QVBoxLayout(this); - QHBoxLayout* layout = new QHBoxLayout; - mainLayout->addLayout(layout); - - QLabel* label = new QLabel( - QStringLiteral("Во время выполнения команд произошли\nследующие ошибки:")); - layout->addWidget(label); - layout->addStretch(); - - _btnClose = new QPushButton(QStringLiteral("Закрыть")); - _btnClose->setDefault(true); - layout->addWidget(_btnClose); - - _errorLog = new QTextEdit; - _errorLog->setReadOnly(true); - mainLayout->addWidget(_errorLog); - - connect(_btnClose, SIGNAL(clicked()), this, SLOT(close())); -} - -SqlErrorDialog::~SqlErrorDialog() -{ -} - -void SqlErrorDialog::setLogText(const QString& a_text) -{ - _errorLog->clear(); - _errorLog->setHtml(a_text); -} - -//!главное окно приложения diff --git a/src/sqlerrordlg.h b/src/sqlerrordlg.h deleted file mode 100644 --- a/src/sqlerrordlg.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SQLERRORDLG_H -#define SQLERRORDLG_H - -#include - -class QPushButton; -class QString; -class QTextEdit; - -class SqlErrorDialog : public QDialog -{ -public: - SqlErrorDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0); - ~SqlErrorDialog() override; - - void setLogText(const QString& a_text); - -private: - QPushButton* _btnClose; - QTextEdit* _errorLog; -}; - -//!главное окно приложения -#endif //SQLERRORDLG_H