From 14cbc51388e5e6a9049a939d58c8f70b336b5f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Math=C3=AFs=20F=C3=A9d=C3=A9rico?= Date: Wed, 3 Nov 2021 18:53:25 +0100 Subject: [PATCH 1/6] :hammer: Refactor OCBwindow for multiple graphs --- main.py | 52 ++--- opencodeblocks/graphics/widget.py | 37 +++ opencodeblocks/graphics/window.py | 367 +++++++++++++++++++----------- 3 files changed, 302 insertions(+), 154 deletions(-) diff --git a/main.py b/main.py index 75b0688d..4c066dc2 100644 --- a/main.py +++ b/main.py @@ -33,37 +33,35 @@ app.setStyle('Fusion') wnd = OCBWindow() - scene = wnd.ocb_widget.scene + # if hasattr(wnd, 'ocb_widget'): + # scene = wnd.ocb_widget.scene - test_block = OCBBlock(title="Other kind of block") - scene.addItem(test_block) - test_block.setPos(-250, 150) + # test_block = OCBBlock(title="Other kind of block") + # scene.addItem(test_block) + # test_block.setPos(-250, 150) - test_block_2 = OCBCodeBlock(title="Dataset", source=SOURCE_TEST) - for _ in range(2): - test_block_2.add_socket(OCBSocket(test_block_2, socket_type='input')) - for _ in range(1): - test_block_2.add_socket(OCBSocket(test_block_2, socket_type='output')) - test_block_2.setPos(-350, -100) - scene.addItem(test_block_2) + # test_block_2 = OCBCodeBlock(title="Dataset", source=SOURCE_TEST) + # for _ in range(2): + # test_block_2.add_socket(OCBSocket(test_block_2, socket_type='input')) + # for _ in range(1): + # test_block_2.add_socket(OCBSocket(test_block_2, socket_type='output')) + # test_block_2.setPos(-350, -100) + # scene.addItem(test_block_2) - test_block_3 = OCBCodeBlock(title="Mon IA (par blocks ?)", source=SOURCE_TEST_2) - for _ in range(2): - test_block_3.add_socket(OCBSocket(test_block_3, socket_type='input')) - for _ in range(1): - test_block_3.add_socket(OCBSocket(test_block_3, socket_type='output')) - test_block_3.setPos(0, -100) - scene.addItem(test_block_3) + # test_block_3 = OCBCodeBlock(title="Mon IA (par blocks ?)", source=SOURCE_TEST_2) + # for _ in range(2): + # test_block_3.add_socket(OCBSocket(test_block_3, socket_type='input')) + # for _ in range(1): + # test_block_3.add_socket(OCBSocket(test_block_3, socket_type='output')) + # test_block_3.setPos(0, -100) + # scene.addItem(test_block_3) - # for i in range(3): - # edge = OCBEdge( - # source_socket=test_block_3.sockets_out[0], - # destination_socket=test_block_2.sockets_in[i] - # ) - # scene.addItem(edge) - - scene.save('scene.ipyg') - scene.load('scene.ipyg') + # # for i in range(3): + # # edge = OCBEdge( + # # source_socket=test_block_3.sockets_out[0], + # # destination_socket=test_block_2.sockets_in[i] + # # ) + # # scene.addItem(edge) wnd.show() sys.exit(app.exec_()) diff --git a/opencodeblocks/graphics/widget.py b/opencodeblocks/graphics/widget.py index c42bc459..560c26bd 100644 --- a/opencodeblocks/graphics/widget.py +++ b/opencodeblocks/graphics/widget.py @@ -3,7 +3,10 @@ """ Module for the OCB Widget """ +import os + from PyQt5.QtWidgets import QVBoxLayout, QWidget +from PyQt5.QtCore import Qt from opencodeblocks.graphics.scene import OCBScene from opencodeblocks.graphics.view import OCBView @@ -14,6 +17,7 @@ class OCBWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) + self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose) self.layout = QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) @@ -21,7 +25,40 @@ def __init__(self, parent=None): # Graphics Scene self.scene = OCBScene() + self.scene.addHasBeenModifiedListener(self.updateTitle) # Graphics View self.view = OCBView(self.scene) self.layout.addWidget(self.view) + + self.savepath = None + + def updateTitle(self): + """ Update the window title. """ + if self.savepath is None: + title = 'New Graph' + else: + title = os.path.basename(self.savepath) + if self.isModified(): + title += "*" + self.setWindowTitle(title) + + def isModified(self) -> bool: + """ Return True if the scene has been modified, False otherwise. """ + return self.scene.has_been_modified + + @property + def savepath(self): + """ Current cached file save path. Update window title when set.""" + return self._savepath + @savepath.setter + def savepath(self, value:str): + self._savepath = value + self.updateTitle() + + def save(self): + self.scene.save(self.savepath) + + def load(self, filepath:str): + self.scene.load(filepath) + self.savepath = filepath diff --git a/opencodeblocks/graphics/window.py b/opencodeblocks/graphics/window.py index c960e362..06c24b17 100644 --- a/opencodeblocks/graphics/window.py +++ b/opencodeblocks/graphics/window.py @@ -4,119 +4,202 @@ """ Module for the OCB Window """ import os -from types import FunctionType -from typing import Optional -from PyQt5.QtCore import QEvent +from PyQt5.QtCore import QPoint, QSettings, QSize, Qt, QSignalMapper +from PyQt5.QtGui import QCloseEvent, QKeySequence -from PyQt5.QtWidgets import QAction, QFileDialog, QMainWindow, QMenu, QMessageBox +from PyQt5.QtWidgets import QDockWidget, QListWidget, QWidget, QAction, QFileDialog, QMainWindow,\ + QMessageBox, QMdiArea from opencodeblocks import __appname__ as application_name from opencodeblocks.graphics.view import MODE_EDITING from opencodeblocks.graphics.widget import OCBWidget + class OCBWindow(QMainWindow): - """ Main window of the OpenCodeBlocks Qt-based application. + """ Main window of the OpenCodeBlocks Qt-based application. """ - Args: - width: Initial window witdh. - height: Initial window height. - x_offset: Initial window horizonal offset. - y_offset: Initial window vertical offset. + def __init__(self): + super().__init__() - """ + self.mdiArea = QMdiArea() + self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) + self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) + self.setCentralWidget(self.mdiArea) - def __init__(self, width:int=800, height:int=600, x_offset:int=0, y_offset:int=0) -> None: - super().__init__() - # Cached save path - self._savepath = None + self.mdiArea.subWindowActivated.connect(self.updateMenus) + self.windowMapper = QSignalMapper(self) + self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow) # Menus - self.menubar = self.menuBar() - self.createFilemenu() - self.createEditmenu() + self.createActions() + self.createMenus() + self.createToolBars() + + # BlocksDock + self.createBlocksDock() # StatusBar self.statusbar = self.statusBar() - # OCB Widget - self.ocb_widget = OCBWidget(self) - self.ocb_widget.scene.addHasBeenModifiedListener(self.changeTitle) - self.setCentralWidget(self.ocb_widget) + self.updateMenus() # Window properties - self.setGeometry(x_offset, y_offset, width, height) - self.changeTitle() + self.readSettings() self.show() - @property - def savepath(self): - """ Current cached file save path. Update window title when set.""" - return self._savepath - @savepath.setter - def savepath(self, value:str): - self._savepath = value - self.changeTitle() - - def changeTitle(self): - """ Update the window title. """ - title = f"{application_name} - " - if self.savepath is None: - title += 'New' - else: - title += os.path.basename(self.savepath) - if self.isModified(): - title += "*" - self.setWindowTitle(title) - - def addMenuAction(self, menu:QMenu, name:str, trigger_func:FunctionType, - tooltip:Optional[str]=None, shortcut:Optional[str]=None): - """ Add an action to a given menu. - - Args: - menu: Menu in which to add action. - name: Display name of the action. - trigger_func: Function to trigger when the action is performed. - tooltip: Tooltip to show when hovering action. - shortcut: Shortcut to perform action. - - """ - action = QAction(name, self) - if shortcut is not None: - action.setShortcut(shortcut) - if tooltip is not None: - action.setToolTip(tooltip) - action.triggered.connect(trigger_func) - menu.addAction(action) - - def createFilemenu(self): + def createToolBars(self): + pass + + def createBlocksDock(self): + self.block_list = QListWidget() + self.block_list.addItem("Data loading") + self.block_list.addItem("Data normalization") + self.block_list.addItem("Data visualisation") + self.block_list.addItem("Data preprocessing") + self.block_list.addItem("Data reshape") + self.block_list.addItem("Model definition") + self.block_list.addItem("Model training") + self.block_list.addItem("Model prediction") + self.block_list.addItem("Model evaluation") + + self.items = QDockWidget("Blocks") + self.items.setWidget(self.block_list) + self.items.setFloating(False) + + self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.items) + + def updateMenus(self): + pass + + def createActions(self): + """ Create all menu actions. """ + # File + self.actNew = QAction('&New', statusTip='Create new ipygraph', + shortcut='Ctrl+N', triggered=self.onFileNew) + self.actOpen = QAction('&Open', statusTip='Open an ipygraph', + shortcut='Ctrl+O', triggered=self.onFileOpen) + self.actSave = QAction('&Save', statusTip='Save the ipygraph', + shortcut='Ctrl+S', triggered=self.onFileSave) + self.actSaveAs = QAction('Save &As...', statusTip='Save the ipygraph as...', + shortcut='Ctrl+Shift+S', triggered=self.onFileSaveAs) + self.actQuit = QAction('&Quit', statusTip='Save and Quit the application', + shortcut='Ctrl+Q', triggered=self.close) + + # Edit + self.actUndo = QAction('&Undo', statusTip='Undo last operation', + shortcut='Ctrl+Z', triggered=self.onEditUndo) + self.actRedo = QAction('&Redo', statusTip='Redo last operation', + shortcut='Ctrl+Y', triggered=self.onEditRedo) + self.actCut = QAction('Cu&t', statusTip='Cut to clipboard', + shortcut='Ctrl+X', triggered=self.onEditCut) + self.actCopy = QAction('&Copy', statusTip='Copy to clipboard', + shortcut='Ctrl+C', triggered=self.onEditCopy) + self.actPaste = QAction('&Paste', statusTip='Paste from clipboard', + shortcut='Ctrl+V', triggered=self.onEditPaste) + self.actDel = QAction('&Del', statusTip='Delete selected items', + shortcut='Del', triggered=self.onEditDelete) + + # Window + self.actClose = QAction("Cl&ose", self, + statusTip="Close the active window", + triggered=self.mdiArea.closeActiveSubWindow) + self.actCloseAll = QAction("Close &All", self, + statusTip="Close all the windows", + triggered=self.mdiArea.closeAllSubWindows) + self.actTile = QAction("&Tile", self, statusTip="Tile the windows", + triggered=self.mdiArea.tileSubWindows) + self.actCascade = QAction("&Cascade", self, + statusTip="Cascade the windows", + triggered=self.mdiArea.cascadeSubWindows) + self.actNext = QAction("Ne&xt", self, + shortcut=QKeySequence.StandardKey.NextChild, + statusTip="Move the focus to the next window", + triggered=self.mdiArea.activateNextSubWindow) + self.actPrevious = QAction("Pre&vious", self, + shortcut=QKeySequence.StandardKey.PreviousChild, + statusTip="Move the focus to the previous window", + triggered=self.mdiArea.activatePreviousSubWindow) + self.actSeparator = QAction(self) + self.actSeparator.setSeparator(True) + + def createMenus(self): """ Create the File menu with linked shortcuts. """ - filemenu = self.menubar.addMenu('&File') - self.addMenuAction(filemenu, '&New', self.onFileNew, 'Create new ipygraph', 'Ctrl+N') - filemenu.addSeparator() - self.addMenuAction(filemenu, '&Open', self.onFileOpen, 'Open an ipygraph', 'Ctrl+O') - self.addMenuAction(filemenu, '&Save', self.onFileSave, 'Save the ipygraph', 'Ctrl+S') - self.addMenuAction(filemenu, 'Save &As...', - self.onFileSaveAs, 'Save the graph as...', 'Ctrl+Shift+S') - filemenu.addSeparator() - self.addMenuAction(filemenu, '&Quit', self.close, 'Save and Quit the application', 'Ctrl+Q') + self.filemenu = self.menuBar().addMenu('&File') + self.filemenu.addAction(self.actNew) + self.filemenu.addAction(self.actOpen) + self.filemenu.addSeparator() + self.filemenu.addAction(self.actSave) + self.filemenu.addAction(self.actSaveAs) + self.filemenu.addSeparator() + self.filemenu.addAction(self.actQuit) + + self.editmenu = self.menuBar().addMenu('&Edit') + self.editmenu.addAction(self.actUndo) + self.editmenu.addAction(self.actRedo) + self.editmenu.addSeparator() + self.editmenu.addAction(self.actCut) + self.editmenu.addAction(self.actCopy) + self.editmenu.addAction(self.actPaste) + self.editmenu.addSeparator() + self.editmenu.addAction(self.actDel) + + self.windowMenu = self.menuBar().addMenu("&Window") + self.updateWindowMenu() + self.windowMenu.aboutToShow.connect(self.updateWindowMenu) + + self.menuBar().addSeparator() + + def updateWindowMenu(self): + self.windowMenu.clear() + self.windowMenu.addAction(self.actClose) + self.windowMenu.addAction(self.actCloseAll) + self.windowMenu.addSeparator() + self.windowMenu.addAction(self.actTile) + self.windowMenu.addAction(self.actCascade) + self.windowMenu.addSeparator() + self.windowMenu.addAction(self.actNext) + self.windowMenu.addAction(self.actPrevious) + self.windowMenu.addAction(self.actSeparator) + + windows = self.mdiArea.subWindowList() + self.actSeparator.setVisible(len(windows) != 0) + + for i, window in enumerate(windows): + child = window.widget() + + text = "%d %s" % (i + 1, child.windowTitle()) + if i < 9: + text = '&' + text + + action = self.windowMenu.addAction(text) + action.setCheckable(True) + action.setChecked(child is self.activeMdiChild()) + action.triggered.connect(self.windowMapper.map) + self.windowMapper.setMapping(action, window) + + def createNewMdiChild(self, filename:str=None): + """ Create a new graph subwindow loading a file if a path is given. """ + ocb_widget = OCBWidget() + if filename is not None: + ocb_widget.scene.load(filename) + ocb_widget.savepath = filename + return self.mdiArea.addSubWindow(ocb_widget) def onFileNew(self): """ Create a new file. """ - if self.maybeSave(): - self.ocb_widget.scene.clear() - self.savepath = None + subwnd = self.createNewMdiChild() + subwnd.show() def onFileOpen(self): """ Open a file. """ - if self.maybeSave(): - filename, _ = QFileDialog.getOpenFileName(self, 'Open ipygraph from file') - if filename == '': - return - if os.path.isfile(filename): - self.ocb_widget.scene.load(filename) - self.statusbar.showMessage(f"Successfully loaded {filename}") - self.savepath = filename + filename, _ = QFileDialog.getOpenFileName(self, 'Open ipygraph from file') + if filename == '': + return + if os.path.isfile(filename): + subwnd = self.createNewMdiChild(filename) + subwnd.show() + self.statusbar.showMessage(f"Successfully loaded {filename}", 2000) def onFileSave(self) -> bool: """ Save file. @@ -125,10 +208,13 @@ def onFileSave(self) -> bool: True if the file was successfully saved, False otherwise. """ - if self.savepath is None: - return self.onFileSaveAs() - self.ocb_widget.scene.save(self.savepath) - self.statusbar.showMessage(f"Successfully saved ipygraph {self.savepath}") + current_window = self.activeMdiChild() + if current_window is not None: + if current_window.savepath is None: + return self.onFileSaveAs() + current_window.save() + self.statusbar.showMessage( + f"Successfully saved ipygraph at {current_window.savepath}", 2000) return True def onFileSaveAs(self) -> bool: @@ -138,64 +224,68 @@ def onFileSaveAs(self) -> bool: True if the file was successfully saved, False otherwise. """ - filename, _ = QFileDialog.getSaveFileName(self, 'Save ipygraph to file') - if filename == '': - return False - if os.path.isfile(filename): - self.savepath = filename - self.onFileSave() - return True - - def createEditmenu(self): - """ Create the Edit menu with linked shortcuts. """ - editmenu = self.menubar.addMenu('&Edit') - self.addMenuAction(editmenu, '&Undo', self.onEditUndo,'Undo last operation', 'Ctrl+Z') - self.addMenuAction(editmenu, '&Redo', self.onEditRedo, 'Redo last operation', 'Ctrl+Y') - self.addMenuAction(editmenu, 'Cu&t', self.onEditCut, 'Cut to clipboard', 'Ctrl+X') - self.addMenuAction(editmenu, '&Copy', self.onEditCopy, 'Copy to clipboard', 'Ctrl+C') - self.addMenuAction(editmenu, '&Paste', self.onEditPaste, 'Paste from clipboard', 'Ctrl+V') - self.addMenuAction(editmenu, '&Del', self.onEditDelete, 'Delete selected items', 'Del') + current_window = self.activeMdiChild() + if current_window is not None: + filename, _ = QFileDialog.getSaveFileName(self, 'Save ipygraph to file') + if filename == '': + return False + if os.path.isfile(filename): + current_window.savepath = filename + self.onFileSave() + return True + return False def onEditUndo(self): """ Undo last operation if not in edit mode. """ - if self.ocb_widget.view.mode != MODE_EDITING: - self.ocb_widget.scene.history.undo() + current_window = self.activeMdiChild() + if current_window is not None and current_window.view.mode != MODE_EDITING: + current_window.scene.history.undo() def onEditRedo(self): """ Redo last operation if not in edit mode. """ - if self.ocb_widget.view.mode != MODE_EDITING: - self.ocb_widget.scene.history.redo() + current_window = self.activeMdiChild() + if current_window is not None and current_window.view.mode != MODE_EDITING: + current_window.scene.history.redo() def onEditCut(self): """ Cut the selected items if not in edit mode. """ - if self.ocb_widget.view.mode != MODE_EDITING: - self.ocb_widget.scene.clipboard.cut() + current_window = self.activeMdiChild() + if current_window is not None and current_window.view.mode != MODE_EDITING: + current_window.scene.clipboard.cut() def onEditCopy(self): """ Copy the selected items if not in edit mode. """ - if self.ocb_widget.view.mode != MODE_EDITING: - self.ocb_widget.scene.clipboard.copy() + current_window = self.activeMdiChild() + if current_window is not None and current_window.view.mode != MODE_EDITING: + current_window.scene.clipboard.copy() def onEditPaste(self): """ Paste the selected items if not in edit mode. """ - if self.ocb_widget.view.mode != MODE_EDITING: - self.ocb_widget.scene.clipboard.paste() + current_window = self.activeMdiChild() + if current_window is not None and current_window.view.mode != MODE_EDITING: + current_window.scene.clipboard.paste() def onEditDelete(self): """ Delete the selected items if not in edit mode. """ - if self.ocb_widget.view.mode != MODE_EDITING: - self.ocb_widget.view.deleteSelected() - - def closeEvent(self, event:QEvent): + current_window = self.activeMdiChild() + if current_window is not None and current_window.view.mode != MODE_EDITING: + current_window.view.deleteSelected() + + # def closeEvent(self, event:QEvent): + # """ Save and quit the application. """ + # if self.maybeSave(): + # event.accept() + # else: + # event.ignore() + + def closeEvent(self, event:QCloseEvent): """ Save and quit the application. """ - if self.maybeSave(): - event.accept() - else: + self.mdiArea.closeAllSubWindows() + if self.mdiArea.currentSubWindow(): event.ignore() - - def isModified(self) -> bool: - """ Return True if the scene has been modified, False otherwise. """ - return self.centralWidget().scene.has_been_modified + else: + self.writeSettings() + event.accept() def maybeSave(self) -> bool: """ Ask for save and returns if the file should be closed. @@ -219,3 +309,26 @@ def maybeSave(self) -> bool: if answer == QMessageBox.StandardButton.Discard: return True return False + + def activeMdiChild(self) -> OCBWidget: + """ Get the active OCBWidget if existing. """ + activeSubWindow = self.mdiArea.activeSubWindow() + if activeSubWindow is not None: + return activeSubWindow.widget() + return None + + def readSettings(self): + settings = QSettings('AutopIA', 'OpenCodeBlocks') + pos = settings.value('pos', QPoint(200, 200)) + size = settings.value('size', QSize(400, 400)) + self.move(pos) + self.resize(size) + + def writeSettings(self): + settings = QSettings('AutopIA', 'OpenCodeBlocks') + settings.setValue('pos', self.pos()) + settings.setValue('size', self.size()) + + def setActiveSubWindow(self, window): + if window: + self.mdiArea.setActiveSubWindow(window) From 44e9e490248fca41557ac771c30d2f82c45f6d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Math=C3=AFs=20F=C3=A9d=C3=A9rico?= Date: Wed, 3 Nov 2021 18:58:17 +0100 Subject: [PATCH 2/6] :beetle: Bugfix SaveAs was not creating new files --- opencodeblocks/graphics/scene/scene.py | 9 ++------- opencodeblocks/graphics/window.py | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/opencodeblocks/graphics/scene/scene.py b/opencodeblocks/graphics/scene/scene.py index c7b6c68b..6708e1ea 100644 --- a/opencodeblocks/graphics/scene/scene.py +++ b/opencodeblocks/graphics/scene/scene.py @@ -54,14 +54,9 @@ def has_been_modified(self): return self._has_been_modified @has_been_modified.setter def has_been_modified(self, value:bool): - if not self._has_been_modified and value: - self._has_been_modified = value - - # Call listeners - for callback in self._has_been_modified_listeners: - callback() - self._has_been_modified = value + for callback in self._has_been_modified_listeners: + callback() def addHasBeenModifiedListener(self, callback:FunctionType): """ Add a callback that will trigger when the scene has been modified. """ diff --git a/opencodeblocks/graphics/window.py b/opencodeblocks/graphics/window.py index 06c24b17..44e20e79 100644 --- a/opencodeblocks/graphics/window.py +++ b/opencodeblocks/graphics/window.py @@ -229,8 +229,7 @@ def onFileSaveAs(self) -> bool: filename, _ = QFileDialog.getSaveFileName(self, 'Save ipygraph to file') if filename == '': return False - if os.path.isfile(filename): - current_window.savepath = filename + current_window.savepath = filename self.onFileSave() return True return False From cc04b463a011b4632b3dbc32c4672e4aab83a879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Math=C3=AFs=20F=C3=A9d=C3=A9rico?= Date: Wed, 3 Nov 2021 19:05:52 +0100 Subject: [PATCH 3/6] :tada: Add isMaximized to window QSettings --- opencodeblocks/graphics/window.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opencodeblocks/graphics/window.py b/opencodeblocks/graphics/window.py index 44e20e79..00cc2430 100644 --- a/opencodeblocks/graphics/window.py +++ b/opencodeblocks/graphics/window.py @@ -322,11 +322,14 @@ def readSettings(self): size = settings.value('size', QSize(400, 400)) self.move(pos) self.resize(size) + if settings.value('isMaximized', False) == 'true': + self.showMaximized() def writeSettings(self): settings = QSettings('AutopIA', 'OpenCodeBlocks') settings.setValue('pos', self.pos()) settings.setValue('size', self.size()) + settings.setValue('isMaximized', self.isMaximized()) def setActiveSubWindow(self, window): if window: From 6aec6709b97c31e329c5355dfd164a52f164fd97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Math=C3=AFs=20F=C3=A9d=C3=A9rico?= Date: Thu, 4 Nov 2021 19:22:21 +0100 Subject: [PATCH 4/6] :tada: Add mdiArea TabbedView mode --- opencodeblocks/graphics/window.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/opencodeblocks/graphics/window.py b/opencodeblocks/graphics/window.py index 00cc2430..132dc82f 100644 --- a/opencodeblocks/graphics/window.py +++ b/opencodeblocks/graphics/window.py @@ -23,8 +23,12 @@ def __init__(self): super().__init__() self.mdiArea = QMdiArea() - self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) - self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) + self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) + self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) + self.mdiArea.setViewMode(QMdiArea.ViewMode.TabbedView) + self.mdiArea.setDocumentMode(True) + self.mdiArea.setTabsMovable(True) + self.mdiArea.setTabsClosable(True) self.setCentralWidget(self.mdiArea) self.mdiArea.subWindowActivated.connect(self.updateMenus) From 4c3655d54e5c49f020caebc624836b5d6481f4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Math=C3=AFs=20F=C3=A9d=C3=A9rico?= Date: Thu, 4 Nov 2021 19:48:07 +0100 Subject: [PATCH 5/6] :art: Add dark mode --- opencodeblocks/graphics/qss/__init__.py | 20 + opencodeblocks/graphics/qss/dark_resources.py | 509 ++++++++++++++++++ opencodeblocks/graphics/qss/ocb.qss | 31 ++ opencodeblocks/graphics/qss/ocb_dark.qss | 1 + opencodeblocks/graphics/window.py | 8 + 5 files changed, 569 insertions(+) create mode 100644 opencodeblocks/graphics/qss/__init__.py create mode 100644 opencodeblocks/graphics/qss/dark_resources.py create mode 100644 opencodeblocks/graphics/qss/ocb.qss create mode 100644 opencodeblocks/graphics/qss/ocb_dark.qss diff --git a/opencodeblocks/graphics/qss/__init__.py b/opencodeblocks/graphics/qss/__init__.py new file mode 100644 index 00000000..5a5ecf9d --- /dev/null +++ b/opencodeblocks/graphics/qss/__init__.py @@ -0,0 +1,20 @@ +# OpenCodeBlock an open-source tool for modular visual programing in python +# Copyright (C) 2021 Mathïs FEDERICO + +""" Module for the OCB qss and styles. """ + +from typing import List + +from PyQt5.QtCore import QFile +from PyQt5.QtWidgets import QApplication + +from opencodeblocks.graphics.qss import dark_resources + +def loadStylesheets(filenames:List[str]): + styles = '' + for filename in filenames: + file = QFile(filename) + file.open(QFile.ReadOnly | QFile.Text) + stylesheet = file.readAll() + styles += "\n" + str(stylesheet, encoding='utf-8') + QApplication.instance().setStyleSheet(styles) diff --git a/opencodeblocks/graphics/qss/dark_resources.py b/opencodeblocks/graphics/qss/dark_resources.py new file mode 100644 index 00000000..358c0113 --- /dev/null +++ b/opencodeblocks/graphics/qss/dark_resources.py @@ -0,0 +1,509 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created by: The Resource Compiler for PyQt5 (Qt v5.11.2) +# +# WARNING! All changes made in this file will be lost! + +from qtpy import QtCore + +qt_resource_data = b"\ +\x00\x00\x05\x1a\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x0e\x00\x00\x00\x0e\x08\x06\x00\x00\x00\x1f\x48\x2d\xd1\ +\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\ +\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\x65\x52\x65\x61\x64\ +\x79\x71\xc9\x65\x3c\x00\x00\x03\x76\x69\x54\x58\x74\x58\x4d\x4c\ +\x3a\x63\x6f\x6d\x2e\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\ +\x00\x00\x00\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\ +\x69\x6e\x3d\x22\xef\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\ +\x30\x4d\x70\x43\x65\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\ +\x7a\x6b\x63\x39\x64\x22\x3f\x3e\x20\x3c\x78\x3a\x78\x6d\x70\x6d\ +\x65\x74\x61\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\ +\x62\x65\x3a\x6e\x73\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\ +\x6d\x70\x74\x6b\x3d\x22\x41\x64\x6f\x62\x65\x20\x58\x4d\x50\x20\ +\x43\x6f\x72\x65\x20\x35\x2e\x36\x2d\x63\x31\x34\x32\x20\x37\x39\ +\x2e\x31\x36\x30\x39\x32\x34\x2c\x20\x32\x30\x31\x37\x2f\x30\x37\ +\x2f\x31\x33\x2d\x30\x31\x3a\x30\x36\x3a\x33\x39\x20\x20\x20\x20\ +\x20\x20\x20\x20\x22\x3e\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ +\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\ +\x61\x78\x2d\x6e\x73\x23\x22\x3e\x20\x3c\x72\x64\x66\x3a\x44\x65\ +\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\ +\x6f\x75\x74\x3d\x22\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\ +\x4d\x4d\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\ +\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\ +\x6d\x6d\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x73\x74\x52\x65\x66\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\ +\x65\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\ +\x79\x70\x65\x2f\x52\x65\x73\x6f\x75\x72\x63\x65\x52\x65\x66\x23\ +\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\ +\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x22\x20\x78\x6d\x70\x4d\x4d\ +\x3a\x4f\x72\x69\x67\x69\x6e\x61\x6c\x44\x6f\x63\x75\x6d\x65\x6e\ +\x74\x49\x44\x3d\x22\x78\x6d\x70\x2e\x64\x69\x64\x3a\x38\x36\x30\ +\x65\x64\x35\x30\x33\x2d\x39\x36\x37\x33\x2d\x32\x30\x34\x31\x2d\ +\x62\x65\x61\x65\x2d\x64\x37\x39\x38\x64\x65\x33\x38\x66\x33\x63\ +\x63\x22\x20\x78\x6d\x70\x4d\x4d\x3a\x44\x6f\x63\x75\x6d\x65\x6e\ +\x74\x49\x44\x3d\x22\x78\x6d\x70\x2e\x64\x69\x64\x3a\x36\x37\x32\ +\x43\x34\x33\x30\x30\x32\x45\x45\x35\x31\x31\x45\x39\x38\x30\x41\ +\x32\x44\x31\x33\x31\x39\x42\x44\x42\x39\x44\x44\x35\x22\x20\x78\ +\x6d\x70\x4d\x4d\x3a\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\ +\x22\x78\x6d\x70\x2e\x69\x69\x64\x3a\x36\x37\x32\x43\x34\x32\x46\ +\x46\x32\x45\x45\x35\x31\x31\x45\x39\x38\x30\x41\x32\x44\x31\x33\ +\x31\x39\x42\x44\x42\x39\x44\x44\x35\x22\x20\x78\x6d\x70\x3a\x43\ +\x72\x65\x61\x74\x6f\x72\x54\x6f\x6f\x6c\x3d\x22\x41\x64\x6f\x62\ +\x65\x20\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\x43\x20\x32\ +\x30\x31\x38\x20\x28\x57\x69\x6e\x64\x6f\x77\x73\x29\x22\x3e\x20\ +\x3c\x78\x6d\x70\x4d\x4d\x3a\x44\x65\x72\x69\x76\x65\x64\x46\x72\ +\x6f\x6d\x20\x73\x74\x52\x65\x66\x3a\x69\x6e\x73\x74\x61\x6e\x63\ +\x65\x49\x44\x3d\x22\x78\x6d\x70\x2e\x69\x69\x64\x3a\x33\x61\x65\ +\x34\x35\x31\x63\x30\x2d\x62\x37\x63\x35\x2d\x64\x65\x34\x37\x2d\ +\x39\x31\x33\x61\x2d\x64\x36\x64\x36\x37\x39\x61\x30\x34\x35\x33\ +\x31\x22\x20\x73\x74\x52\x65\x66\x3a\x64\x6f\x63\x75\x6d\x65\x6e\ +\x74\x49\x44\x3d\x22\x78\x6d\x70\x2e\x64\x69\x64\x3a\x38\x36\x30\ +\x65\x64\x35\x30\x33\x2d\x39\x36\x37\x33\x2d\x32\x30\x34\x31\x2d\ +\x62\x65\x61\x65\x2d\x64\x37\x39\x38\x64\x65\x33\x38\x66\x33\x63\ +\x63\x22\x2f\x3e\x20\x3c\x2f\x72\x64\x66\x3a\x44\x65\x73\x63\x72\ +\x69\x70\x74\x69\x6f\x6e\x3e\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\ +\x46\x3e\x20\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x3e\x20\ +\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\x6e\x64\x3d\x22\x72\ +\x22\x3f\x3e\x58\x7e\x03\x34\x00\x00\x01\x3a\x49\x44\x41\x54\x78\ +\xda\x9c\x52\x3d\x8a\x83\x50\x10\x1e\x7f\x50\x0c\x49\xa1\x78\x00\ +\x2b\x0b\xbb\x14\x39\x83\x39\x8d\x44\x6f\x60\x61\xe5\x85\xbc\x81\ +\xbd\xa8\x85\x58\xa4\x11\x2b\xed\x42\x40\x50\x97\x6f\x96\x27\xca\ +\x86\x65\xd9\x81\xe1\x0d\xdf\xcc\xf7\xe6\x57\x5a\xd7\x95\xee\xf7\ +\xfb\x3a\x8e\x23\xfd\x45\x2c\xcb\xa2\x2c\xcb\x24\xc9\xf7\xfd\xd5\ +\xb6\x6d\xba\x5c\x2e\xa4\x69\xda\xaf\xa4\x61\x18\xe8\xf5\x7a\xd1\ +\xfb\xfd\x26\x15\x99\x3c\xcf\xa3\xe7\xf3\x49\x8a\xa2\xb0\x7e\x92\ +\x79\x9e\x59\x4d\xd3\xa4\xae\xeb\x48\x16\x0e\x64\xd3\x75\x9d\x6e\ +\xb7\x1b\x3b\x61\x43\x61\x03\x83\x8d\x18\xc3\x30\x38\x9e\x89\xaa\ +\xaa\xb2\x5e\xaf\x57\x7a\x3c\x1e\x14\x04\x01\x9d\xcf\x67\x56\xd8\ +\xc0\xe0\x13\x71\xcc\xd9\x97\x53\x55\x15\x35\x4d\x43\xae\xeb\x52\ +\x14\x45\x8c\x39\x8e\xc3\x18\x7c\x7b\xd9\x4a\x45\x6f\xd3\x34\x51\ +\x92\x24\x1c\x08\x82\x20\x01\x83\x6f\xdf\xbf\xbc\xff\x05\x8e\xd3\ +\xe9\xf4\x63\x30\xc0\x04\x49\xbc\x07\x22\x7a\x0a\xc3\x90\x4b\x45\ +\x26\x51\x36\x30\xf8\x3e\x96\x0a\x41\x10\xb4\x2c\x4b\x8a\xe3\x98\ +\x15\xb6\xc0\xc5\x5a\x0e\xc3\x01\x90\xe7\x39\x2f\xb8\xae\xeb\xed\ +\xb3\x34\x4d\x79\xcf\x45\x51\x6c\x13\xdd\x32\x22\x58\xac\x05\x01\ +\x10\xb1\x47\xc8\x9e\x24\x7a\x54\x71\x7b\x7d\xdf\xf3\x00\x70\x76\ +\xdb\x8f\xf2\x77\x17\xcb\xb2\x1c\x7a\x6b\xdb\x96\xef\x55\xfa\xef\ +\x91\x7f\x09\x30\x00\x65\xad\x88\x4d\x91\x3a\xf7\xaf\x00\x00\x00\ +\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x06\x12\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ +\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\ +\x01\x00\x9a\x9c\x18\x00\x00\x05\x1c\x69\x54\x58\x74\x58\x4d\x4c\ +\x3a\x63\x6f\x6d\x2e\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\ +\x00\x00\x00\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\ +\x69\x6e\x3d\x22\xef\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\ +\x30\x4d\x70\x43\x65\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\ +\x7a\x6b\x63\x39\x64\x22\x3f\x3e\x20\x3c\x78\x3a\x78\x6d\x70\x6d\ +\x65\x74\x61\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\ +\x62\x65\x3a\x6e\x73\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\ +\x6d\x70\x74\x6b\x3d\x22\x41\x64\x6f\x62\x65\x20\x58\x4d\x50\x20\ +\x43\x6f\x72\x65\x20\x35\x2e\x36\x2d\x63\x31\x34\x32\x20\x37\x39\ +\x2e\x31\x36\x30\x39\x32\x34\x2c\x20\x32\x30\x31\x37\x2f\x30\x37\ +\x2f\x31\x33\x2d\x30\x31\x3a\x30\x36\x3a\x33\x39\x20\x20\x20\x20\ +\x20\x20\x20\x20\x22\x3e\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ +\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\ +\x61\x78\x2d\x6e\x73\x23\x22\x3e\x20\x3c\x72\x64\x66\x3a\x44\x65\ +\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\ +\x6f\x75\x74\x3d\x22\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\ +\x65\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x22\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\ +\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\ +\x6d\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x20\x78\x6d\x6c\x6e\ +\x73\x3a\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\ +\x2f\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\ +\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x20\x78\ +\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\ +\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\ +\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\ +\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x20\x78\x6d\ +\x70\x3a\x43\x72\x65\x61\x74\x6f\x72\x54\x6f\x6f\x6c\x3d\x22\x41\ +\x64\x6f\x62\x65\x20\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\ +\x43\x20\x32\x30\x31\x38\x20\x28\x57\x69\x6e\x64\x6f\x77\x73\x29\ +\x22\x20\x78\x6d\x70\x3a\x43\x72\x65\x61\x74\x65\x44\x61\x74\x65\ +\x3d\x22\x32\x30\x31\x39\x2d\x30\x32\x2d\x31\x32\x54\x31\x37\x3a\ +\x32\x31\x3a\x34\x31\x2b\x30\x31\x3a\x30\x30\x22\x20\x78\x6d\x70\ +\x3a\x4d\x6f\x64\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x31\ +\x39\x2d\x30\x32\x2d\x31\x32\x54\x31\x37\x3a\x32\x34\x3a\x32\x33\ +\x2b\x30\x31\x3a\x30\x30\x22\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\ +\x64\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x31\x39\x2d\x30\ +\x32\x2d\x31\x32\x54\x31\x37\x3a\x32\x34\x3a\x32\x33\x2b\x30\x31\ +\x3a\x30\x30\x22\x20\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3d\x22\ +\x69\x6d\x61\x67\x65\x2f\x70\x6e\x67\x22\x20\x70\x68\x6f\x74\x6f\ +\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\x72\x4d\x6f\x64\x65\x3d\x22\ +\x33\x22\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\ +\x50\x72\x6f\x66\x69\x6c\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\ +\x43\x36\x31\x39\x36\x36\x2d\x32\x2e\x31\x22\x20\x78\x6d\x70\x4d\ +\x4d\x3a\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\x22\x78\x6d\ +\x70\x2e\x69\x69\x64\x3a\x35\x30\x36\x35\x39\x31\x38\x61\x2d\x39\ +\x36\x66\x34\x2d\x35\x35\x34\x62\x2d\x62\x30\x32\x38\x2d\x62\x33\ +\x61\x33\x38\x32\x65\x63\x65\x38\x35\x32\x22\x20\x78\x6d\x70\x4d\ +\x4d\x3a\x44\x6f\x63\x75\x6d\x65\x6e\x74\x49\x44\x3d\x22\x78\x6d\ +\x70\x2e\x64\x69\x64\x3a\x35\x30\x36\x35\x39\x31\x38\x61\x2d\x39\ +\x36\x66\x34\x2d\x35\x35\x34\x62\x2d\x62\x30\x32\x38\x2d\x62\x33\ +\x61\x33\x38\x32\x65\x63\x65\x38\x35\x32\x22\x20\x78\x6d\x70\x4d\ +\x4d\x3a\x4f\x72\x69\x67\x69\x6e\x61\x6c\x44\x6f\x63\x75\x6d\x65\ +\x6e\x74\x49\x44\x3d\x22\x78\x6d\x70\x2e\x64\x69\x64\x3a\x35\x30\ +\x36\x35\x39\x31\x38\x61\x2d\x39\x36\x66\x34\x2d\x35\x35\x34\x62\ +\x2d\x62\x30\x32\x38\x2d\x62\x33\x61\x33\x38\x32\x65\x63\x65\x38\ +\x35\x32\x22\x3e\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x48\x69\x73\x74\ +\x6f\x72\x79\x3e\x20\x3c\x72\x64\x66\x3a\x53\x65\x71\x3e\x20\x3c\ +\x72\x64\x66\x3a\x6c\x69\x20\x73\x74\x45\x76\x74\x3a\x61\x63\x74\ +\x69\x6f\x6e\x3d\x22\x63\x72\x65\x61\x74\x65\x64\x22\x20\x73\x74\ +\x45\x76\x74\x3a\x69\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\x22\ +\x78\x6d\x70\x2e\x69\x69\x64\x3a\x35\x30\x36\x35\x39\x31\x38\x61\ +\x2d\x39\x36\x66\x34\x2d\x35\x35\x34\x62\x2d\x62\x30\x32\x38\x2d\ +\x62\x33\x61\x33\x38\x32\x65\x63\x65\x38\x35\x32\x22\x20\x73\x74\ +\x45\x76\x74\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x31\x39\x2d\x30\ +\x32\x2d\x31\x32\x54\x31\x37\x3a\x32\x31\x3a\x34\x31\x2b\x30\x31\ +\x3a\x30\x30\x22\x20\x73\x74\x45\x76\x74\x3a\x73\x6f\x66\x74\x77\ +\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x64\x6f\x62\x65\x20\ +\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\x43\x20\x32\x30\x31\ +\x38\x20\x28\x57\x69\x6e\x64\x6f\x77\x73\x29\x22\x2f\x3e\x20\x3c\ +\x2f\x72\x64\x66\x3a\x53\x65\x71\x3e\x20\x3c\x2f\x78\x6d\x70\x4d\ +\x4d\x3a\x48\x69\x73\x74\x6f\x72\x79\x3e\x20\x3c\x2f\x72\x64\x66\ +\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x20\x3c\x2f\ +\x72\x64\x66\x3a\x52\x44\x46\x3e\x20\x3c\x2f\x78\x3a\x78\x6d\x70\ +\x6d\x65\x74\x61\x3e\x20\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\ +\x65\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x5b\xd4\x83\xe3\x00\x00\x00\ +\x9c\x49\x44\x41\x54\x38\x8d\xed\x93\x2d\x0e\x02\x31\x10\x85\xdf\ +\x90\x35\x35\x18\xba\x28\x24\x08\x14\x97\xa8\xef\x3d\x2b\x6b\xeb\ +\x10\xf4\x0a\x24\x35\x1c\xa0\x02\x53\xd3\xd9\x30\x5c\xa0\x74\xb3\ +\xac\x41\xf0\x92\x51\xf3\xe6\x9b\x9f\x64\x48\x44\xb0\x46\x9b\x55\ +\xd5\xbf\x0f\x88\x31\x3e\xa7\x69\x3a\x32\xf3\x99\x99\x77\x8b\x01\ +\x29\xa5\x6d\x08\xe1\x06\xe0\x05\xa0\x79\xed\xb9\x15\x28\xe7\x3c\ +\x7a\xef\xaf\x00\xc6\xc5\x00\x22\x82\x88\xa0\x94\xb2\x77\xce\xdd\ +\xbf\x99\x60\x56\x43\x2f\x29\x22\x20\x22\x28\xa5\x60\xad\x6d\x7a\ +\xbb\x00\x22\x82\xd6\x1a\xc6\x98\x53\xb7\xcb\xa7\x88\x31\x3e\x98\ +\xf9\x52\x6b\x3d\xd4\x5a\x87\x96\x87\xfe\xbf\x80\x37\xe7\x76\x5e\ +\x24\x35\x48\x32\xb8\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ +\x82\ +\x00\x00\x01\x32\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x0b\x00\x00\x00\x0b\x08\x06\x00\x00\x00\xa9\xac\x77\x26\ +\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\ +\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\x65\x52\x65\x61\x64\ +\x79\x71\xc9\x65\x3c\x00\x00\x00\xd4\x49\x44\x41\x54\x78\xda\x6c\ +\xd0\xbd\x8a\xc2\x40\x14\x86\xe1\x64\xfc\x41\x0b\x41\xac\x5c\x11\ +\x0b\x0b\x1b\x2d\xd7\x1b\xd8\xeb\xd0\x42\x17\x6b\x2b\x2d\x14\x9b\ +\x14\x82\x7a\x0b\xb1\x30\x8b\xd7\x23\x6c\x21\x08\xb6\x62\xa5\xa2\ +\x60\x27\xb8\xef\xc8\x27\x0c\xab\x03\x4f\x26\xe4\x7c\x9c\xc9\x1c\ +\x3f\x8a\xa2\xa4\xe7\x79\x33\x34\x90\xf3\x5e\xd7\x09\x3f\xe8\x19\ +\x1e\x53\x54\x50\x83\xff\x46\x55\xf5\xc0\x86\x9b\x68\x63\xaf\x4e\ +\xdf\xb8\xe0\x8e\x2b\x5a\xaa\x77\x8c\x8e\xde\x3b\xc7\x06\xf8\x54\ +\xd7\x12\xfa\xaa\xe7\x8c\x13\x7a\x76\x2c\x60\x85\x01\x0e\x48\x3c\ +\x03\x6e\x78\x8c\x3a\x62\x4e\xc7\x0f\x5d\xf0\xb1\xe2\x4e\x38\x83\ +\x8d\xde\x6d\x47\x3b\xa5\x25\x86\xef\xc2\x37\xfd\xff\x11\x65\xed\ +\x5f\xee\x0c\xe3\xfa\x68\x8f\x9b\x60\x87\x14\xce\xe8\x3a\xb9\xbc\ +\xcd\x19\x0d\x3c\xc4\x1c\x69\x4d\x21\x8b\x85\x82\x45\xd5\x42\xa3\ +\x8b\x6c\xb1\xd6\x6c\xff\xfb\x55\x7d\xf4\x27\xc0\x00\x21\x29\x2e\ +\x78\x26\x38\xb6\x10\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\ +\x82\ +\x00\x00\x05\x41\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x0e\x00\x00\x00\x0e\x08\x06\x00\x00\x00\x1f\x48\x2d\xd1\ +\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\ +\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\x65\x52\x65\x61\x64\ +\x79\x71\xc9\x65\x3c\x00\x00\x03\x26\x69\x54\x58\x74\x58\x4d\x4c\ +\x3a\x63\x6f\x6d\x2e\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\ +\x00\x00\x00\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\ +\x69\x6e\x3d\x22\xef\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\ +\x30\x4d\x70\x43\x65\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\ +\x7a\x6b\x63\x39\x64\x22\x3f\x3e\x20\x3c\x78\x3a\x78\x6d\x70\x6d\ +\x65\x74\x61\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\ +\x62\x65\x3a\x6e\x73\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\ +\x6d\x70\x74\x6b\x3d\x22\x41\x64\x6f\x62\x65\x20\x58\x4d\x50\x20\ +\x43\x6f\x72\x65\x20\x35\x2e\x36\x2d\x63\x31\x34\x32\x20\x37\x39\ +\x2e\x31\x36\x30\x39\x32\x34\x2c\x20\x32\x30\x31\x37\x2f\x30\x37\ +\x2f\x31\x33\x2d\x30\x31\x3a\x30\x36\x3a\x33\x39\x20\x20\x20\x20\ +\x20\x20\x20\x20\x22\x3e\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ +\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\ +\x61\x78\x2d\x6e\x73\x23\x22\x3e\x20\x3c\x72\x64\x66\x3a\x44\x65\ +\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\ +\x6f\x75\x74\x3d\x22\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\ +\x65\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x22\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\ +\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x74\x52\x65\x66\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\ +\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\x73\ +\x6f\x75\x72\x63\x65\x52\x65\x66\x23\x22\x20\x78\x6d\x70\x3a\x43\ +\x72\x65\x61\x74\x6f\x72\x54\x6f\x6f\x6c\x3d\x22\x41\x64\x6f\x62\ +\x65\x20\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\x43\x20\x32\ +\x30\x31\x38\x20\x28\x57\x69\x6e\x64\x6f\x77\x73\x29\x22\x20\x78\ +\x6d\x70\x4d\x4d\x3a\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\ +\x22\x78\x6d\x70\x2e\x69\x69\x64\x3a\x30\x32\x31\x42\x34\x33\x42\ +\x44\x32\x45\x45\x35\x31\x31\x45\x39\x39\x36\x41\x46\x44\x44\x31\ +\x36\x37\x37\x37\x46\x37\x39\x46\x38\x22\x20\x78\x6d\x70\x4d\x4d\ +\x3a\x44\x6f\x63\x75\x6d\x65\x6e\x74\x49\x44\x3d\x22\x78\x6d\x70\ +\x2e\x64\x69\x64\x3a\x30\x32\x31\x42\x34\x33\x42\x45\x32\x45\x45\ +\x35\x31\x31\x45\x39\x39\x36\x41\x46\x44\x44\x31\x36\x37\x37\x37\ +\x46\x37\x39\x46\x38\x22\x3e\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x44\ +\x65\x72\x69\x76\x65\x64\x46\x72\x6f\x6d\x20\x73\x74\x52\x65\x66\ +\x3a\x69\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\x22\x78\x6d\x70\ +\x2e\x69\x69\x64\x3a\x30\x32\x31\x42\x34\x33\x42\x42\x32\x45\x45\ +\x35\x31\x31\x45\x39\x39\x36\x41\x46\x44\x44\x31\x36\x37\x37\x37\ +\x46\x37\x39\x46\x38\x22\x20\x73\x74\x52\x65\x66\x3a\x64\x6f\x63\ +\x75\x6d\x65\x6e\x74\x49\x44\x3d\x22\x78\x6d\x70\x2e\x64\x69\x64\ +\x3a\x30\x32\x31\x42\x34\x33\x42\x43\x32\x45\x45\x35\x31\x31\x45\ +\x39\x39\x36\x41\x46\x44\x44\x31\x36\x37\x37\x37\x46\x37\x39\x46\ +\x38\x22\x2f\x3e\x20\x3c\x2f\x72\x64\x66\x3a\x44\x65\x73\x63\x72\ +\x69\x70\x74\x69\x6f\x6e\x3e\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\ +\x46\x3e\x20\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x3e\x20\ +\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\x6e\x64\x3d\x22\x72\ +\x22\x3f\x3e\xf6\x1b\x54\x2f\x00\x00\x01\xb1\x49\x44\x41\x54\x78\ +\xda\x9c\x52\xbb\x4e\x5b\x41\x10\x3d\xb3\xde\xf5\xc5\x8f\x5c\xc9\ +\x0e\x4e\x6c\x39\xd0\xc4\x1f\x80\x84\x84\x1c\xc9\x5f\x60\x9c\x0f\ +\x00\x94\x2a\xa2\xa7\x81\xda\x45\x94\x22\x55\xc4\x3f\x24\x1f\x90\ +\x47\x91\x16\x51\x90\x22\x12\x25\x42\x89\x14\x25\x01\x5b\xa4\x01\ +\x6c\x63\x73\xb9\xd7\xcb\xce\x5c\xc7\xd8\x20\xa5\x60\xa5\xd5\x8e\ +\xce\x9c\x33\x3b\x2f\xb2\xd6\xe2\xf7\xea\x73\xdb\xfd\xf1\x1d\x44\ +\x16\xff\x3b\xd6\x12\xb2\x4f\x2b\x98\x7b\xff\x91\xe8\xd7\x4a\xc3\ +\xda\xf9\x12\x12\x7e\x1a\x94\x4e\x0a\x81\x14\x4d\x0b\x86\x71\xc0\ +\xb0\xd5\x46\x74\xda\x83\xee\x04\xd0\xfc\x53\xae\xb6\x88\xfe\xe1\ +\x57\x20\xa9\x59\x15\xb3\xf5\x48\x15\x8e\xd5\x40\x10\x42\x3f\x99\ +\x47\xf7\xd3\x0e\x14\xa7\x67\x87\x7d\xc0\x4b\x82\x92\x09\xf8\xb5\ +\x3a\x74\x21\x0f\xf2\x8c\x5c\xb6\x19\x63\x1f\x73\x54\x66\x46\x4a\ +\x8a\xe3\x1a\x0d\x32\x84\x07\xd5\x65\x3c\x6c\xac\xc3\x7f\xd6\x40\ +\xfb\x5d\x53\x5c\xc5\xb5\x26\xcc\x6c\x59\x32\xe9\xec\x7d\x76\x99\ +\xe8\xa9\x84\xc4\xba\xd8\xdf\x85\xbf\x54\x87\x79\x54\x46\xf1\xc5\ +\xab\x38\x66\xfe\x31\xae\x4e\x8e\xc4\x27\x6c\x8a\xeb\x57\x63\xa1\ +\x8b\x18\x0d\xce\xd0\x7a\xbb\x89\xab\xbf\x2d\x11\x88\xc8\xd9\x8c\ +\xb1\x6f\x5c\xff\xd4\x8f\x0c\xa6\x14\x28\x61\xee\x8c\x81\x7c\x87\ +\x45\x8e\x1a\xdd\x28\xd4\x24\x21\x91\xcd\xa1\xf8\xf2\x35\x4c\xa1\ +\xe4\xd2\x6b\xc9\x65\x9b\x31\xf6\x4d\x1e\x35\x31\x2c\xa4\x2b\x55\ +\x47\x2c\x23\x68\xff\xc1\xf1\x9b\x0d\xb9\x6c\x33\xc6\x3e\x19\x49\ +\x78\x3b\x55\x07\x9e\xef\x7c\x80\xed\x5d\x4a\x23\x86\xde\x40\xe0\ +\xf6\xf6\x16\xd2\x0b\x35\x74\xbe\x7d\x01\xa5\x6e\x16\x43\xf3\x1a\ +\xd9\xde\x40\x22\xf1\x48\x84\xe0\x5e\x4a\xc5\xb5\x0e\xfb\x17\x63\ +\x8c\x39\x4a\x79\xb2\x7a\xb2\x72\x91\xef\x81\x72\x06\x2a\x9f\x71\ +\x85\x8e\x5a\xfe\xaf\x83\x9c\x9e\xdb\x67\x6e\x0c\x45\x1e\x82\x83\ +\x9f\x30\x81\x6b\xe2\x7d\x97\xfc\x5a\x80\x01\x00\xf9\x5d\xa7\x18\ +\xdc\xa1\xb6\x98\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\ +\x00\x00\x06\x0b\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ +\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\ +\x01\x00\x9a\x9c\x18\x00\x00\x05\x1c\x69\x54\x58\x74\x58\x4d\x4c\ +\x3a\x63\x6f\x6d\x2e\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\ +\x00\x00\x00\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\ +\x69\x6e\x3d\x22\xef\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\ +\x30\x4d\x70\x43\x65\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\ +\x7a\x6b\x63\x39\x64\x22\x3f\x3e\x20\x3c\x78\x3a\x78\x6d\x70\x6d\ +\x65\x74\x61\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\ +\x62\x65\x3a\x6e\x73\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\ +\x6d\x70\x74\x6b\x3d\x22\x41\x64\x6f\x62\x65\x20\x58\x4d\x50\x20\ +\x43\x6f\x72\x65\x20\x35\x2e\x36\x2d\x63\x31\x34\x32\x20\x37\x39\ +\x2e\x31\x36\x30\x39\x32\x34\x2c\x20\x32\x30\x31\x37\x2f\x30\x37\ +\x2f\x31\x33\x2d\x30\x31\x3a\x30\x36\x3a\x33\x39\x20\x20\x20\x20\ +\x20\x20\x20\x20\x22\x3e\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ +\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\ +\x61\x78\x2d\x6e\x73\x23\x22\x3e\x20\x3c\x72\x64\x66\x3a\x44\x65\ +\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\ +\x6f\x75\x74\x3d\x22\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\ +\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\ +\x65\x2e\x63\x6f\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x22\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\ +\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\ +\x6d\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x20\x78\x6d\x6c\x6e\ +\x73\x3a\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\ +\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\ +\x2f\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\ +\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\ +\x6d\x2f\x78\x61\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x20\x78\ +\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\ +\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\ +\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\ +\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x20\x78\x6d\ +\x70\x3a\x43\x72\x65\x61\x74\x6f\x72\x54\x6f\x6f\x6c\x3d\x22\x41\ +\x64\x6f\x62\x65\x20\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\ +\x43\x20\x32\x30\x31\x38\x20\x28\x57\x69\x6e\x64\x6f\x77\x73\x29\ +\x22\x20\x78\x6d\x70\x3a\x43\x72\x65\x61\x74\x65\x44\x61\x74\x65\ +\x3d\x22\x32\x30\x31\x39\x2d\x30\x32\x2d\x31\x32\x54\x31\x37\x3a\ +\x32\x31\x3a\x34\x31\x2b\x30\x31\x3a\x30\x30\x22\x20\x78\x6d\x70\ +\x3a\x4d\x6f\x64\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x31\ +\x39\x2d\x30\x32\x2d\x31\x32\x54\x31\x37\x3a\x32\x34\x3a\x33\x39\ +\x2b\x30\x31\x3a\x30\x30\x22\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\ +\x64\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x31\x39\x2d\x30\ +\x32\x2d\x31\x32\x54\x31\x37\x3a\x32\x34\x3a\x33\x39\x2b\x30\x31\ +\x3a\x30\x30\x22\x20\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3d\x22\ +\x69\x6d\x61\x67\x65\x2f\x70\x6e\x67\x22\x20\x70\x68\x6f\x74\x6f\ +\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\x72\x4d\x6f\x64\x65\x3d\x22\ +\x33\x22\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\ +\x50\x72\x6f\x66\x69\x6c\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\ +\x43\x36\x31\x39\x36\x36\x2d\x32\x2e\x31\x22\x20\x78\x6d\x70\x4d\ +\x4d\x3a\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\x22\x78\x6d\ +\x70\x2e\x69\x69\x64\x3a\x34\x66\x61\x30\x33\x66\x64\x34\x2d\x38\ +\x63\x32\x66\x2d\x64\x31\x34\x31\x2d\x62\x37\x63\x62\x2d\x35\x32\ +\x38\x33\x39\x63\x30\x37\x32\x37\x39\x32\x22\x20\x78\x6d\x70\x4d\ +\x4d\x3a\x44\x6f\x63\x75\x6d\x65\x6e\x74\x49\x44\x3d\x22\x78\x6d\ +\x70\x2e\x64\x69\x64\x3a\x34\x66\x61\x30\x33\x66\x64\x34\x2d\x38\ +\x63\x32\x66\x2d\x64\x31\x34\x31\x2d\x62\x37\x63\x62\x2d\x35\x32\ +\x38\x33\x39\x63\x30\x37\x32\x37\x39\x32\x22\x20\x78\x6d\x70\x4d\ +\x4d\x3a\x4f\x72\x69\x67\x69\x6e\x61\x6c\x44\x6f\x63\x75\x6d\x65\ +\x6e\x74\x49\x44\x3d\x22\x78\x6d\x70\x2e\x64\x69\x64\x3a\x34\x66\ +\x61\x30\x33\x66\x64\x34\x2d\x38\x63\x32\x66\x2d\x64\x31\x34\x31\ +\x2d\x62\x37\x63\x62\x2d\x35\x32\x38\x33\x39\x63\x30\x37\x32\x37\ +\x39\x32\x22\x3e\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x48\x69\x73\x74\ +\x6f\x72\x79\x3e\x20\x3c\x72\x64\x66\x3a\x53\x65\x71\x3e\x20\x3c\ +\x72\x64\x66\x3a\x6c\x69\x20\x73\x74\x45\x76\x74\x3a\x61\x63\x74\ +\x69\x6f\x6e\x3d\x22\x63\x72\x65\x61\x74\x65\x64\x22\x20\x73\x74\ +\x45\x76\x74\x3a\x69\x6e\x73\x74\x61\x6e\x63\x65\x49\x44\x3d\x22\ +\x78\x6d\x70\x2e\x69\x69\x64\x3a\x34\x66\x61\x30\x33\x66\x64\x34\ +\x2d\x38\x63\x32\x66\x2d\x64\x31\x34\x31\x2d\x62\x37\x63\x62\x2d\ +\x35\x32\x38\x33\x39\x63\x30\x37\x32\x37\x39\x32\x22\x20\x73\x74\ +\x45\x76\x74\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x31\x39\x2d\x30\ +\x32\x2d\x31\x32\x54\x31\x37\x3a\x32\x31\x3a\x34\x31\x2b\x30\x31\ +\x3a\x30\x30\x22\x20\x73\x74\x45\x76\x74\x3a\x73\x6f\x66\x74\x77\ +\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x64\x6f\x62\x65\x20\ +\x50\x68\x6f\x74\x6f\x73\x68\x6f\x70\x20\x43\x43\x20\x32\x30\x31\ +\x38\x20\x28\x57\x69\x6e\x64\x6f\x77\x73\x29\x22\x2f\x3e\x20\x3c\ +\x2f\x72\x64\x66\x3a\x53\x65\x71\x3e\x20\x3c\x2f\x78\x6d\x70\x4d\ +\x4d\x3a\x48\x69\x73\x74\x6f\x72\x79\x3e\x20\x3c\x2f\x72\x64\x66\ +\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x20\x3c\x2f\ +\x72\x64\x66\x3a\x52\x44\x46\x3e\x20\x3c\x2f\x78\x3a\x78\x6d\x70\ +\x6d\x65\x74\x61\x3e\x20\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\ +\x65\x6e\x64\x3d\x22\x72\x22\x3f\x3e\xef\xbc\xde\xce\x00\x00\x00\ +\x95\x49\x44\x41\x54\x38\x8d\xed\x93\x21\x0e\x82\x31\x0c\x85\x5f\ +\xc9\xd4\x04\x86\xfd\x0e\x09\x02\xc5\x51\xe6\x76\xc8\xc9\xd9\x39\ +\x04\xbb\x02\xc9\x0c\x47\x40\x4d\xac\x1b\xe5\x02\x6c\x82\x3f\x24\ +\x08\x9a\xd4\xbd\x7e\x79\x7d\x69\x49\x44\xb0\xa6\x36\xab\xa6\x7f\ +\x1b\xc0\xcc\x3b\x66\x3e\xb5\xd6\x0e\x29\xa5\xc7\x27\x0e\x04\xc0\ +\x33\xc6\x78\xcd\x39\x6f\x47\x22\x35\x01\x2c\x21\x84\x4b\x29\x65\ +\x99\x68\xc6\x00\xef\xfd\xad\xf7\x0e\x00\x20\xa2\x21\xe0\x7b\x21\ +\x3a\xe7\x94\xd6\x1a\x44\x84\xd9\xb1\x4d\x1d\x58\x6b\x8f\xc6\x98\ +\xe9\x0a\x10\x91\xb7\x5d\x6b\x55\xb5\xd6\x3d\x33\x9f\x53\x4a\xf7\ +\x91\x8e\xfe\xbf\x80\x17\xa8\xc0\x5b\x7f\x18\x53\x58\x4b\x00\x00\ +\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ +\x00\x00\x01\x39\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\x0b\x00\x00\x00\x0b\x08\x06\x00\x00\x00\xa9\xac\x77\x26\ +\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\x61\x72\x65\ +\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\x65\x52\x65\x61\x64\ +\x79\x71\xc9\x65\x3c\x00\x00\x00\xdb\x49\x44\x41\x54\x78\xda\x6c\ +\xd0\xb1\xab\x41\x61\x18\xc7\xf1\x73\x4e\xb7\x3b\xdc\x85\x4c\xb8\ +\xca\x66\x61\xb9\x56\x29\x49\xd9\x4d\x12\x29\x32\x2b\x45\x49\x16\ +\x23\x77\xb8\x7f\xc0\x95\x3a\x0c\xfe\x08\x26\x83\xdd\x60\x61\x12\ +\x19\x84\xe4\x0f\x38\xbe\x6f\x3d\x74\xca\x7b\xea\x73\xde\xde\xf7\ +\xf9\xf5\xbc\x4f\xaf\x69\xdb\xf6\xa7\x61\x18\x03\x14\xe1\x33\xde\ +\xbf\x2b\xc6\x68\x5a\xfc\xfa\x88\x20\x06\x53\x23\x2a\xf5\x9e\x0a\ +\x97\x50\x41\x1a\x7b\xc4\xa5\xe3\x0f\x0e\x48\x4a\xbd\x66\xc9\xd5\ +\x47\xfc\xe1\x1b\x73\x94\x31\x43\x50\x46\x54\x75\x9f\xe5\x9a\x2d\ +\x87\x3b\xbc\x18\x49\x93\x1b\xf2\xcf\x80\x3b\xbc\x40\x03\x8e\xcc\ +\xaa\xd6\x36\x96\xba\x70\x02\xbf\xae\xa0\x29\xfb\xac\x2e\x3c\x81\ +\x07\x67\x14\x70\xc2\x97\x9c\xbf\xc2\x17\x04\xd0\xc1\x0e\x19\x4c\ +\x91\xc2\x06\x75\xf8\x55\xee\x43\x1e\xfc\x1f\x55\x84\x5d\x37\xad\ +\xe5\x7d\x43\x18\xaa\x8c\xea\xdc\xc2\x56\x8a\x8e\xc6\x4a\xea\xdd\ +\x87\x00\x03\x00\xa6\x62\x31\x34\x9c\xff\x4d\x8d\x00\x00\x00\x00\ +\x49\x45\x4e\x44\xae\x42\x60\x82\ +" + +qt_resource_name = b"\ +\x00\x05\ +\x00\x6f\xa6\x53\ +\x00\x69\ +\x00\x63\x00\x6f\x00\x6e\x00\x73\ +\x00\x1d\ +\x0d\x61\x33\xc7\ +\x00\x74\ +\x00\x61\x00\x62\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x5f\x00\x6e\x00\x6f\x00\x6e\x00\x73\x00\x65\x00\x6c\x00\x65\ +\x00\x63\x00\x74\x00\x65\x00\x64\x00\x5f\x00\x62\x00\x74\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x1b\ +\x02\x39\x96\x07\ +\x00\x73\ +\x00\x6d\x00\x61\x00\x6c\x00\x6c\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\ +\x00\x2d\x00\x6c\x00\x69\x00\x67\x00\x68\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x1e\ +\x0a\x11\x67\x27\ +\x00\x64\ +\x00\x6f\x00\x63\x00\x6b\x00\x74\x00\x69\x00\x74\x00\x6c\x00\x65\x00\x2d\x00\x6e\x00\x6f\x00\x72\x00\x6d\x00\x61\x00\x6c\x00\x2d\ +\x00\x62\x00\x74\x00\x6e\x00\x2d\x00\x6c\x00\x69\x00\x67\x00\x68\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x11\ +\x0c\x35\x80\x87\ +\x00\x74\ +\x00\x61\x00\x62\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x5f\x00\x62\x00\x74\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\ +\x00\x1a\ +\x00\x1b\xdc\x67\ +\x00\x73\ +\x00\x6d\x00\x61\x00\x6c\x00\x6c\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6c\x00\x65\x00\x66\x00\x74\x00\x2d\ +\x00\x6c\x00\x69\x00\x67\x00\x68\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ +\x00\x1d\ +\x08\xa2\xd1\xc7\ +\x00\x64\ +\x00\x6f\x00\x63\x00\x6b\x00\x74\x00\x69\x00\x74\x00\x6c\x00\x65\x00\x2d\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2d\x00\x62\ +\x00\x74\x00\x6e\x00\x2d\x00\x6c\x00\x69\x00\x67\x00\x68\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\ +" + +qt_resource_struct_v1 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x02\ +\x00\x00\x00\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x11\xaf\ +\x00\x00\x00\x50\x00\x00\x00\x00\x00\x01\x00\x00\x05\x1e\ +\x00\x00\x01\x30\x00\x00\x00\x00\x00\x01\x00\x00\x17\xbe\ +\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x34\ +\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x6a\ +\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +qt_resource_struct_v2 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x11\xaf\ +\x00\x00\x01\x68\xe2\x86\x4e\x20\ +\x00\x00\x00\x50\x00\x00\x00\x00\x00\x01\x00\x00\x05\x1e\ +\x00\x00\x01\x68\xe2\x86\x12\xbe\ +\x00\x00\x01\x30\x00\x00\x00\x00\x00\x01\x00\x00\x17\xbe\ +\x00\x00\x01\x68\xdb\xb6\x1d\x42\ +\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x34\ +\x00\x00\x01\x68\xdb\xb6\x1d\x49\ +\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x6a\ +\x00\x00\x01\x68\xe2\x95\x78\x3b\ +\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x68\xe2\x98\x0e\xbe\ +" + +qt_version = [int(v) for v in QtCore.qVersion().split('.')] +if qt_version < [5, 8, 0]: + rcc_version = 1 + qt_resource_struct = qt_resource_struct_v1 +else: + rcc_version = 2 + qt_resource_struct = qt_resource_struct_v2 + +def qInitResources(): + QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/opencodeblocks/graphics/qss/ocb.qss b/opencodeblocks/graphics/qss/ocb.qss new file mode 100644 index 00000000..13033cd1 --- /dev/null +++ b/opencodeblocks/graphics/qss/ocb.qss @@ -0,0 +1,31 @@ +QDMNodeContentWidget { + background: transparent; +} +QDMNodeContentWidget QFrame { + background: transparent; +} +QDMNodeContentWidget QTextEdit, +QDMNodeContentWidget QLineEdit { + background: #666; + color: #fff; +} +QDMNodeContentWidget QLabel { + color: #e0e0e0; + min-width: 150px; + max-width: 150px; + min-height: 45px; + max-height: 45px; + margin-left: 10px; + margin-top: 5px; + font-size: 28px; +} +QDMNodeContentWidget QLineEdit#calc_node_input { + width: 140px; + height: 36px; + margin-top: 5px; + margin-left: 5px; + font-size: 28px; +} +QGraphicsView { + selection-background-color: #fff; +} diff --git a/opencodeblocks/graphics/qss/ocb_dark.qss b/opencodeblocks/graphics/qss/ocb_dark.qss new file mode 100644 index 00000000..3e7b33d6 --- /dev/null +++ b/opencodeblocks/graphics/qss/ocb_dark.qss @@ -0,0 +1 @@ +QFrame,QDialog,QMainWindow{background:#474747}QSplitter,QMainWindow::separator{background:#474747}QStatusBar{background:#474747;color:#ccc}QTabWidget{border:0}QTabBar{background:#474747;color:#ccc}QMdiArea QTabBar,QMdiArea QTabWidget,QMdiArea QTabWidget::pane,QMdiArea QTabWidget::tab-bar,QMdiArea QTabBar::tab{height:17px}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:selected,QMdiArea QTabBar::tab:top:!selected:hover{border-top-left-radius:4px;border-top-right-radius:4px;padding:2px 8px;padding-top:0;padding-bottom:3px;min-width:8ex;border:1px solid #333;border-bottom:0}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #6d6d6d,stop : .1 #474747,stop : .89 #3f3f3f,stop : 1 #3f3f3f)}QMdiArea QTabBar::tab:top:selected{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #545454,stop : .89 #474747,stop : 1 #474747)}QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #727272,stop : .1 #4c4c4c,stop : .89 #444,stop : 1 #444)}QMdiArea QTabBar QToolButton{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #616161,stop : .89 #4f4f4f,stop : 1 #4f4f4f);border:1px solid #333;border-radius:0}QMdiArea QTabBar QToolButton::left-arrow{image:url(":icons/small_arrow_left-light.png")}QMdiArea QTabBar QToolButton::right-arrow{image:url(":icons/small_arrow_right-light.png")}QMdiArea QTabBar::close-button:selected{image:url(":icons/tab_close_btn.png");origin:border;subcontrol-origin:border;subcontrol-position:right bottom}QMdiArea QTabBar::close-button:!selected{image:url(":icons/tab_close_nonselected_btn.png")}QMdiSubWindow{border-size:1px;border-style:solid;background:#616161}QTabBar::tab:selected,QTabBar::tab:hover{color:#eee}QDockWidget{color:#ddd;font-weight:bold;titlebar-close-icon:url(":icons/docktitle-close-btn-light.png");titlebar-normal-icon:url(":icons/docktitle-normal-btn-light.png")}QDockWidget::title{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #3b3b3b,stop : 1 #2e2e2e);padding-top:4px;padding-right:22px;font-weight:bold}QDockWidget::close-button,QDockWidget::float-button{subcontrol-position:top right;subcontrol-origin:margin;text-align:center;icon-size:16px;width:14px;position:absolute;top:0;bottom:0;left:0;right:4px}QDockWidget::close-button{right:4px}QDockWidget::float-button{right:18px}QMenuBar{background:#474747}QMenuBar::item{spacing:3px;padding:3px 5px;color:#eee;background:transparent}QMenuBar::item:selected,QMenuBar::item:pressed{background:#4f9eee}QMenu{background:#474747;border:1px solid #2e2e2e}QMenu::item{background:#474747;color:#eee}QMenu::item:selected{background:#616161}QMenu::active{background:#616161;color:#eee}QMenu::separator{height:1px;background:#2e2e2e}QMenu::disabled,QMenu::item:disabled{color:#6e6e6e}QListView{background-color:#555;alternate-background-color:#434343}QListView::item{height:22px;color:#e6e6e6}QListView::item:hover{background:#6e6e6e}QListView::item::active:hover{color:#fff}QListView::item:selected,QListView::item::active:selected{color:#fff;background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #4f9eee,stop : 1 #2084ea);border:0}QPushButton{color:#e6e6e6;background:#555;border-color:#141414}QLabel{color:#e6e6e6}QLineEdit,QTextEdit{color:#e6e6e6;background:#5a5a5a}QLineEdit{border:1px solid #3a3a3a;border-radius:2px;padding:1px 2px}QDMNodeContentWidget{background:transparent;}QDMNodeContentWidget QFrame{background:transparent}QDMNodeContentWidget QTextEdit{background:#666}QDMNodeContentWidget QLabel{color:#e0e0e0}QGraphicsView{selection-background-color:#fff} \ No newline at end of file diff --git a/opencodeblocks/graphics/window.py b/opencodeblocks/graphics/window.py index 132dc82f..98923246 100644 --- a/opencodeblocks/graphics/window.py +++ b/opencodeblocks/graphics/window.py @@ -14,6 +14,8 @@ from opencodeblocks.graphics.view import MODE_EDITING from opencodeblocks.graphics.widget import OCBWidget +from opencodeblocks.graphics.qss import loadStylesheets + class OCBWindow(QMainWindow): @@ -22,6 +24,12 @@ class OCBWindow(QMainWindow): def __init__(self): super().__init__() + self.stylesheet_filename = os.path.join(os.path.dirname(__file__), 'qss', 'ocb.qss') + loadStylesheets(( + os.path.join(os.path.dirname(__file__), 'qss', 'ocb_dark.qss'), + self.stylesheet_filename + )) + self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) From c9ac7f389d1e0979b7be11cfe98d7047ee4b9b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Math=C3=AFs=20F=C3=A9d=C3=A9rico?= Date: Sun, 7 Nov 2021 00:43:59 +0100 Subject: [PATCH 6/6] :beetle: Fixed unknowed properties when creating window --- opencodeblocks/graphics/qss/ocb_dark.qss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opencodeblocks/graphics/qss/ocb_dark.qss b/opencodeblocks/graphics/qss/ocb_dark.qss index 3e7b33d6..2dc652c0 100644 --- a/opencodeblocks/graphics/qss/ocb_dark.qss +++ b/opencodeblocks/graphics/qss/ocb_dark.qss @@ -1 +1 @@ -QFrame,QDialog,QMainWindow{background:#474747}QSplitter,QMainWindow::separator{background:#474747}QStatusBar{background:#474747;color:#ccc}QTabWidget{border:0}QTabBar{background:#474747;color:#ccc}QMdiArea QTabBar,QMdiArea QTabWidget,QMdiArea QTabWidget::pane,QMdiArea QTabWidget::tab-bar,QMdiArea QTabBar::tab{height:17px}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:selected,QMdiArea QTabBar::tab:top:!selected:hover{border-top-left-radius:4px;border-top-right-radius:4px;padding:2px 8px;padding-top:0;padding-bottom:3px;min-width:8ex;border:1px solid #333;border-bottom:0}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #6d6d6d,stop : .1 #474747,stop : .89 #3f3f3f,stop : 1 #3f3f3f)}QMdiArea QTabBar::tab:top:selected{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #545454,stop : .89 #474747,stop : 1 #474747)}QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #727272,stop : .1 #4c4c4c,stop : .89 #444,stop : 1 #444)}QMdiArea QTabBar QToolButton{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #616161,stop : .89 #4f4f4f,stop : 1 #4f4f4f);border:1px solid #333;border-radius:0}QMdiArea QTabBar QToolButton::left-arrow{image:url(":icons/small_arrow_left-light.png")}QMdiArea QTabBar QToolButton::right-arrow{image:url(":icons/small_arrow_right-light.png")}QMdiArea QTabBar::close-button:selected{image:url(":icons/tab_close_btn.png");origin:border;subcontrol-origin:border;subcontrol-position:right bottom}QMdiArea QTabBar::close-button:!selected{image:url(":icons/tab_close_nonselected_btn.png")}QMdiSubWindow{border-size:1px;border-style:solid;background:#616161}QTabBar::tab:selected,QTabBar::tab:hover{color:#eee}QDockWidget{color:#ddd;font-weight:bold;titlebar-close-icon:url(":icons/docktitle-close-btn-light.png");titlebar-normal-icon:url(":icons/docktitle-normal-btn-light.png")}QDockWidget::title{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #3b3b3b,stop : 1 #2e2e2e);padding-top:4px;padding-right:22px;font-weight:bold}QDockWidget::close-button,QDockWidget::float-button{subcontrol-position:top right;subcontrol-origin:margin;text-align:center;icon-size:16px;width:14px;position:absolute;top:0;bottom:0;left:0;right:4px}QDockWidget::close-button{right:4px}QDockWidget::float-button{right:18px}QMenuBar{background:#474747}QMenuBar::item{spacing:3px;padding:3px 5px;color:#eee;background:transparent}QMenuBar::item:selected,QMenuBar::item:pressed{background:#4f9eee}QMenu{background:#474747;border:1px solid #2e2e2e}QMenu::item{background:#474747;color:#eee}QMenu::item:selected{background:#616161}QMenu::active{background:#616161;color:#eee}QMenu::separator{height:1px;background:#2e2e2e}QMenu::disabled,QMenu::item:disabled{color:#6e6e6e}QListView{background-color:#555;alternate-background-color:#434343}QListView::item{height:22px;color:#e6e6e6}QListView::item:hover{background:#6e6e6e}QListView::item::active:hover{color:#fff}QListView::item:selected,QListView::item::active:selected{color:#fff;background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #4f9eee,stop : 1 #2084ea);border:0}QPushButton{color:#e6e6e6;background:#555;border-color:#141414}QLabel{color:#e6e6e6}QLineEdit,QTextEdit{color:#e6e6e6;background:#5a5a5a}QLineEdit{border:1px solid #3a3a3a;border-radius:2px;padding:1px 2px}QDMNodeContentWidget{background:transparent;}QDMNodeContentWidget QFrame{background:transparent}QDMNodeContentWidget QTextEdit{background:#666}QDMNodeContentWidget QLabel{color:#e0e0e0}QGraphicsView{selection-background-color:#fff} \ No newline at end of file +QFrame,QDialog,QMainWindow{background:#474747}QSplitter,QMainWindow::separator{background:#474747}QStatusBar{background:#474747;color:#ccc}QTabWidget{border:0}QTabBar{background:#474747;color:#ccc}QMdiArea QTabBar,QMdiArea QTabWidget,QMdiArea QTabWidget::pane,QMdiArea QTabWidget::tab-bar,QMdiArea QTabBar::tab{height:17px}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:selected,QMdiArea QTabBar::tab:top:!selected:hover{border-top-left-radius:4px;border-top-right-radius:4px;padding:2px 8px;padding-top:0;padding-bottom:3px;min-width:8ex;border:1px solid #333;border-bottom:0}QMdiArea QTabBar::tab:top:!selected,QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #6d6d6d,stop : .1 #474747,stop : .89 #3f3f3f,stop : 1 #3f3f3f)}QMdiArea QTabBar::tab:top:selected{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #545454,stop : .89 #474747,stop : 1 #474747)}QMdiArea QTabBar::tab:top:!selected:hover{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #727272,stop : .1 #4c4c4c,stop : .89 #444,stop : 1 #444)}QMdiArea QTabBar QToolButton{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #878787,stop : .1 #616161,stop : .89 #4f4f4f,stop : 1 #4f4f4f);border:1px solid #333;border-radius:0}QMdiArea QTabBar QToolButton::left-arrow{image:url(":icons/small_arrow_left-light.png")}QMdiArea QTabBar QToolButton::right-arrow{image:url(":icons/small_arrow_right-light.png")}QMdiArea QTabBar::close-button:selected{image:url(":icons/tab_close_btn.png");subcontrol-origin:border;subcontrol-position:right bottom}QMdiArea QTabBar::close-button:!selected{image:url(":icons/tab_close_nonselected_btn.png")}QMdiSubWindow{border-style:solid;background:#616161}QTabBar::tab:selected,QTabBar::tab:hover{color:#eee}QDockWidget{color:#ddd;font-weight:bold;titlebar-close-icon:url(":icons/docktitle-close-btn-light.png");titlebar-normal-icon:url(":icons/docktitle-normal-btn-light.png")}QDockWidget::title{background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #3b3b3b,stop : 1 #2e2e2e);padding-top:4px;padding-right:22px;font-weight:bold}QDockWidget::close-button,QDockWidget::float-button{subcontrol-position:top right;subcontrol-origin:margin;text-align:center;icon-size:16px;width:14px;position:absolute;top:0;bottom:0;left:0;right:4px}QDockWidget::close-button{right:4px}QDockWidget::float-button{right:18px}QMenuBar{background:#474747}QMenuBar::item{spacing:3px;padding:3px 5px;color:#eee;background:transparent}QMenuBar::item:selected,QMenuBar::item:pressed{background:#4f9eee}QMenu{background:#474747;border:1px solid #2e2e2e}QMenu::item{background:#474747;color:#eee}QMenu::item:selected{background:#616161}QMenu::active{background:#616161;color:#eee}QMenu::separator{height:1px;background:#2e2e2e}QMenu::disabled,QMenu::item:disabled{color:#6e6e6e}QListView{background-color:#555;alternate-background-color:#434343}QListView::item{height:22px;color:#e6e6e6}QListView::item:hover{background:#6e6e6e}QListView::item::active:hover{color:#fff}QListView::item:selected,QListView::item::active:selected{color:#fff;background:qlineargradient(x1 : 0,y1 : 0,x2 : 0,y2 : 1,stop : 0 #4f9eee,stop : 1 #2084ea);border:0}QPushButton{color:#e6e6e6;background:#555;border-color:#141414}QLabel{color:#e6e6e6}QLineEdit,QTextEdit{color:#e6e6e6;background:#5a5a5a}QLineEdit{border:1px solid #3a3a3a;border-radius:2px;padding:1px 2px}QDMNodeContentWidget{background:transparent;}QDMNodeContentWidget QFrame{background:transparent}QDMNodeContentWidget QTextEdit{background:#666}QDMNodeContentWidget QLabel{color:#e0e0e0}QGraphicsView{selection-background-color:#fff} \ No newline at end of file