commit bccd10fc7780091941ca70bbbd411977f89f5bac Author: VFX - Visual Effects Date: Wed May 26 13:56:50 2021 -0300 first commit diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4e72f2b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/main.py", + "console": "integratedTerminal", + "python": "${command:python.interpreterPath}", + "pythonArgs": ["-B"] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..1345310 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/*.pyc": {"when": "$(basename).py"}, + "**/__pycache__": true + }, +} \ No newline at end of file diff --git a/app/modules/app_functions/functions.py b/app/modules/app_functions/functions.py new file mode 100644 index 0000000..0a8a9ba --- /dev/null +++ b/app/modules/app_functions/functions.py @@ -0,0 +1,36 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# IMPORT +# /////////////////////////////////////////////////////////////// +# Packages +from app.packages.pyside_or_pyqt import * +from app.packages.widgets import * +# Modules +import app.modules.app_settings.settings as app_settings + +# APP FUNCTIONS +# /////////////////////////////////////////////////////////////// +class AppFunctions: + def __init__(self): + # GET WIDGETS FROM "ui_main.py" + # Load widgets inside App Functions + # /////////////////////////////////////////////////////////////// + self.ui = Ui_MainWindow() + self.ui.setupUi(self) + + def change_placeholder(self): + self.ui.search_line_edit.setPlaceholderText("teste") \ No newline at end of file diff --git a/app/modules/app_settings/settings.py b/app/modules/app_settings/settings.py new file mode 100644 index 0000000..0c41975 --- /dev/null +++ b/app/modules/app_settings/settings.py @@ -0,0 +1,53 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +import json +import os + +# APP SETTINGS +class Settings(object): + # APP PATH + # /////////////////////////////////////////////////////////////// + json_file = "settings.json" + app_path = os.path.abspath(os.getcwd()) + settings_path = os.path.normpath(os.path.join(app_path, json_file)) + if not os.path.isfile(settings_path): + print(f"WARNING: \"settings.json\" not found! check in the folder {settings_path}") + + def __init__(self): + super(Settings, self).__init__() + + # DICTIONARY WITH SETTINGS + # Just to have objects references + self.items = {} + + # DESERIALIZE + self.deserialize() + + # SERIALIZE JSON + # /////////////////////////////////////////////////////////////// + def serialize(self): + # WRITE JSON FILE + with open(self.settings_path, "w", encoding='utf-8') as write: + json.dump(self.items, write, indent=4) + + # DESERIALIZE JSON + # /////////////////////////////////////////////////////////////// + def deserialize(self): + # READ JSON FILE + with open(self.settings_path, "r", encoding='utf-8') as reader: + settings = json.loads(reader.read()) + self.items = settings \ No newline at end of file diff --git a/app/modules/ui_functions/functions.py b/app/modules/ui_functions/functions.py new file mode 100644 index 0000000..89e027a --- /dev/null +++ b/app/modules/ui_functions/functions.py @@ -0,0 +1,166 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# IMPORT +# /////////////////////////////////////////////////////////////// +# Packages +from app.packages.pyside_or_pyqt import * +from app.packages.widgets import * +# GUI +from app.uis.main_window.ui_main import Ui_MainWindow # MainWindow +from app.modules.app_settings.settings import * + +# GLOBAL VARS +# /////////////////////////////////////////////////////////////// +_is_maximized = False + +# APP FUNCTIONS +# /////////////////////////////////////////////////////////////// +class UiFunctions: + + def __init__(self): + super(UiFunctions, self).__init__() + # GET WIDGETS FROM "ui_main.py" + # Load widgets inside App Functions + # /////////////////////////////////////////////////////////////// + self.ui = Ui_MainWindow() + self.ui.setupUi(self) + + # SET UI DEFINITIONS + # Set ui definitions before "self.show()" in main.py + # /////////////////////////////////////////////////////////////// + def maximize_restore(self): + global _is_maximized + + # CHANGE UI AND RESIZE GRIP + def change_ui(): + if not _is_maximized: + self.resize(self.width()+1, self.height()+1) + self.ui.margins_app.setContentsMargins(10, 10, 10, 10) + self.ui.maximize_restore_app_btn.setToolTip("Restore") + self.ui.maximize_restore_app_btn.setStyleSheet("background-image: url(:/icons_svg/images/icons_svg/icon_maximize.svg);") + self.ui.bg_app.setStyleSheet("#bg_app { border-radius: 10px; border: 2px solid rgb(30, 32, 33); }") + self.left_grip.show() + self.right_grip.show() + self.top_grip.show() + self.bottom_grip.show() + + else: + self.ui.margins_app.setContentsMargins(0, 0, 0, 0) + self.ui.maximize_restore_app_btn.setToolTip("Restore") + self.ui.maximize_restore_app_btn.setStyleSheet("background-image: url(:/icons_svg/images/icons_svg/icon_restore.svg);") + self.ui.bg_app.setStyleSheet("#bg_app { border-radius: 0px; border: none; }") + self.left_grip.hide() + self.right_grip.hide() + self.top_grip.hide() + self.bottom_grip.hide() + + # CHECK EVENT + if self.isMaximized(): + _is_maximized = False + self.showNormal() + change_ui() + else: + _is_maximized = True + self.showMaximized() + change_ui() + + # START CHAT SELECTION + # /////////////////////////////////////////////////////////////// + def select_chat_message(self, widget): + for w in self.ui.messages_frame.findChildren(QWidget): + if w.objectName() == widget: + w.set_active(True) + + # RESET CHAT SELECTION + # /////////////////////////////////////////////////////////////// + def deselect_chat_message(self, widget): + for w in self.ui.messages_frame.findChildren(QWidget): + if w.objectName() != widget: + if hasattr(w, 'set_active'): + w.set_active(False) + + # SET UI DEFINITIONS + # Set ui definitions before "self.show()" in main.py + # /////////////////////////////////////////////////////////////// + def set_ui_definitions(self): + + # GET SETTINGS FROM JSON DESERIALIZED + settings = Settings() + self.settings = settings.items + + # REMOVE TITLE BAR + # /////////////////////////////////////////////////////////////// + self.setWindowFlag(Qt.FramelessWindowHint) + self.setAttribute(Qt.WA_TranslucentBackground) + + # MOVE WINDOW / MAXIMIZE / RESTORE + def moveWindow(event): + # IF MAXIMIZED CHANGE TO NORMAL + if self.isMaximized(): + UiFunctions.maximize_restore(self) + curso_x = self.pos().x() + curso_y = event.globalPos().y() - QCursor.pos().y() + self.move(curso_x, curso_y) + # MOVE WINDOW + if event.buttons() == Qt.LeftButton: + self.move(self.pos() + event.globalPos() - self.dragPos) + self.dragPos = event.globalPos() + event.accept() + self.ui.logo_top.mouseMoveEvent = moveWindow + self.ui.title_bar.mouseMoveEvent = moveWindow + + # DOUBLE CLICK MAXIMIZE / RESTORE + def maximize_restore(event): + if event.type() == QEvent.MouseButtonDblClick: + UiFunctions.maximize_restore(self) + self.ui.title_bar.mouseDoubleClickEvent = maximize_restore + + # TOP BTNS + self.ui.minimize_app_btn.clicked.connect(lambda: self.showMinimized()) + self.ui.maximize_restore_app_btn.clicked.connect(lambda: UiFunctions.maximize_restore(self)) + self.ui.close_app_btn.clicked.connect(lambda: self.close()) + + + + # DEFAULT PARAMETERS + self.setWindowTitle(self.settings["app_name"]) + self.resize(self.settings["startup_size"][0], self.settings["startup_size"][1]) + self.setMinimumSize(self.settings["minimum_size"][0], self.settings["minimum_size"][1]) + + # APPLY DROP SHADOW + self.shadow = QGraphicsDropShadowEffect() + self.shadow.setBlurRadius(25) + self.shadow.setXOffset(0) + self.shadow.setYOffset(0) + self.shadow.setColor(QColor(0, 0, 0, 80)) + self.ui.stylesheet.setGraphicsEffect(self.shadow) + + # CUSTOM GRIPS + # Create grips to resize window + self.left_grip = CustomGrip(self, Qt.LeftEdge, True) + self.right_grip = CustomGrip(self, Qt.RightEdge, True) + self.top_grip = CustomGrip(self, Qt.TopEdge, True) + self.bottom_grip = CustomGrip(self, Qt.BottomEdge, True) + + # RESIZE GRIPS + # This function should be called whenever "MainWindow/main.py" has its window resized. + # /////////////////////////////////////////////////////////////// + def resize_grips(self): + self.left_grip.setGeometry(0, 10, 10, self.height()) + self.right_grip.setGeometry(self.width() - 10, 10, 10, self.height()) + self.top_grip.setGeometry(0, 0, self.width(), 10) + self.bottom_grip.setGeometry(0, self.height() - 10, self.width(), 10) diff --git a/app/packages/__init__.py b/app/packages/__init__.py new file mode 100644 index 0000000..5da3c80 --- /dev/null +++ b/app/packages/__init__.py @@ -0,0 +1,21 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# APP WIDGETS +from . pyside_or_pyqt import * + +# APP WIDGETS +from . widgets import * diff --git a/app/packages/pyside_or_pyqt/__init__.py b/app/packages/pyside_or_pyqt/__init__.py new file mode 100644 index 0000000..e350d8b --- /dev/null +++ b/app/packages/pyside_or_pyqt/__init__.py @@ -0,0 +1,18 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# APP WIDGETS +from . pyside_or_pyqt import * diff --git a/app/packages/pyside_or_pyqt/pyside_or_pyqt.py b/app/packages/pyside_or_pyqt/pyside_or_pyqt.py new file mode 100644 index 0000000..a429bce --- /dev/null +++ b/app/packages/pyside_or_pyqt/pyside_or_pyqt.py @@ -0,0 +1,19 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +from PySide6.QtCore import * +from PySide6.QtGui import * +from PySide6.QtWidgets import * diff --git a/app/packages/widgets/__init__.py b/app/packages/widgets/__init__.py new file mode 100644 index 0000000..640fe9a --- /dev/null +++ b/app/packages/widgets/__init__.py @@ -0,0 +1,34 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# CUSTOM GRIP +# Resize window using application edges +from . custom_grips import CustomGrip + +# LEFT MENU BUTTON +# Custom button with tooltip +from . left_menu_button import LeftMenuButton + +# TOP USER BOX +# Top user information and status +from . top_user_box import TopUserInfo + +# FRIEND MENU MESSAGE / MESSAGE BUTTON +# Friends messages with name and status +from . friend_message_button import FriendMessageButton + +# CIRCULAR PROGRESS BAR +from . circular_progress import CircularProgress diff --git a/app/packages/widgets/circular_progress/__init__.py b/app/packages/widgets/circular_progress/__init__.py new file mode 100644 index 0000000..e8ee842 --- /dev/null +++ b/app/packages/widgets/circular_progress/__init__.py @@ -0,0 +1,14 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# /////////////////////////////////////////////////////////////// + +# CIRCULAR PROGRESS BAR +from . circular_progress import CircularProgress \ No newline at end of file diff --git a/app/packages/widgets/circular_progress/circular_progress.py b/app/packages/widgets/circular_progress/circular_progress.py new file mode 100644 index 0000000..ccc7877 --- /dev/null +++ b/app/packages/widgets/circular_progress/circular_progress.py @@ -0,0 +1,106 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# /////////////////////////////////////////////////////////////// + +from PySide6.QtCore import * +from PySide6.QtGui import * +from PySide6.QtWidgets import * + +class CircularProgress(QWidget): + def __init__(self): + QWidget.__init__(self) + + # CUSTOM PROPERTIES + self.value = 0 + self.width = 200 + self.height = 200 + self.progress_width = 10 + self.progress_rounded_cap = True + self.max_value = 100 + self.progress_color = 0xff79c6 + # Text + self.enable_text = True + self.font_family = "Segoe UI" + self.font_size = 12 + self.suffix = "%" + self.text_color = 0xff79c6 + # BG + self.enable_bg = True + self.bg_color = 0x44475a + + # SET DEFAULT SIZE WITHOUT LAYOUT + self.resize(self.width, self.height) + + # ADD DROPSHADOW + def add_shadow(self, enable): + if enable: + self.shadow = QGraphicsDropShadowEffect(self) + self.shadow.setBlurRadius(15) + self.shadow.setXOffset(0) + self.shadow.setYOffset(0) + self.shadow.setColor(QColor(0, 0, 0, 80)) + self.setGraphicsEffect(self.shadow) + + # SET VALUE + def set_value(self, value): + self.value = value + self.repaint() # Render progress bar after change value + + + # PAINT EVENT (DESIGN YOUR CIRCULAR PROGRESS HERE) + def paintEvent(self, e): + # SET PROGRESS PARAMETERS + width = self.width - self.progress_width + height = self.height - self.progress_width + margin = self.progress_width / 2 + value = self.value * 360 / self.max_value + + # PAINTER + paint = QPainter() + paint.begin(self) + paint.setRenderHint(QPainter.Antialiasing) # remove pixelated edges + paint.setFont(QFont(self.font_family, self.font_size)) + + # CREATE RECTANGLE + rect = QRect(0, 0, self.width, self.height) + paint.setPen(Qt.NoPen) + paint.drawRect(rect) + + # PEN + pen = QPen() + pen.setWidth(self.progress_width) + # Set Round Cap + if self.progress_rounded_cap: + pen.setCapStyle(Qt.RoundCap) + + # ENABLE BG + if self.enable_bg: + pen.setColor(QColor(self.bg_color)) + paint.setPen(pen) + paint.drawArc(margin, margin, width, height, 0, 360 * 16) + + # CREATE ARC / CIRCULAR PROGRESS + pen.setColor(QColor(self.progress_color)) + paint.setPen(pen) + paint.drawArc(margin, margin, width, height, -90 * 16, -value * 16) + + # CREATE TEXT + if self.enable_text: + pen.setColor(QColor(self.text_color)) + paint.setPen(pen) + paint.drawText(rect, Qt.AlignCenter, f"{self.value}{self.suffix}") + + # END + paint.end() + +if __name__ == "__main__": + progress = CircularProgress() + progress.__init__() \ No newline at end of file diff --git a/app/packages/widgets/custom_grips/__init__.py b/app/packages/widgets/custom_grips/__init__.py new file mode 100644 index 0000000..edc45ae --- /dev/null +++ b/app/packages/widgets/custom_grips/__init__.py @@ -0,0 +1,17 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +from . custom_grips import CustomGrip diff --git a/app/packages/widgets/custom_grips/custom_grips.py b/app/packages/widgets/custom_grips/custom_grips.py new file mode 100644 index 0000000..53a15a1 --- /dev/null +++ b/app/packages/widgets/custom_grips/custom_grips.py @@ -0,0 +1,238 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +from PySide6.QtCore import * +from PySide6.QtGui import * +from PySide6.QtWidgets import * + +class CustomGrip(QWidget): + def __init__(self, parent, position, disable_color = False): + + # SETUP UI + QWidget.__init__(self) + self.parent = parent + self.setParent(parent) + self.wi = Widgets() + + # SHOW TOP GRIP + if position == Qt.TopEdge: + self.wi.top(self) + self.setGeometry(0, 0, self.parent.width(), 10) + self.setMaximumHeight(10) + + # GRIPS + top_left = QSizeGrip(self.wi.top_left) + top_right = QSizeGrip(self.wi.top_right) + + # RESIZE TOP + def resize_top(event): + delta = event.pos() + height = max(self.parent.minimumHeight(), self.parent.height() - delta.y()) + geo = self.parent.geometry() + geo.setTop(geo.bottom() - height) + self.parent.setGeometry(geo) + event.accept() + self.wi.top.mouseMoveEvent = resize_top + + # ENABLE COLOR + if disable_color: + self.wi.top_left.setStyleSheet("background: transparent") + self.wi.top_right.setStyleSheet("background: transparent") + self.wi.top.setStyleSheet("background: transparent") + + # SHOW BOTTOM GRIP + elif position == Qt.BottomEdge: + self.wi.bottom(self) + self.setGeometry(0, self.parent.height() - 10, self.parent.width(), 10) + self.setMaximumHeight(10) + + # GRIPS + self.bottom_left = QSizeGrip(self.wi.bottom_left) + self.bottom_right = QSizeGrip(self.wi.bottom_right) + + # RESIZE BOTTOM + def resize_bottom(event): + delta = event.pos() + height = max(self.parent.minimumHeight(), self.parent.height() + delta.y()) + self.parent.resize(self.parent.width(), height) + event.accept() + self.wi.bottom.mouseMoveEvent = resize_bottom + + # ENABLE COLOR + if disable_color: + self.wi.bottom_left.setStyleSheet("background: transparent") + self.wi.bottom_right.setStyleSheet("background: transparent") + self.wi.bottom.setStyleSheet("background: transparent") + + # SHOW LEFT GRIP + elif position == Qt.LeftEdge: + self.wi.left(self) + self.setGeometry(0, 10, 10, self.parent.height()) + self.setMaximumWidth(10) + + # RESIZE LEFT + def resize_left(event): + delta = event.pos() + width = max(self.parent.minimumWidth(), self.parent.width() - delta.x()) + geo = self.parent.geometry() + geo.setLeft(geo.right() - width) + self.parent.setGeometry(geo) + event.accept() + self.wi.leftgrip.mouseMoveEvent = resize_left + + # ENABLE COLOR + if disable_color: + self.wi.leftgrip.setStyleSheet("background: transparent") + + # RESIZE RIGHT + elif position == Qt.RightEdge: + self.wi.right(self) + self.setGeometry(self.parent.width() - 10, 10, 10, self.parent.height()) + self.setMaximumWidth(10) + + def resize_right(event): + delta = event.pos() + width = max(self.parent.minimumWidth(), self.parent.width() + delta.x()) + self.parent.resize(width, self.parent.height()) + event.accept() + self.wi.rightgrip.mouseMoveEvent = resize_right + + # ENABLE COLOR + if disable_color: + self.wi.rightgrip.setStyleSheet("background: transparent") + + + def mouseReleaseEvent(self, event): + self.mousePos = None + + def resizeEvent(self, event): + if hasattr(self.wi, 'container_top'): + self.wi.container_top.setGeometry(0, 0, self.width(), 10) + + elif hasattr(self.wi, 'container_bottom'): + self.wi.container_bottom.setGeometry(0, 0, self.width(), 10) + + elif hasattr(self.wi, 'leftgrip'): + self.wi.leftgrip.setGeometry(0, 0, 10, self.height() - 20) + + elif hasattr(self.wi, 'rightgrip'): + self.wi.rightgrip.setGeometry(0, 0, 10, self.height() - 20) + +class Widgets(object): + def top(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + self.container_top = QFrame(Form) + self.container_top.setObjectName(u"container_top") + self.container_top.setGeometry(QRect(0, 0, 500, 10)) + self.container_top.setMinimumSize(QSize(0, 10)) + self.container_top.setMaximumSize(QSize(16777215, 10)) + self.container_top.setFrameShape(QFrame.NoFrame) + self.container_top.setFrameShadow(QFrame.Raised) + self.top_layout = QHBoxLayout(self.container_top) + self.top_layout.setSpacing(0) + self.top_layout.setObjectName(u"top_layout") + self.top_layout.setContentsMargins(0, 0, 0, 0) + self.top_left = QFrame(self.container_top) + self.top_left.setObjectName(u"top_left") + self.top_left.setMinimumSize(QSize(10, 10)) + self.top_left.setMaximumSize(QSize(10, 10)) + self.top_left.setCursor(QCursor(Qt.SizeFDiagCursor)) + self.top_left.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.top_left.setFrameShape(QFrame.NoFrame) + self.top_left.setFrameShadow(QFrame.Raised) + self.top_layout.addWidget(self.top_left) + self.top = QFrame(self.container_top) + self.top.setObjectName(u"top") + self.top.setCursor(QCursor(Qt.SizeVerCursor)) + self.top.setStyleSheet(u"background-color: rgb(85, 255, 255);") + self.top.setFrameShape(QFrame.NoFrame) + self.top.setFrameShadow(QFrame.Raised) + self.top_layout.addWidget(self.top) + self.top_right = QFrame(self.container_top) + self.top_right.setObjectName(u"top_right") + self.top_right.setMinimumSize(QSize(10, 10)) + self.top_right.setMaximumSize(QSize(10, 10)) + self.top_right.setCursor(QCursor(Qt.SizeBDiagCursor)) + self.top_right.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.top_right.setFrameShape(QFrame.NoFrame) + self.top_right.setFrameShadow(QFrame.Raised) + self.top_layout.addWidget(self.top_right) + + def bottom(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + self.container_bottom = QFrame(Form) + self.container_bottom.setObjectName(u"container_bottom") + self.container_bottom.setGeometry(QRect(0, 0, 500, 10)) + self.container_bottom.setMinimumSize(QSize(0, 10)) + self.container_bottom.setMaximumSize(QSize(16777215, 10)) + self.container_bottom.setFrameShape(QFrame.NoFrame) + self.container_bottom.setFrameShadow(QFrame.Raised) + self.bottom_layout = QHBoxLayout(self.container_bottom) + self.bottom_layout.setSpacing(0) + self.bottom_layout.setObjectName(u"bottom_layout") + self.bottom_layout.setContentsMargins(0, 0, 0, 0) + self.bottom_left = QFrame(self.container_bottom) + self.bottom_left.setObjectName(u"bottom_left") + self.bottom_left.setMinimumSize(QSize(10, 10)) + self.bottom_left.setMaximumSize(QSize(10, 10)) + self.bottom_left.setCursor(QCursor(Qt.SizeBDiagCursor)) + self.bottom_left.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.bottom_left.setFrameShape(QFrame.NoFrame) + self.bottom_left.setFrameShadow(QFrame.Raised) + self.bottom_layout.addWidget(self.bottom_left) + self.bottom = QFrame(self.container_bottom) + self.bottom.setObjectName(u"bottom") + self.bottom.setCursor(QCursor(Qt.SizeVerCursor)) + self.bottom.setStyleSheet(u"background-color: rgb(85, 170, 0);") + self.bottom.setFrameShape(QFrame.NoFrame) + self.bottom.setFrameShadow(QFrame.Raised) + self.bottom_layout.addWidget(self.bottom) + self.bottom_right = QFrame(self.container_bottom) + self.bottom_right.setObjectName(u"bottom_right") + self.bottom_right.setMinimumSize(QSize(10, 10)) + self.bottom_right.setMaximumSize(QSize(10, 10)) + self.bottom_right.setCursor(QCursor(Qt.SizeFDiagCursor)) + self.bottom_right.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.bottom_right.setFrameShape(QFrame.NoFrame) + self.bottom_right.setFrameShadow(QFrame.Raised) + self.bottom_layout.addWidget(self.bottom_right) + + def left(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + self.leftgrip = QFrame(Form) + self.leftgrip.setObjectName(u"left") + self.leftgrip.setGeometry(QRect(0, 10, 10, 480)) + self.leftgrip.setMinimumSize(QSize(10, 0)) + self.leftgrip.setCursor(QCursor(Qt.SizeHorCursor)) + self.leftgrip.setStyleSheet(u"background-color: rgb(255, 121, 198);") + self.leftgrip.setFrameShape(QFrame.NoFrame) + self.leftgrip.setFrameShadow(QFrame.Raised) + + def right(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + Form.resize(500, 500) + self.rightgrip = QFrame(Form) + self.rightgrip.setObjectName(u"right") + self.rightgrip.setGeometry(QRect(0, 0, 10, 500)) + self.rightgrip.setMinimumSize(QSize(10, 0)) + self.rightgrip.setCursor(QCursor(Qt.SizeHorCursor)) + self.rightgrip.setStyleSheet(u"background-color: rgb(255, 0, 127);") + self.rightgrip.setFrameShape(QFrame.NoFrame) + self.rightgrip.setFrameShadow(QFrame.Raised) diff --git a/app/packages/widgets/friend_message_button/__init__.py b/app/packages/widgets/friend_message_button/__init__.py new file mode 100644 index 0000000..ea0da5c --- /dev/null +++ b/app/packages/widgets/friend_message_button/__init__.py @@ -0,0 +1,19 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# FRIEND MENU MESSAGE / MESSAGE BUTTON +# Friends messages with name and status +from . friend_message_button import FriendMessageButton \ No newline at end of file diff --git a/app/packages/widgets/friend_message_button/friend_message_button.py b/app/packages/widgets/friend_message_button/friend_message_button.py new file mode 100644 index 0000000..b103f7a --- /dev/null +++ b/app/packages/widgets/friend_message_button/friend_message_button.py @@ -0,0 +1,230 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# IMPORT +# /////////////////////////////////////////////////////////////// +# Packages +from app.packages.pyside_or_pyqt import * +# Modules +import os + +# FRIEND MENU MESSAGE / MESSAGE BUTTON +# Friends messages with name and status +class FriendMessageButton(QWidget): + # SIGNALS + # /////////////////////////////////////////////////////////////// + clicked = Signal() + released = Signal() + + def __init__( + self, + id, + user_image, + user_name, + user_descrition, + user_status, + unread_messages, + is_active + ): + QWidget.__init__(self) + + # ICON PATH + # /////////////////////////////////////////////////////////////// + image = user_image + app_path = os.path.abspath(os.getcwd()) + image_path = os.path.join(app_path, image) + + # CUSTOM PARAMETERS + # /////////////////////////////////////////////////////////////// + self.user_image = image_path + self.user_name = user_name + self.user_description = user_descrition + self.user_status = user_status + self.unread_messages = unread_messages + self.is_active = is_active + self._status_color = "#46b946" + self.bg_color_entered = "#22CCCCCC" + self.bg_color_leave = "#00000000" + self.bg_color_active = "#33CCCCCC" + self._bg_color = self.bg_color_leave + + + # SETUP + self.setFixedSize(240, 50) + self.setCursor(Qt.PointingHandCursor) + self.setObjectName(str(id)) + self.setup_ui() + + # SHOW UNREAD MESSAGES + if self.unread_messages > 0: + self.label_messages.show() + self.label_messages.setText(str(self.unread_messages)) + + # CHANGE COLOR + if self.user_status == "online": + self._status_color = "#46b946" + elif self.user_status == "ilde": + self._status_color = "#ff9955" + elif self.user_status == "busy": + self._status_color = "#a02c2c" + elif self.user_status == "invisible": + self._status_color = "#808080" + + # CHANGE OPACITY + if self.user_status == "invisible": + self.opacity = QGraphicsOpacityEffect() + self.opacity.setOpacity(0.4) + self.setGraphicsEffect(self.opacity) + + def reset_unread_message(self): + self.unread_messages = 0 + self.label_messages.hide() + self.repaint() + + # MOUSE PRESS + # Event triggered when the left button is pressed + def mousePressEvent(self, event): + if event.button() == Qt.LeftButton: + # EMIT SIGNAL + self.clicked.emit() + + # MOUSE RELEASE + # Event fired when the mouse leaves the BTN + def mouseReleaseEvent(self, event): + if event.button() == Qt.LeftButton: + self.released.emit() + + # MOUSE ENTER + # Event fired when the mouse enter + def enterEvent(self, event): + if not self.is_active: + self._bg_color = self.bg_color_entered + self.repaint() + + # MOUSE LEAVE + # Event fired when the mouse leave + def leaveEvent(self, event): + if not self.is_active: + self._bg_color = self.bg_color_leave + self.repaint() + + def set_active(self, active): + if active: + self.is_active = active + else: + self.is_active = active + self._bg_color = self.bg_color_leave + self.repaint() + + # SETUP WIDGETS + # /////////////////////////////////////////////////////////////// + def setup_ui(self): + # FRAME TEXT + self.text_frame = QFrame(self) + self.text_frame.setGeometry(60, 0, 170, 50) + + # USER NAME + self.label_user = QLabel(self.text_frame) + self.label_user.setGeometry(0, 8, self.text_frame.width(), 20) + self.label_user.setAlignment(Qt.AlignVCenter) + self.label_user.setText(self.user_name.capitalize()) + self.label_user.setStyleSheet("color: #e7e7e7; font: 700 10pt 'Segoe UI';") + + # USER STATUS + self.label_description = QLabel(self.text_frame) + self.label_description.setGeometry(0, 22, self.text_frame.width(), 18) + self.label_description.setAlignment(Qt.AlignVCenter) + self.label_description.setText(self.user_description) + self.label_description.setStyleSheet("color: #A6A6A6; font: 9pt 'Segoe UI';") + + # USER STATUS + self.label_messages = QLabel(self) + self.label_messages.setFixedSize(35, 20) + self.label_messages.setAlignment(Qt.AlignCenter) + self.label_messages.setStyleSheet(""" + background-color: #1e2021; + padding-left: 5px; + padding-right: 5px; + color: #bdff00; + border-radius: 10px; + border: 3px solid #333; + font: 9pt 'Segoe UI'; + """) + self.label_messages.move(self.width() - 45, 16) + self.label_messages.hide() + + # PAINT EVENT + # PAINT USER IMAGE EVENTS + # /////////////////////////////////////////////////////////////// + def paintEvent(self, event): + # PAINTER USER IMAGE + painter = QPainter() + painter.begin(self) + painter.setRenderHint(QPainter.Antialiasing) + painter.setPen(Qt.NoPen) + + # RECT + rect = QRect(10, 5, 40, 40) + + # DRAW BG + if self.is_active: + painter.setBrush(QBrush(QColor(self.bg_color_active))) + else: + painter.setBrush(QBrush(QColor(self._bg_color))) + painter.drawRoundedRect(5, 0, 230, 50, 25, 25) + + # CIRCLE + painter.setBrush(QBrush(QColor("#000000"))) + painter.drawEllipse(rect) + + # DRAW USER IMAGE + self.draw_user_image(painter, self.user_image, rect) + + painter.end() + + # DRAW USER IMAGE + if self.user_status != "invisible": + self.draw_status(self.user_image, rect) + + # DRAW USER IMAGE + # /////////////////////////////////////////////////////////////// + def draw_user_image(self, qp, image, rect): + user_image = QImage(image) + path = QPainterPath() + path.addEllipse(rect) + qp.setClipPath(path) + qp.drawImage(rect, user_image) + + # DRAW STATUS + # /////////////////////////////////////////////////////////////// + def draw_status(self, status, rect): + painter = QPainter() + painter.begin(self) + painter.setRenderHint(QPainter.Antialiasing) + + # PEN + pen = QPen() + pen.setWidth(3) + pen.setColor(QColor("#151617")) + painter.setPen(pen) + + # BRUSH/STATUS COLOR + painter.setBrush(QBrush(QColor(self._status_color))) + + # DRAW + painter.drawEllipse(rect.x() + 27, rect.y() + 27, 13, 13) + painter.end() + \ No newline at end of file diff --git a/app/packages/widgets/left_menu_button/__init__.py b/app/packages/widgets/left_menu_button/__init__.py new file mode 100644 index 0000000..f8d0c57 --- /dev/null +++ b/app/packages/widgets/left_menu_button/__init__.py @@ -0,0 +1,19 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# LEFT MENU BUTTON +# Custom button with tooltip +from . left_menu_button import LeftMenuButton \ No newline at end of file diff --git a/app/packages/widgets/left_menu_button/left_menu_button.py b/app/packages/widgets/left_menu_button/left_menu_button.py new file mode 100644 index 0000000..babcb7f --- /dev/null +++ b/app/packages/widgets/left_menu_button/left_menu_button.py @@ -0,0 +1,226 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# IMPORT +# /////////////////////////////////////////////////////////////// +# Packages +from app.packages.pyside_or_pyqt import * +# Modules +import app.modules.ui_functions.functions as ui_functions +from app.modules.app_settings.settings import * +import os + +# TOOLTIP / LABEL StyleSheet +style_tooltip = """ +QLabel { + background-color: #0b0b0c; + color: rgb(230, 230, 230); + padding-left: 10px; + padding-right: 10px; + border-radius: 17px; + border: 1px solid #2f3032; + border-left: 3px solid #bdff00; + font: 800 9pt "Segoe UI"; +} +""" + +# CUSTOM LEFT MENU +class LeftMenuButton(QWidget): + # SIGNALS + clicked = Signal() + released = Signal() + + def __init__(self, parent, name, icon, tooltip): + QWidget.__init__(self) + # APP PATH + app_path = os.path.abspath(os.getcwd()) + icon_path = os.path.join(app_path, icon) + + # GET SETTINGS + settings = Settings() + self.settings = settings.items + + # DEFAULT PARAMETERS + self.width = 40 + self.height = 40 + self.pos_x = 0 + self.pos_y = 0 + self.border_radius = 10 + self.parent = parent + self.setGeometry(0, 0, self.width, self.height) + self.setMinimumSize(self.width, self.height) + self.setCursor(Qt.PointingHandCursor) + self.setObjectName(name) + + # BG COLORS + self.color_default = QColor(self.settings["left_menu"]["color"]) + self.color_hover = QColor(self.settings["left_menu"]["color_hover"]) + self.color_pressed = QColor(self.settings["left_menu"]["color_pressed"]) + self._set_color = self.color_default + + # ICON + self.icon_color = QColor(0xE6E6E6) + self.icon_color_pressed = QColor(0x151617) + self._set_icon_path = icon_path + self._set_icon_color = self.icon_color + + # TOOLTIP + self.tooltip_text = tooltip + self.tooltip = _ToolTip(parent, tooltip) + self.tooltip.hide() + + # PAINT EVENT + # Responsible for painting the button, as well as the icon + def paintEvent(self, event): + # PAINTER + paint = QPainter() + paint.begin(self) + paint.setRenderHint(QPainter.RenderHint.Antialiasing) + + # BRUSH + brush = QBrush(self._set_color) + + # CREATE RECTANGLE + rect = QRect(0, 0, self.width, self.height) + paint.setPen(Qt.NoPen) + paint.setBrush(brush) + paint.drawRoundedRect(rect, self.border_radius, self.border_radius) + + # DRAW ICONS + self.icon_paint(paint, self._set_icon_path, rect) + + # END PAINTER + paint.end() + + # DRAW ICON WITH COLORS + def icon_paint(self, qp, image, rect): + icon = QPixmap(image) + painter = QPainter(icon) + painter.setCompositionMode(QPainter.CompositionMode_SourceIn) + painter.fillRect(icon.rect(), self._set_icon_color) + qp.drawPixmap( + (rect.width() - icon.width()) / 2, + (rect.height() - icon.height()) / 2, + icon + ) + painter.end() + + # REPAINT BTN + # Reaload/Repaint BTN + def repaint_btn(self, event): + if event == QEvent.Enter: + self.repaint() + if event == QEvent.Leave: + self.repaint() + if event == QEvent.MouseButtonPress: + self.repaint() + if event == QEvent.MouseButtonRelease: + self.repaint() + + # CHANGE STYLES + # Functions with custom styles + def change_style(self, event): + if event == QEvent.Enter: + self._set_color = self.color_hover + self.repaint_btn(event) + elif event == QEvent.Leave: + self._set_color = self.color_default + self.repaint_btn(event) + elif event == QEvent.MouseButtonPress: + self._set_color = self.color_pressed + self._set_icon_color = self.icon_color_pressed + self.repaint_btn(event) + elif event == QEvent.MouseButtonRelease: + self._set_color = self.color_hover + self._set_icon_color = self.icon_color + self.repaint_btn(event) + + # MOVE TOOLTIP + def move_tooltip(self): + # GET MAIN WINDOW PARENT + gp = self.mapToGlobal(QPoint(0, 0)) + + # SET WIDGET TO GET POSTION + # Return absolute position of widget inside app + pos = self.parent.mapFromGlobal(gp) + + # FORMAT POSITION + # Adjust tooltip position with offset + pos_x = pos.x() + self.width + 12 + pos_y = pos.y() + (self.width - self.tooltip.height()) // 2 + + # SET POSITION TO WIDGET + # Move tooltip position + self.tooltip.move(pos_x, pos_y) + + # MOUSE OVER + # Event triggered when the mouse is over the BTN + def enterEvent(self, event): + self.change_style(QEvent.Enter) + self.move_tooltip() + self.tooltip.show() + + # MOUSE LEAVE + # Event fired when the mouse leaves the BTN + def leaveEvent(self, event): + self.change_style(QEvent.Leave) + self.move_tooltip() + self.tooltip.hide() + + # MOUSE PRESS + # Event triggered when the left button is pressed + def mousePressEvent(self, event): + if event.button() == Qt.LeftButton: + self.change_style(QEvent.MouseButtonPress) + # EMIT SIGNAL + self.clicked.emit() + # SET FOCUS + self.setFocus() + + # MOUSE RELEASED + # Event triggered after the mouse button is released + def mouseReleaseEvent(self, event): + if event.button() == Qt.LeftButton: + self.change_style(QEvent.MouseButtonRelease) + # EMIT SIGNAL + self.released.emit() + +class _ToolTip(QLabel): + def __init__(self, parent, tooltip): + QLabel.__init__(self) + + # LABEL SETUP + self.setObjectName(u"label_tooltip") + self.setStyleSheet(style_tooltip) + self.setMinimumHeight(36) + self.setParent(parent) + self.setText(tooltip) + self.adjustSize() + + # SET DROP SHADOW + self.shadow = QGraphicsDropShadowEffect(self) + self.shadow.setBlurRadius(15) + self.shadow.setXOffset(0) + self.shadow.setYOffset(0) + self.shadow.setColor(QColor(0, 0, 0, 160)) + self.setGraphicsEffect(self.shadow) + + # SET OPACITY + self.opacity = QGraphicsOpacityEffect(self) + self.opacity.setOpacity(0.85) + self.setGraphicsEffect(self.opacity) + + diff --git a/app/packages/widgets/left_menu_button/tooltip.ui b/app/packages/widgets/left_menu_button/tooltip.ui new file mode 100644 index 0000000..f0fab89 --- /dev/null +++ b/app/packages/widgets/left_menu_button/tooltip.ui @@ -0,0 +1,58 @@ + + + Form + + + + 0 + 0 + 220 + 30 + + + + + 220 + 30 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QLabel { + background-color: rgb(12, 12, 13); + color: rgb(230, 230, 230); + padding-left: 10px; + padding-right: 10px; + border-radius: 8px; +} + + + ToolTip + + + + + + + + diff --git a/app/packages/widgets/top_user_box/__init__.py b/app/packages/widgets/top_user_box/__init__.py new file mode 100644 index 0000000..5869f91 --- /dev/null +++ b/app/packages/widgets/top_user_box/__init__.py @@ -0,0 +1,20 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# TOP USER BOX +# Top user information and status +from . top_user_box import TopUserInfo + diff --git a/app/packages/widgets/top_user_box/top_user_box.py b/app/packages/widgets/top_user_box/top_user_box.py new file mode 100644 index 0000000..bc92a4c --- /dev/null +++ b/app/packages/widgets/top_user_box/top_user_box.py @@ -0,0 +1,362 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# IMPORT +# /////////////////////////////////////////////////////////////// +# Packages +from app.packages.pyside_or_pyqt import * +# Modules +import os + +# TOP USER BOX +# Top box with name, description and status +# /////////////////////////////////////////////////////////////// +class TopUserInfo(QWidget): + status = Signal(str) + def __init__(self, parent, left, top, my_name, my_description): + QWidget.__init__(self) + + # ICON PATH + # /////////////////////////////////////////////////////////////// + image = "images/users/me.png" + icon_settings = "images/icons_svg/icon_settings.svg" + app_path = os.path.abspath(os.getcwd()) + image_path = os.path.join(app_path, image) + icon_settings_path = os.path.join(app_path, icon_settings) + + # INITIAL SETUP + # /////////////////////////////////////////////////////////////// + self.setGeometry(0, 0, 240, 60) + self.setObjectName("top_text_box") + self.setStyleSheet("#top_text_box { background-color: #F00000 }") + + # CUSTOM PARAMETERS + # /////////////////////////////////////////////////////////////// + self.user_name = my_name + self.user_description = my_description + self.user_status = "online" + self.user_image = image_path + self.icon_settings = icon_settings + self._status_color = "#46b946" + + # DRAW BASE FRAME + # /////////////////////////////////////////////////////////////// + self.setup_ui() + + # IMAGE FRAME EVENTS + # /////////////////////////////////////////////////////////////// + self.user_overlay.mousePressEvent = self.mouse_press + self.user_overlay.enterEvent = self.mouse_enter + self.user_overlay.leaveEvent = self.mouse_leave + + # SETUP STATUS BOX + # /////////////////////////////////////////////////////////////// + self.status_box = _ChangeStatus(parent) + self.status_box.move(left, top) + self.status_box.focusOutEvent = self.lost_focus_status_box + self.status_box.line_edit.focusOutEvent = self.lost_focus_line_edit + self.status_box.line_edit.keyReleaseEvent = self.change_description + self.status_box.hide() + self.status_box.status.connect(self.change_status) + + # CHANGE USER STATUS + # Change when is connected with status signal + # /////////////////////////////////////////////////////////////// + def change_status(self, status): + # CHANGE STATUS + if status == "online": + self._status_color = "#46b946" + self.repaint() + elif status == "idle": + self._status_color = "#ff9955" + self.repaint() + elif status == "busy": + self._status_color = "#a02c2c" + self.repaint() + elif status == "invisible": + self._status_color = "#808080" + self.repaint() + # EMIT SIGNAL + self.status.emit(status) + + # CHANGE TEXT DESCRIPTION + # /////////////////////////////////////////////////////////////// + def change_description(self, event): + if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: + self.label_description.setText(self.status_box.line_edit.text()) + self.status_box.line_edit.setText("") + self.status_box.hide() + + # SHO HIDE DIALOP POPUP + # /////////////////////////////////////////////////////////////// + # HIDE LINE EDIT WHEN LOST FOCUS + def lost_focus_status_box(self, event): + if not self.status_box.line_edit.hasFocus(): + self.status_box.hide() + self.status_box.line_edit.setText("") + + # HIDE WHEN LOST FOCUS + def lost_focus_line_edit(self, event): + if not self.status_box.hasFocus(): + self.status_box.hide() + self.status_box.line_edit.setText("") + + # OPEN STATUS BOX POPUP + # /////////////////////////////////////////////////////////////// + def mouse_press(self, event): + if self.status_box.isVisible(): + self.status_box.hide() + self.status_box.line_edit.setText("") + else: + self.status_box.show() + self.status_box.line_edit.setFocus() + + # SHOW ICON + # /////////////////////////////////////////////////////////////// + def mouse_enter(self, event): + self.user_overlay.setPixmap(self.icon_settings) + + # HIDE ICON + # /////////////////////////////////////////////////////////////// + def mouse_leave(self, event): + self.user_overlay.setPixmap(None) + + # SETUP WIDGETS + # /////////////////////////////////////////////////////////////// + def setup_ui(self): + # LAYOUT AND BORDER + self.layout = QVBoxLayout(self) + self.layout.setContentsMargins(10,10,10,0) + self.border = QFrame(self) + self.layout.addWidget(self.border) + + # FRAME IMAGE + self.user_overlay = QLabel(self.border) + self.user_overlay.setGeometry(0, 5, 40, 40) + self.user_overlay.setCursor(QCursor(Qt.PointingHandCursor)) + self.user_overlay.setAlignment(Qt.AlignCenter) + opacity = QGraphicsOpacityEffect(self) + opacity.setOpacity(0.75) + self.user_overlay.setGraphicsEffect(opacity) + + # FRAME TEXT + self.text_frame = QFrame(self.border) + self.text_frame.setGeometry(50, 0, 170, 50) + + # USER NAME + self.label_user = QLabel(self.text_frame) + self.label_user.setGeometry(0, 8, self.text_frame.width(), 20) + self.label_user.setAlignment(Qt.AlignVCenter) + self.label_user.setText(self.user_name.capitalize()) + self.label_user.setStyleSheet("color: #bdff00; font: 700 10pt 'Segoe UI';") + + # USER STATUS + self.label_description = QLabel(self.text_frame) + self.label_description.setGeometry(0, 22, self.text_frame.width(), 18) + self.label_description.setAlignment(Qt.AlignVCenter) + self.label_description.setText(self.user_description) + self.label_description.setStyleSheet("color: #A6A6A6; font: 9pt 'Segoe UI';") + + # PAINT USER IMAGE EVENTS + # /////////////////////////////////////////////////////////////// + def paintEvent(self, event): + # PAINTER USER IMAGE + painter = QPainter() + painter.begin(self) + painter.setRenderHint(QPainter.Antialiasing) + + # RECT + rect = QRect(10, 15, 40, 40) + + # CIRCLE + painter.setPen(Qt.NoPen) + painter.setBrush(QBrush(QColor("#000000"))) + painter.drawEllipse(rect) + + # DRAW USER IMAGE + self.draw_user_image(painter, self.user_image, rect) + + # PAINT END + painter.end() + + # DRAW USER IMAGE + self.draw_status(self.user_image, rect) + + # DRAW USER IMAGE + # /////////////////////////////////////////////////////////////// + def draw_user_image(self, qp, image, rect): + user_image = QImage(image) + path = QPainterPath() + path.addEllipse(rect) + qp.setClipPath(path) + qp.drawImage(rect, user_image) + + # DRAW STATUS + # /////////////////////////////////////////////////////////////// + def draw_status(self, status, rect): + painter = QPainter() + painter.begin(self) + painter.setRenderHint(QPainter.Antialiasing) + + # PEN + pen = QPen() + pen.setWidth(3) + pen.setColor(QColor("#151617")) + painter.setPen(pen) + + # BRUSH/STATUS COLOR + painter.setBrush(QBrush(QColor(self._status_color))) + + # DRAW + painter.drawEllipse(rect.x() + 27, rect.y() + 27, 13, 13) + painter.end() + +# SET STYLE TO POPUP +# /////////////////////////////////////////////////////////////// +style = """ +/* QFrame */ +QFrame { + background: #333436; border-radius: 10px; +} +/* Search Message */ +.QLineEdit { + border: 2px solid rgb(47, 48, 50); + border-radius: 15px; + background-color: rgb(47, 48, 50); + color: rgb(121, 121, 121); + padding-left: 10px; + padding-right: 10px; +} +.QLineEdit:hover { + color: rgb(230, 230, 230); + border: 2px solid rgb(62, 63, 66); +} +.QLineEdit:focus { + color: rgb(230, 230, 230); + border: 2px solid rgb(53, 54, 56); + background-color: rgb(14, 14, 15); +} +/* QPushButton */ +.QPushButton{ + background-color: transparent; + border: none; + border-radius: 10px; + background-repeat: no-repeat; + background-position: left center; + text-align: left; + color: #999999; + padding-left: 38px; +} +.QPushButton:hover{ + background-color: #151617; + color: #CCCCCC; +} + +""" +# CHAN STATUS POPUP +# # /////////////////////////////////////////////////////////////// +class _ChangeStatus(QFrame): + status = Signal(str) + def __init__(self, parent): + QFrame.__init__(self) + + # SETUP + # /////////////////////////////////////////////////////////////// + self.setFixedSize(230, 205) + self.setStyleSheet(style) + self.setParent(parent) + + # LAYOUT AND BORDER + # /////////////////////////////////////////////////////////////// + self.layout = QVBoxLayout(self) + self.layout.setContentsMargins(10,10,10,10) + self.border = QFrame(self) + self.layout.addWidget(self.border) + + # LINEEDIT AND BTNS BOX + # /////////////////////////////////////////////////////////////// + self.layout_content = QVBoxLayout(self.border) + self.layout_content.setContentsMargins(0,0,0,0) + self.layout_content.setSpacing(1) + + # CHANGE DESCRIPTION + # /////////////////////////////////////////////////////////////// + self.line_edit = QLineEdit() + self.line_edit.setMinimumHeight(30) + self.line_edit.setPlaceholderText("Write what you are doing...") + + # TOP LABEL + # /////////////////////////////////////////////////////////////// + self.label = QLabel("Change status:") + self.label.setStyleSheet("padding-top: 5px; padding-bottom: 5px; color: rgb(121, 121, 121);") + + # BTN ONLINE + # /////////////////////////////////////////////////////////////// + self.btn_online = QPushButton() + self.btn_online.setText("Online") + self.btn_online.setMinimumHeight(30) + self.btn_online.setStyleSheet("background-image: url(:/icons_svg/images/icons_svg/icon_online.svg)") + self.btn_online.clicked.connect(lambda: self.send_signal("online")) + self.btn_online.setCursor(Qt.PointingHandCursor) + + # BTNL ILDE + # /////////////////////////////////////////////////////////////// + self.btn_idle = QPushButton() + self.btn_idle.setText("Idle") + self.btn_idle.setMinimumHeight(30) + self.btn_idle.setStyleSheet("background-image: url(:/icons_svg/images/icons_svg/icon_idle.svg)") + self.btn_idle.clicked.connect(lambda: self.send_signal("idle")) + self.btn_idle.setCursor(Qt.PointingHandCursor) + + # BTN BUSE + # /////////////////////////////////////////////////////////////// + self.btn_busy = QPushButton() + self.btn_busy.setText("Do not disturb") + self.btn_busy.setMinimumHeight(30) + self.btn_busy.setStyleSheet("background-image: url(:/icons_svg/images/icons_svg/icon_busy.svg)") + self.btn_busy.clicked.connect(lambda: self.send_signal("busy")) + self.btn_busy.setCursor(Qt.PointingHandCursor) + + # BTN INVISIBLE + self.btn_invisible = QPushButton() + self.btn_invisible.setText("Invisible") + self.btn_invisible.setMinimumHeight(30) + self.btn_invisible.setStyleSheet("background-image: url(:/icons_svg/images/icons_svg/icon_invisible.svg)") + self.btn_invisible.clicked.connect(lambda: self.send_signal("invisible")) + self.btn_invisible.setCursor(Qt.PointingHandCursor) + + # ADD WIDGETS TO LAYOUT + # /////////////////////////////////////////////////////////////// + self.layout_content.addWidget(self.line_edit) + self.layout_content.addWidget(self.label) + self.layout_content.addWidget(self.btn_online) + self.layout_content.addWidget(self.btn_idle) + self.layout_content.addWidget(self.btn_busy) + self.layout_content.addWidget(self.btn_invisible) + + # SET DROP SHADOW + # /////////////////////////////////////////////////////////////// + self.shadow = QGraphicsDropShadowEffect(self) + self.shadow.setBlurRadius(15) + self.shadow.setXOffset(0) + self.shadow.setYOffset(0) + self.shadow.setColor(QColor(0, 0, 0, 160)) + self.setGraphicsEffect(self.shadow) + + # SEND SIGNAL TO TOP USER WIDGET + # /////////////////////////////////////////////////////////////// + def send_signal(self, status): + self.status.emit(status) \ No newline at end of file diff --git a/app/uis/chat/message.py b/app/uis/chat/message.py new file mode 100644 index 0000000..9b567d9 --- /dev/null +++ b/app/uis/chat/message.py @@ -0,0 +1,110 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# DEFAULT PACKAGES +# /////////////////////////////////////////////////////////////// +import os + +# IMPORT / GUI, SETTINGS AND WIDGETS +# /////////////////////////////////////////////////////////////// +# Packages +from datetime import datetime +from app.packages.pyside_or_pyqt import * # Qt + +# GLOBALS +send_by = None + +# MAIN WINDOW +# /////////////////////////////////////////////////////////////// +class Message(QWidget): + def __init__(self, message, me_send): + QWidget.__init__(self) + global send_by + send_by = me_send + + self.setMinimumHeight(20) + self.setup_ui() + self.setFixedHeight(self.layout.sizeHint().height()) + + # SET MESSAGE + self.message.setText(message) + + # SET DATE TIME + date_time = datetime.now() + date_time_format = date_time.strftime("%m/%d/%Y %H:%M") + self.data_message.setText(str(date_time_format)) + + def setup_ui(self): + # LAYOUT + self.layout = QHBoxLayout(self) + self.layout.setContentsMargins(0,0,0,0) + + # FRAME BG + self.bg = QFrame() + if send_by: + self.bg.setStyleSheet("#bg {background-color: #0e0e0f; border-radius: 10px; margin-left: 150px; } #bg:hover { background-color: #252628; }") + else: + self.bg.setStyleSheet("#bg {background-color: #28282b; border-radius: 10px; margin-right: 150px; } #bg:hover { background-color: #252628; }") + self.bg.setObjectName("bg") + + # FRAME BG + self.btn = QPushButton() + self.btn.setMinimumSize(40, 40) + self.btn.setMaximumSize(40, 40) + self.btn.setStyleSheet(""" + QPushButton { + background-color: transparent; + border-radius: 20px; + background-repeat: no-repeat; + background-position: center; + background-image: url(:/icons_svg/images/icons_svg/icon_more_options.svg); + } + QPushButton:hover { + background-color: rgb(61, 62, 65); + } + QPushButton:pressed { + background-color: rgb(16, 17, 18); + } + """) + + if send_by: + self.layout.addWidget(self.bg) + self.layout.addWidget(self.btn) + else: + self.layout.addWidget(self.btn) + self.layout.addWidget(self.bg) + + # LAYOUT INSIDE + self.layout_inside = QVBoxLayout(self.bg) + self.layout.setContentsMargins(10,10,10,10) + + # LABEL MESSAGE + self.message = QLabel() + self.message.setText("message test") + self.message.setStyleSheet("font: 500 11pt 'Segoe UI'") + self.message.setTextInteractionFlags(Qt.TextSelectableByMouse|Qt.TextSelectableByKeyboard) + + # LABEL MESSAGE + self.data_message = QLabel() + self.data_message.setText("date") + self.data_message.setStyleSheet("font: 8pt 'Segoe UI'; color: #4c5154") + if send_by: + self.data_message.setAlignment(Qt.AlignRight) + else: + self.data_message.setAlignment(Qt.AlignLeft) + + self.layout_inside.addWidget(self.message) + self.layout_inside.addWidget(self.data_message) diff --git a/app/uis/chat/page_messages.py b/app/uis/chat/page_messages.py new file mode 100644 index 0000000..d0133e9 --- /dev/null +++ b/app/uis/chat/page_messages.py @@ -0,0 +1,109 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# DEFAULT PACKAGES +# /////////////////////////////////////////////////////////////// +import os +import random + +# IMPORT / GUI, SETTINGS AND WIDGETS +# /////////////////////////////////////////////////////////////// +# Packages +from app.packages.pyside_or_pyqt import * # Qt +from app.packages.widgets import * # Widgets +# GUI +from app.uis.chat.ui_page_messages import Ui_chat_page # MainWindow +from app.uis.chat.message import Message # MainWindow + + +# MAIN WINDOW +# /////////////////////////////////////////////////////////////// +class Chat(QWidget): + def __init__( + self, + user_image, + user_name, + user_description, + user_id, + my_name, + ): + QWidget.__init__(self) + + self.page = Ui_chat_page() + self.page.setupUi(self) + + # UPDATE INFO + self.page.user_image.setStyleSheet("#user_image { background-image: url(\"" + os.path.normpath(user_image).replace("\\", "/") + "\") }") + self.page.user_name.setText(user_name) + self.page.user_description.setText(user_description) + + # CHANGE PLACEHOLDER TEXT + format_user_name = user_name.replace(" ", "_").replace("-", "_") + format_user_name = format_user_name.lower() + self.page.line_edit_message.setPlaceholderText(f"Message #{str(format_user_name).lower()}") + + # ENTER / RETURN PRESSED + self.page.line_edit_message.keyReleaseEvent = self.enter_return_release + + # ENTER / RETURN PRESSED + self.page.btn_send_message.clicked.connect(self.send_message) + + # MESSAGES + self.messages = [ + f"Hi {my_name.capitalize()}, how are you?", + f"Hello {my_name.capitalize()}, how are you today?", + f"{my_name.capitalize()}, do you know if it is going to rain today?", + f"{my_name.capitalize()}, how is your day?", + f"{my_name.capitalize()}, do you remember that you owe me $100? Humm..." + ] + + # SEND USER MESSAGE + self.send_by_friend() + + # ENTER / RETURN SEND MESSAGE + def enter_return_release(self, event): + if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: + self.send_message() + + # SEND MESSAGE + def send_message(self): + if self.page.line_edit_message.text() != "": + self.message = Message(self.page.line_edit_message.text(), True) + self.page.chat_messages_layout.addWidget(self.message, Qt.AlignCenter, Qt.AlignBottom) + self.page.line_edit_message.setText("") + + # SCROLL TO END + QTimer.singleShot(10, lambda: self.page.messages_frame.setFixedHeight(self.page.chat_messages_layout.sizeHint().height())) + QTimer.singleShot(15, lambda: self.scroll_to_end()) + + # SEND USER MESSAGE + QTimer.singleShot(1000, lambda: self.send_by_friend()) + + # SEND MESSAGE BY FRIEND + def send_by_friend(self): + self.message = Message(random.choice(self.messages), False) + self.page.chat_messages_layout.addWidget(self.message, Qt.AlignCenter, Qt.AlignBottom) + self.page.line_edit_message.setText("") + + # SCROLL TO END + QTimer.singleShot(10, lambda: self.page.messages_frame.setFixedHeight(self.page.chat_messages_layout.sizeHint().height())) + QTimer.singleShot(15, lambda: self.scroll_to_end()) + + + def scroll_to_end(self): + # SCROLL TO END + self.scroll_bar = self.page.chat_messages.verticalScrollBar() + self.scroll_bar.setValue(self.scroll_bar.maximum()) \ No newline at end of file diff --git a/app/uis/chat/ui_page_messages.py b/app/uis/chat/ui_page_messages.py new file mode 100644 index 0000000..4002738 --- /dev/null +++ b/app/uis/chat/ui_page_messages.py @@ -0,0 +1,290 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'page_messagesEjpDxJ.ui' +## +## Created by: Qt User Interface Compiler version 6.0.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import * +from PySide6.QtGui import * +from PySide6.QtWidgets import * + +class Ui_chat_page(object): + def setupUi(self, chat_page): + if not chat_page.objectName(): + chat_page.setObjectName(u"chat_page") + chat_page.resize(880, 616) + chat_page.setStyleSheet(u"QWidget { color: rgb(165, 165, 165); }\n" +"#chat_page{\n" +" background-color: rgb(0, 0, 0); \n" +"}\n" +"/* TOP */\n" +"#top {\n" +" background-color: rgb(30, 32, 33);\n" +" border-radius: 10px;\n" +"}\n" +"#user_name { \n" +" color: rgb(179, 179, 179);\n" +" font: 600 12pt \"Segoe UI\";\n" +"}\n" +"#user_image {\n" +" border: 1px solid rgb(30, 32, 33);\n" +" background-color: rgb(47, 48, 50);\n" +" border-radius: 20px;\n" +"}\n" +"#top QPushButton {\n" +" background-color: rgb(47, 48, 50);\n" +" border-radius: 20px;\n" +" background-repeat: no-repeat;\n" +" background-position: center;\n" +"}\n" +"#top QPushButton:hover {\n" +" background-color: rgb(61, 62, 65);\n" +"}\n" +"#top QPushButton:pressed {\n" +" background-color: rgb(16, 17, 18);\n" +"}\n" +"#btn_attachment_top { \n" +" background-image: url(:/icons_svg/images/icons_svg/icon_attachment.svg);\n" +"}\n" +"#btn_more_top { \n" +" background-image: url(:/icons_svg/images/icons_svg/icon_more_options.svg);\n" +"}\n" +"/* BOTTOM */\n" +"#bottom QPushButton {\n" +" background-color: rgb(47, 4" + "8, 50);\n" +" border-radius: 20px;\n" +" background-repeat: no-repeat;\n" +" background-position: center;\n" +"}\n" +"#bottom QPushButton:hover {\n" +" background-color: rgb(61, 62, 65);\n" +"}\n" +"#bottom QPushButton:pressed {\n" +" background-color: rgb(16, 17, 18);\n" +"}\n" +"#send_message_frame { \n" +" background-color: rgb(47, 48, 50);\n" +" border-radius: 20px;\n" +"}\n" +"#send_message_frame QPushButton {\n" +" background-color: rgb(76, 77, 80);\n" +" border-radius: 15px;\n" +" background-repeat: no-repeat;\n" +" background-position: center;\n" +"}\n" +"#send_message_frame QPushButton:hover {\n" +" background-color: rgb(81, 82, 86);\n" +"}\n" +"#send_message_frame QPushButton:pressed {\n" +" background-color: rgb(16, 17, 18);\n" +"}\n" +"#line_edit_message {\n" +" background-color: transparent;\n" +" selection-color: rgb(255, 255, 255);\n" +" selection-background-color: rgb(149, 199, 0);\n" +" border: none;\n" +" padding-left: 15px;\n" +" padding-right: 15px;\n" +" background-repeat: none;\n" +" background-position: left center;\n" +" " + "font: 10pt \"Segoe UI\";\n" +" color: rgb(94, 96, 100);\n" +"}\n" +"#line_edit_message:focus {\n" +" color: rgb(165, 165, 165);\n" +"}\n" +"#btn_emoticon{\n" +" background-image: url(:/icons_svg/images/icons_svg/icon_emoticons.svg);\n" +"}\n" +"#btn_send_message{ \n" +" background-image: url(:/icons_svg/images/icons_svg/icon_send.svg);\n" +"}\n" +"#btn_attachment_bottom{ \n" +" \n" +" background-image: url(:/icons_svg/images/icons_svg/icon_more_options.svg);\n" +"}") + self.verticalLayout = QVBoxLayout(chat_page) + self.verticalLayout.setObjectName(u"verticalLayout") + self.top = QFrame(chat_page) + self.top.setObjectName(u"top") + self.top.setMinimumSize(QSize(0, 60)) + self.top.setMaximumSize(QSize(16777215, 60)) + self.top.setFrameShape(QFrame.NoFrame) + self.top.setFrameShadow(QFrame.Raised) + self.horizontalLayout = QHBoxLayout(self.top) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.user_image = QLabel(self.top) + self.user_image.setObjectName(u"user_image") + self.user_image.setMinimumSize(QSize(40, 40)) + self.user_image.setMaximumSize(QSize(40, 40)) + self.user_image.setAlignment(Qt.AlignCenter) + + self.horizontalLayout.addWidget(self.user_image) + + self.user_information_frame = QFrame(self.top) + self.user_information_frame.setObjectName(u"user_information_frame") + self.user_information_frame.setFrameShape(QFrame.NoFrame) + self.user_information_frame.setFrameShadow(QFrame.Raised) + self.verticalLayout_2 = QVBoxLayout(self.user_information_frame) + self.verticalLayout_2.setSpacing(0) + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.verticalLayout_2.setContentsMargins(5, 5, 5, 5) + self.user_name = QLabel(self.user_information_frame) + self.user_name.setObjectName(u"user_name") + self.user_name.setMinimumSize(QSize(0, 22)) + self.user_name.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop) + + self.verticalLayout_2.addWidget(self.user_name) + + self.user_description = QLabel(self.user_information_frame) + self.user_description.setObjectName(u"user_description") + self.user_description.setStyleSheet(u"background: transparent;") + + self.verticalLayout_2.addWidget(self.user_description) + + + self.horizontalLayout.addWidget(self.user_information_frame) + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout.addItem(self.horizontalSpacer) + + self.last_time_connected = QLabel(self.top) + self.last_time_connected.setObjectName(u"last_time_connected") + + self.horizontalLayout.addWidget(self.last_time_connected) + + self.btn_attachment_top = QPushButton(self.top) + self.btn_attachment_top.setObjectName(u"btn_attachment_top") + self.btn_attachment_top.setMinimumSize(QSize(40, 40)) + self.btn_attachment_top.setMaximumSize(QSize(40, 40)) + self.btn_attachment_top.setCursor(QCursor(Qt.PointingHandCursor)) + + self.horizontalLayout.addWidget(self.btn_attachment_top) + + self.btn_more_top = QPushButton(self.top) + self.btn_more_top.setObjectName(u"btn_more_top") + self.btn_more_top.setMinimumSize(QSize(40, 40)) + self.btn_more_top.setMaximumSize(QSize(40, 40)) + self.btn_more_top.setCursor(QCursor(Qt.PointingHandCursor)) + + self.horizontalLayout.addWidget(self.btn_more_top) + + + self.verticalLayout.addWidget(self.top) + + self.chat_messages = QScrollArea(chat_page) + self.chat_messages.setObjectName(u"chat_messages") + self.chat_messages.setStyleSheet(u"background: transparent") + self.chat_messages.setFrameShape(QFrame.NoFrame) + self.chat_messages.setFrameShadow(QFrame.Raised) + self.chat_messages.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.chat_messages.setWidgetResizable(True) + self.chat_messages.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft) + self.messages_widget = QWidget() + self.messages_widget.setObjectName(u"messages_widget") + self.messages_widget.setGeometry(QRect(0, 0, 862, 486)) + self.messages_widget.setStyleSheet(u"background: transparent") + self.chat_layout = QVBoxLayout(self.messages_widget) + self.chat_layout.setSpacing(0) + self.chat_layout.setObjectName(u"chat_layout") + self.chat_layout.setContentsMargins(0, 0, 0, 0) + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.chat_layout.addItem(self.verticalSpacer) + + self.messages_frame = QFrame(self.messages_widget) + self.messages_frame.setObjectName(u"messages_frame") + self.messages_frame.setFrameShape(QFrame.NoFrame) + self.messages_frame.setFrameShadow(QFrame.Raised) + self.chat_messages_layout = QVBoxLayout(self.messages_frame) + self.chat_messages_layout.setSpacing(0) + self.chat_messages_layout.setObjectName(u"chat_messages_layout") + self.chat_messages_layout.setContentsMargins(0, 0, 0, 0) + + self.chat_layout.addWidget(self.messages_frame) + + self.chat_messages.setWidget(self.messages_widget) + + self.verticalLayout.addWidget(self.chat_messages) + + self.bottom = QFrame(chat_page) + self.bottom.setObjectName(u"bottom") + self.bottom.setMinimumSize(QSize(0, 40)) + self.bottom.setMaximumSize(QSize(16777215, 40)) + self.bottom.setFrameShape(QFrame.NoFrame) + self.bottom.setFrameShadow(QFrame.Raised) + self.horizontalLayout_2 = QHBoxLayout(self.bottom) + self.horizontalLayout_2.setSpacing(10) + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.send_message_frame = QFrame(self.bottom) + self.send_message_frame.setObjectName(u"send_message_frame") + self.send_message_frame.setFrameShape(QFrame.StyledPanel) + self.send_message_frame.setFrameShadow(QFrame.Raised) + self.horizontalLayout_3 = QHBoxLayout(self.send_message_frame) + self.horizontalLayout_3.setSpacing(0) + self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") + self.horizontalLayout_3.setContentsMargins(5, 0, 5, 0) + self.btn_emoticon = QPushButton(self.send_message_frame) + self.btn_emoticon.setObjectName(u"btn_emoticon") + self.btn_emoticon.setMinimumSize(QSize(30, 30)) + self.btn_emoticon.setMaximumSize(QSize(30, 30)) + self.btn_emoticon.setCursor(QCursor(Qt.PointingHandCursor)) + + self.horizontalLayout_3.addWidget(self.btn_emoticon) + + self.line_edit_message = QLineEdit(self.send_message_frame) + self.line_edit_message.setObjectName(u"line_edit_message") + self.line_edit_message.setMinimumSize(QSize(0, 40)) + + self.horizontalLayout_3.addWidget(self.line_edit_message) + + self.btn_send_message = QPushButton(self.send_message_frame) + self.btn_send_message.setObjectName(u"btn_send_message") + self.btn_send_message.setMinimumSize(QSize(30, 30)) + self.btn_send_message.setMaximumSize(QSize(30, 30)) + self.btn_send_message.setCursor(QCursor(Qt.PointingHandCursor)) + + self.horizontalLayout_3.addWidget(self.btn_send_message) + + + self.horizontalLayout_2.addWidget(self.send_message_frame) + + self.btn_attachment_bottom = QPushButton(self.bottom) + self.btn_attachment_bottom.setObjectName(u"btn_attachment_bottom") + self.btn_attachment_bottom.setMinimumSize(QSize(40, 40)) + self.btn_attachment_bottom.setMaximumSize(QSize(40, 40)) + self.btn_attachment_bottom.setCursor(QCursor(Qt.PointingHandCursor)) + + self.horizontalLayout_2.addWidget(self.btn_attachment_bottom) + + + self.verticalLayout.addWidget(self.bottom) + + + self.retranslateUi(chat_page) + + QMetaObject.connectSlotsByName(chat_page) + # setupUi + + def retranslateUi(self, chat_page): + chat_page.setWindowTitle(QCoreApplication.translate("chat_page", u"Form", None)) + self.user_image.setText("") + self.user_name.setText(QCoreApplication.translate("chat_page", u"User name", None)) + self.user_description.setText(QCoreApplication.translate("chat_page", u"User description", None)) + self.last_time_connected.setText(QCoreApplication.translate("chat_page", u"connected last time 24h ago", None)) + self.btn_attachment_top.setText("") + self.btn_more_top.setText("") + self.btn_emoticon.setText("") + self.line_edit_message.setPlaceholderText(QCoreApplication.translate("chat_page", u"Message #user", None)) + self.btn_send_message.setText("") + self.btn_attachment_bottom.setText("") + # retranslateUi + diff --git a/app/uis/login/ui_login.py b/app/uis/login/ui_login.py new file mode 100644 index 0000000..2b0d00f --- /dev/null +++ b/app/uis/login/ui_login.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'loginexbKtc.ui' +## +## Created by: Qt User Interface Compiler version 6.0.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import * +from PySide6.QtGui import * +from PySide6.QtWidgets import * + +class Ui_Login(object): + def setupUi(self, Login): + if not Login.objectName(): + Login.setObjectName(u"Login") + Login.resize(300, 420) + Login.setMinimumSize(QSize(300, 420)) + Login.setMaximumSize(QSize(300, 420)) + Login.setStyleSheet(u"#bg {\n" +" background-color: rgb(0, 0, 0);\n" +" border-radius: 10px;\n" +"}\n" +"QLabel {\n" +" color: rgb(121, 121, 121);\n" +" padding-left: 10px;\n" +" padding-top: 20px;\n" +"}\n" +".QLineEdit {\n" +" border: 3px solid rgb(47, 48, 50);\n" +" border-radius: 15px;\n" +" background-color: rgb(47, 48, 50);\n" +" color: rgb(121, 121, 121);\n" +" padding-left: 10px;\n" +" padding-right: 10px;\n" +" background-repeat: none;\n" +" background-position: left center;\n" +"}\n" +".QLineEdit:hover {\n" +" color: rgb(230, 230, 230);\n" +" border: 3px solid rgb(62, 63, 66);\n" +"}\n" +".QLineEdit:focus {\n" +" color: rgb(230, 230, 230);\n" +" border: 3px solid rgb(189, 255, 0);\n" +" background-color: rgb(14, 14, 15);\n" +"}") + self.centralwidget = QWidget(Login) + self.centralwidget.setObjectName(u"centralwidget") + self.verticalLayout = QVBoxLayout(self.centralwidget) + self.verticalLayout.setSpacing(0) + self.verticalLayout.setObjectName(u"verticalLayout") + self.verticalLayout.setContentsMargins(10, 10, 10, 10) + self.bg = QFrame(self.centralwidget) + self.bg.setObjectName(u"bg") + self.bg.setFrameShape(QFrame.NoFrame) + self.bg.setFrameShadow(QFrame.Raised) + self.frame_widgets = QFrame(self.bg) + self.frame_widgets.setObjectName(u"frame_widgets") + self.frame_widgets.setGeometry(QRect(0, 70, 280, 720)) + self.frame_widgets.setMinimumSize(QSize(280, 720)) + self.frame_widgets.setFrameShape(QFrame.NoFrame) + self.frame_widgets.setFrameShadow(QFrame.Raised) + self.verticalLayout_2 = QVBoxLayout(self.frame_widgets) + self.verticalLayout_2.setSpacing(5) + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.verticalLayout_2.setContentsMargins(20, 10, 20, 10) + self.preloader = QFrame(self.frame_widgets) + self.preloader.setObjectName(u"preloader") + self.preloader.setMinimumSize(QSize(240, 240)) + self.preloader.setMaximumSize(QSize(260, 260)) + self.preloader.setFrameShape(QFrame.NoFrame) + self.preloader.setFrameShadow(QFrame.Raised) + + self.verticalLayout_2.addWidget(self.preloader) + + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.verticalLayout_2.addItem(self.verticalSpacer) + + self.logo = QFrame(self.frame_widgets) + self.logo.setObjectName(u"logo") + self.logo.setMinimumSize(QSize(0, 260)) + self.logo.setStyleSheet(u"#logo {\n" +" border-radius: 10px;\n" +" background-image: url(:/images_svg/images/images_svg/logo_home.svg);\n" +" background-position: center;\n" +" background-repeat: no-repeat;\n" +"}") + self.logo.setFrameShape(QFrame.NoFrame) + self.logo.setFrameShadow(QFrame.Raised) + + self.verticalLayout_2.addWidget(self.logo) + + self.user_description = QLabel(self.frame_widgets) + self.user_description.setObjectName(u"user_description") + self.user_description.setStyleSheet(u"background: transparent;") + + self.verticalLayout_2.addWidget(self.user_description) + + self.username = QLineEdit(self.frame_widgets) + self.username.setObjectName(u"username") + self.username.setMinimumSize(QSize(0, 30)) + self.username.setMaximumSize(QSize(16777215, 40)) + + self.verticalLayout_2.addWidget(self.username) + + self.password = QLineEdit(self.frame_widgets) + self.password.setObjectName(u"password") + self.password.setMinimumSize(QSize(0, 30)) + self.password.setMaximumSize(QSize(16777215, 40)) + self.password.setEchoMode(QLineEdit.Password) + + self.verticalLayout_2.addWidget(self.password) + + + self.verticalLayout.addWidget(self.bg) + + Login.setCentralWidget(self.centralwidget) + + self.retranslateUi(Login) + + QMetaObject.connectSlotsByName(Login) + # setupUi + + def retranslateUi(self, Login): + Login.setWindowTitle(QCoreApplication.translate("Login", u"Login. PyBlackBOX", None)) + self.user_description.setText(QCoreApplication.translate("Login", u"Login (pass: 123456):", None)) + self.username.setPlaceholderText(QCoreApplication.translate("Login", u"Username", None)) + self.password.setPlaceholderText(QCoreApplication.translate("Login", u"Password", None)) + # retranslateUi + diff --git a/app/uis/main_window/resources_rc.py b/app/uis/main_window/resources_rc.py new file mode 100644 index 0000000..f7b6005 --- /dev/null +++ b/app/uis/main_window/resources_rc.py @@ -0,0 +1,6779 @@ +# Resource object code (Python 3) +# Created by: object code +# Created by: The Resource Compiler for Qt version 6.0.2 +# WARNING! All changes made in this file will be lost! + +from PySide6 import QtCore + +qt_resource_data = b"\ +\x00\x00\x06\x99\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00(\x00\x00\x00(\x08\x06\x00\x00\x00\x8c\xfe\xb8m\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\ +\x01\xc7o\xa8d\x00\x00\x00\x19tEXtSof\ +tware\x00www.inksca\ +pe.org\x9b\xee<\x1a\x00\x00\x06&ID\ +ATX\x85\xed\x98KlcW\x19\xc7\x7f\xe7\x5c\xfb\ +\xbeb;~\xc4\xb1=\xe9<\x12'\xe9L\xa8\x10\xa0\ +\xc2\xa0A\xc0 A\xa1\x15*l*$DY \x81\ +\xc4\x82\x05\xec\x90h\xc5\x86\x0d\x12\x02VP6H\xd0\ +\x22u\x07\x9a\x22\x16D\xa3\x09S\x1e\x0b\xdaJ\xa8\xd3\ +\x96df2d&vl\xc7\x8e\xaf\xdf\xf7\xda\xf7^\ +\x163\x9dI\x9a\xeb\xc7b\xd31\xd6\ +\xca=\x9eN\xfb\xe4\xd4\xe1\xb92\x12\xf0\xcf\x96@\xd5\ +uTU=\xd0n;6\x96e\xe186\xc5\x9eM\ +q\x94\x13\xc0\xb2|\xa6\xa7\x05\x9av\x07RU5T\ +]g\xb5\xde\xe1\xe9\xd9{\x00\xf4\x81\xd5\xba :\x1d\ +\x03@\x08A\xa7\xd3\xa6V\xdb\xc3\xf7\xbd1H\x07\xe5\ +86\x95J\x19!$\xc9D\x12s\xca\xc0\xf7!\x1a\ +\x89\xb1j\xf5\xf8\xda\xac\xc7\xb0D\x19\x9a\x04\x9b=\xa8\ +yaTM\xc5\xf3}J\xa5\x12\xd5j\xf5\xae\xe1\xf6\ +\xcb\xf7=\xaa\xb5]J\xa5\x12\x9e\xef\xa1j*UO\ +\xe1\x9a=<\x8f\x87\x02\xbe\xda\x92\x18\x86\x8e\xe7\xf9\x14\ +\x0b\xdb8\x8e}\xcf`\xef\x94\xe38\x14\xb6\xb7\xf1<\ +\x0f\xdd0xuD\xf1\x1f\x0a\xf8zW`\x98S\x14\ +\x8b\xdb\xf8\xfe\xff\xe6D\xb6\xb3Sd\xca\x98\xe2Rg\ +\xb8\xcdP\xc0k\x9eJ\xad\xba;\xb4\xe3\xf1\x8c\xcd\x94\ +\xee\x8e\x04\x98\x99\xee\x93\x8e\xf7\x87~\xf7}\x9f\xdd\xea\ +.W\x07\xfaP\x9b\xc0E\xd2q\x05m\xa1\xe1\xba\xad\ +\xc0N\xdf\xfeR\x91/\x9cn\x13\x96\x0e\xdf\xf8\xf1\x22\ +;5\xf5\x90\xcd'\x1ei\xf0\xcc\xd7\x0b \xe0G\xbf\ +\xcdq\xf1_\xd3\x81\xbe<\xcf\xa5\xad\x98\xf4\xbc\x0ez\ +\xc0p\x05\x8e\xe0E\xdb\xa4\xd5\x0a\x86\x03\xf8\xfc\xc7\x9a\ +|\xe7\x17gy\xf1\xe5\x15\x1e?\xbd\x17h\xf3\xd4\xd9\ +\x0a\xcf\xbep\x86\x1f\xfc\xe6\x0c_\xf9\xcc\xf0\x99\x00h\ +\xb5\x9a\xbc\xec\x98\x81\xdf\x02\x01/t\xb4\xa0\xe6\xdb\xea\ +\x0f|r\xc96\xc7\xd2\x0d\xacV\xf0vg\xb5B\xcc\ +\xcfZ\x9c\x98mRo\x8f\xdf\x12\xcf\xb7\x83\xa79\x10\ +p\xa31z\x93\xfc\xc9\x8b9\xbe\xff\xd4_\x89\xaaU\ +\xfe\xf8\xf7d\xa0\xcds/\xe5x\xe2\xd17x\xf2\xf4\ +\xeb\xfc\xf2\x0f\xb9\xb1\x80\x1bVpL\xf1\xceKS_\ +H\xbe\xfc\x86\x827\xc1\xca\x8d\xc7\x13\xc4\xe3q\xa2\xd1\ +(\x9a\xae\xa3(7S\xdau\x07\xf4z=Z\xcd&\ +u\xabN}/8\x0d\xf6KJ\xc9\xefO\x0e\x08s\ +\xb0\xce\x1eZ$Uw4\x9c\x94\x92l6G\xee\xc8\ +\x1c\xaa\xaa\xd2l5i\xb7\xdb\xb4;\x87kE4\x1a\ +#wd\x0e\xc7\xb1)\x14\x0a\x94v\x8ax^p\xa1\ +\xf7<\x8f\xaa\xa7\x90\x95c\x00c\xd2\x83!\x1bO$\ +\x1acqq\x09\xe3\xd6\xc9\x06\xe0\xca\xc6\x06\xddnp\ +!3\x0c\x93\x0f}\xf8#\xa8\xaa\xc6\x89\x13\xf3d2\ +Y\xael\xac\xd3l5\x03\xed\xa7\xc5\xe1\xb2u\x08\xd0\ +\xc4ESMl\xe7`Nd2Y\x8e\xcc=D\xad\ +\xbaK\xd5\xf3\x91\x8a$\x9d\x9ee~!\xcf[o^\ +:42RJ\xe6\x17\xf2\xf4\xfb}*\x952\x9e\xeb\ +!\xa5dq\xf9a\xb6o\xdc\xa0\x5c\xde9`\xaf\xa9\ +*\x868\xfcG\x03\xeb\xe0\xb1\xa8\xc6F\xf5\x0e\xe0\xec\ +l\x96\x85\xfc\x22\x00G\xe6\x1e\x02\xc0u]J;;\ +\x84\xc3aN\xad<\xc2[o^\xc2u\xdd\xdbp'\ +O\xad\xe0\xd86\xedV\x8bL6\x8b\xa2\xdcY\xc9\x0b\ +\xf9<>\x1e\x95r\xf9v\xdb\xf1\xa8\x06L\x08\xf8X\ +t\xc0F\xf5\xe6\xef\xa9H\x84\x85|\x1e\xcf\xf7i6\ +\x1a\xf4z\x1d\x04\x12M\xd3\xc8d\xb3t\xbb]z\xdd\ +.++\x1f`c}\x1d%\x14faa\x9e^\xcf\ +\xc60\x0d\x92F\x8af\xb3\x89c\xdb\xf8x\xe8\xbaI\ +4\x16#\x9f_\xa4\xd3\xe9\xd0\xbeUo\x1f\x8b\x05\xef\ +8\x81e\xe6\x09\xb3I\xcc\xd4\x11B\xb0\xb4\xb4\x8c\x10\ +\x82A\xbf\x8f\x14\x82d*M\x22\x95B\x09)\x94\xcb\ +e\xea\xf5=\x12\xc9$\xbb\xd5*\xb9\xb994]E\ +*!\x12\xc9$\xf5z\x9dr\xb9L(\xa4\x90H\xa5\ +H\xa6\xd2\xc8[\xbe\x84\x90,..\x010m\x1a<\ +n\x04o\x0c\x87\xca\xcc\xdb\xfa\x9bm\xf2\x5c#N~\ +i9\xb0\xe3~U\xab\xbb\xf8\xbe\xcf\xccL\x1a\xd7u\ +\xd9\xbcz\x85\xfc\xe2\x12B\x8c\xbf\xf6]\xde\xf87\xdf\ +\x8c6\xf8\xa4\xde\xbe;@\x805\xed(kF~l\ +\x90\xfb\xd1\xd9\xeee>e\xdf\x18\xfa}\xe4\xad\xe5\xd3\ +\xf6u>\xdb\xbd\xfa\xc0\xa1n\xfb\xefm\x8e\x84\x83\x09\ +.\xeeg\xec-\xc2\xbe\xcb\xaa\x99\xa7\xff\x80^J\xc2\ +x|\xae{\x99G\xed\xc2X\xdb\x89^\x16>\xeal\ +\xb3\xe0\xd68g\x9edK\x09>6M\xaa\xe3\x83:\ +Ov\xd6Ix#N\xa9\xfb42\x07\x83\xb4\xa5L\ +\xf3\x0f\xfd(\xeb\xe1\x19&\xbd\x9dH\xe0a\xa7\xc2\xc7\ +\x9d\xeb\x1c\x1d4\xee&\xdcd#\xb8_\xc7\x5c\x8bc\ +m\x0b[\x84\xf8\x8f\x12g3\x1c\xa7*MZR\xa5\ +#n>\xb6\x98~\x9f\x88\xe7\x90\xf2:\xcc\x0f\xf68\ +>\xb0\xd0\xfc\xc1\xdd\x86\xba7\xc0\xb7\xa5\xf9\x03\x96\x07\ +\xbb,\x0fF\x1fF\xefW\xef\x9d\xf7\xc1wK\xef\x03\ +\xde\xaf\xfe\x0b\x7f\x9fb\xc1\x80\x827\xa5\x00\x00\x00\x00\ +IEND\xaeB`\x82\ +\x00\x00\x06c\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00(\x00\x00\x00(\x08\x06\x00\x00\x00\x8c\xfe\xb8m\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\ +\x01\xc7o\xa8d\x00\x00\x00\x19tEXtSof\ +tware\x00www.inksca\ +pe.org\x9b\xee<\x1a\x00\x00\x05\xf0ID\ +ATX\x85\xed\x98kl\x1cW\x15\xc7\x7fwfv\ +\xbcO\xef\xfamg\xb7\xce\xc3\xbbI\x88\x13\x876\xc5\ +V\x9b\xb6)\x84W\x13PBE\x8a\x0aRA\x15 \ +$$\x08\xaa\xf8BIk\x81@\x02JQ? \x02\ +\xad\xaa\x86\xaaAE\xad\x8c\x04j\x1e\x0e\x0d\xad\x9b\xc8\ +M\xea\xc1\xe1\x02\xfa\xe3\xb7\x91\xcc8Q\x94,\xa5\ +\xf6\x10\x95E\x03\xac\xf6\xc5\xb0\xea\xd9\xc5\x01J\x09\x91\ +D1;\xbe\xfb\xf3\xa9\xc1\xe1\xfeK\xbc\xfb\xf6\x9b\xf8\ +7l\xa2\xab\xf9?\xec\x0a\xf8\xa6\xe0:\x86Gh\xe8\ +\xec\xc2V\xe4\xe2\xf1W\x7fH\x99\xaf\x8a\x0a\xefJ\xdc\ +\xab\x8a\xa9p\xb91\xd2ib\xa3\x11\x9aB\xbd\xbcx\ +\xe2\x0c\x161\xcc\xe7?u\x82{\xd7\xf5`\xd1\x16\x1e\ +m1\xbd\xd4=\xd5\xb0\x85e\xf7\xfe\x02\xaf\x7f\xdd\x0d\ +\x86C\xe1^\x8e\xfc\xe5wh\x98\x98R\x225\x9d\x07\ +\x1e\xdd\xcd\xf2\xc0Z$\x12\xd3\xe4\xcas\x09B\x08T\ +E\xa0\xa9\x0ay\x9a\x8a\x10\x90\x88\xc7i9\xf6:m\ +\xcd\xaf\xf1\xb5\xdaf\xb6\xac\xeb\xca\x1dp,e\xe1\xc9\ +\xbf}\x89\xba\xaf?Ny\xa5\x7f\xc6\x09Y\xc3@\xd5\ +r\xf8\xf8\x05X5\x15\x87U'OSIONp\ +\xf0\x95}\x88\x91C\xfc\xf8\x81\x83\xa8\xea\xdc\xad\x80Z\ +\xff}\xea?\xb8\xc9\xb3\x98\xd4\xad\xee\xa1\xe1\x1f=D\ +\x221\x8a\x96\x05\xd0t\xfd\xba\x09\x8a\x92{\xea4L\ +I*m0\x91\xc9b\xb1XX\x7f{-\xd1T\x01\ +\x8dMq6\xaf\x99;\x92b\xa6nFJ8\xd6\xe1\ +\xa5\xb1u=\xb1\x89|>\xf7H=\xee\xa2\xd2\x9c\xc1\ +f\x93\xa6\xaa\xb8m:\x8d\xaf\xee\xa3\xc6\xf6\x0c[k\ +\xde\xcf\x0dp\xbaz\x07\x9d\xfc\xf1\xf5]l\xfb\xc1o\ +\x10b\x09+\x87\x00\xa7E\xf0\xe2ow\xf3\x87o\xbf\ +\x84\x103c\xcc\xbb^\xcb\xcb\xc6\xa9\xa98\xc3\xbbo\ +\xfds\xe9\xe0\x00$$\xd2\x12_\xe0\x0e:\x83\x9eY\ +\xcd\x16\xb4\xa1\x1e\xbe\xef\x0c\xe1\xb3/3\xd8wq\xc9\ +\xf8\x00$P\xb2r=\x9d\xa1\xdbf\xb5Y\x10\xa0\xaa\ +H\x1e\xdb\xf1\x06\xc7\xff\xfek\xc6\xa3#\x0bz\xf9\xe8\ +\xe5~\x92c\xb1y\xed\xec\xf9\x05\x0c\x8f;\x16\x07\x08\ +P\xe8\x9a\xe4'\xdb\x8f\xd0\xf8\xc2\x13\x18\x99\xcc\x9c\xb6\ +\xe9T\x92\xc3\xfb\xf7\x22\xc4\xfc\xeeM3\x8b\xaa\xcc\x9e\ +\xb8s\xca\x19\xcb\xcb\xc6\xd9\xb6\xf1$\xedM\x0ds\xda\ +u\xb6\x1cc\xc3][\xb19]\xf3\xfaL\xc4\xa3\x14\ +;f\x8ft\xceI\xed\xfe\x0d=\xf4u\x1c\x9b\xd3f\ +8\x1c\xa4be`A\xfeF\x82mT\x16\x0f\xcd:\ +\x9e3\xa0\xae\x99\xc8l\xea\xbagC}AL\xf3\xda\ +2M\xa6RX\xac\xd6\x05\xf9{\xfft\x13\x86\xa1\x12\ +O\xe83\x8e\xe7\xd4\xb0NI^\x83\x89\x0c\xf4q\xf8\ +\xf9=\xe8\x8e\x22*\x02u\x94x\xfdh\x9a\x8d\xfe\x8b\ +\xe7\x09l\xfc\xcc\x9cn\xba\xcf\x1egeq\x84\xf0\x88\ +\x8d\x83->J=)\x1e\xfd\xf2{\xe8\xd3\x9a\x89\x9c\ +\x01\xa5\x04S\x5c\xfb\xb5\xe1\xf3gyxK\x1b\x9b\xab\ +C\x9c>\x7f\x88\xb6\x1e?\xb6I\x0f\xadG\xdb\xf1\xd7\ +\xdc9kr\x0fu\xb5\xd3yt/\xbf\xfcf3V\ +=\xcb\xce\xcd\xbd\xbc\xd9Z\xce\xbeC\xab\xf9\xde\xf6s\ +Sv9/\xf1\x81\x965\xf8\xd6\xd4M\xdd_ \ + \ + \ + \ + ;P6_\x00\ +\x00\x04\x94IDATX\x85\xed\x98\xcdn\xd3J\x18\ +\x86\x9f\x99q\xe28u\x1a\x8a\x0dQ\x7f\x22\x91.h\ +D+\xb1\x80}\xc5\xa2\xac\x10\xdb\xeez\x1fg\xc9M\ +\xb0dSq\x03H\xdc@\x97T\xdd\x81P+u\x81\ +\xd4\x16\x94\x04[\xadc\xe2\xbfxX\xa0D-\x9c\xa4\ +4\xe5\xb4=\x12\xaf4\xf2\xc2\xdf|\xf3\xd8\xf3\xfd\x8c\ +-^\xbcxq\x08T\xb8\x99\x0a\x0c`\xee\xba)\xc6\ +\xa8\x22\x81\xe0\xba)\xc6(\x90\xd7Mp\x9e\xfe\x02^\ +V7\x1e\xd0\xb8\xac\x03!\x04Y\x96\xd1\xedv\xc9\xb2\ +\xec\x87S\xc3\xc0\xb6m\x0c\xc3@k}}\x80RJ\ +\x8e\x8f\x8f\x11B\xf0\xe0\xc1\x03\xee\xdc\xb9\x03@\xab\xd5\ +boo\x0f\xad5\xd5j\x95<\xcf\xaf\x1ePJ\x89\ +\xef\xfb8\x8e\xc3\xf3\xe7\xcfY\x5c\x5c\xc40~\xb8\xcb\ +\xb2\x8c\xfd\xfd}\xde\xbcy\x83\xe7y\xcc\xcc\xccL\x0c\ +9\x11\xa0\x10\x820\x0c\x99\x9e\x9efcc\x83\xb9\xb9\ +9Z\xad\x16\xfd~\x1f\x00\xa5\x14+++\xdc\xbau\ +\x8bW\xaf^\x11\x86!\xe5ry\xa2\xed\x9e(I\xb4\ +\xd6|\xfb\xf6\x8d\xd5\xd5U\x16\x16\x168::\x22\xcf\ +s\x84\x10\x08!\xc8\xf3\x9c\xc3\xc3C\xea\xf5:\xab\xab\ +\xab\xf4z\xbd\x89cq\x22\xc0$Ip]\x97F\xa3\ +\xc1\xf1\xf11R\xfe\xeaf\x10\x9f\xf7\xee\xdd\xc3q\x1c\ +\x92$\xb9:\xc0,\xcb\xb0m\x1b\xd34\xc7.\x9c$\ +\x09\xa5R\x09\xdb\xb6\x87\x19~%\x80J)\xa2(\x22\ +\xcb2\x94Rc\xed\xd24%\x8a\xa2\xb1v\x7f\x1c\xb0\ +X,\xd2n\xb79::\x1aYF\xf2<\xa7Z\xad\ +\xf2\xf9\xf3g\xda\xed6\xc5b\xf1\xea\x00\xa5\x94(\xa5\ +\xd8\xda\xda\x22\x0cC\x5c\xd7Ek}f\xb8\xaeK\x18\ +\x86lmm\xa1\x94\xfa\xd78\xfd\xcf\x00\x07\x05\xf8\xe0\ +\xe0\x80\xcd\xcdM|\xdf\xa7V\xab\xe1\xba.\xae\xebR\ +\xab\xd5\xf0}\x9f\xcd\xcdM\x0e\x0e\x0e\xa8V\xab\x13g\ +\xf1\xc4\x85Zk\x8d\xe38\xec\xed\xed\xf1\xf2\xe5KV\ +VVp\x1c\x07\x80\xaf_\xbf\xf2\xfe\xfd{NNN\ +\x86owR]\x18P\x08A\x92$\x84aH\xbf\xdf\ +\xc7\xb2,\xd24e{{\x9bR\xa9\x04@\x14E\x18\ +\x86\x81eYt:\x1d\xa4\x94\xd8\xb6M\xb1X\xbc0\ +\xeco\x03J)\xe9\xf5z\x9c\x9c\x9c033\xc3\xf2\ +\xf22\xf3\xf3\xf3\xb8\xaeK\xa5R\xc14\xcda\xa6\xf6\ +\xfb}\xe28&\x08\x02:\x9d\x0e\x87\x87\x87|\xfa\xf4\ +\x89V\xab\xc5\xf4\xf44\x96e\xfdv\xeb;\x17P\x08\ +\x81\xd6\x9av\xbbM\xa5Ramm\x8d\xe5\xe5ej\ +\xb5\x1a\xc5b\x91,\xcbH\xd3\x94~\xbf?|;B\ +\x08\x94R\xd4\xebu\x0a\x85\x02I\x92\xf0\xe5\xcb\x17>\ +|\xf8\xc0\xbbw\xefh\xb7\xdb8\x8e3\xf4=1\xe0\ +\xa0mu:\x1d\x9a\xcd&\xcf\x9e=\xa3^\xaf\x13\x86\ +!A\x10\x0c\xdb\xdb8i\xad\x91Rr\xf7\xee]\x1a\ +\x8d\x06\x0f\x1f>\xe4\xed\xdb\xb7|\xfc\xf8\x11\xc7qP\ +J\x8d\x85TO\x9e<\xf9\x070G\x19x\x9e\xc7\xe3\ +\xc7\x8f\xd9\xd8\xd8\xc0\xb2,\xda\xed6q\x1c\x0f\x1f\xe0\ +<\x0dl\xe28\xa6\xdb\xed\xe28\x0e\x8f\x1e=\xc2\xf7\ +}\xf6\xf7\xf7)\x97\xcb\xe3\xa6'#\xcb\x8c\x10\x02\xdf\ +\xf7YZZb}}\x9d^\xaf\x87\xe7y\xc3\x03\xc1\ +E5\x98\xe7y\x1e\xbd^\x8f\xf5\xf5u\x9a\xcd&\xbe\ +\xef\x8f\xf57\x120MS,\xcb\xe2\xe9\xd3\xa7h\xad\ +\xe9v\xbb\x13\x17\xdb3\x0bJI\xb7\xdbEk\xcd\xda\ +\xda\xda\xb0\x0a\x5c\x180\x08\x02\x9a\xcd&\xf3\xf3\xf3x\ +\x9e\xf7G\xe0NCz\x9e\xc7\xc2\xc2\x02KKK\x04\ +\xc1\xe8O\xf3\x91\xabj\xad\x99\x9d\x9d=7\x88'\x95\ +\xd6\x1a\xa5\x14\xb3\xb3\xb3c\xfd\x8f\x04\x94RR*\x95\ +\xd0ZO\x14s\xe7iPb,\xcb\x1a\xeb\x7fd\x99\ +\xe9\xf7\xfb\x84a\x88i\xfe\x9a\xe0\x83\x80\x17B \xa5\ +DJy&y\x06\x07\x86<\xcf\xc9\xf3\xfc\xcc!\xe2\ +\xb4L\xd3\x1cv\xa4\x0b\x03NMM\xb1\xb3\xb3\xc3\xe2\ +\xe2\x22\x8dFcX\x88\x07cP\xa0\xb3,\x1b\x9e\x0d\ +\x07\xddAJ\x89a\x18\x14\x0a\x853\xd7\xd3\x0f\xa6\x94\ +bww\x97\x9d\x9d\x1dl\xdb\xbe8`\xb9\x5c&\x08\ +\x02^\xbf~\xcd\xfd\xfb\xf7\x87N\xd24%\x8ec\xe2\ +8&\x8a\x22\xe28\x1ev\x92\xd3\x80J)\x0a\x85\x02\ +\xa6ib\x9a&\xa5R\x09\xd34)\x14\x0a\x00t\xbb\ +]vwwI\x92\x04\xdb\xb6G\xb6\xbe\x91\x80y\x9e\ +c\xdb6Q\x14\xb1\xbd\xbd}\xe6\xde\xe9\xad==~\ +\x9e\xff\xf38\xbd\xc5B\x08\xa6\xa6\xa6\xc6\xc2\x8d\x05\x1c\ +,R,\x16\xb9}\xfb\xf68\xb3K\xe9\xbcC\xc3\x8d\ +\xff7\xf3\x17\xf0\xb2\xfa_\x00\xde\xd4?\xfc\x00\x15\x03\ +8\xe2\xe6B\x06\xdf\x01\xfc\x97A\xa4\x0eZ\x17\xa8\x00\ +\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x11\xb8\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x96\x00\x00\x00\x96\x08\x02\x00\x00\x00\xb3c\xe6\xb5\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc4\x00\x00\x0e\xc4\ +\x01\x95+\x0e\x1b\x00\x00\x05\x16iTXtXML\ +:com.adobe.xmp\x00\x00\ +\x00\x00\x00 \ +Vl\xd5\xd5\x00\x00\x0cHIDATx\ +\x9c\xed\x9d[S\xdbF\x14\x80WWc\x19_\xe4\x0b\ +-f\x8cm\x1a\x88]\x92L\x9a\xe9\x84d0I\x9b\ +\xf6\x8f\xf5ou\xfa\xd2\x8eg\x9a\x86\x97\xceP2\x09\ +$\x0e\x09\x84\x04\x02\xbe\xe0\xd8\xc6\x92v\xd5\x873h\ +\x1cH)\x09Z\xd9\xc7\xd9\xef\x8117I\xd6\xa7\xb3\ +{v\xa5=\x96~\xf9\xe5\x17\x22\xc0\x8c<\xec\x03\x10\ +\x5c\x16\xa1\x10=B!z\x84B\xf4\x08\x85\xe8\x11\x0a\ +\xd1#\x14\xa2G(D\x8fP\x88\x1e\xa1\x10=B!\ +z\x84B\xf4\x08\x85\xe8\x11\x0a\xd1#\x14\xa2G(D\ +\x8fP\x88\x1e\xa1\x10=B!z\x84B\xf4\x08\x85\xe8\ +\x11\x0a\xd1#\x14\xa2G(D\x8fP\x88\x1e\xa1\x10=\ +B!z\x84B\xf4\x08\x85\xe8Q\x87}\x00\x5cp]\ +\xf7\xa3?\x97$)\xe0#\x09\x80\xb1R\xe8\xba.c\ +\xccu]UU5MSU\x15\x9c\xb9\xae\xeb8\x8e\ +m\xdb\x8e\xe3H\x92$\xcb\xf28\xb9\x1c\x13\x85\xae\xeb\ +RJC\xa1P&\x931M3\x99LNNN\x86\ +\xc3aEQ$Ir\x1c\xa7\xd7\xeb\xb5\xdb\xedF\xa3\ +\xd1h4\xf6\xf7\xf7-\xcb\x82_\x0d\xfb\xc0}`\x1c\ +\x14RJ#\x91\xc8\xfc\xfc|.\x97\xcbd2\xd1h\ +\xd4\x0bGhQ%I\xf2\x82\xef\xe8\xe8\xe8\xdd\xbbw\ +;;;\x9b\x9b\x9b\xddnW\x96\xd1g\x03\xb8\x152\ +\xc6TU]\x5c\x5c\x5c\x5c\x5cL$\x12\x9a\xa6\xd9\xb6\ +}|||\xce\xbfLLL\xcc\xcd\xcd\xe5r\xb9r\ +\xb9\xbc\xb6\xb6\xf6\xf4\xe9S\xc7qP\x8bT~\xfc\xf1\ +\xc7a\x1f\xc3gB)M\xa7\xd3?\xfc\xf0\xc3\xf5\xeb\ +\xd7\xc3\xe10tx\xff\x95\xc8x@\x93K\x081\x0c\ +#\x9f\xcfg2\x99z\xbd\xde\xe9t\xf0Z\xc4\x1a\x85\ +\x94\xd2B\xa1\xb0\xb2\xb2\x12\x8dFA\xc9'\xe1\x89\x9c\ +\x9d\x9d5M\xb3Z\xad\xbex\xf1BQ\x14\x0eG\xca\ +\x1d\x94\x97\x1e\xa5taa\xe1\xa7\x9f~\x8a\xc5b\x9f\ +\xe1\xef\xd4\xa6b\xb1\xd8\xcf?\xff\xbc\xb0\xb0p\xc9M\ +\x0d\x0b|\x0a)\xa5sss\xf7\xef\xdf\x0f\x87\xc3\x8e\ +\xe3\x5c~\x83\x8e\xe3\xe8\xba~\xef\xde\xbdB\xa1\x80\xd1\ +\x222\x85\x8c\xb1t:\xbd\xbc\xbc\xac\xeb\xbam\xdb~\ +m\xd6q\x9cP(T\xa9TR\xa9\x14c\xcc\xaf\xcd\ +\x06\x032\x85\xaa\xaa\xde\xb9s'\x1a\x8d\xfa\x12\x7f\x83\ +8\x8e\x13\x8b\xc5\xee\xde\xbd\xab\xaa\xc8\xf2\x03L\x0a)\ +\xa5\xa5Rivv\x96SsG)\x9d\x9d\x9d-\x95\ +J\xb8\x02\x11\x8dB\xd7u\x0d\xc3\xb8v\xed\x1a\xef\x1d\ +]\xbbv\xcd0\x8c\xff\x1d\x9c\x8c\x0eh\x14RJ\xe7\ +\xe7\xe7\x13\x89\x04\xd7\x10q]7\x91H\x5c\xb9r\x05\ +Q^\x83C\xa1\xeb\xba\xa1P(\x97\xcbi\x9a\xc65\ +>\x18c\x9a\xa6\xe5r\xb9P(\x84%\x10q(d\ +\x8ce2\x99L&\xe3{\x16s\x16\xc7q\xd2\xe9t\ +:\x9d\xc6\xd2#\xe2P\x08\xed\xdb\xe5\x07\xf2\x17\x81R\ +\x1a\x8f\xc7M\xd3\xe4\xbd#\xbf@\xa0\x10\xee\xff%\x93\ +\xc9 wj\x9a\xa6\xa2((\xdaR\x04\x0a\x09!\x9a\ +\xa6}\xde\x5c\xe8\xe7A)\x8dF\xa3\x9a\xa6\x05\xb3\xbb\ +K\x82C\xa1\xaa\xaap/\x22\x98\xdd\xc1\x00\x06\xcb\xac\ +7\x0e\x85\x92$\xa9\xaa\x1a\xa4BUU\xb1\xdc~\xc2\ +q\x94\xc1\x83\xa2\x17\x04p(\x84\xdb\xb9\x81=\xea\x22\ +I\x12\xa5T\x0c*\xfc\x04\x9e_\x0aRa\xb7\xdb\xc5\ +2A\x83C\xa1m\xdb\xedv;\xb0\xceIQ\x94v\ +\xbb\xed\xe3\xcd,\xae P\x08\xcdZ\xbd^\x0f\xf2\x99\ +\xc1F\xa3\x11d\xd3}\x19\x10(\x04\x9a\xcdf\xbb\xdd\ +\x0e \xd1W\x14\xa5\xd5j5\x1a\x0d\x14\xfe\x08\x16\x85\ +\xb2,\xbf{\xf7n\x7f\x7f?\x80\xfb\xb1\xaa\xaa\x1e\x1c\ +\x1c\x1c\x1c\x1c\x88A\x85\x9fH\x92\xd4\xef\xf7\xb7\xb7\xb7\ +m\xdb\xe6\x1a\x1c\xb2,\xdb\xb6\xfd\xea\xd5\xab~\xbf/\ +\xa2\xd0g\x14E\xd9\xdc\xdcl4\x1a\x5c\x83C\x92\xa4\ +f\xb3\xf9\xfc\xf9s,S3\x04\x91BI\x92z\xbd\ +\xde?\xff\xfc\xc3{Gkkk\xddn\x17K\x08\x12\ +D\x0a\x09!\xb2,?}\xfa\xf4\xe5\xcb\x97\x9czD\ +EQ^\xbe|\xf9\xe4\xc9\x13,\xbd \x80\xe9X\x09\ +!\x8e\xe3<|\xf8\xb0\xd5j\xf9nQU\xd5\xa3\xa3\ +\xa3\x87\x0f\x1fb\x19\xd1{ S(\xcb\xf2\xe1\xe1a\ +\xb5Z\xed\xf7\xfb>\xde\x0cRU\xb5\xdf\xefW\xab\xd5\ +\xc3\xc3C\x5c!H\xd0)$\x84(\x8a\xb2\xb5\xb5\xf5\ +\xfb\xef\xbf\xf7z=_b\x11\xfc\xfd\xf1\xc7\x1f[[\ +[\x88\xb2\x18\x0fd\x8f\xbd\x02\x90\x9dZ\x96\xb5\xb2\xb2\ +r\xc9\xa71TUm\xb5Z\xd5j\x15\xa9?\x82T\ +!9I=\xde\xbf\x7f\x7f\xe7\xce\x9d|>\x0f\x93p\ +\x17\xbfC$I\x12>>\ +\xfe\xfb\xef\xbf\x1f?~\x0c\xe5\x12L\xd3\x9c\x9c\x9c4\ +\x0c\x03\xf2\x1dJi\xb7\xdb\x1d,\x97`\xdb\xb6\xa2(\ +\xd8\xe5\x01\xe3\xa0\x90\x9c<\x5cC)\xdd\xdd\xdd}\xfd\ +\xfa5\x14-\xf1$1\xc6(\xa5\x83EK\xd0-_\ +:\x87\xf1y'\xe4$I!\x84\xb8\xaekY\xd6\xd9\ +?\x18's\x1ec\xf8\x96\xc8\x98Vy\xfa/\xc6S\ +!0\x98\x9a\x8e\xb1T\x94\x0a\xc1\xcd`Y B\x08\ +t{\xf0Z\xd34\xe8\xf0\xbc\xbe\xd0q\x1c\xc6\x18<\ +\x0e\x03\xff\x08\x0f\xa8\x0d\x96\x17\x228M\xa3Q\xe8\x15\ +t\x92eY\xd7u]\xd75M\x0b\x87\xc3\xb0\x5c&\ +\x1c\x0e\x1b\x86\x11\x0e\x87#\x91\x08txge\x80*\ +\xdb\xb6\xbb\xddn\xaf\xd7\x83\xafGGG\xcdf\xb3\xd7\ +\xeb\xd9\xb6mY\x96eY\x8c1\x5cu\xdaF]!\ +\x98c\x8cMLL\xc4\xe3qXs\x94L&\xe3\xf1\ +8\x98\x83? \x1f\x86\xe69\xa8\xaaj\x18\x069q\ +\x0c\xaa\xc0e\xab\xd5\xaa\xd7\xeb\x8dF\xa3\xd5j\xb5Z\ +-o\xd48\xe2.GW!\xb8\xd1u}zz:\ +\x9b\xcd\xa6\xd3\xe9X,\x16\x8f\xc75M\x83A\xc2\x7f\ +\xa5\x9d\x17\xd9\xb2\xf7\x1a\xe6W5MK\xa7\xd3_}\ +\xf5\x15O\x1cP\x14B\x11\xbc\x95\x95\x95p\ +8<\x82c\x06_\xf0F\x1d\xf7\xef\xdfW\x14\xe5\xd9\ +\xb3g\xc1\xc4b\x10Q\xc8\x18+\x14\x0aP\x8a\x19\xdd\ +\xe3\xee\x9f\x0a\xa5\xd40\x8c{\xf7\xee\xe5\xf3\xf9`\xa6\ +&\xb8+d\x8cMMMU*\x95\x89\x89\x89\xb1\xf7\ +\x07PJ\xc3\xe1p\xa5R\xc9d2\x01\xbce\xbe\x0a\ +\x19c\x86aT*\x95d29\x06\xc9\xe7\xc5q\x1c\ +'\x99LV*\x95H$\xc2;\x169*t]W\ +\x92\xa4\xef\xbe\xfb.\x9b\xcd\x8e\xfe\xb4\x8b\xefX\x965\ +33s\xeb\xd6-\x98\xa9\xe7\xb7#\xbeQX(\x14\ +\x16\x17\x17\xbf\xa8\xf8\x1b\xc4\xb6\xedo\xbf\xfd6\x9f\xcf\ +s\xdd\x0bG\x85\xba\xae\xdf\xbe}[Q\x14,e\x94\ +|\xc7u]EQn\xdf\xbe\xcd\xb5\xa8\x22/\x85\x94\ +\xd2r\xb9\x0c\xf3g\x9cv\x81\x02Ji2\x99,\x95\ +J\xfc\xce\x03\x17\x85\xae\xebF\x22\x91R\xa94\xb2\x0f\ ++\x04\x89$I\xe5r9\x12\x89p\xea\x11\xb9(t\ +\x1c'\x80j\xf6X\x80\x1b\xa2W\xae\x5c\xe1\x94\x13\xf8\ +\xaf\xd0u]]\xd7\xb3\xd9,\xefj\xf6Xp]W\ +\xd3\xb4l6\xab\xeb:\x8f\x13\xe2\xbfB\xa8f?5\ +5\xf5\xc5&\xa2gq\x1cgjj\x8aS\xd5}.\ +Q\x08\x8b\xfc\xbe\xf0Df\x10Ji\x22\x91H\xa7\xd3\ +\x08\xa2\x10\x1a\x0dD\x9f\x10\x10$\xa6i\xf2\xe8\x5c\xfc\ +\x8f\xc2P(\xf4\xa5M\xa7]\x04\x98r\x83\xa5\xe4\xfe\ +\xe2\x7f\x14\xea\xba\x1e\x8f\xc7E.z\x0a\xc6X\x22\x91\ +\xe0\x91\xd1\xf8\x1f\x85\xb2,#\xfa\xc0\xa3\xc0\x80\x8b\x9b\ +\xc7\x1dD\xff\x15BI\x09\xa1\xf0\x14\x98\x14\xaa\xaa*\ +&e>\x0a\xa75\xfe\x5cfg\x84\xc2\x8f\xc2\xe9\xae\ +\x93\xff\x0a\x1d\xc7\x11#\xc2\xb3@}*\x1e\x89\xba\xff\ +\x0am\xdb\xeet:\xa3\xb0^d\xa4\x90$\xa9\xd3\xe9\ + P(I\x92eY\xadVK(<\x85\xa2(\xcd\ +f\x93G\xc9o\xffOt\xaf\xd7\xdb\xdb\xdb\x1b\xcb\x0a\ +/\x97AQ\x94\xbd\xbd=\x1e\xeb[\xfd\x8fB\xc6\xd8\ +\xf6\xf6v\xb7\xdb\x1d\xfa\xaa\xad\xd1AQ\x94n\xb7\xbb\ +\xb3\xb3\x03\xeb\x81\xfc\xdd8\x97q\xe1\xee\xee.<\x08\ ++RSrR\xc4\xef\xd9\xb3g\xbb\xbb\xbb<.k\ +.\xcd\x1dcluu\xd54\xcdl6\xcb\xf5#\xc8\ +\xfe\xb7X\x0c\xfc\xea\x9cT\xfe\x82u2>\x1bY\x96\ +\xe1\x9a~\xf4\xe8\x11c\x8cG\x8a\xc0E!T\x0a\xfd\ +\xed\xb7\xdf\x96\x97\x97gggC\xa1\x10T:\xf8\xd4\ +3\xe5\xad\xbb\x94>\x84\x9c\x8c\xb1\xa0\xf4\x05,o\xf3\ +\x0a\xd3x\x0b\xac\x07\xcb\x02\x9d\xda\x0eT\xb0\x80\xba\x0c\ +Pm\xcf\x1b\xb4\xb9\x1fB>\x5c\xb1}\xf1#\x87\x81\ +\xfc\xf1\xf1\xf1\xd6\xd6V\xb5Z\xed\xf5z\x9cR<^\ +I\x87$I\xef\xdf\xbf\xff\xf5\xd7_\xaf^\xbdZ,\ +\x16S\xa9\x14\xdc\x81:u\x96\xbd?&\x1f\xd6q\x82\ +\xd7\x94\xd2~\xbf\xef8\x8em\xdbP\xc7\xd0{\x0d\xdf\ +Z'\xc0`\xd4\xb6m\xcf(9)\x80H\x08\xf1J\ +\x22z\xce\xa0N\xa2\xaa\xaa\xfa\x09P\ +'\x8c\xf7\x0e\xc8@\x99PB\x08\x9c\xa3\x8b\xff}\x90\ +x>\xce\x09\x1ah\xa8\xcf\xdfN\xc0\xc5\xa2\x83\x1e\x80\ +c\x1ff\x8c\xe0\xf1\x8bi0\xf4\x08\x85\xe8\x11\x0a\xd1\ +#\x14\xa2G(D\x8fP\x88\x1e\xa1\x10=B!z\ +\x84B\xf4\x08\x85\xe8\x11\x0a\xd1#\x14\xa2G(D\x8f\ +P\x88\x1e\xa1\x10=B!z\x84B\xf4\x08\x85\xe8\x11\ +\x0a\xd1#\x14\xa2G(D\x8fP\x88\x1e\xa1\x10=B\ +!z\x84B\xf4\x08\x85\xe8\x11\x0a\xd1#\x14\xa2G(\ +D\xcf\xbf\x1a\x12\xcd\xa9\xe9\x89y\x84\x00\x00\x00\x00I\ +END\xaeB`\x82\ +\x00\x00\x1d\x1b\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x96\x00\x00\x00\x96\x08\x06\x00\x00\x00<\x01q\xe2\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\ +\x01\xc7o\xa8d\x00\x00\x00\x19tEXtSof\ +tware\x00www.inksca\ +pe.org\x9b\xee<\x1a\x00\x00\x1c\xa8ID\ +ATx\x9c\xed\x9dyp\x1c\xd9}\xdf?\xaf\x8f9\ +{\x0e`\x00\x0c.\xe2\xe2\xb5$\x01r\xb5+)q\ +j\xe5\xc8\xb6\xcaRR\xaa8\xdel|\xc8\x8alm\ +\xd9\xa58.)\xd9\x92r\x94\xffPT.\x97\xecT\ +l\xa5d\xcb\x96\xcb[\x92#\xdb\x91\xb3VJ\xd1e\ +)\x96,\xadv\xb5Q\xedn\xe4%\x97\xd7\xf2X\x12\ +$\x01\xe2\x9c\x01\xe6\xbe\xbb;\x7f\x0cq\x0cf\x00\x0c\ +\x80\xee\x99!\xd9\x9f*V\x11\x83F\xf7\xeb\x9eo\xbf\ +\xf7{\xbf\xdf\xef\xfd\x9e\x98{\xdfi\x13\x07\x07\x8b\x91\ +\xda\xdd\x00\x87\x07\x13GX\x0e\xb6\xe0\x08\xcb\xc1\x16\x1c\ +a9\xd8\x82#,\x07[p\x84\xe5`\x0b\x8e\xb0\x1c\ +l\xc1\x11\x96\x83-8\xc2r\xb0\x05GX\x0e\xb6\xe0\ +\x08\xcb\xc1\x16\x1ca9\xd8\x82#,\x07[p\x84\xe5\ +`\x0b\x8e\xb0\x1cl\xc1\x11\x96\x83-8\xc2r\xb0\x05\ +GX\x0e\xb6\xa0\xb4\xbb\x01\xbbq\xab \xf8\xd4\x9cD\ +\xd1\x14\xbc3h\xf0\xcf\x22\x06\xfe\x87\xecu\xc8\x1a\xf0\ +\xd5\x15\x89\x17\x92\x12na\xf2\xd1!\x9dQw\xbb[\ +\xb53\xa2\x93s\xdeo\x15\x04\xff\xfe\xb6LF\xdf\xf8\ +, \x9b<\xd5c\xf2d\xb7\x81\x22\xda\xd7\xb6VP\ +6\xe1\xcbq\x89\xff\x15\x97\xea\x9e\xc1\xef\x8d\xe9\x8ct\ +\xb0\xb8:VX\x19\x1d>2-3_j\xac\x9eA\ +\x17|d@\xe7\x8c\xbf#\x9b\x7f`.\xe7\x04\x9f\x9e\ +\x97\xb9Sl\xfc\xfbA\x17\xfc\xc1x\x05\xbf\xdc\xdav\ +5K\xc7\x0e*\x7f8\xbf\xbd\xa8\x00\xe6J\xf0\x9bw\ +d\xfeh^\xa2\xf4\x00i\xabd\xc2g\xe6e>v\ +k{QA\xf5\xfe?\xb3\xd0\xb1__g\x0a\xeb\xe5\ +\xb4\xe0\xc5\xd4\xee\xe3\x9ca\xc27V%>|S\xd9\ +\xf1K\xb8_\x98+\xc1\xbf\xbb)\xf37\xab\x82f\xde\ +\x95\xef'%\xfeo\x13\xcf\xa9\x1dt\x9c\xb0r\x06\xfc\ +\xe1\xdc\xde\x9au\xa7\x08\xcfL+\xfc \xd5q\xb7\xd3\ +4/\xa6\x04\x1f\x9e\x96\x99.\xeeM(\x7f\xbc \x93\ +\xd3;O\x5c\x1d\xf7M\xfcuLbe\x1f\x0f*g\ +\xc0'g%\xfeb\xa9\xe3niW\xfe|Y\xe2w\ +f\xf7'\x90\x95\x0a|)\xee\x08kGbe\xf8\xca\ +\xca\xc1\x9a\xf4\xc5\x98\xc4\xa7\xe6$\xf4\xdd\x0fm;\x06\ +U[\xf2\xaf\x96\x0fv\xcf_\x8eK,\x97;K\x5c\ +\x1d%\xac\xcf-I\x14\x8d\x83\x9f\xe7;\x09\x89\xdf\x9e\ +\x91)\x99\x9d\xf5\xb07S6\xe1wg%\xbe\xb9z\ +\xf06\x96L\xf8B\x87\xf5\xd4\x1d\xd3\x9akyx!\ +\xd9\xb89\x8a\xa2 \xc4\xde\xbe\x80\x97\xd3\x82O\xdc\x11\ +\x94;p\xc6X2\xe1\xe3w\xe4=\xdb\x84B\x08\x14\ +\xa5\xb1O\xfb\xf9\x94\xe0z\xa1s^\xa4\x8e\x11\xd6\xb3\ +Kr\xc3\x99P0\x18\xa4\xbf\x7f\x80\xc1\xa1a\xc2\xe1\ +.d\xb9y\xc7\xcd\xd9\xac\xc4'g\xe5\x8e\x1a\x16+\ +&|rV\xe6\x5c\xb6y\x11\xc8\xb2LW\xb8\x8b\xc1\ +\xa1a\xfa\xfb\x07\x08\x04\x83u\xc7\x18&<\xdbA\xee\ +\x87\x8eh\xc9\xcbi\xc1\xc5\x06\x0fZ\xf3k\x04\x83!\ +\x00\x04\xa0i\x1a\xfd\xfd\x03h\x81\xc0\x9e\xce\xfdG\xf3\ +\x1dq\x9b\x00\xfc\xc1\xbc\xc4+\xe9\xe6E\x15\x08T_\ +,\xbf\xa6\xb1\xf6W\xa1`\x08\xbf\xdf_w\xec\x85\x9c\ +\xd8\xd3\xb9\xed\xa4#\x9e\xf8\x17\x1b\x18\xaf\xaa\xea\x22\x14\ +\x0e\xd7}.\x84 \x1c\x0a\x13\xed\xebGU\xd5\xa6\xce\ +\xff\xadU\x89\xaf\x1epR`\x05_\x8e\x0b\xbe\x93h\ +\xae\x1d\xaa\xea\x22\x1a\x8d\x12\x0a\x85\x1a\x9a\x01\xe1pW\ +\xc3\xfb\xff\xcb\x98\xd4\x94\x0f\xccn\xda\xfe\xb4\xff>\xd3\ +\xd86\xe8\xea\xee\xda\xd1\xaeR]*}\xd1~\x02\x9a\ +\xd6\xd4u\x9e]\x90\xb8\x9ck\xdf\xdb|!'\xf8\xdc\ +bs\xc3\xb8\xdf\xe7\xa7\xaf\xaf\x0fUum{\x8c\x10\ +\x82\xee\xeen\xa0\xf6\x9e\xde\xcc\x0b\xcee\xdb\xfe\xb5\xb6\ +_X\xcf\xc5\xea\x9b\xa0\x05\x02\xb8vx\xa8k\x08 \ +\x14\xee\xa2\xbb\xab{W\xe3^\x07~\xf7\xaeD\xba\x0d\ +\xce\xc4\xac\x0e\xbfwWf\xb7\x09\xaf\x00\xba\xba\xbb\xe9\ +\xea\xde\xfd~\xa0\xda\xab\x05\xb4\xfa!\xf1\x7f\xc6\xda?\ +\x1c\xb6UX\x97s\x82\x0b[z\x11I\x92\x08\x04\xea\ +\x8d\xd3\x9d\xf0\xf9\xfd\xf4\xf4\xf4 \xc4\xce\xb7\xb3\x5c\x16\ +\xfc\xe9b\xeb\x1f\xfa\x1f/\xc8,\x95w>F\x92$\ +zz\xfa\xf0\xfb\xea\x85\xb2\x13\x81`\x08I\xaa\xbd\xef\ +\xf3Y\xc1\x1b\xf9\xf6\x8a\xab\xad\xc2j\xf4f\x05\x82!\ +di\xef\xcdr\xbb=\xf4\xf5\xf5\xed:k\xfcnB\ +\xe2\xf5=\xcc\xc8\x0e\xca\x85\x9c\xe0\xf9\xe4\xce\xd7\x93%\ +\x89\xde\x9e>\xdc\x9e\xbd\xe7\xc1l\xf7\x226\x1a\x09Z\ +I\xdb\xae~\xb3\x00?\xca\xd4^^Q\x14\xb4\x06\xb3\ +\x9dfQU\x95\xde\xde>\xa4\x1d\xc4e\x02\x7f\xb2(\ +a\xb4\xc0\xc25\xa8f*\xect)Y\x92\xe8\x8dF\ +Q]\xcdMD\x1a\xa1i\x1a\x8a\x5c\xeb\xdfz5-\ +\xb8Y\xd8\xf7)\x0fL\xdb\x84\xf5\x5c\xac\xfe\x81\x87B\ +\xe1=;B\xb7\xa2(\x0a===u\xc3\xc3fn\ +\x15\x04?h\xc1\xb4\xfc\xfbI\xb1c\xd6\x85\x10\x82H\ +Oo\x9d(\xf6\x8a\x10\x82P8T\xf3\x99\x09<\x17\ +o_\xb2V[R\x93\xe7J\xf0\xd2\x96t\x0f\x97\xcb\ +\x85\xd7\xeb\xb5\xe4\xfc.\xd5EwW7\xb1xl\xdb\ +c\xbe\xb8,\xf3\xe3\xc1\xca\xfa\x9c*\x87\xc4\x8d\x8a\x87\ +\xdbe\x85\xf9\x8aL\xd1\x84\x82!(\x18P\xa6j\x80\ +\x03\xf8eP\x01\x8f\x04\x1e\xc9\xc4#\xa0_\xd5\x19U\ +*\x1cV\x0a\xf8\xee\x99\xe8\x86\x09\x7f\xb5\xcbp\x14\x89\ +\xf4\xe0r\xed>Ii\x06\xaf\xd7\x87KMS*\x97\ +\xd6?{))\x98\xeb\xad&\x05\xb6\x9a\xb6\x08\xebk\ ++R\xdd\x0ci\xaf\x06\xfbnx\xbc^B\xe1.\x92\ +\x89\xd5\x9a\xcf\x85$\xe1\xf5zI*\x0a\xfff\xc1$\ +U\xaa\x90-\x96)\x96\xcb@\xe9\xde\xbf\xfd\x22\xe1R\ +\xdd\x04\x5c*\x9a[!\xed\x11\xf8\x942\xf9|\x01\xd3\ +\xa8\xbd\xe3\xaep\x17\x1e\x8f\xe7\x00\xd7\xaa'\x10\x0c\x10\ +\x8f\xc7\xd7\x7f6\x80\xaf\xafJ|(jA\x00v\x8f\ +\xb4\x5cXE\x03\xbe\x9b\xdcj[\xa9\x96?d\x80\x80\ +\xa6Q)\x95\x90\x15\x09\x90(\x97\xcb\x14\x0ayr\xd9\ +,\x00I\xcb\xaf\x08\xa5r\x99x\xb9L<\xbb\xf1\x99\ +\x10\x02\xaf\xd7\x8bKU1\x00C\xd7\xf17\xe9\x7f\xdb\ +\x0b^\xaf\x0fUMQ.oLA\xbf\x93\x90\xf8\xe5\ +^\x03O\x8b\x8d\x9e\x96\x0b\xeb\xf9T\xed\xc2\x00\x80`\ +0p`\xdbj3&&\x95r\x99\x5c>O\xbe\x90\ +\xc70Z\xff\xc6\xd6\xb4\xc74\xc9\xe7\xf3\xe4\xf3y\x00\ +$!\x90e\x05\x9f\xcf\x87\xa2*X\xe9*\xd7\x02\x01\ +VWV\xd6\x7f\xce\xea\xf0BJ\xf0\xeepk\xfd\xf1\ +-\x17\xd67Vj\x05\xa4(\x0a\xbe=\xfan\x1a\x22\ +\x04\x86n\x90N\xa7H\xa7S\x07?\x9f\x8d\x18\xa6I\ +*\x95$\x95\xaa\xf6\x99~\x9f\x9f@0\x84\xa2\x1c\xdc\ +\xd8\xf6\xfb\xfc\xa4S)*\x95\xca\xfag\x7f\xb3\x22\xf1\ +\xeepkC\xf1-\x15\xd6\x8d\x82\xe0\xc6\x96\xf0\xcd^\ +\x02\xca\x8d0\x0d\x93|!G2\x99D\xd7;)\x8f\ +\xa1y\xb2\xb9,\xd9\x5c\x16Y\x96\x09\x85\xc3\xf8\xbc~\ +\x0e\xd2\x8d\x05\xb4\x00\xab\x9bl\xcb\xeb\x05\xc1tQ0\ +\xeen]\xaf\xd5Ra}\x7f\x8b\xa3P\x96$\xfc\xfe\ +\xfd\xd9\x1a\x86a\x92\xcd\xa6I&\xed\xb0\x94\xda\x83\xae\ +\xeb\xac\xc4\xe3\xac\x10G\xd34\x02\x81\xe0\x9e\xd2\x84\xd6\ +\xf0i\x1a\xa9T\x12}\x93\x09\xf0\xfd\x84`<\xda:\ +a\xb5\xcc\xa43\x81\x17\xb7$\xb6mN\x05i\xfa<\ +&$SI\xe6\xe6f\x1f(Qm%\x93\xc90?\ +?\xc7jbu\xcf=\xb1\x80\xba\x17\xf6\xf9Ts+\ +\x7f\xac\xa2e=\xd6\xa5\xac\xa8\x8b\x975\xca)\xda\x0e\ +\xd3\x84Dr\x95l&cq\xcb:\x9bl&C6\ +\x93\xc1\xafit\x85\xc3l\xcdf\xd8\x0e\xbf\xe6'\xb5\ +\xc9\xd6\x5c.\x0b\xde\xc8\x09N\xfaZ#\xaf\x96\xf5X\ +/n\xf1t{\xbd^\xe4&=\xce\xf9|\x9e\xbbw\ +g\x1e:Qm&\x9b\xc9p\xf7\xee]r\xf7f\x96\ +\xbb!\xcbJ\x9d\xc3y\xbb\xd4o;h\xd9\x95^\xde\ +\x22\xacf\xfc8\xba^aqq\x81\xf8\x0e\x1e\xf4\x87\ +\x09\xd34Y\x89\xc7XZ\x5chjx\xdc:\x1c\xbe\ +\xda\xc2\xe0{K\x845]\x105\xcb\x93$Y\xc6\xe3\ +\xde\xde!*\x04d\xb2\x19\xe6\xe7\xe7k\x9c}\x0eU\ +J\xe52\xf3\xf3s\xa43\xe9\x1d\x8f\xf3x\xdc51\ +\xd3\x85\x12\xdcn\xd1\x8a\xf1\x96\x08\xeb\x95L\xfd0\xb8\ +\x1d\xa6i\xb2\xbc\xb4Lbuu\xdbc\x1c\xaa$\x13\ +\x09\x96\x96\x161\xcd\xed\x1c\xc0\x02\x9f\xd7W\xf3\xc9\xab\ +\xe9\xd6\x0cR-\xb9\xca\xab[\x87Aoc\xa3\xbdT\ +.37w\x97B\xb1\x8d\xf9\x1e\xf7\x19\xa5R\x89\xb9\ +\xb9yJ\xa5\xc61N\xafo\x8b\xb0Z4\x1c\xda.\ +\xac\x9c.\xb8\xb6)\x9bQ\x96\xa5\xba\xdc#!\x04\xb9\ +\x5c\x96\xa5\xc5\x05L\xb3\x13\x96\x02\xdc_\x98\xa6\xc1\xd2\ +\xd2\x22\xd9l\x96\xadN\x05\x97\xcb\x85$m\xf8\xc2\xde\ +\xc8\x8a\x96\xd4z\xb0]X\x97\xf2\xa2f]\x9f\xc7\xe3\ +\xad\x8d\x0b\x0aA2\x99deS|\xcba\x7f\xac\xae\ +\xae\x90H\xa607\xad\x00\x17B\xe0\xdd\x14\xe0\xd7\x81\ +7\x9a\x9bX\x1e\x08\xdb\x85u>[\xfb\xb3\xc7\xb3\xd9\ +\xbe\x12\xac\xae\xae\xae\xc7\xcc\x1c\x0eN:\x9db5\xb1\ +R\xd3sm\xcd\x1c\xd9\xba\xce\xc0\x0elw\x90\x9e\xcf\ +m\xd6\xae\xc0}o6h\x22\x88\xc7\x97(\xe4\x1d{\ +\xcajr\xd9\x0c\xa6^\xa1\xa7\xa7\x07\x13\x81{\x8b\xb0\ +Z\x91\xf3ok\x8fU0\xe0\xc6\xa6n\xb7:\xde\x0b\ +\xaa=U\xcc\x11\x95\x8d\xe4\x0b\x05\xe2+\xab\x80@\x92\ +\xa4\x9aL\xd57\x0b\xc2\xf6*\x88\xb6\x0a\xebz\xa1\xd6\ +\xber\xbb]\xf7b}\x09r\xd9\x9c\x9d\x97v\x00r\ +\xb9,\xc9d\xd5m\xe3ro\xac\x00\xaa\x98\xd5\x85\xad\ +vb\xab\xb0\xaemi\xbc\xcb\xed&\x9b\xcd\x90Nu\ +v\xbe\xd4\x83D:\x9d&\x93\xc9\xe0v\xd5.-\xdb\ +\xfa\xddX\x8d\xad\xc2\xba\xbae\xf6!I\x12\x89\x84\xe3\ +\xf8l5\x89\xc4j\xdd\x92\xb8\xab6[!\xb6\x0a\xeb\ +\xcdMI}Z Hly\xd9\xce\xcb9\xec@l\ +y\x09M\xdbH\xaa\xbc\x9e\xb7\xd7!`\xdb\xd9\x0b\x06\ +,\xde\x8b\x0f*\x8aB\xa9Tt\x9c\x9fm\xc44M\ +J\xa5\xe2zF\xc9|\x09K\xaa'n\x87m\xc2\xba\ +U\x14\xeb\xab\x8d\xbd^/\xa5bk\xebeK\x12h\ +\xde\xceHUv+\x06n\xb5\xbd\x0b:\xa0\x1a\xfe\xf1\ +\xdd\x0b\xf1\x18\xc0\x9d\x1d\xea\xe8\x1f\x14\xdb\xfcXkQ\ +t-\x10 \x9d\xde9\x0ao%OL%\xf9\xc0O\ +/\xf1\xd8\xb1\x0c\x8al\x92-\xc8\xbcp.\xc4\xb3\xdf\ +\xe8gz\xc1\xfa%f\xdb\xe1RM\xde\xff\xaeE~\ +\xe6\x898\xa3\xd1\xea\xc3\xb8\x1bs\xf1\xf5\x1fF\xf8\xc2\ +\xdfF\xc9\x17\xdb\xb3\x08=\x9dN\xa1\x0542\xe9\x0c\ +\xb7\x0b\x82\xa3\x1e{F\x11\xdb\xb6<\xf9\xdc\x92\xc4\x97\ +W\x14TU\xa5\xd8\x82\xdeJ\x92\xe0?\xbdo\x86\x9f\ +{gc;\xaeT\x16|\xe2\x0b\xa3|\xf3\xe5n\xdb\ +\xdb\xd2\x1b.\xf3\xd9g\xde\xe4\xc8P\xe3\xd8\xc9\xcc\x92\ +\x9b_\xffoG\x98]n\xcff8n\xb7\x9br\xa9\ +\xc4S\xdd:\x1f\xb4i1\xabm\xaf\xcdRY\x10\x08\ +\x04Z\x22*\x80\xdf\xf8\xe7s\xdb\x8a\x0a\xaa=\xc8o\ +?}\x8b\x7f4i\xaf\xab\xc3\xad\x1a;\x8a\x0a\xe0P\ +_\x91?\xfd\xe8\xf5\xb6\x0d\xd5\xc5b\x91@0\xc8R\ +e\xf7c\xf7\x8bm\xc2Z0\xdddZ\x94J\xfc\xc8\ +H\x8e\x0f\xbega\xfd\xe7RE\xe6\xdbgG\xf9\x8b\ +\xef\x9e\xe0\xd5\xab\xfd\xeb\x9fK\x12\xfc\xe7_\xbe\x8d[\ +\xb1\xcf\xde\xf9\xb5\xf7.\xd4\x88ja\xd5\xcf\x97^:\ +\xcas?8\xc6ll#\xa3s\xb0\xa7\xc4G\x9e\x9c\ +\xb3\xad\x1d\xbb\x91\xc9d\x987\xed\xeb1m\xb3\xb1\x96\ +\x85\x17]oMp\xf9\x03?\xbd\xc4Z\xa2\xe4j\xc6\ +\xcd'\xfe\xf2\xc7\xb8\xb1\xb0Q}\xe5'O\xcf\xf0\xcc\ +\xcf\x9eE\x08\x93hW\x99\x7f\xf2\x0fW\xf9\xcaK\x11\ +\xcb\xdb\xe1u\x1b\xfc\xfcOl\xf4\x9a?z3\xca\x7f\ +\xf9\xeb\xb7\x92/U\x1f\xf3s/\x1c\xe7\x99\x9f}\x8d\ +w\x9c\xba\x0b\xc0\xcf\xbc#\xceg\xbf6\xc0j\xba\xf5\ +%4t]gY\xf8\x01{R\x1dl\xe9\xb1\xe2\xba\ +L\xaaE\xbd\x95$L\x9e\x98\xda\x10\xf0\xe7\xbe=Y\ +#*\x80\xef\x9d?\xc4w\xcf\x1dZ\xff\xf9\x9d\x8f&\ +li\xcb\xe3\xc7\xd2\x04|\xd5\xe1-WT\xf8\xf4W\ +\xde\xb2.*\x80RE\xe2\xd3_}\x94\x95tu\x12\ +\xe1V\x0c~\xecT\xfb\xa2\x10\xc9L\x96\x98aO\xa9\ +#[\x84\xf5l:\xd4\xb2U\xc9\xc3}%\x82\xfe\xea\ +\xb5J\x15\x89\x17/\x0c5<\xee\xdbgG\xd6\xff\x7f\ +b\xd4\x9e8\xe5##\x1bo\xff+W\xfaY\xcd\xd4\ +\x0f5\x85\x92\xc2K\x97\x077\xda2\xd2\xbe\x98\xa9\xae\ +\xeb|>\x1d\xda\xfd\xc0}`\xb9\xb0\xca\xa6\xe0\xff\xc5\ +[\xe7\xb3\x0a\xfb7,\xd0\xb9\xb8\x86\xb1\xcd6'\xb3\ +\xb1\x0d\xafs8`\x8f\xe8\xc3\xdaF[\xee\xael\xbf\ +\x0ai\xb3\xad\x15\x0e\xd8hA7\xc1+\xf1\x22\x95=\ +/\x1b\xde\x1d\xcb\x85\xf5\xb7\xc5\x00\xb9\x16:Cs\x9b\ +\xfcAam\xfb\xebvi\x1b\xc1\xb1\x9cM\xe1\x8c\x5c\ +qcX\x09\xfbwj\xcb\xc6\xefr\xf9\xf6n\x91\x9a\ ++\x14\xf9\xbb\xc2\xc1\xeag4\xc2\xf2'\xfcb\xa6\xb5\ +\x86\xe8|\xdc\x85nT\xdf\xb8\xb0\xbf\xc8X\xb4\xb1\xcd\ +rfbcm\xe2\x8cM\xfe\xa3\xd9\xe5\x8d\x9c\xa7\xd3\ +\xe31$\xd1\xd8Exfb\xc3\xc0\x9f\x8d\xb5\x7fc\ +\xe7\x172\xd6\x8b\xdbRa\x19\xc0\xf5dk\x93\xf7\xb2\ +\x05\x99\x8b\xd3\x1b+Q~\xed=\x17\xea\xbe\xd0.\xad\ +\xc8/\xfc\xf8\xd5\xf5\x9f_\xb9l\xfd\x1b\x0a\xf0\xea\x1b\ +\x01\xd6\xc2\xa1#\xbdi\xfe\xe9\xdbn\xd5\x1d\xf3\x8f'\ +g9yh#\xbf\xffe\x9b\xda\xb2\x17\xae$K\xbb\ +\xd6\xa0\xdf+\xf2G\xa7\xa2\x9f\xb0\xead?,i|\ +o\xb9\xf5{\xe8\x96u\x89\x9fz\xac:\xd3\xeb\xef\xca\ +qrd\x85\xe5\xa4\x17\x01;\xbe\xe3\x17n\x15\x7f\xf7Z\ +\x98_\xfd\xafG\xb9>[_J\xe0\xf6\xa2\x9b_\xff\ +\xd4\x11\xbej\x83\xe7\xff \xc4\xf3\xd6~w\x96e7\ +\xc4\x0c\x95\x7fu\xa53\x12\xf9\xfa\xba\xca<~4C\ +H\xab\xb0\x10w\xf1\xea\xd5\x00\xb9\xc2\xde\xde!UU\ +\x91e\x05E\x96A\x12\xc8\xf7V\x13\xeb\x86\x0e\x86I\ +E\xd7\xd1\xf5\xca\xaeEK&\xc7\xb3\x1c\x1d* $\ +\x93\x9bs\x1e^\xbf\xa1\xd1\xa9\xf9\x8e\xff\xe3\x04t\x0b\ +k\xfcj\x96\xd9Xg\xcb\x1e\xec\x8a;\xed\x95\xa5U\ +\x95o\xbd\xda\xb5\xebqk\x85u}~?~\x9f\x0f\ +\x8f\xd7\x87\xcb\xe5\xba\xb7L\xad9!\x1a\xa6I\xa9X\ +\xa4T*R\xc8\xe7\xc9\xe6r\xe4\xb2Yr\xb9,\x95\ +J\x85\x8b\xd3\xfe\x8e\x1a\xf2v\xe2l\xc9\xcbO\xb9\xad\ +\xc9\x9d\xb3LXw\xcam\xd9\x8b`O(\x8aB \ +\x18\x22\x14\x0a\x13\x0a\x85\xd6\xb3)\x0f\x82$\x04\x1e\x8f\ +\x07\x8f\xc7\xb3\xbe\x1b\xec\x1a\xb9l\x8ed*A*\x91\ +$\x99Jt|\xf1\xdd\xdb\x15\x19,r\xabY\xa6\x86\ +t\x87>3EQ\xe8\xea\xea&\x12\xe9!\xdc\x15\xde\ +u\xeb9+\xf1\xf9}\xf8\xfc>\x06\x06\xaa\xb1\xc1t\ +*E<\xbeL,\x16\xeb\xc8\xba_\x09\xdd:\x17\x8c\ +e\xc2\xca\x1a\xed\xdf|q3\xe1p\x98\xfe\xfe\x01\xc2\ +Ml\x92\xd9*\x02\xc1 \x81`\x90\xd1\xb1\x09VW\ +VXX\x98'\x99\xb4'\xd3b?d,\xfc\x0e-\ +\x14\x96Ug\xda?\x92$\x11\x8d\xf6\x13\xed\x1f\xb0l\ +\xc3';\x10B\xd0\x1d\x89\xd0\x1d\x89\x90\xcf\xe7Y\x98\ +\x9fgii\xa1\xed;h\xe4u\xebf\x15\x96\x09\xab\ +\xd0\xc6\xa1P\x92$\xa2\xfd\x03\x0c\x0d\x0e7\xbd\xef_\ +\xa9T$\x9b\xc9bl[\x0d\xef\x80m\x12\x12>\xbf\ +\x1f\xb7{g\xa3\xc5\xeb\xf52>1\xc1\xd0\xa1C\xcc\ +\xdd\x9daq\xa1}\x02+v\xa2\xb0\xe46\x8c6B\ +\x08\xfa\xfa\xfa\x18\x1e\x19\xc3\xd5\xe4\x8e\xf6\x00\xb7oM\ +3??\xd7\x92u\x8e\x83C\xc3\x8c\x8e\x8e\xedz\x9c\ +KU\x19\x1b\x9b`pp\x98\x99\x99\xdb,-.\xda\ +\xde\xb6\xadX\xf9\x1dZ&,\xaf\xd4Z\xe7\x8c\xdf\xef\ +gb\xe20\xda\x1e\xb7\xa3\x8b\xc7c\xcc\xcd\xdd\xb5\xa9\ +U\xf5\xcc\xdd\x9d%\xa0\x05\xe8\x8e4\xe7\x10u\xb9\x5c\ +\x1c>|\x94h\xff\x00\xd37o\x90i\xe1\xd29\xb7\ +\x85\xf3\x1a\xcbN\xe5\xd9&E\xc4j$!\x18\x1b\x9b\ +`\xea\xf4\xa3{\x16\x15P\xb33V\xabXY\x89\xef\ +~\xd0\x164\xbf\xc6\xd4\xd4\x19\xc6\xc6\xc6\x91Z4\xf9\ +\xf0Z(,\xcbz\xacp\x0b\xc6B\x9f\xcf\xc7\xd1\xa3\ +\xc7\xf1\x1d`\xdf\xe8V\xba\x1b\xd6\xaf\xb9\x8f\xcd\xd3\xd7\ +\x18\x18\x1c\x22\xdc\xd5\xc5\xf5kW\xc9f\xad\x0b\x127\ +\x22l\xa1+\xd2\xb2\xa7l\xf7\xf6\xb0\x03\x03\x83L\x9e\ +>C\xa9\x5c\x22\x9dJ\x93\xcf\xefo\x1f\xc2\xde\xbe\xde\ +\x96\xba\x1f\x84\x10\xf4\xf5\xf6\xed\xf9\xef\x0c\xc3 \x9f\xcf\ +\x93N\xa5)\x16\x8b\x9c\x9cq\x18\x9f_c\ +\xfa\xe6\x8d\x1dj\xbb\xef\x9f\xe3\xb2u)O\x96\x09\xeb\ +\x98\x5c@\x12.K\xa7\xef\xaa\xaar\xfc\x91\x13\xeb\xfb\ +EGzz\xa8\xe8:\xa5R\x89r\xb9D\xb1X\x8d\ +\xcf%\x13\x09\x92\x89\x04\xcc\xce \xcb2\xdd\x91\x08\xbd\ +\xbdQB\xa1\xc6+P\x06\x06\xabyPv\x8bkd\ +tl\xfdZ\x8dH&\x93,//\xb2\x12\x8f\xd7\x84\ +{\x14E!\xa0\x05py<\xa8\xaa\x8a\xcb\xe5\x22\xd2\ +\xd3\x03@4\x1a\xc5\xeb\xf5r\xf5\xca\x1bT*\xd6y\ +\xef%I\xe2\x88b]\x92\xa6e\xc2r\x09\xe8\xf2\xbb\ +\x89g\xac\xe9\xb9\x5c\xaa\xca\x89SS5\xf1\xc6'\x0e\xd7\xf8\xca\x96\x97\x17y\xf3\xfau\ +dY\xe6\xd8\xb1G\xd6}O\xbbQ(\xe4)\x16\x8b\ +T*\x15\x0c\xdd\xc00\x0ddYF\x96d\xdc\x1e7\ +\x1e\x8f\xb7\xe9\x97u|\xe2pu\x83\xf2\x5csby\ +\xa4[\xa3W\xb2>~jK\xa2\xfa\xcf\x05\x0b\xfcV\ +\x13\xdb8K\x92\xc4\xd1\xa3\xc7v\xb4\x0d\x8a\xc5\x02\xa9\ +T\x92L:M:\x9d!\x97\xcb\xee\x9a\xee\x22I\x12\ +^\x9f\x0f\xbf\xdfO(\x18&\x14\x0e\xa1\xaa\xf51\xa7\ +HO/>\xbf\xc6\xdc\xdc,~_mu\x98P(\ +\xcc\xd8\xf8\x04W\xdf\xb8\x84\xb1\xe9z\xc1`\x90\xe1\xe1\ +\x11B\xe1p\xdd\xf9|~\x8d\xbeh\x94\xc1\xc1\xe1m\ +g|\xe5r\x89D\x22A*\x95$\x9b\xcd\x92\xcf\xe5\ +v\x0dM\x09!\xf0\xf9\xfch\x81\x00\x81\x80F0\x18\ +Z\xdf\xec\xaa\xd1\xbd\x1f>v\x8c\x0b\xaf\x9fk*-\ +\xe8\xe7C6EL\xec*n\xfb+\xb3!\x16S;\ +\xbf5\xc3\x87F8thd\xdb\xdf\x17\x0ay\xce\x9d\ +=\xbb\x1e\xbe\x90\xee=\xe0\xb5\x04:EUQ\x14\x05\ +]\xd71M(\x97\x8a\x14\x8bE\xf2\xf9\x1c\xd9l\xae\ +&\xec\xe1\xf5\xfa\x08wu\x11\x89D\xd6=\xf9;\x91\ +H$\xb8z\xe5r\xc3/}dd\x94\xa1\xe1C\x0d\ +\xfe\xaa\x1e\xd34\xc9\xa43\xc4Wb$VWkz\ +@I\xaa&\x03z=>\xdcn\x17\xaa\xcb\x8d\x10\xd5\ +\xd9q\xa5R\xa1R.S,\x16\xd7W\xfd\xac\x09\x5c\ +\x08\x89G\xdf\xf2X\xddvq\x9b\x99\x99\xb9\xcd\xec\xcc\ +\xcc\x8em\x1b\x08\xfa\xf9\xfc\xb0=U\x17m[Z\xf3\ +\xfe>\xf8\xfd\x1dFC\xaf\xd7\xbb\xabA\xebr\xb9\x19\ +\x18\x1c@UT\x02\xa1\x10\x9a_k\xda\x91h\x18\x06\ +\xb9l\x96T*E\x22\xb1B*\x95f~\xee.\xf3\ +swq\xb9\xddD\xba#D\x22\xbd\x04\x82\xf5\x96k\ +\x22\x91X\xef\xa9dY\xe6\x91\x13'q\xbb\xdd\xbcq\ +\xf9\x12\xf9|\x9e;wn#\x84\xc4\xe0\xd0\xf6\xe1\x9a\ +t*M<\xbeL|%\xbe^\xe3^\x08\x89P(\ +D8\xdcM0\x18\xc4\xaf\xf9\x9b\xce\xb60M\x93l\ +&M*\x95\xa2\x5c)\xd7\xec\xe6\xd5\x88\xa1\xa1C\xac\ +\xc4W\xc8\xed0$\xfeb\xaf}\xa9N\xb6\xf5X\x00\ +O\xcf\x86\x98\xdf\xa6\xd7:yj\x92P\xa8~8\xb1\ +\x0b]\xd7I&\x12\xc4\xe31VWW\xd6]\x0d\xa3\ +c\xe3\x0cn\x8a\xe7m\xee\xa9dY\xe6\xe4\xc9I\xb4\ +@U|\xe5r\x99\xcb\x97.\xae\x7fY\x87FF\x19\ +n\xd0s\xcd\xcd\xdd\xe5\xf6=\x9f\x98,\xcb\xeb\xab\x84\ +B\xe10\xb2\xdc\xbazX\x89D\x827._l\xf8\ +\xbb\x81\x90\xc6\xe7\x87\xec[\xc8a\xebb\xc0g\xfaJ\ +\xfc\xc7\xb4\xa8\x1b\xeb\xc3\xe1pKE\x05\xac\x07\xa7\xbb\ +#\x11\x0c\xc3`uu\x85d2A0\xb0\xd1c\xed\ +$*\xa8\x06\xc5O\x9e\x9a\x5c\x17\xd7\xcc\x9d\xdb\x00u\ +\xe2\x0a\x06\x02D\xfb\xfb\x09\x85\xc2tuu\xefy\x96\ +l\x15k\xcfy\xebJ !\x04\x1f\xee\xb3\xb7x\x8b\ +\xadw<\xe5\xca\xf3xo\xfdPs\xa8\x89\x1cp;\ +\x91$\x89H\xa4\x87\x89\x89#\xebY\xa8\xbb\x89j\x8d\ +5q\xf9\xee9rg\xee\xdcfv\xb6\xd6\x96\xd1\x02\ +A&&\x8e\x10\x89\xf4\xb4MTk4\xca\xb7\x7f[\ +_\x80\xb7\xa8\xf7\xb1\xb0\x00>\xd6\x9d\xc2\xe3\xde\xb0\x07\ +\xba\xbb#h\xfe\xed\xebs\xb6\x83L&S\xb5\xa9\xd6\ +Duj\xaa\xa1\xa8\xd6PU\x95\x13\xa7&\xd7g~\ +3wn\xb3\xd8\x86\xc5\x0f\xcd\xe0\xd74\xba\xbb6\xf2\ +\xed=.\x17\x1f\xed\xb6\xbfL\xba\xed\xc2\x0aI\x15~\ +cx\xc3\xae\x18\x18\x1c\xdc\xe1\xe8\xf6\x90\xcbf\xd7\x0d\ +\xf5\x93\xa7\xa6\xd0\xb4\xdd\x85\xefRUNN\x9e^\x17\ +W6\xdb\xbaE\x0f{\xa5\xff\xde3\x17B\xf0\xa1a\ +\x99\xa0\xc5\xe1\x9bF\xb4\xa4\xe0\xc2\xbb\xdci~\x18\xed\ +\xe2\xf5\xb4^W\xdf\xa0\x13\xe8\xed\xebC\x92%\xfc~\ +mO\x19\x07.Uer\xea4+\xf1\x95\xa6\x9d\xa1\ +\xed \x14\x0a\xe1\xf7\xf9y4(\xf1\x1eOk6\x22\ +\xb5uV\xb8\x99\x8a)\xf84G\xc8vuN\x15\xbb\ +\x87\x09\xdf\xea\x1c\xff\x96k\xa8-J\xf7o\x99e\xa9\ +\x08\x93\x0f\xc9\xb7\xd1\x8c\xf6\x15g{X\x09\x98E\xfe\ +\xb5|\xabe\xa2\x82\x16\x0a\x0b@3J\xbc?\xf3:\ +^\xb3\xf3*\xad<\xa8xL\x9d\xf7e.\xb4\xfc\x85\ +n\xf9\x5c\xb8\xcf\xc8\xf2\x8b\x99\x0b\xb8\xcc\x0e\xad{\xf4\ +\x00\xa1\x98\x06\xbf\x90=OTo\xcd\xbeF\x9bi\x8b\ +\x93eXO\xf1d\xee2R\xa7\xd6L|\x00\x901\ +\xf9\x97\xb9K\x8cTZ\xb3\x03\xdbV\xda\xe6\xbd;V\ +\x8e\xf3/r\x97\x91m\xaa\xf6\xf20\xa3`\xf0T\xf6\ +2G\xcb{_\xdao\x15mu\x0b\x9f(/\xf3\xfe\ +\xecy\xdcf{7*z\x90p\x9b\x15~)s\x9e\ +\xe3\xe5\xedw\x9bm\x05\xed\x8d7\x00\xa3\x95\x04Og\ +\xce\x124Z\xbf\xa3\xc5\x83F\xc0,\xf1+\x99s\x8c\ +V\xda_%\xb0\xed\xc2\x02\xe8\xd5\xb3|0\xf3\x1a\x03\ +z\xe7z\xaf;\x9d\x01=\xcd\xd3\xa9\xd7\xdab\xa87\ +\xa2#\x84\x05\x102\x8a<\x9d9\xcb\xdb\x8bwm\xd8\ +=\xef\xc1\xe6\xb1\xd2\x1cOg\xce\x122[\xbf\xdd\xcc\ +vtT\x0dm\xd94xO\xfe:\xe3\x95U\xbe\xe6\ +;N^X\xbb:\xf7A\xc3c\xea\xbc7w\x95\x93\ +\xe5\xa5v7\xa5\x8e\x96\x85t\xf6JB\xf2\xf0u\xdf\ +q\xa6\x95\xdd7\x02x\x189\x5c^\xe1\xbd\xb9k\x1d\ +\xd5Km\xa6c\x85\xb5\xc655\xc27\xbdGII\ +\xdb\xe7w?L\x04\xcc\x12?\x99\xbf\xc9\x99\xd2B\xbb\ +\x9b\xb2#\x1d5\x146\xe2X9\xceX%\xc1\x8b\x9e\ +Q^v\x8fX\xbea\xe3\xfd\x82d\x9a\xbc\xb54\xc7\ +O\x14n\xe2\xbe\x0f\xa2\x16\x1d/,\x00\x97\xa9\xf3\xae\ +\xfcM\xce\x94\x16y\xd13\xcae\xb5\x17\xf3!1\xf1\ +\x05&\xa7J\xcb\xbc\xa3p\x8b^\xa3};\xde\xef\x95\ +\x8e\x1f\x0a\x1b\x11\x93\xfd\xbc\xe4\x1e\xe1\xa2+\xfa\xc0\xf6\ +`\x02\x93\x13\xe5e\xdeY\xb8M\x8fno\xedQ;\ +\xb8/\x85\xb5FL\xf6\xf1\xaa{\x98\x0bj\x94\xa2h\ +\xefn\xf0V\xe11u\xa6J\x0b\xbc\xbd4KD\xef\ +\x8c\xdd\xd4\xf6\xc3}-\xac5*H\x5cS{\xf8{\ +\xf7\x00\xb7\x94.\xee\xc7\x1b\x1a\xd0\xd3<^\x9cg\xb2\ +\xbc\xf8@d~\xdc\x176\xd6n(\x18\x9c,/q\ +\xb2\xbc\xc4\xb2\xec\xe7\xa2\xda\xc7u5\xc2\x82\xdcY\x8b\ +66#\x80\xa8\x9e\xe1X9\xce\xa9\xd2\xe2}e?\ +5\xc3\x03\xd1cmGJ\xf2pM\xe9\xe6\xba\xda\xc3\ +-5L\xb9\xcd\x81\x06\x97\xa93VIp\xb4\x12\xe3\ +hy\xe5\x81\x8e\x8f>\xd0\xc2\xda\x8c\x01\xc4e?s\ +r\x80\xf9{\xff\xe6\x14\x0d\xdd&\xb1I@\xc4\xc81\ +PI3\xa0W\xff\x0dU\xd2\xc8\x0f\xect\xa3\x96\x07\ +b(l\x06\x89j\xb0\xbbW\xcfr\x86\xaas\xb1\x82\ +\xc4\xaa\xe4!)yH\xc8\x1e\x12\xf7\xfe\x9f\x11.J\ +B\xa6$dt$\x0aB\xa1r\xaf\xc6\x82b\x1ax\ +\xcc\x0a2\x06.S\xc7e\xeahF\x89\x90Y \xac\ +\x17\x08\x1b\x05\xc2f\x91\xb0\x9eGyHD\xd4\x88\x87\ +FX\x8dP0\xe85rU\xfb\xc6I\x09\xb3\x94\x8e\ +\xc9npx\xb0p\x84\xe5`\x0b\x8e\xb0\x1cl\xc1\x11\ +\x96\x83-8\xc2r\xb0\x05GX\x0e\xb6\xe0\x08\xcb\xc1\ +\x16\x1ca9\xd8\x82#,\x07[p\x84\xe5`\x0b\x8e\ +\xb0\x1cl\xc1\x11\x96\x83-8\xc2r\xb0\x05GX\x0e\ +\xb6\xe0\x08\xcb\xc1\x16\x1ca9\xd8\x82#,\x07[p\ +\x84\xe5`\x0b\xff\x1f\xc7\xbbd\x0c \xc8\xf4\xd2\x00\x00\ +\x00\x00IEND\xaeB`\x82\ +\x00\x00 \x9d\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x00\x96\x00\x00\x00\x96\x08\x06\x00\x00\x00<\x01q\xe2\ +\x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\ +\x01\xc7o\xa8d\x00\x00\x00\x19tEXtSof\ +tware\x00www.inksca\ +pe.org\x9b\xee<\x1a\x00\x00 \x00ID\ +ATx\x9c\xed\x9dyt\x1cW\x9d\xef?\xd5\xfb\xde\ +j\xed\xfbfK\xde\x17\xc5v\xbc\xc5NB6;\x84\ +LB\x02\x84\x00a\x09\xcb\x00\x87\xbc\xc0<\xe6\xc1\x0c\ +\xe7<\x083\x07\x1e\xbc\x81a\x86\x97a2\x09[B\ +&$dub\xb2\xc7\xfb.\xaf\xb2l\xc9\xb2$k\ +_[R\xef[U\xbd?JnY\x96\x17\xb5\xa4\x96\ +ZN}\xce\xd1\xe9\xaa\xeaZ~\xd5\xfa\xd6\xad{\x7f\ +\xf7w\x7fW\x90\x0f!\xa3\xa22\xc5hf\xda\x00\x95\ +k\x13UX*IA\x15\x96JRP\x85\xa5\x92\x14\ +Ta\xa9$\x05UX*IA\x15\x96JRP\x85\ +\xa5\x92\x14Ta\xa9$\x05UX*IA\x15\x96J\ +RP\x85\xa5\x92\x14Ta\xa9$\x05UX*IA\ +\x15\x96JRP\x85\xa5\x92\x14Ta\xa9$\x05UX\ +*IA\x15\x96JRP\x85\xa5\x92\x14\xaeIa\xc9\ +\xea\xf0\x90\x19G7\xd3\x06L\x96pTK\xf5\x99L\ +\x8e\x9eM\xa7\xa1\xddI\xf7\x80\x19\x7fH\x87 \xc8\xd8\ +\xcd1\x0a\xb3|\xcc+\x1cb\xf5\x82^\xe6\x17\x0d\xce\ +\xb4\xb9\x1f\x1a\x84\xd9:\xfc\xab{\xc0\xcc\xab{Kx\ +\xffH>\xa1\x88v\x5c\xc7\x14g\xfbx\xe8\xb63\xac\ +\xac\xecK\xb2u*\xb3NX\xe1\xa8\x96\x17w\x96\xf2\ +\xf2\xeeR\xa2\xb1\xd1orA\x10HK\xcf\xc0\xeep\ +\x22\x89\x12^\xcf\x10C\x83\xee1\xe7\xd8|}+_\ +\xbd\xb3\x0eA\x98U\xb7>\xab\x98U\xaf\xc2#\x0d\x19\ +<\xbee!\xbd\x83\xa6\xf86\xbd\xc1\xc0\xca5\x1bX\ +~\xfd:*\x17-\xc6b\xb1\x8d:f\xb0\xbf\x9f\x9a\ +\xa3\x87\xd8\xfe\xeeVZ\x1a\x1b\x00\xf8\xeb\x81\x22\x0cZ\ +\x89/n\xaa\x9fV\xfb?L\xcc\x8a\x12K\x96\x05\x9e\ +\xdf^\xc6s\xdb\xca\x91e\x01\x00\xadV\xcb\xcd\x9b>\ +\xc6\xe6{>\x89\xcd\xe1\x1c\xc79dv\xbc\xb3\x95\xe7\ +~\xf7\x1b$I\x02\xe0g_9@e\xe1PRm\ +\xff\xb0\x92\xf2\xc2\x0aG\xb5\xfc\xdf\x17\x96p\xb0.+\ +\xbe\xadb\xc1b\x1e|\xf8\x1b\xe4\x17\x95$|\xbe\xb7\ +\xb7\xbc\xc8\x8b\xcf\xfc\x16\x80\xd5\xf3{\xf9\xfe\xa7\x8fN\ +\x99\xad*#\xcc\xe8\xab0\x12\xd3\xe0\x0f\xea\x89\xc44\ +\x08\x80\xcd\x1c\xc5b\x8a\xc5\xbf\x0fFt\xfc\xd33\xcb\ +9y\xce\x05(u\xa8\x8f\xde\xf7i\xee\xba\xffA\xc2\ +1\x89^_\x98P$FD\x14\x89\x8a\xc3\xcf\x87$\ +\x22E\x82XM\x06\xb2]N\xccF\xc3\xa8k\xde\xb2\ +\xf9ox\xeb\xb5\x17\xf1y\x868\xde\xe8B\x94\x04\xb4\ +\x9a\x94~\xb6f%\xd3\x22\xacpTKC\x87\x83\xd3\ +-N\xdazmt\xb8-t\xf4Y\xf0\x06\xf5c\xf6\ +5\x1bb\xe4e\x04\x99\x93\xe7\xa1\xb6%\x8d\xf6>+\ +\x00F\x93\x89/?\xf2\xbf(Z\xb0\x9c\xa6>\x1f\x11\ +Qy\x9d\x85CA\x9aj\x0es\xb6\xa6\x9a\xee\x96F\ +<\xee^\xe4aG\x96F\xa3%37\x9f\xaaUk\ +\xb8\xf9\x8e\xbbped\xa2\xd5\xe9\x98S9\x9fc\x87\ +\xf6\x13\x8c\xe8\xe8\x1d4\x91\x9b\x1e\x9c\x8e\x9f\xe1CE\ +\xd2\x84\xd5;hb\xcf\xa9\x1c\x0e\x9c\xce\xe2tk\x1a\ +\xa2(\x8c\xeb\xb8`DGc\xa7\x9d\xc6N{|\x9b\ +\xd9b\xe5K\xdf\xfe\x01\xd6\xbc2\xba=\x8a\x08\xfa;\ +[\xa9\xfe`+\xa7\xabw#\xc6b\x97<\x97$\x89\ +\xf4t\xb4\xf2\xd6\xab\xad\xbc\xb7\xf5\x15\xee\xff\xec\x97\xb8\ +y\xd3\xdd\x98-\xd6\xf8>\xe1\xe8\xf8\x5c\x15*\x891\ +\xa5\xc2\x92e\xa8\xae\xcfb\xeb\xc1\x22\x8e4\xa4\xc7+\ +\xda\x97\xc2l\xb3\xe3\xcc\xc8\xc6d\xb1a0\x9a\x88E\ +\xa3\x84C~\x86\xfa{\xf1\x0d\xb99_\xf3\xd3\x1b\x8c\ +<\xf8\xad\xefc\xc8.!*J\xf8\x06\xdd\xec\xdc\xf2\ +\x1cu\xd5\xbb\xe3%\xd3y\xf4Z\x0d\x05v;if\ +\x03\xb2\x0c\xee`\x88\xb6!/2\x10\x8bFy\xeew\ +\xff\x09\x80gp\xc4Qj3_Z\x94*\x93cJ\ +\x84\x15\x89i\xd8u\x22\x97\x97\xf7\x94\xd2\xdac\x1d\xf3\ +\xbd==\x8b\xc29\xf3\xc9/\xab \xbb\xb0\x0cWv\ +.F\xf3\xd8\xfd\xce\xd3\xdd\xd2\xc8\x9f\x7f\xf5C\x90\xe1\ +\xae/~\x0bG~9\x00'\x0f\xec`\xdb_~O\ +$\x1c\x8a\xefk\xd6\xe9\xd8PZ\xc0\xba\xe2\x02\x96\xe4\ +d\xa0\xd5\x8c\xf6m\xb9\x83!\x9e?Q\xc7\x9bg\x9a\ +\x01x\xe9O\xbfGgP\xea]&\x83H\xba=\x84\ +\xca\xd43\xa1V\xa1,\x0b\x9cnu\xd2\xd0\xe1\xa0\xae\ +\xd5\xc9\x91\x86L\xfc\xa1\xd1\x1a\xb59\xd3Y\xb4\xe6F\ +*\x97\xad&\xb3\xa08a\xc3\x02\xde!$I\xc4\xe6\ +LG\x96$\xde\xff\xcb\xef9\xbe\xfb\xdd\xf8\xf7\x16\x83\ +\x9e\xfb\x16\xceesE\x19\x16\xc3\xd8\xba\xda\xc5<\xbe\ +\xff(o7\x9c\x1b\xb5m\xe5\xbc^~\xf0\xa0\xda*\ +L\x06\x09\x97X\x0d\xed\x0e\xfe\xdfk\x0bi\xea\xb2_\ +\xf2\xfb\xec\xa22V\xde\xf21*\x96\xadB\xa3\x99x\ +\xfd\xc5bW|S\xb1h\x84\xad\x7f\xf85gO\x1c\ +\x8a\x7f\xb7\xa1\xb4\x90\xaf\xacX\x82\xc3d\xb8\xdc\xe1c\ +\xb8\xa1\xa4p\x8c\xb0\xd6,\xe8\x9d\xb0}*W&!\ +a\xf5\x0e\x99x\xecOUx\xfc\xa3\xff\xa1z\x83\x81\ +\xf2\xc5+X\xb2\xee\x16\x8a*\x16^\xf5<\xb2,\xd1\ +\xdb\xde\x86\xd1d\xc6\x99\x99u\xd9\xfdD1\xc6kO\ +\xfe\x0b\xe7N\x9f\x00@\xab\x11\xf8\xdbU\xcb\xb8mn\ +\xe2\xfe+_$2j\xdda\x8d\xb0qI\xe7\xb8\x8f\ +\x8f\xc44\x0c\xf8\x8c\xb8=F\xdc^\xe5/\x1a\xd3\x10\ +\x89j\x88\xc4\xb4\xe8u\x12F\xbd\x88V+\xe3\xb0D\ +pX\xa28-\x11r\xd3\x83\xd8\xcc\xd1\x84\xed\x9d\xed\ +$$\xac\xd7\xf6\x94\xc4E\x95]T\xc6\x92\xb57\x93\ +]XJva)\x1a\xed\xf8N\x15\x09\x05\xf9\xef_\ +>F[\xe3i\x00V\xdc\xb4\x89M\x9f\xf9\xda%\xf7\ +}\xf7\xbf\x9f\x8c\x8b\xca\xa8\xd3\xf2\xdd\x1bV\xb2\xb2 \ +7\x11\x93\xe3\xbc\xdf\xd82j\xfd\xdeu\xe70\xe8\xa4\ +1\xfb\x0d\xf9\x0c\x9c\xeb\xb1\xd1\xd2c\xa3\xa5\xd7\xca\xb9\ +n;\x9d\xfd\x16<\x81\xab\xbfn/\x87\xcd\x1c%?\ +#@I\x8e\x8f\x8a|\x0fs\x0b\x86(\xc9\xf1]\xd3\ +\xfe\xb3\x84\x84u\xecl:\x00\x1a\xad\x8e\xfb\xbe\xfe}\ +LV\xdbU\x8e\x18\xcb\xa1\x0f\xde\x88\x8b\x0a\xa0z\xdb\ +\x9b,\xba~#E\x15\x0bF\xed\xd7\xdf\xd9J\xed\xc1\ +\x1d\x8a\x91\x1a\x81\x1f\xdc\xb4\x86%9\x99\x09_\x0f`\ +ok\x07\x87\xda\xbb\xe3\xeby\x19~V\xce\xeb\xe3\xe8\ +\xd9\x0c\xba\x07\xcc\xb4\xf4\xd8h\xed\xb5\xd2\xdcm\x1bS\ +\x1aO\x05\xbe\xa0\x9e\xfa6'\xf5mN\xde\xa9.\x00\ +\x94\x86\xc3\xa2\x92\x01\xaa\xe6\xf6S5\xb7\x9f\x82L\xff\ +\x94_w&IHX\xe1\x98Rg2\x18\xcd\x13\x12\ +\x15\x80\xc7\xdd?f\xdb\x90\xbb\x97\x22F\x0b\xcbd\x19\ +\xa9\xc3\x95\xa5\xa5MXT\xa7z\xdd\xfcj\xcf\x91Q\ +\xdb\xba\xfa-|\xeb\xd7k\xc7}\x0e\x9b\xc3I\x9a+\ +\x03Gz&\x0eW:v\xa7\x0b\xbb3\x0d\x8b\xcd\x81\ + \x08\x98-\x16\x02~E\x18\xd1H\x98\x80\xcf\x8b\xdf\ +;\xc4\x90\xdbM\x7fO\x07\xbd\xdd\x1d\xf8=\x9eQ\xe7\ +\x0cE\x948\xb2\xea3\xca}\xe5\xa5\x07\xb8aq7\ +\x1b\x96tQ\x9c\xed\x9b\xd0\xbd\xa6\x12\x09\x09\xcba\x89\ +\xd0=`&\x1c\xf4\x11\xf0z\xb0\xd8\x1d\x09_\xb0\xb2\ +\xeaz\xaa\xb7\xbd\x19_7\x9a-\x94\xce_:f?\ +\xab3\x0d\x9b+\x03\xdf@?M\x83\x83\x84b1L\ +\xba\xc4\xda\x1a\x87\xdb{\xf8\xd9\xae\x83\x84.r\xa0\xca\ +\x5c\xda\xbff\xb6X\xc9),&\xb7\xb0\x84\xdc\xc2b\ +r\x0aJ\xc8+,\xc1:\x81\xfb\xbc\x98\x80\xdfO{\ +\xf3\x19Z\x9b\x1ah=[OS}-~\xef\x88\xd8\ +:\xdd\x16^\xd8Q\xc6\x0b;\xca(\xce\xf2q\xcb\x8a\ +\x0enY\xde1k\xebg\x09\xb9\x1b~\xfbf%\xaf\ +\xedU*\xce\xb7=\xf0\x15\x16\xaf\xbdyB\x17=U\ +\xbd\x87#;\xde\xc1h6\xb1\xfe\xceO\x90[\x5c~\ +\xc9\xfd\xfe\xfc\xab\x1f\xd1\xd1X\x07\xc0\x0d%\xf9<\xba\ +n%:\xcd\xd5=\xf8\xfeh\x94\xe7\x8f\xd7\xb1\xa5\xae\ +\x11\xe9\x02'\xaa\xce`\xc0\x91\x96\x8e\xc9l\xc6\x95\x91\ +MzV\x0e\xae\xacl\xb2\xf3\x0a\xc9-(\xc1\x99\x9e\ +1\xa1\xfb\x99\x08\xb2,\xd3\xd6\xd4@\xdd\x89#\x9c>\ +v\x90\x96\xb3\xf5c\x1c\xbeF\xbd\xc8\xc6\xa5]\xdc\xb5\ +\xba\x85\x92\x9c\xd9U\x8a%$\xac\xd3\xadi|\xef\xc9\ +U\x00d\xe5\x17\xf3\x99\xbf\xff\x09\x820\xbe\xae\x9a\x89\ +\xd0\xdeT\xcf\x0b\xbf\xfaQ\xfc\x07/Msr\xff\xe2\ +JV\x16d\x8f)\xbd<\xe10\x0d}C\xeck\xeb\ +`gs;\xc1\x8bJ\xa9\x8f}\xfa\x8bl\xdc|o\ +\xd2l\x9d,\x03\xfd\xbd\x1c\xdb\xb7\x8bc\xfb\xb6\xd3v\ +\xaeq\xd4w\x82 \xb3vA\x0f\x9f\xba\xa9q\xd6\x08\ +,a\x07\xe9\xb7\xffcM\xdc\x87u\xfb\x83_c\xd1\ +\xea\x1b\x93b\xd8y\xf6l}\x81\xfdo\xbf\xcc\x85V\ +j5\x029V\x0bV\xbd\x81\xa8,\xe2\x09Ep\x07\ +/\xedA7\x9a-|\xee\x91\xef3o\xd1\xb2\xc4.\ +,\x83\x84\x8c$IH2H\x92\x1c7A\x96e\x04\ +A\x18\xfe\x03\xcd\xf0\xa7N\xd0p\x99\xb7lBt\x9c\ +kb\xcf{[9\xb2w\xfb\xa8^\x06A\x90\xb9a\ +q7_\xb8\xbd\x9e\x0cGx\xf2\x17J\x22\x09\x0b\xeb\ +\xf0\x99L\x1e{\xa6\x0aP\xfa\xfb>\xfb\xdd\x9f`K\ +KO\x8aq\xe79\xbe\xf7=\xb6=\xff\x07Di\xfc\ +\xfdz\x1a\x8d\x96\xc5knb\xc3\xdd\x9f\xc6`\xb1`\ +\xd0j\xd0kuh\xb5\xc2\xa8\xa1I\x92\x0c\x92,!\ +I \xc92\xa2$!\xca2\x924\x01W\xc0\xb0\xb8\ +tZ\x0dZ\xad\x80^\xab\xc1\xa0\xd3\xa2\xd3Ll0\ +T0\xe0c\xef{o\xb2\xe3\xcdWF\xd5\xc7\xcc\x86\ +\x18\x0f\xdc\xdc\xc8]\xab[\xd0jS\xd3e1\xa1.\ +\x9d\x7fzv9\x87\x86\x03\xef\xf2\xcb+\xb9\xff\x9b?\ +@\x9b`\xc5:Q\x22\xe10\xbb\xb7\ +\x0f\xb5\x07\xb6c\xb6;\xc8.,M\xaa\x9f\xebZD\ +\x94eB\xd1\x18\xa1HLqah5W\xfc\x0d\x8b\ +\xca+)*\xaf\xa0\xf6\xf0\x01\xc4X\x8c\x9eA3\xf5\ +mN\xd6/\xee\x9e\xd1N\xeeI\x0b\x0b \xc7\x15d\ +ee\x1f5M\xe9x\x02\x06$Q\xa4\xb1\xe60-\ +u'\xc8)*\xc7\xeaH\x9b\x02S?\x5cH\xb2L\ +(*\x12\x08\xc7\x90\x01\xbdF\xcb\xe5\xf4\x95\x99\x93O\ +\xf9\xbc\xc5\x1c\xdb\xbf\x1bQ\x8c\xd1=`\xa6{\xd0\xc2\ +\x9a\x05=\x97=&\xd9L\x89\xb0\x00\xd2l\x11>R\ +\xd5A\x9f\xc7Ds\xb7\xe2@\xf5\x0e\xba9\xb1\xf7\x03\ +\xfa;[\xb1\xbb2\xb0\xa7M_\x97\xc9\xb5\x82\x0cD\ +b\x22\xfeH\x14Y\x96\xd1\xeb.\xdd\x92L\xcb\xc8\xa2\ +\xacr!\xc7\xf6\xedB\x92D\xceu\xdb\xd0ke\x16\ +\x96\xccL\x22\x94)\x13\x16\x80N+\xb3fA\x0fs\ +\xf2\xbd\xd4\xb79\xf1\x87\xf4 \xcb\xf4w\xb5S\xb3o\ +\x1b\x8d'\x0f\x13\xf0\x0c\xa2\xd3\x1b0\xdb\x1ch\xa6\xc9\ +=q\xad\x10\x89I\xf8C1$Y\x198\xa2\xb9H\ +`\xae\xccl2\xb2s\xa9\xa9\xde\x0b@M\xb3\x8b\xa5\ +\xe5n\xb2\x9c\xd3\x1f\xd7\x9f\xb4\x91\xd0\x91\x98\x86Wv\ +\x97\xf2\xfa\xbe\xe2\xcb\x06\xc9\x99mv\xacN\x17U\x1b\ +\xee\x98p\x87\xf6\x87\x15A\x10\xb0\x1au\xd8M\x861\ +%\xd8__\xf8#\xefo\xf9\x0b\x00\xb9\xe9A\xfe\xf5\ +\xeb{1\x19\xc4i\xb5oJK\xacQ'\xd6\xc8,\ +*\x1d\xe0\xce\xd5\xadd:C\xf4\x0c\x98\x19\x0a\x8c\x0e\ +\xa2\x8bE\x22\x04\xbcC4\x9f:N\xc5\xb2UjK\ +2A\x221\x89`$\x86N\xa3t#\x9dg\xce\xbc\ +E\x9c>v\x08\xcf\xe0\x00\xbe\xa0\x9e\x98\xa4a\xf9\x9c\ +\xb1qp\xc9$i\xc2:\x8fN+37\xdf\xc3\xe6\ +\xeb\xdb\xb8\xb9\xaa\x93\xc2L?\x06\x9d\x84\xc9 \x22I\ +\x1aBQ-\xb2,\xe1\xeeng\xc1\xaa\x0dj+2\ +Ad\x19\x82\xd1\x18QQ\xc4\xa8\xd7)\x1d\xe3\x1a\x0d\ +e\x95\x0b\xd9\xbf\xfdmdI\xe2l\xa7\x83\x1b\x97v\ +M\xeb\x18\xca\xa4\x0b\xebBl\xa6\x18s\x0b<\xac_\ +\xdc\xcd\xed+\xda\xd9\xb4\xaa\x8d\x0f\x8e\xe5\x11\x0c\xeb\xf0\ +\xb8{\xb1\xbb\xb2\xc8.,\x9d.s\xae)b\x92L\ +(\x22b\xd0k\xd1j\x04l\x0e'A\xbf\x8fs\x0d\ +uH\x92\xc0\x90\xdf\xc0\xba\x85=\xd3f\xcf\x8c\xd6\x9e\ +M\x06\x91\x877\x8f\xe4\xa8\xda\xf1\xca3\xca(h\x95\ +\x09\x11\x93$\xfa\xbcA\x221\xa5>u\xcb\xdf<\x80\ +\xd9\xa6\x84\x90\xef9\x99C\xcf\x80y\xdal\x99\xf1f\ +\xd9\xba\x85\xdd\xac[\xa8\xf4y\x85\x83~\xde}\xfe\xa9\ +\x19\xb6hv#\xcb2\xfd\xbe\x10\x91\x98\x84\xc5je\ +\xddG\xee\x04@\x94\x04^\xdf_4mv\xcc\xb8\xb0\ +\x00\xbez\xd7i\x1c\x16%\xb6\xbb\xa9\xe6\x08\xa7\x0e\xee\ +\x9ca\x8bf7\xb2,\xe3\xf6\x05\x88\xc6$\xd6\xdf\xfa\ +Qtz\xa5U\xbe\xedX\xfe\xb8\x93\xb3L\x96\x94\x10\ +V\x9a5\xc2\x977\x8f\x0c\x09\xdb\xf6\xf2\xd3\xf8.\x91\ +;Te\xfcH2\xb8\x03!\xac\xce4\xe6/]\x01\ +\x80'\xa0\xe7\xc8\xd9\xe9qR\xa7\x84\xb0\x006.\xed\ +b\xf5|e\xc8{\xc8\xefc\xeb\x1f\xff\x1dI\x9a^\ +\xdf\xcb\xb5\x86(J\x0c\x05\xc2,_;\x12>\xbe\xb7\ +6gZ\xae\x9d2\xc2\x02\xf8\xfa\xdd\xb5\xb8\xecJ,\ +w\xfb\xd9:\xf6\xfd\xf5\xc5\x19\xb6h\xf6\x13\x8c\xc4(\ +\x9e\xbf,\x1e\xcat\xbc1\xb9a\xe4\xe7I)a\xa5\ +Y#|\xe7\xbe\x9ax\xb0\xda\x81w^\x8d\x0f\xb1W\ +\x998!Q\xa0\xa8\xac\x12P\xf2ot\xb9\x93\xdf:\ +L)a\x01,)s\xf3\xc9\x9b\x9a\x00\xa5\x12\xfa\xe6\ +3\x8f\xe3\x1fRg\x94\x98\x0c22\xf9\xe5\x95\xf1\xf5\ +\xb3\x9d\xc9\xef\xe1H9a\x01|\xea\xc6F\x96\x95+\ +\x95\xf7\x80w\x887\xfe\xf0\xef\xc8\xd2\xd8\x04\x1e*\xe3\ +'-w\xc4\xd5p\xae{b\xe9\x11\x12!%\x85%\ +\x082\x8f~\xbc\x864\xab\x92z\xa8\xfd\xec)\xf6\xbe\ +\xa9\xd6\xb7&Cf^a|\xf9|\xc2\xe0d\x92\x92\ +\xc2\x02p\xd9\xc3\xfc\xdd'N\x8c\xd4\xb7\xde~\x85\xba\ +\xea=3l\xd5\xec\xc5\xe6\x1aI\xaar~tU2\ +IYa\x81R\xdf\xfa\xd4M\xcapsY\x96y\xe7\ +\xb9'\xe8ni\xbc\xcaQ*\x97\xc2h2\xa37(\ +S\xc5\xb8=\x1fra\x01|\xf2\xc6FnX\xdc\x05\ +(\xe3\x09_{\xf2\x17)\xdf\x9f\xe8\xf7\x0c\xa6\xa4\x8d\ +F\x8b\x05PR\x9e'\x9b\x94\x17\x96 \xc0#\xf7\x9e\ +\x8c\xcfy\xe3\x1br\xf3\xd2\xe3?%\xe4O\xcd\xe4\x18\ +\xb5\xfbw\xf0\xbb\x1f?\xcao\x7f\xf4(]-gg\ +\xda\x9cQ\xe8tJ\xd7N$\x96\xfc\x7f{\xca\x0b\x0b\ +\xc0\xa0\x93\xf8\xde\x03\xc7\xc8p(!\xb6\xfd]m\xbc\ +\xfa_?'zQ^\xd1\x99\xe6\xd8\xaewx\xeb\xd9\ +\xdf\x10\x8dD\x10\xc5\x18\x83=]3m\xd2(\x84\xe1\ +`@IJ~\x7f\xe1\xac\x10\x16@\xba=\xcc\x8f\xbf\ +P\x8d\xd3\xa6\x88\xa9\xa3\xe9\x0c\xaf=\xf9/\x88bj\ +L\x00\xd0\xdd\xd2\xc8\xf6\x97\x9f\x8e\xaf/\xdfp;\x95\ +U\xabg\xd0\xa2\xb1DCJ\xaf\x86\xc9\x98\xfc\xdfl\ +\xd6\x08\x0b ?#\xc0?~\xfah<~\xbb\xa5\xee\ +\x04;^\xf9\xd3\x0c[\xa5\xb0\xe3\x95g\xe2S\xaf,\ +\xdfx\x077\xdf\xff\x85\x94K7\x10\x89(%\xbeY\ +\x9f\xfc>\xd8Y%,\x80\xca\xc2!\xbe\xf7\xc01t\ +Z\xc5azl\xe7\xdb4\xd5\xce\xec$\x00M\xb5G\ +i;\xabDg\xb8\xb2r\xd9x\xcfgf\xd4\x9e\xcb\ +\x11\x1d\xce\xb5e2\xaa\xc2\xba$\xcb\xe7\xf4\xf3\xb9\xdb\ +\x94\xd9ReYf\xfbK\x7fD\x9a\xc1W\xe2\xb1\x9d\ +o\xc7\x97\xd7n\xbe\x1fm\x8a\x95T\x00\x91` \xde\ +{aQ_\x85\x97\xe7\xee5\xe7\x98W\xa4\xb4\x14\x07\ +z\xbb\xa8=\xb8kF\xec\x08\x05\xfc\xb4\xd4\xd5\x00J\ +B\xde\xca\xaa53b\xc7\xd5\x18\xe8\x1diH\xe4\xba\ +\x92?\x8d\xde\xac\x15\x96 \xc0\xe7n=\x13_?~\ +A\xa91\x9d4\x9e\xac\x8e7 *\x96^?m9\ +\xc2\x12\xc5\xdd32\x0bG\xfe4\xe4\x94O\xcd_a\ +\x9c,.\x1d\xa0t8\xd9kw[3\xee\xee\xe9O\ +>\xd6}A\x22\xda\xb2EU\xd3~\xfd\xf12\xd0\xd3\ +\x11_.\xc8L~\x06\xc0Y-,\x80\x1b\x96\x8c\x14\ +\xf1\x8d5G\xae\xb0gr\xe8i\x1f\x99\xf8)\x95\x87\ +\xae\xf5u\xb4\xc6\x97\x0b2\xd4\x12\xeb\xaa\x5c7\xb7/\ +\xbe\xdc=\x03\x9e\xee\xf3\xa5\xa4\xc5\xee\x8c\xcfX\x96j\ +H\x92HkC-\x00VS\x8c\xa2lUXW\xa5\ +(\xcb\x1f\xcf\x1c\xdc\xd7\xd96\xed\xd7\x0f\x07\x95\xd7\x8a\ +5EE\x05\xd0\xd5\xdc@d\xd8\xcee\xe5\xfd\xd3\x92\ +Nr\xd6\x0bK\xaf\x93\xe2Y\x83\x07{\xbb.;?\ +t2\x90%)\xde\x84\xd7\xa4pz\xccsu#\xe1\ +\xdd\xcb\xe7LO\xe7\xf8\xac\x17\x16@\xe1p+G\x92\ +D<\xee\xe9\x9b\xdc\xf2\xc2\xee$\x8d&5\x85%\xcb\ +2uG\xf6\xc6\xd7\x97\xcd\x9d\x9e\xe4 \xd7\x84\xb0\xac\ +\xa6\x91\x89\x8c\xa2\xe1\xe9\xcb\x05\xa5\xd5\xe9\xd1\xe9\x95\x0c\ +:\x01\xdf\xd0\xb4]7\x11\x9aO\x1dc\xa0[q5\ +\x94\xe5z\x11EaZ\xa2\x1bR\xf31K\x10\xf3\x05\ +\xb9\x9f\xa2\x91\xf1\x0b+\x1c\xf4\xb3\xed\xa5?\x12\x8b\xca\ +,\x5c}#\xb9\xc5s\xd0\xe9\xb5\xe8t:\x84qd\ +/\x16\x04\x01gF6\xfd]mx\xdd}Hb,\ +\xe5\xfa\x07w\xbc:\xd2\x97\xda\xd4e\xe7\x1b\xff\xb6\x1e\ +\x8d \x93\x9f\x19\xa0,\xc7\xcb\xd2r7k\x16\xf6`\ +\x9f\xe2Y\xc6R\xebW\x98 \xc6\x0b:U\xa3\xe1\xf1\ +\x87\xd2\x9c\xd8\xf3>\xb5\x07\x94\xe1\xfc\xf5Gv\x91U\ +X\xc6\x82\x157R<\xaf\x0a\x9dA\x8fN\xafC\xab\ +\xd5\xa0\xd1j\x104J\x92Y\x01%?\xa8$J\x88\ +1\x11\x9b3\x83\xfe\xae6\xe55<\xd0OZ\xe6\xf4\ +\x0c\x08\x1d\x0f\xfd]m\xb8\xbb\xc6\xfa\xf6$Y\xa0\xad\ +\xd7J[\xaf\x95\x9d5\xb9\xfc\xe6\x8d\x05,+\xef\xe7\ +\xde\xf5\xe7XR65u\xb0kBX\xe7'\xe8\x04\ +\xd0\xea\xc7?\xc5n\xd7\xb9\xd1\xee\x89\xde\xb6&z\xdb\ +\x9a0[_\xa2d~\x15\xa5\x0b\xae#\xbb\xb0\x9c+\ +e\x88\xb5\xbb\xb2\xe3\xcb\x9dM\xf5)%\xac\x0b#?\ +\xe6\x17\x0fR\x9c\xe5\xc7\x13\xd0\xd3\xdeo\xa5\xa3\xcf\x82\ +8\x1c\x97%\x8a\x02\x87\xcfdr\xf8L&+*\xfa\ +\xf8\xfc\x1dg(\xce\x9a\x5c \xe55!\xac`hD\ +XF\xd3\xf8\x07c\x9e\x8f\x9f\xd7\xeb$\xb2\x9c!:\ +\xfa\x87Cw\xfd\x1eNWo\xe7t\xf5v,\xf64\ +\x0a+\x96\x90W\x5cANq\x05&\xab}\xd49\xf2\ +J+\xa9\xd9\xf7\x0e\xa0D9,X\xb5a\xb2\xb73\ +%\x9c:\xb4\x8b\xe6S\xc7\x00%\x96\xed\x87\x9f;<\ +*]d$\xa6\xa1\xa1\xdd\xc9\x9e\xdal\xf6\x9c\xcc\x89\ +\x0f\xb0\xa8>\x93IM\xb3\x8bG?^\xc3\xdaI\xe4\ +\xd3\xba&\x84\xe5\x0b\x8d\x94R\xfaq\x0a\xcb\xe7\x19\xc0\ +3\xa08W\xcb\xf3\xbc\xfc\xf4\xe1\x83\x1ciHg\xeb\ +\xc1\x22\x8e\x9c\xc9\x8c?\xcd\x01\xef \xf5\x87wR\x7f\ +x'\x82 `K\xcb$-3\x17GF\x0ef\xab\ +\x03\xadV\x87V\xa7G\x8cE9s\xec \x91`\x00\ +\x83\xd92\xf57\x99\x00\x83}\xdd|\xf0\x97?\xc4\xd7\ +\xbfp{\xfd\x98\x1c\xa4\x06\x9d\xc4\xc2\x92\x01\x16\x96\x0c\ +\xf0\xa5M\xf5\xbcw8\x9f\xe7\xb6\xcd\xa1\xdfc$\x1c\ +\xd5\xf2\xb3\xe7\x97\xf2\xf9\xdb\xcep\xcf\xfas\x17\x9f~\ +\x5c\x5c\x13\xc2\xea\x1dTF\x9f\x08\x82\x80\xcd9\xbe\xdc\ +\x04\xad\xf5'\xe3\xcb\x0b\x8a\x07\x11\x04\x99\xeb*\xfa\xb9\ +\xae\xa2\x1foP\xcf\xde\xdalv\xd7\xe4r\xa2\xc9\x85\ +$+\x22\x93e\x19\xef@/\xde\x81^83v\xe8\ +\xbf$\xc68\xf8\xfe\x16\xd6\x7f\xf4SSpW\x13#\ +\xe4\xf7\xf1\xea\x13?'\x1cT\x5c0k\x17\xf6\xb0q\ +\xe9\x95C\xa45\x82\xccm+\xda\xd9\xb8\xb4\x8b_\xbf\ +\xba\x90\x9d'r\x91e\x81\xdf\xbf]I\x9a-\xc2M\ +\xcb:\xafx\xfc\xa5\xb8&\x84\xd55\xa0\x94\x10\x16\x87\ +\x13\xbda|\xb3\xd0\xb7\x0e\x87\xba\x80\xe2\x8d\xbe\x10\xbb\ +9\xca\xed+\xda\xb9}E;\xbe\xa0\x9e\x93\xe7\x5c\xd4\ +4\xb98y\xceEK\x8f\x95\x98x\xf9\xe6z\xdd\xe1\ +}\xac\xddt\xdf\x8c\xb4\x0eC\x01//>\xfe\x13\xdc\ +\xddJ\x87s~F\x80o\xde];\xee\xe3\x8dz\x91\ +\xef\xdcw\x82\x1cW\x90\xbf\xec(\x03\xe0?_\x9f\xcf\ +\xe2\xb2\x012\x1d\x89\xb9qf\xbd\xb0z\x87L\xf8C\ +\xcam\xa4e\xe6\x8d\xeb\x18I\x12i:\xa5D\x9d\xea\ +u\x12\x0b\x8a/\x9f\x1b\xc2f\x8e\xb2z~\x0f\xab\xe7\ ++\xf5\x0dQ\x12\xe8r[\xe8\xec\xb7\xe0\x09\xea\xf1\x07\ +u\x18\xf5\x12oU\x17p\xb6\xc3\xc1P_7\x07\xde\ +y\x955\x9b\xee\x9b\xe4\x9d%F\x7fW\x1b[\x9e\xfc\ +E<\xee\xcaa\x89\xf2\x8f\x0f\x1eMx\xb2rA\x80\ +\xcf\xde\xd2@\xb7\xdb\xcc\xce\x9a\x5c\x82\x11\x1d\xcf\xbe?\ +\x87G\xee9y\xf5\x83/`\xd6\x0b\xab\xbem\xa4\x8f\ +.\xb7d\xce\xb8\x8ei;SK`x\xc6\xd2es\ +\xfa\x13\xca\x81\xae\xd5\xc8\x14d\xfa)\xb8(\xa6\xa9$\ +\xc7\xcb\xf7\x9eZ\x85,\x0b\xec{\xf3%rK\xe6R\ +\xba \xc1\xe9\x82'\x80,I\x1c\xd9\xf1\x16{\xde\xf8\ +s|\xd4\x92\xc3\x1a\xe1\xb1\xcfW\x8f\xb11\x11\xbez\ +\xd7i\xaa\xcfd\x12\x08\xeb\xd8~<\x8f\x87n;\x13\ +Oy0\x1ef\xb5\xe7=\x12\xd3\xf0\xe6\xc1\x91\x9c\x04\ +\x85s\xe7\x8f\xeb\xb8S\xd5\xbb\xe3\xcb7,\xea\xbe\xc2\ +\x9e\xe3\xa7\xb2\xd0\x13O\x1c'\xcb2\xaf\xff\xf6\x97\xb4\ +\xd6\xd7\x5c\xe5\xa8\x89#I\x22u\x87\xf7\xf2\xf4\xff\xf9\ +\x1e\xdb_~:.\xaa\xa2l??}\xf8`D\xc1\xdc\xf9\xfc\ +\xf9_\x7fH\xefpt\xe9\xd9\x9aj\x9aN\x1dc\xde\ +ukYv\xc3\xad\xe4\x95V$t\x9d\xde\x8e\x16\x8e\ +\xeex\x8b\xda\xfd;\xe2yY5\xc3\xee\x91M+\xdb\ +XQ\xd9\x9b\x94\xe9\xe3L\x06\x11\xab)\x86/\xa8\xc7\ +{\x99\xf9\x90.G\xca\x0b+&\x0a\x88\x92@L\xd4\ + \x8a\x021Q\xc0\x13\xd4\x13\x08+\xa6\xe7\x14\xcf\x19\ +\x97\xa8\x00vmy.\x9e\xf3\xa1jn/\xb9\x93\x9c\ +\xfd}\xcb\xde\x92\xb8\xa8\x16\xac\xda\xc0m\x0f|%\x9e\ +\xeb\xf3\xb3\x7f\xff\x13\xf6\xfd\xf5E\xf6\xbd\xfd2\xb2$\ +!\x891N\x1d\xdc\xc9\xa9\x83;\xb1\xa5\xa5S:\x7f\ +)9\xc5s\xc8\xcc+\xc4lwb\x1e\xf6\xe8G#\ +!|\x83\xfd\x0c\xf4v\xd1\xd3\xdaD\xf3\xe9\xe3\xf1\xe8\ +\x84\xf3d9C\xfc\x8f{k(\xcb\xf3\xa2\xd5\xc8\xc4\ +D\x01\x9dVN\xea\xdc\x84r\x82\xb1\x81)%\xac\xd8\ +pHG$\xaa!\x1a\xd3\x10\x8d\x09H\x97\x98\xc0V\ +\xab\x910\xe9c\x84\xa2:\xfa\xda\x9b9\xbe\xfb=\xe6\ +,Yq\xc5\x097k\xf6m\xe7\xf8\xee\xf7\x00\xc5\xc5\ +p\xf7\xda\x89y\x94\xcf\x13\x8eji\xe9U^\x0f\x19\ +\xb9\x85\xdc\xf1\x99\xbf\x1d3\x0f\xd0\x9a\xcd\xf7Qu\xe3\ +&\xde\xfa\xd3oh\xaa=\x824\xfc\x9e\xf5\x0d\xba\xa9\ +\xd9\xb7\x8d\x9a}\xdb\x12\xba\xa6Q/r\xd3\xf2\x0en\ +_\xd1\x86Q/2\xe0\x1b)E\x04Y\xb9/\x83~\ +\xf8O'Mz\xfa\xdepT\x8b/\xa8\x5c#3\xc1\ +\xa9\xe9RBX\x81\xb0\x16o@G\xf4\x0a\x8e\xc7\x0b\ +\x11\x04e\x10\xc5\xbb\x87\x0b\x09\x87\x82\xbc\xf7\xfcS\xbc\ +\xf7\xfcS\x98mvl\x0e\x17:\x83\x09\xbd\xd1\x88 \ +(\x95\xe8h(H_\xe7\xc8`\x82{\xd67%\xfc\ +C]LL\x14\xe2O\xb1n\xb8Nu\xa9:\x9e\xd1\ +b\xe5\xee\xaf\xfc\x1d\xd1H\x88\x03\xef\xbc\xc6\xe9C\xbb\ +\xf0\x0c\xf4\x8f\xbb\x08\x10\x04(\xce\xf6\xb2\xa2\xb2\x8f5\ +\x0b\xba/;\xd8T\x16 \x22j\x88\x88\x1a\x18\xbe5\ +\xbdV\xc2fV^g\x13\xa1\xa1c$Wi\xa2s\ +\x1e\xce\xb8\xb0\x82a-n\xef\xf8\xbc\xe5\x17r\xe7\xea\ +Vz\x06\xcd\x1co\x1cI\x88\x1f\xf4y\x09\xfa\xbcW\ +\xcc\x04B:\x0e\xd6g\xf1\xee\ +\xe1|j\x9a\xd3G\xb9\xd3\x8cz\x91\xfb76\xf1\xf1\ +\x1b\x9a\xd1j&\xf7\xb0\xa9\xc2\xba\xc6\x91ee\x8a\x93\ +cM\xe9\x1c<\x9d\xc5\x89\xe6\xf41\xb3\xac\xea\xb4\x12\ +w\xach\xe7\xfe\x8dM\xf1i\xfd&\x8b*\xack\x0c\ +\x7fHGc\xa7\x83\xc6.;\xb5\xcdi\x9cjM\xc3\ +\xe3\xbf\xb4\x03:\xdb\x15\xe4\xd6\xaa\x0en\xa9j'\xc3\ +15\x82:\x8f*\xacY\x88$\x0b\xf4\x0d\x9a\xe8\x1a\ +0+a\xd2n3\x9dn\x0bM\x9dv\xba\x07\xaf\x1c\ +\xad\x91n\x0f\xb3j^/k\x17\xf6\xb0\xac\xdc\x9d\xb4\ +\x86\x84*\xac\x14\xc4\x17\xd43\xe830\xe470\xe0\ +32\xe05(\x02\x1a\x16R\xcf\xa0\xe9\x8a\x03:.\ +\xc4d\x10\x99W8\xc4\xc2\x92\x01\xae\xab\xe8gn\xfe\ +PR\xa3 \xce\xa3\x0a+\x89H\xb2@ \xa4\xc3\x1f\ +\xd2\xe1\x0b\xea\xf1\x0f/\xfb\xc3\xca\xb27\xa0g\xc0k\ +d\xc8o`\xd0o`\xc0k\xc0\x130\x10\x9d`\xd2\ +\x0e\x9dV\xa2$\xc7Gy\x9e\x97\xb2\x1c/\x15EC\ +\x94\xe7z']\x11\x9f\x90-\xd3~\xc5Y\x88,\x0b\ +x\x03z<\xc3\x01o\xde\xf3\x9f\x01=C~\xc3\xf0\ +6\x03\xde\xa0\x0e\x7fH\x19\xb9\xe3\x0f\xe9\x922\x19\x92\ +N+\x91\x9d\x16\x227=@\x9e+Hnz\x80\xdc\ +\xf4 y\xe9\x01\xf2\xd2\x03\xf1$t3\x8d*, \ +\x1a\xd3\xd03h\xa6{\xc0\xa4|\x0e\x0e\xbfr\x06L\ +\xf4zL\x97\xad\xfcN5\x16S\x8ct[\x18\x875\ +\x82\xcb\x16!\xcd\x1a\xc1i\x8b\xe0\xb2\x85\xc9v\x05\xc9\ +M\x0f\x92\xe5\x0cMKF\xbe\xc9\xf2\xa1\x12\x96()\ +YV\xcev:h\xec\xb4\xd3\xd4i\xa7k\xc0\x8c\xdb\ +kJ8B\xf2J\xd8\xccQ\xacF\xa5_\xd0j\x8a\ +b5\xc5\x86\xff\x94e\xcb\xf0\xba\xc3\x1cU\x84c\x0f\ +\xe3\xb0D0$\xd8\x1f\x97\xca\x5c\xd3\xc2\xear\x9b\xa9\ +iN\xa7\xa1C\x11Rs\x97=\xe1\xa4c.{\x18\ +\xa75\x82\xc3\x12\xc5n\x89\xe2\xb0D\xb0\x9b\x95e\xbb\ +9\x1a\xdfn7+\xfbX&\x18Tw\xadqM\x09\ ++\x1c\xd5r\xba\xd5\xc9\xb1\xb3\x19\x1c\xac\xcf\xa2\xb5\xe7\ +\xeas\x1f\x1bt\x12.{\x98\x5cW\x90\x9c\xf4\x80\xf2\ +\xe9\x0a\x92\xeb\x0aR\x90\xe9O(\x06Ie\x84Y/\ +\xacPD\xcb\x9e\xda\x1c\xb6\x1f\xcb\xe3\xe4\xb9\xb4+6\ +\xc3\xb3\x9c!\xca\xf3<\xcc\xc9\xf7*\x9fy\xde)\xf3\ +4\xab\x8cfV\x0aK\x96\x95\x10\x8f\xf7\x8f\xe4\xb3\xa7\ +6\x87Pdl\x04\xa7F\x90\xa9(\xf4P5\xa7\x8f\ +\xf9\xc5C\x94\xe7ypL0\xc4W%qf\x95\xb0\ +dY`Om6/l/\xa7\xb9{\xec\x00\xca\x0c\ +G\x98\xaa\xb9}T\xcd\xedgY\xb9;\xe1\x84\x18*\ +S\xc7\xac\x10\x96,\xc3\xae\x93\xb9\xfcy[9m\xbd\ +\xa3\xebM&\x83\xc8\xba\x85\xdd|\xa4\xaa\x83E%\x03\ +\xd3\xe2UV\xb9:)/\xac\xe6n\x1b\xff\xb5u>\ +'\x87\x87\xd3\x9f\xa74\xc7\xc7\xddk\xcf\xb1nQ\xb7\ +Z\xc1NARVX\x91\x98\x86g\xdf\x9f\xcb\x96\xbd\ +\xc5\xa3\x06)T\xe4{\xf8\xc4M\x8d\xacJ\xd2\xb0r\ +\x95\xa9!%\x85\xd5\xdeg\xe5\x9f\x9f]\x1eO6\x0b\ +J\x8b\xeeK\x9b\xea&\x95pUe\xfaHIam\ +\xd9[\x1c\x17\x95V+s\xef\xfaf>\xb1\xb1iT\ +>w\x95\xd4&%\x85u\xfd\xfc^\xb6\x1d\xcf\xa3(\ +\xcb\xc77\xef>Ei\xee\x95G7\xab\xa4\x1e\xb3v\ +\xf8\x97Jj3\xabSE\xaa\xa4.\xaa\xb0T\x92\x82\ +*,\x95\xa4\xa0\x0aK%)\xa8\xc2RI\x0a\xaa\xb0\ +T\x92\x82*,\x95\xa4\xa0\x0aK%)\xa8\xc2RI\ +\x0a\xaa\xb0T\x92\x82*,\x95\xa4\xa0\x0aK%)\xa8\ +\xc2RI\x0a\xaa\xb0T\x92\x82*,\x95\xa4\xa0\x0aK\ +%)\xe3\xdb\x0c\x12\x00\x00\x00\x1eIDAT\xa8\xc2\ +RI\x0a\xaa\xb0T\x92\x82*,\x95\xa4\xa0\x0aK%\ +)\xa8\xc2RI\x0a\xff\x1f\x85\xc5\xc2\xea\xab\x884~\ +\x00\x00\x00\x00IEND\xaeB`\x82\ +\x00\x00\x18A\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \ + \x0a \x0a <\ +sodipodi:namedvi\ +ew\x0a id=\x22base\ +\x22\x0a pagecolor\ +=\x22#3b3b3b\x22\x0a \ +bordercolor=\x22#66\ +6666\x22\x0a borde\ +ropacity=\x221.0\x22\x0a \ + inkscape:pag\ +eopacity=\x220\x22\x0a \ + inkscape:pages\ +hadow=\x222\x22\x0a i\ +nkscape:zoom=\x2240\ +.756193\x22\x0a in\ +kscape:cx=\x2210\x22\x0a \ + inkscape:cy=\ +\x2210\x22\x0a inksca\ +pe:document-unit\ +s=\x22mm\x22\x0a inks\ +cape:current-lay\ +er=\x22layer1\x22\x0a \ + inkscape:docume\ +nt-rotation=\x220\x22\x0a\ + showgrid=\x22f\ +alse\x22\x0a units\ +=\x22px\x22\x0a inksc\ +ape:window-width\ +=\x221920\x22\x0a ink\ +scape:window-hei\ +ght=\x221027\x22\x0a \ +inkscape:window-\ +x=\x221912\x22\x0a in\ +kscape:window-y=\ +\x22-8\x22\x0a inksca\ +pe:window-maximi\ +zed=\x221\x22 />\x0a \x0a \ +\x0a \ +\x0a\ + image/svg+xml\ +\x0a \ + \x0a \x0a\ + \ +\x0a \x0a\ + \x0a \ +\x0a \x0a \x0a\x0a\ +\ +\x00\x00\x0d\xba\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \x0a\ + \x0a \x0a \ + \x0a\ + \x0a \ + \x0a image/svg\ ++xml\ +\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a\ +\x00\x00\x09\xbe\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a\ + \x0a \x0a \x0a \x0a \ + ima\ +ge/svg+xml\x0a <\ +dc:type\x0a \ + rdf:resource=\ +\x22http://purl.org\ +/dc/dcmitype/Sti\ +llImage\x22 />\x0a \ + \x0a \ +\x0a <\ +/rdf:RDF>\x0a \x0a \x0a \ + \x0a \ + \x0a\x0a\ +\x00\x00\x04\x81\ +\x00\ +\x00\x0f$x\x9c\xedWKo\xe36\x10\xbe\xe7W\x08\ +\xca\xa5E#\x89\xd4[\xaa\xe5m\x8b @\x81\xf6\xd2\ +n\xd1\xa3AK\x94MD\x12\x05\x91\x8e\xed\xa0?\xbe\ +C\xea\xe5G\x92&[\xf4\xb0@-$6\xe7\x9b\x07\ +g8\x9c\x19->\x1d\xea\xcax\xa2\x9d`\xbc\xc9L\ +l#\xd3\xa0M\xce\x0b\xd6l2\xf3\x8f\xcf\x0fVl\ +\x1aB\x92\xa6 \x15ohf6\xdc\xfc\xb4\xbcY\x88\ +\xa7\xcd\x8da\x18 \xdc\x88\xb4\xc83s+e\x9b:\ +N\xbb\xeb*\x9bw\x1b\xa7\xc8\x1dZ\xd1\x9a6R8\ +\xd8\xc6\x8e9\xb3\xe73{\xdeQ\x22\xd9\x13\xcdy]\ +\xf3Fh\xc9F\xdc\x9e0wE9q\xef\xf7{{\ +\xefi&\x9c$\x89\x83\x5c\xc7u-\xe0\xb0\xc4\xb1\x91\ +\xe4`\x9d\x8b\xc2\x1e_\x12u\x11B\x0e`3\xe7\xfb\ +\xb8R\x01Qi\xe1ob\x1f\x09\xb6\xe0\xbb.\xa7%\ +\xc8Q\xbb\xa1\xd2\xb9\xff|?\x81\x16\xb2\x0bY\x9c\xa8\ +a\xcd\xa3\xc8IK\xcf\xac\x8e\xc4>\x02\xa4\xa6\xa2%\ +9\x15\xceH\xd7\xf2{V\xc8-\x1cR\xa0W[\xca\ +6[\x99\x99\x9e\x1d\x87=\xe5\x89\xd1\xfdO\xfc\x90\x99\ +\xc8@\x86g'a\x1c\xf9Ib\xc0\xa1\xban\x88\xfd\ +\x81i>k\xac\x09\xac\xc8Lp4\xee\x17\x83\xbd\xf4\ +4%\x8co|\xe4\x05\xc4/\xd7~rg\xb8\xc8E\ +\x16\x0a,\x84\xbf\xd5\x22\xa3\xa3i\xc1s\xb5\xf3\xccd\ +9oV5\xef\xe8\x8a\xb7\x92\xa9sU\x81\x5c\x02\xf3\ +\xa2\xa0\xa5PB\xbdY\xb5r5\x00\xd0d\xba%r\ +k\xd1\xb2\xa4\xb9\xecY\xc1WV\xd0\xd5c\xc3%\x9c\ +UI*\xd1\xc7C}xS\x1dW\x02R-\x97\x14\ +4\xcan7c\xa4m\x01\xdc3\xb9]u\xa4`;\ +\xf1\x22\xde\xf0\x97\xd1\x9d\xe8M\xae\x0a\xa6.@N/\ +\xf0\xb2\xa2\x07\xb6\xae\xe8\xe5\x8e\xf2-\xa9K\xda\xad\x84\ +\xa4-\xe8\xc4\x130Z\x99)5/@\xfca^S\ +\xb9\xe5\xe0\x05\xd9I>\xef\xa3ap\xca\xeda\x22\x08\ +\x22iU1I\xc5\xaa%\x1d\xa9A\xc3\x1d\x82\x07\xeb\ +\xff\xf0m\xfc`<\xe8\xb5\xa6\xd8n\xe8\x07\xb1\xe7y\ +'\xd05\xf3\x87\xc4\xff;\xcd_\x91\x17\xff\xfb\xf5u\ +\xf9\xf5\xc5\xe2\x7f\xfd\x8b\xd0\x9dP\xa6\xfb[\xb5t\xae\ +\xae\x13\x95\x89\xd5\x13\x13}A9\xab3\xaaP\x9e\x94\ +D\x1cz\xc1\x84\xf5$\xa8@\xac\xaa\xa8\x5c\x0d\xa5\xc7\ +4\x1c]l\x1dU_\xf5\xaf\xa9F\xab\x02]\xa8>\ +1\x17\xe15\x99\x8aWK6\xd0\x8a+\xdee\xe6\xad\ +\xb7V\xcf\x00\xacyW\xd0n\x84B\xfd9\x838\xb4\ ++&\x8f\xfd\x041\xe8\x9e\xeb\xf9\x86N\xf8\x8b\xa8\xd8\ +\x92\x82\xef3\xd3\xbd\x04\x9f9\x87\xf2\xe6#;\x0aB\ +\x9cx\x97p\x0e\xbd\x0e_i\xcc\xc1\x8coc\x8c=\ +\xd7\xf7/AhR;5\x95X\xaa\xacB1\xae\xeb\ ++\xf1]\xd7)\x86\x8a\x1c)x\xab\xbf\xf0\xabj:\ +.\x89\xd4G9\xeeCl\xf9~\xd3\xa9\xc8\x9e\xf6\x85\ +\xc1\xdcT\xc6'M{\xd6\x80\xef\xd6\xd8\xdb\x13\xf7\xca\ +\x9f\x81c\xec\xf7\x18\xb9\xd1+,*\x1c\x09\xbe\x8a\xe2\ +\x80BX\xac\xf8\x15\xac&\x07V\xb3g\xd5B\xf1\x98\ +>\xd0\x8dHA$\x99Se\xa4\x04c\xcf\x86\xd9+\ +\xfd\xed\xfea9\xe4\xe3\x22\xcf\xd3?y\xf78\xa6'\ +\xf4<` k\xbe\x83}\x9b\xcb\x89\xbc(\xf2\x14\xa6\ +\xa5\x9a\xc8%\xab\xe1\xfc\xd5\xa0\xf5\x1dLG\x90\xb1\x13\ +p\xc6,\x8f-\x9d\x95\xf6j;\xda\x8f]/\xce\x9e\ +E^3%\xe4\xfc.\xe1j\xfc\xac\x8c\x0cn\x9d(\ +e\xb2\xa2Km\xb3\xff9z\xe1\x0cn\x0cN:'\ +^.\x9c1\x06z\xb5\xb9\x88fE\xd6\xb4\xca\xcc_\ +T\xce\x18WI\xb3\xe9\xf8\xae\xed{\xbe\xce*s\x8e\ +\xec\x90e\x83Eu\xdd\xc7\xad\x02\xf8\xab\x81\xec\x00E\ +.J\xc2;+\xb0\x11\xf6p\xe0bj\x05\xc6\x8f\x0a\ +\x81D\x0f]\x1c\xde\x8d?\x03\xcf@\xfaQ\xbc~\x9c\ +\xc0\xf4G\xadh\x801\xf2\xa27\x85zB\x00\xa6\xfa\ +\xb91B\xf1\x9b\xfc\x9a+\xc2I\xfcq\x03\xe7\xbe\x90\ +\xb7}A6B\xfe\x1d2\x9e\x8d\x1al\xfa\x91\x87<\ +\xbd~;\x04=\xa7\x9b$\xef\xdd\x1d\xb6\x93\xd8\xf7\xdf\ +\xe9\xbbk\xfbI\x10\x85\x08\x7fP\xfb\x87\x1d\x0f.\x1c\ +\xf7\xfe\xd1q\xd7N\xfc\x10&u\xef\xbd[\xf3l?\ +\x88\xbc\x18\xbd\xd7\xf7\xfe\xfd\x22P[\xfb\xa8\x81/;\ +\xf7y\xfe\x95G=u\xc3\xc5Nou\x97\xf2\xbe\x17\ +\xb2\xe3\x8f4\xbd-KxoC\xc3\xb2/\xaa\xe9\xb4\ +\xacXC\xe1\x22\xa6p\x0d\x9b\xe2\xaa\xbfB\xc3\x08\xad\ +`\xea\x9d\x1bx\xcbUuiy\xf37\x053\xc4=\ +\ +\x00\x00\x07\xb1\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a <\ +sodipodi:namedvi\ +ew\x0a id=\x22base\ +\x22\x0a pagecolor\ +=\x22#3b3b3b\x22\x0a \ +bordercolor=\x22#66\ +6666\x22\x0a borde\ +ropacity=\x221.0\x22\x0a \ + inkscape:pag\ +eopacity=\x220\x22\x0a \ + inkscape:pages\ +hadow=\x222\x22\x0a i\ +nkscape:zoom=\x2240\ +.756193\x22\x0a in\ +kscape:cx=\x2210\x22\x0a \ + inkscape:cy=\ +\x2210\x22\x0a inksca\ +pe:document-unit\ +s=\x22mm\x22\x0a inks\ +cape:current-lay\ +er=\x22layer1\x22\x0a \ + inkscape:docume\ +nt-rotation=\x220\x22\x0a\ + showgrid=\x22f\ +alse\x22\x0a units\ +=\x22px\x22\x0a inksc\ +ape:window-width\ +=\x221920\x22\x0a ink\ +scape:window-hei\ +ght=\x221027\x22\x0a \ +inkscape:window-\ +x=\x221912\x22\x0a in\ +kscape:window-y=\ +\x22-8\x22\x0a inksca\ +pe:window-maximi\ +zed=\x221\x22 />\x0a \x0a \ +\x0a \ +\x0a\ + image/svg+xml\ +\x0a \ + \x0a \x0a\ + \ +\x0a \x0a\ + \x0a \ +\x0a \x0a \x0a\x0a\ +\ +\x00\x00\x08(\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \ +\x0a \x0a\ + \ +\x0a \x0a \ + \x0a image/sv\ +g+xml\x0a \x0a <\ +dc:title>\x0a \x0a \x0a \x0a \x0a \x0a \x0a\ +\x0a\ +\x00\x00\x12\x84\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \ + \x0a \x0a <\ +sodipodi:namedvi\ +ew\x0a id=\x22base\ +\x22\x0a pagecolor\ +=\x22#3b3b3b\x22\x0a \ +bordercolor=\x22#66\ +6666\x22\x0a borde\ +ropacity=\x221.0\x22\x0a \ + inkscape:pag\ +eopacity=\x220\x22\x0a \ + inkscape:pages\ +hadow=\x222\x22\x0a i\ +nkscape:zoom=\x2240\ +.756193\x22\x0a in\ +kscape:cx=\x2210\x22\x0a \ + inkscape:cy=\ +\x2210\x22\x0a inksca\ +pe:document-unit\ +s=\x22mm\x22\x0a inks\ +cape:current-lay\ +er=\x22layer1\x22\x0a \ + inkscape:docume\ +nt-rotation=\x220\x22\x0a\ + showgrid=\x22f\ +alse\x22\x0a units\ +=\x22px\x22\x0a inksc\ +ape:window-width\ +=\x221920\x22\x0a ink\ +scape:window-hei\ +ght=\x221027\x22\x0a \ +inkscape:window-\ +x=\x221912\x22\x0a in\ +kscape:window-y=\ +\x22-8\x22\x0a inksca\ +pe:window-maximi\ +zed=\x221\x22 />\x0a \x0a \ +\x0a \ +\x0a\ + image/svg+xml\ +\x0a \ + \x0a \x0a\ + \ +\x0a \x0a\ + \x0a \ +\x0a \x0a \x0a\x0a\ +\x00\x00\x07A\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a\ + \x0a \ +\x0a \ + \x0a \ + \x0a image/svg+\ +xml\x0a\ + \x0a \x0a \x0a \x0a \ +\x0a \x0a \x0a \x0a\x0a\ +\ +\x00\x00\x06\xd5\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a\ + \x0a \x0a \x0a \x0a \ + ima\ +ge/svg+xml\x0a <\ +dc:type\x0a \ + rdf:resource=\ +\x22http://purl.org\ +/dc/dcmitype/Sti\ +llImage\x22 />\x0a \ + \x0a \ +\x0a <\ +/rdf:RDF>\x0a \x0a \x0a \ + \x0a \x0a\x0a\ +\x00\x00\x07\xa2\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \ + \x0a <\ +metadata\x0a id\ +=\x22metadata5\x22>\x0a \ + \x0a \ + \x0a image/svg+x\ +ml\x0a \ + \x0a \x0a \x0a \x0a \x0a\ + \x0a \x0a \x0a\ +\x0a\ +\x00\x00\x0a\xd7\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\ +\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \ + i\ +mage/svg+xml\x0a \ + \x0a \ + \ +\x0a \ + \x0a \ + \x0a \x0a \x0a \ + \x0a \x0a<\ +/svg>\x0a\ +\x00\x00\x07~\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \ +\x0a <\ +metadata\x0a id\ +=\x22metadata5\x22>\x0a \ + \x0a \ + \x0a image/svg+x\ +ml\x0a \ + \x0a \x0a \x0a \x0a \x0a\ + \x0a \x0a \ + \x0a\x0a\ +\x00\x00\x1an\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \ +\x0a\ + \x0a \x0a \x0a \x0a \x0a \ + \ +image/svg+xml\x0a \ + \x0a \ + \x0a \ + \x0a \ + \x0a <\ +/metadata>\x0a \x0a\ + \x0a \ + \x0a\x0a\ +\x00\x00\x0f\xeb\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \ +\x0a \x0a \ + \x0a \ + \ +\x0a image/svg+xm\ +l\x0a \ + \x0a \ +\x0a \x0a \ +\x0a \x0a \ + \x0a \x0a \x0a\x0a\ +\x00\x00\x07|\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\ +\x0a \x0a \x0a \x0a \ +\x0a \ +\x0a\ + image/svg+xml\ +\x0a \ + \x0a \x0a\ + \ +\x0a \x0a\ + \x0a \ +\x0a \x0a <\ +/g>\x0a\x0a\ +\x00\x00\x07|\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\ +\x0a \x0a \x0a \x0a \ +\x0a \ +\x0a\ + image/svg+xml\ +\x0a \ + \x0a \x0a\ + \ +\x0a \x0a\ + \x0a \ +\x0a \x0a <\ +/g>\x0a\x0a\ +\x00\x00\x10)\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \x0a \x0a \x0a \x0a \ + \ +image/svg+xml\x0a \ + \x0a \ + \x0a \ + \x0a \ + \x0a <\ +/metadata>\x0a \x0a\ + \x0a \ + \x0a \ +\x0a \x0a \ +\x0a\x0a\ +\x00\x007\x0d\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a \x0a \ +\ +\x0a \x0a \x0a \x0a \x0a \x0a \ + i\ +mage/svg+xml\x0a \ + \x0a \ + \ +\x0a \ + \x0a \ + \x0a \x0a \x0a \ + \x0a\ + \x0a \ +\x0a \ + \x0a \ + \x0a \x0a \x0a \ +\x0a\x0a\ +\x00\x00.\xea\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0a\x0a\ + \x0a \x0a \x0a \x0a \x0a \ + im\ +age/svg+xml\x0a \ +\x0a \ + <\ +/dc:title>\x0a \ + \x0a \ +\x0a \x0a \x0a \ + \x0a \x0a\x0a\ +" + +qt_resource_name = b"\ +\x00\x0a\ +\x0d\xc7l'\ +\x00i\ +\x00m\x00a\x00g\x00e\x00s\x00_\x00s\x00v\x00g\ +\x00\x09\ +\x06Y\xb5\x87\ +\x00i\ +\x00c\x00o\x00n\x00s\x00_\x00s\x00v\x00g\ +\x00\x05\ +\x00|\x9c\x93\ +\x00u\ +\x00s\x00e\x00r\x00s\ +\x00\x06\ +\x07\x03}\xc3\ +\x00i\ +\x00m\x00a\x00g\x00e\x00s\ +\x00\x07\ +\x09\x87W\x87\ +\x00c\ +\x00a\x00t\x00.\x00p\x00n\x00g\ +\x00\x09\ +\x0c\x98\xbf\x87\ +\x00m\ +\x00o\x00u\x00s\x00e\x00.\x00p\x00n\x00g\ +\x00\x06\ +\x078WG\ +\x00m\ +\x00e\x00.\x00p\x00n\x00g\ +\x00\x0c\ +\x09\x0d\x1eG\ +\x00m\ +\x00e\x00_\x001\x005\x000\x00p\x00x\x00.\x00p\x00n\x00g\ +\x00\x0d\ +\x04o\x1f\xe7\ +\x00c\ +\x00a\x00t\x00_\x001\x005\x000\x00p\x00x\x00.\x00p\x00n\x00g\ +\x00\x0f\ +\x0eL\xcf\xe7\ +\x00m\ +\x00o\x00u\x00s\x00e\x00_\x001\x005\x000\x00p\x00x\x00.\x00p\x00n\x00g\ +\x00\x11\ +\x08e\xb7\xc7\ +\x00i\ +\x00c\x00o\x00n\x00_\x00s\x00e\x00t\x00t\x00i\x00n\x00g\x00s\x00.\x00s\x00v\x00g\ +\ +\x00\x13\ +\x05\x81q\xe7\ +\x00i\ +\x00c\x00o\x00n\x00_\x00a\x00t\x00t\x00a\x00c\x00h\x00m\x00e\x00n\x00t\x00.\x00s\ +\x00v\x00g\ +\x00\x11\ +\x02\x8e\x8eG\ +\x00i\ +\x00c\x00o\x00n\x00_\x00a\x00d\x00d\x00_\x00u\x00s\x00e\x00r\x00.\x00s\x00v\x00g\ +\ +\x00\x15\ +\x0d\x86\xc9\xc7\ +\x00i\ +\x00c\x00o\x00n\x00_\x00m\x00o\x00r\x00e\x00_\x00o\x00p\x00t\x00i\x00o\x00n\x00s\ +\x00.\x00s\x00v\x00g\ +\x00\x0e\ +\x02`\xf5G\ +\x00i\ +\x00c\x00o\x00n\x00_\x00c\x00l\x00o\x00s\x00e\x00.\x00s\x00v\x00g\ +\x00\x12\ +\x02w\xd8g\ +\x00i\ +\x00c\x00o\x00n\x00_\x00i\x00n\x00v\x00i\x00s\x00i\x00b\x00l\x00e\x00.\x00s\x00v\ +\x00g\ +\x00\x12\ +\x09\xb2\x94g\ +\x00i\ +\x00c\x00o\x00n\x00_\x00e\x00m\x00o\x00t\x00i\x00c\x00o\x00n\x00s\x00.\x00s\x00v\ +\x00g\ +\x00\x11\ +\x0c\xcb\x13G\ +\x00i\ +\x00c\x00o\x00n\x00_\x00m\x00a\x00x\x00i\x00m\x00i\x00z\x00e\x00.\x00s\x00v\x00g\ +\ +\x00\x11\ +\x0c\xc2SG\ +\x00i\ +\x00c\x00o\x00n\x00_\x00m\x00i\x00n\x00i\x00m\x00i\x00z\x00e\x00.\x00s\x00v\x00g\ +\ +\x00\x10\ +\x0eN&'\ +\x00i\ +\x00c\x00o\x00n\x00_\x00r\x00e\x00s\x00t\x00o\x00r\x00e\x00.\x00s\x00v\x00g\ +\x00\x0d\ +\x07\x0b\xd6G\ +\x00i\ +\x00c\x00o\x00n\x00_\x00s\x00e\x00n\x00d\x00.\x00s\x00v\x00g\ +\x00\x0f\ +\x04\xcd.\x07\ +\x00i\ +\x00c\x00o\x00n\x00_\x00o\x00n\x00l\x00i\x00n\x00e\x00.\x00s\x00v\x00g\ +\x00\x0f\ +\x08\xf3\xdb\x87\ +\x00i\ +\x00c\x00o\x00n\x00_\x00s\x00i\x00g\x00n\x00a\x00l\x00.\x00s\x00v\x00g\ +\x00\x0f\ +\x04\x17\xd3G\ +\x00i\ +\x00c\x00o\x00n\x00_\x00s\x00e\x00a\x00r\x00c\x00h\x00.\x00s\x00v\x00g\ +\x00\x0d\ +\x04l\xd0\x87\ +\x00i\ +\x00c\x00o\x00n\x00_\x00i\x00d\x00l\x00e\x00.\x00s\x00v\x00g\ +\x00\x0d\ +\x03\xe8\xd0G\ +\x00i\ +\x00c\x00o\x00n\x00_\x00b\x00u\x00s\x00y\x00.\x00s\x00v\x00g\ +\x00\x13\ +\x0eoG'\ +\x00l\ +\x00o\x00g\x00o\x00_\x00s\x00y\x00m\x00b\x00o\x00l\x00_\x00t\x00o\x00p\x00.\x00s\ +\x00v\x00g\ +\x00\x0d\ +\x04\x8c\xf0\xe7\ +\x00l\ +\x00o\x00g\x00o\x00_\x00h\x00o\x00m\x00e\x00.\x00s\x00v\x00g\ +\x00\x0d\ +\x00\x81\x17G\ +\x00t\ +\x00e\x00x\x00t\x00_\x00l\x00o\x00g\x00o\x00.\x00s\x00v\x00g\ +" + +qt_resource_struct = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x002\x00\x02\x00\x00\x00\x01\x00\x00\x00\x1b\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x1a\x00\x02\x00\x00\x00\x01\x00\x00\x00\x09\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x04\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00B\x00\x02\x00\x00\x00\x01\x00\x00\x00\x05\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x06\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x03\xa4\x00\x00\x00\x00\x00\x01\x00\x01g\xa3\ +\x00\x00\x01x\xb1\x92\xc4<\ +\x00\x00\x03\x84\x00\x00\x00\x00\x00\x01\x00\x010\x92\ +\x00\x00\x01x\xefU\xf7\x8c\ +\x00\x00\x03X\x00\x00\x00\x00\x00\x01\x00\x01 e\ +\x00\x00\x01x\xb1\xfdxB\ +\x00\x00\x00B\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x1a\x00\x02\x00\x00\x00\x10\x00\x00\x00\x0b\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x01\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x9cz\ +\x00\x00\x01x\xb1\xd5\xcb\x8d\ +\x00\x00\x01\xc2\x00\x00\x00\x00\x00\x01\x00\x00\xa4/\ +\x00\x00\x01x\xd7f\x05\xec\ +\x00\x00\x01H\x00\x00\x00\x00\x00\x01\x00\x00\x8e3\ +\x00\x00\x01x\xbb{\xd2\xcf\ +\x00\x00\x038\x00\x00\x00\x00\x00\x01\x00\x01\x18\xe5\ +\x00\x00\x01x\xd7e\x02C\ +\x00\x00\x02\xf4\x00\x00\x00\x00\x00\x01\x00\x01\x01v\ +\x00\x00\x01x\xbc6\x97\xbd\ +\x00\x00\x03\x18\x00\x00\x00\x00\x00\x01\x00\x01\x11e\ +\x00\x00\x01x\xd7e,\xaf\ +\x00\x00\x02\xac\x00\x00\x00\x00\x00\x01\x00\x00\xdf\x82\ +\x00\x00\x01x\xd7e\x9c6\ +\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x80u\ +\x00\x00\x01x\xbb\xa5V\xdb\ +\x00\x00\x02\x8c\x00\x00\x00\x00\x00\x01\x00\x00\xd4\xa7\ +\x00\x00\x01x\xbb\xa3\x9a\xee\ +\x00\x00\x00\xf4\x00\x00\x00\x00\x00\x01\x00\x00h0\ +\x00\x00\x01x\xbb\x82d,\ +\x00\x00\x02\xd0\x00\x00\x00\x00\x00\x01\x00\x00\xe7\x04\ +\x00\x00\x01x\xbb\x9a_T\ +\x00\x00\x01\xec\x00\x00\x00\x00\x00\x01\x00\x00\xac[\ +\x00\x00\x01x\xbb\xa0\x14\xfc\ +\x00\x00\x02>\x00\x00\x00\x00\x00\x01\x00\x00\xc6(\ +\x00\x00\x01x\xb1\xd4Z\xb6\ +\x00\x00\x02\x16\x00\x00\x00\x00\x00\x01\x00\x00\xbe\xe3\ +\x00\x00\x01x\xb1\xd6\xab\xd4\ +\x00\x00\x01p\x00\x01\x00\x00\x00\x01\x00\x00\x97\xf5\ +\x00\x00\x01x\xbb\xae\x98\xda\ +\x00\x00\x02f\x00\x00\x00\x00\x00\x01\x00\x00\xcd\x01\ +\x00\x00\x01x\xb1\xd9o\x1a\ +\x00\x00\x00B\x00\x02\x00\x00\x00\x01\x00\x00\x00\x1c\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x002\x00\x02\x00\x00\x00\x06\x00\x00\x00\x1d\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x01\x00\x00*p\ +\x00\x00\x01x\xbb\xcc*\xb0\ +\x00\x00\x00\x80\x00\x00\x00\x00\x00\x01\x00\x00\x0d\x04\ +\x00\x00\x01x\xef}H\xa2\ +\x00\x00\x00\x92\x00\x00\x00\x00\x00\x01\x00\x00\x18\xb4\ +\x00\x00\x01x\xef}\x01T\ +\x00\x00\x00T\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01x\xbb\xc6'\xba\ +\x00\x00\x00h\x00\x00\x00\x00\x00\x01\x00\x00\x06\x9d\ +\x00\x00\x01x\xbb\xc5\xe6t\ +\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x00G\x8f\ +\x00\x00\x01x\xbb\xcc\x9d\xc6\ +" + +def qInitResources(): + QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/app/uis/main_window/ui_main.py b/app/uis/main_window/ui_main.py new file mode 100644 index 0000000..261e88f --- /dev/null +++ b/app/uis/main_window/ui_main.py @@ -0,0 +1,619 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'mainMcMyCG.ui' +## +## Created by: Qt User Interface Compiler version 6.0.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import * +from PySide6.QtGui import * +from PySide6.QtWidgets import * + +from . resources_rc import * + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + if not MainWindow.objectName(): + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(1200, 720) + self.stylesheet = QWidget(MainWindow) + self.stylesheet.setObjectName(u"stylesheet") + self.stylesheet.setStyleSheet(u"/* DEFAULT */\n" +"QWidget {\n" +" font: 9pt \"Segoe UI\";\n" +" color: rgb(230, 230, 230);\n" +" selection-background-color: rgb(86, 115, 0);\n" +"}\n" +"/* Bg App */\n" +"#bg_app { \n" +" background-color: rgb(0, 0, 0);\n" +" border: 2px solid rgb(30, 32, 33);\n" +"}\n" +"\n" +"/* Left Menu */\n" +"#left_menu {\n" +" border-top-left-radius: 10px;\n" +" border-bottom-left-radius: 10px;\n" +"}\n" +"\n" +"/* Logo Top */\n" +"#logo_top {\n" +" background-image: url(:/images_svg/images/images_svg/logo_symbol_top.svg);\n" +" background-position: center;\n" +" background-repeat: no-repeat;\n" +"}\n" +"\n" +"/* Buttons */\n" +"#left_menu QPushButton {\n" +" border: none; \n" +" background-color: transparent;\n" +" border-radius: 10px;\n" +" background-repeat: none;\n" +" background-position: center;\n" +"}\n" +"#left_menu QPushButton:hover {\n" +" background-color: rgb(21, 22, 23);\n" +"}\n" +"#left_menu QPushButton:pressed {\n" +" background-color: rgb(172, 229, 0);\n" +"}\n" +"#add_user_btn { \n" +" background-image: url(:/icons_svg/images/icons_svg/ico" + "n_add_user.svg);\n" +"}\n" +"#settings_btn { \n" +" background-image: url(:/icons_svg/images/icons_svg/icon_settings.svg);\n" +"}\n" +"\n" +"/* Left Messages */\n" +"#left_messages {\n" +" background-color: rgb(21, 22, 23);\n" +" border: none;\n" +" border-left: 3px solid rgb(30, 32, 33);\n" +"}\n" +"\n" +"/* Top */\n" +"#top_messages {\n" +" border: none;\n" +" border-bottom: 1px solid rgb(47, 48, 50);\n" +"}\n" +"\n" +"/* Search Message */\n" +"#search_sms_frame .QLineEdit {\n" +" border: 2px solid rgb(47, 48, 50);\n" +" border-radius: 15px;\n" +" background-color: rgb(47, 48, 50);\n" +" color: rgb(121, 121, 121);\n" +" padding-left: 30px;\n" +" padding-right: 10px;\n" +" background-image: url(:/icons_svg/images/icons_svg/icon_search.svg);\n" +" background-repeat: none;\n" +" background-position: left center;\n" +"}\n" +"#search_sms_frame .QLineEdit:hover {\n" +" color: rgb(230, 230, 230);\n" +" border: 2px solid rgb(62, 63, 66);\n" +"}\n" +"#search_sms_frame .QLineEdit:focus {\n" +" color: rgb(230, 230, 230);\n" +" border: 2px solid rgb(53, 54" + ", 56);\n" +" background-color: rgb(14, 14, 15);\n" +"}\n" +"\n" +"/* Menus Scroll Area */\n" +"#left_messages_scroll, #messages_scroll {\n" +" background-color: transparent;\n" +"}\n" +"\n" +"/* Bottom / Signal */\n" +"#bottom_messages { \n" +" background-color: rgb(30, 32, 33);\n" +"}\n" +"#signal_icon { \n" +" background-image: url(:/icons_svg/images/icons_svg/icon_signal.svg);\n" +" background-repeat: none;\n" +" background-position: left center;\n" +"}\n" +"#label_top{ \n" +" font: 800 10pt \"Segoe UI\";\n" +" color: rgb(189, 255, 0);\n" +"}\n" +"#label_bottom { \n" +" color: rgb(166, 166, 166);\n" +"}\n" +"\n" +"/* Right Content */\n" +"#right_content {\n" +" border-top-right-radius: 10px;\n" +" border-bottom-right-radius: 10px;\n" +"}\n" +"\n" +"/* Top Bar */\n" +"#top_bar {\n" +" border-top-right-radius: 10px;\n" +"}\n" +"\n" +"/* Title Bar */\n" +"#title_bar {\n" +" background-image: url(:/images_svg/images/images_svg/text_logo.svg);\n" +" background-repeat: no-repeat;\n" +" background-position: left center;\n" +" border-left: 15px solid trans" + "parent;\n" +"}\n" +"\n" +"/* Top BTNs */\n" +"#top_btns { }\n" +"#top_btns .QPushButton { \n" +" background-position: center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" outline: none;\n" +" border-radius: 8px;\n" +" text-align: left;\n" +"}\n" +"#top_btns .QPushButton:hover { background-color: rgb(21, 22, 23); }\n" +"#top_btns .QPushButton:pressed { background-color: rgb(172, 229, 0); }\n" +"#top_btns #close_app_btn:hover { background-color: rgb(255, 0, 127); }\n" +"#top_btns #close_app_btn:pressed { background-color: rgb(172, 229, 0); }\n" +"\n" +"/* Content / Pages */\n" +"#app_pages {\n" +" background-color: transparent;\n" +"}\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"ScrollBars */\n" +"QScrollBar:horizontal {\n" +" border: none;\n" +" background: rgb(52, 59, 72);\n" +" height: 8px;\n" +" margin: 0px 21px 0 21px;\n" +" border-radius: 0px;\n" +"}\n" +"QScrollBar::handle:horizontal {\n" +" background: rgb(47, 48, 50);\n" +" min-widt" + "h: 25px;\n" +" border-radius: 4px\n" +"}\n" +"QScrollBar::add-line:horizontal {\n" +" border: none;\n" +" background: rgb(55, 63, 77);\n" +" width: 20px;\n" +" border-top-right-radius: 4px;\n" +" border-bottom-right-radius: 4px;\n" +" subcontrol-position: right;\n" +" subcontrol-origin: margin;\n" +"}\n" +"QScrollBar::sub-line:horizontal {\n" +" border: none;\n" +" background: rgb(55, 63, 77);\n" +" width: 20px;\n" +" border-top-left-radius: 4px;\n" +" border-bottom-left-radius: 4px;\n" +" subcontrol-position: left;\n" +" subcontrol-origin: margin;\n" +"}\n" +"QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal\n" +"{\n" +" background: none;\n" +"}\n" +"QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal\n" +"{\n" +" background: none;\n" +"}\n" +" QScrollBar:vertical {\n" +" border: none;\n" +" background: rgb(52, 59, 72);\n" +" width: 8px;\n" +" margin: 21px 0 21px 0;\n" +" border-radius: 0px;\n" +" }\n" +" QScrollBar::handle:vertical { \n" +" background: rgb(47, 48" + ", 50);\n" +" min-height: 25px;\n" +" border-radius: 4px\n" +" }\n" +" QScrollBar::add-line:vertical {\n" +" border: none;\n" +" background: transparent;\n" +" height: 10px;\n" +" border-radius: 4px;\n" +" subcontrol-position: bottom;\n" +" subcontrol-origin: margin;\n" +" }\n" +" QScrollBar::sub-line:vertical {\n" +" border: none;\n" +" background: transparent;\n" +" height: 10px;\n" +" border-radius: 4px;\n" +" subcontrol-position: top;\n" +" subcontrol-origin: margin;\n" +" }\n" +" QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {\n" +" background: none;\n" +" }\n" +"\n" +" QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {\n" +" background: none;\n" +" }\n" +"\n" +"") + self.margins_app = QVBoxLayout(self.stylesheet) + self.margins_app.setSpacing(0) + self.margins_app.setObjectName(u"margins_app") + self.margins_app.setContentsMargins(10, 10, 10, 10) + self.bg_app = QFrame(self.stylesheet) + self.bg_app.setObjectName(u"bg_app") + self.bg_app.setStyleSheet(u"#bg_app { border-radius: 10px; }") + self.bg_app.setFrameShape(QFrame.NoFrame) + self.bg_app.setFrameShadow(QFrame.Raised) + self.bg_app.setLineWidth(0) + self.base_Layout = QVBoxLayout(self.bg_app) + self.base_Layout.setSpacing(0) + self.base_Layout.setObjectName(u"base_Layout") + self.base_Layout.setContentsMargins(0, 0, 0, 0) + self.horizontal_Layout = QHBoxLayout() + self.horizontal_Layout.setSpacing(0) + self.horizontal_Layout.setObjectName(u"horizontal_Layout") + self.left_menu = QFrame(self.bg_app) + self.left_menu.setObjectName(u"left_menu") + self.left_menu.setMinimumSize(QSize(50, 0)) + self.left_menu.setMaximumSize(QSize(50, 16777215)) + self.left_menu.setFrameShape(QFrame.NoFrame) + self.left_menu.setFrameShadow(QFrame.Raised) + self.left_menu.setLineWidth(0) + self.vertical_left_menu_layout = QVBoxLayout(self.left_menu) + self.vertical_left_menu_layout.setSpacing(0) + self.vertical_left_menu_layout.setObjectName(u"vertical_left_menu_layout") + self.vertical_left_menu_layout.setContentsMargins(0, 0, 0, 0) + self.logo_top = QLabel(self.left_menu) + self.logo_top.setObjectName(u"logo_top") + self.logo_top.setMinimumSize(QSize(50, 50)) + self.logo_top.setMaximumSize(QSize(50, 50)) + + self.vertical_left_menu_layout.addWidget(self.logo_top) + + self.top_menus = QFrame(self.left_menu) + self.top_menus.setObjectName(u"top_menus") + self.top_menus.setMinimumSize(QSize(0, 50)) + self.top_menus.setFrameShape(QFrame.NoFrame) + self.top_menus.setFrameShadow(QFrame.Raised) + self.top_menus_layout = QVBoxLayout(self.top_menus) + self.top_menus_layout.setSpacing(5) + self.top_menus_layout.setObjectName(u"top_menus_layout") + self.top_menus_layout.setContentsMargins(5, 5, 5, 5) + + self.vertical_left_menu_layout.addWidget(self.top_menus) + + self.spacer_vertical_menu = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.vertical_left_menu_layout.addItem(self.spacer_vertical_menu) + + self.bottom_menus = QFrame(self.left_menu) + self.bottom_menus.setObjectName(u"bottom_menus") + self.bottom_menus.setMinimumSize(QSize(0, 50)) + self.bottom_menus.setFrameShape(QFrame.NoFrame) + self.bottom_menus.setFrameShadow(QFrame.Raised) + self.bottom_menus_layout = QVBoxLayout(self.bottom_menus) + self.bottom_menus_layout.setSpacing(5) + self.bottom_menus_layout.setObjectName(u"bottom_menus_layout") + self.bottom_menus_layout.setSizeConstraint(QLayout.SetMinAndMaxSize) + self.bottom_menus_layout.setContentsMargins(5, 5, 5, 5) + + self.vertical_left_menu_layout.addWidget(self.bottom_menus) + + + self.horizontal_Layout.addWidget(self.left_menu) + + self.left_messages = QFrame(self.bg_app) + self.left_messages.setObjectName(u"left_messages") + self.left_messages.setMinimumSize(QSize(243, 0)) + self.left_messages.setMaximumSize(QSize(243, 16777215)) + self.left_messages.setFrameShape(QFrame.NoFrame) + self.left_messages.setFrameShadow(QFrame.Raised) + self.left_messages.setLineWidth(0) + self.left_box_layout = QVBoxLayout(self.left_messages) + self.left_box_layout.setSpacing(0) + self.left_box_layout.setObjectName(u"left_box_layout") + self.left_box_layout.setContentsMargins(0, 0, 0, 0) + self.top_messages = QFrame(self.left_messages) + self.top_messages.setObjectName(u"top_messages") + self.top_messages.setMinimumSize(QSize(0, 105)) + self.top_messages.setMaximumSize(QSize(16777215, 105)) + self.top_messages.setFrameShape(QFrame.NoFrame) + self.top_messages.setFrameShadow(QFrame.Raised) + self.top_messages_layout = QVBoxLayout(self.top_messages) + self.top_messages_layout.setSpacing(0) + self.top_messages_layout.setObjectName(u"top_messages_layout") + self.top_messages_layout.setContentsMargins(0, 0, 0, 0) + self.top_user_frame = QFrame(self.top_messages) + self.top_user_frame.setObjectName(u"top_user_frame") + self.top_user_frame.setMinimumSize(QSize(0, 60)) + self.top_user_frame.setMaximumSize(QSize(16777215, 60)) + self.top_user_frame.setFrameShape(QFrame.NoFrame) + self.top_user_frame.setFrameShadow(QFrame.Raised) + + self.top_messages_layout.addWidget(self.top_user_frame) + + self.search_sms_frame = QFrame(self.top_messages) + self.search_sms_frame.setObjectName(u"search_sms_frame") + self.search_sms_frame.setMinimumSize(QSize(0, 40)) + self.search_sms_frame.setMaximumSize(QSize(16777215, 40)) + self.search_sms_frame.setFrameShape(QFrame.NoFrame) + self.search_sms_frame.setFrameShadow(QFrame.Raised) + self.verticalLayout_6 = QVBoxLayout(self.search_sms_frame) + self.verticalLayout_6.setSpacing(0) + self.verticalLayout_6.setObjectName(u"verticalLayout_6") + self.verticalLayout_6.setContentsMargins(10, 0, 10, 0) + self.search_line_edit = QLineEdit(self.search_sms_frame) + self.search_line_edit.setObjectName(u"search_line_edit") + self.search_line_edit.setMinimumSize(QSize(0, 30)) + self.search_line_edit.setMaximumSize(QSize(16777215, 40)) + + self.verticalLayout_6.addWidget(self.search_line_edit, 0, Qt.AlignVCenter) + + + self.top_messages_layout.addWidget(self.search_sms_frame) + + + self.left_box_layout.addWidget(self.top_messages) + + self.left_messages_scroll = QScrollArea(self.left_messages) + self.left_messages_scroll.setObjectName(u"left_messages_scroll") + self.left_messages_scroll.setFrameShape(QFrame.NoFrame) + self.left_messages_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.left_messages_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.left_messages_scroll.setWidgetResizable(True) + self.messages_scroll = QWidget() + self.messages_scroll.setObjectName(u"messages_scroll") + self.messages_scroll.setGeometry(QRect(0, 0, 240, 524)) + self.messages_layout_base = QVBoxLayout(self.messages_scroll) + self.messages_layout_base.setSpacing(0) + self.messages_layout_base.setObjectName(u"messages_layout_base") + self.messages_layout_base.setContentsMargins(0, 5, 0, 5) + self.messages_frame = QFrame(self.messages_scroll) + self.messages_frame.setObjectName(u"messages_frame") + self.messages_frame.setFrameShape(QFrame.NoFrame) + self.messages_frame.setFrameShadow(QFrame.Raised) + self.messages_layout = QVBoxLayout(self.messages_frame) + self.messages_layout.setSpacing(5) + self.messages_layout.setObjectName(u"messages_layout") + self.messages_layout.setContentsMargins(0, 0, 0, 0) + + self.messages_layout_base.addWidget(self.messages_frame, 0, Qt.AlignTop) + + self.left_messages_scroll.setWidget(self.messages_scroll) + + self.left_box_layout.addWidget(self.left_messages_scroll) + + self.bottom_messages = QFrame(self.left_messages) + self.bottom_messages.setObjectName(u"bottom_messages") + self.bottom_messages.setMinimumSize(QSize(0, 65)) + self.bottom_messages.setMaximumSize(QSize(16777215, 65)) + self.bottom_messages.setFrameShape(QFrame.NoFrame) + self.bottom_messages.setFrameShadow(QFrame.Raised) + self.verticalLayout_5 = QVBoxLayout(self.bottom_messages) + self.verticalLayout_5.setSpacing(0) + self.verticalLayout_5.setObjectName(u"verticalLayout_5") + self.verticalLayout_5.setContentsMargins(15, 0, 10, 0) + self.signal_frame = QFrame(self.bottom_messages) + self.signal_frame.setObjectName(u"signal_frame") + self.signal_frame.setMinimumSize(QSize(0, 35)) + self.signal_frame.setMaximumSize(QSize(16777215, 35)) + self.signal_frame.setFrameShape(QFrame.NoFrame) + self.signal_frame.setFrameShadow(QFrame.Raised) + self.horizontalLayout_2 = QHBoxLayout(self.signal_frame) + self.horizontalLayout_2.setSpacing(10) + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.signal_icon = QFrame(self.signal_frame) + self.signal_icon.setObjectName(u"signal_icon") + self.signal_icon.setMaximumSize(QSize(30, 16777215)) + self.signal_icon.setFrameShape(QFrame.NoFrame) + self.signal_icon.setFrameShadow(QFrame.Raised) + + self.horizontalLayout_2.addWidget(self.signal_icon) + + self.signal_text = QFrame(self.signal_frame) + self.signal_text.setObjectName(u"signal_text") + self.signal_text.setFrameShape(QFrame.NoFrame) + self.signal_text.setFrameShadow(QFrame.Raised) + self.verticalLayout_7 = QVBoxLayout(self.signal_text) + self.verticalLayout_7.setSpacing(0) + self.verticalLayout_7.setObjectName(u"verticalLayout_7") + self.verticalLayout_7.setContentsMargins(0, 2, 0, 2) + self.label_top = QLabel(self.signal_text) + self.label_top.setObjectName(u"label_top") + + self.verticalLayout_7.addWidget(self.label_top) + + self.label_bottom = QLabel(self.signal_text) + self.label_bottom.setObjectName(u"label_bottom") + + self.verticalLayout_7.addWidget(self.label_bottom) + + + self.horizontalLayout_2.addWidget(self.signal_text) + + + self.verticalLayout_5.addWidget(self.signal_frame, 0, Qt.AlignVCenter) + + + self.left_box_layout.addWidget(self.bottom_messages) + + + self.horizontal_Layout.addWidget(self.left_messages) + + self.right_content = QFrame(self.bg_app) + self.right_content.setObjectName(u"right_content") + font = QFont() + font.setFamily(u"Segoe UI") + font.setPointSize(9) + font.setBold(False) + font.setItalic(False) + font.setStyleStrategy(QFont.PreferAntialias) + self.right_content.setFont(font) + self.right_content.setFrameShape(QFrame.NoFrame) + self.right_content.setFrameShadow(QFrame.Raised) + self.right_content.setLineWidth(0) + self.verticalLayout = QVBoxLayout(self.right_content) + self.verticalLayout.setSpacing(0) + self.verticalLayout.setObjectName(u"verticalLayout") + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.top_bar = QFrame(self.right_content) + self.top_bar.setObjectName(u"top_bar") + self.top_bar.setMinimumSize(QSize(0, 45)) + self.top_bar.setMaximumSize(QSize(16777215, 45)) + self.top_bar.setFrameShape(QFrame.NoFrame) + self.top_bar.setFrameShadow(QFrame.Raised) + self.top_bar.setLineWidth(0) + self.horizontalLayout = QHBoxLayout(self.top_bar) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.title_bar = QLabel(self.top_bar) + self.title_bar.setObjectName(u"title_bar") + self.title_bar.setLineWidth(0) + + self.horizontalLayout.addWidget(self.title_bar) + + self.top_btns = QFrame(self.top_bar) + self.top_btns.setObjectName(u"top_btns") + self.top_btns.setMaximumSize(QSize(100, 16777215)) + self.top_btns.setFrameShape(QFrame.NoFrame) + self.top_btns.setFrameShadow(QFrame.Raised) + self.top_btns.setLineWidth(0) + self.top_btn_layout = QHBoxLayout(self.top_btns) + self.top_btn_layout.setSpacing(4) + self.top_btn_layout.setObjectName(u"top_btn_layout") + self.top_btn_layout.setContentsMargins(0, 0, 0, 0) + self.minimize_app_btn = QPushButton(self.top_btns) + self.minimize_app_btn.setObjectName(u"minimize_app_btn") + self.minimize_app_btn.setMinimumSize(QSize(28, 28)) + self.minimize_app_btn.setMaximumSize(QSize(28, 28)) + font1 = QFont() + font1.setFamily(u"Segoe UI") + font1.setPointSize(9) + font1.setBold(False) + font1.setItalic(False) + font1.setStyleStrategy(QFont.NoAntialias) + self.minimize_app_btn.setFont(font1) + self.minimize_app_btn.setCursor(QCursor(Qt.PointingHandCursor)) + self.minimize_app_btn.setStyleSheet(u"background-image: url(:/icons_svg/images/icons_svg/icon_minimize.svg);") + self.minimize_app_btn.setIconSize(QSize(20, 20)) + + self.top_btn_layout.addWidget(self.minimize_app_btn) + + self.maximize_restore_app_btn = QPushButton(self.top_btns) + self.maximize_restore_app_btn.setObjectName(u"maximize_restore_app_btn") + self.maximize_restore_app_btn.setMinimumSize(QSize(28, 28)) + self.maximize_restore_app_btn.setMaximumSize(QSize(28, 28)) + font2 = QFont() + font2.setFamily(u"Segoe UI") + font2.setPointSize(9) + font2.setBold(False) + font2.setItalic(False) + font2.setStyleStrategy(QFont.PreferDefault) + self.maximize_restore_app_btn.setFont(font2) + self.maximize_restore_app_btn.setCursor(QCursor(Qt.PointingHandCursor)) + self.maximize_restore_app_btn.setStyleSheet(u"background-image: url(:/icons_svg/images/icons_svg/icon_maximize.svg);") + self.maximize_restore_app_btn.setIconSize(QSize(20, 20)) + + self.top_btn_layout.addWidget(self.maximize_restore_app_btn) + + self.close_app_btn = QPushButton(self.top_btns) + self.close_app_btn.setObjectName(u"close_app_btn") + self.close_app_btn.setMinimumSize(QSize(28, 28)) + self.close_app_btn.setMaximumSize(QSize(28, 28)) + self.close_app_btn.setCursor(QCursor(Qt.PointingHandCursor)) + self.close_app_btn.setStyleSheet(u"background-image: url(:/icons_svg/images/icons_svg/icon_close.svg);") + self.close_app_btn.setIconSize(QSize(20, 20)) + + self.top_btn_layout.addWidget(self.close_app_btn) + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.top_btn_layout.addItem(self.horizontalSpacer) + + + self.horizontalLayout.addWidget(self.top_btns) + + + self.verticalLayout.addWidget(self.top_bar) + + self.content = QFrame(self.right_content) + self.content.setObjectName(u"content") + self.content.setFrameShape(QFrame.NoFrame) + self.content.setFrameShadow(QFrame.Raised) + self.content.setLineWidth(0) + self.verticalLayout_4 = QVBoxLayout(self.content) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") + self.app_pages = QStackedWidget(self.content) + self.app_pages.setObjectName(u"app_pages") + self.app_pages.setStyleSheet(u"background-color: transparent;") + self.home = QWidget() + self.home.setObjectName(u"home") + self.home.setStyleSheet(u"#home {\n" +" background-position: center;\n" +" background-repeat: no-repeat;\n" +" background-image: url(:/images_svg/images/images_svg/logo_home.svg);\n" +"}") + self.app_pages.addWidget(self.home) + self.chat = QWidget() + self.chat.setObjectName(u"chat") + self.chat_layout = QVBoxLayout(self.chat) + self.chat_layout.setSpacing(0) + self.chat_layout.setObjectName(u"chat_layout") + self.chat_layout.setContentsMargins(0, 0, 0, 0) + self.app_pages.addWidget(self.chat) + + self.verticalLayout_4.addWidget(self.app_pages) + + + self.verticalLayout.addWidget(self.content) + + + self.horizontal_Layout.addWidget(self.right_content) + + + self.base_Layout.addLayout(self.horizontal_Layout) + + + self.margins_app.addWidget(self.bg_app) + + MainWindow.setCentralWidget(self.stylesheet) + + self.retranslateUi(MainWindow) + + self.app_pages.setCurrentIndex(1) + + + QMetaObject.connectSlotsByName(MainWindow) + # setupUi + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) + self.search_line_edit.setPlaceholderText(QCoreApplication.translate("MainWindow", u"Search messages", None)) + self.label_top.setText(QCoreApplication.translate("MainWindow", u"Signal 80%", None)) + self.label_bottom.setText(QCoreApplication.translate("MainWindow", u"PyBlackBOX server signal", None)) + self.title_bar.setText("") +#if QT_CONFIG(tooltip) + self.minimize_app_btn.setToolTip(QCoreApplication.translate("MainWindow", u"Minimize", None)) +#endif // QT_CONFIG(tooltip) + self.minimize_app_btn.setText("") +#if QT_CONFIG(tooltip) + self.maximize_restore_app_btn.setToolTip(QCoreApplication.translate("MainWindow", u"Maximize", None)) +#endif // QT_CONFIG(tooltip) + self.maximize_restore_app_btn.setText("") +#if QT_CONFIG(tooltip) + self.close_app_btn.setToolTip(QCoreApplication.translate("MainWindow", u"Close", None)) +#endif // QT_CONFIG(tooltip) + self.close_app_btn.setText("") + # retranslateUi + diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000..d90779f Binary files /dev/null and b/icon.ico differ diff --git a/images/icons_svg/icon_add_user.svg b/images/icons_svg/icon_add_user.svg new file mode 100644 index 0000000..52c916f --- /dev/null +++ b/images/icons_svg/icon_add_user.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_attachment.svg b/images/icons_svg/icon_attachment.svg new file mode 100644 index 0000000..51a21f5 --- /dev/null +++ b/images/icons_svg/icon_attachment.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_busy.svg b/images/icons_svg/icon_busy.svg new file mode 100644 index 0000000..309de02 --- /dev/null +++ b/images/icons_svg/icon_busy.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_close.svg b/images/icons_svg/icon_close.svg new file mode 100644 index 0000000..56651fa --- /dev/null +++ b/images/icons_svg/icon_close.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_emoticons.svg b/images/icons_svg/icon_emoticons.svg new file mode 100644 index 0000000..9b5c4e9 --- /dev/null +++ b/images/icons_svg/icon_emoticons.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_idle.svg b/images/icons_svg/icon_idle.svg new file mode 100644 index 0000000..0997f52 --- /dev/null +++ b/images/icons_svg/icon_idle.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_invisible.svg b/images/icons_svg/icon_invisible.svg new file mode 100644 index 0000000..cf2bcec --- /dev/null +++ b/images/icons_svg/icon_invisible.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_maximize.svg b/images/icons_svg/icon_maximize.svg new file mode 100644 index 0000000..4b15003 --- /dev/null +++ b/images/icons_svg/icon_maximize.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_minimize.svg b/images/icons_svg/icon_minimize.svg new file mode 100644 index 0000000..e333b56 --- /dev/null +++ b/images/icons_svg/icon_minimize.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_more_options.svg b/images/icons_svg/icon_more_options.svg new file mode 100644 index 0000000..689ac36 --- /dev/null +++ b/images/icons_svg/icon_more_options.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_online.svg b/images/icons_svg/icon_online.svg new file mode 100644 index 0000000..d335a7e --- /dev/null +++ b/images/icons_svg/icon_online.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_restore.svg b/images/icons_svg/icon_restore.svg new file mode 100644 index 0000000..18dabdd --- /dev/null +++ b/images/icons_svg/icon_restore.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_search.svg b/images/icons_svg/icon_search.svg new file mode 100644 index 0000000..b072584 --- /dev/null +++ b/images/icons_svg/icon_search.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_send.svg b/images/icons_svg/icon_send.svg new file mode 100644 index 0000000..8e75b7f --- /dev/null +++ b/images/icons_svg/icon_send.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_settings.svg b/images/icons_svg/icon_settings.svg new file mode 100644 index 0000000..02f1b90 --- /dev/null +++ b/images/icons_svg/icon_settings.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/icons_svg/icon_signal.svg b/images/icons_svg/icon_signal.svg new file mode 100644 index 0000000..5c1558d --- /dev/null +++ b/images/icons_svg/icon_signal.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/images_svg/logo_home.svg b/images/images_svg/logo_home.svg new file mode 100644 index 0000000..113d8cc --- /dev/null +++ b/images/images_svg/logo_home.svg @@ -0,0 +1,95 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/images/images_svg/logo_symbol_top.svg b/images/images_svg/logo_symbol_top.svg new file mode 100644 index 0000000..de3926e --- /dev/null +++ b/images/images_svg/logo_symbol_top.svg @@ -0,0 +1,71 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/images/images_svg/text_logo.svg b/images/images_svg/text_logo.svg new file mode 100644 index 0000000..a07f60a --- /dev/null +++ b/images/images_svg/text_logo.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/images/users/cat.png b/images/users/cat.png new file mode 100644 index 0000000..ee27ca8 Binary files /dev/null and b/images/users/cat.png differ diff --git a/images/users/cat_150px.png b/images/users/cat_150px.png new file mode 100644 index 0000000..8d1484c Binary files /dev/null and b/images/users/cat_150px.png differ diff --git a/images/users/me.png b/images/users/me.png new file mode 100644 index 0000000..f6db97e Binary files /dev/null and b/images/users/me.png differ diff --git a/images/users/me_150px.png b/images/users/me_150px.png new file mode 100644 index 0000000..82214b9 Binary files /dev/null and b/images/users/me_150px.png differ diff --git a/images/users/mouse.png b/images/users/mouse.png new file mode 100644 index 0000000..807f88a Binary files /dev/null and b/images/users/mouse.png differ diff --git a/images/users/mouse_150px.png b/images/users/mouse_150px.png new file mode 100644 index 0000000..5dc4e0f Binary files /dev/null and b/images/users/mouse_150px.png differ diff --git a/login.ui b/login.ui new file mode 100644 index 0000000..c67cb7f --- /dev/null +++ b/login.ui @@ -0,0 +1,241 @@ + + + Login + + + + 0 + 0 + 300 + 420 + + + + + 300 + 420 + + + + + 300 + 420 + + + + Login. PyBlackBOX + + + #bg { + background-color: rgb(0, 0, 0); + border-radius: 10px; +} +QLabel { + color: rgb(121, 121, 121); + padding-left: 10px; + padding-top: 20px; +} +.QLineEdit { + border: 3px solid rgb(47, 48, 50); + border-radius: 15px; + background-color: rgb(47, 48, 50); + color: rgb(121, 121, 121); + padding-left: 10px; + padding-right: 10px; + background-repeat: none; + background-position: left center; +} +.QLineEdit:hover { + color: rgb(230, 230, 230); + border: 3px solid rgb(62, 63, 66); +} +.QLineEdit:focus { + color: rgb(230, 230, 230); + border: 3px solid rgb(189, 255, 0); + background-color: rgb(14, 14, 15); +} + + + + + 0 + + + 10 + + + 10 + + + 10 + + + 10 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + 0 + 70 + 280 + 720 + + + + + 280 + 720 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 5 + + + 20 + + + 10 + + + 20 + + + 10 + + + + + + 240 + 240 + + + + + 260 + 260 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 260 + + + + #logo { + border-radius: 10px; + background-image: url(:/images_svg/images/images_svg/logo_home.svg); + background-position: center; + background-repeat: no-repeat; +} + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + background: transparent; + + + Login (pass: 123456): + + + + + + + + 0 + 30 + + + + + 16777215 + 40 + + + + Username + + + + + + + + 0 + 30 + + + + + 16777215 + 40 + + + + QLineEdit::Password + + + Password + + + + + + + + + + + + + + + diff --git a/main.py b/main.py new file mode 100644 index 0000000..8cf30e4 --- /dev/null +++ b/main.py @@ -0,0 +1,349 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +# DEFAULT PACKAGES +# /////////////////////////////////////////////////////////////// +import sys +import os + +# IMPORT / GUI, SETTINGS AND WIDGETS +# /////////////////////////////////////////////////////////////// +# Packages +from app.packages.pyside_or_pyqt import * # Qt +from app.packages.widgets import * # Widgets +# GUIs +from app.uis.login.ui_login import Ui_Login # Login / Splash Screen +from app.uis.main_window.ui_main import Ui_MainWindow # MainWindow +from app.uis.chat.page_messages import Chat # Chat Widget +# Modules +import app.modules.ui_functions.functions as ui_functions +from app.modules.app_settings.settings import * + +# GLOBALS +# /////////////////////////////////////////////////////////////// +counter = 0 + +# LOGIN +# /////////////////////////////////////////////////////////////// +class LoginWindow(QMainWindow): + + def __init__(self): + QMainWindow.__init__(self) + # GET WIDGETS FROM "ui_login.py" + # Load widgets inside LoginWindow + # /////////////////////////////////////////////////////////////// + self.ui = Ui_Login() + self.ui.setupUi(self) + + # REMOVE TITLE BAR + # /////////////////////////////////////////////////////////////// + self.setWindowFlag(Qt.FramelessWindowHint) + self.setAttribute(Qt.WA_TranslucentBackground) + + # IMPORT CIRCULAR PROGRESS + # /////////////////////////////////////////////////////////////// + self.progress = CircularProgress() + self.progress.width = 240 + self.progress.height = 240 + self.progress.value = 0 + self.progress.setFixedSize(self.progress.width, self.progress.height) + self.progress.font_size = 20 + self.progress.add_shadow(True) + self.progress.progress_width = 4 + self.progress.progress_color = QColor("#bdff00") + self.progress.text_color = QColor("#E6E6E6") + self.progress.bg_color = QColor("#222222") + self.progress.setParent(self.ui.preloader) + self.progress.show() + + # ADD DROP SHADOW + # /////////////////////////////////////////////////////////////// + self.shadow = QGraphicsDropShadowEffect(self) + self.shadow.setBlurRadius(15) + self.shadow.setXOffset(0) + self.shadow.setYOffset(0) + self.shadow.setColor(QColor(0, 0, 0, 80)) + self.ui.bg.setGraphicsEffect(self.shadow) + + # QTIMER + # /////////////////////////////////////////////////////////////// + self.timer = QTimer() + self.timer.timeout.connect(self.update) + self.timer.start(30) + + # KEY PRESS EVENT + # /////////////////////////////////////////////////////////////// + self.ui.username.keyReleaseEvent = self.check_login + self.ui.password.keyReleaseEvent = self.check_login + + self.show() + + # CHECK LOGIN + # /////////////////////////////////////////////////////////////// + def check_login(self, event): + if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: + username = self.ui.username.text() + password = self.ui.password.text() + + def open_main(): + # SHOW MAIN WINDOW + self.main = MainWindow() + self.main.top_user.label_user.setText(username.capitalize()) + self.main.show() + self.close() + + if username and password == "123456": + self.ui.user_description.setText(f"Welcome {username}!") + self.ui.user_description.setStyleSheet("#user_description { color: #bdff00 }") + self.ui.username.setStyleSheet("#username:focus { border: 3px solid #bdff00; }") + self.ui.password.setStyleSheet("#password:focus { border: 3px solid #bdff00; }") + QTimer.singleShot(1200, lambda: open_main()) + else: + # SET STYLESHEET + self.ui.username.setStyleSheet("#username:focus { border: 3px solid rgb(255, 0, 127); }") + self.ui.password.setStyleSheet("#password:focus { border: 3px solid rgb(255, 0, 127); }") + self.shacke_window() + + + def shacke_window(self): + # SHACKE WINDOW + actual_pos = self.pos() + QTimer.singleShot(0, lambda: self.move(actual_pos.x() + 1, actual_pos.y())) + QTimer.singleShot(50, lambda: self.move(actual_pos.x() + -2, actual_pos.y())) + QTimer.singleShot(100, lambda: self.move(actual_pos.x() + 4, actual_pos.y())) + QTimer.singleShot(150, lambda: self.move(actual_pos.x() + -5, actual_pos.y())) + QTimer.singleShot(200, lambda: self.move(actual_pos.x() + 4, actual_pos.y())) + QTimer.singleShot(250, lambda: self.move(actual_pos.x() + -2, actual_pos.y())) + QTimer.singleShot(300, lambda: self.move(actual_pos.x(), actual_pos.y())) + + # UPDATE PROGRESS BAR + # /////////////////////////////////////////////////////////////// + def update(self): + global counter + + # SET VALUE TO PROGRESS BAR + self.progress.set_value(counter) + + # CLOSE SPLASH SCREEN AND OPEN MAIN APP + if counter >= 100: + # STOP TIMER + self.timer.stop() + self.animation_login() + + # INCREASE COUNTER + counter += 1 + + # START ANIMATION TO LOGIN + # /////////////////////////////////////////////////////////////// + def animation_login(self): + # ANIMATION + self.animation = QPropertyAnimation(self.ui.frame_widgets, b"geometry") + self.animation.setDuration(1500) + self.animation.setStartValue(QRect(0, 70, self.ui.frame_widgets.width(), self.ui.frame_widgets.height())) + self.animation.setEndValue(QRect(0, -325, self.ui.frame_widgets.width(), self.ui.frame_widgets.height())) + self.animation.setEasingCurve(QEasingCurve.InOutQuart) + self.animation.start() + +# MAIN WINDOW +# /////////////////////////////////////////////////////////////// +class MainWindow(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + # GET WIDGETS FROM "ui_main.py" + # Load widgets inside MainWindow + # /////////////////////////////////////////////////////////////// + self.ui = Ui_MainWindow() + self.ui.setupUi(self) + + # SET DEFAULT PAGE + # /////////////////////////////////////////////////////////////// + self.ui.app_pages.setCurrentWidget(self.ui.home) + + # LOAD DICT SETTINGS FROM "settings.json" FILE + # /////////////////////////////////////////////////////////////// + self.settings = Settings() + + self.custom_btn_top = LeftMenuButton( + self, + "custom_btn_top", + "images/icons_svg/icon_add_user.svg", + "Add new friend" + ) + self.custom_btn_bottom_1 = LeftMenuButton( + self, + "custom_btn_bottom_1", + "images/icons_svg/icon_more_options.svg", + "More options, test with many words" + ) + self.custom_btn_bottom_2 = LeftMenuButton( + self, + "custom_btn_bottom_2", + "images/icons_svg/icon_settings.svg", + "Open settings" + ) + self.ui.top_menus_layout.addWidget(self.custom_btn_top) + self.ui.bottom_menus_layout.addWidget(self.custom_btn_bottom_1) + self.ui.bottom_menus_layout.addWidget(self.custom_btn_bottom_2) + + # DEBUG + self.custom_btn_top.clicked.connect(lambda: print(f"{self.settings['app_name']}: clicked")) + self.custom_btn_top.released.connect(lambda: print(f"{self.custom_btn_top.objectName()}: released")) + self.custom_btn_bottom_1.clicked.connect(lambda: print(f"{self.custom_btn_bottom_1.objectName()}: clicked")) + self.custom_btn_bottom_1.released.connect(lambda: print(f"{self.custom_btn_bottom_1.objectName()}: released")) + + + # TOP USER BOX + # Add widget to App + # /////////////////////////////////////////////////////////////// + self.top_user = TopUserInfo(self.ui.left_messages, 8, 64, "wanderson", "Writing python codes") + self.top_user.setParent(self.ui.top_user_frame) + self.top_user.status.connect(self.status_change) + + # SET UI DEFINITIONS + # Run set_ui_definitions() in the ui_functions.py + # /////////////////////////////////////////////////////////////// + ui_functions.UiFunctions.set_ui_definitions(self) + + # ADD MESSAGE BTNS / FRIEND MENUS + # Add btns to page + # /////////////////////////////////////////////////////////////// + add_user = [ + { + "user_image" : "images/users/cat.png", + "user_name" : "Tom", + "user_description" : "Did you see a mouse?", + "user_status" : "online", + "unread_messages" : 2, + "is_active" : False + }, + { + "user_image" : "images/users/mouse.png", + "user_name" : "Jerry", + "user_description" : "I think I saw a cat...", + "user_status" : "busy", + "unread_messages" : 1, + "is_active" : False + }, + { + "user_image" : "images/users/me.png", + "user_name" : "Me From The Future", + "user_description" : "Lottery result...", + "user_status" : "invisible", + "unread_messages" : 0, + "is_active" : False + } + ] + self.menu = FriendMessageButton + def add_menus(self, parameters): + id = 0 + for parameter in parameters: + + user_image = parameter['user_image'] + user_name = parameter['user_name'] + user_description = parameter['user_description'] + user_status = parameter['user_status'] + unread_messages = parameter['unread_messages'] + is_active = parameter['is_active'] + + self.menu = FriendMessageButton( + id, user_image, user_name, user_description, user_status, unread_messages, is_active + ) + self.menu.clicked.connect(self.btn_clicked) + self.menu.released.connect(self.btn_released) + self.ui.messages_layout.addWidget(self.menu) + id += 1 + + add_menus(self, add_user) + + + # SHOW MAIN WINDOW + # /////////////////////////////////////////////////////////////// + self.show() + + # SET USERNAME TO MAIN WINDOW + # /////////////////////////////////////////////////////////////// + def set_user_and_description(self, username): + self.top_user.user_name = username + print(f"User: {username} are logged!") + + # PRINT STATUS + # /////////////////////////////////////////////////////////////// + def status_change(self, status): + print(f"send signal: {status}") + + # GET BTN CLICKED + # /////////////////////////////////////////////////////////////// + def btn_clicked(self): + # GET BT CLICKED + btn = self.sender() + + # UNSELECT CHATS + ui_functions.UiFunctions.deselect_chat_message(self, btn.objectName()) + + # SELECT CLICKED + if btn.objectName(): + btn.reset_unread_message() + ui_functions.UiFunctions.select_chat_message(self, btn.objectName()) + + # LOAD CHAT PAGE + if btn.objectName(): + # REMOVE CHAT + for chat in reversed(range(self.ui.chat_layout.count())): + self.ui.chat_layout.itemAt(chat).widget().deleteLater() + self.chat = None + + # SET CHAT WIDGET + self.chat = Chat(btn.user_image, btn.user_name, btn.user_description, btn.objectName(), self.top_user.user_name) + + # ADD WIDGET TO LAYOUT + self.ui.chat_layout.addWidget(self.chat) + + # JUMP TO CHAT PAGE + self.ui.app_pages.setCurrentWidget(self.ui.chat) + + # DEBUG + print(f"Button {btn.objectName()}, clicked!") + + # GET BTN RELEASED + # /////////////////////////////////////////////////////////////// + def btn_released(self): + # GET BT CLICKED + btn = self.sender() + print(F"Button {btn.objectName()}, released!") + + + # RESIZE EVENT + # Whenever the window is resized, this event will be triggered + # /////////////////////////////////////////////////////////////// + def resizeEvent(self, event): + ui_functions.UiFunctions.resize_grips(self) + + # MOUSE CLICK EVENTS + # /////////////////////////////////////////////////////////////// + def mousePressEvent(self, event): + # SET DRAG POS WINDOW + self.dragPos = event.globalPos() + + +# SETTINGS WHEN TO START +# Set the initial class and also additional parameters of the "QApplication" class +# /////////////////////////////////////////////////////////////// +if __name__ == "__main__": + # APPLICATION + app = QApplication(sys.argv) + app.setWindowIcon(QIcon("icon.ico")) + window = LoginWindow() + sys.exit(app.exec_()) \ No newline at end of file diff --git a/main.ui b/main.ui new file mode 100644 index 0000000..4c93b1a --- /dev/null +++ b/main.ui @@ -0,0 +1,1119 @@ + + + MainWindow + + + + 0 + 0 + 1200 + 720 + + + + MainWindow + + + + /* DEFAULT */ +QWidget { + font: 9pt "Segoe UI"; + color: rgb(230, 230, 230); + selection-background-color: rgb(86, 115, 0); +} +/* Bg App */ +#bg_app { + background-color: rgb(0, 0, 0); + border: 2px solid rgb(30, 32, 33); +} + +/* Left Menu */ +#left_menu { + border-top-left-radius: 10px; + border-bottom-left-radius: 10px; +} + +/* Logo Top */ +#logo_top { + background-image: url(:/images_svg/images/images_svg/logo_symbol_top.svg); + background-position: center; + background-repeat: no-repeat; +} + +/* Buttons */ +#left_menu QPushButton { + border: none; + background-color: transparent; + border-radius: 10px; + background-repeat: none; + background-position: center; +} +#left_menu QPushButton:hover { + background-color: rgb(21, 22, 23); +} +#left_menu QPushButton:pressed { + background-color: rgb(172, 229, 0); +} +#add_user_btn { + background-image: url(:/icons_svg/images/icons_svg/icon_add_user.svg); +} +#settings_btn { + background-image: url(:/icons_svg/images/icons_svg/icon_settings.svg); +} + +/* Left Messages */ +#left_messages { + background-color: rgb(21, 22, 23); + border: none; + border-left: 3px solid rgb(30, 32, 33); +} + +/* Top */ +#top_messages { + border: none; + border-bottom: 1px solid rgb(47, 48, 50); +} + +/* Search Message */ +#search_sms_frame .QLineEdit { + border: 2px solid rgb(47, 48, 50); + border-radius: 15px; + background-color: rgb(47, 48, 50); + color: rgb(121, 121, 121); + padding-left: 30px; + padding-right: 10px; + background-image: url(:/icons_svg/images/icons_svg/icon_search.svg); + background-repeat: none; + background-position: left center; +} +#search_sms_frame .QLineEdit:hover { + color: rgb(230, 230, 230); + border: 2px solid rgb(62, 63, 66); +} +#search_sms_frame .QLineEdit:focus { + color: rgb(230, 230, 230); + border: 2px solid rgb(53, 54, 56); + background-color: rgb(14, 14, 15); +} + +/* Menus Scroll Area */ +#left_messages_scroll, #messages_scroll { + background-color: transparent; +} + +/* Bottom / Signal */ +#bottom_messages { + background-color: rgb(30, 32, 33); +} +#signal_icon { + background-image: url(:/icons_svg/images/icons_svg/icon_signal.svg); + background-repeat: none; + background-position: left center; +} +#label_top{ + font: 800 10pt "Segoe UI"; + color: rgb(189, 255, 0); +} +#label_bottom { + color: rgb(166, 166, 166); +} + +/* Right Content */ +#right_content { + border-top-right-radius: 10px; + border-bottom-right-radius: 10px; +} + +/* Top Bar */ +#top_bar { + border-top-right-radius: 10px; +} + +/* Title Bar */ +#title_bar { + background-image: url(:/images_svg/images/images_svg/text_logo.svg); + background-repeat: no-repeat; + background-position: left center; + border-left: 15px solid transparent; +} + +/* Top BTNs */ +#top_btns { } +#top_btns .QPushButton { + background-position: center; + background-repeat: no-repeat; + border: none; + outline: none; + border-radius: 8px; + text-align: left; +} +#top_btns .QPushButton:hover { background-color: rgb(21, 22, 23); } +#top_btns .QPushButton:pressed { background-color: rgb(172, 229, 0); } +#top_btns #close_app_btn:hover { background-color: rgb(255, 0, 127); } +#top_btns #close_app_btn:pressed { background-color: rgb(172, 229, 0); } + +/* Content / Pages */ +#app_pages { + background-color: transparent; +} +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +ScrollBars */ +QScrollBar:horizontal { + border: none; + background: rgb(52, 59, 72); + height: 8px; + margin: 0px 21px 0 21px; + border-radius: 0px; +} +QScrollBar::handle:horizontal { + background: rgb(47, 48, 50); + min-width: 25px; + border-radius: 4px +} +QScrollBar::add-line:horizontal { + border: none; + background: rgb(55, 63, 77); + width: 20px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + subcontrol-position: right; + subcontrol-origin: margin; +} +QScrollBar::sub-line:horizontal { + border: none; + background: rgb(55, 63, 77); + width: 20px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + subcontrol-position: left; + subcontrol-origin: margin; +} +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal +{ + background: none; +} +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal +{ + background: none; +} + QScrollBar:vertical { + border: none; + background: rgb(52, 59, 72); + width: 8px; + margin: 21px 0 21px 0; + border-radius: 0px; + } + QScrollBar::handle:vertical { + background: rgb(47, 48, 50); + min-height: 25px; + border-radius: 4px + } + QScrollBar::add-line:vertical { + border: none; + background: transparent; + height: 10px; + border-radius: 4px; + subcontrol-position: bottom; + subcontrol-origin: margin; + } + QScrollBar::sub-line:vertical { + border: none; + background: transparent; + height: 10px; + border-radius: 4px; + subcontrol-position: top; + subcontrol-origin: margin; + } + QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; + } + + QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; + } + + + + + + 0 + + + 10 + + + 10 + + + 10 + + + 10 + + + + + #bg_app { border-radius: 10px; } + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 50 + 50 + + + + + 50 + 50 + + + + + + + + + 0 + 50 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 50 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 5 + + + QLayout::SetMinAndMaxSize + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + + + + 243 + 0 + + + + + 243 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 105 + + + + + 16777215 + 105 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + 0 + 40 + + + + + 16777215 + 40 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 10 + + + 0 + + + 10 + + + 0 + + + + + + 0 + 30 + + + + + 16777215 + 40 + + + + Search messages + + + + + + + + + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 240 + 524 + + + + + 0 + + + 0 + + + 5 + + + 0 + + + 5 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 0 + 65 + + + + + 16777215 + 65 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 15 + + + 0 + + + 10 + + + 0 + + + + + + 0 + 35 + + + + + 16777215 + 35 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 10 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 30 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 2 + + + 0 + + + 2 + + + + + Signal 80% + + + + + + + PyBlackBOX server signal + + + + + + + + + + + + + + + + + + + + Segoe UI + 9 + false + false + PreferAntialias + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 45 + + + + + 16777215 + 45 + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + + 100 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 28 + 28 + + + + + 28 + 28 + + + + + Segoe UI + 9 + false + false + NoAntialias + + + + PointingHandCursor + + + Minimize + + + background-image: url(:/icons_svg/images/icons_svg/icon_minimize.svg); + + + + + + + 20 + 20 + + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + + Segoe UI + 9 + false + false + PreferDefault + + + + PointingHandCursor + + + Maximize + + + background-image: url(:/icons_svg/images/icons_svg/icon_maximize.svg); + + + + + + + 20 + 20 + + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + PointingHandCursor + + + Close + + + background-image: url(:/icons_svg/images/icons_svg/icon_close.svg); + + + + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + + + + background-color: transparent; + + + 1 + + + + #home { + background-position: center; + background-repeat: no-repeat; + background-image: url(:/images_svg/images/images_svg/logo_home.svg); +} + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/page_messages.ui b/page_messages.ui new file mode 100644 index 0000000..8479cee --- /dev/null +++ b/page_messages.ui @@ -0,0 +1,515 @@ + + + chat_page + + + + 0 + 0 + 880 + 616 + + + + Form + + + QWidget { color: rgb(165, 165, 165); } +#chat_page{ + background-color: rgb(0, 0, 0); +} +/* TOP */ +#top { + background-color: rgb(30, 32, 33); + border-radius: 10px; +} +#user_name { + color: rgb(179, 179, 179); + font: 600 12pt "Segoe UI"; +} +#user_image { + border: 1px solid rgb(30, 32, 33); + background-color: rgb(47, 48, 50); + border-radius: 20px; +} +#top QPushButton { + background-color: rgb(47, 48, 50); + border-radius: 20px; + background-repeat: no-repeat; + background-position: center; +} +#top QPushButton:hover { + background-color: rgb(61, 62, 65); +} +#top QPushButton:pressed { + background-color: rgb(16, 17, 18); +} +#btn_attachment_top { + background-image: url(:/icons_svg/images/icons_svg/icon_attachment.svg); +} +#btn_more_top { + background-image: url(:/icons_svg/images/icons_svg/icon_more_options.svg); +} +/* BOTTOM */ +#bottom QPushButton { + background-color: rgb(47, 48, 50); + border-radius: 20px; + background-repeat: no-repeat; + background-position: center; +} +#bottom QPushButton:hover { + background-color: rgb(61, 62, 65); +} +#bottom QPushButton:pressed { + background-color: rgb(16, 17, 18); +} +#send_message_frame { + background-color: rgb(47, 48, 50); + border-radius: 20px; +} +#send_message_frame QPushButton { + background-color: rgb(76, 77, 80); + border-radius: 15px; + background-repeat: no-repeat; + background-position: center; +} +#send_message_frame QPushButton:hover { + background-color: rgb(81, 82, 86); +} +#send_message_frame QPushButton:pressed { + background-color: rgb(16, 17, 18); +} +#line_edit_message { + background-color: transparent; + selection-color: rgb(255, 255, 255); + selection-background-color: rgb(149, 199, 0); + border: none; + padding-left: 15px; + padding-right: 15px; + background-repeat: none; + background-position: left center; + font: 10pt "Segoe UI"; + color: rgb(94, 96, 100); +} +#line_edit_message:focus { + color: rgb(165, 165, 165); +} +#btn_emoticon{ + background-image: url(:/icons_svg/images/icons_svg/icon_emoticons.svg); +} +#btn_send_message{ + background-image: url(:/icons_svg/images/icons_svg/icon_send.svg); +} +#btn_attachment_bottom{ + + background-image: url(:/icons_svg/images/icons_svg/icon_more_options.svg); +} + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + + + + Qt::AlignCenter + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 22 + + + + User name + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + background: transparent; + + + User description + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + connected last time 24h ago + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + PointingHandCursor + + + + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + PointingHandCursor + + + + + + + + + + + + + background: transparent + + + QFrame::NoFrame + + + QFrame::Raised + + + Qt::ScrollBarAlwaysOff + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 862 + 486 + + + + background: transparent + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 0 + 40 + + + + + 16777215 + 40 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 10 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 5 + + + 0 + + + 5 + + + 0 + + + + + + 30 + 30 + + + + + 30 + 30 + + + + PointingHandCursor + + + + + + + + + + + 0 + 40 + + + + Message #user + + + + + + + + 30 + 30 + + + + + 30 + 30 + + + + PointingHandCursor + + + + + + + + + + + + + + 40 + 40 + + + + + 40 + 40 + + + + PointingHandCursor + + + + + + + + + + + + + + + + diff --git a/resources.qrc b/resources.qrc new file mode 100644 index 0000000..9f79409 --- /dev/null +++ b/resources.qrc @@ -0,0 +1,33 @@ + + + images/images_svg/logo_home.svg + images/images_svg/logo_symbol_top.svg + images/images_svg/text_logo.svg + + + images/icons_svg/icon_busy.svg + images/icons_svg/icon_idle.svg + images/icons_svg/icon_invisible.svg + images/icons_svg/icon_online.svg + images/icons_svg/icon_search.svg + images/icons_svg/icon_add_user.svg + images/icons_svg/icon_attachment.svg + images/icons_svg/icon_close.svg + images/icons_svg/icon_emoticons.svg + images/icons_svg/icon_maximize.svg + images/icons_svg/icon_minimize.svg + images/icons_svg/icon_more_options.svg + images/icons_svg/icon_restore.svg + images/icons_svg/icon_send.svg + images/icons_svg/icon_settings.svg + images/icons_svg/icon_signal.svg + + + images/users/cat.png + images/users/cat_150px.png + images/users/me.png + images/users/me_150px.png + images/users/mouse.png + images/users/mouse_150px.png + + diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..c7029b6 --- /dev/null +++ b/settings.json @@ -0,0 +1,19 @@ +{ + "app_name": "PyBlackBOX - Free GUI 2", + "custom_title_bar": true, + "startup_size": [ + 1400, + 800 + ], + "minimum_size": [ + 960, + 540 + ], + "left_menu": { + "color": "#FF000000", + "color_hover": "#151617", + "color_pressed": "#ACE500", + "icon_color": "#E6E6E6", + "icon_color_pressed": "#151617" + } +} \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..7c6fef2 --- /dev/null +++ b/setup.py @@ -0,0 +1,33 @@ +import sys +import os +from cx_Freeze import setup, Executable +# Packages +from app.packages.pyside_or_pyqt import * # Qt +from app.packages.widgets import * # Widgets +# GUIs +from app.uis.login.ui_login import Ui_Login # Login / Splash Screen +from app.uis.main_window.ui_main import Ui_MainWindow # MainWindow +from app.uis.chat.page_messages import Chat # Chat Widget +# Modules +import app.modules.ui_functions.functions as ui_functions +import app.modules.app_settings.settings as app_settings + +# ADD FILES/FOLDERS +files = ['icon.ico', 'settings.json','images/'] + +# TARGET +target = Executable( + script="main.py", + base="Win32GUI", + icon="icon.ico" +) + +# SETUP CX FREEZE +setup( + name = "PyBlackBOX", + version = "1.0", + description = "Modern GUI for desktop chat", + author = "Wanderson M. Pimenta", + options = {'build_exe' : {'include_files' : files}}, + executables = [target] +)