Add a new dialog to get database settings. Fixes: #5
Added a new dialog for database settings. Updated dbConfig to use QSettings.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
from datetime import date
|
||||
|
||||
from PySide6.QtCore import QSettings
|
||||
from pony.orm import ( # type: ignore[import-untyped]
|
||||
Database,
|
||||
LongStr,
|
||||
@@ -11,11 +11,8 @@ from pony.orm import ( # type: ignore[import-untyped]
|
||||
set_sql_debug,
|
||||
)
|
||||
|
||||
db = Database
|
||||
|
||||
db = Database()
|
||||
|
||||
|
||||
class Cases(db.Entity): # type: ignore[name-defined]
|
||||
case_id = PrimaryKey(int, auto=True)
|
||||
docket_id = Required(str)
|
||||
@@ -50,13 +47,18 @@ class History(db.Entity): # type: ignore[name-defined]
|
||||
number = Required(int)
|
||||
|
||||
|
||||
def updateDatabase(settings: QSettings) -> None:
|
||||
set_sql_debug(True)
|
||||
engine = settings.value('engine')
|
||||
if engine not in ['QMYSQL', 'MARIADB']:
|
||||
raise Exception(f"Unknown database engine: {engine}")
|
||||
db.bind(
|
||||
provider="mysql",
|
||||
user="scotus",
|
||||
host="ceph5",
|
||||
database="scotus",
|
||||
password="lechOtvirf8Om/",
|
||||
user=settings.value('user'),
|
||||
host=settings.value('hostname'),
|
||||
database=settings.value('databasename'),
|
||||
password=settings.value('password'),
|
||||
)
|
||||
db.generate_mapping(create_tables=True)
|
||||
db.disconnect()
|
||||
return
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
#!venv/bin/python3
|
||||
import faulthandler
|
||||
import sys
|
||||
from typing import cast
|
||||
|
||||
from PySide6.QtCore import QSettings
|
||||
from PySide6.QtCore import QFile
|
||||
from PySide6.QtSql import (
|
||||
QSqlDatabase,
|
||||
)
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QDialog,
|
||||
QMainWindow,
|
||||
)
|
||||
|
||||
from lib.dbConfig import updateDatabase
|
||||
from lib.utils import openSettings
|
||||
from setupDialog import setupDialog
|
||||
|
||||
faulthandler.enable()
|
||||
|
||||
@@ -21,16 +26,25 @@ def main() -> int:
|
||||
#
|
||||
app = QApplication(sys.argv)
|
||||
settings = openSettings('database')
|
||||
file = QFile(settings.fileName())
|
||||
if not file.exists():
|
||||
result = setupDialog().exec()
|
||||
if result == QDialog.DialogCode.Rejected:
|
||||
print(f"We require database credentials")
|
||||
return(2)
|
||||
updateDatabase(settings)
|
||||
db = QSqlDatabase.addDatabase("QMYSQL")
|
||||
db.setHostName(settings.value("hostname"))
|
||||
portStr = cast(str, settings.value('port', '3306'))
|
||||
db.setPort(int(portStr))
|
||||
db.setDatabaseName(settings.value("databasename","scotus")) # type: ignore
|
||||
db.setUserName(settings.value("user","scotus")) # type: ignore
|
||||
db.setPassword(settings.value("password"))
|
||||
settings.endGroup()
|
||||
db.open()
|
||||
import lib.dbConfig
|
||||
|
||||
window = MainWindow()
|
||||
assert isinstance(window, QMainWindow)
|
||||
return app.exec()
|
||||
|
||||
|
||||
|
||||
67
setupDialog.py
Normal file
67
setupDialog.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from PySide6.QtCore import Slot, Qt
|
||||
from PySide6.QtGui import QPalette
|
||||
from PySide6.QtWidgets import QDialog, QStatusBar, QVBoxLayout, QWidget
|
||||
|
||||
from lib.utils import openSettings
|
||||
from ui.dbSetup import Ui_setupDialog
|
||||
|
||||
class setupDialog(QDialog,Ui_setupDialog):
|
||||
def __init__(self, parent: QWidget | None = None):
|
||||
super(setupDialog,self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.sqliteEdit.setEnabled(False)
|
||||
|
||||
layout = self.layout()
|
||||
assert isinstance(layout, QVBoxLayout)
|
||||
self.statusBar = QStatusBar(self)
|
||||
self.statusBar.setObjectName('statusBar')
|
||||
where = layout.indexOf(self.buttonBox)
|
||||
layout.insertWidget(where, self.statusBar)
|
||||
self.pwEdit.editingFinished.connect(self.pwDone)
|
||||
self.pwConfirmEdit.editingFinished.connect(self.pwDone)
|
||||
return
|
||||
|
||||
@Slot()
|
||||
def pwDone(self):
|
||||
pw = self.pwEdit.text()
|
||||
confirm = self.pwConfirmEdit.text()
|
||||
|
||||
if pw != confirm:
|
||||
palette = self.statusBar.palette()
|
||||
palette.setColor(QPalette.ColorRole.WindowText, Qt.GlobalColor.red)
|
||||
self.statusBar.setPalette(palette)
|
||||
self.statusBar.showMessage("Password doesn't match")
|
||||
self.pwGood = False
|
||||
else:
|
||||
self.statusBar.clearMessage()
|
||||
self.pwGood = True
|
||||
return
|
||||
|
||||
@Slot(int) # type: ignore
|
||||
def done(self, r:int) -> None:
|
||||
if r == QDialog.DialogCode.Rejected:
|
||||
super(setupDialog,self).done(r)
|
||||
return
|
||||
self.pwDone()
|
||||
if not self.pwGood:
|
||||
return
|
||||
super(setupDialog,self).done(r)
|
||||
return
|
||||
|
||||
@Slot()
|
||||
def accept(self) -> None:
|
||||
settings=openSettings('database')
|
||||
settings.setValue('hostname', self.hostEdit.text())
|
||||
settings.setValue('databasename', self.dbEdit.text())
|
||||
settings.setValue('user',self.userEdit.text())
|
||||
settings.setValue('password', self.pwEdit.text())
|
||||
settings.setValue('port', self.portEdit.text())
|
||||
if self.comboBox.currentIndex() == 0:
|
||||
settings.setValue('engine', 'QMYSQL')
|
||||
elif self.comboBox.currentIndex() == 1:
|
||||
settings.setValue('engine', 'QSQLITE')
|
||||
# Other types: QDB2, QIBASE, QOCI, QODBC, QPSQL, QMIMER
|
||||
else:
|
||||
print("Bad Database Type")
|
||||
settings.sync()
|
||||
return super().accept()
|
||||
176
ui/dbSetup.py
Normal file
176
ui/dbSetup.py
Normal file
@@ -0,0 +1,176 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'dbSetup.ui'
|
||||
##
|
||||
## Created by: Qt User Interface Compiler version 6.8.2
|
||||
##
|
||||
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
################################################################################
|
||||
|
||||
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
||||
QMetaObject, QObject, QPoint, QRect,
|
||||
QSize, QTime, QUrl, Qt)
|
||||
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
|
||||
QCursor, QFont, QFontDatabase, QGradient,
|
||||
QIcon, QImage, QKeySequence, QLinearGradient,
|
||||
QPainter, QPalette, QPixmap, QRadialGradient,
|
||||
QTransform)
|
||||
from PySide6.QtWidgets import (QAbstractButton, QApplication, QComboBox, QDialog,
|
||||
QDialogButtonBox, QFormLayout, QLabel, QLineEdit,
|
||||
QSizePolicy, QStackedWidget, QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_setupDialog(object):
|
||||
def setupUi(self, setupDialog):
|
||||
if not setupDialog.objectName():
|
||||
setupDialog.setObjectName(u"setupDialog")
|
||||
setupDialog.resize(400, 300)
|
||||
self.actionBrowse = QAction(setupDialog)
|
||||
self.actionBrowse.setObjectName(u"actionBrowse")
|
||||
icon = QIcon(QIcon.fromTheme(u"folder-open"))
|
||||
self.actionBrowse.setIcon(icon)
|
||||
self.actionBrowse.setMenuRole(QAction.MenuRole.NoRole)
|
||||
self.verticalLayout = QVBoxLayout(setupDialog)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.comboBox = QComboBox(setupDialog)
|
||||
self.comboBox.addItem("")
|
||||
self.comboBox.addItem("")
|
||||
self.comboBox.setObjectName(u"comboBox")
|
||||
|
||||
self.verticalLayout.addWidget(self.comboBox)
|
||||
|
||||
self.stackedWidget = QStackedWidget(setupDialog)
|
||||
self.stackedWidget.setObjectName(u"stackedWidget")
|
||||
self.mariadb = QWidget()
|
||||
self.mariadb.setObjectName(u"mariadb")
|
||||
self.formLayout = QFormLayout(self.mariadb)
|
||||
self.formLayout.setObjectName(u"formLayout")
|
||||
self.label = QLabel(self.mariadb)
|
||||
self.label.setObjectName(u"label")
|
||||
|
||||
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label)
|
||||
|
||||
self.hostEdit = QLineEdit(self.mariadb)
|
||||
self.hostEdit.setObjectName(u"hostEdit")
|
||||
|
||||
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.hostEdit)
|
||||
|
||||
self.label_2 = QLabel(self.mariadb)
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2)
|
||||
|
||||
self.portEdit = QLineEdit(self.mariadb)
|
||||
self.portEdit.setObjectName(u"portEdit")
|
||||
|
||||
self.formLayout.setWidget(1, QFormLayout.FieldRole, self.portEdit)
|
||||
|
||||
self.label_3 = QLabel(self.mariadb)
|
||||
self.label_3.setObjectName(u"label_3")
|
||||
|
||||
self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3)
|
||||
|
||||
self.dbEdit = QLineEdit(self.mariadb)
|
||||
self.dbEdit.setObjectName(u"dbEdit")
|
||||
|
||||
self.formLayout.setWidget(2, QFormLayout.FieldRole, self.dbEdit)
|
||||
|
||||
self.label_4 = QLabel(self.mariadb)
|
||||
self.label_4.setObjectName(u"label_4")
|
||||
|
||||
self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_4)
|
||||
|
||||
self.userEdit = QLineEdit(self.mariadb)
|
||||
self.userEdit.setObjectName(u"userEdit")
|
||||
|
||||
self.formLayout.setWidget(3, QFormLayout.FieldRole, self.userEdit)
|
||||
|
||||
self.label_5 = QLabel(self.mariadb)
|
||||
self.label_5.setObjectName(u"label_5")
|
||||
|
||||
self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_5)
|
||||
|
||||
self.pwEdit = QLineEdit(self.mariadb)
|
||||
self.pwEdit.setObjectName(u"pwEdit")
|
||||
self.pwEdit.setEchoMode(QLineEdit.EchoMode.Password)
|
||||
|
||||
self.formLayout.setWidget(4, QFormLayout.FieldRole, self.pwEdit)
|
||||
|
||||
self.label_7 = QLabel(self.mariadb)
|
||||
self.label_7.setObjectName(u"label_7")
|
||||
|
||||
self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_7)
|
||||
|
||||
self.pwConfirmEdit = QLineEdit(self.mariadb)
|
||||
self.pwConfirmEdit.setObjectName(u"pwConfirmEdit")
|
||||
self.pwConfirmEdit.setEchoMode(QLineEdit.EchoMode.Password)
|
||||
|
||||
self.formLayout.setWidget(5, QFormLayout.FieldRole, self.pwConfirmEdit)
|
||||
|
||||
self.stackedWidget.addWidget(self.mariadb)
|
||||
self.sqlite = QWidget()
|
||||
self.sqlite.setObjectName(u"sqlite")
|
||||
self.formLayout_2 = QFormLayout(self.sqlite)
|
||||
self.formLayout_2.setObjectName(u"formLayout_2")
|
||||
self.label_6 = QLabel(self.sqlite)
|
||||
self.label_6.setObjectName(u"label_6")
|
||||
|
||||
self.formLayout_2.setWidget(0, QFormLayout.LabelRole, self.label_6)
|
||||
|
||||
self.sqliteEdit = QLineEdit(self.sqlite)
|
||||
self.sqliteEdit.setObjectName(u"sqliteEdit")
|
||||
|
||||
self.formLayout_2.setWidget(0, QFormLayout.FieldRole, self.sqliteEdit)
|
||||
|
||||
self.stackedWidget.addWidget(self.sqlite)
|
||||
|
||||
self.verticalLayout.addWidget(self.stackedWidget)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(setupDialog)
|
||||
self.buttonBox.setObjectName(u"buttonBox")
|
||||
self.buttonBox.setOrientation(Qt.Orientation.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Cancel|QDialogButtonBox.StandardButton.Ok)
|
||||
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
|
||||
#if QT_CONFIG(shortcut)
|
||||
self.label.setBuddy(self.hostEdit)
|
||||
self.label_2.setBuddy(self.portEdit)
|
||||
self.label_3.setBuddy(self.dbEdit)
|
||||
self.label_4.setBuddy(self.userEdit)
|
||||
self.label_5.setBuddy(self.pwEdit)
|
||||
self.label_7.setBuddy(self.pwConfirmEdit)
|
||||
#endif // QT_CONFIG(shortcut)
|
||||
|
||||
self.retranslateUi(setupDialog)
|
||||
self.buttonBox.accepted.connect(setupDialog.accept)
|
||||
self.buttonBox.rejected.connect(setupDialog.reject)
|
||||
self.comboBox.currentIndexChanged.connect(self.stackedWidget.setCurrentIndex)
|
||||
|
||||
self.stackedWidget.setCurrentIndex(0)
|
||||
|
||||
|
||||
QMetaObject.connectSlotsByName(setupDialog)
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, setupDialog):
|
||||
setupDialog.setWindowTitle(QCoreApplication.translate("setupDialog", u"setupDialog", None))
|
||||
self.actionBrowse.setText("")
|
||||
#if QT_CONFIG(tooltip)
|
||||
self.actionBrowse.setToolTip(QCoreApplication.translate("setupDialog", u"Browse for database file", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.comboBox.setItemText(0, QCoreApplication.translate("setupDialog", u"MariaDB/MySQL", None))
|
||||
self.comboBox.setItemText(1, QCoreApplication.translate("setupDialog", u"SQLite", None))
|
||||
|
||||
self.label.setText(QCoreApplication.translate("setupDialog", u"Host", None))
|
||||
self.label_2.setText(QCoreApplication.translate("setupDialog", u"Port", None))
|
||||
self.portEdit.setText(QCoreApplication.translate("setupDialog", u"3306", None))
|
||||
self.label_3.setText(QCoreApplication.translate("setupDialog", u"Database Name", None))
|
||||
self.dbEdit.setText(QCoreApplication.translate("setupDialog", u"scotus", None))
|
||||
self.label_4.setText(QCoreApplication.translate("setupDialog", u"User Name", None))
|
||||
self.userEdit.setText(QCoreApplication.translate("setupDialog", u"scotus", None))
|
||||
self.label_5.setText(QCoreApplication.translate("setupDialog", u"Password", None))
|
||||
self.label_7.setText(QCoreApplication.translate("setupDialog", u"Confirm", None))
|
||||
self.label_6.setText(QCoreApplication.translate("setupDialog", u"Datbase File", None))
|
||||
# retranslateUi
|
||||
|
||||
231
ui/dbSetup.ui
Normal file
231
ui/dbSetup.ui
Normal file
@@ -0,0 +1,231 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>setupDialog</class>
|
||||
<widget class="QDialog" name="setupDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>setupDialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>MariaDB/MySQL</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SQLite</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="mariadb">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>hostEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="hostEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>portEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="portEdit">
|
||||
<property name="text">
|
||||
<string>3306</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Database Name</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>dbEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="dbEdit">
|
||||
<property name="text">
|
||||
<string>scotus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>User Name</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>userEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="userEdit">
|
||||
<property name="text">
|
||||
<string>scotus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pwEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="pwEdit">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::EchoMode::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Confirm</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pwConfirmEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="pwConfirmEdit">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::EchoMode::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="sqlite">
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Datbase File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="sqliteEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionBrowse">
|
||||
<property name="icon">
|
||||
<iconset theme="folder-open"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Browse for database file</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>setupDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>227</x>
|
||||
<y>278</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>setupDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>295</x>
|
||||
<y>284</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>comboBox</sender>
|
||||
<signal>currentIndexChanged(int)</signal>
|
||||
<receiver>stackedWidget</receiver>
|
||||
<slot>setCurrentIndex(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>22</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>149</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user