From c5a29c1f967e59f2723ddf15b8999f7468689bef Mon Sep 17 00:00:00 2001 From: MinyazevR Date: Mon, 1 Jul 2024 02:35:42 +0300 Subject: [PATCH 1/6] Add action for clang-tools --- .github/workflows/clang-tools.yml | 22 ++++++++++++++++++++++ .pre-commit-config.yaml | 5 +++++ 2 files changed, 27 insertions(+) create mode 100644 .github/workflows/clang-tools.yml create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/clang-tools.yml b/.github/workflows/clang-tools.yml new file mode 100644 index 0000000..c5f321d --- /dev/null +++ b/.github/workflows/clang-tools.yml @@ -0,0 +1,22 @@ +name: Clang-tidy and clang-format + +on: [push, pull_request, workflow_dispatch] + +jobs: + format: + runs-on: ubuntu-latest + # permissions: + # contents: read + # pull-requests: read + steps: + - uses: actions/checkout@v4 + - uses: cpp-linter/cpp-linter-action@v2.12.0 + id: linter + with: + style: 'file' + tidy-checks: '' + version: 15 + # lines-changed-only: true + - name: Exit + if: steps.linter.outputs.checks-failed > 0 + run: exit 1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..a020f20 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v15.0.7 + hooks: + - id: clang-format From b42a39ccc7b12ba4e7a42b9e1fbca152dd6acd66 Mon Sep 17 00:00:00 2001 From: MinyazevR Date: Mon, 1 Jul 2024 02:39:07 +0300 Subject: [PATCH 2/6] Add .clang-format and .clang-tidy --- .clang-format | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++ .clang-tidy | 145 +++++++++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-tidy diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..d5e65e6 --- /dev/null +++ b/.clang-format @@ -0,0 +1,206 @@ +--- +Language: Cpp +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BitFieldColonSpacing: After +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: true + AfterExternBlock: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +BreakAfterJavaFieldAnnotations: false +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Mozilla +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RequiresClausePosition: OwnLine +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: AlignWithSpaces +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..c952fea --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,145 @@ +--- +Checks: '-*, +bugprone-argument-comment, +bugprone-assert-side-effect, +bugprone-bad-signal-to-kill-thread, +bugprone-branch-clone, +bugprone-copy-constructor-init, +bugprone-dangling-handle, +bugprone-dynamic-static-initializers, +bugprone-fold-init-type, +bugprone-forward-declaration-namespace, +bugprone-forwarding-reference-overload, +bugprone-inaccurate-erase, +bugprone-incorrect-roundings, +bugprone-integer-division, +bugprone-lambda-function-name, +bugprone-macro-parentheses, +bugprone-macro-repeated-side-effects, +bugprone-misplaced-operator-in-strlen-in-alloc, +bugprone-misplaced-pointer-arithmetic-in-alloc, +bugprone-misplaced-widening-cast, +bugprone-move-forwarding-reference, +bugprone-multiple-statement-macro, +bugprone-no-escape, +bugprone-parent-virtual-call, +bugprone-posix-return, +bugprone-reserved-identifier, +bugprone-sizeof-container, +bugprone-sizeof-expression, +bugprone-spuriously-wake-up-functions, +bugprone-string-constructor, +bugprone-string-integer-assignment, +bugprone-string-literal-with-embedded-nul, +bugprone-suspicious-enum-usage, +bugprone-suspicious-include, +bugprone-suspicious-memset-usage, +bugprone-suspicious-missing-comma, +bugprone-suspicious-semicolon, +bugprone-suspicious-string-compare, +bugprone-suspicious-memory-comparison, +bugprone-suspicious-realloc-usage, +bugprone-swapped-arguments, +bugprone-terminating-continue, +bugprone-throw-keyword-missing, +bugprone-too-small-loop-variable, +bugprone-undefined-memory-manipulation, +bugprone-undelegated-constructor, +bugprone-unhandled-self-assignment, +bugprone-unused-raii, +bugprone-unused-return-value, +bugprone-use-after-move, +bugprone-virtual-near-miss, +cert-dcl21-cpp, +cert-dcl58-cpp, +cert-err34-c, +cert-err52-cpp, +cert-err60-cpp, +cert-flp30-c, +cert-msc50-cpp, +cert-msc51-cpp, +cert-str34-c, +cppcoreguidelines-interfaces-global-init, +cppcoreguidelines-narrowing-conversions, +cppcoreguidelines-pro-type-member-init, +cppcoreguidelines-pro-type-static-cast-downcast, +cppcoreguidelines-slicing, +google-default-arguments, +google-explicit-constructor, +google-runtime-operator, +hicpp-exception-baseclass, +hicpp-multiway-paths-covered, +misc-misplaced-const, +misc-new-delete-overloads, +misc-no-recursion, +misc-non-copyable-objects, +misc-throw-by-value-catch-by-reference, +misc-unconventional-assign-operator, +misc-uniqueptr-reset-release, +modernize-avoid-bind, +modernize-concat-nested-namespaces, +modernize-deprecated-headers, +modernize-deprecated-ios-base-aliases, +modernize-loop-convert, +modernize-make-shared, +modernize-make-unique, +modernize-pass-by-value, +modernize-raw-string-literal, +modernize-redundant-void-arg, +modernize-replace-auto-ptr, +modernize-replace-disallow-copy-and-assign-macro, +modernize-replace-random-shuffle, +modernize-return-braced-init-list, +modernize-shrink-to-fit, +modernize-unary-static-assert, +modernize-use-auto, +modernize-use-bool-literals, +modernize-use-emplace, +modernize-use-equals-default, +modernize-use-equals-delete, +modernize-use-nodiscard, +modernize-use-noexcept, +modernize-use-nullptr, +modernize-use-override, +modernize-use-transparent-functors, +modernize-use-uncaught-exceptions, +mpi-buffer-deref, +mpi-type-mismatch, +openmp-use-default-none, +performance-faster-string-find, +performance-for-range-copy, +performance-implicit-conversion-in-loop, +performance-inefficient-algorithm, +performance-inefficient-string-concatenation, +performance-inefficient-vector-operation, +performance-move-const-arg, +performance-move-constructor-init, +performance-no-automatic-move, +performance-noexcept-move-constructor, +performance-trivially-destructible, +performance-type-promotion-in-math-fn, +performance-unnecessary-copy-initialization, +performance-unnecessary-value-param, +portability-simd-intrinsics, +readability-avoid-const-params-in-decls, +readability-const-return-type, +readability-container-size-empty, +readability-convert-member-functions-to-static, +readability-delete-null-pointer, +readability-deleted-default, +readability-inconsistent-declaration-parameter-name, +readability-make-member-function-const, +readability-misleading-indentation, +readability-misplaced-array-index, +readability-non-const-parameter, +readability-redundant-control-flow, +readability-redundant-declaration, +readability-redundant-function-ptr-dereference, +readability-redundant-smartptr-get, +readability-redundant-string-cstr, +readability-redundant-string-init, +readability-simplify-subscript-expr, +readability-static-definition-in-anonymous-namespace, +readability-string-compare, +readability-uniqueptr-delete-release, +readability-use-anyofallof' From e491363938f89ebc35a4e22a1ebe8af5a53d6625 Mon Sep 17 00:00:00 2001 From: MinyazevR Date: Mon, 1 Jul 2024 03:57:19 +0300 Subject: [PATCH 3/6] Formatted, fixed bugs with start 2D-model and fixed ui --- checker.cpp | 569 ++++++++++++++++++------------------ checker.h | 29 +- htmlTemplates.h | 41 ++- main.cpp | 11 +- mainwindow.cpp | 35 +-- mainwindow.h | 26 +- mainwindow.ui | 92 +++--- optionsAliases.h | 10 +- translations/checkapp_ru.ts | 20 +- 9 files changed, 418 insertions(+), 415 deletions(-) diff --git a/checker.cpp b/checker.cpp index 83f9bd2..24ee1db 100644 --- a/checker.cpp +++ b/checker.cpp @@ -14,13 +14,14 @@ #include "checker.h" +#include #include -#include #include #include -#include -#include "optionsAliases.h" +#include + #include "htmlTemplates.h" +#include "optionsAliases.h" const int BACKGROUND_TIMELIMIT = 20 * 1000; const int MAX_VISIBLE_THREADS = 2; @@ -29,361 +30,369 @@ const QString TEMP_POSTFIX = "tmp_patched_qrs"; #ifdef Q_OS_LINUX void gnomeEnvironmentHandler(QProcess &process) { - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QString xdgCurrentDesktop = env.value("XDG_CURRENT_DESKTOP"); - if (xdgCurrentDesktop.contains("GNOME")) { - QStringList environment; - environment << "QT_QPA_PLATFORM=xcb"; - environment << "QT_DEBUG_PLUGINS=1"; - environment << "DISPLAY=:0"; - process.setEnvironment(environment); - } + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString xdgCurrentDesktop = env.value("XDG_CURRENT_DESKTOP"); + if (xdgCurrentDesktop.contains("GNOME")) { + QStringList environment; + environment << "QT_QPA_PLATFORM=xcb"; + environment << "DISPLAY=:0"; + process.setEnvironment(environment); + } } #endif Checker::Checker(const QString &tasksPath) - : mTasksPath(tasksPath) + : mTasksPath(tasksPath) { } -void Checker::reviewTasks(const QFileInfoList &qrsInfos, const QFileInfoList &fieldsInfos, const QHash &options) +void Checker::reviewTasks(const QFileInfoList &qrsInfos, + const QFileInfoList &fieldsInfos, + const QHash &options) { - auto patcherOptions = generatePatcherOptions(options); - auto runnerOptions = generateRunnerOptions(options); - - QProgressDialog dialog; - dialog.setCancelButtonText(tr("Cancel")); - dialog.setWindowTitle("TRIK CheckApp"); - dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - dialog.setLabelText(tr("A check is performed...")); - - QFutureWatcher>> watcher; - connect(&dialog, &QProgressDialog::canceled, &watcher - , &QFutureWatcher>>::cancel); - connect(&watcher, &QFutureWatcher>>::progressRangeChanged - , &dialog, &QProgressDialog::setRange); - connect(&watcher, &QFutureWatcher>>::progressValueChanged - , &dialog, &QProgressDialog::setValue); - connect(&watcher, &QFutureWatcher>>::finished, - this, [this, &dialog, &watcher](){ - dialog.setLabelText(tr("Creating a report")); - if (!watcher.isCanceled()) { - auto r = watcher.result(); - auto keys = r.keys(); - for (auto &x: keys) { - std::sort(r[x].begin(), r[x].end()); - } - - auto htmlReportName = createHtmlReport(r); - if (!QFile::exists(htmlReportName)) { - qDebug() << "Error: Report file not found: " << htmlReportName; - } - else if (!QDesktopServices::openUrl(QUrl::fromLocalFile(htmlReportName))) { - qDebug() << "Error: Couldn't open url for report file: " << htmlReportName; - } - } - dialog.reset(); - }); - - if (!options[backgroundOption].toBool()) { - QThreadPool::globalInstance()->setMaxThreadCount(MAX_VISIBLE_THREADS); - } - - QList tasksList; - for (auto &&qrs : qrsInfos) { - tasksList += new Task({qrs, fieldsInfos, patcherOptions, runnerOptions}); - } - createTasksEnvironment(); - auto futureTasks = QtConcurrent::mappedReduced(tasksList, checkTask, reduceFunction); - watcher.setFuture(futureTasks); - - dialog.exec(); - if (dialog.wasCanceled()) { - watcher.waitForFinished(); - } - - removeTasksEnvironment(); - qDeleteAll(tasksList); + auto patcherOptions = generatePatcherOptions(options); + auto runnerOptions = generateRunnerOptions(options); + + QProgressDialog dialog; + dialog.setCancelButtonText(tr("Cancel")); + dialog.setWindowTitle("TRIK CheckApp"); + dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); + dialog.setLabelText(tr("A check is performed...")); + + QFutureWatcher>> watcher; + connect(&dialog, &QProgressDialog::canceled, &watcher, &QFutureWatcher>>::cancel); + connect(&watcher, + &QFutureWatcher>>::progressRangeChanged, + &dialog, + &QProgressDialog::setRange); + connect(&watcher, + &QFutureWatcher>>::progressValueChanged, + &dialog, + &QProgressDialog::setValue); + connect(&watcher, &QFutureWatcher>>::finished, this, [this, &dialog, &watcher]() { + dialog.setLabelText(tr("Creating a report")); + if (!watcher.isCanceled()) { + auto r = watcher.result(); + auto keys = r.keys(); + for (auto &x : keys) { + std::sort(r[x].begin(), r[x].end()); + } + + auto htmlReportName = createHtmlReport(r); + if (!QFile::exists(htmlReportName)) { + qDebug() << "Error: Report file not found: " << htmlReportName; + } else if (!QDesktopServices::openUrl(QUrl::fromLocalFile(htmlReportName))) { + qDebug() << "Error: Couldn't open url for report file: " << htmlReportName; + } + } + dialog.reset(); + }); + + if (!options[backgroundOption].toBool()) { + QThreadPool::globalInstance()->setMaxThreadCount(MAX_VISIBLE_THREADS); + } + + QList tasksList; + for (auto &&qrs : qrsInfos) { + tasksList += new Task({ qrs, fieldsInfos, patcherOptions, runnerOptions }); + } + createTasksEnvironment(); + auto futureTasks = QtConcurrent::mappedReduced(tasksList, checkTask, reduceFunction); + watcher.setFuture(futureTasks); + + dialog.exec(); + if (dialog.wasCanceled()) { + watcher.waitForFinished(); + } + + removeTasksEnvironment(); + qDeleteAll(tasksList); } void Checker::createTasksEnvironment() { - QDir(mTasksPath).mkdir(TEMP_POSTFIX); + QDir(mTasksPath).mkdir(TEMP_POSTFIX); } void Checker::removeTasksEnvironment() { - const QString tmpDirPath = mTasksPath + QDir::separator() + TEMP_POSTFIX; - QDir(tmpDirPath).removeRecursively(); + const QString tmpDirPath = mTasksPath + QDir::separator() + TEMP_POSTFIX; + QDir(tmpDirPath).removeRecursively(); } -QPair Checker::handleJsonReport(const QString &filename) { - - QFile file(filename); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug() << "Error: The report file could not be opened:" << filename; - return QPair("", "error"); - } +QPair Checker::handleJsonReport(const QString &filename) +{ + QFile file(filename); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "Error: The report file could not be opened:" << filename; + return { "", "error" }; + } - const QString jsonString = file.readAll(); - file.close(); + const QString jsonString = file.readAll(); + file.close(); - if (!QFile::remove(filename)) { - qDebug() << "Error: Couldn't delete the report file: " << filename; - } + if (!QFile::remove(filename)) { + qDebug() << "Error: Couldn't delete the report file: " << filename; + } - QJsonParseError parseError; - const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8(), &parseError); + QJsonParseError parseError{}; + const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8(), &parseError); - if (jsonDoc.isNull() || jsonDoc.isEmpty()) { - qDebug() <<"Error: The report file should not be empty " << parseError.errorString(); - return QPair("", "error"); - } + if (jsonDoc.isNull() || jsonDoc.isEmpty()) { + qDebug() << "Error: The report file should not be empty " << parseError.errorString(); + return { "", "error" }; + } - auto jsonObj = jsonDoc.array().at(0).toObject(); - if (!jsonObj.contains("level") || !jsonObj.contains("message")) { - qDebug() <<"Error: The report file should not be empty " << parseError.errorString(); - return QPair("", "error"); - } + auto jsonObj = jsonDoc.array().at(0).toObject(); + if (!jsonObj.contains("level") || !jsonObj.contains("message")) { + qDebug() << "Error: The report file should not be empty " << parseError.errorString(); + return { "", "error" }; + } - const QString level = jsonObj["level"].toString(); - const QString message = jsonObj["message"].toString(); + const QString level = jsonObj["level"].toString(); + const QString message = jsonObj["message"].toString(); - return QPair(message, level); - } + return { message, level }; +} Checker::task_results_t Checker::checkTask(const Checker::Task *t) { - const QString ext = QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows ? ".exe": ""; - const QString tasksPath = t->qrs.absoluteDir().absolutePath(); - const QString tmpDirPath = tasksPath + QDir::separator() + TEMP_POSTFIX; + const QString ext = QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows ? ".exe" : ""; + const QString tasksPath = t->qrs.absoluteDir().absolutePath(); + const QString tmpDirPath = tasksPath + QDir::separator() + TEMP_POSTFIX; - task_results_t result; + task_results_t result; - static const QRegularExpression pattern(tr("in") + " (\\d+(\\.\\d+)?) " + tr("sec")); + static const QRegularExpression pattern(tr("in") + R"( (\\d+(\\.\\d+)?) )" + tr("sec")); - for (auto &&f : t->fieldsInfos) { - const QString patchedQrsName = tmpDirPath + QDir::separator() + t->qrs.fileName(); - QFile::copy(t->qrs.absoluteFilePath(), patchedQrsName); - QFile patchedQrs(patchedQrsName); + for (auto &&f : t->fieldsInfos) { + const QString patchedQrsName = tmpDirPath + QDir::separator() + t->qrs.fileName(); + QFile::copy(t->qrs.absoluteFilePath(), patchedQrsName); + QFile patchedQrs(patchedQrsName); - TaskReport report; - report.name = t->qrs.fileName(); - report.task = f.fileName(); - report.time = "-"; + TaskReport report; + report.name = t->qrs.fileName(); + report.task = f.fileName(); + report.time = "-"; - report.message = executeProcess("./patcher" + ext, QStringList(patchedQrs.fileName()) + t->patcherOptions << f.absoluteFilePath()); + auto execDir = QCoreApplication::applicationDirPath(); + report.message = executeProcess(execDir + QDir::separator() + "patcher" + ext, + QStringList(patchedQrs.fileName()) + t->patcherOptions << f.absoluteFilePath()); - if (isErrorMessage(report.message)) { - qDebug() << "Error: Failed to patch:" << report.message; - report.level = "error"; - result.append(report); - continue; - } + if (isErrorMessage(report.message)) { + qDebug() << "Error: Failed to patch:" << report.message; + report.level = "error"; + result.append(report); + continue; + } - const QString reportFileName = tmpDirPath + QDir::separator() + report.name + report.task; - auto additional_options = QStringList("-r") << reportFileName; + const QString reportFileName = tmpDirPath + QDir::separator() + report.name + report.task; + auto additional_options = QStringList("-r") << reportFileName; - auto message = executeProcess("./2D-model" + ext, QStringList(patchedQrs.fileName()) + t->runnerOptions + additional_options); + auto message = executeProcess(execDir + QDir::separator() + "2D-model" + ext, + QStringList(patchedQrs.fileName()) + t->runnerOptions + additional_options); - auto twoModelResult = handleJsonReport(reportFileName); - report.level = twoModelResult.second; + auto twoModelResult = handleJsonReport(reportFileName); + report.level = twoModelResult.second; - if (twoModelResult.first != "") { - report.message = twoModelResult.first; + if (twoModelResult.first != "") { + report.message = twoModelResult.first; - if (twoModelResult.second == "error") { - qDebug() << "Error: Failed to run 2D-model:" << report.message; - result.append(report); - continue; - } - } + if (twoModelResult.second == "error") { + qDebug() << "Error: Failed to run 2D-model:" << report.message; + result.append(report); + continue; + } + } - else if (twoModelResult.second == "error") { - report.message = getErrorMessage(message); - qDebug() << "Error: Failed to run 2D-model:" << message; - result.append(report); - continue; - } + else if (twoModelResult.second == "error") { + report.message = getErrorMessage(message); + qDebug() << "Error: Failed to run 2D-model:" << message; + result.append(report); + continue; + } - auto match = pattern.match(report.message); + auto match = pattern.match(report.message); - if (match.hasMatch()) { - report.time = match.captured(1) + " " + tr("sec"); - } + if (match.hasMatch()) { + report.time = match.captured(1) + " " + tr("sec"); + } - result.append(report); - } + result.append(report); + } - return result; + return result; } -void Checker::reduceFunction(QHash &result, const Checker::task_results_t &intermediate) +void Checker::reduceFunction(QHash &result, + const Checker::task_results_t &intermediate) { - for (auto &i : intermediate) { - result[i.name].append(i); - } + for (auto &i : intermediate) { + result[i.name].append(i); + } } QString Checker::executeProcess(const QString &program, const QStringList &options) { - QProcess process; + QProcess process; #ifdef Q_OS_LINUX - gnomeEnvironmentHandler(process); + gnomeEnvironmentHandler(process); #endif - QEventLoop l; - - connect(&process, QOverload::of(&QProcess::finished) - , &l, [&](int exitCode, QProcess::ExitStatus exitStatus) { - Q_UNUSED(exitCode) - if (exitStatus == QProcess::ExitStatus::CrashExit) { - l.exit(-1); - } - else { - l.exit(); - } - }); - - connect(&process, &QProcess::errorOccurred, &l, [&](QProcess::ProcessError processError) { - qDebug() << "ERROR" << processError << program << options; - l.exit(-1); - }); - - if (options.contains("-b")) { - QTimer::singleShot(BACKGROUND_TIMELIMIT, Qt::TimerType::CoarseTimer, &l, [&](){ - qDebug() << "ERROR TIMEOUT" << program << options; - l.exit(-2); - }); - } - - process.start(program, options); - auto rc = l.exec(); - switch (rc) { - case -1: return "Error: Application proccess crashed. Please, check manually"; - default: return process.readAllStandardError(); - } + QEventLoop l; + + connect(&process, + QOverload::of(&QProcess::finished), + &l, + [&](int exitCode, QProcess::ExitStatus exitStatus) { + Q_UNUSED(exitCode) + if (exitStatus == QProcess::ExitStatus::CrashExit) { + l.exit(-1); + } else { + l.exit(); + } + }); + + connect(&process, &QProcess::errorOccurred, &l, [&](QProcess::ProcessError processError) { + qDebug() << "ERROR" << processError << program << options; + l.exit(-1); + }); + + if (options.contains("-b")) { + QTimer::singleShot(BACKGROUND_TIMELIMIT, Qt::TimerType::CoarseTimer, &l, [&]() { + qDebug() << "ERROR TIMEOUT" << program << options; + l.exit(-2); + }); + } + + process.start(program, options); + auto rc = l.exec(); + + if (rc == -1) { + return "Error: Application proccess crashed. Please, check manually"; } -const QString Checker::createHtmlReport(const QHash> &result) + return process.readAllStandardError(); +} + +QString Checker::createHtmlReport(const QHash> &result) { - auto qrsNames = result.keys(); - std::sort(qrsNames.begin(), qrsNames.end()); - - const QDateTime dateTime = QDateTime::currentDateTime(); - QString body = reportHeader.arg(mTasksPath.section(QDir::separator(), -1), dateTime.toString("hh:mm:ss dd.MM.yyyy")); - - int i = 0; - for (auto &&key : qrsNames) { - int numberOfCorrect = 0; - auto studentResults = result[key]; - - for(auto &&r: studentResults) { - numberOfCorrect += !isErrorReport(r); - } - - QString color = yellowCssClass; - if (numberOfCorrect == studentResults.length()) { - color = greenCssClass; - } else if (numberOfCorrect == 0) { - color = blackCssClass; - } - - QString name = QString(tr("Total %1 of %2")).arg(numberOfCorrect).arg(studentResults.length()); - body += taskReport.arg(color, key, tr("All"), name, "-"); - - for (auto &&r : studentResults) { - const QString errorMessage = isErrorReport(r) ? r.message : tr("Complete"); - body += taskReport.arg("", "", r.task, errorMessage, r.time); - } - - i++; - } - - QFile htmlBegin(":/report_begin.html"); - htmlBegin.open(QFile::ReadOnly); - QString report = htmlBegin.readAll(); - htmlBegin.close(); - - report += body; - - QFile htmlEnd(":/report_end.html"); - htmlEnd.open(QFile::ReadOnly); - report += htmlEnd.readAll(); - htmlEnd.close(); - - const QString reportFileName = QString("report_%1.html").arg(dateTime.toString("dd_MM_yyyy_hh_mm_ss")); - QFileInfo reportFileInfo(mTasksPath + QDir::separator() + reportFileName); - QFile reportFile(reportFileInfo.absoluteFilePath()); - if (!reportFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - qDebug() << "Error: Failed to open" << reportFileInfo.absoluteFilePath() << "with" << reportFile.errorString(); - } - if (reportFile.write(report.toUtf8()) < 0) { - qDebug() << "Error: Failed to write" << reportFileInfo.absoluteFilePath() << "with" << reportFile.errorString(); - } - reportFile.close(); - - return reportFileInfo.absoluteFilePath(); + auto qrsNames = result.keys(); + std::sort(qrsNames.begin(), qrsNames.end()); + + const QDateTime dateTime = QDateTime::currentDateTime(); + QString body = + reportHeader.arg(mTasksPath.section(QDir::separator(), -1), dateTime.toString("hh:mm:ss dd.MM.yyyy")); + + int i = 0; + for (auto &&key : qrsNames) { + int numberOfCorrect = 0; + auto studentResults = result[key]; + + for (auto &&r : studentResults) { + numberOfCorrect += !isErrorReport(r); + } + + QString color = yellowCssClass; + if (numberOfCorrect == studentResults.length()) { + color = greenCssClass; + } else if (numberOfCorrect == 0) { + color = blackCssClass; + } + + QString name = QString(tr("Total %1 of %2")).arg(numberOfCorrect).arg(studentResults.length()); + body += taskReport.arg(color, key, tr("All"), name, "-"); + + for (auto &&r : studentResults) { + const QString errorMessage = isErrorReport(r) ? r.message : tr("Complete"); + body += taskReport.arg("", "", r.task, errorMessage, r.time); + } + + i++; + } + + QFile htmlBegin(":/report_begin.html"); + htmlBegin.open(QFile::ReadOnly); + QString report = htmlBegin.readAll(); + htmlBegin.close(); + + report += body; + + QFile htmlEnd(":/report_end.html"); + htmlEnd.open(QFile::ReadOnly); + report += htmlEnd.readAll(); + htmlEnd.close(); + + const QString reportFileName = QString("report_%1.html").arg(dateTime.toString("dd_MM_yyyy_hh_mm_ss")); + QFileInfo reportFileInfo(mTasksPath + QDir::separator() + reportFileName); + QFile reportFile(reportFileInfo.absoluteFilePath()); + if (!reportFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + qDebug() << "Error: Failed to open" << reportFileInfo.absoluteFilePath() << "with" << reportFile.errorString(); + } + if (reportFile.write(report.toUtf8()) < 0) { + qDebug() << "Error: Failed to write" << reportFileInfo.absoluteFilePath() << "with" << reportFile.errorString(); + } + reportFile.close(); + + return reportFileInfo.absoluteFilePath(); } -const QStringList Checker::generateRunnerOptions(const QHash &options) +QStringList Checker::generateRunnerOptions(const QHash &options) { - QStringList result; - if (options[closeSuccessOption].toBool()) { - result << "--close-on-success"; - } + QStringList result; + if (options[closeSuccessOption].toBool()) { + result << "--close-on-success"; + } - if (options[backgroundOption].toBool()) { - result << "-b"; - } + if (options[backgroundOption].toBool()) { + result << "-b"; + } - if (options[consoleOption].toBool()) { - result << "-c"; - } + if (options[consoleOption].toBool()) { + result << "-c"; + } - return result; + return result; } -const QStringList Checker::generatePatcherOptions(const QHash &options) +QStringList Checker::generatePatcherOptions(const QHash &options) { - QStringList result; - if (options[resetRP].toBool()) { - result << "--rrp"; - } - - if (options[patchField].toBool()) { - result << "-f"; - } - else { - if (options[patchWP].toBool()) { - result << "--wp"; - } - else { - result << "-w"; - } - } - - return result; + QStringList result; + if (options[resetRP].toBool()) { + result << "--rrp"; + } + + if (options[patchField].toBool()) { + result << "-f"; + } else { + if (options[patchWP].toBool()) { + result << "--wp"; + } else { + result << "-w"; + } + } + + return result; } bool Checker::isErrorMessage(const QString &message) { - return message.indexOf(tr("Error")) != -1 or message.indexOf("Error") != -1; + return message.indexOf(tr("Error")) != -1 or message.indexOf("Error") != -1; } bool Checker::isErrorReport(const TaskReport &report) { - return report.level == "error"; + return report.level == "error"; } QString Checker::getErrorMessage(const QString &message) { - auto messageLastIndex = message.lastIndexOf(tr("Error")); - auto endErrorIndex = message.indexOf(QChar::LineFeed, messageLastIndex); + auto messageLastIndex = message.lastIndexOf(tr("Error")); + auto endErrorIndex = message.indexOf(QChar::LineFeed, messageLastIndex); - if (messageLastIndex != -1 and endErrorIndex == -1) { - return message.mid(messageLastIndex); - } - return message.mid(messageLastIndex, endErrorIndex - messageLastIndex + 1); + if (messageLastIndex != -1 and endErrorIndex == -1) { + return message.mid(messageLastIndex); + } + return message.mid(messageLastIndex, endErrorIndex - messageLastIndex + 1); } diff --git a/checker.h b/checker.h index 275afa2..a806d23 100644 --- a/checker.h +++ b/checker.h @@ -21,29 +21,32 @@ class Checker : public QObject { Q_OBJECT -public: - Checker(const QString &tasksPath); - - void reviewTasks(const QFileInfoList &qrsInfos, const QFileInfoList &fieldsInfos, const QHash &options); - struct Task { + public: + explicit Checker(const QString &tasksPath); + + void reviewTasks(const QFileInfoList &qrsInfos, + const QFileInfoList &fieldsInfos, + const QHash &options); + struct Task + { QFileInfo qrs; const QFileInfoList &fieldsInfos; const QStringList &patcherOptions; const QStringList &runnerOptions; }; - struct TaskReport { + struct TaskReport + { QString name; QString task; QString time; QString message; QString level; - bool operator <(const TaskReport& other) const { return task < other.task; } + bool operator<(const TaskReport &other) const { return task < other.task; } }; -private: + private: typedef QList task_results_t; static void reduceFunction(QHash &result, const task_results_t &intermediate); @@ -54,15 +57,15 @@ class Checker : public QObject static QPair handleJsonReport(const QString &filename); - const QString createHtmlReport(const QHash > &result); + QString createHtmlReport(const QHash> &result); - const QStringList generateRunnerOptions(const QHash &options); + static QStringList generateRunnerOptions(const QHash &options); - const QStringList generatePatcherOptions(const QHash &options); + static QStringList generatePatcherOptions(const QHash &options); static bool isErrorMessage(const QString &message); - static bool isErrorReport(const TaskReport &message); + static bool isErrorReport(const TaskReport &report); static QString getErrorMessage(const QString &message); diff --git a/htmlTemplates.h b/htmlTemplates.h index 5139e1a..8bac499 100644 --- a/htmlTemplates.h +++ b/htmlTemplates.h @@ -19,22 +19,22 @@ // %1 - task folder name // %2 - time and date QString reportHeader = - "
" - "
" - "

