Page MenuHomePhabricator

No OneTemporary

diff --git a/restruct.pro b/restruct.pro
--- a/restruct.pro
+++ b/restruct.pro
@@ -1,48 +1,49 @@
######################################################################
# Project started 11.01.2008 at 13:10
######################################################################
QT += core concurrent
TEMPLATE = app
TARGET = restruct
CONFIG += c++14
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
isEmpty(INCLUDEPATH): INCLUDEPATH = $$(HOME)/src/include
isEmpty(LIBS): LIBS = -L$$(HOME)/src/lib
INCLUDEPATH += src
unix:INCLUDEPATH += /usr/include/postgresql
LIBS += -lktools -lsqlproc -lpq
SOURCES += src/updater.cpp \
- src/exitcode.cpp
+ src/exitcode.cpp \
+ src/psettings.cpp
HEADERS += \
src/updater.h \
src/psettings.h \
src/exitcode.h
RESOURCES += resource/project.qrc
win32 {
QT += gui widgets
SOURCES += src/main_win.cpp src/mainwindow.cpp
HEADERS += src/mainwindow.h
RC_FILE = resource/project.rc
contains(DEFINES,SQLPROC_STATIC):LIBS += -luuid -loleaut32
}
unix {
CONFIG += console
SOURCES += src/main_lin.cpp src/mainconsole.cpp
HEADERS += src/mainconsole.h
}
target.path = /bin # install location
INSTALLS += target
diff --git a/src/mainconsole.cpp b/src/mainconsole.cpp
--- a/src/mainconsole.cpp
+++ b/src/mainconsole.cpp
@@ -1,229 +1,159 @@
#include "exitcode.h"
#include "mainconsole.h"
#include "psettings.h"
#include "updater.h"
-#include <QCommandLineParser>
#include <QTimer>
#include <QtConcurrentRun>
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)), this, SLOT(progress(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<int> 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 = 0;
}
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 LOGFILE_VALUE = QStringLiteral("файл_журнала");
- 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 LOGFILE_OPTION = QStringLiteral("L");
- QString URIDB_OPTION = QStringLiteral("u");
- 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 logfileOption(LOGFILE_OPTION, QStringLiteral("Сохранить протокол работы в файл"), LOGFILE_VALUE);
- parser.addOption(logfileOption);
- QCommandLineOption dropdbOption(DROPDB_OPTION, QStringLiteral("Сначала удалить базу данных"));
- parser.addOption(dropdbOption);
- QCommandLineOption uridbOption(URIDB_OPTION, QStringLiteral("Не создавать учебную базу данных"));
- parser.addOption(uridbOption);
- 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.logfile = parser.value(logfileOption);
- result.dropdb = parser.isSet(dropdbOption);
- result.uridb = !parser.isSet(uridbOption);
-
- 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 char* CONSOLE_BRIGHT_RED_BEGIN = "\x1B[1m\x1B[31m";
static const char* CONSOLE_RESET = "\x1B(B\x1B[m";
hideProgress();
_os << CONSOLE_BRIGHT_RED_BEGIN << QStringLiteral("ОШИБКА") << CONSOLE_RESET << endl;
message(a_error);
_os << CONSOLE_RESET << endl;
++_errorCount;
}
void MainConsole::message(const QString& a_message)
{
hideProgress();
_os << toConsoleText(a_message) << endl;
}
void MainConsole::progress(int a_value)
{
static const char* CONSOLE_GREEN_BEGIN = "\x1B[0m\x1B[32m";
static const char* CONSOLE_RESET = "\x1B(B\x1B[m";
char bytes[50 + 2 + 1];
auto begin = std::begin(bytes);
auto end = std::end(bytes) - 1;
*begin++ = '[';
*end-- = '\0';
*end = ']';
std::fill(begin, end, '.');
int done = a_value / 2;
std::fill(begin, begin + done, 'O');
if (a_value & 1)
bytes[done + 1] = 'o';
_os << '\r' << CONSOLE_GREEN_BEGIN << bytes << CONSOLE_RESET << flush;
}
void MainConsole::hideProgress()
{
static const char* CONSOLE_ERASE_LINE = "\r\x1B[K";
_os << CONSOLE_ERASE_LINE << flush;
}
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);
if (result.endsWith(QChar('\n')))
result.chop(1);
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
--- a/src/mainconsole.h
+++ b/src/mainconsole.h
@@ -1,45 +1,44 @@
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <QFutureWatcher>
#include <QObject>
#include <QTextStream>
class ProgramSettings;
class DatabaseUpdater;
class QStringList;
class MainConsole : public QObject
{
Q_OBJECT
public:
MainConsole(QObject* a_parent = nullptr);
~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 progress(int a_value);
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<int> _futureWatcher;
- ProgramSettings processArguments();
QString toConsoleText(const QString& a_text);
void hideProgress();
};
#endif // MAINCLASS_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,473 +1,393 @@
#include "exitcode.h"
#include "mainwindow.h"
#include "psettings.h"
#include "updater.h"
#include <kactivityindicator.h>
#include <ksettings.h>
#include <sqlproc.h>
#include <klogon_win.h>
#include <QApplication>
#include <QCloseEvent>
#include <QEvent>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressBar>
#include <QPushButton>
#include <QShortcut>
#include <QStandardPaths>
#include <QStyle>
#include <QTextCodec>
#include <QTextEdit>
#include <QTimer>
#include <QVBoxLayout>
#include <QtConcurrentRun>
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
: QDialog(parent, flags)
, _exitCode(0)
, _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;
_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()));
QTimer::singleShot(0, this, SLOT(startExecution()));
}
MainWindow::~MainWindow()
{
delete _updater;
}
//---------------------------------------------------------------------------
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);
+ ProgramSettings pset = processArguments();
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<int> rc = QtConcurrent::run(_updater, &DatabaseUpdater::run, pset);
_futureWatcher.setFuture(rc);
}
//---------------------------------------------------------------------------
void MainWindow::finishExecution()
{
_ai->stop();
_ai->setVisible(false);
//проверяем число ошибок, т.к. при выполнении без транзакции run() всегда возвращает 0
if (_errorCount == 0)
{
ExitCode rc(_updater->revisionBefore(), _updater->revisionAfter());
message(rc.message());
_exitCode = rc.exitCode();
closeDialog(); //при успешном завершении, то окно закрывается автоматически
}
else
{
_btnClose->show();
_btnSave->show();
_btnClose->setFocus();
message(QStringLiteral("Выполнение прервано в результате ошибки.\nБаза данных не изменилась."));
_exitCode = -1;
}
}
//---------------------------------------------------------------------------
int MainWindow::executeAction()
{
- ProgramSettings pset;
-
- processArguments(pset);
+ ProgramSettings pset = processArguments();
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("Выполнение прервано в результате ошибки."
"<br>База данных не изменилась."));
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<QString, QString> 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;
KLogon* logon = KLogon::create();
if (!logon)
return;
QString defaultDSN;
QString ospoName;
HKEY k;
DWORD cb = 0;
QString valuename("System Directory");
if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\irs\\b04"), 0, KEY_QUERY_VALUE, &k) == ERROR_SUCCESS
|| 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();
systemini.endGroup();
systemini.beginGroup("Common");
ospoName = systemini.value("SystemName").toString().replace(QLatin1Char('B'),QStringLiteral("ОСПО Б-"));
}
QString username = QString::fromLocal8Bit(qgetenv("USERNAME"));
QHash<QString, QString> aliases = loadAliases(ospoName);
if (aliases.contains(username))
username = aliases[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;
}
//---------------------------------------------------------------------------
QHash<QString, QString> MainWindow::loadAliases(const QString& a_ospoName)
{
QHash<QString, QString> result;
QApplication::setOrganizationName(a_ospoName);
QString filename = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(1);
filename.replace(QApplication::applicationName(), QStringLiteral("aliases.conf"));
QFile inf(filename);
if (inf.open(QIODevice::ReadOnly))
{
QTextStream is(&inf);
is.setCodec(QTextCodec::codecForName("UTF-8"));
while ( !is.atEnd() )
{
QStringList chunks = is.readLine().split(QLatin1Char(':'));
if (chunks.size() == 2)
result[chunks.at(0).trimmed()] = chunks.at(1).trimmed();
}
}
return result;
}
//---------------------------------------------------------------------------
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("<font color=\"#0000FF\">Операция:</font><br>")).append(a_commandDescription).append("<br>");
QString dbError = a_dbError;
errorHtml.append(QStringLiteral("<font color=\"#0000FF\">Сообщение об ошибке:</font><pre>")).append(dbError.trimmed().replace('\n', "<br>")).append("</pre>");
if (!a_command.isEmpty())
errorHtml.append(QStringLiteral("<font color=\"#0000FF\">Текст команды:</font><pre>")).append(a_command).append("</pre>");
errorHtmlToLog(errorHtml);
}
//---------------------------------------------------------------------------
void MainWindow::error(const QString& a_error)
{
QString errorHtml = a_error;
errorHtmlToLog(errorHtml.replace('<', "&lt;").replace('>', "&gt;").replace('\n', "<br>"));
}
//---------------------------------------------------------------------------
void MainWindow::errorHtmlToLog(const QString& a_errorHtml)
{
QString errorHtml = a_errorHtml;
QTextCursor cursor = _protocol->textCursor();
cursor.insertHtml(QStringLiteral("<font color=\"#0000FF\">Ошибка</font><br>"));
cursor.insertHtml(errorHtml);
cursor.insertHtml(QStringLiteral("<hr>"));
_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("<b>");
static const QString HTML_BOLD_END = QStringLiteral("</b>");
static const QString HTML_BR = QStringLiteral("<br>");
static const QString HTML_NBSP = QStringLiteral("&nbsp;&nbsp;");
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("<br>")));
_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/mainwindow.h b/src/mainwindow.h
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -1,64 +1,63 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QDialog>
#include <QFutureWatcher>
#include <QString>
class QLabel;
class QListWidget;
class QPushButton;
class QProgressBar;
class QTextEdit;
class ProgramSettings;
class SqlErrorDialog;
class SqlProcessor;
class DatabaseUpdater;
class ProgramSettings;
class KActivityIndicator;
class MainWindow : public QDialog
{
Q_OBJECT
public:
MainWindow(QWidget* parent = 0, Qt::WindowFlags flags = 0);
~MainWindow() override;
private slots:
void saveProtocol();
void closeDialog();
void startExecution();
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);
protected:
void closeEvent(QCloseEvent* a_event) override;
private:
int executeAction();
void logon(ProgramSettings& a_pset);
- void processArguments(ProgramSettings& a_pset);
void errorHtmlToLog(const QString& a_errorHtml);
static QString toHtml(const QString& a_text);
static QHash<QString, QString> loadAliases(const QString &a_ospoName);
int _exitCode;
int _errorCount;
QTextEdit* _protocol;
QLabel* _lblWait;
QPushButton* _btnSave;
QPushButton* _btnClose;
KActivityIndicator* _ai;
QProgressBar* _progress;
QFutureWatcher<int> _futureWatcher;
DatabaseUpdater* _updater;
};
//!главное окно приложения
#endif //MAINWINDOW_H
diff --git a/src/psettings.cpp b/src/psettings.cpp
new file mode 100644
--- /dev/null
+++ b/src/psettings.cpp
@@ -0,0 +1,71 @@
+#include "psettings.h"
+#include <QCommandLineParser>
+
+ProgramSettings 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 LOGFILE_VALUE = QStringLiteral("файл_журнала");
+ 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 LOGFILE_OPTION = QStringLiteral("L");
+ QString URIDB_OPTION = QStringLiteral("u");
+ 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 logfileOption(LOGFILE_OPTION, QStringLiteral("Сохранить протокол работы в файл"), LOGFILE_VALUE);
+ parser.addOption(logfileOption);
+ QCommandLineOption dropdbOption(DROPDB_OPTION, QStringLiteral("Сначала удалить базу данных"));
+ parser.addOption(dropdbOption);
+ QCommandLineOption uridbOption(URIDB_OPTION, QStringLiteral("Не создавать учебную базу данных"));
+ parser.addOption(uridbOption);
+ 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.logfile = parser.value(logfileOption);
+ result.dropdb = parser.isSet(dropdbOption);
+ result.uridb = !parser.isSet(uridbOption);
+
+ 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;
+}
diff --git a/src/psettings.h b/src/psettings.h
--- a/src/psettings.h
+++ b/src/psettings.h
@@ -1,24 +1,26 @@
#if !defined PSETTINGS_H
#define PSETTINGS_H
#include <QString>
class ProgramSettings
{
public:
ProgramSettings() : dbVersion(0), dropdb(false), uridb(true) {}
QString username;
QString password;
QString database;
QString host;
QString port;
QString controlFile;
QString logfile;
QString packageId;
QString helpText;
int dbVersion;
bool dropdb;
bool uridb;
};
+ProgramSettings processArguments();
+
#endif

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 11, 8:11 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
127129

Event Timeline