Page MenuHomePhabricator

No OneTemporary

diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,393 +1,401 @@
#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();
logon(pset);
+ _logFile = pset.logFile;
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;
}
+
+ if (!_logFile.isEmpty())
+ saveProtocol(_logFile);
}
//---------------------------------------------------------------------------
int MainWindow::executeAction()
{
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::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()
+void MainWindow::saveProtocol(const QString& a_fileName)
{
- QString filename = QFileDialog::getSaveFileName(this,
- QStringLiteral("Сохранить протокол в файл…"), QString(),
- QStringLiteral("Текстовые файлы (*.txt);;Все файлы (*.*)"));
+ QString filename = a_fileName;
+ if (filename.isEmpty())
+ 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,63 +1,64 @@
#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 saveProtocol(const QString& a_fileName = QString());
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 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;
+ QString _logFile;
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
--- a/src/psettings.cpp
+++ b/src/psettings.cpp
@@ -1,71 +1,73 @@
#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 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.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(logFileOption))
+ result.logFile = parser.value(logFileOption);
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,26 +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 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:14 PM (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
126731

Event Timeline