" - "" - "%1
%2" - "

" - "
" - "
" - "" - "" - "" - "" - "" - ""; + "
" + "
" + "

" + "" + "%1
%2" + "

" + "
" + "
" + "
" - "Имя
ТестСтатус
" - "Время исполнения
" + "" + "" + "" + "" + ""; QString greenCssClass = "u-custom-color-1 u-text-black"; QString yellowCssClass = "u-palette-3-light-1 u-text-black"; @@ -46,8 +46,7 @@ QString blackCssClass = "u-custom-color-2"; // %4 - status // %5 - execution time QString taskReport = - "" - "" - "" - ""; - + "" + "" + "" + ""; diff --git a/main.cpp b/main.cpp index c9eaf3e..1b4fe73 100644 --- a/main.cpp +++ b/main.cpp @@ -15,14 +15,14 @@ #include "mainwindow.h" #include +#include +#include #include #include -#include -#include int main(int argc, char *argv[]) { - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setStyle(QStyleFactory::create("Fusion")); QApplication a(argc, argv); @@ -30,9 +30,8 @@ int main(int argc, char *argv[]) const QString translation_file = ":/translations/checkapp_" + QLocale::system().name() + ".qm"; if (!translator.load(translation_file)) { qDebug() << "Failed to load translation file: " << translation_file; - } - else { - a.installTranslator(&translator); + } else { + a.installTranslator(&translator); } MainWindow w; diff --git a/mainwindow.cpp b/mainwindow.cpp index 8ccc211..15d0753 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -15,24 +15,24 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -#include #include #include #include #include +#include #include "checker.h" #include "optionsAliases.h" MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , mUi(new Ui::MainWindow) - , mTasksDir(QDir::currentPath()) - , mLocalSettings(QDir::toNativeSeparators(mTasksDir.absolutePath() + "/checkapp.ini")) + : QMainWindow(parent) + , mUi(new Ui::MainWindow) + , mTasksDir(QDir::currentPath()) + , mLocalSettings(QDir::toNativeSeparators(mTasksDir.absolutePath() + "/checkapp.ini")) { mUi->setupUi(this); - connect(mUi->backgroundOption, &QGroupBox::toggled, this, [this](bool state){ + connect(mUi->backgroundOption, &QGroupBox::toggled, this, [this](bool state) { mDirOptions[mTasksPath][backgroundOption] = !state; mUi->closeOnSuccessOption->setEnabled(state); }); @@ -49,16 +49,16 @@ MainWindow::~MainWindow() void MainWindow::on_runCheckButton_clicked() { - auto qrsList = mTasksDir.entryInfoList({"*.qrs"}, QDir::Files); + auto qrsList = mTasksDir.entryInfoList({ "*.qrs" }, QDir::Files); if (qrsList.isEmpty()) { - qrsList = mTasksDir.entryInfoList({"*.tsj"}, QDir::Files); + qrsList = mTasksDir.entryInfoList({ "*.tsj" }, QDir::Files); } if (qrsList.isEmpty()) { showNoQrsTsjMessage(); return; } - auto fields = mFieldsDir.entryInfoList({"*.xml"}, QDir::Files); + auto fields = mFieldsDir.entryInfoList({ "*.xml" }, QDir::Files); if (fields.isEmpty()) { showNoFieldsMessage(); return; @@ -70,7 +70,7 @@ void MainWindow::on_runCheckButton_clicked() void MainWindow::on_chooseField_clicked() { mFieldsDir = chooseDirectoryDialog(); - if (mFieldsDir.entryInfoList({"*.xml"}, QDir::Files).isEmpty()) { + if (mFieldsDir.entryInfoList({ "*.xml" }, QDir::Files).isEmpty()) { showNoFieldsMessage(); } @@ -82,7 +82,7 @@ void MainWindow::on_chooseField_clicked() void MainWindow::on_openTasks_clicked() { mTasksDir = chooseDirectoryDialog(); - if (mTasksDir.entryInfoList({"*.qrs", "*.tsj"}, QDir::Files).isEmpty()) { + if (mTasksDir.entryInfoList({ "*.qrs", "*.tsj" }, QDir::Files).isEmpty()) { showNoQrsTsjMessage(); return; } @@ -135,15 +135,16 @@ QDir MainWindow::chooseDirectoryDialog() return dialog.directory(); } - void MainWindow::resetUiOptions(const QHash &options) { - mUi->closeOnSuccessOption->setCheckState(options[closeSuccessOption].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + mUi->closeOnSuccessOption->setCheckState(options[closeSuccessOption].toBool() ? Qt::CheckState::Checked + : Qt::CheckState::Unchecked); mUi->backgroundOption->setChecked(!options[backgroundOption].toBool()); mUi->wPPCheckBox->setCheckState(options[patchField].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); mUi->wPcheckBox->setCheckState(options[patchWP].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); mUi->resetPCheckBox->setCheckState(options[resetRP].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - mUi->showConsoleCheckBox->setCheckState(options[consoleOption].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + mUi->showConsoleCheckBox->setCheckState(options[consoleOption].toBool() ? Qt::CheckState::Checked + : Qt::CheckState::Unchecked); mUi->xmlFieldsDir->setText(options[xmlFieldsDir].toString()); } @@ -152,7 +153,7 @@ void MainWindow::loadSettings() QSettings settings(mLocalSettings, QSettings::IniFormat); auto groups = settings.childGroups(); for (auto &&g : groups) { - QHash options; + QHash options; settings.beginGroup(g); @@ -170,10 +171,10 @@ void MainWindow::saveSettings() { QSettings settings(mLocalSettings, QSettings::IniFormat); auto mDirOptionsKeys = mDirOptions.keys(); - for (auto &&dir: mDirOptionsKeys) { + for (auto &&dir : mDirOptionsKeys) { settings.beginGroup(dir); auto options = mDirOptions[dir].keys(); - for (auto &&option: options) { + for (auto &&option : options) { settings.setValue(option, mDirOptions[dir][option]); } settings.endGroup(); diff --git a/mainwindow.h b/mainwindow.h index 9024cc6..e722262 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -18,18 +18,20 @@ #include QT_BEGIN_NAMESPACE -namespace Ui { class MainWindow; } +namespace Ui { +class MainWindow; +} QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT -public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); + public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow() override; -private slots: + private slots: void on_chooseField_clicked(); void on_openTasks_clicked(); @@ -44,20 +46,20 @@ private slots: void on_showConsoleCheckBox_stateChanged(int state); - void on_closeOnSuccessOption_stateChanged(int arg1); + void on_closeOnSuccessOption_stateChanged(int state); -private: - QDir chooseDirectoryDialog(); + private: + static QDir chooseDirectoryDialog(); - void resetUiOptions(const QHash &options); + void resetUiOptions(const QHash &options); void loadSettings(); void saveSettings(); - void showNoQrsTsjMessage(); + static void showNoQrsTsjMessage(); - void showNoFieldsMessage(); + static void showNoFieldsMessage(); Ui::MainWindow *mUi; QDir mTasksDir; @@ -66,5 +68,5 @@ private slots: QDir mStudioDir; QString mLocalSettings; - QHash > mDirOptions; + QHash> mDirOptions; }; diff --git a/mainwindow.ui b/mainwindow.ui index a79b64f..32e9403 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 582 - 252 + 749 + 291 @@ -162,53 +162,47 @@ false - - - - 10 - 20 - 371 - 42 - - - - - - - - 0 - 0 - - - - Display the robot console - - - false - - - - - - - false - - - - 0 - 0 - - - - Close the window after checking the task - - - false - - - - - + + + + + + + + 0 + 0 + + + + Display the robot console + + + false + + + + + + + false + + + + 0 + 0 + + + + Close the window after checking the task + + + false + + + + + + diff --git a/optionsAliases.h b/optionsAliases.h index 502909c..8a51516 100644 --- a/optionsAliases.h +++ b/optionsAliases.h @@ -27,10 +27,6 @@ const QString patchWorld = "patchWorld"; const QString patchWP = "patchWroldAndPosition"; const QString resetRP = "resetRobotPosition"; -const QHash defaultOptions {{closeSuccessOption, true} - ,{backgroundOption, false} - ,{consoleOption, false} - ,{xmlFieldsDir, ""} - ,{patchField, true} - ,{patchWP, false}}; - +const QHash defaultOptions{ { closeSuccessOption, true }, { backgroundOption, false }, + { consoleOption, false }, { xmlFieldsDir, "" }, + { patchField, true }, { patchWP, false } }; diff --git a/translations/checkapp_ru.ts b/translations/checkapp_ru.ts index 069baf5..1714b9d 100644 --- a/translations/checkapp_ru.ts +++ b/translations/checkapp_ru.ts @@ -4,7 +4,7 @@ Checker - + Cancel Отменить @@ -14,24 +14,24 @@ Выполняется проверка - + Creating a report Создаю отчёт - + in за сколько секунд за - + sec сек - + Total %1 of %2 Итого %1 из %2 @@ -41,13 +41,13 @@ Все - + Error Ошибка - + Complete Выполнено @@ -106,7 +106,7 @@ Включить визуализацию проверки - + Display the robot console Отображать консоль робота @@ -116,7 +116,7 @@ Закрывать окно после проверки задачи - + <html><head/><body><p>Check the solutions on the selected fields</p></body></html> <html><head/><body><p>Проверить решения на выбранных полях</p></body></html> @@ -126,7 +126,7 @@ Выполнить проверку ... - + There is no .qrs or .tsj files in solutions directory. В каталоге решений нет файлов .qrs или .tsj. From 6602d61b27f84deb777dc469f0be7d07b360506c Mon Sep 17 00:00:00 2001 From: MinyazevR Date: Mon, 1 Jul 2024 05:08:58 +0300 Subject: [PATCH 4/6] Never use tabs --- .clang-format | 9 +-- checker.h | 44 +++++++------- main.cpp | 20 +++---- mainwindow.cpp | 158 ++++++++++++++++++++++++------------------------- mainwindow.h | 32 +++++----- 5 files changed, 128 insertions(+), 135 deletions(-) diff --git a/.clang-format b/.clang-format index d5e65e6..833a619 100644 --- a/.clang-format +++ b/.clang-format @@ -196,11 +196,4 @@ StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION TabWidth: 4 -UseTab: AlignWithSpaces -WhitespaceSensitiveMacros: - - BOOST_PP_STRINGIZE - - CF_SWIFT_NAME - - NS_SWIFT_NAME - - PP_STRINGIZE - - STRINGIZE -... +UseTab: Never diff --git a/checker.h b/checker.h index a806d23..4b96536 100644 --- a/checker.h +++ b/checker.h @@ -19,7 +19,7 @@ class Checker : public QObject { - Q_OBJECT + Q_OBJECT public: explicit Checker(const QString &tasksPath); @@ -29,33 +29,33 @@ class Checker : public QObject const QHash &options); struct Task { - QFileInfo qrs; - const QFileInfoList &fieldsInfos; - const QStringList &patcherOptions; - const QStringList &runnerOptions; - }; + QFileInfo qrs; + const QFileInfoList &fieldsInfos; + const QStringList &patcherOptions; + const QStringList &runnerOptions; + }; struct TaskReport { - QString name; - QString task; - QString time; - QString message; - QString level; + QString name; + QString task; + QString time; + QString message; + QString level; bool operator<(const TaskReport &other) const { return task < other.task; } - }; + }; private: - typedef QList task_results_t; + typedef QList task_results_t; - static void reduceFunction(QHash &result, const task_results_t &intermediate); + static void reduceFunction(QHash &result, const task_results_t &intermediate); - static task_results_t checkTask(const Task *task); + static task_results_t checkTask(const Task *task); - static QString executeProcess(const QString &program, const QStringList &options); + static QString executeProcess(const QString &program, const QStringList &options); - static QPair handleJsonReport(const QString &filename); + static QPair handleJsonReport(const QString &filename); QString createHtmlReport(const QHash> &result); @@ -63,15 +63,15 @@ class Checker : public QObject static QStringList generatePatcherOptions(const QHash &options); - static bool isErrorMessage(const QString &message); + static bool isErrorMessage(const QString &message); static bool isErrorReport(const TaskReport &report); - static QString getErrorMessage(const QString &message); + static QString getErrorMessage(const QString &message); - const QString &mTasksPath; + const QString &mTasksPath; - void createTasksEnvironment(); + void createTasksEnvironment(); - void removeTasksEnvironment(); + void removeTasksEnvironment(); }; diff --git a/main.cpp b/main.cpp index 1b4fe73..ac79ab6 100644 --- a/main.cpp +++ b/main.cpp @@ -23,18 +23,18 @@ int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QApplication::setStyle(QStyleFactory::create("Fusion")); - QApplication a(argc, argv); + QApplication::setStyle(QStyleFactory::create("Fusion")); + QApplication a(argc, argv); - QTranslator translator; - const QString translation_file = ":/translations/checkapp_" + QLocale::system().name() + ".qm"; - if (!translator.load(translation_file)) { - qDebug() << "Failed to load translation file: " << translation_file; + QTranslator translator; + const QString translation_file = ":/translations/checkapp_" + QLocale::system().name() + ".qm"; + if (!translator.load(translation_file)) { + qDebug() << "Failed to load translation file: " << translation_file; } else { a.installTranslator(&translator); - } + } - MainWindow w; - w.show(); - return a.exec(); + MainWindow w; + w.show(); + return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp index 15d0753..32ad8a9 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -30,167 +30,167 @@ MainWindow::MainWindow(QWidget *parent) , mTasksDir(QDir::currentPath()) , mLocalSettings(QDir::toNativeSeparators(mTasksDir.absolutePath() + "/checkapp.ini")) { - mUi->setupUi(this); + mUi->setupUi(this); connect(mUi->backgroundOption, &QGroupBox::toggled, this, [this](bool state) { - mDirOptions[mTasksPath][backgroundOption] = !state; - mUi->closeOnSuccessOption->setEnabled(state); - }); + mDirOptions[mTasksPath][backgroundOption] = !state; + mUi->closeOnSuccessOption->setEnabled(state); + }); - loadSettings(); - mUi->runCheckButton->setEnabled(!mTasksPath.isEmpty()); + loadSettings(); + mUi->runCheckButton->setEnabled(!mTasksPath.isEmpty()); } MainWindow::~MainWindow() { - saveSettings(); - delete mUi; + saveSettings(); + delete mUi; } void MainWindow::on_runCheckButton_clicked() { auto qrsList = mTasksDir.entryInfoList({ "*.qrs" }, QDir::Files); - if (qrsList.isEmpty()) { + if (qrsList.isEmpty()) { qrsList = mTasksDir.entryInfoList({ "*.tsj" }, QDir::Files); - } - if (qrsList.isEmpty()) { - showNoQrsTsjMessage(); - return; - } + } + if (qrsList.isEmpty()) { + showNoQrsTsjMessage(); + return; + } auto fields = mFieldsDir.entryInfoList({ "*.xml" }, QDir::Files); - if (fields.isEmpty()) { - showNoFieldsMessage(); - return; - } - Checker checker(mTasksPath); - checker.reviewTasks(qrsList, fields, mDirOptions[mTasksPath]); + if (fields.isEmpty()) { + showNoFieldsMessage(); + return; + } + Checker checker(mTasksPath); + checker.reviewTasks(qrsList, fields, mDirOptions[mTasksPath]); } void MainWindow::on_chooseField_clicked() { - mFieldsDir = chooseDirectoryDialog(); + mFieldsDir = chooseDirectoryDialog(); if (mFieldsDir.entryInfoList({ "*.xml" }, QDir::Files).isEmpty()) { - showNoFieldsMessage(); - } + showNoFieldsMessage(); + } - auto path = QDir::toNativeSeparators(mFieldsDir.absolutePath()); - mUi->xmlFieldsDir->setText(path); - mDirOptions[mTasksPath][xmlFieldsDir] = path; + auto path = QDir::toNativeSeparators(mFieldsDir.absolutePath()); + mUi->xmlFieldsDir->setText(path); + mDirOptions[mTasksPath][xmlFieldsDir] = path; } void MainWindow::on_openTasks_clicked() { - mTasksDir = chooseDirectoryDialog(); + mTasksDir = chooseDirectoryDialog(); if (mTasksDir.entryInfoList({ "*.qrs", "*.tsj" }, QDir::Files).isEmpty()) { - showNoQrsTsjMessage(); - return; - } + showNoQrsTsjMessage(); + return; + } - mTasksPath = QDir::toNativeSeparators(mTasksDir.absolutePath()); - mUi->currentTasksDir->setText(mTasksPath); + mTasksPath = QDir::toNativeSeparators(mTasksDir.absolutePath()); + mUi->currentTasksDir->setText(mTasksPath); - if (!mDirOptions.contains(mTasksPath)) { - mDirOptions[mTasksPath] = defaultOptions; - } + if (!mDirOptions.contains(mTasksPath)) { + mDirOptions[mTasksPath] = defaultOptions; + } - auto xmlField = mDirOptions[mTasksPath][xmlFieldsDir].toString(); - mFieldsDir = xmlField.isEmpty() ? mTasksDir : QDir(xmlField); - mDirOptions[mTasksPath][xmlFieldsDir] = xmlField.isEmpty() ? mTasksPath : xmlField; + auto xmlField = mDirOptions[mTasksPath][xmlFieldsDir].toString(); + mFieldsDir = xmlField.isEmpty() ? mTasksDir : QDir(xmlField); + mDirOptions[mTasksPath][xmlFieldsDir] = xmlField.isEmpty() ? mTasksPath : xmlField; - resetUiOptions(mDirOptions[mTasksPath]); - mUi->runCheckButton->setEnabled(true); + resetUiOptions(mDirOptions[mTasksPath]); + mUi->runCheckButton->setEnabled(true); } void MainWindow::on_wPcheckBox_stateChanged(int state) { - mDirOptions[mTasksPath][patchWP] = state == Qt::CheckState::Checked; + mDirOptions[mTasksPath][patchWP] = state == Qt::CheckState::Checked; } void MainWindow::on_wPPCheckBox_stateChanged(int state) { - mDirOptions[mTasksPath][patchField] = state == Qt::CheckState::Checked; + mDirOptions[mTasksPath][patchField] = state == Qt::CheckState::Checked; } void MainWindow::on_resetPCheckBox_stateChanged(int state) { - mDirOptions[mTasksPath][resetRP] = state == Qt::CheckState::Checked; + mDirOptions[mTasksPath][resetRP] = state == Qt::CheckState::Checked; } void MainWindow::on_showConsoleCheckBox_stateChanged(int state) { - mDirOptions[mTasksPath][consoleOption] = state == Qt::CheckState::Checked; + mDirOptions[mTasksPath][consoleOption] = state == Qt::CheckState::Checked; } void MainWindow::on_closeOnSuccessOption_stateChanged(int state) { - mDirOptions[mTasksPath][closeSuccessOption] = state == Qt::CheckState::Checked; + mDirOptions[mTasksPath][closeSuccessOption] = state == Qt::CheckState::Checked; } QDir MainWindow::chooseDirectoryDialog() { - QFileDialog dialog; - dialog.setFileMode(QFileDialog::Directory); - dialog.exec(); - return dialog.directory(); + QFileDialog dialog; + dialog.setFileMode(QFileDialog::Directory); + dialog.exec(); + return dialog.directory(); } void MainWindow::resetUiOptions(const QHash &options) { mUi->closeOnSuccessOption->setCheckState(options[closeSuccessOption].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - mUi->backgroundOption->setChecked(!options[backgroundOption].toBool()); - mUi->wPPCheckBox->setCheckState(options[patchField].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - mUi->wPcheckBox->setCheckState(options[patchWP].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - mUi->resetPCheckBox->setCheckState(options[resetRP].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + mUi->backgroundOption->setChecked(!options[backgroundOption].toBool()); + mUi->wPPCheckBox->setCheckState(options[patchField].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + mUi->wPcheckBox->setCheckState(options[patchWP].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + mUi->resetPCheckBox->setCheckState(options[resetRP].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); mUi->showConsoleCheckBox->setCheckState(options[consoleOption].toBool() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - mUi->xmlFieldsDir->setText(options[xmlFieldsDir].toString()); + mUi->xmlFieldsDir->setText(options[xmlFieldsDir].toString()); } void MainWindow::loadSettings() { - QSettings settings(mLocalSettings, QSettings::IniFormat); - auto groups = settings.childGroups(); - for (auto &&g : groups) { + QSettings settings(mLocalSettings, QSettings::IniFormat); + auto groups = settings.childGroups(); + for (auto &&g : groups) { QHash options; - settings.beginGroup(g); + settings.beginGroup(g); - auto defaultOptionsKeys = defaultOptions.keys(); - for (auto &&key : defaultOptionsKeys) { - options[key] = settings.value(key, defaultOptions[key]); - } - settings.endGroup(); + auto defaultOptionsKeys = defaultOptions.keys(); + for (auto &&key : defaultOptionsKeys) { + options[key] = settings.value(key, defaultOptions[key]); + } + settings.endGroup(); - mDirOptions[g] = options; - } + mDirOptions[g] = options; + } } void MainWindow::saveSettings() { - QSettings settings(mLocalSettings, QSettings::IniFormat); - auto mDirOptionsKeys = mDirOptions.keys(); + QSettings settings(mLocalSettings, QSettings::IniFormat); + auto mDirOptionsKeys = mDirOptions.keys(); for (auto &&dir : mDirOptionsKeys) { - settings.beginGroup(dir); - auto options = mDirOptions[dir].keys(); + settings.beginGroup(dir); + auto options = mDirOptions[dir].keys(); for (auto &&option : options) { - settings.setValue(option, mDirOptions[dir][option]); - } - settings.endGroup(); - } + settings.setValue(option, mDirOptions[dir][option]); + } + settings.endGroup(); + } } void MainWindow::showNoQrsTsjMessage() { - QMessageBox msgBox; - msgBox.setText(tr("There is no .qrs or .tsj files in solutions directory.")); - msgBox.exec(); + QMessageBox msgBox; + msgBox.setText(tr("There is no .qrs or .tsj files in solutions directory.")); + msgBox.exec(); } void MainWindow::showNoFieldsMessage() { - QMessageBox msgBox; - msgBox.setText(tr("There is no .xml files in fields directory.")); - msgBox.exec(); + QMessageBox msgBox; + msgBox.setText(tr("There is no .xml files in fields directory.")); + msgBox.exec(); } diff --git a/mainwindow.h b/mainwindow.h index e722262..65a29da 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -25,26 +25,26 @@ QT_END_NAMESPACE class MainWindow : public QMainWindow { - Q_OBJECT + Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow() override; private slots: - void on_chooseField_clicked(); + void on_chooseField_clicked(); - void on_openTasks_clicked(); + void on_openTasks_clicked(); - void on_runCheckButton_clicked(); + void on_runCheckButton_clicked(); - void on_wPcheckBox_stateChanged(int state); + void on_wPcheckBox_stateChanged(int state); - void on_wPPCheckBox_stateChanged(int state); + void on_wPPCheckBox_stateChanged(int state); - void on_resetPCheckBox_stateChanged(int state); + void on_resetPCheckBox_stateChanged(int state); - void on_showConsoleCheckBox_stateChanged(int state); + void on_showConsoleCheckBox_stateChanged(int state); void on_closeOnSuccessOption_stateChanged(int state); @@ -53,20 +53,20 @@ class MainWindow : public QMainWindow void resetUiOptions(const QHash &options); - void loadSettings(); + void loadSettings(); - void saveSettings(); + void saveSettings(); static void showNoQrsTsjMessage(); static void showNoFieldsMessage(); - Ui::MainWindow *mUi; - QDir mTasksDir; - QDir mFieldsDir; - QString mTasksPath; - QDir mStudioDir; - QString mLocalSettings; + Ui::MainWindow *mUi; + QDir mTasksDir; + QDir mFieldsDir; + QString mTasksPath; + QDir mStudioDir; + QString mLocalSettings; QHash> mDirOptions; }; From 10cef29460cb25c6e6fbd2cca26cbfbcd2b7ea6e Mon Sep 17 00:00:00 2001 From: MinyazevR Date: Wed, 3 Jul 2024 02:57:17 +0300 Subject: [PATCH 5/6] Add correct clang-tidy conf --- .github/workflows/clang-tools.yml | 22 ------------------- .github/workflows/main.yml | 36 +++++++++++++++++++++++++++++-- checkapp.pri | 5 ++++- 3 files changed, 38 insertions(+), 25 deletions(-) delete mode 100644 .github/workflows/clang-tools.yml diff --git a/.github/workflows/clang-tools.yml b/.github/workflows/clang-tools.yml deleted file mode 100644 index c5f321d..0000000 --- a/.github/workflows/clang-tools.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Clang-tidy and clang-format - -on: [push, pull_request, workflow_dispatch] - -jobs: - format: - runs-on: ubuntu-latest - # permissions: - # contents: read - # pull-requests: read - steps: - - uses: actions/checkout@v4 - - uses: cpp-linter/cpp-linter-action@v2.12.0 - id: linter - with: - style: 'file' - tidy-checks: '' - version: 15 - # lines-changed-only: true - - name: Exit - if: steps.linter.outputs.checks-failed > 0 - run: exit 1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bc5d6e7..99595a0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -82,14 +82,46 @@ jobs: else true fi + + - name: Install dependencies + if: ${{ matrix.os-name == 'linux' }} + run: sudo apt-get update && sudo apt-get install bear=3.0.18-1 + + - name: Create build dir + run: mkdir -p build - name: QMake - run: qmake trikCheckApp.pro CONFIG+=release + run: qmake ../trikCheckApp.pro CONFIG+=release + working-directory: ./build - name: QMake all timeout-minutes: 1 run: make -j $(nproc) qmake_all + working-directory: ./build + - name: Make all with bear + timeout-minutes: 10 + if: ${{ matrix.os-name == 'linux' }} + run: bear -- make -j $(nproc) all + working-directory: ./build + - name: Make all timeout-minutes: 10 - run: make -j $(nproc) all + if: ${{ matrix.os-name != 'linux' }} + run: make -j $(nproc) all + working-directory: ./build + + - name: Lint + if: ${{ matrix.os-name == 'linux'}} + uses: cpp-linter/cpp-linter-action@v2.12.0 + id: linter + with: + style: 'file' + tidy-checks: '' + version: 15 + database: './build' + verbosity: 'info' + + - name: Exit + if: ${{ matrix.os-name == 'linux' && steps.linter.outputs.checks-failed > 0 }} + run: exit 1 diff --git a/checkapp.pri b/checkapp.pri index e4fd6cc..51d1c40 100644 --- a/checkapp.pri +++ b/checkapp.pri @@ -16,7 +16,10 @@ QT += core gui concurrent greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -CONFIG += c++11 lrelease embed_translations +greaterThan(QT_MAJOR_VERSION, 5): CONFIG += c++17 +else: CONFIG += c++11 + +CONFIG += lrelease embed_translations QM_FILES_RESOURCE_PREFIX = /translations From b00533a454d1687bdafa1faeeb09e9a63431e72e Mon Sep 17 00:00:00 2001 From: iakov Date: Wed, 3 Jul 2024 16:49:07 +0300 Subject: [PATCH 6/6] Remove obsolete Qt4 handling --- checkapp.pri | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/checkapp.pri b/checkapp.pri index 51d1c40..d6fefab 100644 --- a/checkapp.pri +++ b/checkapp.pri @@ -12,14 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -QT += core gui concurrent - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -greaterThan(QT_MAJOR_VERSION, 5): CONFIG += c++17 -else: CONFIG += c++11 - -CONFIG += lrelease embed_translations +QT += core gui widgets concurrent QM_FILES_RESOURCE_PREFIX = /translations @@ -44,9 +37,7 @@ FORMS += \ TRANSLATIONS += \ $$PWD/translations/checkapp_ru.ts -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin +unix:target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target win32 {
" + "Имя
ТестСтатус
" + "Время исполнения
%2%3%4%5
%2%3%4%5