diff --git a/src/mainconsole.cpp b/src/mainconsole.cpp --- a/src/mainconsole.cpp +++ b/src/mainconsole.cpp @@ -1,159 +1,163 @@ #include "exitcode.h" #include "mainconsole.h" #include "psettings.h" #include "updater.h" #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)), 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 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(); } 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; + _os << CONSOLE_BRIGHT_RED_BEGIN << QStringLiteral("ОШИБКА") << CONSOLE_RESET << '\n'; message(a_error); - _os << CONSOLE_RESET << endl; + _os << CONSOLE_RESET << '\n'; + _os.flush(); ++_errorCount; } void MainConsole::message(const QString& a_message) { hideProgress(); - _os << toConsoleText(a_message) << endl; + _os << toConsoleText(a_message) << '\n'; + _os.flush(); } 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; + _os << '\r' << CONSOLE_GREEN_BEGIN << bytes << CONSOLE_RESET; + _os.flush(); } void MainConsole::hideProgress() { static const char* CONSOLE_ERASE_LINE = "\r\x1B[K"; - _os << CONSOLE_ERASE_LINE << flush; + _os << CONSOLE_ERASE_LINE; + _os.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); }