From cd565ec57d5894756c7fb3024cc36c10578610b5 Mon Sep 17 00:00:00 2001 From: KenanZhu <3471685733@qq.com> Date: Sat, 22 Nov 2025 14:29:01 +0800 Subject: [PATCH] feat(gui.SeatMapWidget): add seat select map widget --- gui/ALConfigWidget.py | 38 ++++++ gui/SeatFrame.py | 99 ++++++++++++++++ gui/SeatMapTable.py | 270 ++++++++++++++++++++++++++++++++++++++++++ gui/SeatMapWidget.py | 252 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 659 insertions(+) create mode 100644 gui/SeatFrame.py create mode 100644 gui/SeatMapTable.py create mode 100644 gui/SeatMapWidget.py diff --git a/gui/ALConfigWidget.py b/gui/ALConfigWidget.py index 7e5404e..160d858 100644 --- a/gui/ALConfigWidget.py +++ b/gui/ALConfigWidget.py @@ -19,7 +19,9 @@ from PySide6.QtWidgets import ( from PySide6.QtGui import QCloseEvent from .Ui_ALConfigWidget import Ui_ALConfigWidget +from .SeatMapWidget import SeatMapWidget +from .SeatMapTable import seats_maps from ConfigReader import ConfigReader from ConfigWriter import ConfigWriter @@ -66,6 +68,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget): self.ShowPasswordCheckBox.clicked.connect(self.onShowPasswordCheckBoxChecked) self.FloorComboBox.currentIndexChanged.connect(self.onFloorComboBoxCurrentIndexChanged) + self.SelectSeatsButton.clicked.connect(self.onSelectSeatsButtonClicked) self.UserListWidget.currentItemChanged.connect(self.onUserListWidgetCurrentItemChanged) self.AddUserButton.clicked.connect(self.onAddUserButtonClicked) self.DelUserButton.clicked.connect(self.onDelUserButtonClicked) @@ -602,6 +605,41 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget): self.RoomComboBox.addItems(self.__floor_room_map[floor]) self.RoomComboBox.setCurrentIndex(0) + @Slot() + def onSeatMapWidgetClosed( + self, + selected_seats: list[str] + ): + + self.__seat_map_widget.seatMapWidgetClosed.disconnect(self.onSeatMapWidgetClosed) + self.__seat_map_widget.deleteLater() + self.__seat_map_widget = None + if len(selected_seats) == 0: + return + self.SeatIDEdit.setText(",".join(selected_seats)) + + @Slot() + def onSelectSeatsButtonClicked( + self + ): + + floor = self.FloorComboBox.currentText() + room = self.RoomComboBox.currentText() + floor_idx = self.__floor_rmap[floor] + room_idx = self.__room_rmap[room] + if self.__seat_map_widget is None: + self.__seat_map_widget = SeatMapWidget( + self, + floor, + room, + seats_maps[floor_idx][room_idx] + ) + self.__seat_map_widget.seatMapWidgetClosed.connect(self.onSeatMapWidgetClosed) + self.__seat_map_widget.show() + self.__seat_map_widget.raise_() + self.__seat_map_widget.activateWindow() + self.__seat_map_widget.selectSeats(self.SeatIDEdit.text().split(",")) + @Slot() def onUserListWidgetCurrentItemChanged( self, diff --git a/gui/SeatFrame.py b/gui/SeatFrame.py new file mode 100644 index 0000000..ae1a393 --- /dev/null +++ b/gui/SeatFrame.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +""" +Copyright (c) 2025 KenanZhu. +All rights reserved. + +This software is provided "as is", without any warranty of any kind. +You may use, modify, and distribute this file under the terms of the MIT License. +See the LICENSE file for details. +""" +from PySide6.QtCore import ( + Qt, Signal +) +from PySide6.QtWidgets import ( + QFrame, QLabel +) + + +class SeatFrame(QFrame): + + clicked = Signal(str) + + def __init__( + self, + seat_number, + parent=None + ): + + super().__init__(parent) + self.__seat_number = seat_number + self.__is_selected = False + self.setUpUi() + + def setUpUi( + self + ): + + self.setFixedSize(60, 40) + self.setFrameStyle(QFrame.Box | QFrame.Plain) + self.setLineWidth(2) + self.setStyleSheet(""" + QFrame { + background-color: #4196EB; + border: 2px solid #4196EB; + border-radius: 5px; + } + QLabel { + color: #F0F0F0; + font-weight: bold; + } + """) + self.label = QLabel(self.__seat_number, self) + self.label.setAlignment(Qt.AlignCenter) + self.label.setGeometry(0, 0, 60, 40) + + def mousePressEvent( + self, + event + ): + + if event.button() == Qt.LeftButton: + self.toggleSelection() + self.clicked.emit(self.__seat_number) + + + def isSelected( + self + ): + + return self.__is_selected + + + def toggleSelection(self): + + self.__is_selected = not self.__is_selected + if self.__is_selected: + self.setStyleSheet(""" + QFrame { + background-color: #4CAF50; + border: 2px solid #388E3C; + border-radius: 5px; + color: white; + } + QLabel { + color: #F0F0F0; + font-weight: bold; + } + """) + else: + self.setStyleSheet(""" + QFrame { + background-color: #4196EB; + border: 2px solid #4196EB; + border-radius: 5px; + } + QLabel { + color: #F0F0F0; + font-weight: bold; + } + """) \ No newline at end of file diff --git a/gui/SeatMapTable.py b/gui/SeatMapTable.py new file mode 100644 index 0000000..9210351 --- /dev/null +++ b/gui/SeatMapTable.py @@ -0,0 +1,270 @@ +seats_maps = { + "2": { + "1": """ +,,,,,,,,,,,039A,039B,,040A,040B,,041A,041B,,042A,042B,,043A,043B,,044A,044B,,,,,,,,, +,,,,,,,,,,,039C,039D,,040C,040D,,041C,041D,,042C,042D,,043C,043D,,044C,044D,,,,,,,,, +038B,038D,,037B,037D,,036B,036D,,,,,,,,,,,,,,,,,,,,,,045C,045A,,046C,046A,,047C,047A +038A,038C,,037A,037C,,036A,036C,,,,,,,,,,,,,,,,,,,,,,045D,045B,,046D,046B,,047D,047B +035B,035D,,034B,034D,,033B,033D,,,,,,,,,,,,,,,,,,,,,,048C,048A,,049C,049A,,050C,050A +035A,035C,,034A,034C,,033A,033C,,,,,,,,,,,,,,,,,,,,,,048D,048B,,049D,049B,,050D,050B +032B,032D,,031B,031D,,030B,030D,,,,,,,,,,,,,,,,,,,,,,051C,051A,,052C,052A,,053C,053A +032A,032C,,031A,031C,,030A,030C,,,,,,,,,,,,,,,,,,,,,,051D,051B,,052D,052B,,053D,053B +029B,029D,,028B,028D,,027B,027D,,,,,,,,,,,,,,,,,,,,,,054C,054A,,055C,055A,,056C,056A +029A,029C,,028A,028C,,027A,027C,,,,,,,,,,,,,,,,,,,,,,054D,054B,,055D,055B,,056D,056B +026B,026D,,025B,025D,,024B,024D,,,,,,,,,,,,,,,,,,,,,,057C,057A,,058C,058A,,059C,059A +026A,026C,,025A,025C,,024A,024C,,,,,,,,,,,,,,,,,,,,,,057D,057B,,058D,058B,,059D,059B +023B,023D,,022B,022D,,021B,021D,,,,,,,,,,,,,,,,,,,,,,060C,060A,,061C,061A,,062C,062A +023A,023C,,022A,022C,,021A,021C,,,,,,,,,,,,,,,,,,,,,,060D,060B,,061D,061B,,062D,062B +020B,020D,,019B,019D,,018B,018D,,,,,,,,,,,,,,,,,,,,,,063C,063A,,064C,064A,,065C,065A +020A,020C,,019A,019C,,018A,018C,,,,,,,,,,,,,,,,,,,,,,063D,063B,,064D,064B,,065D,065B +,,,,,,,,,,,017D,017C,,014D,014C,,011D,011C,,008D,008C,,005D,005C,,002D,002C,001D,001C,,,,,,, +,,,,,,,,,,,017B,017A,,014B,014A,,011B,011A,,008B,008A,,005B,005A,,002B,002A,001B,001A,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,073D,073C,,015D,015C,,012D,012C,,,,,006D,006C,,003D,003C,,,,,,,,, +,,,,,,,,,,,073B,073A,,015B,015A,,012B,012A,,,,,006B,006A,,003B,003A,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,072D,072C,,016D,016C,,013D,013C,,,,,007D,007C,,004D,004C,,,,,,,,, +,,,,,,,,,,,072B,072A,,016B,016A,,013B,013A,,,,,007B,007A,,004B,004A,,,,,,,,, +,,,,,,,,,,,071D,071C,,070D,070C,,069D,069C,,068D,068C,,067D,067C,,066D,066C,,,,,,,,, +,,,,,,,,,,,071B,071A,,070B,070A,,069B,069A,,068B,068A,,067B,067A,,066B,066A,,,,,,,,, +""", + "2": """ +023B,023D,024B,024D,,,,,,,,,,,,,,, +023A,023C,024A,024C,,,,,,,,,,,,,,, +022B,022D,032D,032C,,,,,,,,,,,,,,, +022A,022C,032B,032A,,,,,,,,,,,,,,, +021B,021D,,,,,,,,,,,,,,,,, +021A,021C,,,,,,,,,,,,,,,,, +020B,020D,,,,,,,,,,,,,,,,, +020A,020C,,,,,,,,,,,,,,,,, +019B,019D,,,,,,,,,,,,,,,,, +019A,019C,,,,,,,,,,,,,,,,, +018B,018D,,,,,,,,,,,,,,,,, +018A,018C,,,,,,,,,,,,,,,,, +017B,017D,,,,,,,,,,,,,,,,, +017A,017C,,,,,,,,,,,,,,,,, +016B,016D,,,,,,,,,,,,,,,,, +016A,016C,,,,,031A,031C,,,,,,,,,,, +015B,015D,,,,,030B,030D,,,,,,,,,,, +015A,015C,,,,,030A,030C,,,,,,,,,,, +014B,014D,,,,,029B,029D,,,,,,,,,,, +014A,014C,,,,,029A,029C,,,,,,,,,,, +013B,013D,,,,,028B,028D,,,,,,,,,,, +013A,013C,,,,,028A,028C,,,,,,,,,,, +012B,012D,,,,,027B,027D,,,,,,,,,,, +012A,012C,,,,,027A,027C,,,,,,,,,,, +011B,011D,,,,,026B,026D,,,,,,,,,,, +011A,011C,,,,,026A,026C,,,,,,,,,,, +010B,010D,,,,,025B,025D,,,,,,,,,,, +010A,010C,,,,,,,,,,,,,,,,, +009B,009D,,,,,,,,,,,,,,,,, +009A,009C,,,,,,,,,,,,,,,,, +008B,008D,,,,,,,,,,,,,,,,, +008A,008C,,,,,,,,,,,,,,,,, +007B,007D,,,,,,,,,,,,,,,,, +007A,007C,,,,,,,,,,,,,,,,, +006B,006D,,,,,,,,,,,,,,,,, +006A,006C,,,,,,,,,,,,,,,,, +005B,005D,,,,,,,,,,,,,,,,, +005A,005C,,,,,,,,,,,,,,,,, +004D,004C,003D,003C,002D,002C,001D,001C,,,,,,,,,,, +004B,004A,003B,003A,002B,002A,001B,001A,,,,,,,,,,, + +""" + }, + "3": { + "3": """ +,,007B,007D,,,,,,,,008C,008A,, +,,007A,007C,,,,,,,,008D,008B,, +,,006B,006D,,,,,,,,009C,009A,, +,,006A,006C,,,,,,,,009D,009B,, +,,005B,005D,,,,,,,,010C,010a,, +,,005A,005C,,,,,,,,010D,010B,, +,,004B,004D,,,,,,,,011C,011A,, +,,004A,004C,,,,,,,,011D,011B,, +,,003B,003D,,,,,,,,012C,012A,, +,,003A,003C,,,,,,,,012D,012B,, +,,002B,002D,,,,,,,,013C,013A,, +,,002A,002C,,,,,,,,013D,013B,, +,,001B,001D,,,,,,,,014C,014A,, +,,001A,001C,,,,,,,,014D,014B,, +""", + "4": """ +,,037D,037C,038D,038C,039D,039C,040D,040C,041D,041C,042D,042C,043D,043C,044D,044C,045D,045C,,,046D,046C,047D,047C,048D,048C,049D,049C,050D,050C,051D,051C,052D,052C,053D,053C,054D,054C,055D,055C,056D,056C,057D,057C,, +,,037B,037A,038B,038A,039B,039A,040B,040A,041B,041A,042B,042A,043B,043A,044B,044A,045B,045A,,,046B,046A,047B,047A,048B,048A,049B,049A,050B,050A,051B,051A,052B,052A,053B,053A,054B,054A,055B,055A,056B,056A,057B,057A,, +036B,036D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,058C,058A,,060C,060A +036A,036C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,058D,058B,,060D,060B +035B,035D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,059C,059A,,061C,061A +035A,035C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,059D,059B,,061D,061B +034B,034D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,062C,062A +034A,034C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,062D,062B +033B,033D,,,,,,,,,,,,080B,080D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,063C,063A +033A,033C,,,,,,,,,,,,080A,080C,,081A,081B,082A,082B,083A,083B,084A,084B,085A,085B,086A,086B,087A,,,,,,,,,,,,,,,,,,063D,063B +032B,032D,,,,,,,,,,,,079B,079D,,081C,081D,082C,082D,083C,083D,084C,084D,085C,085D,086C,086D,087C,,,,,,,,,,,,,,,,,,064C,064A +032A,032C,,,,,,,,,,,,079A,079C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,064D,064B +031B,031D,,,,,,,,,,,,078B,078D,,,,,,,,,,,,,,088A,088C,,,,,,,,,,,,,,,,,065C,065A +031A,031C,,,,,,,,,,,,078A,078C,,,,,,,,,,,,,,088B,088D,,,,,,,,,,,,,,,,,065D,065B +030B,030D,,,,,,,,,,,,077B,077D,,,,,,,,,,,,,,089A,089C,,,,,,,,,,,,,,,,,066C,066A +030A,030C,,,,,,,,,,,,077A,077C,,,,,,,,,,,,,,089B,089D,,,,,,,,,,,,,,,,,066D,066B +029B,029D,,,,,,,,,,,,076B,076D,,,,,,,,,,,,,,090A,090C,,,,,,,,,,,,,,,,,, +029A,029C,,,,,,,,,,,,076A,076C,,,,,,,,,,,,,,090B,090D,,,,,,,,,,,,,,,,,, +028B,028D,,,,,,,,,,,,075B,075D,,,,,,,,,,,,,,091A,091C,,,,,,,,,,,,,,,,,, +028A,028C,,,,,,,,,,,,075A,075C,,,,,,,,,,,,,,091B,091D,,,,,,,,,,,,,,,,,, +027B,027D,,,,,,,,,,,,074B,074D,,,,,,,,,,,,,,092A,092C,,,,,,,,,,,,,,,,,, +027A,027C,,,,,,,,,,,,,,,,,,,,,,,,,,,092B,092D,,,,,,,,,,,,,,,,,, +026B,026D,,,,,,,,,,,,,,,073D,073C,072D,072C,071D,071C,070D,070C,069D,069C,068D,068C,,,,,,,,,,,,,,,,,,,, +026A,026C,,,,,,,,,,,,,,,073B,073A,072B,072A,071B,071A,070B,070A,069B,069A,068B,068A,,,,,,,,,,,,,,,,,,,, +025B,025D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +025A,025C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +024B,024D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +024A,024C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +023B,023D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +023A,023C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,067C,, +022B,022D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,067B,, +022A,022C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,067A,, +,,021D,021C,020D,020C,019D,019C,018D,018C,017D,017C,016D,016C,015D,015C,014D,014C,013D,013C,012D,012C,011D,011C,010D,010C,009D,009C,008D,008C,007D,007C,006D,006C,005D,005C,004D,004C,003D,003C,002D,002C,001D,001C,,,, +,,021B,021A,020B,020A,019B,019A,018B,018A,017B,017A,016B,016A,015B,015A,014B,014A,013B,013A,012B,012A,011B,011A,010B,010A,009B,009A,008B,008A,007B,007a,006B,006A,005B,005A,004B,004A,003b,003A,002B,002A,001B,001A,,,, + +""" + }, + "4": { + "5": """ +,,,,,,,,042A,042B,045A,045B,048A,048B,051A,051B,054A,054B,057A,057B,060A,060B,,,,,, +,,,,,,,,042C,042D,045C,045D,048C,048D,051C,051D,054C,054D,057C,057D,060C,060D,,,,,, +,,,,,,,,041A,041B,044A,044B,047A,047B,050A,050B,053A,053B,056A,056B,059A,059B,,,,,, +,,,,,,,,041C,041D,044C,044D,047C,047D,050C,050D,053C,053D,056C,056D,059C,059D,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,040A,040B,043A,043B,046A,046B,049A,049B,052A,052B,055A,055B,058A,058B,,,,,, +,,,,,,,,040C,040D,043C,043D,046C,046D,049C,049D,052C,052D,055C,055D,058C,058D,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,, +,039B,039D,038B,038D,,037B,037D,,,,,,,,,,,,,,,,,,,,, +,039A,039C,038A,038C,,037A,037C,,,,,,,,,,,,,,,,,,,,, +,036B,036D,035B,035D,,034B,034D,,,,,,,,,,,,,,,,,,,,, +,036A,036C,035A,035C,,034A,034C,,,,,,,,,,,,,,,,,,,,, +,033B,033D,032B,032D,,031B,031D,,,,,,,,,,,,,,,,,,,,, +,033A,033C,032A,032C,,031A,031C,,,,,,,,,,,,,,,,,,,,, +,030B,030D,029B,029D,,028B,028D,,,,,,,,,,,,,,,,,,,,, +,030A,030C,029A,029C,,028A,028C,,,,,,,,,,,,,,,,,,,,, +,027B,027D,026B,026D,,025B,025D,,,,,,,,,,,,,,,,,,,,, +,027A,027C,026A,026C,,025A,025C,,,,,,,,,,,,,,,,,,,,, +,024B,024D,023B,023D,,022B,022D,,,,,,,,,,,,,,,,,,,,, +,024A,024C,023A,023C,,022A,022C,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,019D,019C,016D,016C,013D,013C,010D,010C,007D,007C,004D,004C,001D,001C,,,,,, +,,,,,,,,019B,019A,016B,016A,013B,013A,010B,010A,007B,007A,004B,004A,001B,001A,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,020D,020C,017D,017C,014D,014C,011D,011C,008D,008C,005D,005C,002D,002C,,,,,, +,,,,,,,,020B,020A,017B,017A,014B,014A,011B,011A,008B,008A,005B,005A,002B,002A,,,,,, +,,,,,,,,021D,021C,018D,018C,015D,015C,012D,012C,009D,009C,006D,006C,003D,003C,,,,,, +,,,,,,,,021B,021A,018B,018A,015B,015A,012B,012A,009B,009A,006B,006A,003B,003A,,,,,, + +""", + "6": """ +,,,026C,026D,027D,027C,028D,028C,029D,029C,030D,030C,031D,031C,032D,032C,033D,033C,035D,035C,036D,036C,037D,037C,038D,038C,039D,039C,040D,040C,041D,041C,042D,042C,043D,043C,044D,044C,045D,045C,046D,046C +,,,026A,026B,027B,027A,028B,028A,029B,029A,030B,030A,031B,031A,032B,032A,033B,033A,035B,035A,036B,036A,037B,037A,038B,038A,039B,039A,040B,040A,041B,041A,042B,042A,043B,043A,044B,044A,045B,045A,046B,046A +025D,025C,,,,,,,,,,,,,,,,034D,034C,,,,,,,,,,,,,,,,,,,,,,,047C,047A +025B,025A,,,,,,,,,,,,,,,,034B,034A,,,,,,,,,,,,,,,,,,,,,,,047D,047B +024D,024C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,048C,048A +024B,024A,,,,,,,,,,,,,,050D,050C,052D,052C,054D,054C,056D,056C,058D,058C,060D,060C,,,,,,,,,,,,,,,048D,048B +023D,023C,,,,,,,,,,,,,,050B,050A,052B,052A,054B,054A,056B,056A,058B,058A,060B,060A,,,,,,,,,,,,,,,, +023B,023A,,,,,,,,,,,,,,049D,049C,051D,051C,053D,053C,055D,055C,057D,057C,059D,059C,,,,,,,,,,,,,,,, +022D,022C,,,,,,,,,,,,,,049B,049A,051B,051A,053B,053A,055B,055A,057B,057A,059B,059A,,,,,,,,,,,,,,,, +022B,022A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +021D,021C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +021B,021A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +020D,020C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +020B,020A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +019D,019C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +019B,019A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +015D,015C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +015B,015A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +014D,014C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +014B,014A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +013D,013C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +013B,013A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +012D,012C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +012B,012A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +011D,011C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +011B,011A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +010D,010C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +010B,010A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +009D,009C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +009B,009A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +008D,008C,,007D,007C,006D,006C,005D,005C,004D,004C,003D,003C,002D,002C,001D,001C,,,,,,,,,,,,,,,,,,,,,,,,,, +008B,008A,,007B,007A,006B,006A,005B,005A,004B,004A,003B,003A,002B,002A,001B,001A,,,,,,,,,,,,,,,,,,,,,,,,,, + +""", + "7": """ +,,,,,,,,022D,022C,021D,021C,020D,020C,019D,019C,018D,018C,017D,017C,,,,,,,,,,,, +,,,,,,,,022B,022A,021B,021A,020B,020A,019B,019A,018B,018A,017B,017A,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +016D,016C,015D,015C,014D,014C,013D,013C,012D,012C,011D,011C,010D,010C,009D,009C,008D,008C,007D,007C,006D,006C,005D,005C,004D,004C,003D,003C,002D,002C,001D,001C +016B,016A,015B,015A,014B,014A,013B,013A,012B,012A,011B,011A,010B,010A,009B,009A,008B,008A,007B,007A,006B,006A,005B,005A,004B,004A,003B,003A,002B,002A,001B,001A + +""" + }, + "5": { + "8": """ +,,,046D,046C,047D,047C,048D,048C,049D,049C,050D,050C,051D,051C,052D,052C,053D,053C,054D,054C,055D,055C,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,046B,046A,047B,047A,048B,048A,049B,049A,050B,050A,051B,051A,052B,052A,053B,053A,054B,054A,055B,055A,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,056C,056A,,,,,,,,,,,,,,,,,,,,,,,,,, +045B,045D,,,,,,,,,,,,,,,,,,,,,,056D,056B,,,,,,,,,,,,,,,,,,,,,,,,,, +045A,045C,,,,,,,,,,,,,,,,,,,,,,057C,057A,,,,,,,,,,,,,,,,,,,,,,,,,, +044B,044D,,,,,,,,,,,,,,,,,,,,,,057D,057B,,,,,,,,,,,,,,,,,,,,,,,,,, +044A,044C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +043B,043D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +043A,043C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +042B,042D,,,,,,,,,,,,,,,,,070B,070D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +042A,042C,,,,,,,,,,,,,,,,,070A,070C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +041B,041D,,,,,,,,,,,,,,,,,069B,069D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +041A,041C,,,,,,,,,,,,,,,,,069A,069C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +040B,040D,,,,,,,,,,,,,,,,,068B,068D,,071A,071B,072A,072B,073A,073B,074A,074B,075A,075B,076A,076B,077A,077B,,,,,,,,,,,,,,,, +040A,040C,,,,,,,,,,,,,,,,,068A,068C,,071C,071D,072C,072D,073C,073D,074C,074D,075C,075D,076C,076D,077C,077D,,,,,,,,,,,,,,,, +039B,039D,,,,,,,,,,,,,,,,,067B,067D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +039A,039C,,,,,,,,,,,,,,,,,067A,067C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +038B,038D,,,,,,,,,,,,,,,,,066B,066D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +038A,038C,,,,,,,,,,,,,,,,,066A,066C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +037B,037D,,,,,,,,,,,,,,,,,065B,065D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +037A,037C,,,,,,,,,,,,,,,,,065A,065C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +036B,036D,,,,,,,,,,,,,,,,,064B,064D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +036A,036C,,,,,,,,,,,,,,,,,064A,064C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +035B,035D,,,,,,,,,,,,,,,,,063B,063D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +035A,035C,,,,,,,,,,,,,,,,,063A,063C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +034B,034D,,,,,,,,,,,,,,,,,062B,062D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +034A,034C,,,,,,,,,,,,,,,,,062A,062C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +033B,033D,,,,,,,,,,,,,,,,,,,061D,061C,,060D,060C,,059D,059C,,058D,058C,,,,,,,,,,,,,,,,,,,, +033A,033C,,,,,,,,,,,,,,,,,,,061B,061A,,060B,060A,,059B,059A,,058B,058A,,,,,,,,,,,,,,,,,,,, +032B,032D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +032A,032C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +031B,031D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +031A,031C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +030B,030D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +030A,030C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +029B,029D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +029A,029C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +028B,028D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +028A,028C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +027B,027D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +027A,027C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +026B,026D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +026A,026C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +025B,025D,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +025A,025C,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,024D,024C,023D,023C,022D,022C,021D,021C,020D,020C,019D,019C,018D,018C,017D,017C,016D,016C,015D,015C,014D,014C,013D,013C,012D,012C,011D,011C,010D,010C,009D,009C,008D,008C,007D,007C,006D,006C,005D,005C,004D,004C,003D,003C,002D,002C,001D,001C +,,,024B,024A,023B,023A,022B,022A,021B,021A,020B,020A,019B,019A,018B,018A,017B,017A,016B,016A,015B,015A,014B,014A,013B,013A,012B,012A,011B,011A,010B,010A,009B,009A,008B,008A,007B,007A,006B,006A,005B,005A,004B,004A,003B,003A,002B,002A,001B,001A + +""" + } +} \ No newline at end of file diff --git a/gui/SeatMapWidget.py b/gui/SeatMapWidget.py new file mode 100644 index 0000000..7bc518e --- /dev/null +++ b/gui/SeatMapWidget.py @@ -0,0 +1,252 @@ +# -*- coding: utf-8 -*- +""" +Copyright (c) 2025 KenanZhu. +All rights reserved. + +This software is provided "as is", without any warranty of any kind. +You may use, modify, and distribute this file under the terms of the MIT License. +See the LICENSE file for details. +""" +from PySide6.QtCore import ( + Qt, Slot, Signal, QEvent +) +from PySide6.QtWidgets import ( + QFrame, QWidget, QLabel, QHBoxLayout, QVBoxLayout, + QGridLayout, QGraphicsView, QGraphicsScene, QGraphicsItem, + QPushButton, +) +from PySide6.QtGui import ( + QPainter, QWheelEvent, QCloseEvent +) +from .SeatFrame import SeatFrame + + +class SeatMapWidget(QWidget): + + seatMapWidgetClosed = Signal(list) + + def __init__( + self, + parent: QWidget = None, + floor: str = "", + room: str = "", + seats_data: dict = {}, + ): + + super().__init__(parent) + + self.__floor = floor + self.__room = room + self.__seats_data = seats_data + self.__selected_seats = [] + self.__seat_frames = {} + self.setUpUi() + self.connectSignals() + + @staticmethod + def formatSeatNumber( + seat_number: str + ) -> str: + + if seat_number and not seat_number[-1].isdigit(): + digits = seat_number[:-1] + letter = seat_number[-1] + return digits.zfill(3) + letter + return seat_number.zfill(3) + + + def setUpUi( + self + ): + + self.setWindowFlags(Qt.WindowType.Window) + self.setWindowModality(Qt.WindowModality.ApplicationModal) + self.setMinimumSize(800, 600) + self.resize(800, 600) + self.setWindowTitle(f"选择楼层座位 - AutoLibrary") + + self.SeatMapWidgetMainLayout = QVBoxLayout(self) + self.TitleLabel = QLabel(f"楼层座位分布图: {self.__floor}-{self.__room}") + self.TitleLabel.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.TitleLabel.setStyleSheet("font-size: 16px; font-weight: bold; margin: 10px;") + self.SeatMapWidgetMainLayout.addWidget(self.TitleLabel) + + self.SeatMapGraphicsView = QGraphicsView(self) + self.SeatMapGraphicsScene = QGraphicsScene(self) + self.SeatMapGraphicsView.setScene(self.SeatMapGraphicsScene) + self.SeatMapGraphicsView.setRenderHint(QPainter.RenderHint.LosslessImageRendering) + self.SeatMapGraphicsView.setDragMode(QGraphicsView.DragMode.ScrollHandDrag) + self.SeatMapGraphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) + self.SeatMapGraphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) + self.SeatMapGraphicsView.viewport().installEventFilter(self) + + self.SeatsContainerWidget = QWidget() + self.SeatsContainerLayout = QGridLayout(self.SeatsContainerWidget) + self.createSeatMap() + + self.ContainerProxy = self.SeatMapGraphicsScene.addWidget(self.SeatsContainerWidget) + self.ContainerProxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, False) + self.SeatMapWidgetMainLayout.addWidget(self.SeatMapGraphicsView) + + self.TipsLabel = QLabel( + " 点击座位进行选择/取消选择, 最多选择1个座位 \n" + " [操作方法: Ctrl+鼠标滚轮缩放 | 滚轮/拖拽/方向键 移动]" + ) + self.TipsLabel.setAlignment(Qt.AlignmentFlag.AlignLeft) + self.TipsLabel.setStyleSheet("color: #666; margin: 5px;") + self.SeatMapWidgetMainLayout.addWidget(self.TipsLabel) + + self.ConfirmButton = QPushButton("确认") + self.ConfirmButton.setFixedSize(80, 25) + self.CancelButton = QPushButton("取消") + self.CancelButton.setFixedSize(80, 25) + self.SeatMapWidgetControlLayout = QHBoxLayout() + self.SeatMapWidgetControlLayout.setAlignment(Qt.AlignmentFlag.AlignRight) + self.SeatMapWidgetControlLayout.addWidget(self.CancelButton) + self.SeatMapWidgetControlLayout.addWidget(self.ConfirmButton) + self.SeatMapWidgetMainLayout.addLayout(self.SeatMapWidgetControlLayout) + + + def connectSignals( + self + ): + + self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked) + self.CancelButton.clicked.connect(self.onCancelButtonClicked) + + + def closeEvent( + self, + event: QCloseEvent + ): + + self.seatMapWidgetClosed.emit(self.__selected_seats) + super().closeEvent(event) + + + def eventFilter( + self, + watched, + event + ): + + if (watched is self.SeatMapGraphicsView.viewport() and + event.type() == QEvent.Type.Wheel and + event.modifiers() == Qt.KeyboardModifier.ControlModifier + ): + self.zoomGraphicsView(event) + return True + return super().eventFilter(watched, event) + + + def zoomGraphicsView( + self, + event: QWheelEvent + ): + + delta = event.angleDelta().y() + zoom_factor = 1.2 if delta > 0 else 1/1.2 + self.SeatMapGraphicsView.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse) + self.SeatMapGraphicsView.scale(zoom_factor, zoom_factor) + + + def createSeatMap( + self + ): + + rows = self.__seats_data.strip().split("\n") + for row_idx, row in enumerate(rows): + col_idx = 0 + seats_number = [seat.strip() for seat in row.split(",")] + for seat_number in seats_number: + if seat_number: + seat_widget = SeatFrame(seat_number) + seat_widget.clicked.connect(self.onSeatClicked) + self.SeatsContainerLayout.addWidget(seat_widget, row_idx, col_idx) + self.__seat_frames[seat_number] = seat_widget + else: + spacer = QFrame() + spacer.setFixedSize(20, 30) + spacer.setStyleSheet("background-color: transparent; border: none;") + self.SeatsContainerLayout.addWidget(spacer, row_idx, col_idx) + col_idx += 1 + self.SeatsContainerLayout.setSpacing(20) + self.SeatsContainerLayout.setContentsMargins(20, 20, 20, 20) + self.SeatsContainerWidget.adjustSize() + + + def selectSeat( + self, + seat_number: str + ): + + if len(self.__selected_seats) >= 1: + return + seat_number = self.formatSeatNumber(seat_number) + if seat_number not in self.__seat_frames: + return + widget = self.__seat_frames[seat_number] + if widget.isSelected(): + return + widget.toggleSelection() + self.__selected_seats.append(seat_number) + + + def selectSeats( + self, + selected_seats: list + ): + + self.clearSelections() + for seat_number in selected_seats: + self.selectSeat(seat_number) + + + def getSelectedSeats( + self + ) -> list[str]: + + return self.__selected_seats + + + def clearSelections( + self + ): + + seats_to_clear = self.__selected_seats.copy() + for seat_number in seats_to_clear: + if seat_number not in self.__seat_frames: + continue + widget = self.__seat_frames[seat_number] + if widget.isSelected(): + widget.toggleSelection() + self.__selected_seats = [] + + @Slot(str) + def onSeatClicked( + self, + seat_number: str + ): + + if seat_number in self.__selected_seats: + self.__selected_seats.remove(seat_number) + else: + if len(self.__selected_seats) < 1: + self.__selected_seats.append(seat_number) + else: + self.__seat_frames[seat_number].toggleSelection() + + @Slot() + def onConfirmButtonClicked( + self + ): + + self.close() + + @Slot() + def onCancelButtonClicked( + self + ): + + self.clearSelections() + self.close() \ No newline at end of file