├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── FileManager.cpp ├── FileManager.h ├── LICENSE ├── MainWindow.cpp ├── MainWindow.h ├── ModelTreeItem.cpp ├── ModelTreeItem.h ├── ModelTreeModel.cpp ├── ModelTreeModel.h ├── PropertyPane.cpp ├── PropertyPane.h ├── README.md ├── WorldView.cpp ├── WorldView.h ├── main.cpp ├── qdarkstyle ├── .gitignore ├── COPYING ├── README.md ├── __init__.py ├── compile_qrc.py ├── pyqt5_style_rc.py ├── pyqt_style_rc.py ├── pyside_style_rc.py ├── rc │ ├── Hmovetoolbar.png │ ├── Hsepartoolbar.png │ ├── Vmovetoolbar.png │ ├── Vsepartoolbar.png │ ├── branch_closed-on.png │ ├── branch_closed.png │ ├── branch_open-on.png │ ├── branch_open.png │ ├── checkbox_checked.png │ ├── checkbox_checked_disabled.png │ ├── checkbox_checked_focus.png │ ├── checkbox_indeterminate.png │ ├── checkbox_indeterminate_disabled.png │ ├── checkbox_indeterminate_focus.png │ ├── checkbox_unchecked.png │ ├── checkbox_unchecked_disabled.png │ ├── checkbox_unchecked_focus.png │ ├── close-hover.png │ ├── close-pressed.png │ ├── close.png │ ├── down_arrow.png │ ├── down_arrow_disabled.png │ ├── left_arrow.png │ ├── left_arrow_disabled.png │ ├── radio_checked.png │ ├── radio_checked_disabled.png │ ├── radio_checked_focus.png │ ├── radio_unchecked.png │ ├── radio_unchecked_disabled.png │ ├── radio_unchecked_focus.png │ ├── right_arrow.png │ ├── right_arrow_disabled.png │ ├── sizegrip.png │ ├── stylesheet-branch-end.png │ ├── stylesheet-branch-more.png │ ├── stylesheet-vline.png │ ├── transparent.png │ ├── undock.png │ ├── up_arrow.png │ └── up_arrow_disabled.png ├── style.qrc └── style.qss └── sdf ├── Color.cpp ├── Color.h ├── IncludedElement.cpp ├── IncludedElement.h ├── Parser.cpp ├── Parser.h ├── Pose.cpp ├── Pose.h ├── SDFElement.cpp ├── SDFElement.h ├── Scene.cpp ├── Scene.h ├── World.cpp └── World.h /.gitattributes: -------------------------------------------------------------------------------- 1 | qdarkstyle/* linguist-vendored 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | #JetBrains CLion 32 | .idea/ 33 | cmake-build-*/ 34 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(gwd) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused") 7 | 8 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 9 | set(CMAKE_AUTOMOC ON) 10 | set(CMAKE_AUTORCC ON) 11 | 12 | find_package(roslib REQUIRED) 13 | 14 | find_package(Qt5 REQUIRED COMPONENTS Widgets Xml) 15 | 16 | # Not actually using this right now, but should I be? Needs more research 17 | # find_package(SDFormat REQUIRED) 18 | 19 | set(SOURCE_FILES main.cpp MainWindow.cpp WorldView.cpp ModelTreeItem.cpp ModelTreeModel.cpp qdarkstyle/style.qrc 20 | sdf/World.cpp sdf/IncludedElement.cpp sdf/Scene.cpp sdf/World.cpp sdf/SDFElement.cpp sdf/Color.cpp 21 | sdf/IncludedElement.cpp sdf/Pose.cpp sdf/Scene.cpp sdf/Parser.cpp PropertyPane.cpp FileManager.cpp) 22 | 23 | add_executable(gwd ${SOURCE_FILES}) 24 | target_include_directories(gwd PRIVATE ${SDFormat_INCLUDE_DIRS} ${roslib_INCLUDE_DIRS}) 25 | target_link_directories(gwd PRIVATE ${roslib_LIBRARY_DIRS}) 26 | target_link_libraries(gwd PRIVATE Qt5::Widgets Qt5::Xml ${SDFormat_LIBRARIES} ${roslib_LIBRARIES}) 27 | -------------------------------------------------------------------------------- /FileManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "FileManager.h" 7 | 8 | FileManager::FileManager(QObject *parent) : QObject(parent) { 9 | 10 | } 11 | 12 | World &FileManager::getWorld() { 13 | return world; 14 | } 15 | 16 | const QString &FileManager::getCurrentPath() const { 17 | return currentFilePath; 18 | } 19 | 20 | void FileManager::newFile() { 21 | world = World{}; 22 | currentFilePath.clear(); 23 | emit onNewWorld(world); 24 | emit onCurrentPathChanged(currentFilePath); 25 | } 26 | 27 | void FileManager::openFile() { 28 | auto parentWidget = dynamic_cast(parent()); 29 | auto filename = QFileDialog::getOpenFileName(parentWidget, "Open World", 30 | QStandardPaths::writableLocation(QStandardPaths::HomeLocation), "SDF Files (*.sdf *.world *.xml"); 31 | 32 | if(filename.isEmpty()) { 33 | return; 34 | } 35 | 36 | QFile file{filename}; 37 | if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { 38 | QMessageBox::critical(parentWidget, "Gazebo World Designer", "Could not open world file\n" + filename, QMessageBox::Ok); 39 | return; 40 | } 41 | 42 | QDomDocument document; 43 | document.setContent(file.readAll()); 44 | file.close(); 45 | 46 | world = Parser::ParseWorld(document); 47 | 48 | currentFilePath = filename; 49 | 50 | emit onNewWorld(world); 51 | emit onCurrentPathChanged(currentFilePath); 52 | } 53 | 54 | void FileManager::saveFile() { 55 | if(currentFilePath.isEmpty()) { 56 | saveFileAs(); 57 | } else { 58 | writeWorldToFile(currentFilePath); 59 | } 60 | } 61 | 62 | void FileManager::saveFileAs() { 63 | auto parentWidget = dynamic_cast(parent()); 64 | auto newFileName = QFileDialog::getSaveFileName(parentWidget, "Save World", QStandardPaths::writableLocation(QStandardPaths::HomeLocation), "SDF Files (*.sdf *.world *.xml"); 65 | if(newFileName.isEmpty()) { 66 | return; 67 | } 68 | currentFilePath = newFileName; 69 | writeWorldToFile(currentFilePath); 70 | emit onCurrentPathChanged(currentFilePath); 71 | } 72 | 73 | void FileManager::writeWorldToFile(const QString &filepath) { 74 | auto parentWidget = dynamic_cast(parent()); 75 | 76 | QDomDocument xmlDocument; 77 | auto xml = world.toXML(xmlDocument); 78 | 79 | QDomElement sdfElement = xmlDocument.createElement("sdf"); 80 | sdfElement.setAttribute("version", "1.4"); 81 | sdfElement.appendChild(xml); 82 | xmlDocument.appendChild(sdfElement); 83 | 84 | QFile file{filepath}; 85 | if(!file.open(QIODevice::ReadWrite | QIODevice::Text)) { 86 | QMessageBox::critical(parentWidget, "Gazebo World Designer", 87 | ("Unable to open file for saving: " + currentFilePath), QMessageBox::Ok); 88 | return; 89 | } 90 | QTextStream textStream{&file}; 91 | xmlDocument.save(textStream,1); 92 | textStream.flush(); 93 | file.close(); 94 | } 95 | -------------------------------------------------------------------------------- /FileManager.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_FILEMANAGER_H 2 | #define GWD_FILEMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class FileManager : public QObject { 9 | Q_OBJECT 10 | public: 11 | explicit FileManager(QObject *parent = nullptr); 12 | 13 | World& getWorld(); 14 | const QString &getCurrentPath() const; 15 | 16 | signals: 17 | void onNewWorld(World &world); 18 | void onCurrentPathChanged(const QString &path); 19 | 20 | public slots: 21 | void newFile(); 22 | void openFile(); 23 | void saveFile(); 24 | void saveFileAs(); 25 | 26 | 27 | private: 28 | QString currentFilePath; 29 | World world; 30 | 31 | void writeWorldToFile(const QString &filepath); 32 | 33 | }; 34 | 35 | 36 | #endif //GWD_FILEMANAGER_H 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Matthew Barulic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MainWindow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "ModelTreeModel.h" 7 | #include "PropertyPane.h" 8 | #include "MainWindow.h" 9 | 10 | MainWindow::MainWindow() { 11 | setWindowTitle("Gazebo World Designer"); 12 | 13 | auto fileManager = new FileManager(this); 14 | 15 | auto worldView = new WorldView; 16 | 17 | createMenus(fileManager); 18 | 19 | auto splitter = new QSplitter{this}; 20 | splitter->addWidget(createLeftPanel()); 21 | splitter->addWidget(worldView); 22 | splitter->addWidget(createRightPanel(fileManager, worldView)); 23 | 24 | setCentralWidget(splitter); 25 | 26 | connect(fileManager, &FileManager::onCurrentPathChanged, [this](const QString &path){ 27 | if(path.isEmpty()) { 28 | setWindowTitle("Gazebo World Designer"); 29 | } else { 30 | setWindowTitle("Gazebo World Designer - " + path); 31 | } 32 | }); 33 | 34 | connect(fileManager, &FileManager::onNewWorld, worldView, &WorldView::newWorld); 35 | 36 | fileManager->newFile(); 37 | } 38 | 39 | void MainWindow::createMenus(FileManager *fileManager) { 40 | auto closeAct = new QAction{"&Close", this}; 41 | closeAct->setShortcuts(QKeySequence::Close); 42 | connect(closeAct, &QAction::triggered, this, &QMainWindow::close); 43 | addAction(closeAct); 44 | 45 | auto newFileAct = new QAction{"&New", this}; 46 | newFileAct->setShortcuts(QKeySequence::New); 47 | connect(newFileAct, &QAction::triggered, fileManager, &FileManager::newFile); 48 | addAction(newFileAct); 49 | 50 | auto openFileAct = new QAction{"&Open", this}; 51 | openFileAct->setShortcuts(QKeySequence::Open); 52 | connect(openFileAct, &QAction::triggered, fileManager, &FileManager::openFile); 53 | addAction(openFileAct); 54 | 55 | auto saveFileAct = new QAction{"&Save", this}; 56 | saveFileAct->setShortcuts(QKeySequence::Save); 57 | connect(saveFileAct, &QAction::triggered, fileManager, &FileManager::saveFile); 58 | addAction(saveFileAct); 59 | 60 | auto saveFileAsAct = new QAction{"&Save As", this}; 61 | saveFileAsAct->setShortcuts(QKeySequence::SaveAs); 62 | connect(saveFileAsAct, &QAction::triggered, fileManager, &FileManager::saveFileAs); 63 | addAction(saveFileAsAct); 64 | 65 | auto fileMenu = menuBar()->addMenu("&File"); 66 | fileMenu->addAction(newFileAct); 67 | fileMenu->addAction(openFileAct); 68 | fileMenu->addAction(saveFileAct); 69 | fileMenu->addAction(saveFileAsAct); 70 | fileMenu->addSeparator(); 71 | fileMenu->addAction(closeAct); 72 | } 73 | 74 | QWidget *MainWindow::createLeftPanel() { 75 | auto leftSideLayout = new QVBoxLayout; 76 | leftSideLayout->addWidget(new QLabel{"Available Models"}); 77 | 78 | auto treeModel = new ModelTreeModel; 79 | auto modelTreeView = new QTreeView; 80 | modelTreeView->setModel(treeModel); 81 | modelTreeView->header()->hide(); 82 | modelTreeView->setDragEnabled(true); 83 | modelTreeView->viewport()->setAcceptDrops(false); 84 | modelTreeView->setDragDropMode(QAbstractItemView::DragOnly); 85 | leftSideLayout->addWidget(modelTreeView); 86 | 87 | auto leftLine = new QFrame(); 88 | leftLine->setFrameShape(QFrame::HLine); 89 | leftLine->setFrameShadow(QFrame::Plain); 90 | leftSideLayout->addWidget(leftLine); 91 | 92 | leftSideLayout->addWidget(new QLabel{"Current World"}); 93 | 94 | auto leftSideWidget = new QWidget; 95 | leftSideWidget->setLayout(leftSideLayout); 96 | 97 | return leftSideWidget; 98 | } 99 | 100 | QWidget *MainWindow::createRightPanel(FileManager *fileManager, 101 | WorldView *worldView) { 102 | auto propertyPanesLayout = new QVBoxLayout; 103 | propertyPanesLayout->addWidget(new QLabel{"Object Properties"}); 104 | auto objectPropertyPane = new PropertyPane; 105 | propertyPanesLayout->addWidget(objectPropertyPane); 106 | propertyPanesLayout->addStretch(); 107 | auto line = new QFrame(); 108 | line->setFrameShape(QFrame::HLine); 109 | line->setFrameShadow(QFrame::Plain); 110 | propertyPanesLayout->addWidget(line); 111 | propertyPanesLayout->addWidget(new QLabel{"Scene Properties"}); 112 | auto scenePropertyPane = new PropertyPane; 113 | propertyPanesLayout->addWidget(scenePropertyPane); 114 | 115 | connect(fileManager, &FileManager::onNewWorld, [scenePropertyPane](World &world){ 116 | scenePropertyPane->showProperties(&world.scene); 117 | }); 118 | 119 | connect(worldView, &WorldView::onSelectedIndexChanged, [objectPropertyPane,world=&fileManager->getWorld()](int index){ 120 | if(index >= 0) { 121 | objectPropertyPane->showProperties(world->elements[static_cast(index)].get()); 122 | } else { 123 | objectPropertyPane->clear(); 124 | } 125 | }); 126 | 127 | auto propertyPanesWidget = new QWidget; 128 | propertyPanesWidget->setLayout(propertyPanesLayout); 129 | 130 | return propertyPanesWidget; 131 | } 132 | -------------------------------------------------------------------------------- /MainWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_MAINWINDOW_H 2 | #define GWD_MAINWINDOW_H 3 | 4 | #include 5 | #include "FileManager.h" 6 | #include "WorldView.h" 7 | 8 | class MainWindow : public QMainWindow { 9 | Q_OBJECT 10 | 11 | public: 12 | MainWindow(); 13 | 14 | public slots: 15 | 16 | private: 17 | void createMenus(FileManager *fileManager); 18 | [[nodiscard]] QWidget* createLeftPanel(); 19 | [[nodiscard]] QWidget * 20 | createRightPanel(FileManager *fileManager, WorldView *worldView); 21 | 22 | }; 23 | 24 | 25 | #endif //GWD_MAINWINDOW_H 26 | -------------------------------------------------------------------------------- /ModelTreeItem.cpp: -------------------------------------------------------------------------------- 1 | #include "ModelTreeItem.h" 2 | 3 | ModelTreeItem::ModelTreeItem(const QString &name, const QString &gazeboName, ModelTreeItem *parentItem) { 4 | parent = parentItem; 5 | humanReadableName = name; 6 | gazeboModelName = gazeboName; 7 | } 8 | 9 | ModelTreeItem::~ModelTreeItem() { 10 | qDeleteAll(childItems); 11 | } 12 | 13 | void ModelTreeItem::appendChild(ModelTreeItem *item) { 14 | childItems.append(item); 15 | } 16 | 17 | ModelTreeItem *ModelTreeItem::child(int row) { 18 | return childItems.value(row); 19 | } 20 | 21 | int ModelTreeItem::childCount() const { 22 | return childItems.size(); 23 | } 24 | 25 | int ModelTreeItem::columnCount() const { 26 | return 1; 27 | } 28 | 29 | QString ModelTreeItem::name() const { 30 | return humanReadableName; 31 | } 32 | 33 | QString ModelTreeItem::gazeboName() const { 34 | return gazeboModelName; 35 | } 36 | 37 | int ModelTreeItem::row() const { 38 | if (parent != nullptr) 39 | return parent->childItems.indexOf(const_cast(this)); 40 | 41 | return 0; 42 | } 43 | 44 | ModelTreeItem *ModelTreeItem::parentItem() { 45 | return parent; 46 | } 47 | -------------------------------------------------------------------------------- /ModelTreeItem.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_MODELTREEITEM_H 2 | #define GWD_MODELTREEITEM_H 3 | 4 | #include 5 | #include 6 | 7 | class ModelTreeItem { 8 | public: 9 | explicit ModelTreeItem(const QString &name, const QString &gazeboName, ModelTreeItem *parentItem); 10 | ~ModelTreeItem(); 11 | 12 | void appendChild(ModelTreeItem *item); 13 | 14 | ModelTreeItem *child(int row); 15 | 16 | int childCount() const; 17 | 18 | int columnCount() const; 19 | 20 | QString name() const; 21 | 22 | QString gazeboName() const; 23 | 24 | int row() const; 25 | 26 | ModelTreeItem *parentItem(); 27 | 28 | private: 29 | QList childItems; 30 | QString humanReadableName; 31 | QString gazeboModelName; 32 | ModelTreeItem *parent; 33 | }; 34 | 35 | 36 | #endif //GWD_MODELTREEITEM_H 37 | -------------------------------------------------------------------------------- /ModelTreeModel.cpp: -------------------------------------------------------------------------------- 1 | #include "ModelTreeModel.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | ModelTreeModel::ModelTreeModel(QObject *parent) : QAbstractItemModel(parent) { 13 | rootItem = new ModelTreeItem{"Models","", nullptr}; 14 | 15 | searchForDownloadedModels(); 16 | searchForROSModels(); 17 | } 18 | 19 | ModelTreeModel::~ModelTreeModel() { 20 | delete rootItem; 21 | } 22 | 23 | QVariant ModelTreeModel::data(const QModelIndex &index, int role) const { 24 | if(!index.isValid()) 25 | return QVariant(); 26 | 27 | if(role != Qt::DisplayRole) 28 | return QVariant(); 29 | 30 | ModelTreeItem *item = static_cast(index.internalPointer()); 31 | 32 | return item->name(); 33 | } 34 | 35 | Qt::ItemFlags ModelTreeModel::flags(const QModelIndex &index) const { 36 | Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index); 37 | 38 | ModelTreeItem *item = static_cast(index.internalPointer()); 39 | 40 | if(index.isValid() && item->childCount() == 0) 41 | return Qt::ItemIsDragEnabled | defaultFlags; 42 | else 43 | return defaultFlags; 44 | } 45 | 46 | QModelIndex ModelTreeModel::index(int row, int column, const QModelIndex &parent) const { 47 | 48 | if(!hasIndex(row, column, parent)) 49 | return QModelIndex(); 50 | 51 | ModelTreeItem *parentItem; 52 | 53 | if(!parent.isValid()) 54 | parentItem = rootItem; 55 | else 56 | parentItem = static_cast(parent.internalPointer()); 57 | 58 | ModelTreeItem *childItem = parentItem->child(row); 59 | 60 | if(childItem != nullptr) 61 | return createIndex(row, column, childItem); 62 | else 63 | return QModelIndex(); 64 | } 65 | 66 | QModelIndex ModelTreeModel::parent(const QModelIndex &index) const { 67 | if(!index.isValid()) 68 | return QModelIndex(); 69 | 70 | ModelTreeItem *childItem = static_cast(index.internalPointer()); 71 | ModelTreeItem *parentItem = childItem->parentItem(); 72 | 73 | if(parentItem == rootItem) 74 | return QModelIndex(); 75 | 76 | return createIndex(parentItem->row(), 0, parentItem); 77 | } 78 | 79 | int ModelTreeModel::rowCount(const QModelIndex &parent) const { 80 | ModelTreeItem *parentItem; 81 | if(parent.column() > 0) 82 | return 0; 83 | 84 | if(!parent.isValid()) 85 | parentItem = rootItem; 86 | else 87 | parentItem = static_cast(parent.internalPointer()); 88 | 89 | return parentItem->childCount(); 90 | } 91 | 92 | int ModelTreeModel::columnCount(const QModelIndex &parent) const { 93 | if (parent.isValid()) 94 | return static_cast(parent.internalPointer())->columnCount(); 95 | else 96 | return rootItem->columnCount(); 97 | } 98 | 99 | Qt::DropActions ModelTreeModel::supportedDropActions() const { 100 | return Qt::CopyAction; 101 | } 102 | 103 | QStringList ModelTreeModel::mimeTypes() const { 104 | return QStringList{"text/plain"}; 105 | } 106 | 107 | QMimeData *ModelTreeModel::mimeData(const QModelIndexList &indexes) const { 108 | QMimeData *mimeData = new QMimeData; 109 | QString encodedData; 110 | for(const QModelIndex &index : indexes) { 111 | if(index.isValid()) { 112 | ModelTreeItem *item = static_cast(index.internalPointer()); 113 | QString gazeboName = item->gazeboName(); 114 | QString humanName = item->name(); 115 | encodedData += gazeboName; 116 | } 117 | } 118 | mimeData->setText(encodedData); 119 | return mimeData; 120 | } 121 | 122 | void ModelTreeModel::searchForROSModels() { 123 | std::vector> model_paths; 124 | ros::package::getPlugins("gazebo_ros", "gazebo_model_path", model_paths, true); 125 | for(const auto& pair : model_paths) { 126 | auto packageItem = new ModelTreeItem{pair.first.c_str(), "", rootItem}; 127 | rootItem->appendChild(packageItem); 128 | 129 | auto models = findModelsInPath(pair.second.c_str()); 130 | for(const auto &model : models) { 131 | auto modelItem = new ModelTreeItem{model.first, model.second, packageItem}; 132 | packageItem->appendChild(modelItem); 133 | } 134 | } 135 | } 136 | 137 | void ModelTreeModel::searchForDownloadedModels() { 138 | QDir dir{QStandardPaths::writableLocation(QStandardPaths::HomeLocation)}; 139 | dir = QDir{dir.filePath(".gazebo")}; 140 | if(!dir.exists()) 141 | return; 142 | 143 | auto packageItem = new ModelTreeItem{"Downloaded Models", "", rootItem}; 144 | rootItem->appendChild(packageItem); 145 | 146 | auto models = findModelsInPath(dir.absolutePath()); 147 | for(const auto &model : models) { 148 | auto modelItem = new ModelTreeItem{model.first, model.second, packageItem}; 149 | packageItem->appendChild(modelItem); 150 | } 151 | } 152 | 153 | QVector> ModelTreeModel::findModelsInPath(QString directory) { 154 | QVector> models; 155 | 156 | QDirIterator iterator{directory, QStringList{} << "*.config", QDir::Files, QDirIterator::Subdirectories}; 157 | 158 | while(iterator.hasNext()) { 159 | auto filepath = iterator.next(); 160 | 161 | QFile configFile{filepath}; 162 | if(!configFile.open(QIODevice::ReadOnly | QIODevice::Text)) 163 | continue; 164 | 165 | QDomDocument modelConfig; 166 | modelConfig.setContent(configFile.readAll()); 167 | configFile.close(); 168 | 169 | if(modelConfig.documentElement().tagName() != tr("model")) 170 | continue; 171 | 172 | auto name = modelConfig.documentElement().firstChildElement("name").text(); 173 | 174 | QFileInfo configFileInfo{configFile}; 175 | QDir configPath = configFileInfo.absoluteDir(); 176 | 177 | auto sdfName = configPath.dirName(); 178 | 179 | models.append({name, sdfName}); 180 | } 181 | 182 | return models; 183 | } 184 | -------------------------------------------------------------------------------- /ModelTreeModel.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_MODELTREEMODEL_H 2 | #define GWD_MODELTREEMODEL_H 3 | 4 | #include 5 | #include "ModelTreeItem.h" 6 | 7 | class ModelTreeModel : public QAbstractItemModel { 8 | Q_OBJECT 9 | 10 | public: 11 | explicit ModelTreeModel(QObject *parent = 0); 12 | 13 | ~ModelTreeModel(); 14 | 15 | QVariant data(const QModelIndex &index, int role) const override; 16 | Qt::ItemFlags flags(const QModelIndex &index) const override; 17 | 18 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 19 | 20 | QModelIndex parent(const QModelIndex &index) const override; 21 | 22 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 23 | 24 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 25 | 26 | Qt::DropActions supportedDropActions() const override; 27 | 28 | QStringList mimeTypes() const override; 29 | 30 | QMimeData *mimeData(const QModelIndexList &indexes) const override; 31 | 32 | private: 33 | 34 | ModelTreeItem *rootItem; 35 | 36 | void searchForROSModels(); 37 | 38 | void searchForDownloadedModels(); 39 | 40 | QVector> findModelsInPath(QString directory); 41 | 42 | }; 43 | 44 | 45 | #endif //GWD_MODELTREEMODEL_H 46 | -------------------------------------------------------------------------------- /PropertyPane.cpp: -------------------------------------------------------------------------------- 1 | #include "PropertyPane.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "sdf/IncludedElement.h" 8 | 9 | using namespace std; 10 | 11 | PropertyPane::PropertyPane(QWidget *parent) : QWidget(parent) { 12 | layout = new QFormLayout; 13 | 14 | setLayout(layout); 15 | } 16 | 17 | void setButtonBackground(QPushButton *button, QColor color) { 18 | QString stylesheet = "QPushButton {background-color: rgba("; 19 | stylesheet += std::to_string(color.red()).c_str(); 20 | stylesheet += ", "; 21 | stylesheet += std::to_string(color.green()).c_str(); 22 | stylesheet += ", "; 23 | stylesheet += std::to_string(color.blue()).c_str(); 24 | stylesheet += ", "; 25 | stylesheet += std::to_string(color.alpha()).c_str(); 26 | stylesheet += ");}"; 27 | button->setStyleSheet(stylesheet); 28 | } 29 | 30 | QColor QColorFromSDFColor(const Color &color) { 31 | return QColor{static_cast(color.r * 255), 32 | static_cast(color.g * 255), 33 | static_cast(color.b * 255), 34 | static_cast(color.a * 255)}; 35 | } 36 | 37 | Color SDFColorFromQColor(const QColor &color) { 38 | return Color(color.red()/255.0, color.green()/255.0, color.blue()/255.0, color.alpha()/255.0); 39 | } 40 | 41 | void PropertyPane::showProperties(SDFElement *element) { 42 | clearChildren(); 43 | 44 | IncludedElement *includedElement; 45 | if( (includedElement = dynamic_cast(element)) != nullptr) { 46 | QLineEdit *nameLineEdit = new QLineEdit{includedElement->name.value_or(string{""}).c_str()}; 47 | connect(nameLineEdit, &QLineEdit::textChanged, [includedElement](const QString &text){ 48 | includedElement->name = text.toStdString(); 49 | }); 50 | 51 | QLineEdit *uriLineEdit = new QLineEdit{includedElement->uri.c_str()}; 52 | connect(uriLineEdit, &QLineEdit::textChanged, [includedElement](const QString &text){ 53 | includedElement->uri = text.toStdString(); 54 | }); 55 | 56 | QCheckBox *staticCheckBox = new QCheckBox; 57 | staticCheckBox->setChecked(includedElement->isStatic.value_or(false)); 58 | connect(staticCheckBox, &QCheckBox::stateChanged, [includedElement,staticCheckBox]() { 59 | includedElement->isStatic = staticCheckBox->isChecked(); 60 | }); 61 | 62 | layout->addRow("Name", nameLineEdit); 63 | layout->addRow("URI", uriLineEdit); 64 | layout->addRow("Static", staticCheckBox); 65 | } 66 | 67 | Scene *scene; 68 | if( (scene = dynamic_cast(element)) != nullptr) { 69 | QPushButton *ambientButton = new QPushButton; 70 | ambientButton->setFlat(true); 71 | setButtonBackground(ambientButton, QColorFromSDFColor(scene->ambient)); 72 | connect(ambientButton, &QPushButton::clicked, [scene,ambientButton,this](){ 73 | auto chosenColor = QColorDialog::getColor(QColorFromSDFColor(scene->ambient),this,"Select Ambient Color"); 74 | if(chosenColor.isValid()) { 75 | scene->ambient = SDFColorFromQColor(chosenColor); 76 | setButtonBackground(ambientButton, chosenColor); 77 | } 78 | }); 79 | 80 | QPushButton *backgroundButton = new QPushButton; 81 | backgroundButton->setFlat(true); 82 | setButtonBackground(backgroundButton, QColorFromSDFColor(scene->background)); 83 | connect(backgroundButton, &QPushButton::clicked, [scene,backgroundButton,this](){ 84 | auto chosenColor = QColorDialog::getColor(QColorFromSDFColor(scene->background),this,"Select Background Color"); 85 | if(chosenColor.isValid()) { 86 | scene->background = SDFColorFromQColor(chosenColor); 87 | setButtonBackground(backgroundButton, chosenColor); 88 | } 89 | }); 90 | 91 | QCheckBox *shadowsCheckBox = new QCheckBox; 92 | shadowsCheckBox->setChecked(scene->shadows); 93 | connect(shadowsCheckBox, &QCheckBox::stateChanged, [scene,shadowsCheckBox]() { 94 | scene->shadows = shadowsCheckBox->isChecked(); 95 | }); 96 | 97 | QCheckBox *gridCheckBox = new QCheckBox; 98 | gridCheckBox->setChecked(scene->show_grid); 99 | connect(gridCheckBox, &QCheckBox::stateChanged, [scene,gridCheckBox]() { 100 | scene->show_grid = gridCheckBox->isChecked(); 101 | }); 102 | 103 | QCheckBox *originCheckBox = new QCheckBox; 104 | originCheckBox->setChecked(scene->show_origin); 105 | connect(originCheckBox, &QCheckBox::stateChanged, [scene,originCheckBox]() { 106 | scene->show_origin = originCheckBox->isChecked(); 107 | }); 108 | 109 | layout->addRow("Ambient", ambientButton); 110 | layout->addRow("Background", backgroundButton); 111 | layout->addRow("Shadows", shadowsCheckBox); 112 | layout->addRow("Show Grid", gridCheckBox); 113 | layout->addRow("Show Origin", originCheckBox); 114 | } 115 | } 116 | 117 | void PropertyPane::clear() { 118 | while(!layout->isEmpty()) { 119 | layout->removeRow(0); 120 | } 121 | } 122 | 123 | void PropertyPane::clearChildren() { 124 | for(QWidget *child : findChildren()) { 125 | delete child; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /PropertyPane.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_PROPERTYPANE_H 2 | #define GWD_PROPERTYPANE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "sdf/SDFElement.h" 8 | 9 | class PropertyPane : public QWidget { 10 | Q_OBJECT 11 | public: 12 | PropertyPane(QWidget *parent = nullptr); 13 | 14 | 15 | public slots: 16 | void showProperties(SDFElement *element); 17 | void clear(); 18 | 19 | private: 20 | 21 | QFormLayout *layout; 22 | 23 | void clearChildren(); 24 | 25 | }; 26 | 27 | 28 | #endif //GWD_PROPERTYPANE_H 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gazebo World Designer 2 | A visual tool for laying out Gazebo simulation world files. 3 | 4 | ## Features 5 | - Load & Save Gazebo-compatible SDF World files. 6 | - Add, delete, and move included elements 7 | - Edit included element properties 8 | - Edit worldwide scene properties 9 | 10 | ![Screenshot](https://raw.githubusercontent.com/wiki/barulicm/GazeboWorldDesigner/GWDScreenshot.png) 11 | -------------------------------------------------------------------------------- /WorldView.cpp: -------------------------------------------------------------------------------- 1 | #include "WorldView.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "sdf/IncludedElement.h" 11 | #include "sdf/Parser.h" 12 | 13 | WorldView::WorldView(QWidget *parent) : QWidget(parent) { 14 | setAcceptDrops(true); 15 | setFocusPolicy(Qt::StrongFocus); 16 | } 17 | 18 | void WorldView::newWorld(World &newWorld) { 19 | world = &newWorld; 20 | setSelectedIndex(-1); 21 | update(); 22 | } 23 | 24 | void WorldView::paintEvent(QPaintEvent *) { 25 | 26 | QPainter painter{this}; 27 | 28 | drawOrigin(painter); 29 | 30 | if(world != nullptr) { 31 | for (size_t i = 0; i < world->elements.size(); ++i) { 32 | world->elements[i]->render(painter, scaledOrigin(), scale, 33 | (i == static_cast(selectedIndex))); 34 | } 35 | } 36 | } 37 | 38 | void WorldView::dragEnterEvent(QDragEnterEvent *event) { 39 | event->acceptProposedAction(); 40 | } 41 | 42 | void WorldView::dragMoveEvent(QDragMoveEvent *event) { 43 | event->acceptProposedAction(); 44 | } 45 | 46 | void WorldView::dragLeaveEvent(QDragLeaveEvent *event) { 47 | event->accept(); 48 | } 49 | 50 | void WorldView::dropEvent(QDropEvent *event) { 51 | if(world != nullptr) { 52 | const QMimeData *mimeData = event->mimeData(); 53 | if (mimeData->hasText()) { 54 | std::unique_ptr element = std::make_unique(); 55 | element->uri = "model://" + mimeData->text().toStdString(); 56 | element->isStatic = true; 57 | 58 | const QPointF &dropPos = event->posF(); 59 | element->pose = Pose{}; 60 | element->pose->x = (dropPos.x() - scaledOrigin().x()) * scale; 61 | element->pose->y = (dropPos.y() - scaledOrigin().y()) * scale; 62 | element->pose->z = 0.0; 63 | 64 | world->elements.push_back(std::move(element)); 65 | 66 | setSelectedIndex(static_cast(world->elements.size() - 1)); 67 | update(); 68 | } 69 | setFocus(); 70 | event->acceptProposedAction(); 71 | update(); 72 | } 73 | } 74 | 75 | void WorldView::wheelEvent(QWheelEvent *event) { 76 | auto delta = event->angleDelta().y()/120; 77 | 78 | scale += delta * 0.001; 79 | 80 | scale = std::max(0.00000001, std::min(scale, 1.0)); 81 | 82 | event->accept(); 83 | 84 | update(); 85 | } 86 | 87 | void WorldView::mousePressEvent(QMouseEvent *event) { 88 | if(world != nullptr) { 89 | if ((event->buttons() | Qt::MouseButton::LeftButton) != 0) { 90 | if (!world->elements.empty()) { 91 | // check if close enough to an object 92 | QPointF pressPos = (event->pos() - scaledOrigin()) * scale; 93 | std::vector distances(world->elements.size(), 0); 94 | std::transform(world->elements.begin(), world->elements.end(), 95 | distances.begin(), [&pressPos, this]( 96 | const std::unique_ptr &e) { 97 | return e->distanceToPoint(pressPos.x(), pressPos.y()) / 98 | scale; 99 | }); 100 | auto mindist = std::min_element(distances.begin(), 101 | distances.end()); 102 | if (*mindist < 10) { 103 | auto index = static_cast(std::distance( 104 | distances.begin(), mindist)); 105 | if (index != selectedIndex) { 106 | setSelectedIndex( 107 | static_cast(std::distance(distances.begin(), 108 | mindist))); 109 | } 110 | isDraggingElement = true; 111 | } else { 112 | isDraggingView = true; 113 | prevMousePose = event->pos(); 114 | } 115 | } else { 116 | isDraggingView = true; 117 | prevMousePose = event->pos(); 118 | } 119 | } 120 | } 121 | } 122 | 123 | void WorldView::mouseMoveEvent(QMouseEvent *event) { 124 | if(world != nullptr) { 125 | if (isDraggingElement && selectedIndex >= 0) { 126 | const auto &draggedElement = world->elements[static_cast(selectedIndex)]; 127 | QPointF movePos = (event->pos() - scaledOrigin()) * scale; 128 | draggedElement->setPose(movePos.x(), movePos.y(), 0); 129 | update(); 130 | } else if(isDraggingView) { 131 | auto deltaX = static_cast(event->x() - prevMousePose.x()) / width(); 132 | auto deltaY = static_cast(event->y() - prevMousePose.y()) / height(); 133 | origin.setX(origin.x() + deltaX); 134 | origin.setY(origin.y() + deltaY); 135 | prevMousePose = event->pos(); 136 | update(); 137 | } 138 | } 139 | } 140 | 141 | void WorldView::mouseReleaseEvent(QMouseEvent *event) { 142 | if((event->buttons() | Qt::MouseButton::LeftButton) != 0) { 143 | isDraggingElement = false; 144 | isDraggingView = false; 145 | update(); 146 | } 147 | } 148 | 149 | void WorldView::keyPressEvent(QKeyEvent *event) { 150 | if(world != nullptr) { 151 | if (event->key() == Qt::Key_Delete && !world->elements.empty()) { 152 | world->elements.erase( 153 | world->elements.begin() + static_cast(selectedIndex)); 154 | setSelectedIndex(0); 155 | update(); 156 | } else { 157 | QWidget::keyPressEvent(event); 158 | } 159 | } 160 | } 161 | 162 | void WorldView::drawOrigin(QPainter &painter) { 163 | QPointF c = scaledOrigin(); 164 | painter.setPen(Qt::red); 165 | painter.drawLine(c, c + QPointF{1.0/scale, 0}); 166 | painter.setPen(Qt::green); 167 | painter.drawLine(c, c + QPointF{0, 1.0/scale}); 168 | } 169 | 170 | QPointF WorldView::scaledOrigin() { 171 | return QPointF{origin.x() * width(), origin.y() * height()}; 172 | } 173 | 174 | void WorldView::setSelectedIndex(int index) { 175 | selectedIndex = index; 176 | emit onSelectedIndexChanged(selectedIndex); 177 | } 178 | -------------------------------------------------------------------------------- /WorldView.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_WORLDVIEW_H 2 | #define GWD_WORLDVIEW_H 3 | 4 | #include 5 | #include 6 | #include "sdf/World.h" 7 | 8 | class WorldView : public QWidget { 9 | Q_OBJECT 10 | 11 | public: 12 | WorldView(QWidget *parent = nullptr); 13 | 14 | public slots: 15 | void newWorld(World &newWorld); 16 | 17 | signals: 18 | void onSelectedIndexChanged(int index); 19 | 20 | protected: 21 | void paintEvent(QPaintEvent *event) override; 22 | 23 | void dragEnterEvent(QDragEnterEvent *event) override; 24 | void dragMoveEvent(QDragMoveEvent *event) override; 25 | void dragLeaveEvent(QDragLeaveEvent *event) override; 26 | void dropEvent(QDropEvent *event) override; 27 | 28 | void wheelEvent(QWheelEvent *event) override; 29 | 30 | void mousePressEvent(QMouseEvent *event) override; 31 | void mouseMoveEvent(QMouseEvent *event) override; 32 | void mouseReleaseEvent(QMouseEvent *event) override; 33 | 34 | void keyPressEvent(QKeyEvent *event) override; 35 | 36 | private: 37 | World *world = nullptr; 38 | 39 | void drawOrigin(QPainter &painter); 40 | QPointF scaledOrigin(); 41 | 42 | double scale = 0.01; // m/px 43 | QPointF origin{0.5f,0.5f}; 44 | 45 | bool isDraggingElement = false; 46 | bool isDraggingView = false; 47 | QPoint prevMousePose; 48 | 49 | int selectedIndex = 0; 50 | void setSelectedIndex(int index); 51 | 52 | }; 53 | 54 | #endif //GWD_WORLDVIEW_H 55 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "MainWindow.h" 6 | 7 | void loadStylesheet(QApplication &application) { 8 | QFile f{":qdarkstyle/style.qss"}; 9 | if (!f.exists()) { 10 | std::cerr << "Unable to set stylesheet. File not found!" << std::endl; 11 | } else { 12 | f.open(QFile::ReadOnly | QFile::Text); 13 | QTextStream ts{&f}; 14 | application.setStyleSheet(ts.readAll()); 15 | } 16 | } 17 | 18 | int main(int argc, char **argv) { 19 | 20 | QApplication application{argc, argv}; 21 | 22 | loadStylesheet(application); 23 | 24 | MainWindow window; 25 | window.show(); 26 | 27 | return application.exec(); 28 | } -------------------------------------------------------------------------------- /qdarkstyle/.gitignore: -------------------------------------------------------------------------------- 1 | /*.pyc 2 | -------------------------------------------------------------------------------- /qdarkstyle/COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) <2013-2014> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /qdarkstyle/README.md: -------------------------------------------------------------------------------- 1 | This stylesheet was created and is maintained by Colin Duquesnoy on [GitHub](https://github.com/ColinDuquesnoy/QDarkStyleSheet). 2 | -------------------------------------------------------------------------------- /qdarkstyle/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # The MIT License (MIT) 4 | # 5 | # Copyright (c) <2013-2014> 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | # 25 | """ 26 | Initialise the QDarkStyleSheet module when used with python. 27 | 28 | This modules provides a function to transparently load the stylesheets 29 | with the correct rc file. 30 | """ 31 | import logging 32 | import platform 33 | 34 | 35 | __version__ = "2.3.0" 36 | 37 | 38 | def _logger(): 39 | return logging.getLogger('qdarkstyle') 40 | 41 | 42 | def load_stylesheet(pyside=True): 43 | """ 44 | Loads the stylesheet. Takes care of importing the rc module. 45 | 46 | :param pyside: True to load the pyside rc file, False to load the PyQt rc file 47 | 48 | :return the stylesheet string 49 | """ 50 | # Smart import of the rc file 51 | if pyside: 52 | import qdarkstyle.pyside_style_rc 53 | else: 54 | import qdarkstyle.pyqt_style_rc 55 | 56 | # Load the stylesheet content from resources 57 | if not pyside: 58 | from PyQt4.QtCore import QFile, QTextStream 59 | else: 60 | from PySide.QtCore import QFile, QTextStream 61 | 62 | f = QFile(":qdarkstyle/style.qss") 63 | if not f.exists(): 64 | _logger().error("Unable to load stylesheet, file not found in " 65 | "resources") 66 | return "" 67 | else: 68 | f.open(QFile.ReadOnly | QFile.Text) 69 | ts = QTextStream(f) 70 | stylesheet = ts.readAll() 71 | if platform.system().lower() == 'darwin': # see issue #12 on github 72 | mac_fix = ''' 73 | QDockWidget::title 74 | { 75 | background-color: #31363b; 76 | text-align: center; 77 | height: 12px; 78 | } 79 | ''' 80 | stylesheet += mac_fix 81 | return stylesheet 82 | 83 | 84 | def load_stylesheet_pyqt5(): 85 | """ 86 | Loads the stylesheet for use in a pyqt5 application. 87 | 88 | :param pyside: True to load the pyside rc file, False to load the PyQt rc file 89 | 90 | :return the stylesheet string 91 | """ 92 | # Smart import of the rc file 93 | import qdarkstyle.pyqt5_style_rc 94 | 95 | # Load the stylesheet content from resources 96 | from PyQt5.QtCore import QFile, QTextStream 97 | 98 | f = QFile(":qdarkstyle/style.qss") 99 | if not f.exists(): 100 | _logger().error("Unable to load stylesheet, file not found in " 101 | "resources") 102 | return "" 103 | else: 104 | f.open(QFile.ReadOnly | QFile.Text) 105 | ts = QTextStream(f) 106 | stylesheet = ts.readAll() 107 | if platform.system().lower() == 'darwin': # see issue #12 on github 108 | mac_fix = ''' 109 | QDockWidget::title 110 | { 111 | background-color: #31363b; 112 | text-align: center; 113 | height: 12px; 114 | } 115 | ''' 116 | stylesheet += mac_fix 117 | return stylesheet 118 | -------------------------------------------------------------------------------- /qdarkstyle/compile_qrc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # The MIT License (MIT) 5 | # 6 | # Copyright (c) <2013-2014> 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in 16 | # all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | # THE SOFTWARE. 25 | # 26 | """ 27 | Utility scripts to compile the qrc file. The script will 28 | attempt to compile the qrc file using the following tools: 29 | - rcc 30 | - pyside-rcc 31 | - pyrcc4 32 | 33 | Delete the compiled files that you don't want to use 34 | manually after running this script. 35 | """ 36 | import os 37 | 38 | 39 | def compile_all(): 40 | """ 41 | Compile style.qrc using rcc, pyside-rcc and pyrcc4 42 | """ 43 | # print("Compiling for Qt: style.qrc -> style.rcc") 44 | # os.system("rcc style.qrc -o style.rcc") 45 | print("Compiling for PyQt4: style.qrc -> pyqt_style_rc.py") 46 | os.system("pyrcc4 -py3 style.qrc -o pyqt_style_rc.py") 47 | print("Compiling for PyQt5: style.qrc -> pyqt5_style_rc.py") 48 | os.system("pyrcc5 style.qrc -o pyqt5_style_rc.py") 49 | print("Compiling for PySide: style.qrc -> pyside_style_rc.py") 50 | os.system("pyside-rcc -py3 style.qrc -o pyside_style_rc.py") 51 | 52 | 53 | if __name__ == "__main__": 54 | compile_all() 55 | -------------------------------------------------------------------------------- /qdarkstyle/pyside_style_rc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Resource object code 4 | # 5 | # Created: Sun Nov 20 17:38:35 2016 6 | # by: The Resource Compiler for PySide (Qt v4.8.7) 7 | # 8 | # WARNING! All changes made in this file will be lost! 9 | 10 | from PySide import QtCore 11 | 12 | qt_resource_data = b"\x00\x00_\xaa/*\x0a * The MIT License (MIT)\x0a *\x0a * Copyright (c) <2013-2014> \x0a *\x0a * Permission is hereby granted, free of charge, to any person obtaining a copy\x0a * of this software and associated documentation files (the \x22Software\x22), to deal\x0a * in the Software without restriction, including without limitation the rights\x0a * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\x0a * copies of the Software, and to permit persons to whom the Software is\x0a * furnished to do so, subject to the following conditions:\x0a\x0a * The above copyright notice and this permission notice shall be included in\x0a * all copies or substantial portions of the Software.\x0a\x0a * THE SOFTWARE IS PROVIDED \x22AS IS\x22, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\x0a * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\x0a * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\x0a * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\x0a * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\x0a * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\x0a * THE SOFTWARE.\x0a */\x0aQToolTip\x0a{\x0a border: 1px solid #76797C;\x0a background-color: rgb(90, 102, 117);;\x0a color: white;\x0a padding: 5px;\x0a opacity: 200;\x0a}\x0a\x0aQWidget\x0a{\x0a color: #eff0f1;\x0a background-color: #31363b;\x0a selection-background-color:#3daee9;\x0a selection-color: #eff0f1;\x0a background-clip: border;\x0a border-image: none;\x0a border: 0px transparent black;\x0a outline: 0;\x0a}\x0a\x0aQWidget:item:hover\x0a{\x0a background-color: #3daee9;\x0a color: #eff0f1;\x0a}\x0a\x0aQWidget:item:selected\x0a{\x0a background-color: #3daee9;\x0a}\x0a\x0aQCheckBox\x0a{\x0a spacing: 5px;\x0a outline: none;\x0a color: #eff0f1;\x0a margin-bottom: 2px;\x0a}\x0a\x0aQCheckBox:disabled\x0a{\x0a color: #76797C;\x0a}\x0a\x0aQCheckBox::indicator,\x0aQGroupBox::indicator\x0a{\x0a width: 18px;\x0a height: 18px;\x0a}\x0aQGroupBox::indicator\x0a{\x0a margin-left: 2px;\x0a}\x0a\x0aQCheckBox::indicator:unchecked\x0a{\x0a image: url(:/qss_icons/rc/checkbox_unchecked.png);\x0a}\x0a\x0aQCheckBox::indicator:unchecked:hover,\x0aQCheckBox::indicator:unchecked:focus,\x0aQCheckBox::indicator:unchecked:pressed,\x0aQGroupBox::indicator:unchecked:hover,\x0aQGroupBox::indicator:unchecked:focus,\x0aQGroupBox::indicator:unchecked:pressed\x0a{\x0a border: none;\x0a image: url(:/qss_icons/rc/checkbox_unchecked_focus.png);\x0a}\x0a\x0aQCheckBox::indicator:checked\x0a{\x0a image: url(:/qss_icons/rc/checkbox_checked.png);\x0a}\x0a\x0aQCheckBox::indicator:checked:hover,\x0aQCheckBox::indicator:checked:focus,\x0aQCheckBox::indicator:checked:pressed,\x0aQGroupBox::indicator:checked:hover,\x0aQGroupBox::indicator:checked:focus,\x0aQGroupBox::indicator:checked:pressed\x0a{\x0a border: none;\x0a image: url(:/qss_icons/rc/checkbox_checked_focus.png);\x0a}\x0a\x0a\x0aQCheckBox::indicator:indeterminate\x0a{\x0a image: url(:/qss_icons/rc/checkbox_indeterminate.png);\x0a}\x0a\x0aQCheckBox::indicator:indeterminate:focus,\x0aQCheckBox::indicator:indeterminate:hover,\x0aQCheckBox::indicator:indeterminate:pressed\x0a{\x0a image: url(:/qss_icons/rc/checkbox_indeterminate_focus.png);\x0a}\x0a\x0aQCheckBox::indicator:checked:disabled,\x0aQGroupBox::indicator:checked:disabled\x0a{\x0a image: url(:/qss_icons/rc/checkbox_checked_disabled.png);\x0a}\x0a\x0aQCheckBox::indicator:unchecked:disabled,\x0aQGroupBox::indicator:unchecked:disabled\x0a{\x0a image: url(:/qss_icons/rc/checkbox_unchecked_disabled.png);\x0a}\x0a\x0aQRadioButton\x0a{\x0a spacing: 5px;\x0a outline: none;\x0a color: #eff0f1;\x0a margin-bottom: 2px;\x0a}\x0a\x0aQRadioButton:disabled\x0a{\x0a color: #76797C;\x0a}\x0aQRadioButton::indicator\x0a{\x0a width: 21px;\x0a height: 21px;\x0a}\x0a\x0aQRadioButton::indicator:unchecked\x0a{\x0a image: url(:/qss_icons/rc/radio_unchecked.png);\x0a}\x0a\x0a\x0aQRadioButton::indicator:unchecked:hover,\x0aQRadioButton::indicator:unchecked:focus,\x0aQRadioButton::indicator:unchecked:pressed\x0a{\x0a border: none;\x0a outline: none;\x0a image: url(:/qss_icons/rc/radio_unchecked_focus.png);\x0a}\x0a\x0aQRadioButton::indicator:checked\x0a{\x0a border: none;\x0a outline: none;\x0a image: url(:/qss_icons/rc/radio_checked.png);\x0a}\x0a\x0aQRadioButton::indicator:checked:hover,\x0aQRadioButton::indicator:checked:focus,\x0aQRadioButton::indicator:checked:pressed\x0a{\x0a border: none;\x0a outline: none;\x0a image: url(:/qss_icons/rc/radio_checked_focus.png);\x0a}\x0a\x0aQRadioButton::indicator:checked:disabled\x0a{\x0a outline: none;\x0a image: url(:/qss_icons/rc/radio_checked_disabled.png);\x0a}\x0a\x0aQRadioButton::indicator:unchecked:disabled\x0a{\x0a image: url(:/qss_icons/rc/radio_unchecked_disabled.png);\x0a}\x0a\x0a\x0aQMenuBar\x0a{\x0a background-color: #31363b;\x0a color: #eff0f1;\x0a}\x0a\x0aQMenuBar::item\x0a{\x0a background: transparent;\x0a}\x0a\x0aQMenuBar::item:selected\x0a{\x0a background: transparent;\x0a border: 1px solid #76797C;\x0a}\x0a\x0aQMenuBar::item:pressed\x0a{\x0a border: 1px solid #76797C;\x0a background-color: #3daee9;\x0a color: #eff0f1;\x0a margin-bottom:-1px;\x0a padding-bottom:1px;\x0a}\x0a\x0aQMenu\x0a{\x0a border: 1px solid #76797C;\x0a color: #eff0f1;\x0a margin: 2px;\x0a}\x0a\x0aQMenu::icon\x0a{\x0a margin: 5px;\x0a}\x0a\x0aQMenu::item\x0a{\x0a padding: 5px 30px 5px 30px;\x0a margin-left: 5px;\x0a border: 1px solid transparent; /* reserve space for selection border */\x0a}\x0a\x0aQMenu::item:selected\x0a{\x0a color: #eff0f1;\x0a}\x0a\x0aQMenu::separator {\x0a height: 2px;\x0a background: lightblue;\x0a margin-left: 10px;\x0a margin-right: 5px;\x0a}\x0a\x0aQMenu::indicator {\x0a width: 18px;\x0a height: 18px;\x0a}\x0a\x0a/* non-exclusive indicator = check box style indicator\x0a (see QActionGroup::setExclusive) */\x0aQMenu::indicator:non-exclusive:unchecked {\x0a image: url(:/qss_icons/rc/checkbox_unchecked.png);\x0a}\x0a\x0aQMenu::indicator:non-exclusive:unchecked:selected {\x0a image: url(:/qss_icons/rc/checkbox_unchecked_disabled.png);\x0a}\x0a\x0aQMenu::indicator:non-exclusive:checked {\x0a image: url(:/qss_icons/rc/checkbox_checked.png);\x0a}\x0a\x0aQMenu::indicator:non-exclusive:checked:selected {\x0a image: url(:/qss_icons/rc/checkbox_checked_disabled.png);\x0a}\x0a\x0a/* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */\x0aQMenu::indicator:exclusive:unchecked {\x0a image: url(:/qss_icons/rc/radio_unchecked.png);\x0a}\x0a\x0aQMenu::indicator:exclusive:unchecked:selected {\x0a image: url(:/qss_icons/rc/radio_unchecked_disabled.png);\x0a}\x0a\x0aQMenu::indicator:exclusive:checked {\x0a image: url(:/qss_icons/rc/radio_checked.png);\x0a}\x0a\x0aQMenu::indicator:exclusive:checked:selected {\x0a image: url(:/qss_icons/rc/radio_checked_disabled.png);\x0a}\x0a\x0aQMenu::right-arrow {\x0a margin: 5px;\x0a image: url(:/qss_icons/rc/right_arrow.png)\x0a}\x0a\x0a\x0aQWidget:disabled\x0a{\x0a color: #454545;\x0a background-color: #31363b;\x0a}\x0a\x0aQAbstractItemView\x0a{\x0a alternate-background-color: #31363b;\x0a color: #eff0f1;\x0a border: 1px solid 3A3939;\x0a border-radius: 2px;\x0a}\x0a\x0aQWidget:focus, QMenuBar:focus\x0a{\x0a border: 1px solid #3daee9;\x0a}\x0a\x0aQTabWidget:focus, QCheckBox:focus, QRadioButton:focus, QSlider:focus\x0a{\x0a border: none;\x0a}\x0a\x0aQLineEdit\x0a{\x0a background-color: #232629;\x0a padding: 5px;\x0a border-style: solid;\x0a border: 1px solid #76797C;\x0a border-radius: 2px;\x0a color: #eff0f1;\x0a}\x0a\x0aQGroupBox {\x0a border:1px solid #76797C;\x0a border-radius: 2px;\x0a margin-top: 20px;\x0a}\x0a\x0aQGroupBox::title {\x0a subcontrol-origin: margin;\x0a subcontrol-position: top center;\x0a padding-left: 10px;\x0a padding-right: 10px;\x0a padding-top: 10px;\x0a}\x0a\x0aQAbstractScrollArea\x0a{\x0a border-radius: 2px;\x0a border: 1px solid #76797C;\x0a background-color: transparent;\x0a}\x0a\x0aQScrollBar:horizontal\x0a{\x0a height: 15px;\x0a margin: 3px 15px 3px 15px;\x0a border: 1px transparent #2A2929;\x0a border-radius: 4px;\x0a background-color: #2A2929;\x0a}\x0a\x0aQScrollBar::handle:horizontal\x0a{\x0a background-color: #605F5F;\x0a min-width: 5px;\x0a border-radius: 4px;\x0a}\x0a\x0aQScrollBar::add-line:horizontal\x0a{\x0a margin: 0px 3px 0px 3px;\x0a border-image: url(:/qss_icons/rc/right_arrow_disabled.png);\x0a width: 10px;\x0a height: 10px;\x0a subcontrol-position: right;\x0a subcontrol-origin: margin;\x0a}\x0a\x0aQScrollBar::sub-line:horizontal\x0a{\x0a margin: 0px 3px 0px 3px;\x0a border-image: url(:/qss_icons/rc/left_arrow_disabled.png);\x0a height: 10px;\x0a width: 10px;\x0a subcontrol-position: left;\x0a subcontrol-origin: margin;\x0a}\x0a\x0aQScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on\x0a{\x0a border-image: url(:/qss_icons/rc/right_arrow.png);\x0a height: 10px;\x0a width: 10px;\x0a subcontrol-position: right;\x0a subcontrol-origin: margin;\x0a}\x0a\x0a\x0aQScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on\x0a{\x0a border-image: url(:/qss_icons/rc/left_arrow.png);\x0a height: 10px;\x0a width: 10px;\x0a subcontrol-position: left;\x0a subcontrol-origin: margin;\x0a}\x0a\x0aQScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal\x0a{\x0a background: none;\x0a}\x0a\x0a\x0aQScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal\x0a{\x0a background: none;\x0a}\x0a\x0aQScrollBar:vertical\x0a{\x0a background-color: #2A2929;\x0a width: 15px;\x0a margin: 15px 3px 15px 3px;\x0a border: 1px transparent #2A2929;\x0a border-radius: 4px;\x0a}\x0a\x0aQScrollBar::handle:vertical\x0a{\x0a background-color: #605F5F;\x0a min-height: 5px;\x0a border-radius: 4px;\x0a}\x0a\x0aQScrollBar::sub-line:vertical\x0a{\x0a margin: 3px 0px 3px 0px;\x0a border-image: url(:/qss_icons/rc/up_arrow_disabled.png);\x0a height: 10px;\x0a width: 10px;\x0a subcontrol-position: top;\x0a subcontrol-origin: margin;\x0a}\x0a\x0aQScrollBar::add-line:vertical\x0a{\x0a margin: 3px 0px 3px 0px;\x0a border-image: url(:/qss_icons/rc/down_arrow_disabled.png);\x0a height: 10px;\x0a width: 10px;\x0a subcontrol-position: bottom;\x0a subcontrol-origin: margin;\x0a}\x0a\x0aQScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on\x0a{\x0a\x0a border-image: url(:/qss_icons/rc/up_arrow.png);\x0a height: 10px;\x0a width: 10px;\x0a subcontrol-position: top;\x0a subcontrol-origin: margin;\x0a}\x0a\x0a\x0aQScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on\x0a{\x0a border-image: url(:/qss_icons/rc/down_arrow.png);\x0a height: 10px;\x0a width: 10px;\x0a subcontrol-position: bottom;\x0a subcontrol-origin: margin;\x0a}\x0a\x0aQScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical\x0a{\x0a background: none;\x0a}\x0a\x0a\x0aQScrollBar::add-page:vertical, QScrollBar::sub-page:vertical\x0a{\x0a background: none;\x0a}\x0a\x0aQTextEdit\x0a{\x0a background-color: #232629;\x0a color: #eff0f1;\x0a border: 1px solid #76797C;\x0a}\x0a\x0aQPlainTextEdit\x0a{\x0a background-color: #232629;;\x0a color: #eff0f1;\x0a border-radius: 2px;\x0a border: 1px solid #76797C;\x0a}\x0a\x0aQHeaderView::section\x0a{\x0a background-color: #76797C;\x0a color: #eff0f1;\x0a padding: 5px;\x0a border: 1px solid #76797C;\x0a}\x0a\x0aQSizeGrip {\x0a image: url(:/qss_icons/rc/sizegrip.png);\x0a width: 12px;\x0a height: 12px;\x0a}\x0a\x0a\x0aQMainWindow::separator\x0a{\x0a background-color: #31363b;\x0a color: white;\x0a padding-left: 4px;\x0a spacing: 2px;\x0a border: 1px dashed #76797C;\x0a}\x0a\x0aQMainWindow::separator:hover\x0a{\x0a\x0a background-color: #787876;\x0a color: white;\x0a padding-left: 4px;\x0a border: 1px solid #76797C;\x0a spacing: 2px;\x0a}\x0a\x0a\x0aQMenu::separator\x0a{\x0a height: 1px;\x0a background-color: #76797C;\x0a color: white;\x0a padding-left: 4px;\x0a margin-left: 10px;\x0a margin-right: 5px;\x0a}\x0a\x0a\x0aQFrame\x0a{\x0a border-radius: 2px;\x0a border: 1px solid #76797C;\x0a}\x0a\x0aQFrame[frameShape=\x220\x22]\x0a{\x0a border-radius: 2px;\x0a border: 1px transparent #76797C;\x0a}\x0a\x0aQStackedWidget\x0a{\x0a border: 1px transparent black;\x0a}\x0a\x0aQToolBar {\x0a border: 1px transparent #393838;\x0a background: 1px solid #31363b;\x0a font-weight: bold;\x0a}\x0a\x0aQToolBar::handle:horizontal {\x0a image: url(:/qss_icons/rc/Hmovetoolbar.png);\x0a}\x0aQToolBar::handle:vertical {\x0a image: url(:/qss_icons/rc/Vmovetoolbar.png);\x0a}\x0aQToolBar::separator:horizontal {\x0a image: url(:/qss_icons/rc/Hsepartoolbar.png);\x0a}\x0aQToolBar::separator:vertical {\x0a image: url(:/qss_icons/rc/Vsepartoolbar.png);\x0a}\x0aQToolButton#qt_toolbar_ext_button {\x0a background: #58595a\x0a}\x0a\x0aQPushButton\x0a{\x0a color: #eff0f1;\x0a background-color: #31363b;\x0a border-width: 1px;\x0a border-color: #76797C;\x0a border-style: solid;\x0a padding: 5px;\x0a border-radius: 2px;\x0a outline: none;\x0a}\x0a\x0aQPushButton:disabled\x0a{\x0a background-color: #31363b;\x0a border-width: 1px;\x0a border-color: #454545;\x0a border-style: solid;\x0a padding-top: 5px;\x0a padding-bottom: 5px;\x0a padding-left: 10px;\x0a padding-right: 10px;\x0a border-radius: 2px;\x0a color: #454545;\x0a}\x0a\x0aQPushButton:focus {\x0a background-color: #3daee9;\x0a color: white;\x0a}\x0a\x0aQPushButton:pressed\x0a{\x0a background-color: #3daee9;\x0a padding-top: -15px;\x0a padding-bottom: -17px;\x0a}\x0a\x0aQComboBox\x0a{\x0a selection-background-color: #3daee9;\x0a border-style: solid;\x0a border: 1px solid #76797C;\x0a border-radius: 2px;\x0a padding: 5px;\x0a min-width: 75px;\x0a}\x0a\x0aQPushButton:checked{\x0a background-color: #76797C;\x0a border-color: #6A6969;\x0a}\x0a\x0aQComboBox:hover,QPushButton:hover,QAbstractSpinBox:hover,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QAbstractView:hover,QTreeView:hover\x0a{\x0a border: 1px solid #3daee9;\x0a color: #eff0f1;\x0a}\x0a\x0aQComboBox:on\x0a{\x0a padding-top: 3px;\x0a padding-left: 4px;\x0a selection-background-color: #4a4a4a;\x0a}\x0a\x0aQComboBox QAbstractItemView\x0a{\x0a background-color: #232629;\x0a border-radius: 2px;\x0a border: 1px solid #76797C;\x0a selection-background-color: #3daee9;\x0a}\x0a\x0aQComboBox::drop-down\x0a{\x0a subcontrol-origin: padding;\x0a subcontrol-position: top right;\x0a width: 15px;\x0a\x0a border-left-width: 0px;\x0a border-left-color: darkgray;\x0a border-left-style: solid;\x0a border-top-right-radius: 3px;\x0a border-bottom-right-radius: 3px;\x0a}\x0a\x0aQComboBox::down-arrow\x0a{\x0a image: url(:/qss_icons/rc/down_arrow_disabled.png);\x0a}\x0a\x0aQComboBox::down-arrow:on, QComboBox::down-arrow:hover,\x0aQComboBox::down-arrow:focus\x0a{\x0a image: url(:/qss_icons/rc/down_arrow.png);\x0a}\x0a\x0aQAbstractSpinBox {\x0a padding: 5px;\x0a border: 1px solid #76797C;\x0a background-color: #232629;\x0a color: #eff0f1;\x0a border-radius: 2px;\x0a min-width: 75px;\x0a}\x0a\x0aQAbstractSpinBox:up-button\x0a{\x0a background-color: transparent;\x0a subcontrol-origin: border;\x0a subcontrol-position: center right;\x0a}\x0a\x0aQAbstractSpinBox:down-button\x0a{\x0a background-color: transparent;\x0a subcontrol-origin: border;\x0a subcontrol-position: center left;\x0a}\x0a\x0aQAbstractSpinBox::up-arrow,QAbstractSpinBox::up-arrow:disabled,QAbstractSpinBox::up-arrow:off {\x0a image: url(:/qss_icons/rc/up_arrow_disabled.png);\x0a width: 10px;\x0a height: 10px;\x0a}\x0aQAbstractSpinBox::up-arrow:hover\x0a{\x0a image: url(:/qss_icons/rc/up_arrow.png);\x0a}\x0a\x0a\x0aQAbstractSpinBox::down-arrow,QAbstractSpinBox::down-arrow:disabled,QAbstractSpinBox::down-arrow:off\x0a{\x0a image: url(:/qss_icons/rc/down_arrow_disabled.png);\x0a width: 10px;\x0a height: 10px;\x0a}\x0aQAbstractSpinBox::down-arrow:hover\x0a{\x0a image: url(:/qss_icons/rc/down_arrow.png);\x0a}\x0a\x0a\x0aQLabel\x0a{\x0a border: 0px solid black;\x0a}\x0a\x0aQTabWidget{\x0a border: 0px transparent black;\x0a}\x0a\x0aQTabWidget::pane {\x0a border: 1px solid #76797C;\x0a padding: 5px;\x0a margin: 0px;\x0a}\x0a\x0aQTabBar\x0a{\x0a qproperty-drawBase: 0;\x0a left: 5px; /* move to the right by 5px */\x0a border-radius: 3px;\x0a}\x0a\x0aQTabBar:focus\x0a{\x0a border: 0px transparent black;\x0a}\x0a\x0aQTabBar::close-button {\x0a image: url(:/qss_icons/rc/close.png);\x0a background: transparent;\x0a}\x0a\x0aQTabBar::close-button:hover\x0a{\x0a image: url(:/qss_icons/rc/close-hover.png);\x0a background: transparent;\x0a}\x0a\x0aQTabBar::close-button:pressed {\x0a image: url(:/qss_icons/rc/close-pressed.png);\x0a background: transparent;\x0a}\x0a\x0a/* TOP TABS */\x0aQTabBar::tab:top {\x0a color: #eff0f1;\x0a border: 1px solid #76797C;\x0a border-bottom: 1px transparent black;\x0a background-color: #31363b;\x0a padding: 5px;\x0a min-width: 50px;\x0a border-top-left-radius: 2px;\x0a border-top-right-radius: 2px;\x0a}\x0a\x0aQTabBar::tab:top:!selected\x0a{\x0a color: #eff0f1;\x0a background-color: #54575B;\x0a border: 1px solid #76797C;\x0a border-bottom: 1px transparent black;\x0a border-top-left-radius: 2px;\x0a border-top-right-radius: 2px; \x0a}\x0a\x0aQTabBar::tab:top:!selected:hover {\x0a background-color: #3daee9;\x0a}\x0a\x0a/* BOTTOM TABS */\x0aQTabBar::tab:bottom {\x0a color: #eff0f1;\x0a border: 1px solid #76797C;\x0a border-top: 1px transparent black;\x0a background-color: #31363b;\x0a padding: 5px;\x0a border-bottom-left-radius: 2px;\x0a border-bottom-right-radius: 2px;\x0a min-width: 50px;\x0a}\x0a\x0aQTabBar::tab:bottom:!selected\x0a{\x0a color: #eff0f1;\x0a background-color: #54575B;\x0a border: 1px solid #76797C;\x0a border-top: 1px transparent black;\x0a border-bottom-left-radius: 2px;\x0a border-bottom-right-radius: 2px;\x0a}\x0a\x0aQTabBar::tab:bottom:!selected:hover {\x0a background-color: #3daee9;\x0a}\x0a\x0a/* LEFT TABS */\x0aQTabBar::tab:left {\x0a color: #eff0f1;\x0a border: 1px solid #76797C;\x0a border-left: 1px transparent black;\x0a background-color: #31363b;\x0a padding: 5px;\x0a border-top-right-radius: 2px;\x0a border-bottom-right-radius: 2px;\x0a min-height: 50px;\x0a}\x0a\x0aQTabBar::tab:left:!selected\x0a{\x0a color: #eff0f1;\x0a background-color: #54575B;\x0a border: 1px solid #76797C;\x0a border-left: 1px transparent black;\x0a border-top-right-radius: 2px;\x0a border-bottom-right-radius: 2px;\x0a}\x0a\x0aQTabBar::tab:left:!selected:hover {\x0a background-color: #3daee9;\x0a}\x0a\x0a\x0a/* RIGHT TABS */\x0aQTabBar::tab:right {\x0a color: #eff0f1;\x0a border: 1px solid #76797C;\x0a border-right: 1px transparent black;\x0a background-color: #31363b;\x0a padding: 5px;\x0a border-top-left-radius: 2px;\x0a border-bottom-left-radius: 2px;\x0a min-height: 50px;\x0a}\x0a\x0aQTabBar::tab:right:!selected\x0a{\x0a color: #eff0f1;\x0a background-color: #54575B;\x0a border: 1px solid #76797C;\x0a border-right: 1px transparent black;\x0a border-top-left-radius: 2px;\x0a border-bottom-left-radius: 2px;\x0a}\x0a\x0aQTabBar::tab:right:!selected:hover {\x0a background-color: #3daee9;\x0a}\x0a\x0aQTabBar QToolButton::right-arrow:enabled {\x0a image: url(:/qss_icons/rc/right_arrow.png);\x0a }\x0a\x0a QTabBar QToolButton::left-arrow:enabled {\x0a image: url(:/qss_icons/rc/left_arrow.png);\x0a }\x0a\x0aQTabBar QToolButton::right-arrow:disabled {\x0a image: url(:/qss_icons/rc/right_arrow_disabled.png);\x0a }\x0a\x0a QTabBar QToolButton::left-arrow:disabled {\x0a image: url(:/qss_icons/rc/left_arrow_disabled.png);\x0a }\x0a\x0a\x0aQDockWidget {\x0a background: #31363b;\x0a border: 1px solid #403F3F;\x0a titlebar-close-icon: url(:/qss_icons/rc/close.png);\x0a titlebar-normal-icon: url(:/qss_icons/rc/undock.png);\x0a}\x0a\x0aQDockWidget::close-button, QDockWidget::float-button {\x0a border: 1px solid transparent;\x0a border-radius: 2px;\x0a background: transparent;\x0a}\x0a\x0aQDockWidget::close-button:hover, QDockWidget::float-button:hover {\x0a background: rgba(255, 255, 255, 10);\x0a}\x0a\x0aQDockWidget::close-button:pressed, QDockWidget::float-button:pressed {\x0a padding: 1px -1px -1px 1px;\x0a background: rgba(255, 255, 255, 10);\x0a}\x0a\x0aQTreeView, QListView\x0a{\x0a border: 1px solid #76797C;\x0a background-color: #232629;\x0a}\x0a\x0aQTreeView:branch:selected, QTreeView:branch:hover\x0a{\x0a background: url(:/qss_icons/rc/transparent.png);\x0a}\x0a\x0aQTreeView::branch:has-siblings:!adjoins-item {\x0a border-image: url(:/qss_icons/rc/transparent.png);\x0a}\x0a\x0aQTreeView::branch:has-siblings:adjoins-item {\x0a border-image: url(:/qss_icons/rc/transparent.png);\x0a}\x0a\x0aQTreeView::branch:!has-children:!has-siblings:adjoins-item {\x0a border-image: url(:/qss_icons/rc/transparent.png);\x0a}\x0a\x0aQTreeView::branch:has-children:!has-siblings:closed,\x0aQTreeView::branch:closed:has-children:has-siblings {\x0a image: url(:/qss_icons/rc/branch_closed.png);\x0a}\x0a\x0aQTreeView::branch:open:has-children:!has-siblings,\x0aQTreeView::branch:open:has-children:has-siblings {\x0a image: url(:/qss_icons/rc/branch_open.png);\x0a}\x0a\x0aQTreeView::branch:has-children:!has-siblings:closed:hover,\x0aQTreeView::branch:closed:has-children:has-siblings:hover {\x0a image: url(:/qss_icons/rc/branch_closed-on.png);\x0a }\x0a\x0aQTreeView::branch:open:has-children:!has-siblings:hover,\x0aQTreeView::branch:open:has-children:has-siblings:hover {\x0a image: url(:/qss_icons/rc/branch_open-on.png);\x0a }\x0a\x0aQListView::item:!selected:hover, QTreeView::item:!selected:hover {\x0a background: rgba(167,218,245, 0.3);\x0a outline: 0;\x0a color: #eff0f1\x0a}\x0a\x0aQListView::item:selected:hover, QTreeView::item:selected:hover {\x0a background: #3daee9;\x0a color: #eff0f1;\x0a}\x0a\x0aQSlider::groove:horizontal {\x0a border: 1px solid #565a5e;\x0a height: 4px;\x0a background: #565a5e;\x0a margin: 0px;\x0a border-radius: 2px;\x0a}\x0a\x0aQSlider::handle:horizontal {\x0a background: #232629;\x0a border: 1px solid #565a5e;\x0a width: 16px;\x0a height: 16px;\x0a margin: -8px 0;\x0a border-radius: 9px;\x0a}\x0a\x0aQSlider::groove:vertical {\x0a border: 1px solid #565a5e;\x0a width: 4px;\x0a background: #565a5e;\x0a margin: 0px;\x0a border-radius: 3px;\x0a}\x0a\x0aQSlider::handle:vertical {\x0a background: #232629;\x0a border: 1px solid #565a5e;\x0a width: 16px;\x0a height: 16px;\x0a margin: 0 -8px;\x0a border-radius: 9px;\x0a}\x0a\x0aQToolButton {\x0a background-color: transparent;\x0a border: 1px transparent #76797C;\x0a border-radius: 2px;\x0a margin: 3px;\x0a padding: 5px;\x0a}\x0a\x0aQToolButton[popupMode=\x221\x22] { /* only for MenuButtonPopup */\x0a padding-right: 20px; /* make way for the popup button */\x0a border: 1px #76797C;\x0a border-radius: 5px;\x0a}\x0a\x0aQToolButton[popupMode=\x222\x22] { /* only for InstantPopup */\x0a padding-right: 10px; /* make way for the popup button */\x0a border: 1px #76797C;\x0a}\x0a\x0a\x0aQToolButton:hover, QToolButton::menu-button:hover {\x0a background-color: transparent;\x0a border: 1px solid #3daee9;\x0a padding: 5px;\x0a}\x0a\x0aQToolButton:checked, QToolButton:pressed,\x0a QToolButton::menu-button:pressed {\x0a background-color: #3daee9;\x0a border: 1px solid #3daee9;\x0a padding: 5px;\x0a}\x0a\x0a/* the subcontrol below is used only in the InstantPopup or DelayedPopup mode */\x0aQToolButton::menu-indicator {\x0a image: url(:/qss_icons/rc/down_arrow.png);\x0a top: -7px; left: -2px; /* shift it a bit */\x0a}\x0a\x0a/* the subcontrols below are used only in the MenuButtonPopup mode */\x0aQToolButton::menu-button {\x0a border: 1px transparent #76797C;\x0a border-top-right-radius: 6px;\x0a border-bottom-right-radius: 6px;\x0a /* 16px width + 4px for border = 20px allocated above */\x0a width: 16px;\x0a outline: none;\x0a}\x0a\x0aQToolButton::menu-arrow {\x0a image: url(:/qss_icons/rc/down_arrow.png);\x0a}\x0a\x0aQToolButton::menu-arrow:open {\x0a border: 1px solid #76797C;\x0a}\x0a\x0aQPushButton::menu-indicator {\x0a subcontrol-origin: padding;\x0a subcontrol-position: bottom right;\x0a left: 8px;\x0a}\x0a\x0aQTableView\x0a{\x0a border: 1px solid #76797C;\x0a gridline-color: #31363b;\x0a background-color: #232629;\x0a}\x0a\x0a\x0aQTableView, QHeaderView\x0a{\x0a border-radius: 0px;\x0a}\x0a\x0aQTableView::item:pressed, QListView::item:pressed, QTreeView::item:pressed {\x0a background: #3daee9;\x0a color: #eff0f1;\x0a}\x0a\x0aQTableView::item:selected:active, QTreeView::item:selected:active, QListView::item:selected:active {\x0a background: #3daee9;\x0a color: #eff0f1;\x0a}\x0a\x0a\x0aQHeaderView\x0a{\x0a background-color: #31363b;\x0a border: 1px transparent;\x0a border-radius: 0px;\x0a margin: 0px;\x0a padding: 0px;\x0a\x0a}\x0a\x0aQHeaderView::section {\x0a background-color: #31363b;\x0a color: #eff0f1;\x0a padding: 5px;\x0a border: 1px solid #76797C;\x0a border-radius: 0px;\x0a text-align: center;\x0a}\x0a\x0aQHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one\x0a{\x0a border-top: 1px solid #76797C;\x0a}\x0a\x0aQHeaderView::section::vertical\x0a{\x0a border-top: transparent;\x0a}\x0a\x0aQHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one\x0a{\x0a border-left: 1px solid #76797C;\x0a}\x0a\x0aQHeaderView::section::horizontal\x0a{\x0a border-left: transparent;\x0a}\x0a\x0a\x0aQHeaderView::section:checked\x0a {\x0a color: white;\x0a background-color: #334e5e;\x0a }\x0a\x0a /* style the sort indicator */\x0aQHeaderView::down-arrow {\x0a image: url(:/qss_icons/rc/down_arrow.png);\x0a}\x0a\x0aQHeaderView::up-arrow {\x0a image: url(:/qss_icons/rc/up_arrow.png);\x0a}\x0a\x0a\x0aQTableCornerButton::section {\x0a background-color: #31363b;\x0a border: 1px transparent #76797C;\x0a border-radius: 0px;\x0a}\x0a\x0aQToolBox {\x0a padding: 5px;\x0a border: 1px transparent black;\x0a}\x0a\x0aQToolBox::tab {\x0a color: #eff0f1;\x0a background-color: #31363b;\x0a border: 1px solid #76797C;\x0a border-bottom: 1px transparent #31363b;\x0a border-top-left-radius: 5px;\x0a border-top-right-radius: 5px;\x0a}\x0a\x0aQToolBox::tab:selected { /* italicize selected tabs */\x0a font: italic;\x0a background-color: #31363b;\x0a border-color: #3daee9;\x0a }\x0a\x0aQStatusBar::item {\x0a border: 0px transparent dark;\x0a }\x0a\x0a\x0aQFrame[height=\x223\x22], QFrame[width=\x223\x22] {\x0a background-color: #76797C;\x0a}\x0a\x0a\x0aQSplitter::handle {\x0a border: 1px dashed #76797C;\x0a}\x0a\x0aQSplitter::handle:hover {\x0a background-color: #787876;\x0a border: 1px solid #76797C;\x0a}\x0a\x0aQSplitter::handle:horizontal {\x0a width: 1px;\x0a}\x0a\x0aQSplitter::handle:vertical {\x0a height: 1px;\x0a}\x0a\x0aQProgressBar {\x0a border: 1px solid #76797C;\x0a border-radius: 5px;\x0a text-align: center;\x0a}\x0a\x0aQProgressBar::chunk {\x0a background-color: #05B8CC;\x0a}\x0a\x00\x00\x03\xac\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x03)IDATX\x85\xed\x95Oh\x5cU\x14\xc6\x7f\xe7e\x88d\xda\xc6\xbd\xa9\x94HW\xb6\x91:(\xae\xd3M\xc5\x0aM@fc\xda7/%\xcdF\x07\xd1$\x8e\xae\xb2P\xa8I\xddd\x99\xc2\xbc\x19\xd3n\x9e S\xc1\xe2\x9f\x85u\x1b\xfc\xd3\xa4\x15\x91RJpJ\xd7%3$\xcd\xe0\xfb\x5c\xbc7M\x90\xbc7\x1d\xe9\xce\xf9V\xf7\xcfw\xce\xfd\xee9\xe7\x9e\x0b=\xf4\xf0\x7f\x87uC\x0e\x82\xa0\x7f\xab\xd1\x18\x97\xd9\x98A\x0e\x18\x8a\xb7\xea\x98\xfd*\xa8e\xb3\xd9Z>\x9f\xdfy\xea\x02\xaa\xe5\xf2[\x98-\x00\xc3\x06\xb7\x047dV\x07p\xc2p\x08\xb3Q\xc1\x08p\xd7`\xee\x9c\xe7}\xf5T\x04\x04A\xd0\xb7\xd5l.\x00\xef\x1b|kaX:{\xfe\xfc\xda~\x5c\xdf\xf7O8p\x118\x05,\xde\xdb\xd8(\xcd\xcf\xcf\x87i\xfe3\x9d\x04\xc4\x87\xbf'i\xd6\x9d\x9c\xbc\x94\xc6\xf5<\xef&\xf0z\xd5\xf7g\x81\x8b\xc3G\x8e\x00\xcc\xa5\xd9\xa4F \x0e\xfb\x97f6s\xaeP\xf8\x1c`ii\xe9\x99\xc1\xc1\xc1i\x93\xde&\x0a9&\xad\xcb\xec\xea\xc3\xcd\xcd\xe5b\xb1\xf8\x08\xa0R\xa9\xcc\x99\xf4\x99\x03\xe3g=\xaf\xd6\xb5\x80 \x08\xfa\xb7\x9b\xcd?$\xfd\xe9NN\xbe\x01p\xe5\xf2\xe5\xc3a&s=\xceu\x0881=\x1a\x9b\xad\xf7\xb5Z\xa7'\xa6\xa6\xea\x00\x15\xdf\xff\xde\xcc\x86\x07\xb2\xd9cI\x85\xe9\xec\xb7\x08\xb0\xd5h\x8c\x0b^p\xa4\x8f\xda7\x0f3\x99\xeb2;\xbe\x8fm{<\xf2w&\xf3M\x10\x04\xfd\x00\xe68\x1f\x22\x1d\xddn6\xcf$\x9d\x93(@fc\xc0Z\xbb\xe0\x9e=t\xe8\x82`\x04)9m\xd1\xdeK[\x8d\xc6\x05\x00\xd7u\x7f\xc3\xec6\xd0\xbd\x00\x83\x9cI?\xedY\x9a \x0au:\xa4\xd0\x22n{\xfe\xa3\xe0\x95\xae\x05`\xf6\x5c\xfb\x9d\xc78\x96\xca\xdf\xb5s\x14q\xdb\xb8\x8f\xd9P\x12=\xd5\xa1\xcc\xba\xea\x94\xfb\xea\x01CJ\x8c\x5c\xb2\x00\xe9\x81I\x87\xf7\xac\xfc\xce\x13\xa6@p\xfb\xf14\xba\xfd\x83\xee\x05\x98\xfd\x8c\xd9\xe8\x9e\x95+\xa9\xfc];\xc7\xe0\xea\xae\x1e\x9d\x04V\xbb\x16 \xa8!\x1d\xf7}\xff\x04\xc0\xc3\xcd\xcde\xcc\xd61S\xca\xe1\x02n\x0e\x1c<\xb8\x0c\xb0R.\xe7\x0c^D\xfa\xbak\x01\xd9l\xb6\x06\xdc\x8d{;\xc5b\xf1Q_\xabu\x1a\xb8\x15Sv\xd3\xd1\xce\xb1\xb4\x86\xe3\xbc\x99\xcf\xe7w$Y\x18}^w\xb6[\xadk]\x0b\xc8\xe7\xf3;8\xce,p*\xee\xedLLM\xd5\x07\xb2\xd9W\x91\xde\x95\xb4\x0a4\x81\xa6`\xd5\xcc\xde\x198p\xe05\xd7u\xef\x03T}\xbf\x04\x9c\x94\xd9\xcc\xf4\xf4t+\xe9\x9c\x8eU^\xf5\xfd\x05\xe0\x03\xa0\xe4z\xdeb'\xbe$\xab\xfa~\xc9\xcc>\x01\x16]\xcf+\xa5\xf1;\x16\xd5\xbd\x8d\x8d\x92\xa4K\xc0B\xd5\xf7\xbf\xabV\xab/'qW\xca\xe5\xdc\x17\x95\xca\x0ff\xf6)\xd1w\xfcq'\xffO\xfc\xceW|\x7f,4[D:\x1a\xb7\xd7\x1b\x82\xbfb'\xcf#\x8d\x125\xa0;2\x9b)\x14\x0a\x89\x85\xf7\x9f\x04\xc0\xe3\x1f\xf2\x8c`\x0c\xc8a\x16\xf5\x09\xa9n\xf0\x8b\xa4\xdav\xabu--\xe7=\xf4\xd0\xc3\xbf\xf1\x0fx\xe5N\xf2\x11\xe4iB\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02J\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdf\x04\x19\x10\x14\x1a8\xc77\xd0\x00\x00\x00\x1diTXtComment\x00\x00\x00\x00\x00Created with GIMPd.e\x07\x00\x00\x01\xaeIDATx\xda\xed\x9bI\x92\xc3 \x0cE#]\xdc\xf6\xc9\xd3\xbb\xaeT\x06&\xe9\x7f\x09\x8c\xd6]2\xef!h \xf0x\xec\xd8\xb1\xe3\xce!\xcc\x8f\x9d\xe7\xf9l\xfc;YB@+p\xa4\x10\xc9\x0a\xcd\x92!\xb3\x80\xa3D\xc8\x8c\xf0\x9e\x12dFpO\x112;\xbcU\x82\xcc\x0en\x15!+\xc1\x8fH\x90\xd5\xe0{%\xe8^\x0a/\xd8\xfb=U V\xf8\xe38\xfes\x5c\xd7E\x11\xf5\xfa\xcd\xdawk\x12\xd4\xbba\xef\x8dC\xc3[C\x11\xa5\x8f\x920\x92\xb7\xc6\xa0\xa8q\xef-\xc1\x92\xaf\xc4b\x1e\x02\xa5\xf1\xe7%\xa1\x94\xc7:\xef\x88W\xef\xa3\x1a\xe9\x99\xf7\xdb\x84\xe86\x09\x22*\x01\xd9\xf3\x90\xff\x02\x9e\x12\x18\xf0_\x87\x80\xc7\xa2\xc7\xdax$\xfc\xfb0\x80,\x85-\x95\xc0\xeay\xf8^`D\x02\x1b\x1e\xbe\x19\xea\x91\x10\x01\xff1\x07\xa06=586\xfc\xeb<@\xd9\x0e\x8f\xce\x09\x8c\xcd\x15\xed<\xa0\x17\x86\xb5\xb3\xa4\x1e\x88\xb4B\xb1\xe0\xe9\x02Z\xe0\x98\xf0!\x02,\xeb\x80\xe9\x05\xb4\xc21%h6x\xb6\x04\x8d\x86g\x9c'\x84\x0ah\x81\x8f\x94\x00\xd9\x0d\x8e\xf6\x00\x00\x88K\x04\xd39.\x90?\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xb6\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x18\x00\x00\x00\x11\x08\x06\x00\x00\x00\xc7xl0\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b,\x0d\x1fC\xaa\xe1\x00\x00\x006IDAT8\xcbc` \x01,Z\xb4\xe8\xff\xa2E\x8b\xfe\x93\xa2\x87\x89\x81\xc6`\xd4\x82\x11`\x01#\xa9\xc9t\xd0\xf9\x80\x85\x1cMqqq\x8c\xa3\xa9h\xd4\x82ad\x01\x001\xb5\x09\xec\x1fK\xb4\x15\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02B\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\x00\x00\x00\x06bKGD\x00\xb3\x00y\x00y\xdc\xddS\xfc\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdf\x04\x19\x10\x17;_\x83tM\x00\x00\x00\x1diTXtComment\x00\x00\x00\x00\x00Created with GIMPd.e\x07\x00\x00\x01\xa6IDATx\xda\xed\x9b\xdb\x0e\xc3 \x0cC\x9bh\xff\xdd\xf6\xcb\xb7\xb7i\x9avIK\xec\x98B^7Q|p(\x85\xb0,3f\xcc\x189\x8c\xf9\xb0m\xdb\xee\xc1\xff\xd9%\x00D\x05W\x021U\xd1,\x18\xd6\x8bp\x14\x08\xebQ|&\x04\xebQx&\x08\xeb]|+\x04\xeb]x+\x08\xbb\x92\xf83\x10\xecj\xe2\x8fB\xb8Uvr]\xd7g'\xf7}/\x01lU\xa3\xff*\x1e\x05!\xe2\x02S\x11_\x05\xc1+m\x7f\xe6wj\x0ad\x8f\xfe\x11q\x99N\xf8\xe5\x02S\x14\xcf\x84\xe0\xd5\xb6\xff%\x92\x91\x0e\x86\x1e\xfd\xa8x\xc6\xc4\xf8\xc9\x05\xae2\xf2UNp%\xdbW@0\x84\xfd[\xed\x8cL\x87\xf74p\x85\x91\xaft\x82\xab\x89gCpE\xf1L\x08\x96\x91\xff\xe8WXv\xfb\xaf\xf3\x80+\x8e<\xd3\x09\xae.\x1e\x0d\xc1{\x10\x8f\x84\xe0\xccN*\xb6O]\x07(\xb6\xefj9\xc9N;W\xcbI\xf6\x9c\xe3\xc8\x9c\xcc\x82\x80\x9cpS\xe6\x00$\x04\xf4\xdb&\xf5k0\xbb\xb3\x08\xf1\xd0\xaf\xc1L'\xb0\xd6\x19\xd4u@\x14\x02s\x91\x05\xd9\x11j\x81\xc0^aB7E\x8f\x8aA\x8b\xa7o\x8a\x1eqB\xc5\xb7\x05\x1c@\x14B\x95\xf8\xaf)\x90\x99\x06-\xeb\x81\xcb\x9c\x0c\x9d\x11\xc3\xaa\x17\xa0\x1e\x8eF\x9d\xc0<\x22\xa7\x1f\x8f\xff\x13\xc7\xae\x14))\x90\xf8\xe6\x04\x84\xf8\x7f\x05\x12e%2\xef\x10*\xc4\x87\x01 !\xa0\x22Z%\xe6\xcb\xe01\x0b%O4>n\xa9\xac2\x08Z\xb1\xb4\x22\x84\x92ry\x15\x08\xad\x97&\xe6\x95\x19@\xc7\xc6\xbc4\x85\x84\xd1\xd5\xb5\xb9\x0c \xcc\x8b\x933F\x8f\x07S!r\xe7\x176+c\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02\xd8\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x02UIDATX\x85\xed\x95MOSQ\x10\x86\x9f\xb9\x1a\x12\xefO\x10\x0d\xc1\xb0\x12M\xb0\xf1\x0f\xc0\x06\xe3\x06HLw\xd0\x0f\x16l\x8d\x01,\xaeXh\x82\x05\xff\xc2=\xad\xec\xae\x89\x16W~,\xc4\xad\xf1\x8bhb\x0c!\xa4\xb1\x86?\xd0\x86\x86&}]\xb4!\xc6p[.\xb0\xb3\xefv\xe6\xcc\xd4\xefD\x0d\xbc\xffe\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\x9f\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x14\x1f\xf9#\xd9\x0b\x00\x00\x00#IDAT\x08\xd7c`\xc0\x0d\xe6|\x80\xb1\x18\x91\x05R\x04\xe0B\x08\x15)\x02\x0c\x0c\x8c\xc8\x02\x08\x95h\x00\x00\xac\xac\x07\x90Ne4\xac\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x01\xd0\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01MIDATX\x85\xed\xd7MN\xc2@\x18\xc6\xf1\xff[\x08\x08\xea\x01\xd0+\x88\x09[\xcf!\xbb\xca\xd8\x1aI\xe0>bBBiI\x97x\x0c\xd7\x84p\x07q\xef\x07\x02\x81\xd7\x85\xd4\x10\xc0\xdd\x10\x13\xed\xb3\x9b\xc9\x9by~\x93n:\xf0\xdf#\x9bk\xcf\x98k\xa0\x01\x94\x81\x03K=\x1f\xc0HDZA\x18F\x80\xee\x02\x88gL\x08\xd4\x80)0\x00^-\x01\x8e\x80\x0a\x90\x07\xba\xdd(\xbaI\x10\xdf\x00\xcf\x18\x0f\x08\x04\x1e\xb3\x8bE\xb5\x1d\xc7cK\xe5\x00\xd4]\xb74w\x9c>\x22\x17\x02&\x88\xa2\x1e\x80\xb36\xd3\x00\xa6K\x91K\xdb\xe5\x00\xed8\x1eK6[\x05f*\xd2L\xf6\xd7\x01g\xc0 \x0c\xc3g\xdb\xe5I\x82 xBd\x80jy\x17\xa0\x80\xea\xfb\xbe\xca\xbf\xb3\x5c\xbe\x01\xc5]\x80_I\x0aH\x01) \x05\xa4\x80\x14\x90\x02R\xc0:`\x82H\xf1\xc7Ik\x8d\xce!0\xd9\x02(\x8c\x80J\xdduK\xfb\xea\xae\xd5j\xa7\xa8V\x80\xe1\x16\xc0\x11\xb9\x07\xf2\xf3L\xe6\xc1\xf7\xfd\x93}\x94gD\xfa@NEZ\xc9\xfe\xe6\xc3\xa4\x03x\xc0l\xf5\xf7\xfab\xa5]\xe4xu\xf3\x9cB'\x8c\xa2[6\x1f&\xc9\xa8o\xcc\x95\x8a4Q=\x07\x0aV\x00_\xdf|\x88\xea]\xb7\xd7\x8b-\x9d\xf9G\xf2\x09>pdA\x95\x87\xdfi\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xc3\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x0b\x07\x09.7\xffD\xe8\xf0\x00\x00\x00\x1diTXtComment\x00\x00\x00\x00\x00Created with GIMPd.e\x07\x00\x00\x00'IDATx\xda\xed\xc1\x01\x0d\x00\x00\x00\xc2\xa0\xf7Om\x0e7\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80w\x03@@\x00\x01\xafz\x0e\xe8\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x01\xd0\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01MIDATX\x85\xed\x97;N\xc3@\x14\x00\xe7EQ\xc2\xf7\x00\x81+\x00R\xeeB\xca\x8d\xedX\x14p\x1fBe\x99\x8d)\xc3\x1dh\xa8\xa3(w \xf4|B>\xf2\xa3p\x8c\x8cL\xb9\x16\x12x*[Zyf%\x17\xef\xc1\x7fG\x8a/\xaa*6\x8e\xfd\x86\xc8\xa5\xc2)\xb0\xe3\xc8\xf3!0\x03\x86\xc6\xf7\xad\x88h)@U%\x89\xe3[\x15\xe9\x03K`\x82\xc8\xab\x13\xbd\xea\x01\xd0\x05\xda\x88\xc4}\xcf\x0b\xf3\x88f~\xc6\xc6\xb1/\x99\xfc\xb1\xd1l\xf6\x8c1s'\xf2-I\x92t\xd2\xcdf\x8cj`\xad}\x00F\x00\x8d\xfc@C\xe4\x12X\xa6p\xeeZ\x0e`\x8c\x99o\xd2\xb4\x07\xacD\xf5\xea\xcb\x9b?(\x9c\x00\x93 \x08\x9e]\xcbs\xc20|\x02&d\xff\xd7\xf7\x00`\x17x\xafJ^\xe0\x0d\xd8\xfb)\xe0W\xa8\x03\xea\x80:\xa0\x0e\xa8\x03\xea\x80:\xa0\x0e(\x06,(L*\x15\xb2\xbfu\x95\x02f@7I\x92NUfk\xed1\xd9x>-\x05\x08\xdc\x00\xedt\xbd\xbe\x8f\xa2\xe8\xa8\x12y\x9a\x8e\x81\x96\xc0\xb0\xe0\xcdPU\x19Y\x1b\xa1\x1a\x00+\xb2\xc5\xe4\xc5\x89]\xf5\x90\xec\xe6-\x85\xc8\xf3\xfd\x8b|1)\xaff\xd6\x9a\xed\xdc~F6)\xbb`\x01LQ\xbd\xf6\x06\x83;G\xdf\xfc#|\x02\x90\xc4u0\xa38\xd1\xd4\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xef\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00Q\x00\x00\x00:\x08\x06\x00\x00\x00\xc8\xbc\xb5\xaf\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b*2\xff\x7f Z\x00\x00\x00oIDATx\xda\xed\xd0\xb1\x0d\x000\x08\x03A\xc8\xa0\x0c\xc7\xa2I\xcf\x04(\xba/]Y\x97\xb1\xb4\xee\xbes\xab\xaa\xdc\xf8\xf5\x84 B\x84(\x88\x10!B\x14D\x88\x10!\x0a\x22D\x88\x10\x05\x11\x22D\x88\x82\x08\x11\x22DA\x84\x08Q\x10!B\x84(\x88\x10!B\x14D\x88\x10!\x0a\x22D\x88\x10\x05\x11\x22D\x88\x82\x08\x11\x22DA\x84\x08Q\x10!B\xfc\xaa\x07\x12U\x04tV\x9e\x9eT\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02V\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdf\x04\x19\x10\x14-\x80z\x92\xdf\x00\x00\x00\x1diTXtComment\x00\x00\x00\x00\x00Created with GIMPd.e\x07\x00\x00\x01\xbaIDATx\xda\xed\x9b[\x92\x02!\x0cEM\x16\xa6\x1b\xd0\xd5\x8e\x1b\xd0\x8d\xe9\x9fe9\xda<\x92{\x13h\xf2=\x95\xe6\x1c\x1eC\x10\x0e\x87\x15+V\xec9\x84\xf9\xb1\xbf\xe3\xf1Q\xf3w\x97\xfb]\xa6\x10P\x0b\x1c)D\xb2B\xb3d\xc8(\xe0(\x112\x22\xbc\xa7\x04\x19\x11\xdcS\x84\x8c\x0eo\x95 \xa3\x83[E\xc8L\xf0=\x12d6\xf8V\x09\xba\xb6\xc2\x13\xf6~\xcb(\x10+\xfc\xf9v{\xe5\xb8\x9eN\x14Q\xef\xdf,}\xb7$A\xbd\x1b\xf6\xd984\xbc5\x141\xf4Q\x12z\xf2\x96\x18\x145\xef\xbd%X\xf2m\xb1\x98\xa7\xc0\xd6\xfc\xf3\x92\xb0\x95\xc7\xba\xee\x88W\xef\xa3\x1a\xe9\x99\xf7\xdb\x82\xe8\xb6\x08\x22F\x02\xb2\xe7!\xff\x05<%0\xe0\xbfN\x01\x8fM\x8f\xb5\xf1H\xf8\xcfi\x00\xd9\x0a[F\x02\xab\xe7\xe1\xb5@\x8f\x046<\xbc\x18j\x91\x10\x01\xffo\x0d@\x15=%86\xfc\xfb:@)\x87{\xd7\x04FqE;\x0fh\x85aU\x96\xd4\x03\x91Z(\x16<]@\x0d\x1c\x13>D\x80e\x1f0\xbc\x80Z8\xa6\x04\xcd\x06\xcf\x96\xa0\xd1\xf0\x8c\xf3\x84P\x015\xf0\x91\x12 \xd5`o\xcf36E\x94j\xb0\x17&b$h\xa69\x1f!A3\xc1GHp;\x14E\xcca\xef|\xd0CQ\xc4\x02\xc6\x18\x09\x9a\x15\x9e%\xe1g\x82\xdai\xc0\xaa\xe7\xad\xdf\xf9\xf5#i\xc8\x99`\x86|E\x01\x96\x9bW\xa8\xc6\xf6\xe6\xddb\xd1\xec=\x8f\xceo\xbe \x91=J#y]\x91\xa9M\xb6n\x89M\x1a\xeb\xa2dk\xf2]_\x95\xcd,\x82vY:\xa3\x84\x90\xeb\xf2Y$X\x1fM\xac'3\xde\x0d\xdb\xed\xa3)\xa4\x8c\xa1\x9e\xcdy\x08a>\x9c\x5c\xb1\xf7x\x02Q\xa0Z\x91w\xd2\x02#\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x01\xec\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01iIDATX\x85\xed\x97;N\xc3@\x10\x86\xbf\xb1\xa2\x84\xe7\x01\x02W\x00\xa4\xdc\x85\x94\x8e\xedD\x14p\x1fBe-\x1bS\x86;\xd0PGQ\xee@\xe8y\x84<\xe4\xa1p\x8c\x8c,%\x056\x05\xf8\xafv\xb5#\x7f\x9f\xad\x95<\x03\xff=\x92\xdd\xa8\xaaXc|G\xe4R\xe1\x14\xd8)\x88\xf3!0\x01\xfa\xae\xef[\x11\xd1\x9c\x80\xaaJd\xcc\xad\x8at\x8090B\xe4\xb5\x10\xbc\xea\x01\xd0\x02\x1a\x88\x98\x8e\xe7\xf5R\x89ZZc\x8d\xf1%\x81?:\xb5Z\xdbu\xddi!\xf0u\xa2(j\xc6\xab\xd5\x10\xd5\xc0Z\xfb\x00\x0c\x00\x9c\xb4\xc0\x11\xb9\x04\xe61\x9c\x17\x0d\x07p]w\xba\x8a\xe36\xb0\x10\xd5\xab/n\xbaP8\x01FA\x10<\x17\x0dO\xd3\xeb\xf5\x9e\x80\x11\xc9\xfd\xfa.\x00\xec\x02\xefe\xc13y\x03\xf6\xd2MmC!\x00\xd6\x18\xddV\xb3)^\x10\xc8\xa6sg\xd3\xe1o\xa4\x12\xa8\x04*\x81J\xa0\x12\xa8\x04*\x81\xad\xfd\xc0\xb6\xff\xf9O\x93\xfd\x0232\x9dJ\x89\xd9_\xb3r\x02\x13\xa0\x15EQ\xb3,\xb2\xb5\xf6\x98\xa4=\x1f\xe7\x04\x04n\x80F\xbc\x5c\xde\x87axT\x0a<\x8e\x87@]\xa0\x9f\xe1&QU\x19X\x1b\xa2\x1a\x00\x0b\x92\xc1\xe4\xa5\x10\xba\xea!\xc9\x9b\xd7\x15B\xcf\xf7/\xd2\xc1$?\x9aY\xeb\xae\xfb\xf63\x92N\xb9\x88\xcc\x801\xaa\xd7^\xb7{W\xd03\xffH>\x01\xac\x18zV\x83\xd7\xe8n\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa6\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1d\x00\xb0\xd55\xa3\x00\x00\x00*IDAT\x08\xd7c`\xc0\x06\xfe\x9fg``B0\xa1\x1c\x08\x93\x81\x81\x09\xc1d``b``4D\xe2 s\x19\x90\x8d@\x02\x00d@\x09u\x86\xb3\xad\x9c\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\x96\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\x00\x00\x00\x02bKGD\x00\xd3\xb5W\xa0\x5c\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x0b\x07\x0c\x0d\x1bu\xfe1\x99\x00\x00\x00'IDAT\x08\xd7e\x8c\xb1\x0d\x00\x00\x08\x83\xe0\xff\xa3up\xb1\xca\xd4\x90Px\x08U!\x14\xb6Tp\xe6H\x8d\x87\xcc\x0f\x0d\xe0\xf0\x08\x024\xe2+\xa7\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa0\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1c\x1f$\xc6\x09\x17\x00\x00\x00$IDAT\x08\xd7c`@\x05\xff\xcf\xc3XL\xc8\x5c&dY&d\xc5p\x0e\xa3!\x9c\xc3h\x88a\x1a\x0a\x00\x00m\x84\x09u7\x9e\xd9#\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa5\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xbb\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00?\x00\x00\x00\x07\x08\x06\x00\x00\x00\xbfv\x95\x1f\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x095+U\xcaRj\x00\x00\x00;IDAT8\xcbc`\x18\x05#\x130\x12\xa3\xa8\xbe}*%v\xfc\xa7\x97;\xd1\xc1\xaa\xa5s\x18\xae_9\x8fS\x9ei4\xe6\x09\x00M\x1d\xc3!\x19\xf3\x0c\x0c\x0cxc~\x14\x8cT\x00\x00id\x0b\x05\xfdkX\xca\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xe4\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x006\x00\x00\x00\x0a\x08\x06\x00\x00\x00\xff\xfd\xad\x0b\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x06bKGD\x00\x7f\x00\x87\x00\x95\xe6\xde\xa6\xaf\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x09*+\x98\x90\x5c\xf4\x00\x00\x00dIDATH\xc7c\xfc\xcf0<\x01\x0b\xa5\x064\xb4O\x85\x87\xcd\xaa\xa5s\x18\xae]9\xcfH+5\x14y\xcc\xd8\xc8\x88$\x03|\x89\xd0O-5\x84\xc0\xd9s\xe7\xe0l&\x86\x91\x92\x14\x91}MTR\x0cM&\xa8\x9fZjF\x93\xe2hR\x1c\x82I\x91\x91\xd2zLK\xc7\x10\xc5\x08l\xc54\xb5\xd4\xd0\xd5c\x83\x15\x00\x00z0J\x09q\xea-n\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xe0\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00Q\x00\x00\x00:\x08\x06\x00\x00\x00\xc8\xbc\xb5\xaf\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b)\x1c\x08\x84~V\x00\x00\x00`IDATx\xda\xed\xd9\xb1\x0d\x00 \x08\x00AqP\x86cQ\xed\x8d\x85%\x89w\xa5\x15\xf9HE\x8c\xa6\xaaj\x9do\x99\x19\x1dg\x9d\x03\x11E\x14\x11\x11E\x14QDD\x14QD\x11\x11QD\x11EDD\x11E\x14\x11\x11E\x14\xf1[\xd1u\xb0\xdb\xdd\xd9O\xb4\xce\x88(\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf6\xcei\x07\x1e\xe99U@\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02\xf8\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x02uIDATX\x85\xed\x96\xcdN\x13Q\x18\x86\x9f\xaf\x15\xd22x\x03VMiX\x89\xa6?\xf1\x06 &\x1a7\x94\x84\xd9\xb63\xc4\x0b0F\x104Q\x16.H\xd1\xb8rC\xb4t\xd8\x92\x98\xe2\xca\xb8\x117,\x8c\xda6\x12\xc0\x10@\x03\x86\x0b\xc0T\xa3q>\x17\xb4\xd1D\xa6e\x0a;\xfbl\xbf\xf7\x9c\xf7I\xe6\xcc\x99\x816m\xfew\xc4O\xd84\xcd\xce\xeepxHD\xd2@J!\x02\x80\xea\x0e\x22\xef\x05\x8a{\xd5jq~~\xfe\xc7\xb1\x0b\xd8\x99\xcc\xb0\x8a\xe4\x04z\x80\x0f\xa2\xba\xa8\x22;\xb5q\x04\xe8\x07.\x00\x1b*2V(\x14\x9e\x1d\x8b\x80i\x9a\xc1\x93\x86\x91S\xd5\x1b\x02/\x08\x06\xc7\xf3\xf9|\xe5\xa0\xaceY\x09\x81)T/\xab\xeat4\x16\x1b\x9f\x9c\x9ct\x1b\xed\x7f\xa2\x99@\xad\xfc:0\x9aw\x9c\x07\x8d\xb2\x85B\xa1\x0c\x5c\x19\xb1\xacQ`\xea\xd3\xe6&\xc0X\xa35\xc1FC;\x93\x19\x06\x1e\x09\x8c\xce:\xce\xc3f\xb2uJ\xe5\xf2R2\x91\xf8.\x22\xf7\x12\xc9d\xa5\x5c.\xafye=\x1f\x81i\x9a\x9d\xdd]]\xab\xc0\xc7Y\xc7\xb9z\xd8\xf2\xbf\xb1\xb3\xd9\x97@\xcf\xd7j\xb5\xcf\xeb`\x06\xbc\x16w\x87\xc3C@L\x82\xc1\x89V\xca\x01\x02\xaa\xb7\x80^\xc30\x06=3^\x03\x11I\xa3Z\xf1:p\x87\xe1\xe9\xdc\x5c\x09XF\xd5\xbf\x00\x90B\xe4u\xab\xe5uD\xf5\x95\xa8^\xf4-\xa0pJ\xfe\xbc\xe7-\xe3\xc2\x17D\x22\xbe\x05\x00T\xd5\xd7My`A \xfb\x1e\xfe\x05vE\xf5\xf4Q\x05T5\x82\xean+\x02oU\xa4\xff\xa8\x02\xc0\x80\xc0\x1b\xdf\x02\x02E\xe0\xbceY\x89V\x9bm\xdbN\x01\xe7\x14\x9e\xfb\x16\xd8\xabV\x8b\xc0\x86\xc0T\x8b\xfd\x22\xae\x9b\x03\xd6;B\xa1\x05\xaf\x90\xe7U\xbc\xb2\xb2\xf2+\x15\x8fo\x03wR\xc9d\xb5T./\xf9i\xb7\xb3\xd9\x09\xe0\x9a\xc0\xc8\x93|~\xd5\xb7\x00@\xa9RYK\xc4\xe3\x06p7\x95L~;\xa4\x84\xd4\xca\xef\x8b\xc8t\xdeq\x1e7\x0a7\xfd\x1aFc\xb1\xf1\xcf[[\xaa\xaa9+\x9b\xbd\x14T\x1d\xaf\xddp\xff`\xdbvJ\x5c7\xa70 \x22\xb9\xb3\xd1\xe8\xed\xa6\xb6\xcd\x02u,\xcbJ\x8b\xea4\xd0\x0b,\x03\x8b\xc0vm|\x86\xfd\x1f\x92>`]\xe0f\xdeq<\x0f^K\x02\xb0\xff\x854\x0ccP\x5c7\x8dH\x0a\xa8\xdf\x13;\x0a\xefD\xb5\xd8\x11\x0a-\xcc\xcc\xcc\xfc\xf4\xb3o\x9b6\xff7\xbf\x01J7\xdd\xdd\x8c\xf1\x82j\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\x93\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\x00\x00\x00\x02bKGD\x00\xd3\xb5W\xa0\x5c\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x0b\x07\x0c\x0c+J<0t\x00\x00\x00$IDAT\x08\xd7c`@\x05\xff\xff\xc3XL\xc8\x5c&dY&d\xc5p\x0e##\x9c\xc3\xc8\x88a\x1a\x0a\x00\x00\x9e\x14\x0a\x05+\xca\xe5u\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa6\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x1b\x0e\x16M[o\x00\x00\x00*IDAT\x08\xd7c`\xc0\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\x81\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x01\x03\x00\x00\x00%=m\x22\x00\x00\x00\x06PLTE\x00\x00\x00\xae\xae\xaewk\xd6-\x00\x00\x00\x01tRNS\x00@\xe6\xd8f\x00\x00\x00)IDATx^\x05\xc0\xb1\x0d\x00 \x08\x04\xc0\xc3X\xd8\xfe\x0a\xcc\xc2p\x8cm(\x0e\x97Gh\x86Uq\xda\x1do%\xba\xcd\xd8\xfd5\x0a\x04\x1b\xd6\xd9\x1a\x92\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xdc\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x10\x00\x00\x00@\x08\x06\x00\x00\x00\x13}\xf7\x96\x00\x00\x00\x06bKGD\x00\xb3\x00y\x00y\xdc\xddS\xfc\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdf\x04\x19\x10-\x19\xafJ\xeb\xd0\x00\x00\x00\x1diTXtComment\x00\x00\x00\x00\x00Created with GIMPd.e\x07\x00\x00\x00@IDATX\xc3\xed\xce1\x0a\x00 \x0c\x03@\xf5\xa3}[_\xaaS\xc1\xc9\xc5E\xe42\x05\x1a\x8e\xb6v\x99^%\x22f\xf5\xcc\xec\xfb\xe8t\x1b\xb7\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf06\xf0A\x16\x0bB\x08x\x15WD\xa2\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x01\xe3\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01`IDATX\x85\xed\xd7;NBa\x10\x86\xe1w@E\xbc,\x00\xdd\x82\x98\x90\x00F\x05W!\xa5\x17b,\xb0C\x12]\x83\x0d\xd8\x88\x15\xdeb\x89{09`\x14IN\x08{\x10{/\x08\x08c\xa1\x87@\xa0<\xc4D\xcf\xd7\xfdS\xfc\xdfS\xce\xc0\x7f\x8f\xf4\xbdT%\x92y\xd8\x16\x95\x04\x82\x1f\x98\xb4\xa9\xe7\x03\xa5\x0a\x925\xf6C\x97\x88\xe8 @U\xd6\x8eK\x17\xaal\x02\x0d\x01S\xd1W;\xda\x05\x99Q\x08\x00\x1e\x90s#\x19\xda\xb1\x10]@$}\x1f\x17\xe4\x0c\xb4\x88\x8c\xc5\x8cd\xb0fG\xb9\x95h\xa6\xecC\xdby`E\x95\xadBj\xe9\x0a\xc0\xd5U\xaa$\x80\x86\xfb\xd3\xb5nw9\x80\x91\x0c\xd6:\xadV\x0ch\x8a\xb0g\xcd\xbb\x00\x84\x05\x01\xf3\xf6 \xfclw\xb9\x95\xe2a\xe4\x090\x01\xff \x00\xbc\x0a\xef\xa3*\xef\xc9\x1b05\x0c\xf0+q\x00\x0e\xc0\x018\x00\x07\xe0\x00\x1c\x80\x03\xe8\x05\xd4\xa5gS\x19a\xa6\x81\xfa\x10\x80V\x15\x02\xd1L\xd97\xaa\xe6\xe5\xf4\xdd<\x10\x10\xa8\x0c\x02\xd4u\x0ax\xd0\xf6\xcd\xeaQan\x14\xe5\xe3\xb8\xf3\xc0DG4k\xcd\xfb\x0e\x93h\xe61\x07\x1a\x07\x9a\x80\x09\xfabO\xbd\xcc\xf2}\x98L(\xe4\x0a\xc9\xf0\xee\xc0ab!\x22\xe9\xd2\xc6\xcf\xde\xbe\x08x\xed\x01P\x17\xa8\xa8\xca\x89\x91\x0a_\xdb\xf4\xe7\x1f\xc9\x17\xa4)p#\xfc\x8b\x13\x87\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02V\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdf\x04\x19\x10\x15\x00\xdc\xbe\xff\xeb\x00\x00\x00\x1diTXtComment\x00\x00\x00\x00\x00Created with GIMPd.e\x07\x00\x00\x01\xbaIDATx\xda\xed\x9b[\x92\x02!\x0cEM\xd67.H\x17\xa0\x0b\xd2\xfd\xe9\x9fe9\xda<\x92{\x13h\xf2=\x95\xe6\x1c\x1eC\x10\x0e\x87\x15+V\xec9\x84\xf9\xb1\xdb\xe9\xf4\xa8\xf9\xbb\xe3\xf5*S\x08\xa8\x05\x8e\x14\x22Y\xa1Y2d\x14p\x94\x08\x19\x11\xdeS\x82\x8c\x08\xee)BF\x87\xb7J\x90\xd1\xc1\xad\x22d&\xf8\x1e\x092\x1b|\xab\x04][\xe1\x09{\xbfe\x14\x88\x15\xfe\xefry\xe5\xb8\x9f\xcf\x14Q\xef\xdf,}\xb7$A\xbd\x1b\xf6\xd984\xbc5\x141\xf4Q\x12z\xf2\x96\x18\x145\xef\xbd%X\xf2m\xb1\x98\xa7\xc0\xd6\xfc\xf3\x92\xb0\x95\xc7\xba\xee\x88W\xef\xa3\x1a\xe9\x99\xf7\xdb\x82\xe8\xb6\x08\x22F\x02\xb2\xe7!\xff\x05<%0\xe0\xbfN\x01\x8fM\x8f\xb5\xf1H\xf8\xcfi\x00\xd9\x0a[F\x02\xab\xe7\xe1\xb5@\x8f\x046<\xbc\x18j\x91\x10\x01\xffo\x0d@\x15=%86\xfc\xfb:@)\x87{\xd7\x04FqE;\x0fh\x85aU\x96\xd4\x03\x91Z(\x16<]@\x0d\x1c\x13>D\x80e\x1f0\xbc\x80Z8\xa6\x04\xcd\x06\xcf\x96\xa0\xd1\xf0\x8c\xf3\x84P\x015\xf0\x91\x12 \xd5`o\xcf36E\x94j\xb0\x17&b$h\xa69\x1f!A3\xc1GHp;\x14E\xcca\xef|\xd0CQ\xc4\x02\xc6\x18\x09\x9a\x15\x9e%\xe1g\x82\xdai\xc0\xaa\xe7\xad\xdf\xf9\xf5#i\xc8\x99`\x86|E\x01\x96\x9bW\xa8\xc6\xf6\xe6\xddb\xd1\xec=\x8f\xceo\xbe \x91=J#y]\x91\xa9M\xb6n\x89M\x1a\xeb\xa2dk\xf2]_\x95\xcd,\x82vY:\xa3\x84\x90\xeb\xf2Y$X\x1fM\xac'3\xde\x0d\xdb\xed\xa3)\xa4\x8c\xa1\x9e\xcdy\x08a>\x9c\x5c\xb1\xf7x\x02G\xb0[\x07:D>\x01\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa0\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f\x0d\xfcR+\x9c\x00\x00\x00$IDAT\x08\xd7c`@\x05s>\xc0XL\xc8\x5c&dY&d\xc5pN\x8a\x00\x9c\x93\x22\x80a\x1a\x0a\x00\x00)\x95\x08\xaf\x88\xac\xba4\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x03\xcc\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x03IIDATX\x85\xed\x96\xcdk\x5cU\x18\xc6\x7f\xcf\x9d\x99\x98\xe9d\x16\xd2\x9d\xa9\x92\x0e\xa1\x0b\xd3\xd8v\xf0\x1fh\x11\x14+4\x81\xdeU\xca\xcc\xbd\xa5T\x5c\x04Dm:\xd5M\x16.\xe2DW\xb3\x1b\xeax\xa7\x18\xb2\x08\xc8T\xb0\x88\x1b\xeb\xc6\x85h\xf3US\xa4\xb4U\x9aRp%\x990\xa56\xb9\xaf\x8b\xf9h\xc1\xcc\x0cS\xbak\x9e\xdd9\xe79\xef\xfb\xbb\xef}\xef9\x17v\xb5\xab\xe7]\xea\xc5\xec\xban\xdf@<>.i\x0cH\x1b\x0c\x02`\xb6\x8etMP\xa9\xd6j\x95\x85\x85\x85\x7f\x9f9\x80\x9f\xc9\x9c4)/\xd8\x0f\xac\xca\xec\xaaI\xeb\x8d\xe5A\xe0(0\x0a\xdc2i*\x08\x82o\x9e\x09\x80\xeb\xba\x91d\x22\x917\xb3\x0f\x04\xdf\x13\x89\xe4J\xa5\xd2\xf2N^\xcf\xf3\x0e\x0bf0{\xd3\xccf\x87R\xa9\xdc\xf4\xf4t\xd8)~\xb4\x1b@#\xf9\xfb\xc0\xb9R\xb9\xfcy'o\x10\x04K\xc0[\xa7=\xef\x1c0\xf3\xe7\xed\xdb\x00S\x9d\xf6t\xac\x80\x9f\xc9\x9cDZ\x10|T*\x97\xbf\x00\x98\x9c\x9c|asc\xe3]\x83\x09\xd5K\x0ef+\xe68s\xc9d\xb2X(\x14\x1e\x02\xf8\xd9\xec\x14\xf0\x99I\xe3A\x10Tz\x06p]\xb7o`\xcf\x9e\x1b\xc0\x1f_\x95\xcbo\x03\x9c\x99\x98\xd8\xb7\x1d\x8b]\xc1l\x14\x08\x01\xa7a\x0f\x01G\xb0\xe2lm\x1d\xbf87\xb7\xde\x80\xf8\x01\xd8\xbfY\xab\x8d\xb4kLg\xa7I\x80\x81x|\x1cH)\x12\xb9\xd0|\xf2\xedX\xec\x8a\x99\x1d\xdca\xaf\xd3\xa0\x18\x0d\xa3\xd1\xef\x5c\xd7\xed\x03p\xcc\xce\x03\xc3\x89D\xe2D\xbbxP\x04\xf0}?\x0d\xbcj\xf0m\xcf\x00\xd5Z\xad\x02\xdc\x12\xcc\x00\x14\x0a\x85\x87\xce\xd6\xd6q\x07V\x1b\x96\xc7\xaf\xa3\xde\xf9HZ\xde\x0e\xc3w\x1a\x87\x8e\x14\x86y\xe0f\xac\xbf\xffr\xbb<\x91v\x0bkkk\xdb\xe9C\x87\xee\x02\x9f\xa4\x8f\x1c\xa9-.-\xfd|muuc\xf8\xc0\x81R_4\xfa\xb7I{\x05/\x02\x8f\x0c\x16\x1d\x98\xd9\xac\xd5\xde\x9b\x9f\x9f\xff\x07\xc0\xcff/\x00g\x04\xa7/\x96J7\xda\xe5\xe9\xda\xe5^&\x93\x97\xf4\xa1\xa4\x5c)\x08f\xbb\xf9\x01\xf9\xd9l\x0e\xf8T\xd2l)\x08r\x9d\xcc]o\xc3\xa1T*\xf7\xd7\x9d;ffy/\x9b}#b\x96k\x9cp\xff\x93\xef\xfbi\x85a\xde\xe0\x98\xa4\xfc+CC\x1fw\xa5\xedfh\xca\xf3\xbc1\x99\xcd\x02\xc3\xd4?\xb3\xab\xc0\xdd\xc6\xf2\xcb\xd4\x7fHF\x80\x9b\x8d\xdb\xb3m\xe3=\x15\x00\xd4o\xc8D\x22qBa8\x86\x94\x06\x9a\xe7\xc4\xba\xc1o2\xab\xc4\xfa\xfb/\x17\x8b\xc5G\xbd\xc4\xdd\xd5\xae\x9eo\xfd\x07\xb0\xd0<\xea\x1c\xa0\xa5_\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa6\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa0\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x1b)\xb3G\xee\x04\x00\x00\x00$IDAT\x08\xd7c`@\x05s>\xc0XL\xc8\x5c&dY&d\xc5pN\x8a\x00\x9c\x93\x22\x80a\x1a\x0a\x00\x00)\x95\x08\xaf\x88\xac\xba4\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x01\xed\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01jIDATX\x85\xed\x97\xcbN\xc2@\x14\x86\xbfC\x08x}\x00\xf4\x15\xd4\x84w\x91ei\x0bq\xa1\xef#\xae\x9aq\xa8K|\x077\xae\x09\xe1\x1d\xc4\xbd\x17\xe4\x92\x1e\x17\xa5\xa6\x06\xd8\x98!\x18\xed\xbf\x9av&\xfd\xbeN\xa6\xcd9\xf0\xdf#\xf9\x0bU\x15kLP\x12\xb9T8\x05v\x1cq>\x04\x86@\xc7\x0b\x02+\x22\xba$\xa0\xaa\x12\x1bs\xab\x22M`\x02\xf4\x11yu\x82W=\x00\xea@\x15\x11\xd3\xf4\xfdv&Q\xce\xd6Xc\x02I\xe1\x8f\xa5r\xb9\xe1y\xde\xc8\x09|\x918\x8ek\xc9|\xdeC5\xb4\xd6>\x00]\x80R\xb6\xa0$r\x09L\x128w\x0d\x07\xf0\xbb\x86gi\xb7\xdbO@\x9f\xf4|}\x17\x00v\x81\xf7M\xc1sy\x03\xf6V\x09l%\x85\xc0\xd6\x05\xca\xeb&\xac1\xban\xee'\xf1\xc3PV\xdd\xdf\xfa\x0e\x14\x02\x85@!\xb0\xf6?\xb0\xee\xbbu\x9d\xad\xef@!\xf0\xab\x04\xc6\xe4*\x95\x0df\x7f\xc1Z\x12\x18\x02\xf58\x8ek\x9b\x22[k\x8fI\xcb\xf3\xc1\x92\x80\xc0\x0dPMf\xb3\xfb(\x8a\x8e6\x02O\x92\x1eP\x11\xe8\xe4\xb8iTU\xba\xd6F\xa8\x86\xc0\x94\xb41yqBW=$}\xf3\x8aB\xe4\x07\xc1E\xd6\x98,\xb7f\xd6z\x8b\xba\xfd\x8c\xb4Rv\x9110@\xf5\xdao\xb5\xee\x1c=\xf3\x8f\xe4\x13\xfb6zV\x11\xde\xcf\xd8\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x00\xa6\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f \xb9\x8dw\xe9\x00\x00\x00*IDAT\x08\xd7c`\xc0\x06\xe6|```B0\xa1\x1c\x08\x93\x81\x81\x09\xc1d``b`H\x11@\xe2 s\x19\x90\x8d@\x02\x00#\xed\x08\xafd\x9f\x0f\x15\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02\xd4\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x02QIDATX\x85\xed\x96AKTQ\x14\xc7\x7f\xe7\x8d\xb8\xd0&0wi\x84\xe1\xaa)\x90A\xc7\x92^\xa0\x1b\xa1\x8d\x0a\xf5\x19Z;3\xda\xd8j\x16A6\x83\xf3\xbe\x87A\x8d\xad\xc2M\xf6\x14\xf4\x0d\x99H\x0e\x11\xe2\xaa\x11\xdb\x184\xa8\x0b\xc3wZ\xccH\x10\xf3t\xee\xe8\xae\xf9o\xef9\xfc\x7f\xf7\xdc{\xcf=\xd0TS\xff\xbb\xc4$8\x92.\xb6v\x86\x0f'T\x18\x07\x8d\x02]\xd5\xa5\x12\xcag\x11\xc9\xef\x97\xdb\xf3\xc5t\xe4\xf8\xd2\x01lg\xed1*\x19\xa0\x07\xe4\x0b\xaaKX\x94\x00D\xb5K\xb1\x86A\xef\x22\xec\x082\xedN\xc6\xde\x5c\x0a\xc0\x93\xf9\xf9\xd0\x8f\xdd\x9b\x19\x948\xf0^\x95\xd4Jbp\xb3V\xec\x90S\xe8\x0b\xf9:\x8b0\x0ad\x97\xcb\xb1\x14i\xf1\xeb\xdddM\xd9\x8e7g\xe7\xbc\x93\x87\xceZ\xb2\xee\x9c\x9c7e\xe7\xbc\x13;\xe7e\xce\x8b=\xb3\x02\xd5\xb2\xbf\x16$\xe9\xc6cs\xf5\x02Tr\xbdi\x94W\x08\x13\xcb\x93\x83yc\x80H\xba\xd8z\xed\xea\xc1WA\xbf\xb9\xf1{\x8fL\xccO\xf5\xc0),\x8aj\xcf\xcf\xf2\x95H\xd0\xc5\xb4\x82\x92;\xc3\x87\x13\xc0-_e\xa6\x11s\x00\xcb\x97g@oG\xf8`,0&h\xa1\xf2\xd4\xd8\x0c\xbap\xf5\xc8M\x0cl\xa8\xb2%`\x0e\x00\x1a\x15\xf4c\xa3\xe6\xa7\x12\xf8\x80\xd0\xdf\x00\x00\xd7\x15)]\x14@a\x97\xbf\x0d\xcb\x08\x00\xc4\xacS\xd64\x10\x11 \xb0\x17\x9c\x05\xb0\x87O\xf7E\x01\x14\xed\x02\xf6\xcc\x01\x94O\x0a\xc3\x17\x05\x00F\x80\x821\x80\x88\xe4E\xb83\xe4\x14\xfa\x1au\xb6\x9d\xd5(p\x1b\xd1w\xc6\x00\xfb\xe5\xf6<\xc2N\xc8\xd7\xd9\x86\xdcU\x05\xb52\xc0\xf6Q[\xcb\x821@1\x1d9Ve\x0aa\xd4\xceyS\xa6\xfev\xceK\x01#\xa2~r\xfdi\xffoc\x00\x80\x95\xf8\xe0[ \x0b\xcc\xd6\x0d\xa1*\xf6\xdc\xda\x0c\x22/D\xc8\xb8\x89\xfb\x81\xe5\x87z\xe6\x81\xb4Zv\xb8\xf0\x12a\x1aX\x14\xb5Rnb`\xa3V\xa8\xed\xacF\xabe\x1f\x11!\xe3\xfe\x8a=?\xef;6\x18H\xbcq\x94,\xd0\xab\xca\x96\x08K\x08\xdf\x01PnPy1\x11`[\xd4O\x9e\xb7sc\x00\xa8\xfc\x90\x1d\xe1\x831\xaa#\x99 \xdd\x15\x7f-\x89\xca:\x96\xe6\x8f\xdaZ\x16\xce:\xf3\xa6\x9aj\xea_\xfd\x01\xd3\x1c\xd9\x7f^\xb93\xcd\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02\x00\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01}IDATX\x85\xed\x97;N\x02Q\x14\x86\xbf\x83(>\x17\xa0nAMHxD\x9dq\x15Z\xfa\x8a\xb1\xd0\x0eHt\x0d6`\xa3V>c\xa9{0\x194\x82$\x84\xb8\x07\xb5\xf7\x81\x82p,t\x08\x04\xc3\x14\xceX\xe8|\xdd\xbd\xe7\xe6\xfe_ns\xcf\x81\xff\x8e\xb4\xacT\xc5\xc8\xe4\x96De\x0da\x1c\xe8u)\xe7\x15\xe5\x16d\xd7JF\x8f\x11\xd1v\x01U\x99\xd9\xce\x1f\xa9\xb2\x00\xbc\x09\x14\x15}r#]\x90A\x850\x10\x029\xb4\x12\xd1\x15[\xa2!`\xa4\xaf\x97\x059\x00\xbdD\x82sV\x22r\xefF\xb8\x8d\x99)\x0c\xa3\xb53`J\x95\xc5l*~\x02\x10hX\xaa\xac\x01o]\xef\x81Y\xb7\xc3\x01\xacD\xe4\xbe^\xad\xce\x01\x15\x11\xd6\xed\xfd\x86\x00\xc2\x98@\xf1b#\xf6\xe0v\xb8\xcd\xe5\xa6q\x07\x14\x81\xf1v\x01\xe8Sx\xf1*\xbc\x89g\xa0\xdf^\x04\x9dN\x9b\xe9\x9c:\x9d\xe9\x84\x95\x8cK\xa7z\xa0S\xf17\xf0\x05|\x01_\xc0\x17\xf0\x05|\x01_\xc0\xb1\x1fp\xfa\xcf\x7fJ\xf3\x0b\x94\xa5\xa9S\xf1\x90\x01\xa0\xfc\x8d\x80\xde*\x84\xcdLa\xd8\xab\xe4\xc9\xf4\xd5(\x10\x16(\xb5\x0bh`\x0f\x08\xa1\xb5\xf3\xe9\xad\xec\x88\x17\xe1\xddt\x9d\x01=u\xd1]{\xbfe0137\xfb\xa0\xcb@\x05(\x82>\xba\x13/C|\x0e&=\x0a\xfb\xd9Dl\xb5m0\xb1%\x8ct~\xfe\xabo\x9f\x00\xfa\xdc\x11\xa0,PR\x95\x1d+\x15;u\xe9\xce?\xc2\x07\xd1\xbcu\x94\xcf\xbc\x8d\xf9\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x03\xa5\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x03\x22IDATX\x85\xed\x96MlTU\x14\xc7\x7f\xe7\x0d\xa9\x09\xcc\x90Pv\xb6\xc6``\xe3\xa3\x864\xf4\xc3\xc6g\xa4\x1b\xa2\x98@\x13]\xc9\x1a6\xda\x84~Y\x5c\xcd\xce:\xa43\x09\xcb\xaee\x83\x89\x19L\x04\xc3\xc6:\x98\xb4o\x22bK'\xc64\xac\x9c\x067\x94t\x98\x92P:\xef\xef\xe2M\xa75\x99\xe9\xccCv\xf4\xbf\xba\xe7\xbds\xef\xf9\xdds\xee\x17\xeciO\xaf\xba,\x8a\xb3\x9b,\xb4\x1dN\xac\x0f\xc98\x07\xea\x06:\xaa\xbf\x8a\x88\xdf\xcd,\xfb\xa8t [H\xba\x1b/\x1d\xc0\xcb\xcc\x7f\x82,\x05\x1c\x01\xbb\x8f4\x8bC\x11\xc0\xa4\x0e\xe1\x9c\x02ua<0l\x22w\xa9\xf7\xfb\x97\x02\xf0\xe9\xf5\xeb\xb1\x7fV\xdeL!F\x80\x9f$&\x7f\x1d\xed[\xa8\xe7;\x90\xc9\x9f\x88\x05\x9a\xc28\x0d\x5c\xb9S\xea\x9d$iA\xab\x93\xac+/\xe3O{i\xbf\xf2~f~\xac\xe5>i\x7f\xdcK\xfb\x15/\xed\xa7\x9a\xf9\xee\x9a\x81j\xda\xbf3l,7\xd2;\x0d\xf0\xe1\xd5\xe5\xd7\x9e<\x7f|\xd1\xe03Y\xd0\x15\x0eb\x8b\x18\xd7\xe2\xb1\xf6\x99[\xc3\xc7\x9eU\xc1'\x10\xdf`\x0c\xdd\xb9\xd4\x97\x8d\x0c\xe0&\x0bm\xed\x07\xcb\x7f\x1a\xfa+7\xd2\xff\x11\xc0\x07W\xe7;+\x9b\xceMP\x17X\x00r\xaa\xc3\x84mc1\x16\xd3\x99\xd9\xe1\xfe\x22\xc0{\x99\xfcm\x93\x8e\xac\x96\xe2n\xa3\x85\xe94\x028\x9cX\x1f\x02\xde\x0ad\x97\xb7f^\xd9tnb:\x1ezhG\xdfZ\xbb\xab\xb2\xc9\x8fn\xb2\xd0\x06\xe0\x04\xf6%p\xf4P\xa2|\xb6Q\x9c\x86\x00\xe1Vcak\xc1\x95+\xab\x17@]h\x97\xb2\x09\x03{\xa7\xfd`\xf9\x02@n\xb4\xe7\x9e\xc4\x92At\x00P\xb7\xa1_jf`\xe7\xc3T\xef.A\x00\x9c\xdf\xb2\x0d~\xc68\xf9\x02\x00\xbc.\xacX\xb3L\xee\x7f\xd3^_\x06\x0e\xc8\xdd\x01\xb4\xc2\xf6\x81\x15\x09\x00,\xdaIY7\x80\x99\x11f%2\xc0C\x02:k\x96\xac\xd0j\x09$\x96\xb6mu\x00\x0f\xa3\x03\x88\xdf\x04\xa7\xb6=\xf5m\xab%0\xb3k;>\x0d\x02\xf9\xc8\x00f\x965\xe3\xf8@&\x7f\x02 \x1ek\x9f\xc1X\xc4\xd0.\xd1%\xe3\x8f\xd5R|\x06\xc0\xcb\xccu\x03oc\xfa!2\xc0\xa3\xd2\x81,\xc6\x83X\xa0)\x80[\xc3\xc7\x9e\xc5b:\x03\xdc\xafF\xab\x95\xa3\xba\xf2\x11,TT\xf9\xb8\x90t7\x90\x0c9)`\xf9\xe9\xfe}7\x22\x03\x14\x92\xee\x86\xc48\xc6i/\xed\x8f\x03\xcc\x0e\xf7\x17W\xd7\xe2=\xc0\x17R\x90\x07\xd6\x81u\xa4\xbc\x99>\x7f\xbc\x16\xef\x9b\x1b\x19X\x01\xf0\xd2\xfe$0h\x0a\xc6\xee^<\xf9\xbcQ\x9c\xa6\xf2\xd2~\xaaz\xb1\x8c\xb7\xd4A2oz\xferx\x81\xf9S\xcd\xdc\x9bo\xb3\xa4\x1c/\x91\xff\x1ac\x02\xb8mr&s\xa3=\xf7\xea\xc2f\xe6\xba\xabi\x1f4#\x95[\xeb\xfd\xaa\xd9u\x1c\xe1A\xe2\x9fC\x5c\x01\x8eJ,\x991\x8b\xf17\x00\xe2\x0d\xc2\x1d\xe3\x02\xcb\xa6`,7\xfan\xc3\x85\xf7B\x00\x10\xde\x90\x87\x12\xe5\xb3T\x9fd\x86u\x86\xf1U4\xd9]\x1ce\x9f\xee\xdfw\xe3\x7f\xd5|O{z\xe5\xf4/\x95?G\xacm\xe50s\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x02\x02\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x09pHYs\x00\x00\x0d\xd7\x00\x00\x0d\xd7\x01B(\x9bx\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01\x7fIDATX\x85\xed\x97\xcbJBQ\x14\x86\xbfe\xa5\xd9\xe5\x01\xacW\xc8@(\xa3\xd2\x9e\x22\x87\xdd\x88\x0663\xa1\x9e\xa1\x896\xa9F]iX\xef\x10\x1c\x8d\xb4@\xa2w\xc8\xe6]\xac,W\x83:\xa2\x1c\xcf$\xb6\x18u\xfe\xd9^\x1b\xf6\xf7\xb1`o\xf6\x82\xff\x1eiZ\xa9J,[X\x14\x95$B\x18\xe85\xc4yA\xb9\x05\xd9\xb1\xd6\xc6\x8f\x10Q\xa7\x80\xaa\xccl\x15\x0fU\x99\x07^\x05J\x8a>\x9a\xa0\x0b2\xa0\x10\x01\x02 \x07Vj|\xd9\x96\xa8\x0b\xc42\x97K\x82\xec\x83\xe6\x91\xee\x84\x95\x1a+\x9b\x80\xdb\x89g\xafC\xe8\xc7)0\xa5\xcaB.=q\x0c\xe0\xab[\xaa$\x81\xd7\xaew\xdf\xaci8\x80\x95\x1a+\xd7\xaa\xd5\x04\xf0&\xc2\xaa]\xaf\x0b \x8c\x08\x94\xce\xd7\xa3\xf7\xa6\xe1v\xf2\x1b\xb1;\xa0\x04\x84\x9d\x02\x10Txn\x17\xbc!O@_+\x81\x8e\xc4\x13\xe8\xb8@\xb7\xdbF\xb8\x86\xc7\x09\x82\xe0\x1e\x91.\xaa\x85e\x02YT_\xd6\x05\x9ff<~\x06r\xf10\xbd\xaa\xef\x1b\xa3\xab:\xdf\xa5e\xed\xfc\x97\xf6)\xdew\x17\x7f#\x89@\x22\x90\x08$\x02\x89@\x22\x90\x08\xac\xdc\x0f\xac\xfa\x9f\xff4\xb3O\xa0\x8fH\xee\xcb\xa63\xa2\xb7\x05\xf4\x17\x04\x14\xee\x80\xe2y\xb9\x9c_\x17\xbbR\xa9\xec\xa1Z\x04n\x17\x04<\x91K`c\x94J]W\xab\xd5\xddu\xc0S\x22\x1d \xa3\x22\x8dx~\xfe`\xd2\x04|`8\xd9\xbd>:\xa1\x8b\xecLV\x9eQh\x86\xd6\x9e1\x7f0\x89\xabUc\x8eU\xa4\x8e\xea\x01\x90u\x22\xf0\xf1\xceoQ\xbdh\xb5\xdb\x91\xa3{\xfe\x91\xbc\x03\x16qj'Dt\xfeO\x00\x00\x00\x00IEND\xaeB`\x82" 13 | qt_resource_name = b"\x00\x09\x09_\x97\x13\x00q\x00s\x00s\x00_\x00i\x00c\x00o\x00n\x00s\x00\x0a\x09$M%\x00q\x00d\x00a\x00r\x00k\x00s\x00t\x00y\x00l\x00e\x00\x09\x00(\xad#\x00s\x00t\x00y\x00l\x00e\x00.\x00q\x00s\x00s\x00\x02\x00\x00\x07\x83\x00r\x00c\x00\x11\x0a\xe5l\x07\x00r\x00a\x00d\x00i\x00o\x00_\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00.\x00p\x00n\x00g\x00\x09\x06\x98\x83'\x00c\x00l\x00o\x00s\x00e\x00.\x00p\x00n\x00g\x00\x11\x08\x8cj\xa7\x00H\x00s\x00e\x00p\x00a\x00r\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00.\x00p\x00n\x00g\x00\x1a\x01!\xebG\x00s\x00t\x00y\x00l\x00e\x00s\x00h\x00e\x00e\x00t\x00-\x00b\x00r\x00a\x00n\x00c\x00h\x00-\x00m\x00o\x00r\x00e\x00.\x00p\x00n\x00g\x00\x0a\x05\x95\xde'\x00u\x00n\x00d\x00o\x00c\x00k\x00.\x00p\x00n\x00g\x00\x13\x08\xc8\x96\xe7\x00r\x00a\x00d\x00i\x00o\x00_\x00u\x00n\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00.\x00p\x00n\x00g\x00\x15\x0f\xf3\xc0\x07\x00u\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\x00\x1f\x0a\xae'G\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00u\x00n\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\x00\x0f\x0c\xe2hg\x00t\x00r\x00a\x00n\x00s\x00p\x00a\x00r\x00e\x00n\x00t\x00.\x00p\x00n\x00g\x00\x16\x01u\xcc\x87\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00u\x00n\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00.\x00p\x00n\x00g\x00\x14\x0b\xc5\xd7\xc7\x00s\x00t\x00y\x00l\x00e\x00s\x00h\x00e\x00e\x00t\x00-\x00v\x00l\x00i\x00n\x00e\x00.\x00p\x00n\x00g\x00\x11\x08\x90\x94g\x00c\x00l\x00o\x00s\x00e\x00-\x00p\x00r\x00e\x00s\x00s\x00e\x00d\x00.\x00p\x00n\x00g\x00\x14\x07\xec\xd1\xc7\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00.\x00p\x00n\x00g\x00\x0e\x0e\xde\xfa\xc7\x00l\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\x00\x12\x07\x8f\x9d'\x00b\x00r\x00a\x00n\x00c\x00h\x00_\x00o\x00p\x00e\x00n\x00-\x00o\x00n\x00.\x00p\x00n\x00g\x00\x0f\x02\x9f\x05\x87\x00r\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\x00\x0e\x04\xa2\xfc\xa7\x00d\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\x00\x11\x08\xc4j\xa7\x00V\x00s\x00e\x00p\x00a\x00r\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00.\x00p\x00n\x00g\x00\x10\x01\x07J\xa7\x00V\x00m\x00o\x00v\x00e\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00.\x00p\x00n\x00g\x00\x19\x08>\xcc\x07\x00s\x00t\x00y\x00l\x00e\x00s\x00h\x00e\x00e\x00t\x00-\x00b\x00r\x00a\x00n\x00c\x00h\x00-\x00e\x00n\x00d\x00.\x00p\x00n\x00g\x00\x1c\x01\xe0J\x07\x00r\x00a\x00d\x00i\x00o\x00_\x00u\x00n\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\x00\x14\x06^,\x07\x00b\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00-\x00o\x00n\x00.\x00p\x00n\x00g\x00\x0f\x06S%\xa7\x00b\x00r\x00a\x00n\x00c\x00h\x00_\x00o\x00p\x00e\x00n\x00.\x00p\x00n\x00g\x00\x0c\x06A@\x87\x00s\x00i\x00z\x00e\x00g\x00r\x00i\x00p\x00.\x00p\x00n\x00g\x00\x10\x01\x00\xca\xa7\x00H\x00m\x00o\x00v\x00e\x00t\x00o\x00o\x00l\x00b\x00a\x00r\x00.\x00p\x00n\x00g\x00\x1c\x08?\xdag\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00u\x00n\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00f\x00o\x00c\x00u\x00s\x00.\x00p\x00n\x00g\x00\x0f\x01\xf4\x81G\x00c\x00l\x00o\x00s\x00e\x00-\x00h\x00o\x00v\x00e\x00r\x00.\x00p\x00n\x00g\x00\x18\x03\x8e\xdeg\x00r\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\x00\x1a\x0e\xbc\xc3g\x00r\x00a\x00d\x00i\x00o\x00_\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\x00\x17\x0c\xabQ\x07\x00d\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\x00\x11\x0b\xda0\xa7\x00b\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00.\x00p\x00n\x00g\x00\x1a\x01\x87\xaeg\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00i\x00n\x00d\x00e\x00t\x00e\x00r\x00m\x00i\x00n\x00a\x00t\x00e\x00.\x00p\x00n\x00g\x00\x17\x0ce\xce\x07\x00l\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\x00\x19\x0bYn\x87\x00r\x00a\x00d\x00i\x00o\x00_\x00u\x00n\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00f\x00o\x00c\x00u\x00s\x00.\x00p\x00n\x00g\x00\x1a\x05\x11\xe0\xe7\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00f\x00o\x00c\x00u\x00s\x00.\x00p\x00n\x00g\x00\x17\x0f\x1e\x9bG\x00r\x00a\x00d\x00i\x00o\x00_\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00f\x00o\x00c\x00u\x00s\x00.\x00p\x00n\x00g\x00 \x09\xd7\x1f\xa7\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00i\x00n\x00d\x00e\x00t\x00e\x00r\x00m\x00i\x00n\x00a\x00t\x00e\x00_\x00f\x00o\x00c\x00u\x00s\x00.\x00p\x00n\x00g\x00\x0c\x06\xe6\xe6g\x00u\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\x00\x1d\x09\x07\x81\x07\x00c\x00h\x00e\x00c\x00k\x00b\x00o\x00x\x00_\x00c\x00h\x00e\x00c\x00k\x00e\x00d\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g" 14 | qt_resource_struct = b"\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x18\x00\x02\x00\x00\x00\x01\x00\x00\x00+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00J\x00\x02\x00\x00\x00'\x00\x00\x00\x04\x00\x00\x04P\x00\x00\x00\x00\x00\x01\x00\x00\x80e\x00\x00\x03D\x00\x00\x00\x00\x00\x01\x00\x00y\xd7\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x01\x00\x00f\x5c\x00\x00\x01\xd4\x00\x00\x00\x00\x00\x01\x00\x00ov\x00\x00\x05\xa4\x00\x00\x00\x00\x00\x01\x00\x00\x8bH\x00\x00\x03\xa2\x00\x00\x00\x00\x00\x01\x00\x00{\xa3\x00\x00\x04\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x83,\x00\x00\x02\xd6\x00\x00\x00\x00\x00\x01\x00\x00w\xcb\x00\x00\x04\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x85\x86\x00\x00\x02\xfa\x00\x00\x00\x00\x00\x01\x00\x00xo\x00\x00\x06J\x00\x00\x00\x00\x00\x01\x00\x00\x90\xbb\x00\x00\x00\xf6\x00\x00\x00\x00\x00\x01\x00\x00g\x16\x00\x00\x042\x00\x00\x00\x00\x00\x01\x00\x00\x7f\xe0\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x7f6\x00\x00\x03\xe0\x00\x00\x00\x00\x00\x01\x00\x00~\x9f\x00\x00\x00|\x00\x00\x00\x00\x00\x01\x00\x00c^\x00\x00\x06\xfe\x00\x00\x00\x00\x00\x01\x00\x00\x98n\x00\x00\x02\xac\x00\x00\x00\x00\x00\x01\x00\x00w1\x00\x00\x02\x5c\x00\x00\x00\x00\x00\x01\x00\x00t\x97\x00\x00\x03j\x00\x00\x00\x00\x00\x01\x00\x00z\xbf\x00\x00\x04v\x00\x00\x00\x00\x00\x01\x00\x00\x81E\x00\x00\x00\x94\x00\x00\x00\x00\x00\x01\x00\x00e\xac\x00\x00\x024\x00\x00\x00\x00\x00\x01\x00\x00r=\x00\x00\x03\x1c\x00\x00\x00\x00\x00\x01\x00\x00y\x18\x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00i\x5c\x00\x00\x07\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x99\x10\x00\x00\x06\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x96h\x00\x00\x01l\x00\x00\x00\x00\x00\x01\x00\x00l\xdb\x00\x00\x00T\x00\x00\x00\x00\x00\x01\x00\x00_\xae\x00\x00\x06\x12\x00\x00\x00\x00\x00\x01\x00\x00\x8d\xe3\x00\x00\x02\x06\x00\x00\x00\x00\x00\x01\x00\x00qJ\x00\x00\x05|\x00\x00\x00\x00\x00\x01\x00\x00\x8a\xa4\x00\x00\x05\xde\x00\x00\x00\x00\x00\x01\x00\x00\x8d9\x00\x00\x05H\x00\x00\x00\x00\x00\x01\x00\x00\x89\xfa\x00\x00\x01\xb0\x00\x00\x00\x00\x00\x01\x00\x00n\xaf\x00\x00\x05\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x86*\x00\x00\x02\x8a\x00\x00\x00\x00\x00\x01\x00\x00v\x87\x00\x00\x06\x84\x00\x00\x00\x00\x00\x01\x00\x00\x92\xbf\x00\x00\x01<\x00\x00\x00\x00\x00\x01\x00\x00l8\x00\x00\x002\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00" 15 | def qInitResources(): 16 | QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) 17 | 18 | def qCleanupResources(): 19 | QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) 20 | 21 | qInitResources() 22 | -------------------------------------------------------------------------------- /qdarkstyle/rc/Hmovetoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/Hmovetoolbar.png -------------------------------------------------------------------------------- /qdarkstyle/rc/Hsepartoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/Hsepartoolbar.png -------------------------------------------------------------------------------- /qdarkstyle/rc/Vmovetoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/Vmovetoolbar.png -------------------------------------------------------------------------------- /qdarkstyle/rc/Vsepartoolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/Vsepartoolbar.png -------------------------------------------------------------------------------- /qdarkstyle/rc/branch_closed-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/branch_closed-on.png -------------------------------------------------------------------------------- /qdarkstyle/rc/branch_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/branch_closed.png -------------------------------------------------------------------------------- /qdarkstyle/rc/branch_open-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/branch_open-on.png -------------------------------------------------------------------------------- /qdarkstyle/rc/branch_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/branch_open.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_checked.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_checked_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_checked_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_checked_focus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_checked_focus.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_indeterminate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_indeterminate.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_indeterminate_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_indeterminate_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_indeterminate_focus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_indeterminate_focus.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_unchecked.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_unchecked_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_unchecked_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/checkbox_unchecked_focus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/checkbox_unchecked_focus.png -------------------------------------------------------------------------------- /qdarkstyle/rc/close-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/close-hover.png -------------------------------------------------------------------------------- /qdarkstyle/rc/close-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/close-pressed.png -------------------------------------------------------------------------------- /qdarkstyle/rc/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/close.png -------------------------------------------------------------------------------- /qdarkstyle/rc/down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/down_arrow.png -------------------------------------------------------------------------------- /qdarkstyle/rc/down_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/down_arrow_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/left_arrow.png -------------------------------------------------------------------------------- /qdarkstyle/rc/left_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/left_arrow_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/radio_checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/radio_checked.png -------------------------------------------------------------------------------- /qdarkstyle/rc/radio_checked_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/radio_checked_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/radio_checked_focus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/radio_checked_focus.png -------------------------------------------------------------------------------- /qdarkstyle/rc/radio_unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/radio_unchecked.png -------------------------------------------------------------------------------- /qdarkstyle/rc/radio_unchecked_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/radio_unchecked_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/radio_unchecked_focus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/radio_unchecked_focus.png -------------------------------------------------------------------------------- /qdarkstyle/rc/right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/right_arrow.png -------------------------------------------------------------------------------- /qdarkstyle/rc/right_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/right_arrow_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/rc/sizegrip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/sizegrip.png -------------------------------------------------------------------------------- /qdarkstyle/rc/stylesheet-branch-end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/stylesheet-branch-end.png -------------------------------------------------------------------------------- /qdarkstyle/rc/stylesheet-branch-more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/stylesheet-branch-more.png -------------------------------------------------------------------------------- /qdarkstyle/rc/stylesheet-vline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/stylesheet-vline.png -------------------------------------------------------------------------------- /qdarkstyle/rc/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/transparent.png -------------------------------------------------------------------------------- /qdarkstyle/rc/undock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/undock.png -------------------------------------------------------------------------------- /qdarkstyle/rc/up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/up_arrow.png -------------------------------------------------------------------------------- /qdarkstyle/rc/up_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barulicm/GazeboWorldDesigner/e33973b0336602a4b284083acafb03107716ea67/qdarkstyle/rc/up_arrow_disabled.png -------------------------------------------------------------------------------- /qdarkstyle/style.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | rc/up_arrow_disabled.png 4 | rc/Hmovetoolbar.png 5 | rc/stylesheet-branch-end.png 6 | rc/branch_closed-on.png 7 | rc/stylesheet-vline.png 8 | rc/branch_closed.png 9 | rc/branch_open-on.png 10 | rc/transparent.png 11 | rc/right_arrow_disabled.png 12 | rc/sizegrip.png 13 | rc/close.png 14 | rc/close-hover.png 15 | rc/close-pressed.png 16 | rc/down_arrow.png 17 | rc/Vmovetoolbar.png 18 | rc/left_arrow.png 19 | rc/stylesheet-branch-more.png 20 | rc/up_arrow.png 21 | rc/right_arrow.png 22 | rc/left_arrow_disabled.png 23 | rc/Hsepartoolbar.png 24 | rc/branch_open.png 25 | rc/Vsepartoolbar.png 26 | rc/down_arrow_disabled.png 27 | rc/undock.png 28 | rc/checkbox_checked_disabled.png 29 | rc/checkbox_checked_focus.png 30 | rc/checkbox_checked.png 31 | rc/checkbox_indeterminate.png 32 | rc/checkbox_indeterminate_focus.png 33 | rc/checkbox_unchecked_disabled.png 34 | rc/checkbox_unchecked_focus.png 35 | rc/checkbox_unchecked.png 36 | rc/radio_checked_disabled.png 37 | rc/radio_checked_focus.png 38 | rc/radio_checked.png 39 | rc/radio_unchecked_disabled.png 40 | rc/radio_unchecked_focus.png 41 | rc/radio_unchecked.png 42 | 43 | 44 | style.qss 45 | 46 | 47 | -------------------------------------------------------------------------------- /qdarkstyle/style.qss: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) <2013-2014> 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | QToolTip 25 | { 26 | border: 1px solid #76797C; 27 | background-color: rgb(90, 102, 117);; 28 | color: white; 29 | padding: 5px; 30 | opacity: 200; 31 | } 32 | 33 | QWidget 34 | { 35 | color: #eff0f1; 36 | background-color: #31363b; 37 | selection-background-color:#3daee9; 38 | selection-color: #eff0f1; 39 | background-clip: border; 40 | border-image: none; 41 | border: 0px transparent black; 42 | outline: 0; 43 | } 44 | 45 | QWidget:item:hover 46 | { 47 | background-color: #3daee9; 48 | color: #eff0f1; 49 | } 50 | 51 | QWidget:item:selected 52 | { 53 | background-color: #3daee9; 54 | } 55 | 56 | QCheckBox 57 | { 58 | spacing: 5px; 59 | outline: none; 60 | color: #eff0f1; 61 | margin-bottom: 2px; 62 | } 63 | 64 | QCheckBox:disabled 65 | { 66 | color: #76797C; 67 | } 68 | 69 | QCheckBox::indicator, 70 | QGroupBox::indicator 71 | { 72 | width: 18px; 73 | height: 18px; 74 | } 75 | QGroupBox::indicator 76 | { 77 | margin-left: 2px; 78 | } 79 | 80 | QCheckBox::indicator:unchecked 81 | { 82 | image: url(:/qss_icons/rc/checkbox_unchecked.png); 83 | } 84 | 85 | QCheckBox::indicator:unchecked:hover, 86 | QCheckBox::indicator:unchecked:focus, 87 | QCheckBox::indicator:unchecked:pressed, 88 | QGroupBox::indicator:unchecked:hover, 89 | QGroupBox::indicator:unchecked:focus, 90 | QGroupBox::indicator:unchecked:pressed 91 | { 92 | border: none; 93 | image: url(:/qss_icons/rc/checkbox_unchecked_focus.png); 94 | } 95 | 96 | QCheckBox::indicator:checked 97 | { 98 | image: url(:/qss_icons/rc/checkbox_checked.png); 99 | } 100 | 101 | QCheckBox::indicator:checked:hover, 102 | QCheckBox::indicator:checked:focus, 103 | QCheckBox::indicator:checked:pressed, 104 | QGroupBox::indicator:checked:hover, 105 | QGroupBox::indicator:checked:focus, 106 | QGroupBox::indicator:checked:pressed 107 | { 108 | border: none; 109 | image: url(:/qss_icons/rc/checkbox_checked_focus.png); 110 | } 111 | 112 | 113 | QCheckBox::indicator:indeterminate 114 | { 115 | image: url(:/qss_icons/rc/checkbox_indeterminate.png); 116 | } 117 | 118 | QCheckBox::indicator:indeterminate:focus, 119 | QCheckBox::indicator:indeterminate:hover, 120 | QCheckBox::indicator:indeterminate:pressed 121 | { 122 | image: url(:/qss_icons/rc/checkbox_indeterminate_focus.png); 123 | } 124 | 125 | QCheckBox::indicator:checked:disabled, 126 | QGroupBox::indicator:checked:disabled 127 | { 128 | image: url(:/qss_icons/rc/checkbox_checked_disabled.png); 129 | } 130 | 131 | QCheckBox::indicator:unchecked:disabled, 132 | QGroupBox::indicator:unchecked:disabled 133 | { 134 | image: url(:/qss_icons/rc/checkbox_unchecked_disabled.png); 135 | } 136 | 137 | QRadioButton 138 | { 139 | spacing: 5px; 140 | outline: none; 141 | color: #eff0f1; 142 | margin-bottom: 2px; 143 | } 144 | 145 | QRadioButton:disabled 146 | { 147 | color: #76797C; 148 | } 149 | QRadioButton::indicator 150 | { 151 | width: 21px; 152 | height: 21px; 153 | } 154 | 155 | QRadioButton::indicator:unchecked 156 | { 157 | image: url(:/qss_icons/rc/radio_unchecked.png); 158 | } 159 | 160 | 161 | QRadioButton::indicator:unchecked:hover, 162 | QRadioButton::indicator:unchecked:focus, 163 | QRadioButton::indicator:unchecked:pressed 164 | { 165 | border: none; 166 | outline: none; 167 | image: url(:/qss_icons/rc/radio_unchecked_focus.png); 168 | } 169 | 170 | QRadioButton::indicator:checked 171 | { 172 | border: none; 173 | outline: none; 174 | image: url(:/qss_icons/rc/radio_checked.png); 175 | } 176 | 177 | QRadioButton::indicator:checked:hover, 178 | QRadioButton::indicator:checked:focus, 179 | QRadioButton::indicator:checked:pressed 180 | { 181 | border: none; 182 | outline: none; 183 | image: url(:/qss_icons/rc/radio_checked_focus.png); 184 | } 185 | 186 | QRadioButton::indicator:checked:disabled 187 | { 188 | outline: none; 189 | image: url(:/qss_icons/rc/radio_checked_disabled.png); 190 | } 191 | 192 | QRadioButton::indicator:unchecked:disabled 193 | { 194 | image: url(:/qss_icons/rc/radio_unchecked_disabled.png); 195 | } 196 | 197 | 198 | QMenuBar 199 | { 200 | background-color: #31363b; 201 | color: #eff0f1; 202 | } 203 | 204 | QMenuBar::item 205 | { 206 | background: transparent; 207 | } 208 | 209 | QMenuBar::item:selected 210 | { 211 | background: transparent; 212 | border: 1px solid #76797C; 213 | } 214 | 215 | QMenuBar::item:pressed 216 | { 217 | border: 1px solid #76797C; 218 | background-color: #3daee9; 219 | color: #eff0f1; 220 | margin-bottom:-1px; 221 | padding-bottom:1px; 222 | } 223 | 224 | QMenu 225 | { 226 | border: 1px solid #76797C; 227 | color: #eff0f1; 228 | margin: 2px; 229 | } 230 | 231 | QMenu::icon 232 | { 233 | margin: 5px; 234 | } 235 | 236 | QMenu::item 237 | { 238 | padding: 5px 30px 5px 30px; 239 | margin-left: 5px; 240 | border: 1px solid transparent; /* reserve space for selection border */ 241 | } 242 | 243 | QMenu::item:selected 244 | { 245 | color: #eff0f1; 246 | } 247 | 248 | QMenu::separator { 249 | height: 2px; 250 | background: lightblue; 251 | margin-left: 10px; 252 | margin-right: 5px; 253 | } 254 | 255 | QMenu::indicator { 256 | width: 18px; 257 | height: 18px; 258 | } 259 | 260 | /* non-exclusive indicator = check box style indicator 261 | (see QActionGroup::setExclusive) */ 262 | QMenu::indicator:non-exclusive:unchecked { 263 | image: url(:/qss_icons/rc/checkbox_unchecked.png); 264 | } 265 | 266 | QMenu::indicator:non-exclusive:unchecked:selected { 267 | image: url(:/qss_icons/rc/checkbox_unchecked_disabled.png); 268 | } 269 | 270 | QMenu::indicator:non-exclusive:checked { 271 | image: url(:/qss_icons/rc/checkbox_checked.png); 272 | } 273 | 274 | QMenu::indicator:non-exclusive:checked:selected { 275 | image: url(:/qss_icons/rc/checkbox_checked_disabled.png); 276 | } 277 | 278 | /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ 279 | QMenu::indicator:exclusive:unchecked { 280 | image: url(:/qss_icons/rc/radio_unchecked.png); 281 | } 282 | 283 | QMenu::indicator:exclusive:unchecked:selected { 284 | image: url(:/qss_icons/rc/radio_unchecked_disabled.png); 285 | } 286 | 287 | QMenu::indicator:exclusive:checked { 288 | image: url(:/qss_icons/rc/radio_checked.png); 289 | } 290 | 291 | QMenu::indicator:exclusive:checked:selected { 292 | image: url(:/qss_icons/rc/radio_checked_disabled.png); 293 | } 294 | 295 | QMenu::right-arrow { 296 | margin: 5px; 297 | image: url(:/qss_icons/rc/right_arrow.png) 298 | } 299 | 300 | 301 | QWidget:disabled 302 | { 303 | color: #454545; 304 | background-color: #31363b; 305 | } 306 | 307 | QAbstractItemView 308 | { 309 | alternate-background-color: #31363b; 310 | color: #eff0f1; 311 | border: 1px solid 3A3939; 312 | border-radius: 2px; 313 | } 314 | 315 | QWidget:focus, QMenuBar:focus 316 | { 317 | border: 1px solid #3daee9; 318 | } 319 | 320 | QTabWidget:focus, QCheckBox:focus, QRadioButton:focus, QSlider:focus 321 | { 322 | border: none; 323 | } 324 | 325 | QLineEdit 326 | { 327 | background-color: #232629; 328 | padding: 5px; 329 | border-style: solid; 330 | border: 1px solid #76797C; 331 | border-radius: 2px; 332 | color: #eff0f1; 333 | } 334 | 335 | QGroupBox { 336 | border:1px solid #76797C; 337 | border-radius: 2px; 338 | margin-top: 20px; 339 | } 340 | 341 | QGroupBox::title { 342 | subcontrol-origin: margin; 343 | subcontrol-position: top center; 344 | padding-left: 10px; 345 | padding-right: 10px; 346 | padding-top: 10px; 347 | } 348 | 349 | QAbstractScrollArea 350 | { 351 | border-radius: 2px; 352 | border: 1px solid #76797C; 353 | background-color: transparent; 354 | } 355 | 356 | QScrollBar:horizontal 357 | { 358 | height: 15px; 359 | margin: 3px 15px 3px 15px; 360 | border: 1px transparent #2A2929; 361 | border-radius: 4px; 362 | background-color: #2A2929; 363 | } 364 | 365 | QScrollBar::handle:horizontal 366 | { 367 | background-color: #605F5F; 368 | min-width: 5px; 369 | border-radius: 4px; 370 | } 371 | 372 | QScrollBar::add-line:horizontal 373 | { 374 | margin: 0px 3px 0px 3px; 375 | border-image: url(:/qss_icons/rc/right_arrow_disabled.png); 376 | width: 10px; 377 | height: 10px; 378 | subcontrol-position: right; 379 | subcontrol-origin: margin; 380 | } 381 | 382 | QScrollBar::sub-line:horizontal 383 | { 384 | margin: 0px 3px 0px 3px; 385 | border-image: url(:/qss_icons/rc/left_arrow_disabled.png); 386 | height: 10px; 387 | width: 10px; 388 | subcontrol-position: left; 389 | subcontrol-origin: margin; 390 | } 391 | 392 | QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on 393 | { 394 | border-image: url(:/qss_icons/rc/right_arrow.png); 395 | height: 10px; 396 | width: 10px; 397 | subcontrol-position: right; 398 | subcontrol-origin: margin; 399 | } 400 | 401 | 402 | QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on 403 | { 404 | border-image: url(:/qss_icons/rc/left_arrow.png); 405 | height: 10px; 406 | width: 10px; 407 | subcontrol-position: left; 408 | subcontrol-origin: margin; 409 | } 410 | 411 | QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal 412 | { 413 | background: none; 414 | } 415 | 416 | 417 | QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal 418 | { 419 | background: none; 420 | } 421 | 422 | QScrollBar:vertical 423 | { 424 | background-color: #2A2929; 425 | width: 15px; 426 | margin: 15px 3px 15px 3px; 427 | border: 1px transparent #2A2929; 428 | border-radius: 4px; 429 | } 430 | 431 | QScrollBar::handle:vertical 432 | { 433 | background-color: #605F5F; 434 | min-height: 5px; 435 | border-radius: 4px; 436 | } 437 | 438 | QScrollBar::sub-line:vertical 439 | { 440 | margin: 3px 0px 3px 0px; 441 | border-image: url(:/qss_icons/rc/up_arrow_disabled.png); 442 | height: 10px; 443 | width: 10px; 444 | subcontrol-position: top; 445 | subcontrol-origin: margin; 446 | } 447 | 448 | QScrollBar::add-line:vertical 449 | { 450 | margin: 3px 0px 3px 0px; 451 | border-image: url(:/qss_icons/rc/down_arrow_disabled.png); 452 | height: 10px; 453 | width: 10px; 454 | subcontrol-position: bottom; 455 | subcontrol-origin: margin; 456 | } 457 | 458 | QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on 459 | { 460 | 461 | border-image: url(:/qss_icons/rc/up_arrow.png); 462 | height: 10px; 463 | width: 10px; 464 | subcontrol-position: top; 465 | subcontrol-origin: margin; 466 | } 467 | 468 | 469 | QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on 470 | { 471 | border-image: url(:/qss_icons/rc/down_arrow.png); 472 | height: 10px; 473 | width: 10px; 474 | subcontrol-position: bottom; 475 | subcontrol-origin: margin; 476 | } 477 | 478 | QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical 479 | { 480 | background: none; 481 | } 482 | 483 | 484 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical 485 | { 486 | background: none; 487 | } 488 | 489 | QTextEdit 490 | { 491 | background-color: #232629; 492 | color: #eff0f1; 493 | border: 1px solid #76797C; 494 | } 495 | 496 | QPlainTextEdit 497 | { 498 | background-color: #232629;; 499 | color: #eff0f1; 500 | border-radius: 2px; 501 | border: 1px solid #76797C; 502 | } 503 | 504 | QHeaderView::section 505 | { 506 | background-color: #76797C; 507 | color: #eff0f1; 508 | padding: 5px; 509 | border: 1px solid #76797C; 510 | } 511 | 512 | QSizeGrip { 513 | image: url(:/qss_icons/rc/sizegrip.png); 514 | width: 12px; 515 | height: 12px; 516 | } 517 | 518 | 519 | QMainWindow::separator 520 | { 521 | background-color: #31363b; 522 | color: white; 523 | padding-left: 4px; 524 | spacing: 2px; 525 | border: 1px dashed #76797C; 526 | } 527 | 528 | QMainWindow::separator:hover 529 | { 530 | 531 | background-color: #787876; 532 | color: white; 533 | padding-left: 4px; 534 | border: 1px solid #76797C; 535 | spacing: 2px; 536 | } 537 | 538 | 539 | QMenu::separator 540 | { 541 | height: 1px; 542 | background-color: #76797C; 543 | color: white; 544 | padding-left: 4px; 545 | margin-left: 10px; 546 | margin-right: 5px; 547 | } 548 | 549 | 550 | QFrame 551 | { 552 | border-radius: 2px; 553 | border: 1px solid #76797C; 554 | } 555 | 556 | QFrame[frameShape="0"] 557 | { 558 | border-radius: 2px; 559 | border: 1px transparent #76797C; 560 | } 561 | 562 | QStackedWidget 563 | { 564 | border: 1px transparent black; 565 | } 566 | 567 | QToolBar { 568 | border: 1px transparent #393838; 569 | background: 1px solid #31363b; 570 | font-weight: bold; 571 | } 572 | 573 | QToolBar::handle:horizontal { 574 | image: url(:/qss_icons/rc/Hmovetoolbar.png); 575 | } 576 | QToolBar::handle:vertical { 577 | image: url(:/qss_icons/rc/Vmovetoolbar.png); 578 | } 579 | QToolBar::separator:horizontal { 580 | image: url(:/qss_icons/rc/Hsepartoolbar.png); 581 | } 582 | QToolBar::separator:vertical { 583 | image: url(:/qss_icons/rc/Vsepartoolbar.png); 584 | } 585 | QToolButton#qt_toolbar_ext_button { 586 | background: #58595a 587 | } 588 | 589 | QPushButton 590 | { 591 | color: #eff0f1; 592 | background-color: #31363b; 593 | border-width: 1px; 594 | border-color: #76797C; 595 | border-style: solid; 596 | padding: 5px; 597 | border-radius: 2px; 598 | outline: none; 599 | } 600 | 601 | QPushButton:disabled 602 | { 603 | background-color: #31363b; 604 | border-width: 1px; 605 | border-color: #454545; 606 | border-style: solid; 607 | padding-top: 5px; 608 | padding-bottom: 5px; 609 | padding-left: 10px; 610 | padding-right: 10px; 611 | border-radius: 2px; 612 | color: #454545; 613 | } 614 | 615 | QPushButton:focus { 616 | background-color: #3daee9; 617 | color: white; 618 | } 619 | 620 | QPushButton:pressed 621 | { 622 | background-color: #3daee9; 623 | padding-top: -15px; 624 | padding-bottom: -17px; 625 | } 626 | 627 | QComboBox 628 | { 629 | selection-background-color: #3daee9; 630 | border-style: solid; 631 | border: 1px solid #76797C; 632 | border-radius: 2px; 633 | padding: 5px; 634 | min-width: 75px; 635 | } 636 | 637 | QPushButton:checked{ 638 | background-color: #76797C; 639 | border-color: #6A6969; 640 | } 641 | 642 | QComboBox:hover,QPushButton:hover,QAbstractSpinBox:hover,QLineEdit:hover,QTextEdit:hover,QPlainTextEdit:hover,QAbstractView:hover,QTreeView:hover 643 | { 644 | border: 1px solid #3daee9; 645 | color: #eff0f1; 646 | } 647 | 648 | QComboBox:on 649 | { 650 | padding-top: 3px; 651 | padding-left: 4px; 652 | selection-background-color: #4a4a4a; 653 | } 654 | 655 | QComboBox QAbstractItemView 656 | { 657 | background-color: #232629; 658 | border-radius: 2px; 659 | border: 1px solid #76797C; 660 | selection-background-color: #3daee9; 661 | } 662 | 663 | QComboBox::drop-down 664 | { 665 | subcontrol-origin: padding; 666 | subcontrol-position: top right; 667 | width: 15px; 668 | 669 | border-left-width: 0px; 670 | border-left-color: darkgray; 671 | border-left-style: solid; 672 | border-top-right-radius: 3px; 673 | border-bottom-right-radius: 3px; 674 | } 675 | 676 | QComboBox::down-arrow 677 | { 678 | image: url(:/qss_icons/rc/down_arrow_disabled.png); 679 | } 680 | 681 | QComboBox::down-arrow:on, QComboBox::down-arrow:hover, 682 | QComboBox::down-arrow:focus 683 | { 684 | image: url(:/qss_icons/rc/down_arrow.png); 685 | } 686 | 687 | QAbstractSpinBox { 688 | padding: 5px; 689 | border: 1px solid #76797C; 690 | background-color: #232629; 691 | color: #eff0f1; 692 | border-radius: 2px; 693 | min-width: 75px; 694 | } 695 | 696 | QAbstractSpinBox:up-button 697 | { 698 | background-color: transparent; 699 | subcontrol-origin: border; 700 | subcontrol-position: center right; 701 | } 702 | 703 | QAbstractSpinBox:down-button 704 | { 705 | background-color: transparent; 706 | subcontrol-origin: border; 707 | subcontrol-position: center left; 708 | } 709 | 710 | QAbstractSpinBox::up-arrow,QAbstractSpinBox::up-arrow:disabled,QAbstractSpinBox::up-arrow:off { 711 | image: url(:/qss_icons/rc/up_arrow_disabled.png); 712 | width: 10px; 713 | height: 10px; 714 | } 715 | QAbstractSpinBox::up-arrow:hover 716 | { 717 | image: url(:/qss_icons/rc/up_arrow.png); 718 | } 719 | 720 | 721 | QAbstractSpinBox::down-arrow,QAbstractSpinBox::down-arrow:disabled,QAbstractSpinBox::down-arrow:off 722 | { 723 | image: url(:/qss_icons/rc/down_arrow_disabled.png); 724 | width: 10px; 725 | height: 10px; 726 | } 727 | QAbstractSpinBox::down-arrow:hover 728 | { 729 | image: url(:/qss_icons/rc/down_arrow.png); 730 | } 731 | 732 | 733 | QLabel 734 | { 735 | border: 0px solid black; 736 | } 737 | 738 | QTabWidget{ 739 | border: 0px transparent black; 740 | } 741 | 742 | QTabWidget::pane { 743 | border: 1px solid #76797C; 744 | padding: 5px; 745 | margin: 0px; 746 | } 747 | 748 | QTabBar 749 | { 750 | qproperty-drawBase: 0; 751 | left: 5px; /* move to the right by 5px */ 752 | border-radius: 3px; 753 | } 754 | 755 | QTabBar:focus 756 | { 757 | border: 0px transparent black; 758 | } 759 | 760 | QTabBar::close-button { 761 | image: url(:/qss_icons/rc/close.png); 762 | background: transparent; 763 | } 764 | 765 | QTabBar::close-button:hover 766 | { 767 | image: url(:/qss_icons/rc/close-hover.png); 768 | background: transparent; 769 | } 770 | 771 | QTabBar::close-button:pressed { 772 | image: url(:/qss_icons/rc/close-pressed.png); 773 | background: transparent; 774 | } 775 | 776 | /* TOP TABS */ 777 | QTabBar::tab:top { 778 | color: #eff0f1; 779 | border: 1px solid #76797C; 780 | border-bottom: 1px transparent black; 781 | background-color: #31363b; 782 | padding: 5px; 783 | min-width: 50px; 784 | border-top-left-radius: 2px; 785 | border-top-right-radius: 2px; 786 | } 787 | 788 | QTabBar::tab:top:!selected 789 | { 790 | color: #eff0f1; 791 | background-color: #54575B; 792 | border: 1px solid #76797C; 793 | border-bottom: 1px transparent black; 794 | border-top-left-radius: 2px; 795 | border-top-right-radius: 2px; 796 | } 797 | 798 | QTabBar::tab:top:!selected:hover { 799 | background-color: #3daee9; 800 | } 801 | 802 | /* BOTTOM TABS */ 803 | QTabBar::tab:bottom { 804 | color: #eff0f1; 805 | border: 1px solid #76797C; 806 | border-top: 1px transparent black; 807 | background-color: #31363b; 808 | padding: 5px; 809 | border-bottom-left-radius: 2px; 810 | border-bottom-right-radius: 2px; 811 | min-width: 50px; 812 | } 813 | 814 | QTabBar::tab:bottom:!selected 815 | { 816 | color: #eff0f1; 817 | background-color: #54575B; 818 | border: 1px solid #76797C; 819 | border-top: 1px transparent black; 820 | border-bottom-left-radius: 2px; 821 | border-bottom-right-radius: 2px; 822 | } 823 | 824 | QTabBar::tab:bottom:!selected:hover { 825 | background-color: #3daee9; 826 | } 827 | 828 | /* LEFT TABS */ 829 | QTabBar::tab:left { 830 | color: #eff0f1; 831 | border: 1px solid #76797C; 832 | border-left: 1px transparent black; 833 | background-color: #31363b; 834 | padding: 5px; 835 | border-top-right-radius: 2px; 836 | border-bottom-right-radius: 2px; 837 | min-height: 50px; 838 | } 839 | 840 | QTabBar::tab:left:!selected 841 | { 842 | color: #eff0f1; 843 | background-color: #54575B; 844 | border: 1px solid #76797C; 845 | border-left: 1px transparent black; 846 | border-top-right-radius: 2px; 847 | border-bottom-right-radius: 2px; 848 | } 849 | 850 | QTabBar::tab:left:!selected:hover { 851 | background-color: #3daee9; 852 | } 853 | 854 | 855 | /* RIGHT TABS */ 856 | QTabBar::tab:right { 857 | color: #eff0f1; 858 | border: 1px solid #76797C; 859 | border-right: 1px transparent black; 860 | background-color: #31363b; 861 | padding: 5px; 862 | border-top-left-radius: 2px; 863 | border-bottom-left-radius: 2px; 864 | min-height: 50px; 865 | } 866 | 867 | QTabBar::tab:right:!selected 868 | { 869 | color: #eff0f1; 870 | background-color: #54575B; 871 | border: 1px solid #76797C; 872 | border-right: 1px transparent black; 873 | border-top-left-radius: 2px; 874 | border-bottom-left-radius: 2px; 875 | } 876 | 877 | QTabBar::tab:right:!selected:hover { 878 | background-color: #3daee9; 879 | } 880 | 881 | QTabBar QToolButton::right-arrow:enabled { 882 | image: url(:/qss_icons/rc/right_arrow.png); 883 | } 884 | 885 | QTabBar QToolButton::left-arrow:enabled { 886 | image: url(:/qss_icons/rc/left_arrow.png); 887 | } 888 | 889 | QTabBar QToolButton::right-arrow:disabled { 890 | image: url(:/qss_icons/rc/right_arrow_disabled.png); 891 | } 892 | 893 | QTabBar QToolButton::left-arrow:disabled { 894 | image: url(:/qss_icons/rc/left_arrow_disabled.png); 895 | } 896 | 897 | 898 | QDockWidget { 899 | background: #31363b; 900 | border: 1px solid #403F3F; 901 | titlebar-close-icon: url(:/qss_icons/rc/close.png); 902 | titlebar-normal-icon: url(:/qss_icons/rc/undock.png); 903 | } 904 | 905 | QDockWidget::close-button, QDockWidget::float-button { 906 | border: 1px solid transparent; 907 | border-radius: 2px; 908 | background: transparent; 909 | } 910 | 911 | QDockWidget::close-button:hover, QDockWidget::float-button:hover { 912 | background: rgba(255, 255, 255, 10); 913 | } 914 | 915 | QDockWidget::close-button:pressed, QDockWidget::float-button:pressed { 916 | padding: 1px -1px -1px 1px; 917 | background: rgba(255, 255, 255, 10); 918 | } 919 | 920 | QTreeView, QListView 921 | { 922 | border: 1px solid #76797C; 923 | background-color: #232629; 924 | } 925 | 926 | QTreeView:branch:selected, QTreeView:branch:hover 927 | { 928 | background: url(:/qss_icons/rc/transparent.png); 929 | } 930 | 931 | QTreeView::branch:has-siblings:!adjoins-item { 932 | border-image: url(:/qss_icons/rc/transparent.png); 933 | } 934 | 935 | QTreeView::branch:has-siblings:adjoins-item { 936 | border-image: url(:/qss_icons/rc/transparent.png); 937 | } 938 | 939 | QTreeView::branch:!has-children:!has-siblings:adjoins-item { 940 | border-image: url(:/qss_icons/rc/transparent.png); 941 | } 942 | 943 | QTreeView::branch:has-children:!has-siblings:closed, 944 | QTreeView::branch:closed:has-children:has-siblings { 945 | image: url(:/qss_icons/rc/branch_closed.png); 946 | } 947 | 948 | QTreeView::branch:open:has-children:!has-siblings, 949 | QTreeView::branch:open:has-children:has-siblings { 950 | image: url(:/qss_icons/rc/branch_open.png); 951 | } 952 | 953 | QTreeView::branch:has-children:!has-siblings:closed:hover, 954 | QTreeView::branch:closed:has-children:has-siblings:hover { 955 | image: url(:/qss_icons/rc/branch_closed-on.png); 956 | } 957 | 958 | QTreeView::branch:open:has-children:!has-siblings:hover, 959 | QTreeView::branch:open:has-children:has-siblings:hover { 960 | image: url(:/qss_icons/rc/branch_open-on.png); 961 | } 962 | 963 | QListView::item:!selected:hover, QTreeView::item:!selected:hover { 964 | background: rgba(167,218,245, 0.3); 965 | outline: 0; 966 | color: #eff0f1 967 | } 968 | 969 | QListView::item:selected:hover, QTreeView::item:selected:hover { 970 | background: #3daee9; 971 | color: #eff0f1; 972 | } 973 | 974 | QSlider::groove:horizontal { 975 | border: 1px solid #565a5e; 976 | height: 4px; 977 | background: #565a5e; 978 | margin: 0px; 979 | border-radius: 2px; 980 | } 981 | 982 | QSlider::handle:horizontal { 983 | background: #232629; 984 | border: 1px solid #565a5e; 985 | width: 16px; 986 | height: 16px; 987 | margin: -8px 0; 988 | border-radius: 9px; 989 | } 990 | 991 | QSlider::groove:vertical { 992 | border: 1px solid #565a5e; 993 | width: 4px; 994 | background: #565a5e; 995 | margin: 0px; 996 | border-radius: 3px; 997 | } 998 | 999 | QSlider::handle:vertical { 1000 | background: #232629; 1001 | border: 1px solid #565a5e; 1002 | width: 16px; 1003 | height: 16px; 1004 | margin: 0 -8px; 1005 | border-radius: 9px; 1006 | } 1007 | 1008 | QToolButton { 1009 | background-color: transparent; 1010 | border: 1px transparent #76797C; 1011 | border-radius: 2px; 1012 | margin: 3px; 1013 | padding: 5px; 1014 | } 1015 | 1016 | QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ 1017 | padding-right: 20px; /* make way for the popup button */ 1018 | border: 1px #76797C; 1019 | border-radius: 5px; 1020 | } 1021 | 1022 | QToolButton[popupMode="2"] { /* only for InstantPopup */ 1023 | padding-right: 10px; /* make way for the popup button */ 1024 | border: 1px #76797C; 1025 | } 1026 | 1027 | 1028 | QToolButton:hover, QToolButton::menu-button:hover { 1029 | background-color: transparent; 1030 | border: 1px solid #3daee9; 1031 | padding: 5px; 1032 | } 1033 | 1034 | QToolButton:checked, QToolButton:pressed, 1035 | QToolButton::menu-button:pressed { 1036 | background-color: #3daee9; 1037 | border: 1px solid #3daee9; 1038 | padding: 5px; 1039 | } 1040 | 1041 | /* the subcontrol below is used only in the InstantPopup or DelayedPopup mode */ 1042 | QToolButton::menu-indicator { 1043 | image: url(:/qss_icons/rc/down_arrow.png); 1044 | top: -7px; left: -2px; /* shift it a bit */ 1045 | } 1046 | 1047 | /* the subcontrols below are used only in the MenuButtonPopup mode */ 1048 | QToolButton::menu-button { 1049 | border: 1px transparent #76797C; 1050 | border-top-right-radius: 6px; 1051 | border-bottom-right-radius: 6px; 1052 | /* 16px width + 4px for border = 20px allocated above */ 1053 | width: 16px; 1054 | outline: none; 1055 | } 1056 | 1057 | QToolButton::menu-arrow { 1058 | image: url(:/qss_icons/rc/down_arrow.png); 1059 | } 1060 | 1061 | QToolButton::menu-arrow:open { 1062 | border: 1px solid #76797C; 1063 | } 1064 | 1065 | QPushButton::menu-indicator { 1066 | subcontrol-origin: padding; 1067 | subcontrol-position: bottom right; 1068 | left: 8px; 1069 | } 1070 | 1071 | QTableView 1072 | { 1073 | border: 1px solid #76797C; 1074 | gridline-color: #31363b; 1075 | background-color: #232629; 1076 | } 1077 | 1078 | 1079 | QTableView, QHeaderView 1080 | { 1081 | border-radius: 0px; 1082 | } 1083 | 1084 | QTableView::item:pressed, QListView::item:pressed, QTreeView::item:pressed { 1085 | background: #3daee9; 1086 | color: #eff0f1; 1087 | } 1088 | 1089 | QTableView::item:selected:active, QTreeView::item:selected:active, QListView::item:selected:active { 1090 | background: #3daee9; 1091 | color: #eff0f1; 1092 | } 1093 | 1094 | 1095 | QHeaderView 1096 | { 1097 | background-color: #31363b; 1098 | border: 1px transparent; 1099 | border-radius: 0px; 1100 | margin: 0px; 1101 | padding: 0px; 1102 | 1103 | } 1104 | 1105 | QHeaderView::section { 1106 | background-color: #31363b; 1107 | color: #eff0f1; 1108 | padding: 5px; 1109 | border: 1px solid #76797C; 1110 | border-radius: 0px; 1111 | text-align: center; 1112 | } 1113 | 1114 | QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one 1115 | { 1116 | border-top: 1px solid #76797C; 1117 | } 1118 | 1119 | QHeaderView::section::vertical 1120 | { 1121 | border-top: transparent; 1122 | } 1123 | 1124 | QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one 1125 | { 1126 | border-left: 1px solid #76797C; 1127 | } 1128 | 1129 | QHeaderView::section::horizontal 1130 | { 1131 | border-left: transparent; 1132 | } 1133 | 1134 | 1135 | QHeaderView::section:checked 1136 | { 1137 | color: white; 1138 | background-color: #334e5e; 1139 | } 1140 | 1141 | /* style the sort indicator */ 1142 | QHeaderView::down-arrow { 1143 | image: url(:/qss_icons/rc/down_arrow.png); 1144 | } 1145 | 1146 | QHeaderView::up-arrow { 1147 | image: url(:/qss_icons/rc/up_arrow.png); 1148 | } 1149 | 1150 | 1151 | QTableCornerButton::section { 1152 | background-color: #31363b; 1153 | border: 1px transparent #76797C; 1154 | border-radius: 0px; 1155 | } 1156 | 1157 | QToolBox { 1158 | padding: 5px; 1159 | border: 1px transparent black; 1160 | } 1161 | 1162 | QToolBox::tab { 1163 | color: #eff0f1; 1164 | background-color: #31363b; 1165 | border: 1px solid #76797C; 1166 | border-bottom: 1px transparent #31363b; 1167 | border-top-left-radius: 5px; 1168 | border-top-right-radius: 5px; 1169 | } 1170 | 1171 | QToolBox::tab:selected { /* italicize selected tabs */ 1172 | font: italic; 1173 | background-color: #31363b; 1174 | border-color: #3daee9; 1175 | } 1176 | 1177 | QStatusBar::item { 1178 | border: 0px transparent dark; 1179 | } 1180 | 1181 | 1182 | QFrame[height="3"], QFrame[width="3"] { 1183 | background-color: #76797C; 1184 | } 1185 | 1186 | 1187 | QSplitter::handle { 1188 | border: 1px dashed #76797C; 1189 | } 1190 | 1191 | QSplitter::handle:hover { 1192 | background-color: #787876; 1193 | border: 1px solid #76797C; 1194 | } 1195 | 1196 | QSplitter::handle:horizontal { 1197 | width: 1px; 1198 | } 1199 | 1200 | QSplitter::handle:vertical { 1201 | height: 1px; 1202 | } 1203 | 1204 | QProgressBar { 1205 | border: 1px solid #76797C; 1206 | border-radius: 5px; 1207 | text-align: center; 1208 | } 1209 | 1210 | QProgressBar::chunk { 1211 | background-color: #05B8CC; 1212 | } 1213 | 1214 | QDateEdit 1215 | { 1216 | selection-background-color: #3daee9; 1217 | border-style: solid; 1218 | border: 1px solid #3375A3; 1219 | border-radius: 2px; 1220 | padding: 1px; 1221 | min-width: 75px; 1222 | } 1223 | 1224 | QDateEdit:on 1225 | { 1226 | padding-top: 3px; 1227 | padding-left: 4px; 1228 | selection-background-color: #4a4a4a; 1229 | } 1230 | 1231 | QDateEdit QAbstractItemView 1232 | { 1233 | background-color: #232629; 1234 | border-radius: 2px; 1235 | border: 1px solid #3375A3; 1236 | selection-background-color: #3daee9; 1237 | } 1238 | 1239 | QDateEdit::drop-down 1240 | { 1241 | subcontrol-origin: padding; 1242 | subcontrol-position: top right; 1243 | width: 15px; 1244 | border-left-width: 0px; 1245 | border-left-color: darkgray; 1246 | border-left-style: solid; 1247 | border-top-right-radius: 3px; 1248 | border-bottom-right-radius: 3px; 1249 | } 1250 | 1251 | QDateEdit::down-arrow 1252 | { 1253 | image: url(:/qss_icons/rc/down_arrow_disabled.png); 1254 | } 1255 | 1256 | QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, 1257 | QDateEdit::down-arrow:focus 1258 | { 1259 | image: url(:/qss_icons/rc/down_arrow.png); 1260 | } -------------------------------------------------------------------------------- /sdf/Color.cpp: -------------------------------------------------------------------------------- 1 | #include "Color.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | Color::Color() {} 7 | 8 | Color::Color(double red, double green, double blue, double alpha) 9 | : r(red), g(green), b(blue), a(alpha) {} 10 | 11 | QDomElement Color::toXML(QDomDocument &document) const { 12 | QDomElement element = document.createElement("color"); 13 | element.appendChild(document.createTextNode((to_string(r) + " " + to_string(g) + " " + to_string(b) + " " + to_string(a)).c_str())); 14 | return element; 15 | } 16 | 17 | Color Color::fromString(const std::string &s) { 18 | 19 | stringstream ss{s}; 20 | 21 | Color color; 22 | 23 | ss >> color.r; 24 | ss >> color.g; 25 | ss >> color.b; 26 | ss >> color.a; 27 | 28 | return color; 29 | } 30 | 31 | template<> 32 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const { 33 | if(optional) { 34 | return optional->toXML(document); 35 | } else { 36 | return QDomElement{}; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sdf/Color.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_COLOR_H 2 | #define GWD_COLOR_H 3 | 4 | #include 5 | #include "SDFElement.h" 6 | 7 | struct Color : public SDFElement { 8 | 9 | Color(); 10 | 11 | Color(double r, double g, double b, double a); 12 | 13 | double r = 0; 14 | double g = 0; 15 | double b = 0; 16 | double a = 0; 17 | 18 | QDomElement toXML(QDomDocument &document) const override; 19 | 20 | static Color fromString(const std::string &s); 21 | 22 | }; 23 | 24 | template<> 25 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const; 26 | 27 | #endif //GWD_COLOR_H 28 | -------------------------------------------------------------------------------- /sdf/IncludedElement.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "IncludedElement.h" 4 | 5 | using namespace std; 6 | 7 | QDomElement IncludedElement::toXML(QDomDocument &document) const { 8 | QDomElement xml = document.createElement("include"); 9 | 10 | QDomElement uriElement = document.createElement("uri"); 11 | uriElement.appendChild(document.createTextNode(uri.c_str())); 12 | xml.appendChild(uriElement); 13 | 14 | auto nameElement = optionalToXML(document, name); 15 | nameElement.setTagName("name"); 16 | xml.appendChild(nameElement); 17 | 18 | auto staticElement = optionalToXML(document, isStatic); 19 | staticElement.setTagName("static"); 20 | xml.appendChild(staticElement); 21 | 22 | auto poseElement = optionalToXML(document, pose); 23 | poseElement.setTagName("pose"); 24 | xml.appendChild(poseElement); 25 | 26 | return xml; 27 | } 28 | 29 | void IncludedElement::render(QPainter &painter, const QPointF &origin, const double &scale, bool selected) const { 30 | QPointF posPoint; 31 | if(pose) { 32 | posPoint.setX(pose->x); 33 | posPoint.setY(pose->y); 34 | } else { 35 | posPoint.setX(0); 36 | posPoint.setY(0); 37 | } 38 | posPoint /= scale; 39 | posPoint += origin; 40 | painter.setPen( (selected ? Qt::white : Qt::lightGray) ); 41 | painter.drawLine(posPoint + QPointF{-10,0}, posPoint + QPointF{10,0}); 42 | painter.drawLine(posPoint + QPointF{0,-10}, posPoint + QPointF{0,10}); 43 | 44 | painter.drawText(posPoint + QPointF{2,-2}, uri.c_str()); 45 | } 46 | 47 | double IncludedElement::distanceToPoint(const double &x, const double &y) const { 48 | if(!pose) 49 | return std::hypot(x, y); 50 | 51 | double dx = x - pose->x; 52 | double dy = y - pose->y; 53 | return std::hypot(dx, dy); 54 | } 55 | 56 | void IncludedElement::setPose(const double &x, const double &y, const double &z) { 57 | if(!pose) { 58 | pose = Pose{}; 59 | } 60 | pose->x = x; 61 | pose->y = y; 62 | pose->z = z; 63 | } 64 | -------------------------------------------------------------------------------- /sdf/IncludedElement.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_INCLUDEDMODEL_H 2 | #define GWD_INCLUDEDMODEL_H 3 | 4 | 5 | #include 6 | #include "SDFElement.h" 7 | #include "Pose.h" 8 | 9 | struct IncludedElement : public SDFElement { 10 | 11 | std::string uri; 12 | std::experimental::optional name; 13 | std::experimental::optional isStatic; 14 | std::experimental::optional pose; 15 | 16 | QDomElement toXML(QDomDocument &document) const override; 17 | 18 | void render(QPainter &painter, const QPointF &origin, const double &scale, bool selected) const override; 19 | 20 | double distanceToPoint(const double &x, const double &y) const override; 21 | 22 | void setPose(const double &x, const double &y, const double &z) override; 23 | }; 24 | 25 | 26 | #endif //GWD_INCLUDEDMODEL_H 27 | -------------------------------------------------------------------------------- /sdf/Parser.cpp: -------------------------------------------------------------------------------- 1 | #include "Parser.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | World Parser::ParseWorld(const QDomDocument &xml) { 7 | World world; 8 | 9 | auto worldElement = xml.documentElement().firstChildElement("world"); 10 | 11 | if(worldElement.isNull()) 12 | return world; 13 | 14 | world.scene = parseScene(worldElement.firstChildElement("scene")); 15 | 16 | auto children = worldElement.childNodes(); 17 | 18 | for(int i = 0; i < children.size(); ++i) { 19 | auto child = children.item(i); 20 | if(child.toElement().tagName() == "include") { 21 | world.elements.push_back(parseInclude(children.item(i).toElement())); 22 | } 23 | } 24 | 25 | return world; 26 | } 27 | 28 | Scene Parser::parseScene(const QDomElement &sceneElement) { 29 | Scene scene; 30 | 31 | scene.ambient = Color::fromString(sceneElement.firstChildElement("ambient").text().toStdString()); 32 | 33 | scene.background = Color::fromString(sceneElement.firstChildElement("background").text().toStdString()); 34 | 35 | scene.shadows = boolFromString(sceneElement.firstChildElement("shadows").text().toStdString()); 36 | 37 | auto gridElement = sceneElement.firstChildElement("grid"); 38 | if(!gridElement.isNull()) { 39 | istringstream{gridElement.text().toStdString()} >> scene.show_grid; 40 | } 41 | 42 | auto originElement = sceneElement.firstChildElement("origin_visual"); 43 | if(!originElement.isNull()) { 44 | istringstream{originElement.text().toStdString()} >> scene.show_origin; 45 | } 46 | 47 | auto skyElement = sceneElement.firstChildElement("sky"); 48 | if(!skyElement.isNull()) { 49 | auto timeElement = skyElement.firstChildElement("time"); 50 | if(!timeElement.isNull()) { 51 | scene.time = stod(timeElement.text().toStdString()); 52 | } 53 | auto sunriseElement = skyElement.firstChildElement("sunrise"); 54 | if(!sunriseElement.isNull()) { 55 | scene.sunrise_time = stod(sunriseElement.text().toStdString()); 56 | } 57 | auto sunsetElement = skyElement.firstChildElement("sunset"); 58 | if(!sunsetElement.isNull()) { 59 | scene.sunset_time = stod(sunsetElement.text().toStdString()); 60 | } 61 | auto cloudsElement = skyElement.firstChildElement("clouds"); 62 | if(!cloudsElement.isNull()) { 63 | auto speedElement = cloudsElement.firstChildElement("speed"); 64 | if(!speedElement.isNull()) { 65 | scene.clouds_speed = stod(speedElement.text().toStdString()); 66 | } 67 | auto directionElement = cloudsElement.firstChildElement("direction"); 68 | if(!directionElement.isNull()) { 69 | scene.clouds_direction = stod(directionElement.text().toStdString()); 70 | } 71 | auto humidityElement = cloudsElement.firstChildElement("humidity"); 72 | if(!humidityElement.isNull()) { 73 | scene.clouds_humidity = stod(humidityElement.text().toStdString()); 74 | } 75 | auto meanSizeElement = cloudsElement.firstChildElement("mean_size"); 76 | if(!meanSizeElement.isNull()) { 77 | scene.clouds_mean_size = stod(meanSizeElement.text().toStdString()); 78 | } 79 | auto ambientElement = cloudsElement.firstChildElement("ambient"); 80 | if(!ambientElement.isNull()) { 81 | scene.clouds_ambient_color = Color::fromString(ambientElement.text().toStdString()); 82 | } 83 | } 84 | } 85 | 86 | return scene; 87 | } 88 | 89 | unique_ptr Parser::parseInclude(const QDomElement &includeElement) { 90 | 91 | unique_ptr element{new IncludedElement}; 92 | 93 | element->uri = includeElement.firstChildElement("uri").text().toStdString(); 94 | 95 | auto nameElement = includeElement.firstChildElement("name"); 96 | if(!nameElement.isNull()) { 97 | element->name = nameElement.text().toStdString(); 98 | } 99 | 100 | auto staticElement = includeElement.firstChildElement("static"); 101 | if(!staticElement.isNull()) { 102 | bool tmp; 103 | istringstream{staticElement.text().toStdString()} >> tmp; 104 | element->isStatic = tmp; 105 | } 106 | 107 | auto poseElement = includeElement.firstChildElement("pose"); 108 | if(!poseElement.isNull()) { 109 | element->pose = Pose::fromString(poseElement.text().toStdString()); 110 | } 111 | 112 | return move(element); 113 | 114 | } 115 | 116 | bool Parser::boolFromString(const std::string &s) { 117 | 118 | string s_lower = s; 119 | transform(s.begin(), s.end(), s_lower.begin(), ::tolower); 120 | 121 | if(s_lower == "true" || s_lower == "1") { 122 | return true; 123 | } 124 | 125 | return false; 126 | } 127 | -------------------------------------------------------------------------------- /sdf/Parser.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_PARSER_H 2 | #define GWD_PARSER_H 3 | 4 | #include "World.h" 5 | #include "IncludedElement.h" 6 | #include 7 | 8 | class Parser { 9 | public: 10 | static World ParseWorld(const QDomDocument &xml); 11 | 12 | private: 13 | static Scene parseScene(const QDomElement &sceneElement); 14 | 15 | static std::unique_ptr parseInclude(const QDomElement &includeElement); 16 | 17 | static bool boolFromString(const std::string &s); 18 | }; 19 | 20 | 21 | #endif //GWD_PARSER_H 22 | -------------------------------------------------------------------------------- /sdf/Pose.cpp: -------------------------------------------------------------------------------- 1 | #include "Pose.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | QDomElement Pose::toXML(QDomDocument &document) const { 8 | QDomElement element = document.createElement("pose"); 9 | element.appendChild(document.createTextNode((to_string(x) + " " + to_string(y) + " " + to_string(z) + " " 10 | + to_string(roll) + " " + to_string(pitch) + " " 11 | + to_string(yaw)).c_str())); 12 | return element; 13 | } 14 | 15 | Pose Pose::fromString(const std::string &s) { 16 | stringstream ss{s}; 17 | 18 | Pose pose; 19 | 20 | ss >> pose.x; 21 | ss >> pose.y; 22 | ss >> pose.z; 23 | ss >> pose.roll; 24 | ss >> pose.pitch; 25 | ss >> pose.yaw; 26 | 27 | return pose; 28 | } 29 | 30 | template<> 31 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const { 32 | if(optional) { 33 | return optional->toXML(document); 34 | } else { 35 | return QDomElement{}; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sdf/Pose.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_POSE_H 2 | #define GWD_POSE_H 3 | 4 | #include 5 | #include "SDFElement.h" 6 | 7 | struct Pose : public SDFElement { 8 | 9 | double x = 0.0; 10 | double y = 0.0; 11 | double z = 0.0; 12 | double roll = 0.0; 13 | double pitch = 0.0; 14 | double yaw = 0.0; 15 | 16 | QDomElement toXML(QDomDocument &document) const override; 17 | 18 | static Pose fromString(const std::string &s); 19 | 20 | }; 21 | 22 | template<> 23 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const; 24 | 25 | #endif //GWD_POSE_H 26 | -------------------------------------------------------------------------------- /sdf/SDFElement.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SDFElement.h" 3 | 4 | using namespace std; 5 | 6 | QDomElement SDFElement::toXML(QDomDocument &document) const { 7 | return QDomElement{}; 8 | } 9 | 10 | template<> 11 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const { 12 | 13 | if(optional) { 14 | QDomElement element = document.createElement(typeid(std::string).name()); 15 | element.appendChild(document.createTextNode(optional.value().c_str())); 16 | return element; 17 | } else { 18 | return QDomElement{}; 19 | } 20 | } 21 | 22 | template<> 23 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const { 24 | if(optional) { 25 | QDomElement element = document.createElement(typeid(std::string).name()); 26 | element.appendChild(document.createTextNode( (optional.value() ? "true" : "false") )); 27 | return element; 28 | } else { 29 | return QDomElement{}; 30 | } 31 | } 32 | 33 | void SDFElement::render(QPainter &, const QPointF &, const double &, bool) const { 34 | 35 | } 36 | 37 | double SDFElement::distanceToPoint(const double &x, const double &y) const { 38 | return numeric_limits::infinity(); 39 | } 40 | 41 | void SDFElement::setPose(const double &x, const double &y, const double &z) { 42 | 43 | } 44 | -------------------------------------------------------------------------------- /sdf/SDFElement.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_SDFELEMENT_H 2 | #define GWD_SDFELEMENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class SDFElement { 11 | public: 12 | virtual QDomElement toXML(QDomDocument &document) const; 13 | 14 | virtual void render(QPainter &painter, const QPointF &origin, const double &scale, bool selected) const; 15 | 16 | virtual double distanceToPoint(const double &x, const double &y) const; 17 | 18 | virtual void setPose(const double &x, const double &y, const double &z); 19 | 20 | protected: 21 | 22 | template 23 | QDomElement optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const { 24 | if(optional) { 25 | QDomElement element = document.createElement(typeid(T).name()); 26 | element.appendChild(document.createTextNode(std::to_string(optional.value()).c_str())); 27 | return element; 28 | } else { 29 | return QDomElement{}; 30 | } 31 | } 32 | }; 33 | 34 | template<> 35 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const; 36 | 37 | template<> 38 | QDomElement SDFElement::optionalToXML(QDomDocument &document, const std::experimental::optional &optional) const; 39 | 40 | #endif //GWD_SDFELEMENT_H 41 | -------------------------------------------------------------------------------- /sdf/Scene.cpp: -------------------------------------------------------------------------------- 1 | #include "Scene.h" 2 | 3 | using namespace std; 4 | 5 | QDomElement Scene::toXML(QDomDocument &document) const { 6 | 7 | QDomElement xml = document.createElement("scene"); 8 | 9 | auto ambientElement = ambient.toXML(document); 10 | ambientElement.setTagName("ambient"); 11 | xml.appendChild(ambientElement); 12 | 13 | auto backgroundElement = background.toXML(document); 14 | backgroundElement.setTagName("background"); 15 | xml.appendChild(backgroundElement); 16 | 17 | auto shadowsElement = document.createElement("shadows"); 18 | shadowsElement.appendChild( document.createTextNode( (shadows ? "true" : "false") ) ); 19 | xml.appendChild(shadowsElement); 20 | 21 | auto gridElement = document.createElement("grid"); 22 | gridElement.appendChild( document.createTextNode( (show_grid ? "true" : "false") ) ); 23 | xml.appendChild(gridElement); 24 | 25 | auto originElement = document.createElement("origin_visual"); 26 | originElement.appendChild( document.createTextNode( (show_origin ? "true" : "false") ) ); 27 | xml.appendChild(originElement); 28 | 29 | auto timeElement = optionalToXML(document, time); 30 | timeElement.setTagName("time"); 31 | xml.appendChild(timeElement); 32 | 33 | auto sunriseElement = optionalToXML(document, sunrise_time); 34 | sunriseElement.setTagName("sunrise"); 35 | xml.appendChild(sunriseElement); 36 | 37 | auto sunsetElement = optionalToXML(document, sunset_time); 38 | sunsetElement.setTagName("sunset"); 39 | xml.appendChild(sunsetElement); 40 | 41 | if(clouds_ambient_color || clouds_humidity || clouds_mean_size || clouds_speed || clouds_direction) { 42 | auto cloudsElement = document.createElement("clouds"); 43 | 44 | auto ambientColorElement = optionalToXML(document, clouds_ambient_color); 45 | ambientColorElement.setTagName("ambient"); 46 | cloudsElement.appendChild(ambientColorElement); 47 | 48 | auto humidityElement = optionalToXML(document, clouds_humidity); 49 | humidityElement.setTagName("humidity"); 50 | cloudsElement.appendChild(humidityElement); 51 | 52 | auto meanSizeElement = optionalToXML(document, clouds_mean_size); 53 | meanSizeElement.setTagName("mean_size"); 54 | cloudsElement.appendChild(meanSizeElement); 55 | 56 | auto speedElement = optionalToXML(document, clouds_speed); 57 | speedElement.setTagName("speed"); 58 | cloudsElement.appendChild(speedElement); 59 | 60 | auto directionElement = optionalToXML(document, clouds_direction); 61 | directionElement.setTagName("direction"); 62 | cloudsElement.appendChild(directionElement); 63 | 64 | xml.appendChild(cloudsElement); 65 | } 66 | 67 | return xml; 68 | } -------------------------------------------------------------------------------- /sdf/Scene.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_SCENE_H 2 | #define GWD_SCENE_H 3 | 4 | #include 5 | #include 6 | #include "SDFElement.h" 7 | #include "Color.h" 8 | 9 | class Scene : public SDFElement { 10 | 11 | public: 12 | 13 | QDomElement toXML(QDomDocument &document) const override; 14 | 15 | Color ambient = Color(1,1,1,1); 16 | Color background = Color(0.7,0.7,0.7,1); 17 | bool shadows = true; 18 | bool show_grid = true; 19 | bool show_origin = true; 20 | 21 | std::experimental::optional time; 22 | std::experimental::optional sunrise_time; 23 | std::experimental::optional sunset_time; 24 | std::experimental::optional clouds_speed; 25 | std::experimental::optional clouds_direction; 26 | std::experimental::optional clouds_humidity; 27 | std::experimental::optional clouds_mean_size; 28 | std::experimental::optional clouds_ambient_color; 29 | 30 | }; 31 | 32 | 33 | #endif //GWD_SCENE_H 34 | -------------------------------------------------------------------------------- /sdf/World.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "World.h" 3 | 4 | using namespace std; 5 | 6 | QDomElement World::toXML(QDomDocument &document) const { 7 | QDomElement xml = document.createElement("world"); 8 | xml.setAttribute("name", name.c_str()); 9 | 10 | xml.appendChild(scene.toXML(document)); 11 | 12 | for(const auto &element : elements) { 13 | xml.appendChild(element->toXML(document)); 14 | } 15 | 16 | return xml; 17 | } 18 | -------------------------------------------------------------------------------- /sdf/World.h: -------------------------------------------------------------------------------- 1 | #ifndef GWD_WORLD_H 2 | #define GWD_WORLD_H 3 | 4 | #include 5 | #include 6 | #include "SDFElement.h" 7 | #include "Scene.h" 8 | 9 | class World : public SDFElement { 10 | 11 | public: 12 | std::string name = "default"; 13 | 14 | Scene scene; 15 | 16 | std::vector> elements; 17 | 18 | QDomElement toXML(QDomDocument &document) const override; 19 | }; 20 | 21 | 22 | #endif //GWD_WORLD_H 23 | --------------------------------------------------------------------------------