class TextboxWidget(TritonWidget): def __init__(self, base, name): TritonWidget.__init__(self, base) self.name = name self.setBackgroundColor(self, Qt.white) self.layout = QHBoxLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) self.label = QLabel() self.label.setText(name) self.label.setFont(QFont('Helvetica', 10)) self.box = QLineEdit() self.box.setFixedWidth(250) self.box.setFont(QFont('Helvetica', 10)) self.layout.addWidget(self.label) self.layout.addWidget(self.box)
class AbstractReferenceSelector(QWidget): changed = Signal() def __init__(self, parent=None): QWidget.__init__(self, parent) self.completer = None self.p_selected_id = 0 self.layout = QHBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.name = QLineEdit() self.name.setText("") self.layout.addWidget(self.name) self.details = QLabel() self.details.setText("") self.details.setVisible(False) self.layout.addWidget(self.details) self.button = QPushButton("...") self.button.setFixedWidth( self.button.fontMetrics().horizontalAdvance("XXXX")) self.layout.addWidget(self.button) self.setLayout(self.layout) self.setFocusProxy(self.name) self.button.clicked.connect(self.on_button_clicked) if self.details_field: self.name.setFixedWidth( self.name.fontMetrics().horizontalAdvance("X") * 15) self.details.setVisible(True) self.completer = QCompleter(self.dialog.model.completion_model) self.completer.setCompletionColumn( self.dialog.model.completion_model.fieldIndex(self.selector_field)) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.name.setCompleter(self.completer) self.completer.activated[QModelIndex].connect(self.on_completion) def getId(self): return self.p_selected_id def setId(self, selected_id): if self.p_selected_id == selected_id: return self.p_selected_id = selected_id self.name.setText( self.dialog.model.getFieldValue(selected_id, self.selector_field)) if self.details_field: self.details.setText( self.dialog.model.getFieldValue(selected_id, self.details_field)) selected_id = Property(int, getId, setId, notify=changed, user=True) def setFilterValue(self, filter_value): self.dialog.setFilterValue(filter_value) def on_button_clicked(self): ref_point = self.mapToGlobal(self.name.geometry().bottomLeft()) self.dialog.setGeometry(ref_point.x(), ref_point.y(), self.dialog.width(), self.dialog.height()) res = self.dialog.exec(enable_selection=True, selected=self.selected_id) if res: self.selected_id = self.dialog.selected_id self.changed.emit() @Slot(QModelIndex) def on_completion(self, index): model = index.model() self.selected_id = model.data(model.index(index.row(), 0), Qt.DisplayRole) self.changed.emit() def isCustom(self): return True
class Config(QWidget): def __init__(self): super().__init__() # global self.config_params self.xml_root = None # self.tab = QWidget() # self.tabs.resize(200,5) #------------------------------------------- label_width = 110 domain_value_width = 100 value_width = 60 label_height = 20 units_width = 70 self.scroll = QScrollArea() # might contain centralWidget self.config_params = QWidget() self.vbox = QVBoxLayout() self.vbox.addStretch(0) #============ Domain ================================ label = QLabel("Domain (micron)") label.setFixedHeight(label_height) label.setStyleSheet("background-color: orange") label.setAlignment(QtCore.Qt.AlignCenter) self.vbox.addWidget(label) hbox = QHBoxLayout() label = QLabel("Xmin") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.xmin = QLineEdit() self.xmin.setFixedWidth(domain_value_width) self.xmin.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.xmin) label = QLabel("Xmax") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.xmax = QLineEdit() self.xmax.setFixedWidth(domain_value_width) self.xmax.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.xmax) label = QLabel("dx") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.xdel = QLineEdit() self.xdel.setFixedWidth(value_width) self.xdel.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.xdel) self.vbox.addLayout(hbox) #---------- hbox = QHBoxLayout() label = QLabel("Ymin") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.ymin = QLineEdit() self.ymin.setFixedWidth(domain_value_width) self.ymin.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.ymin) label = QLabel("Ymax") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.ymax = QLineEdit() self.ymax.setFixedWidth(domain_value_width) self.ymax.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.ymax) label = QLabel("dy") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.ydel = QLineEdit() self.ydel.setFixedWidth(value_width) self.ydel.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.ydel) self.vbox.addLayout(hbox) #---------- hbox = QHBoxLayout() label = QLabel("Zmin") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.zmin = QLineEdit() self.zmin.setFixedWidth(domain_value_width) self.zmin.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.zmin) label = QLabel("Zmax") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.zmax = QLineEdit() self.zmax.setFixedWidth(domain_value_width) self.zmax.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.zmax) label = QLabel("dz") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.zdel = QLineEdit() self.zdel.setFixedWidth(value_width) self.zdel.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.zdel) self.vbox.addLayout(hbox) #---------- hbox = QHBoxLayout() self.virtual_walls = QCheckBox("Virtual walls") # self.motility_enabled.setAlignment(QtCore.Qt.AlignRight) # label.setFixedWidth(label_width) hbox.addWidget(self.virtual_walls) self.vbox.addLayout(hbox) # self.vbox.addWidget(QHLine()) #============ Misc ================================ label = QLabel("Misc runtime parameters") label.setFixedHeight(label_height) label.setStyleSheet("background-color: orange") label.setAlignment(QtCore.Qt.AlignCenter) self.vbox.addWidget(label) hbox = QHBoxLayout() # hbox.setFixedHeight(label_width) label = QLabel("Max Time") # label_width = 210 label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.max_time = QLineEdit() # self.max_time.setFixedWidth(200) self.max_time.setFixedWidth(domain_value_width) self.max_time.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.max_time) label = QLabel("min") label.setFixedWidth(units_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) self.vbox.addLayout(hbox) #---------- hbox = QHBoxLayout() label = QLabel("# threads") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.num_threads = QLineEdit() # self.num_threads.setFixedWidth(value_width) self.num_threads.setFixedWidth(domain_value_width) self.num_threads.setValidator(QtGui.QIntValidator()) hbox.addWidget(self.num_threads) label = QLabel(" ") label.setFixedWidth(units_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) self.vbox.addLayout(hbox) #------------------ hbox = QHBoxLayout() label = QLabel("Save data:") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) #------ self.save_svg = QCheckBox("SVG") # self.motility_2D.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(self.save_svg) label = QLabel("every") # label_width = 210 # label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.svg_interval = QLineEdit() self.svg_interval.setFixedWidth(value_width) self.svg_interval.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.svg_interval) label = QLabel("min") # label.setFixedWidth(units_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) #------ self.save_full = QCheckBox("Full") # self.motility_2D.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(self.save_full) label = QLabel("every") # label_width = 210 # label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.full_interval = QLineEdit() self.full_interval.setFixedWidth(value_width) self.full_interval.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.full_interval) label = QLabel("min") # label.setFixedWidth(units_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) self.vbox.addLayout(hbox) #============ Cells IC ================================ label = QLabel("Initial conditions of cells (x,y,z, type)") label.setFixedHeight(label_height) label.setStyleSheet("background-color: orange") label.setAlignment(QtCore.Qt.AlignCenter) self.vbox.addWidget(label) self.cells_csv = QCheckBox("config/cells.csv") self.vbox.addWidget(self.cells_csv) #-------------------------- # Dummy widget for filler?? # label = QLabel("") # label.setFixedHeight(1000) # # label.setStyleSheet("background-color: orange") # label.setAlignment(QtCore.Qt.AlignCenter) # self.vbox.addWidget(label) self.vbox.addStretch() #================================================================== self.config_params.setLayout(self.vbox) self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.scroll.setWidgetResizable(True) self.scroll.setWidget( self.config_params) # self.config_params = QWidget() self.layout = QVBoxLayout(self) self.layout.addWidget(self.scroll) # @QtCore.Slot() # def save_xml(self): # # self.text.setText(random.choice(self.hello)) # pass def fill_gui(self): self.xmin.setText(self.xml_root.find(".//x_min").text) self.xmax.setText(self.xml_root.find(".//x_max").text) self.xdel.setText(self.xml_root.find(".//dx").text) self.ymin.setText(self.xml_root.find(".//y_min").text) self.ymax.setText(self.xml_root.find(".//y_max").text) self.ydel.setText(self.xml_root.find(".//dy").text) self.zmin.setText(self.xml_root.find(".//z_min").text) self.zmax.setText(self.xml_root.find(".//z_max").text) self.zdel.setText(self.xml_root.find(".//dz").text) self.max_time.setText(self.xml_root.find(".//max_time").text) self.num_threads.setText(self.xml_root.find(".//omp_num_threads").text) self.svg_interval.setText(self.xml_root.find(".//SVG//interval").text) # NOTE: do this *after* filling the mcds_interval, directly above, due to the callback/constraints on them?? if self.xml_root.find(".//SVG//enable").text.lower() == 'true': self.save_svg.setChecked(True) else: self.save_svg.setChecked(False) self.full_interval.setText( self.xml_root.find(".//full_data//interval").text) if self.xml_root.find(".//full_data//enable").text.lower() == 'true': self.save_full.setChecked(True) else: self.save_full.setChecked(False) # Read values from the GUI widgets and generate/write a new XML def fill_xml(self): # pass # self.xmin.setText(self.xml_root.find(".//x_min").text) print("config_tab: fill_xml: xmin=", str(self.xmin.text)) self.xml_root.find(".//x_min").text = self.xmin.text() self.xml_root.find(".//x_max").text = self.xmax.text() self.xml_root.find(".//dx").text = self.xdel.text() self.xml_root.find(".//y_min").text = self.ymin.text() self.xml_root.find(".//y_max").text = self.ymax.text() self.xml_root.find(".//dy").text = self.ydel.text() self.xml_root.find(".//z_min").text = self.zmin.text() self.xml_root.find(".//z_max").text = self.zmax.text() self.xml_root.find(".//dz").text = self.zdel.text() if not self.xml_root.find(".//virtual_wall_at_domain_edge"): # create it? print("config_tab.py: no virtual_wall_at_domain_edge tag") else: if self.virtual_walls.isChecked(): self.xml_root.find( ".//virtual_wall_at_domain_edge").text = 'true' else: self.xml_root.find( ".//virtual_wall_at_domain_edge").text = 'false' self.xml_root.find(".//max_time").text = self.max_time.text() self.xml_root.find(".//omp_num_threads").text = self.num_threads.text() if self.save_svg.isChecked(): self.xml_root.find(".//SVG//enable").text = 'true' else: self.xml_root.find(".//SVG//enable").text = 'false' self.xml_root.find(".//SVG//interval").text = self.svg_interval.text() if self.save_full.isChecked(): self.xml_root.find(".//full_data//enable").text = 'true' else: self.xml_root.find(".//full_data//enable").text = 'false' self.xml_root.find( ".//full_data//interval").text = self.full_interval.text() if self.cells_csv.isChecked(): self.xml_root.find(".//initial_conditions//cell_positions" ).attrib['enabled'] = 'true' else: self.xml_root.find(".//initial_conditions//cell_positions" ).attrib['enabled'] = 'false'
class PlaylistPopup(QWidget): def __init__(self, result, parent=None): # Popup when "Add song to playlist" is clicked on # How this works is a QWidget that encompasses the entire window area, representing an unclickable translucent background. # Another QWidget is then contained inside that QWidget representing the popup. # result: (dict) Python dict containing information of the song clicked QWidget.__init__(self) self.setParent(parent) self.result = result # Signals are used to indicate to close the window self.SIGNALS = self.TranslucentWidgetSignals() # Make the window frameless and expanding. self.setWindowFlags(Qt.FramelessWindowHint) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Makes the window background colour translucent self.setAttribute(Qt.WA_StyledBackground) self.setStyleSheet( "PlaylistPopup { background-color: rgba(255, 255, 255, 0.5)}") # Sets the grid settings of the "background" and the "popup" layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) playlistAdd = QWidget(self) playlistAdd.setFixedSize(800, 300) playlistAdd.setStyleSheet( ".QWidget { background-color: rgba(255, 255, 255, 1)}") innerLayout = QGridLayout() innerLayout.setContentsMargins(20, 20, 20, 20) innerLayout.setSpacing(30) # Heading font font = QFont() font.setPointSize(24) # Default label font font2 = QFont() font2.setPointSize(16) # Heading label = QLabel("添加到播放列表/Add to Playlist", self) label.setAlignment(Qt.AlignCenter) label.setFont(font) innerLayout.addWidget(label, 0, 0) # Playlist selection self.comboBox = QComboBox(self) self.comboBox.setFont(font) playlists = DB.getPlaylists("") for playlist in playlists: self.comboBox.addItem(playlist["playlist_name"]) self.comboBox.setCurrentIndex(-1) innerLayout.addWidget(self.comboBox, 1, 0) # Textbox to create a new playlist self.textBox = QLineEdit(self) self.textBox.setFont(font2) self.textBox.setAlignment(Qt.AlignCenter) self.textBox.setPlaceholderText( "输入以创建新的播放列表/Type to create a new playlist") self.textBox.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) # TODO: resize textbox with window self.textBox.setFixedWidth(760) innerLayout.addWidget(self.textBox, 2, 0, Qt.AlignCenter) # Add actions for then the QComboBox or QLineEdit is changed. # This is done so there is only one action between "Add to existing Playlist" or "Add to new Playlist" self.comboBox.currentIndexChanged.connect(self.comboBoxChanged) self.textBox.textEdited.connect(self.textBoxChanged) # Confirm button confirmButton = QToolButton(self) confirmButton.setText("确认/Confirm") confirmButton.setFont(font) confirmButton.clicked.connect(self.processPlaylistRequest) innerLayout.addWidget(confirmButton, 3, 0, Qt.AlignCenter) # Exit button btn = QToolButton(self) btn.setFixedSize(44, 44) btn.setText("X") btn.setFont(font) btn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) btn.clicked.connect(lambda: self.SIGNALS.CLOSE.emit()) innerLayout.addWidget(btn, 0, 0, Qt.AlignRight) playlistAdd.setLayout(innerLayout) layout.addWidget(playlistAdd, 0, 0, Qt.AlignCenter) self.setLayout(layout) def comboBoxChanged(self): # Called when the ComboBox is changed # Clears the text in the "Create Playlist" TextBox if self.textBox.text() != "": self.textBox.setText("") def textBoxChanged(self): # Called when the TextBox is changed # Clears the selection in the "Add to Playlist" ComboBox if self.comboBox.currentIndex != -1: self.comboBox.setCurrentIndex(-1) def processPlaylistRequest(self): # Called when the Confirm button is clicked def addToPlaylist(self, playlistID): # Adds the song to the playlist # Get song ID song = self.result["song_id"] DB.addPlaylistSong(playlistID, song) if self.textBox.text() != "": # New playlist playlistName = self.textBox.text() counter = 1 while DB.checkPlaylist(playlistName): playlistName = "{} ({})".format(self.textBox.text(), counter) counter += 1 playlistID = DB.newPlaylist(playlistName)[0]["playlist_id"] addToPlaylist(self, playlistID) self.SIGNALS.CLOSE.emit() elif self.comboBox.currentIndex != -1: playlistID = DB.checkPlaylist( self.comboBox.currentText())[0]["playlist_id"] # Add to existing playlist addToPlaylist(self, playlistID) self.SIGNALS.CLOSE.emit() # Taken from https://stackoverflow.com/questions/44264852/pyside-pyqt-overlay-widget class TranslucentWidgetSignals(QtCore.QObject): CLOSE = QtCore.Signal()
class Config(QWidget): def __init__(self): super().__init__() # global self.params_cell_def self.tab = QWidget() # self.tabs.resize(200,5) #------------------------------------------- label_width = 110 domain_value_width = 100 value_width = 60 label_height = 20 units_width = 70 self.scroll = QScrollArea() # might contain centralWidget self.params_cell_def = QWidget() self.vbox = QVBoxLayout() self.vbox.addStretch(0) #============ Domain ================================ label = QLabel("Domain (micron)") label.setFixedHeight(label_height) label.setStyleSheet("background-color: orange") label.setAlignment(QtCore.Qt.AlignCenter) self.vbox.addWidget(label) hbox = QHBoxLayout() label = QLabel("Xmin") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.xmin = QLineEdit() self.xmin.setFixedWidth(domain_value_width) self.xmin.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.xmin) label = QLabel("Xmax") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.xmax = QLineEdit() self.xmax.setFixedWidth(domain_value_width) self.xmax.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.xmax) self.vbox.addLayout(hbox) #---------- hbox = QHBoxLayout() label = QLabel("Ymin") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.ymin = QLineEdit() self.ymin.setFixedWidth(domain_value_width) self.ymin.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.ymin) label = QLabel("Ymax") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.ymax = QLineEdit() self.ymax.setFixedWidth(domain_value_width) self.ymax.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.ymax) self.vbox.addLayout(hbox) #---------- hbox = QHBoxLayout() self.virtual_walls = QCheckBox("Virtual walls") # self.motility_enabled.setAlignment(QtCore.Qt.AlignRight) # label.setFixedWidth(label_width) hbox.addWidget(self.virtual_walls) self.vbox.addLayout(hbox) self.vbox.addWidget(QHLine()) #---------- hbox = QHBoxLayout() # hbox.setFixedHeight(label_width) label = QLabel("Max Time") # label_width = 210 label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.max_time = QLineEdit() self.max_time.setFixedWidth(200) self.max_time.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.max_time) label = QLabel("min") label.setFixedWidth(units_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) self.vbox.addLayout(hbox) #---------- hbox = QHBoxLayout() label = QLabel("# threads") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.num_threads = QLineEdit() self.num_threads.setFixedWidth(value_width) self.num_threads.setValidator(QtGui.QIntValidator()) hbox.addWidget(self.num_threads) self.vbox.addLayout(hbox) #------------------ hbox = QHBoxLayout() label = QLabel("Save data:") label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) #------ self.save_svg = QCheckBox("SVG") # self.motility_2D.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(self.save_svg) label = QLabel("every") # label_width = 210 # label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.svg_interval = QLineEdit() self.svg_interval.setFixedWidth(value_width) self.svg_interval.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.svg_interval) label = QLabel("min") # label.setFixedWidth(units_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) #------ self.save_svg = QCheckBox("Full") # self.motility_2D.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(self.save_svg) label = QLabel("every") # label_width = 210 # label.setFixedWidth(label_width) label.setAlignment(QtCore.Qt.AlignRight) hbox.addWidget(label) self.full_interval = QLineEdit() self.full_interval.setFixedWidth(value_width) self.full_interval.setValidator(QtGui.QDoubleValidator()) hbox.addWidget(self.full_interval) label = QLabel("min") # label.setFixedWidth(units_width) label.setAlignment(QtCore.Qt.AlignLeft) hbox.addWidget(label) self.vbox.addLayout(hbox) #-------------- self.cells_csv = QCheckBox("cells.csv") self.vbox.addWidget(self.cells_csv) #-------------------------- # Dummy widget for filler?? label = QLabel("") label.setFixedHeight(300) # label.setStyleSheet("background-color: orange") label.setAlignment(QtCore.Qt.AlignCenter) self.vbox.addWidget(label) #================================================================== self.params_cell_def.setLayout(self.vbox) self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.scroll.setWidgetResizable(True) self.scroll.setWidget(self.params_cell_def) self.layout = QVBoxLayout(self) self.layout.addWidget(self.scroll)
class AddSteamWidget(TritonWidget): def __init__(self, base, *args, **kwargs): TritonWidget.__init__(self, base, *args, **kwargs) self.sharedSecret = None self.identitySecret = None self.steamId = None self.type = Globals.SteamAuth self.setWindowTitle('Add Steam') self.setBackgroundColor(self, Qt.white) self.boxLayout = QVBoxLayout(self) self.boxLayout.setContentsMargins(20, 20, 20, 20) self.nameWidget = TextboxWidget(base, 'Name:') self.steamIdWidget = TextboxWidget(base, 'Steam ID:') self.sharedWidget = TextboxWidget(base, 'Shared Secret:') self.identityWidget = TextboxWidget(base, 'Identity Secret:') self.verifyLabel = QLabel() self.verifyLabel.setText('Click the Verify button to check the first code.') self.verifyLabel.setFont(QFont('Helvetica', 10)) self.verifyBox = QLineEdit() self.verifyBox.setFixedWidth(150) self.verifyBox.setFont(QFont('Helvetica', 10)) self.verifyBox.setEnabled(False) palette = QPalette() palette.setColor(QPalette.Text, Qt.black) self.verifyBox.setPalette(palette) self.verifyBox.setAlignment(Qt.AlignCenter) self.verifyButton = QPushButton('Verify') self.verifyButton.clicked.connect(self.checkVerify) self.verifyButton.setFixedWidth(150) self.addButton = QPushButton('OK') self.addButton.clicked.connect(self.add) self.boxLayout.addWidget(self.nameWidget) self.boxLayout.addWidget(self.steamIdWidget) self.boxLayout.addWidget(self.sharedWidget) self.boxLayout.addWidget(self.identityWidget) self.boxLayout.addSpacing(10) self.boxLayout.addWidget(self.verifyLabel) self.boxLayout.addWidget(self.verifyBox, 0, Qt.AlignCenter) self.boxLayout.addWidget(self.verifyButton, 0, Qt.AlignCenter) self.boxLayout.addSpacing(10) self.boxLayout.addWidget(self.addButton, 0, Qt.AlignRight) self.setFixedSize(self.sizeHint()) self.center() self.show() def getName(self): return self.nameWidget.box.text() def getAccount(self): return {'name': self.getName(), 'type': self.type, 'sharedSecret': self.sharedSecret, 'identitySecret': self.identitySecret, 'steamId': self.steamId, 'icon': 'icons/SteamIcon.png'} def invalidateSecret(self, text=''): self.sharedSecret = None self.identitySecret = None self.steamId = None self.verifyBox.setText(text) def checkVerify(self): self.sharedSecret = self.sharedWidget.box.text() self.identitySecret = self.identityWidget.box.text() self.steamId = self.steamIdWidget.box.text() if not self.sharedSecret or not self.identitySecret or not self.steamId: self.invalidateSecret('Invalid') return try: self.verifyBox.setText(self.base.getAuthCode(self.getAccount())) except: self.invalidateSecret('Invalid') def add(self): if not self.sharedSecret or not self.getName(): return self.base.addAccount(self.getAccount()) self.close()
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): super(MainWindow, self).__init__() self.setupUi(self) self.view = None self.uid = None self.b_id = None self.chap_id = None self.page_num = None self.page_length = None self.label_choose_page = None self.widget_choose_page = None self.add_bookmark_dialog = None self.add_signal_func = { LoginView: self.add_LoginView_signal, RegisterView: self.add_RegisterView_signal, WelcomeView: self.add_WelcomeView_signal, UserBookmarkView: self.add_UserBookmarkView_signal, ChapterView: self.add_ChapterView_signal, ContentView: self.add_ContentView_signal, BookBookmarkView: self.add_BookBookmarkView_signal } self.remove_signal_func = { LoginView: self.remove_LoginView_signal, RegisterView: self.remove_RegisterView_signal, WelcomeView: self.remove_WelcomeView_signal, UserBookmarkView: self.remove_BookmarkView_signal, ChapterView: self.remove_ChapterView_signal, ContentView: self.remove_ContentView_signal, BookBookmarkView: self.remove_BookmarkView_signal } self.add_view(LoginView, None) def closeEvent(self, event: PySide6.QtGui.QCloseEvent) -> None: if self.uid is not None: get_logout_response(self.uid) event.accept() def display_status_message(self, message, timeout=0): self.MainStatusBar.showMessage(message, timeout) def toggle_view(self, subview): old_view = type(self.view) self.remove_view() self.add_view(subview, old_view) def add_view(self, subview, old_view): assert subview in { LoginView, RegisterView, WelcomeView, UserBookmarkView, ChapterView, ContentView, BookBookmarkView } if subview == UserBookmarkView: self.view = subview(self.uid) elif subview == ChapterView: self.view = subview(self.b_id) elif subview == ContentView: self.view = subview(self.b_id, self.chap_id, self.page_num) self.page_num, self.page_length = self.view.get_page_info() elif subview == BookBookmarkView: self.view = subview(self.uid, self.b_id) else: self.view = subview() self.MainGridLayout.addWidget(self.view) self.add_signal_func.get(subview, lambda x: None)(old_view) self.view.show() def remove_view(self): type_of_view = type(self.view) assert type_of_view in { LoginView, RegisterView, WelcomeView, UserBookmarkView, ChapterView, ContentView, BookBookmarkView } self.view.hide() self.remove_signal_func.get(type_of_view, lambda: None)() self.MainToolBar.clear() self.MainGridLayout.removeWidget(self.view) self.view = None def add_LoginView_signal(self, old_view): self.view.login_button_signal.connect(self.toggle_view) self.view.register_button_signal.connect(self.toggle_view) self.view.display_status_signal.connect(self.display_status_message) self.view.set_current_user_signal.connect(self.set_current_user) def remove_LoginView_signal(self): self.view.login_button_signal.disconnect(self.toggle_view) self.view.register_button_signal.disconnect(self.toggle_view) self.view.display_status_signal.disconnect(self.display_status_message) self.view.set_current_user_signal.disconnect(self.set_current_user) def add_RegisterView_signal(self, old_view): self.view.submit_button_signal.connect(self.toggle_view) self.view.display_status_signal.connect(self.display_status_message) def remove_RegisterView_signal(self): self.view.submit_button_signal.disconnect(self.toggle_view) self.view.display_status_signal.disconnect(self.display_status_message) def add_WelcomeView_signal(self, old_view): self.view.select_book_signal.connect(self.toggle_view) self.view.display_status_signal.connect(self.display_status_message) self.view.set_current_book_signal.connect(self.set_current_book) action_logout = QAction('Logout', self) action_explore_bookmark = QAction('My Bookmark', self) action_logout.triggered.connect(self.logout_action_onclick) action_explore_bookmark.triggered.connect( lambda: self.toggle_view(UserBookmarkView)) self.MainToolBar.addAction(action_logout) self.MainToolBar.addAction(action_explore_bookmark) def remove_WelcomeView_signal(self): self.view.select_book_signal.disconnect(self.toggle_view) self.view.display_status_signal.disconnect(self.display_status_message) self.view.set_current_book_signal.disconnect(self.set_current_book) def add_BookmarkView_signal(self): self.view.display_status_signal.connect(self.display_status_message) self.view.set_current_book_signal.connect(self.set_current_book) self.view.set_current_chapter_signal.connect(self.set_current_chapter) self.view.set_current_page_signal.connect(self.set_current_page) self.view.select_chapter_signal.connect(self.toggle_view) def remove_BookmarkView_signal(self): self.view.display_status_signal.disconnect(self.display_status_message) self.view.set_current_book_signal.disconnect(self.set_current_book) self.view.set_current_chapter_signal.disconnect( self.set_current_chapter) self.view.set_current_page_signal.disconnect(self.set_current_page) self.view.select_chapter_signal.disconnect(self.toggle_view) def add_UserBookmarkView_signal(self, old_view): self.add_BookmarkView_signal() action_back = QAction('Back', self) action_remove_all = QAction('Remove all', self) action_back.triggered.connect(lambda: self.toggle_view(old_view)) action_remove_all.triggered.connect( lambda: self.view.delete_bookmark_all('user')) self.MainToolBar.addAction(action_back) self.MainToolBar.addAction(action_remove_all) def add_ChapterView_signal(self, old_view): self.view.display_status_signal.connect(self.display_status_message) self.view.select_chapter_signal.connect(self.toggle_view) self.view.set_current_chapter_signal.connect(self.set_current_chapter) action_back = QAction('Back', self) action_explore_bookmark = QAction('My Bookmark', self) action_back.triggered.connect(lambda: self.toggle_view(WelcomeView)) action_explore_bookmark.triggered.connect( lambda: self.toggle_view(BookBookmarkView)) self.MainToolBar.addAction(action_back) self.MainToolBar.addAction(action_explore_bookmark) def remove_ChapterView_signal(self): self.view.display_status_signal.disconnect(self.display_status_message) self.view.select_chapter_signal.disconnect(self.toggle_view) self.view.set_current_chapter_signal.disconnect( self.set_current_chapter) def add_ContentView_signal(self, old_view): self.view.set_current_page_signal.connect(self.set_current_page) self.view.set_page_length_signal.connect(self.set_page_length) action_back = QAction('Back', self) action_chapter_minus = QAction('<<', self) action_page_minus = QAction('<', self) action_page_plus = QAction('>', self) action_chapter_plus = QAction('>>', self) action_add_bookmark = QAction('Add Bookmark', self) action_explore_bookmark = QAction('My Bookmark', self) action_download = QAction('Download', self) self.label_choose_page = QLabel( f' ( {self.page_num + 1} / {self.page_length} ) ') self.widget_choose_page = QLineEdit() self.widget_choose_page.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.widget_choose_page.setFixedWidth(60) self.widget_choose_page.setAlignment(Qt.AlignCenter) self.widget_choose_page.setValidator( QIntValidator(self.page_num + 1, self.page_length)) action_chapter_minus.setToolTip('Chapter Up') action_page_minus.setToolTip('Page Up') action_page_plus.setToolTip('Page Down') action_chapter_plus.setToolTip('Chapter Up') action_back.triggered.connect(lambda: self.toggle_view(ChapterView)) action_chapter_minus.triggered.connect(self.chapter_minus_onclick) action_page_minus.triggered.connect(self.page_minus_onclick) action_page_plus.triggered.connect(self.page_plus_onclick) action_chapter_plus.triggered.connect(self.chapter_plus_onclick) action_add_bookmark.triggered.connect(self.open_add_bookmark_dialog) action_explore_bookmark.triggered.connect( lambda: self.toggle_view(BookBookmarkView)) action_download.triggered.connect(self.download_file) self.widget_choose_page.editingFinished.connect( self.page_choose_onfinish) self.MainToolBar.addAction(action_back) self.MainToolBar.addSeparator() self.MainToolBar.addActions([action_chapter_minus, action_page_minus]) self.MainToolBar.addWidget(self.widget_choose_page) self.MainToolBar.addWidget(self.label_choose_page) self.MainToolBar.addActions([action_page_plus, action_chapter_plus]) self.MainToolBar.addSeparator() self.MainToolBar.addActions( [action_add_bookmark, action_explore_bookmark, action_download]) def remove_ContentView_signal(self): self.view.set_current_page_signal.disconnect(self.set_current_page) self.view.set_page_length_signal.disconnect(self.set_page_length) def add_BookBookmarkView_signal(self, old_view): self.add_BookmarkView_signal() action_back = QAction('Back', self) action_remove_all = QAction('Remove all', self) action_back.triggered.connect(lambda: self.toggle_view(old_view)) action_remove_all.triggered.connect( lambda: self.view.delete_bookmark_all('user_book', self.view.b_id)) self.MainToolBar.addAction(action_back) self.MainToolBar.addAction(action_remove_all) def download_file(self): file_path = QFileDialog.getSaveFileName(self, 'Save File', 'C:\\', 'Texts (*.txt)')[0] file_content = get_chapter('single', self.b_id, self.chap_id)[1] if file_content == []: self.display_status_message('Fail to download.', 2000) with open(file_path, 'w', encoding='utf-8') as fp: fp.write(file_content) self.display_status_message('Successfully downloaded.', 2000) def set_current_user(self, uid): self.uid = uid def set_current_book(self, b_id): self.b_id = b_id def set_current_chapter(self, chap_id): self.chap_id = chap_id def set_page_length(self, page_length): self.page_length = page_length if self.label_choose_page is not None: self.label_choose_page.setText( f' ( {self.page_num + 1} / {self.page_length} ) ') def set_current_page(self, page_num): self.page_num = page_num if self.label_choose_page is not None: self.label_choose_page.setText( f' ( {self.page_num + 1} / {self.page_length} ) ') def page_minus_onclick(self): if self.page_num == 0: self.display_status_message('We are at the first page.', 2000) else: self.set_current_page(self.page_num - 1) self.view.set_page(self.page_num) def page_plus_onclick(self): if self.page_num == self.page_length - 1: self.display_status_message('We are at the last page.', 2000) else: self.set_current_page(self.page_num + 1) self.view.set_page(self.page_num) def page_choose_onfinish(self): page_num = int(self.widget_choose_page.text()) - 1 self.set_current_page(page_num) self.view.set_page(page_num) def chapter_minus_onclick(self): chap_list = get_chapter('simple', self.b_id) chap_list.sort() pos = chap_list.index(self.chap_id) if pos == 0: self.display_status_message('We are at the first chapter.', 2000) else: self.chap_id = chap_list[pos - 1] self.view.refresh(self.b_id, self.chap_id) def chapter_plus_onclick(self): chap_list = get_chapter('simple', self.b_id) chap_list.sort() chap_list_length = len(chap_list) pos = chap_list.index(self.chap_id) if pos == chap_list_length - 1: self.display_status_message('We are at the last chapter.', 2000) else: self.chap_id = chap_list[pos + 1] self.view.refresh(self.b_id, self.chap_id) def open_add_bookmark_dialog(self): self.add_bookmark_dialog = AddBookmarkDialog() self.add_bookmark_dialog.display_status_signal.connect( self.display_status_message) self.add_bookmark_dialog.close_dialog_signal.connect( self.close_add_bookmark_dialog) self.add_bookmark_dialog.transmit_bookmark_name_signal.connect( self.add_bookmark) self.add_bookmark_dialog.show() def close_add_bookmark_dialog(self): self.add_bookmark_dialog.close() self.add_bookmark_dialog.display_status_signal.disconnect( self.display_status_message) self.add_bookmark_dialog.close_dialog_signal.disconnect( self.close_add_bookmark_dialog) self.add_bookmark_dialog.transmit_bookmark_name_signal.disconnect( self.add_bookmark) self.add_bookmark_dialog = None def add_bookmark(self, bm_name): request = {'type': 'get_bookmark_id', 'data': {}} resp = get_response(request) assert resp['type'] == 'get_bookmark_id' resp_data = resp['data'] if resp_data['status'] == 'error': return resp['type'] bm_id = resp_data['content'] return add_bookmark(self.uid, self.b_id, bm_id, bm_name, self.chap_id, self.page_num) def logout_action_onclick(self): resp = get_logout_response(self.uid) assert resp['type'] == 'logout' resp_data = resp['data'] self.uid = None self.toggle_view(LoginView) message = 'Successfully Logouted.' if resp_data[ 'status'] == 'ok' else resp_data['type'] self.display_status_message(message, 3000)
class AddOTPWidget(TritonWidget): def __init__(self, base, *args, **kwargs): TritonWidget.__init__(self, base, *args, **kwargs) self.key = None self.type = Globals.OTPAuth self.setWindowTitle('Add Authenticator') self.setBackgroundColor(self, Qt.white) self.boxLayout = QVBoxLayout(self) self.boxLayout.setContentsMargins(20, 20, 20, 20) self.nameWidget = TextboxWidget(base, 'Name:') self.secretLabel = QLabel() self.secretLabel.setText( 'Enter the Secret Code. If you have a QR code,\nyou can paste the URL of the image instead.' ) self.secretLabel.setFont(QFont('Helvetica', 10)) self.secretBox = QLineEdit() self.secretBox.setFixedWidth(300) self.secretBox.setFont(QFont('Helvetica', 10)) self.secretBox.textChanged.connect( lambda text: self.invalidateSecret()) self.verifyLabel = QLabel() self.verifyLabel.setText( 'Click the Verify button to check the first code.') self.verifyLabel.setFont(QFont('Helvetica', 10)) self.verifyBox = QLineEdit() self.verifyBox.setFixedWidth(150) self.verifyBox.setFont(QFont('Helvetica', 10)) self.verifyBox.setEnabled(False) palette = QPalette() palette.setColor(QPalette.Text, Qt.black) self.verifyBox.setPalette(palette) self.verifyBox.setAlignment(Qt.AlignCenter) self.verifyButton = QPushButton('Verify') self.verifyButton.clicked.connect(self.checkVerify) self.verifyButton.setFixedWidth(150) self.addButton = QPushButton('OK') self.addButton.clicked.connect(self.add) self.boxLayout.addWidget(self.nameWidget) self.boxLayout.addSpacing(10) self.boxLayout.addWidget(self.secretLabel) self.boxLayout.addWidget(self.secretBox) self.boxLayout.addSpacing(10) self.boxLayout.addWidget(self.verifyLabel) self.boxLayout.addWidget(self.verifyBox, 0, Qt.AlignCenter) self.boxLayout.addWidget(self.verifyButton, 0, Qt.AlignCenter) self.boxLayout.addSpacing(10) self.boxLayout.addWidget(self.addButton, 0, Qt.AlignRight) self.setFixedSize(self.sizeHint()) self.center() self.show() def getName(self): return self.nameWidget.box.text() def getAccount(self): return { 'name': self.getName(), 'type': self.type, 'key': self.key, 'icon': 'icons/WinAuthIcon.png' } def invalidateSecret(self, value=''): self.key = None self.verifyBox.setText(value) def checkVerify(self): self.key = self.secretBox.text() if not self.key: self.invalidateSecret('Invalid') return self.key = self.base.readQRLink(self.key) or self.key self.key = self.key.upper().replace(' ', '') try: self.verifyBox.setText(self.base.getAuthCode(self.getAccount())) except: self.invalidateSecret('Invalid') def add(self): if not self.key or not self.getName(): return self.base.addAccount(self.getAccount()) self.close()