mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:21:24 +02:00
Merge branch 'exportToTestRail' of https://github.com/NissimHadar/hifi into exportToTestRail
This commit is contained in:
commit
85d74afac4
8 changed files with 287 additions and 11 deletions
|
@ -5,7 +5,7 @@ project(${TARGET_NAME})
|
||||||
SET (CMAKE_AUTOUIC ON)
|
SET (CMAKE_AUTOUIC ON)
|
||||||
SET (CMAKE_AUTOMOC ON)
|
SET (CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
setup_hifi_project (Core Widgets Network)
|
setup_hifi_project (Core Widgets Network Xml)
|
||||||
link_hifi_libraries ()
|
link_hifi_libraries ()
|
||||||
|
|
||||||
# FIX: Qt was built with -reduce-relocations
|
# FIX: Qt was built with -reduce-relocations
|
||||||
|
@ -18,7 +18,7 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
include_directories (${Qt5Core_INCLUDE_DIRS})
|
include_directories (${Qt5Core_INCLUDE_DIRS})
|
||||||
include_directories (${Qt5Widgets_INCLUDE_DIRS})
|
include_directories (${Qt5Widgets_INCLUDE_DIRS})
|
||||||
|
|
||||||
set (QT_LIBRARIES Qt5::Core Qt5::Widgets)
|
set (QT_LIBRARIES Qt5::Core Qt5::Widgets QT::Gui Qt5::Xml)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
# Do not show Console
|
# Do not show Console
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <quazip5/quazip.h>
|
#include <quazip5/quazip.h>
|
||||||
#include <quazip5/JlCompress.h>
|
#include <quazip5/JlCompress.h>
|
||||||
|
|
||||||
|
#include "TestSuiteCreator.h"
|
||||||
#include "ui/AutoTester.h"
|
#include "ui/AutoTester.h"
|
||||||
extern AutoTester* autoTester;
|
extern AutoTester* autoTester;
|
||||||
|
|
||||||
|
@ -821,6 +822,26 @@ void Test::createTestsOutline() {
|
||||||
QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created");
|
QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Test::createTestRailTestSuite() {
|
||||||
|
QString previousSelection = testDirectory;
|
||||||
|
QString parent = previousSelection.left(previousSelection.lastIndexOf('/'));
|
||||||
|
if (!parent.isNull() && parent.right(1) != "/") {
|
||||||
|
parent += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
testDirectory =
|
||||||
|
QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
// If user cancelled then restore previous selection and return
|
||||||
|
if (testDirectory == "") {
|
||||||
|
testDirectory = previousSelection;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestSuiteCreator testSuiteCreator;
|
||||||
|
testSuiteCreator.createTestSuite(testDirectory, autoTester->getSelectedUser(), autoTester->getSelectedBranch());
|
||||||
|
}
|
||||||
|
|
||||||
QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) {
|
QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) {
|
||||||
imageDirectory = QDir(pathToImageDirectory);
|
imageDirectory = QDir(pathToImageDirectory);
|
||||||
QStringList nameFilters;
|
QStringList nameFilters;
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
void createMDFile(const QString& topLevelDirectory);
|
void createMDFile(const QString& topLevelDirectory);
|
||||||
|
|
||||||
void createTestsOutline();
|
void createTestsOutline();
|
||||||
|
void createTestRailTestSuite();
|
||||||
|
|
||||||
bool compareImageLists(bool isInteractiveMode, QProgressBar* progressBar);
|
bool compareImageLists(bool isInteractiveMode, QProgressBar* progressBar);
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ public:
|
||||||
bool createTestResultsFolderPath(const QString& directory);
|
bool createTestResultsFolderPath(const QString& directory);
|
||||||
void zipAndDeleteTestResultsFolder();
|
void zipAndDeleteTestResultsFolder();
|
||||||
|
|
||||||
bool isAValidDirectory(const QString& pathname);
|
static bool isAValidDirectory(const QString& pathname);
|
||||||
QString extractPathFromTestsDown(const QString& fullPath);
|
QString extractPathFromTestsDown(const QString& fullPath);
|
||||||
QString getExpectedImageDestinationDirectory(const QString& filename);
|
QString getExpectedImageDestinationDirectory(const QString& filename);
|
||||||
QString getExpectedImagePartialSourceDirectory(const QString& filename);
|
QString getExpectedImagePartialSourceDirectory(const QString& filename);
|
||||||
|
|
208
tools/auto-tester/src/TestSuiteCreator.cpp
Normal file
208
tools/auto-tester/src/TestSuiteCreator.cpp
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
//
|
||||||
|
// TestSuiteCreator.cpp
|
||||||
|
//
|
||||||
|
// Created by Nissim Hadar on 6 Jul 2018.
|
||||||
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TestSuiteCreator.h"
|
||||||
|
#include "Test.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
void TestSuiteCreator::createTestSuite(const QString& testDirectory, const QString& user, const QString& branch) {
|
||||||
|
QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
|
||||||
|
document.appendChild(instruction);
|
||||||
|
|
||||||
|
// We create a single section, within sections
|
||||||
|
QDomElement root = document.createElement("sections");
|
||||||
|
document.appendChild(root);
|
||||||
|
|
||||||
|
QDomElement topLevelSection = document.createElement("section");
|
||||||
|
|
||||||
|
QDomElement suiteName = document.createElement("name");
|
||||||
|
suiteName.appendChild(document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString()));
|
||||||
|
topLevelSection.appendChild(suiteName);
|
||||||
|
|
||||||
|
QDomElement secondLevelSections = document.createElement("sections");
|
||||||
|
topLevelSection.appendChild(processDirectory(testDirectory, user, branch, secondLevelSections));
|
||||||
|
|
||||||
|
topLevelSection.appendChild(secondLevelSections);
|
||||||
|
root.appendChild(topLevelSection);
|
||||||
|
|
||||||
|
// Write to file
|
||||||
|
const QString testRailsFilename{ "D:/t/TestRailSuite.xml" };
|
||||||
|
QFile file(testRailsFilename);
|
||||||
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
|
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create XML file");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream << document.toString();
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
QMessageBox::information(0, "Success", "TestRail XML file has been created");
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement TestSuiteCreator::processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element) {
|
||||||
|
QDomElement result = element;
|
||||||
|
|
||||||
|
// Loop over all entries in directory
|
||||||
|
QDirIterator it(directory.toStdString().c_str());
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QString nextDirectory = it.next();
|
||||||
|
|
||||||
|
// The object name appears after the last slash (we are assured there is at least 1).
|
||||||
|
QString objectName = nextDirectory.right(nextDirectory.length() - nextDirectory.lastIndexOf("/") - 1);
|
||||||
|
|
||||||
|
// Only process directories
|
||||||
|
if (Test::isAValidDirectory(nextDirectory)) {
|
||||||
|
// Ignore the utils and preformance directories
|
||||||
|
if (nextDirectory.right(QString("utils").length()) == "utils" || nextDirectory.right(QString("performance").length()) == "performance") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a section and process it
|
||||||
|
|
||||||
|
QDomElement sectionElement = document.createElement("section");
|
||||||
|
|
||||||
|
QDomElement sectionElementName = document.createElement("name");
|
||||||
|
sectionElementName.appendChild(document.createTextNode(objectName));
|
||||||
|
sectionElement.appendChild(sectionElementName);
|
||||||
|
|
||||||
|
QDomElement testsElement = document.createElement("sections");
|
||||||
|
sectionElement.appendChild(processDirectory(nextDirectory, user, branch, testsElement));
|
||||||
|
|
||||||
|
result.appendChild(sectionElement);
|
||||||
|
} else if (objectName == "test.js" || objectName == "testStory.js") {
|
||||||
|
QDomElement sectionElement = document.createElement("section");
|
||||||
|
QDomElement sectionElementName = document.createElement("name");
|
||||||
|
sectionElementName.appendChild(document.createTextNode("all"));
|
||||||
|
sectionElement.appendChild(sectionElementName);
|
||||||
|
sectionElement.appendChild(processTest(nextDirectory, objectName, user, branch, document.createElement("cases")));
|
||||||
|
result.appendChild(sectionElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) {
|
||||||
|
QDomElement result = element;
|
||||||
|
|
||||||
|
QDomElement caseElement = document.createElement("case");
|
||||||
|
|
||||||
|
caseElement.appendChild(document.createElement("id"));
|
||||||
|
|
||||||
|
// The name of the test is derived from the full path.
|
||||||
|
// The first term is the first word after "tests"
|
||||||
|
// The last word is the penultimate word
|
||||||
|
QStringList words = fullDirectory.split('/');
|
||||||
|
int i = 0;
|
||||||
|
while (words[i] != "tests") {
|
||||||
|
++i;
|
||||||
|
if (i >= words.length() - 1) {
|
||||||
|
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder \"tests\" not found in " + fullDirectory);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
QString title{ words[i] };
|
||||||
|
for (++i; i < words.length() - 1; ++i) {
|
||||||
|
title += " / " + words[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement titleElement = document.createElement("title");
|
||||||
|
titleElement.appendChild(document.createTextNode(title));
|
||||||
|
caseElement.appendChild(titleElement);
|
||||||
|
|
||||||
|
QDomElement templateElement = document.createElement("template");
|
||||||
|
templateElement.appendChild(document.createTextNode("Test Case (Steps)"));
|
||||||
|
caseElement.appendChild(templateElement);
|
||||||
|
|
||||||
|
QDomElement typeElement = document.createElement("type");
|
||||||
|
typeElement.appendChild(document.createTextNode("3 - Regression"));
|
||||||
|
caseElement.appendChild(typeElement);
|
||||||
|
|
||||||
|
QDomElement priorityElement = document.createElement("priority");
|
||||||
|
priorityElement.appendChild(document.createTextNode("Medium"));
|
||||||
|
caseElement.appendChild(priorityElement);
|
||||||
|
|
||||||
|
QDomElement estimateElementName = document.createElement("estimate");
|
||||||
|
estimateElementName.appendChild(document.createTextNode("60"));
|
||||||
|
caseElement.appendChild(estimateElementName);
|
||||||
|
|
||||||
|
caseElement.appendChild(document.createElement("references"));
|
||||||
|
|
||||||
|
QDomElement customElement = document.createElement("custom");
|
||||||
|
|
||||||
|
QDomElement tester_countElement = document.createElement("tester_count");
|
||||||
|
tester_countElement.appendChild(document.createTextNode("1"));
|
||||||
|
customElement.appendChild(tester_countElement);
|
||||||
|
|
||||||
|
QDomElement domain_bot_loadElement = document.createElement("domain_bot_load");
|
||||||
|
QDomElement domain_bot_loadElementId = document.createElement("id");
|
||||||
|
domain_bot_loadElementId.appendChild(document.createTextNode("1"));
|
||||||
|
domain_bot_loadElement.appendChild(domain_bot_loadElementId);
|
||||||
|
QDomElement domain_bot_loadElementValue = document.createElement("value");
|
||||||
|
domain_bot_loadElementValue.appendChild(document.createTextNode(" Without Bots (hifiqa-rc / hifi-qa-stable / hifiqa-master)"));
|
||||||
|
domain_bot_loadElement.appendChild(domain_bot_loadElementValue);
|
||||||
|
customElement.appendChild(domain_bot_loadElement);
|
||||||
|
|
||||||
|
QDomElement automation_typeElement = document.createElement("automation_type");
|
||||||
|
QDomElement automation_typeElementId = document.createElement("id");
|
||||||
|
automation_typeElementId.appendChild(document.createTextNode("0"));
|
||||||
|
automation_typeElement.appendChild(automation_typeElementId);
|
||||||
|
QDomElement automation_typeElementValue = document.createElement("value");
|
||||||
|
automation_typeElementValue.appendChild(document.createTextNode("None"));
|
||||||
|
automation_typeElement.appendChild(automation_typeElementValue);
|
||||||
|
customElement.appendChild(automation_typeElement);
|
||||||
|
|
||||||
|
QDomElement added_to_releaseElement = document.createElement("added_to_release");
|
||||||
|
QDomElement added_to_releaseElementId = document.createElement("id");
|
||||||
|
added_to_releaseElementId.appendChild(document.createTextNode("4"));
|
||||||
|
added_to_releaseElement.appendChild(added_to_releaseElementId);
|
||||||
|
QDomElement added_to_releaseElementValue = document.createElement("value");
|
||||||
|
added_to_releaseElementValue.appendChild(document.createTextNode(branch));
|
||||||
|
added_to_releaseElement.appendChild(added_to_releaseElementValue);
|
||||||
|
customElement.appendChild(added_to_releaseElement);
|
||||||
|
|
||||||
|
QDomElement precondsElement = document.createElement("preconds");
|
||||||
|
precondsElement.appendChild(document.createTextNode("Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script"));
|
||||||
|
customElement.appendChild(precondsElement);
|
||||||
|
|
||||||
|
QString testMDName = QString("https://github.com/") + user + "/hifi_tests/blob/" + branch + "/tests/content/entity/light/point/create/test.md";
|
||||||
|
|
||||||
|
QDomElement steps_seperatedElement = document.createElement("steps_separated");
|
||||||
|
QDomElement stepElement = document.createElement("step");
|
||||||
|
QDomElement stepIndexElement = document.createElement("index");
|
||||||
|
stepIndexElement.appendChild(document.createTextNode("1"));
|
||||||
|
stepElement.appendChild(stepIndexElement);
|
||||||
|
QDomElement stepContentElement = document.createElement("content");
|
||||||
|
stepContentElement.appendChild(document.createTextNode(QString("Execute instructions in [THIS TEST](") + testMDName + ")"));
|
||||||
|
stepElement.appendChild(stepContentElement);
|
||||||
|
QDomElement stepExpectedElement = document.createElement("expected");
|
||||||
|
stepExpectedElement.appendChild(document.createTextNode("Refer to the expected result in the linked description."));
|
||||||
|
stepElement.appendChild(stepExpectedElement);
|
||||||
|
steps_seperatedElement.appendChild(stepElement);
|
||||||
|
customElement.appendChild(steps_seperatedElement);
|
||||||
|
|
||||||
|
QDomElement notesElement = document.createElement("notes");
|
||||||
|
notesElement.appendChild(document.createTextNode(testMDName));
|
||||||
|
customElement.appendChild(notesElement);
|
||||||
|
|
||||||
|
caseElement.appendChild(customElement);
|
||||||
|
|
||||||
|
result.appendChild(caseElement);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
29
tools/auto-tester/src/TestSuiteCreator.h
Normal file
29
tools/auto-tester/src/TestSuiteCreator.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// TestSuiteCreator.h
|
||||||
|
//
|
||||||
|
// Created by Nissim Hadar on 6 Jul 2018.
|
||||||
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_test_suite_creator_h
|
||||||
|
#define hifi_test_suite_creator_h
|
||||||
|
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QtXml/QDomDocument>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class TestSuiteCreator {
|
||||||
|
public:
|
||||||
|
void createTestSuite(const QString& testDirectory, const QString& user, const QString& branch);
|
||||||
|
|
||||||
|
QDomElement processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element);
|
||||||
|
QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDomDocument document;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_test_suite_creator_h
|
|
@ -68,6 +68,10 @@ void AutoTester::on_createTestsOutlineButton_clicked() {
|
||||||
test->createTestsOutline();
|
test->createTestsOutline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoTester::on_createTestRailTestSuiteButton_clicked() {
|
||||||
|
test->createTestRailTestSuite();
|
||||||
|
}
|
||||||
|
|
||||||
// To toggle between show and hide
|
// To toggle between show and hide
|
||||||
// if (uState & ABS_AUTOHIDE) on_showTaskbarButton_clicked();
|
// if (uState & ABS_AUTOHIDE) on_showTaskbarButton_clicked();
|
||||||
// else on_hideTaskbarButton_clicked();
|
// else on_hideTaskbarButton_clicked();
|
||||||
|
|
|
@ -45,7 +45,7 @@ private slots:
|
||||||
void on_createMDFileButton_clicked();
|
void on_createMDFileButton_clicked();
|
||||||
void on_createAllMDFilesButton_clicked();
|
void on_createAllMDFilesButton_clicked();
|
||||||
void on_createTestsOutlineButton_clicked();
|
void on_createTestsOutlineButton_clicked();
|
||||||
|
void on_createTestRailTestSuiteButton_clicked();
|
||||||
void on_hideTaskbarButton_clicked();
|
void on_hideTaskbarButton_clicked();
|
||||||
void on_showTaskbarButton_clicked();
|
void on_showTaskbarButton_clicked();
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>612</width>
|
<width>612</width>
|
||||||
<height>537</height>
|
<height>553</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>380</x>
|
<x>380</x>
|
||||||
<y>430</y>
|
<y>450</y>
|
||||||
<width>101</width>
|
<width>101</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>430</x>
|
<x>430</x>
|
||||||
<y>270</y>
|
<y>320</y>
|
||||||
<width>101</width>
|
<width>101</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>330</x>
|
<x>330</x>
|
||||||
<y>110</y>
|
<y>170</y>
|
||||||
<width>220</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>320</x>
|
<x>320</x>
|
||||||
<y>280</y>
|
<y>330</y>
|
||||||
<width>131</width>
|
<width>131</width>
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>320</x>
|
<x>320</x>
|
||||||
<y>330</y>
|
<y>380</y>
|
||||||
<width>255</width>
|
<width>255</width>
|
||||||
<height>23</height>
|
<height>23</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>330</x>
|
<x>330</x>
|
||||||
<y>170</y>
|
<y>230</y>
|
||||||
<width>220</width>
|
<width>220</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -229,6 +229,19 @@
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QPushButton" name="createTestRailTestSuiteButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>330</x>
|
||||||
|
<y>90</y>
|
||||||
|
<width>220</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Create TestRail Test Suite</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenuBar" name="menuBar">
|
<widget class="QMenuBar" name="menuBar">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
|
|
Loading…
Reference in a new issue