def __create_source_layout(self, side): sourceLayout = QVBoxLayout() selectedSourceFrame = QFrame() selectedSourceFrame.setFrameShape(QFrame.Box) selectedSourceFrame.setFrameShadow(QFrame.Raised) selectedSourceLayout = QGridLayout(selectedSourceFrame) sourceLabel = QLabel("Selected account: None") sourceLabel.setObjectName("SourceLabel{}".format(side)) selectedSourceLayout.addWidget(sourceLabel, 0, 0) changeSourceBtn = QPushButton("Change...") changeSourceBtn.clicked.connect(lambda: self.__account_select(side)) selectedSourceLayout.addWidget(changeSourceBtn, 0, 1) playlistLabel = QLabel("Selected playlist:") playlistLabel.setObjectName("PlaylistLabel{}".format(side)) playlistLabel.setDisabled(True) selectedSourceLayout.addWidget(playlistLabel, 1, 0) playlistSelect = QComboBox() playlistSelect.setDisabled(True) playlistSelect.setObjectName("Playlist{}".format(side)) playlistSelect.currentIndexChanged.connect( lambda: self.__playlist_select(side)) selectedSourceLayout.addWidget(playlistSelect, 1, 1) sourceLayout.addWidget(selectedSourceFrame) trackList = QListWidget() trackList.setObjectName("Tracklist{}".format(side)) trackList.currentItemChanged.connect(self.__track_select) sourceLayout.addWidget(trackList) return sourceLayout
def __init__(self, x, y, w, h): QWidget.__init__(self) self.x = x self.y = y self.w = w self.h = h self.title = Box.title start_position = (self.x, self.y, self.w, self.h) self.setGeometry(*start_position) width = self.w - self.x height = self.h - self.y self.resize(width, height) tb = QtWidgets.QToolBar self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setAttribute(Qt.WA_TranslucentBackground) layout = QtWidgets.QHBoxLayout(self) frame = QFrame(self) # frame.setFrameShape(QFrame.StyledPanel) frame.setFrameShape(QFrame.WinPanel) frame.setLineWidth(.1) layout.addWidget(frame) self.show()
def __init__(self, route=None): super().__init__() layout = QVBoxLayout() self.route = route self.preview_text_edit = QTextEdit() self.preview_text_edit.setFont(TEXT_FONT) self.preview_text_edit.setReadOnly(True) if route is not None: if route.group is not None: for parameter in route.group.parameters: param_layout = self._create_parameter_layout( route.group.storage_prefix, parameter) layout.addLayout(param_layout) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) layout.addWidget(line) for parameter in route.parameters: param_layout = self._create_parameter_layout( route.storage_prefix, parameter) layout.addLayout(param_layout) self.highlighter = TextHighlighter(self.preview_text_edit.document()) self._update_preview() layout.addWidget(self.preview_text_edit) self.setLayout(layout)
def horizontal_line(): line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) line.setFixedHeight(2) line.setContentsMargins(0, 30, 0, 0) return line
def __init__(self): super().__init__() page2Layout = QVBoxLayout(self) table_header = QHBoxLayout() label0 = QLabel() label0.setObjectName("label0") table_header.addWidget(label0) table_header.addItem(QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Minimum)) label1 = QLabel() label1.setObjectName("label1") table_header.addWidget(label1) page2Layout.addLayout(table_header) hLine = QFrame(self.__songs_table) hLine.setFrameShape(QFrame.HLine) hLine.setFrameShadow(QFrame.Sunken) page2Layout.addWidget(hLine) scrollArea = QScrollArea() scrollClient = QWidget() scrollClient.setObjectName("scrollClient") scrollArea.setWidgetResizable(True) scrollArea.setWidget(scrollClient) page2Layout.addWidget(scrollArea) self.__new_song_row.connect(self.__add_song_row)
def _create_vertical_line(): vertical_line = QFrame() vertical_line.setFixedWidth(20) vertical_line.setFrameShape(QFrame.VLine) vertical_line.setFrameShadow(QFrame.Sunken) vertical_line.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) vertical_line.setMinimumHeight(300) return vertical_line
class Separator: def __init__(self): self.widget = QFrame() self.widget.setFrameShape(QFrame.HLine) self.widget.setFrameShadow(QFrame.Sunken) def getWidget(self): return self.widget
def build_ui(self): self.setGeometry(50, 50, 450, 300) self.setMinimumSize(400, 300) self.setWindowTitle('Spore Reporter') layout = QVBoxLayout() # self.err_wdg = QWidget() # err_layout = QHBoxLayout(self.err_wdg) # layout.addWidget(err_wdg) # # err_lbl = 'Ops..\nSpore seems to have caused an error.\n' info_msg = 'Help to improve Spore by anonymously submitting your logs' self.info_lbl = QLabel(info_msg) layout.addWidget(self.info_lbl) self.address_edt = QLineEdit() self.address_edt.setPlaceholderText('E-Mail Address (optional)') layout.addWidget(self.address_edt) self.subject_edt = QLineEdit() self.subject_edt.setPlaceholderText('Subject (optional)') layout.addWidget(self.subject_edt) self.msg_edt = QTextEdit() self.msg_edt.setPlaceholderText('Message (optional)') self.msg_edt.setFixedHeight(60) layout.addWidget(self.msg_edt) self.log_edt = QTextEdit() self.log_edt.setReadOnly(True) self.log_edt.setLineWrapMode(QTextEdit.NoWrap) layout.addWidget(self.log_edt) ctrl_layout = QGridLayout() layout.addLayout(ctrl_layout) self.submit_btn = QPushButton('Submit') ctrl_layout.addWidget(self.submit_btn, 0, 0, 1, 1) self.cancel_btn = QPushButton('Cancel') ctrl_layout.addWidget(self.cancel_btn, 0, 1, 1, 1) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) ctrl_layout.addWidget(line, 1, 0, 1, 2) self.disable_btn = QPushButton('Disable Reporter') ctrl_layout.addWidget(self.disable_btn, 2, 0, 1, 1) self.auto_btn = QPushButton('Send Reports Automatically') ctrl_layout.addWidget(self.auto_btn, 2, 1, 1, 1) self.setLayout(layout)
class Layout_Main_Window(QWidget): def __init__(self): QWidget.__init__(self) self.Main_Layout = QHBoxLayout() self.Child_1 = Layout_Child_1() self.Child_2 = Layout_Child_2() self.Main_Layout.addWidget(self.Child_1) self.line = QFrame() self.line.setFrameShape(QFrame.VLine) self.line.setFrameShadow(QFrame.Sunken) self.Main_Layout.addWidget(self.line) self.Main_Layout.addWidget(self.Child_2) self.setLayout(self.Main_Layout)
class PageAbout(QWidget): def __init__(self, parent=None): QWidget.__init__(self) parent.addWidget(self) self.gridLayout_about = QGridLayout(self) self.frame_about = QFrame(self) self.frame_about.setEnabled(True) self.frame_about.setStyleSheet(styles.frame_about) self.frame_about.setFrameShape(QFrame.StyledPanel) self.frame_about.setFrameShadow(QFrame.Raised) self.gridLayout_about.addWidget(self.frame_about, 0, 1, 1, 1) self.gridLayout_frame_about = QGridLayout(self.frame_about) self.gridLayout_frame_about.setContentsMargins(-1, 60, -1, -1) self.spacer_about_l = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.spacer_about_r = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.spacer_about_b = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.gridLayout_frame_about.addItem(self.spacer_about_l, 0, 0, 1, 1) self.gridLayout_frame_about.addItem(self.spacer_about_r, 0, 2, 1, 1) self.gridLayout_frame_about.addItem(self.spacer_about_b, 3, 1, 1, 1) self.label_about_name = QLabel("WebCheck", self.frame_about) self.label_about_name.setStyleSheet(styles.label_about_name) self.label_about_name.setAlignment(Qt.AlignCenter) self.gridLayout_frame_about.addWidget(self.label_about_name, 0, 1, 1, 1) self.label_about_name = QLabel( "Made by Eugene Oros & Michał Piotrowski", self.frame_about) self.label_about_name.setStyleSheet(styles.label_about_made) self.label_about_name.setAlignment(Qt.AlignCenter) self.gridLayout_frame_about.addWidget(self.label_about_name, 1, 1, 1, 1) self.label_about_version = QLabel("Version 1.0.0", self.frame_about) self.label_about_version.setStyleSheet(styles.label_about_version) self.label_about_version.setAlignment(Qt.AlignCenter) self.gridLayout_frame_about.addWidget(self.label_about_version, 2, 0, 1, 3) self.label_about_c = QLabel("\u00a9 All rights reserved", self.frame_about) self.label_about_c.setStyleSheet(styles.label_about_c) self.label_about_c.setAlignment(Qt.AlignCenter) self.gridLayout_frame_about.addWidget(self.label_about_c, 3, 0, 1, 3)
def __init__(self, parent=None): '''Constructor Function''' QWidget.__init__(self, parent) self.Main_Layout = QHBoxLayout() self.Child_1 = Layout_Child_1() self.Child_2 = Layout_Child_2() self.Main_Layout.addWidget(self.Child_1) # Add a Saperator line = QFrame() line.setFrameShape(QFrame.VLine) line.setFrameShadow(QFrame.Sunken) self.Main_Layout.addWidget(line) self.Main_Layout.addWidget(self.Child_2) self.setLayout(self.Main_Layout)
def set_up_group_box(self): self.desc_group_box.setLayout(QVBoxLayout()) self.desc_label = QLabel(self.model.desc) self.desc_label.setWordWrap(True) self.desc_group_box.layout().addWidget(self.desc_label) if isinstance(self.model, (MonsterCard)): self.desc_group_box.setTitle(self.get_group_box_title()) line = QFrame() line.setFrameShape((QFrame.HLine)) line.setFrameShadow(QFrame.Sunken) self.desc_group_box.layout().addWidget(line) label = QLabel( f"ATK/{self.model.attack} DEF/{self.model.defence}") label.setAlignment(Qt.AlignRight) self.desc_group_box.layout().addWidget(label)
def __init__(self): super(Main_Widget,self).__init__() First = First_Widget() Second = Second_Widget() Third = Second_Widget() Line = QFrame() Line.setFrameShape(QFrame.VLine) Line.setFrameShadow(QFrame.Sunken) H_Layout = QHBoxLayout() H_Layout.addWidget(Second) #H_Layout.addWidget(First) H_Layout.addWidget(Line) H_Layout.addWidget(Third) self.setLayout(H_Layout)
def __init__(self): super(Zero_Layout,self).__init__() First = First_Layout() Second = Second_Layout() Third = Third_Layout() H_layout = QHBoxLayout() H_layout.addWidget(First) line = QFrame() line.setFrameShape(QFrame.VLine) line.setFrameShadow(QFrame.Sunken) H_layout.addWidget(line) #H_layout.addWidget(Second) H_layout.addWidget(Third) self.setLayout(H_layout)
def __init__(self, controller, parent=None): super(CommandParser, self).__init__(parent) self.controller = controller cmnd2send_label = QLabel('Command:') cmnd2send_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.cmnd2send_editor = QLineEdit() # cmnd2send_editor.setKeyboardTracking(False) self.cmnd2send_editor.setAlignment(Qt.AlignLeft) self.cmnd2send_editor.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) # cmnd2send_editor.setClearButtonEnabled() send_button = QPushButton('Send') send_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) separator = QFrame() separator.setFrameShape(QFrame.HLine) separator.setFrameShadow(QFrame.Sunken) separator.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) scrollbar = QScrollBar() cmnd_received_label = QLabel('RESPONSE:') self.cmnd_received_window = QTextEdit() # self.cmnd_received_window.moveCursor(QTextCursor.Down) self.cmnd_received_window.setReadOnly(True) self.cmnd_received_window.setVerticalScrollBar(scrollbar) # Layout editor_layout = QGridLayout() editor_layout.addWidget(cmnd2send_label, 0, 0) editor_layout.addWidget(self.cmnd2send_editor, 0, 1) editor_layout.addWidget(send_button, 0, 2) editor_layout.addWidget(separator, 1, 0, 1, 3) editor_layout.addWidget(cmnd_received_label, 2, 0, 1, 3) editor_layout.addWidget(self.cmnd_received_window, 3, 0, 1, 3) layout = QHBoxLayout() layout.addLayout(editor_layout) self.setLayout(layout) # Signals and slots send_button.clicked.connect(self.parse_cmnd)
class Welcome_Widget(QWidget): def __init__(self, parent=None): super(Welcome_Widget, self).__init__(parent) self.setUp_UI() def setUp_UI(self): self.image = Image_Widget(self) self.line = QFrame() self.line.setFrameShape(QFrame.VLine) self.line.setFrameShadow(QFrame.Sunken) self.login = Login_Widget(self) self.layout = QHBoxLayout() self.layout.addWidget(self.image) self.layout.addWidget(self.line) self.layout.addWidget(self.login) self.setLayout(self.layout)
def _init_widgets(self): self.resize(530, 180) main_layout = QVBoxLayout() frame = QFrame() frame.setFrameShape(QFrame.NoFrame) frame.setFrameShadow(QFrame.Plain) frameLayout = QVBoxLayout() self.connectRad = QRadioButton(frame) self.createRad = QRadioButton(frame) self.connectRad.setChecked(True) self.connectRad.toggled.connect(self.handleRadioButtons) self.createRad.toggled.connect(self.handleRadioButtons) frameLayout.addWidget(self.connectRad) internalFrame = QFrame() internalFrameLayout = QHBoxLayout(internalFrame) hostLabel = QLabel() portLabel = QLabel() self.hostText = QLineEdit() self.portText = QLineEdit() internalFrameLayout.addWidget(hostLabel) internalFrameLayout.addWidget(self.hostText) internalFrameLayout.addWidget(portLabel) internalFrameLayout.addWidget(self.portText) self.portText.setMaximumSize(QSize(80, 200)) internalFrame.setLayout(internalFrameLayout) frameLayout.addWidget(internalFrame) frameLayout.addWidget(self.createRad) frame.setLayout(frameLayout) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) main_layout.addWidget(frame) main_layout.addWidget(self.buttonBox) self.setLayout(main_layout) self.setWindowTitle("Cartprograph Connect") self.connectRad.setText("Connect to Existing Cartprograph Server") self.createRad.setText("Create New Cartprograph Server") hostLabel.setText("Host") portLabel.setText("Port")
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setFixedSize(1200, 920) self.setWindowTitle("Vlasov Roman lr3") # OpenGL widget glWidgetW = 800 glWidgetH = 900 self.OpenGLWidget = OpenGLView() self.OpenGLWidget.setFixedSize(glWidgetW, glWidgetH) self.OpenGLWidget.setIterations(0) # number of iterations minIter = 0 maxIter = 6 self.iterationsLabel = QLabel("Number of iterations: ") self.iterationsSpinBox = QSpinBox() self.iterationsSpinBox.setMinimum(minIter) self.iterationsSpinBox.setMaximum(maxIter) self.iterationsSpinBox.valueChanged.connect(self.onSpinPointsChanged) self.iterationsSlider = QSlider(QtCore.Qt.Horizontal) self.iterationsSlider.setMinimum(minIter) self.iterationsSlider.setMaximum(maxIter) self.iterationsSlider.valueChanged.connect(self.onSliderPointsChanged) self.iterationsMinLabel = QLabel("Min: %d" % minIter) self.iterationsMinLabel.setFixedWidth(40) self.iterationsMaxLabel = QLabel("Max: %d" % maxIter) self.iterationsMaxLabel.setFixedWidth(60) line1 = QFrame() line1.setFrameShape(QFrame.HLine) layoutAmount = QHBoxLayout() layoutAmount.addWidget(self.iterationsMinLabel) layoutAmount.addWidget(self.iterationsSpinBox) layoutAmount.addWidget(self.iterationsMaxLabel) # tools panel layout layoutTools = QVBoxLayout() layoutTools.addWidget(self.iterationsLabel) layoutTools.addLayout(layoutAmount) layoutTools.addWidget(self.iterationsSlider) verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) layoutTools.addItem(verticalSpacer) # window layout layout = QHBoxLayout() layout.addWidget(self.OpenGLWidget) layout.addLayout(layoutTools) self.setLayout(layout)
class Ui_FE14ChapterEditor(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.toolbar = QToolBar() self.addToolBar(self.toolbar) self.add_chapter_action = QAction("Add Chapter") self.hide_selector_action = QAction("Toggle Selection Pane") self.toolbar.addAction(self.add_chapter_action) self.toolbar.addSeparator() self.toolbar.addAction(self.hide_selector_action) self.selector_layout = QVBoxLayout() self.chapter_search_bar = QLineEdit() self.chapter_search_bar.setPlaceholderText("Search...") self.chapter_list_view = QListView() self.selector_layout.addWidget(self.chapter_search_bar) self.selector_layout.addWidget(self.chapter_list_view) self.selector_widget = QWidget() self.selector_widget.setLayout(self.selector_layout) self.selector_widget.setFixedWidth(225) self.config_tab = FE14ChapterConfigTab() self.map_tab = FE14MapEditor() self.characters_tab = FE14CharacterEditor(is_person=True) self.conversation_tab = FE14ConversationEditor() self.tab_widget = QTabWidget() self.tab_widget.addTab(self.config_tab, "Config") self.tab_widget.addTab(self.map_tab, "Map") self.tab_widget.addTab(self.characters_tab, "Characters") self.tab_widget.addTab(self.conversation_tab, "Text") self.main_layout = QHBoxLayout() self.main_widget = QWidget() self.visual_splitter = QFrame() self.visual_splitter.setFrameShape(QFrame.VLine) self.visual_splitter.setFrameShadow(QFrame.Sunken) self.main_widget.setLayout(self.main_layout) self.main_layout.addWidget(self.selector_widget) self.main_layout.addWidget(self.visual_splitter) self.main_layout.addWidget(self.tab_widget) self.setCentralWidget(self.main_widget)
def initUI(self): hbox = QHBoxLayout() topleft = QFrame(self) topleft.setFrameShape(QFrame.StyledPanel) # topleft.setFrameShape(QFrame.Shadow) # ? 报错 topright = QFrame(self) topright.setFrameShape(QFrame.StyledPanel) bottom = QFrame(self) bottom.setFrameShape(QFrame.StyledPanel) splitter1 = QSplitter(Qt.Horizontal) # 横向增加部件 splitter1.addWidget(topleft) splitter1.addWidget(topright) splitter2 = QSplitter(Qt.Vertical) splitter2.addWidget(splitter1) splitter2.addWidget(bottom) hbox.addWidget(splitter2) self.setLayout(hbox) self.setGeometry(300, 300, 600, 400) self.setWindowTitle("QSplitter") self.show()
def initUI(self): hbox = QHBoxLayout(self) topleft = QFrame(self) topleft.setFrameShape(QFrame.StyledPanel) topright = QFrame(self) topright.setFrameShape(QFrame.StyledPanel) bottom = QFrame(self) bottom.setFrameShape(QFrame.StyledPanel) splitter1 = QSplitter(QtCore.Qt.Horizontal) splitter1.addWidget(topleft) splitter1.addWidget(topright) splitter2 = QSplitter(QtCore.Qt.Vertical) splitter2.addWidget(splitter1) splitter2.addWidget(bottom) hbox.addWidget(splitter2) self.setLayout(hbox) QApplication.setStyle(QStyleFactory.create('Cleanlooks')) self.setGeometry(500, 500, 500, 500) self.setWindowTitle('QSplitter') self.show()
def setupLayout(self): # OpenGL widget glWidgetW = 800 glWidgetH = 900 self.OpenGLWidget = OpenGLView() self.OpenGLWidget.setFixedSize(glWidgetW, glWidgetH) self.OpenGLWidget.updatePoints(self.x, self.y, self.z) # radio buttons self.cubicSplineInterpolationMode = QRadioButton( "Cubic Spline Interpolation mode") self.cubicSplineInterpolationMode.setChecked(True) self.cubicSplineInterpolationMode.toggled.connect( self.onModeRadioButtonToggled) self.BesierCurveMode = QRadioButton(" Besier Curve mode") line1 = QFrame() line1.setFrameShape(QFrame.HLine) # point coords layout pointsLayout = QVBoxLayout() [ pointsLayout.addLayout( self.createPointWidget(self.x[i], self.y[i], self.z[i])) for i in range(self.points) ] # tools panel layout layoutTools = QVBoxLayout() layoutTools.addWidget(self.cubicSplineInterpolationMode) layoutTools.addWidget(self.BesierCurveMode) layoutTools.addWidget(line1) layoutTools.addLayout(pointsLayout) verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) layoutTools.addItem(verticalSpacer) # window layout layout = QHBoxLayout() layout.addWidget(self.OpenGLWidget) layout.addLayout(layoutTools) self.setLayout(layout)
class Ui_FilewriterCtrl(object): def setupUi(self, FilewriterCtrl): FilewriterCtrl.resize(649, 450) broker_placeholder_text = "address:port/topic" self.central_widget = QWidget(FilewriterCtrl) self.vertical_layout_2 = QVBoxLayout(self.central_widget) self.vertical_layout = QVBoxLayout() self.horizontal_layout = QHBoxLayout() self.horizontal_layout.setContentsMargins(-1, -1, 0, -1) self.status_layout = QVBoxLayout() self.status_layout.setContentsMargins(-1, -1, -1, 0) self.status_topic_layout = QHBoxLayout() self.status_topic_layout.setContentsMargins(-1, -1, -1, 0) self.status_broker_label = QLabel(self.central_widget) self.status_topic_layout.addWidget(self.status_broker_label) self.status_broker_edit = QLineEdit(self.central_widget) self.status_broker_edit.setPlaceholderText(broker_placeholder_text) self.status_topic_layout.addWidget(self.status_broker_edit) self.status_layout.addLayout(self.status_topic_layout) self.line_2 = QFrame(self.central_widget) self.line_2.setFrameShape(QFrame.HLine) self.line_2.setFrameShadow(QFrame.Sunken) self.status_layout.addWidget(self.line_2) self.file_writer_table_group = QGroupBox(self.central_widget) size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(1) size_policy.setHeightForWidth( self.file_writer_table_group.sizePolicy().hasHeightForWidth()) self.file_writer_table_group.setSizePolicy(size_policy) self.vertical_layout_4 = QVBoxLayout(self.file_writer_table_group) self.vertical_layout_3 = QVBoxLayout() self.file_writers_list = QTreeView(self.file_writer_table_group) self.file_writers_list.setEditTriggers( QAbstractItemView.NoEditTriggers) self.file_writers_list.setIndentation(0) self.vertical_layout_3.addWidget(self.file_writers_list) self.vertical_layout_4.addLayout(self.vertical_layout_3) self.status_layout.addWidget(self.file_writer_table_group) self.files_group = QGroupBox(self.central_widget) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(4) size_policy.setHeightForWidth( self.files_group.sizePolicy().hasHeightForWidth()) self.files_group.setSizePolicy(size_policy) self.vertical_layout_6 = QVBoxLayout(self.files_group) self.files_list = QTreeView(self.files_group) self.files_list.setIndentation(0) self.vertical_layout_6.addWidget(self.files_list) self.vertical_layout_5 = QVBoxLayout() self.horizontal_layout_4 = QHBoxLayout() spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontal_layout_4.addItem(spacer) self.stop_file_writing_button = QPushButton(self.files_group) self.stop_file_writing_button.setEnabled(False) self.horizontal_layout_4.addWidget(self.stop_file_writing_button) self.vertical_layout_5.addLayout(self.horizontal_layout_4) self.vertical_layout_6.addLayout(self.vertical_layout_5) self.status_layout.addWidget(self.files_group) self.horizontal_layout.addLayout(self.status_layout) self.line = QFrame(self.central_widget) self.line.setFrameShape(QFrame.VLine) self.line.setFrameShadow(QFrame.Sunken) self.horizontal_layout.addWidget(self.line) self.command_layout = QVBoxLayout() self.command_layout.setContentsMargins(-1, 0, -1, 0) self.command_broker_layout = QHBoxLayout() self.command_broker_label = QLabel(self.central_widget) self.command_broker_layout.addWidget(self.command_broker_label) self.command_broker_edit = QLineEdit(self.central_widget) self.command_broker_edit.setPlaceholderText(broker_placeholder_text) self.command_broker_layout.addWidget(self.command_broker_edit) self.command_layout.addLayout(self.command_broker_layout) self.command_widget = FilewriterCommandWidget(FilewriterCtrl) self.command_layout.addWidget(self.command_widget) self.horizontal_layout.addLayout(self.command_layout) self.vertical_layout.addLayout(self.horizontal_layout) self.vertical_layout_2.addLayout(self.vertical_layout) FilewriterCtrl.setCentralWidget(self.central_widget) self.status_broker_label.setText("Status broker") self.file_writer_table_group.setTitle("File-writers") self.files_group.setTitle("Files") self.stop_file_writing_button.setText("Stop file-writing") self.command_broker_label.setText("Command broker") self.command_broker_edit.setPlaceholderText("address:port/topic") QMetaObject.connectSlotsByName(FilewriterCtrl)
class ElementAllegroMonitored(QFrame): def __init__(self, name, link, is_done, price, xpath, time, is_monitoring, parent=None, shared_dict=None): QFrame.__init__(self, parent) self.shared_dict = shared_dict self.setMinimumSize(QSize(0, 300)) self.setStyleSheet("""QFrame{border-bottom: 0.5px solid #aaa;}""") self.setFrameShape(QFrame.StyledPanel) self.setFrameShadow(QFrame.Raised) self.horizontalLayout = QHBoxLayout(self) # create description frame and layout self.frame_description = QFrame(self) self.frame_description.setMinimumSize(QSize(440, 16777215)) self.frame_description.setStyleSheet("""QFrame{border: none;}""") self.frame_description.setFrameShape(QFrame.StyledPanel) self.frame_description.setFrameShadow(QFrame.Raised) self.gridLayout_description = QGridLayout(self.frame_description) self.horizontalLayout.addWidget(self.frame_description) self.gridLayout_description.setColumnStretch(0, 1) self.gridLayout_description.setColumnStretch(1, 2) self.gridLayout_description.setColumnStretch(2, 3) self.gridLayout_description.setColumnStretch(3, 1) self.gridLayout_description.setColumnStretch(4, 6) # fill description layout self.label_name = QLabel(name, self.frame_description) self.label_name.setStyleSheet(styles.label_allegro_monitored_name) self.label_name.setTextFormat(Qt.MarkdownText) self.label_name.setAlignment(Qt.AlignJustify | Qt.AlignVCenter) self.label_name.setWordWrap(False) self.gridLayout_description.addWidget(self.label_name, 0, 0, 1, 5) self.url_link = "<a href=\"" + link + "\" style = \" color: #838836; text-decoration: none; font-family:corbel; title=\"Go to monitored page\"\">check product</a>" self.label_monitored_link = QLabel(url_link, self.frame_description) self.label_monitored_link.setStyleSheet(styles.label_allegro_monitored_link) self.gridLayout_description.addWidget(self.label_monitored_link, 1, 1, 2, 2) self.label_monitored_link.setOpenExternalLinks(True) self.label_stat = QLabel(self.frame_description) self.label_stat.setStyleSheet(styles.label_allegro_monitored_stat) self.gridLayout_description.addWidget(self.label_stat, 1, 4, 1, 1) self.label_is_on = QLabel(self.frame_description) self.label_is_on.setStyleSheet(styles.label_allegro_monitored_stat) self.gridLayout_description.addWidget(self.label_is_on, 5, 0, 1, 2) self.label_new_time = QLabel("Actual refresh time[s]: " + str(time)+" s", self.frame_description) self.label_new_time.setStyleSheet(styles.label_allegro_monitored_stat) self.gridLayout_description.addWidget(self.label_new_time, 4, 0, 1, 3) self.lineEdit_new_time = QLineEdit(self.frame_description) self.lineEdit_new_time.setMinimumSize(QSize(0, 33)) self.lineEdit_new_time.setStyleSheet(styles.lineEdit) self.gridLayout_description.addWidget(self.lineEdit_new_time, 4, 3, 1, 2) self.lineEdit_new_time.setPlaceholderText("Set new interval") self.label_new_price = QLabel("Actual price: " + str(price), self) self.label_new_price.setStyleSheet(styles.label_allegro_monitored_stat) self.gridLayout_description.addWidget(self.label_new_price, 3, 0, 1, 3) self.lineEdit_new_price = QLineEdit(self) self.lineEdit_new_price.setMinimumSize(QSize(0, 35)) self.lineEdit_new_price.setStyleSheet(styles.lineEdit) self.gridLayout_description.addWidget(self.lineEdit_new_price, 3, 3, 1, 2) self.lineEdit_new_price.setPlaceholderText("Set new price") self.label_img_link = QLabel(self.frame_description) self.label_img_link.setMaximumSize(QSize(20, 20)) self.label_img_link.setStyleSheet("""QLabel{border: none;}""") self.label_img_link.setPixmap(QPixmap(os.path.join(path, "img/link.png"))) self.label_img_link.setScaledContents(True) self.gridLayout_description.addWidget(self.label_img_link, 1, 0, 2, 1) self.label_img_stat = QLabel("done", self.frame_description) if is_done: self.label_stat.setText("done") self.label_img_stat.setPixmap(QPixmap(os.path.join(path, "img/check.png"))) else: self.label_stat.setText("in progress") self.label_img_stat.setPixmap(QPixmap(os.path.join(path, "img/loading.png"))) self.label_img_stat.setMaximumSize(QSize(20, 20)) self.label_img_stat.setStyleSheet("""QLabel{border: none;}""") self.label_img_stat.setScaledContents(True) self.gridLayout_description.addWidget(self.label_img_stat, 1, 3, 1, 1) self.label_img_monitor = QLabel("done", self.frame_description) if is_monitoring: monitor_text = "I am just monitoring" self.label_img_monitor.setPixmap(QPixmap(os.path.join(path, "img/monitoring.png"))) else: monitor_text = "I am going to buy" self.label_img_monitor.setPixmap(QPixmap(os.path.join(path, "img/buy.png"))) self.label_is_monitoring = QLabel(monitor_text, self) self.label_is_monitoring.setStyleSheet(styles.label_allegro_monitored_stat) self.gridLayout_description.addWidget(self.label_is_monitoring, 2, 4, 1, 1) self.label_img_monitor.setMaximumSize(QSize(20, 20)) self.label_img_monitor.setStyleSheet("""QLabel{border: none;}""") self.label_img_monitor.setScaledContents(True) self.gridLayout_description.addWidget(self.label_img_monitor, 2, 3, 1, 1) # create spacer and delete btn self.spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(self.spacer) self.pushButton_delete = QPushButton(self) # self.pushButton_delete.clicked.connect( lambda: self.deleteLater()) self.pushButton_delete.clicked.connect(lambda: self.on_delete(link)) icon = QIcon() icon.addFile(os.path.join(path, "img/delete.png"), QSize(), QIcon.Selected, QIcon.Off) # icon.Active.addFile(os.path.join(path, "img/icon.png"), QSize(), QIcon.Selected, QIcon.Off) self.pushButton_delete.setIcon(icon) self.pushButton_delete.setIconSize(QSize(50, 50)) self.pushButton_delete.setStyleSheet("""QPushButton{border:none; }""") self.pushButton_delete.setCursor(QCursor(Qt.PointingHandCursor)) # self.pushButton_delete.ico self.horizontalLayout.addWidget(self.pushButton_delete) self.is_on = data.get_switch_state(link) self.pushButton_switch = QPushButton(self) self.pushButton_switch.clicked.connect(lambda: self.on_switch(link)) self.icon_on = QIcon() self.icon_off = QIcon() self.icon_on.addFile(os.path.join(path, "img/switch_on.png"), QSize(), QIcon.Selected, QIcon.On) self.icon_off.addFile(os.path.join(path, "img/switch_off.png"), QSize(), QIcon.Selected, QIcon.Off) if self.is_on: self.label_is_on.setText("Disable") self.pushButton_switch.setIcon(self.icon_on) else: self.label_is_on.setText("Enable") self.pushButton_switch.setIcon(self.icon_off) self.pushButton_switch.setIconSize(QSize(100, 40)) self.pushButton_switch.setStyleSheet("""QPushButton{border:none; }""") self.pushButton_switch.setCursor(QCursor(Qt.PointingHandCursor)) self.gridLayout_description.addWidget(self.pushButton_switch, 5, 2, 1, 1) self.pushButton_save_changes = QPushButton("Save", self) self.pushButton_save_changes.clicked.connect(lambda: self.on_save_changes(link)) self.pushButton_save_changes.setIconSize(QSize(100, 20)) self.pushButton_save_changes.setStyleSheet(styles.btn_dark) self.pushButton_save_changes.setCursor(QCursor(Qt.PointingHandCursor)) self.gridLayout_description.addWidget(self.pushButton_save_changes, 5, 3, 1, 2) def on_delete(self, link): data.delete_monitored_element(link) self.deleteLater() self.shared_dict['isTerminatedP2'] = True def on_save_changes(self, link): data.change_price_time(link, self.lineEdit_new_price.text(), self.lineEdit_new_time.text()) if self.lineEdit_new_price.text() != '': self.label_new_price.setText("Actual price: " + self.lineEdit_new_price.text()) if self.lineEdit_new_time.text() != '': self.label_new_time.setText("Actual refresh time[s]: " + self.lineEdit_new_time.text() + " s") self.lineEdit_new_time.clear() self.lineEdit_new_price.clear() self.shared_dict['isTerminatedP2'] = True def on_switch(self, link): # m.stop_run_monitor() if self.is_on: self.label_is_on.setText("Enable") self.pushButton_switch.setIcon(self.icon_off) self.is_on = False data.switch_state(self.is_on, link) else: self.label_is_on.setText("Disable") self.pushButton_switch.setIcon(self.icon_on) self.is_on = True data.switch_state(self.is_on, link) self.shared_dict['isTerminatedP2'] = True
def _add_line(self): line = QFrame() line.setFrameShape((QFrame.HLine)) line.setFrameShadow(QFrame.Sunken) self.main_layout.addWidget(line)
def __init__(self): super(SidePanel, self).__init__() # Internal variables self._coverdir = path.join("data", "images", "covers") self._id = 0 self._imagedata = "" size = [220, 16] # Width, Height (for QLineEdits/QTextEdits) # QDockWidget settings self.setAllowedAreas(Qt.RightDockWidgetArea) self.setFeatures(QDockWidget.DockWidgetClosable) self.setFixedWidth(350) self.setVisible(False) # Fonts bold = QFont() bold.setBold(True) boldUnderline = QFont() boldUnderline.setBold(True) boldUnderline.setUnderline(True) # Horizontal line hline = QFrame() hline.setFrameShape(QFrame.HLine) hline.setFrameShadow(QFrame.Sunken) """Widgets""" # Cover self.cover = QLabel() self.cover.setAlignment(Qt.AlignCenter) self.cover.setMinimumHeight(200) self.cover.setMaximumSize(self.width(), 250) # Buttons self.fetchInfoButton = QPushButton("Fetch missing info") self.fetchInfoButton.setToolTip("Try to fetch info from MobyGames") self.fetchInfoButton.clicked.connect(self._fetchInfo) self.editDetailsButton = QPushButton("Edit") self.editDetailsButton.setCheckable(True) self.editDetailsButton.clicked.connect(self._editDetails) self.saveDetailsButton = QPushButton("Save") self.saveDetailsButton.clicked.connect(self._saveInfo) self.fetchPriceButton = QPushButton("Update price data") self.fetchPriceButton.setToolTip("Try to update price data from Pricecharting") self.fetchPriceButton.clicked.connect(self._fetchPriceData) self.savePriceButton = QPushButton("Save") self.savePriceButton.clicked.connect(self._saveInfo) # Info layout widgets self.nameInfoLabel = QLabel("Name:") self.nameInfoLabel.setFont(bold) self.nameDataLabel = QLabel() self.nameDataLabel.setWordWrap(True) self.platformInfoLabel = QLabel("Platform:") self.platformInfoLabel.setFont(bold) self.platformDataLabel = QLabel() self.publisherInfoLabel = QLabel("Publisher:") self.publisherInfoLabel.setFont(bold) self.publisherDataLabel = QLabel() self.developerInfoLabel = QLabel("Developer:") self.developerInfoLabel.setFont(bold) self.developerDataLabel = QLabel() self.regionInfoLabel = QLabel("Region:") self.regionInfoLabel.setFont(bold) self.regionDataLabel = QLabel() self.codeInfoLabel = QLabel("Code:") self.codeInfoLabel.setFont(bold) self.codeDataLabel = QLabel() self.codeDataLabel.setWordWrap(True) self.itemInfoLabel = QLabel("Game:") self.itemInfoLabel.setFont(bold) self.itemDataLabel = QLabel() self.boxInfoLabel = QLabel("Box:") self.boxInfoLabel.setFont(bold) self.boxDataLabel = QLabel() self.manualInfoLabel = QLabel("Manual:") self.manualInfoLabel.setFont(bold) self.manualDataLabel = QLabel() self.genreInfoLabel = QLabel("Genre:") self.genreInfoLabel.setFont(bold) self.genreDataLabel = QLabel() self.yearInfoLabel = QLabel("Year:") self.yearInfoLabel.setFont(bold) self.yearDataLabel = QLabel() self.commentInfoLabel = QLabel("Comment:") self.commentInfoLabel.setFont(bold) self.commentDataLabel = QLabel() self.commentDataLabel.setWordWrap(True) self.platformsInfoLabel = QLabel("Available for:") self.platformsInfoLabel.setFont(bold) self.platformsDataLabel = QLabel() self.platformsDataLabel.setWordWrap(True) self.platformsDataLabel.setMaximumHeight(50) # Can get quite large otherwise # Edit layout widgets self.nameEditLabel = QLabel("Name:") self.nameEditLabel.setFont(bold) self.nameDataTE = QTextEdit() self.nameDataTE.setMaximumSize(size[0], size[1] * 2) self.platformEditLabel = QLabel("Platform:") self.platformEditLabel.setFont(bold) self.platformDataLE = QLineEdit() self.platformDataLE.setMaximumSize(size[0], size[1]) self.publisherEditLabel = QLabel("Publisher:") self.publisherEditLabel.setFont(bold) self.publisherDataLE = QLineEdit() self.publisherDataLE.setMaximumSize(size[0], size[1]) self.developerEditLabel = QLabel("Developer:") self.developerEditLabel.setFont(bold) self.developerDataLE = QLineEdit() self.developerDataLE.setMaximumSize(size[0], size[1]) self.regionEditLabel = QLabel("Region:") self.regionEditLabel.setFont(bold) self.regionDataCoB = QComboBox() self.regionDataCoB.addItems(("NTSC (JP)", "NTSC (NA)", "PAL")) self.regionDataCoB.setMinimumWidth(size[0]) # If not set it will be too small self.regionDataCoB.setMaximumSize(size[0], size[1]) self.codeEditLabel = QLabel("Code:") self.codeEditLabel.setFont(bold) self.codeDataLE = QLineEdit() self.codeDataLE.setMaximumSize(size[0], size[1]) self.itemEditLabel = QLabel("Game:") self.itemEditLabel.setFont(bold) self.itemDataCB = QCheckBox() self.itemDataCB.setChecked(False) self.boxEditLabel = QLabel("Box:") self.boxEditLabel.setFont(bold) self.boxDataCB = QCheckBox() self.boxDataCB.setChecked(False) self.manualEditLabel = QLabel("Manual:") self.manualEditLabel.setFont(bold) self.manualDataCB = QCheckBox() self.manualDataCB.setChecked(False) self.genreEditLabel = QLabel("Genre:") self.genreEditLabel.setFont(bold) self.genreDataLE = QLineEdit() self.genreDataLE.setMaximumSize(size[0], size[1]) self.yearEditLabel = QLabel("Year:") self.yearEditLabel.setFont(bold) self.yearDataLE = QLineEdit() self.yearDataLE.setMaximumSize(size[0], size[1]) self.commentEditLabel = QLabel("Comment:") self.commentEditLabel.setFont(bold) self.commentDataTE = QTextEdit() self.commentDataTE.setMaximumSize(size[0], size[1] * 2) self.platformsEditLabel = QLabel("Available for:") self.platformsEditLabel.setFont(bold) self.platformsDataTE = QTextEdit() self.platformsDataTE.setMaximumSize(size[0], size[1] * 2) # Price widgets self.paidPriceLabel = QLabel("Paid:") self.paidPriceLabel.setFont(bold) self.paidPriceDataLE = QLineEdit() self.paidPriceDataLE.setMaximumSize(60, size[1]) self.paidPriceDataLE.setAlignment(Qt.AlignRight) self.loosePriceLabel = QLabel("Loose:") self.loosePriceLabel.setFont(bold) self.loosePriceDataLabel = QLabel() self.loosePriceDataLabel.setAlignment(Qt.AlignRight) self.cibPriceLabel = QLabel("CIB:") self.cibPriceLabel.setFont(bold) self.cibPriceDataLabel = QLabel() self.cibPriceDataLabel.setAlignment(Qt.AlignRight) self.newPriceLabel = QLabel("New:") self.newPriceLabel.setFont(bold) self.newPriceDataLabel = QLabel() self.newPriceDataLabel.setAlignment(Qt.AlignRight) """Layouts""" # Cover self.coverVbox = QVBoxLayout() self.coverVbox.addWidget(self.cover, 1) self.coverVbox.addWidget(hline, 0) # Buttons self.detailsButtonHbox = QHBoxLayout() self.detailsButtonHbox.addWidget(self.fetchInfoButton, 0) self.detailsButtonHbox.addWidget(self.editDetailsButton, 0) self.detailsButtonHbox.addWidget(self.saveDetailsButton, 0) self.priceButtonHbox = QHBoxLayout() self.priceButtonHbox.addWidget(self.fetchPriceButton, 0) self.priceButtonHbox.addWidget(self.savePriceButton, 0) # Info layouts self.nameInfoHbox = QHBoxLayout() self.nameInfoHbox.addWidget(self.nameInfoLabel, 0) self.nameInfoHbox.addWidget(self.nameDataLabel, 0) self.platformInfoHbox = QHBoxLayout() self.platformInfoHbox.addWidget(self.platformInfoLabel, 0) self.platformInfoHbox.addWidget(self.platformDataLabel, 0) self.publisherInfoHbox = QHBoxLayout() self.publisherInfoHbox.addWidget(self.publisherInfoLabel, 0) self.publisherInfoHbox.addWidget(self.publisherDataLabel, 0) self.developerInfoHbox = QHBoxLayout() self.developerInfoHbox.addWidget(self.developerInfoLabel, 0) self.developerInfoHbox.addWidget(self.developerDataLabel, 0) self.regionInfoHbox = QHBoxLayout() self.regionInfoHbox.addWidget(self.regionInfoLabel, 0) self.regionInfoHbox.addWidget(self.regionDataLabel, 0) self.codeInfoHbox = QHBoxLayout() self.codeInfoHbox.addWidget(self.codeInfoLabel, 0) self.codeInfoHbox.addWidget(self.codeDataLabel, 0) self.itemInfoHbox = QHBoxLayout() self.itemInfoHbox.addWidget(self.itemInfoLabel, 0) self.itemInfoHbox.addWidget(self.itemDataLabel, 0) self.boxInfoHbox = QHBoxLayout() self.boxInfoHbox.addWidget(self.boxInfoLabel, 0) self.boxInfoHbox.addWidget(self.boxDataLabel, 0) self.manualInfoHbox = QHBoxLayout() self.manualInfoHbox.addWidget(self.manualInfoLabel, 0) self.manualInfoHbox.addWidget(self.manualDataLabel, 0) self.genreInfoHbox = QHBoxLayout() self.genreInfoHbox.addWidget(self.genreInfoLabel, 0) self.genreInfoHbox.addWidget(self.genreDataLabel, 0) self.yearInfoHbox = QHBoxLayout() self.yearInfoHbox.addWidget(self.yearInfoLabel, 0) self.yearInfoHbox.addWidget(self.yearDataLabel, 0) self.commentInfoHbox = QHBoxLayout() self.commentInfoHbox.addWidget(self.commentInfoLabel, 0) self.commentInfoHbox.addWidget(self.commentDataLabel, 0) self.platformsInfoHbox = QHBoxLayout() self.platformsInfoHbox.addWidget(self.platformsInfoLabel, 0) self.platformsInfoHbox.addWidget(self.platformsDataLabel, 0) # Edit layouts self.nameEditHbox = QHBoxLayout() self.nameEditHbox.addWidget(self.nameEditLabel, 0) self.nameEditHbox.addWidget(self.nameDataTE, 0) self.platformEditHbox = QHBoxLayout() self.platformEditHbox.addWidget(self.platformEditLabel, 0) self.platformEditHbox.addWidget(self.platformDataLE, 0) self.publisherEditHbox = QHBoxLayout() self.publisherEditHbox.addWidget(self.publisherEditLabel, 0) self.publisherEditHbox.addWidget(self.publisherDataLE, 0) self.developerEditHbox = QHBoxLayout() self.developerEditHbox.addWidget(self.developerEditLabel, 0) self.developerEditHbox.addWidget(self.developerDataLE, 0) self.regionEditHbox = QHBoxLayout() self.regionEditHbox.addWidget(self.regionEditLabel, 0) self.regionEditHbox.addWidget(self.regionDataCoB, 0) self.codeEditHbox = QHBoxLayout() self.codeEditHbox.addWidget(self.codeEditLabel, 0) self.codeEditHbox.addWidget(self.codeDataLE, 0) self.itemEditHbox = QHBoxLayout() self.itemEditHbox.addWidget(self.itemEditLabel, 0) self.itemEditHbox.addWidget(self.itemDataCB, 0) self.itemEditHbox.addSpacing(135) self.boxEditHbox = QHBoxLayout() self.boxEditHbox.addWidget(self.boxEditLabel, 0) self.boxEditHbox.addWidget(self.boxDataCB, 0) self.boxEditHbox.addSpacing(135) self.manualEditHbox = QHBoxLayout() self.manualEditHbox.addWidget(self.manualEditLabel, 0) self.manualEditHbox.addWidget(self.manualDataCB, 0) self.manualEditHbox.addSpacing(135) self.genreEditHbox = QHBoxLayout() self.genreEditHbox.addWidget(self.genreEditLabel, 0) self.genreEditHbox.addWidget(self.genreDataLE, 0) self.yearEditHbox = QHBoxLayout() self.yearEditHbox.addWidget(self.yearEditLabel, 0) self.yearEditHbox.addWidget(self.yearDataLE, 0) self.commentEditHbox = QHBoxLayout() self.commentEditHbox.addWidget(self.commentEditLabel, 0) self.commentEditHbox.addWidget(self.commentDataTE, 0) self.platformsEditHbox = QHBoxLayout() self.platformsEditHbox.addWidget(self.platformsEditLabel, 0) self.platformsEditHbox.addWidget(self.platformsDataTE, 0) # Price layouts self.paidPriceHbox = QHBoxLayout() self.paidPriceHbox.addWidget(self.paidPriceLabel, 0) self.paidPriceHbox.addWidget(self.paidPriceDataLE, 0) self.loosePriceHbox = QHBoxLayout() self.loosePriceHbox.addWidget(self.loosePriceLabel, 0) self.loosePriceHbox.addWidget(self.loosePriceDataLabel, 0) self.cibPriceHbox = QHBoxLayout() self.cibPriceHbox.addWidget(self.cibPriceLabel, 0) self.cibPriceHbox.addWidget(self.cibPriceDataLabel, 0) self.newPriceHbox = QHBoxLayout() self.newPriceHbox.addWidget(self.newPriceLabel, 0) self.newPriceHbox.addWidget(self.newPriceDataLabel, 0) # Info layout self.infoLayout = QVBoxLayout() self.infoLayout.addLayout(self.nameInfoHbox, 0) self.infoLayout.addLayout(self.platformInfoHbox, 0) self.infoLayout.addLayout(self.publisherInfoHbox, 0) self.infoLayout.addLayout(self.developerInfoHbox, 0) self.infoLayout.addLayout(self.genreInfoHbox, 0) self.infoLayout.addLayout(self.regionInfoHbox, 0) self.infoLayout.addLayout(self.yearInfoHbox, 0) self.infoLayout.addLayout(self.codeInfoHbox, 0) self.infoLayout.addLayout(self.itemInfoHbox, 0) self.infoLayout.addLayout(self.boxInfoHbox, 0) self.infoLayout.addLayout(self.manualInfoHbox, 0) self.infoLayout.addLayout(self.commentInfoHbox, 0) self.infoLayout.addLayout(self.platformsInfoHbox, 0) # Edit layout self.editLayout = QVBoxLayout() self.editLayout.addLayout(self.nameEditHbox, 0) self.editLayout.addLayout(self.platformEditHbox, 0) self.editLayout.addLayout(self.publisherEditHbox, 0) self.editLayout.addLayout(self.developerEditHbox, 0) self.editLayout.addLayout(self.genreEditHbox, 0) self.editLayout.addLayout(self.regionEditHbox, 0) self.editLayout.addLayout(self.yearEditHbox, 0) self.editLayout.addLayout(self.codeEditHbox, 0) self.editLayout.addLayout(self.itemEditHbox, 0) self.editLayout.addLayout(self.boxEditHbox, 0) self.editLayout.addLayout(self.manualEditHbox, 0) self.editLayout.addLayout(self.commentEditHbox, 0) self.editLayout.addLayout(self.platformsEditHbox, 0) # Price layout self.priceLayout = QVBoxLayout() self.priceLayout.addLayout(self.paidPriceHbox, 0) self.priceLayout.addLayout(self.loosePriceHbox, 0) self.priceLayout.addLayout(self.cibPriceHbox, 0) self.priceLayout.addLayout(self.newPriceHbox, 0) self.priceLayout.addStretch(1) self.priceLayout.addLayout(self.priceButtonHbox, 0) """Main layout""" self.infoWidget = QWidget() self.infoWidget.setLayout(self.infoLayout) self.editWidget = QWidget() self.editWidget.setLayout(self.editLayout) # Add info and edit widgets to a stacked layout so we can switch layouts when editing self.stackedLayout = QStackedLayout() self.stackedLayout.addWidget(self.infoWidget) self.stackedLayout.addWidget(self.editWidget) self.stackedLayout.setCurrentIndex(0) # Default to info layout self.detailsLayout = QVBoxLayout() self.detailsLayout.addLayout(self.coverVbox, 1) self.detailsLayout.addLayout(self.stackedLayout, 0) self.detailsLayout.addLayout(self.detailsButtonHbox, 0) self.detailsWidget = QWidget() self.detailsWidget.setLayout(self.detailsLayout) self.priceWidget = QWidget() self.priceWidget.setLayout(self.priceLayout) self.tab = QTabWidget() self.tab.addTab(self.detailsWidget, "Details") self.tab.addTab(self.priceWidget, "Price info") self.setWidget(self.tab)
class UiSignUp: def setupUi(self, widget): widget.resize(800, 480) self.frame_menu = QFrame(widget) self.frame_menu.setGeometry(QRect(0, 0, 800, 60)) self.frame_menu.setStyleSheet( "QLabel {" " color: white;" " background-color: rgb(249, 138, 15);" " font: 20pt 배달의민족 주아;" "}" "QPushButton {" " color: white;" " background-color: rgba(0, 0, 0, 0);" " font: 16pt 배달의민족 주아;" " border: none;" " border-radius: 16px;" "}" "QPushButton:hover {" " background-color: rgb(241, 219, 194);" "}") self.label_menu = QLabel(self.frame_menu) self.label_menu.setGeometry(QRect(0, 0, 800, 60)) self.label_menu.setText("사용자 등록") self.label_menu.setAlignment(Qt.AlignCenter) img_home = QPixmap(str(PATH_IMG / "home.png")) self.button_home = QPushButton(self.frame_menu) self.button_home.setGeometry(QRect(10, 5, 90, 50)) self.button_home.setIcon(QIcon(img_home)) self.button_home.setIconSize(QSize(40, 40)) self.button_home.setText("홈") self.frame_main = QFrame(widget) self.frame_main.setGeometry(QRect(0, 60, 800, 420)) self.frame_main.setStyleSheet( "QFrame {" " font: 20pt 배달의민족 주아;" " background-color: white;" "}" "QLineEdit {" " font: 20pt 배달의민족 주아;" " border: 3px solid black;" " border-radius: 10px;" "}" "QLineEdit:hover {" " background-color: rgb(200, 200, 200);" "}" "QLineEdit:focus {" " border-color: rgb(0, 85, 255);" "}") self.line_left = QFrame(self.frame_main) self.line_left.setGeometry(QRect(130, 50, 2, 80)) self.line_left.setFrameShape(QFrame.VLine) self.line_left.setStyleSheet( "background-color: rgb(176, 176, 176); border: none;") self.line_right = QFrame(self.frame_main) self.line_right.setGeometry(QRect(670, 50, 2, 80)) self.line_right.setFrameShape(QFrame.VLine) self.line_right.setStyleSheet( "background-color: rgb(176, 176, 176); border: none;") path_left = PATH_IMG / "arrow_left.png" path_right = PATH_IMG / "arrow_right.png" path_left_hover = PATH_IMG / "arrow_left_hover.png" path_right_hover = PATH_IMG / "arrow_right_hover.png" self.button_left = QPushButton(self.frame_main) self.button_left.setGeometry(QRect(30, 50, 80, 80)) self.button_left.setStyleSheet("QPushButton {" f" image: url({path_left});" " border: none;" "}" "QPushButton:hover {" f" image: url({path_left_hover});" "}") self.button_right = QPushButton(self.frame_main) self.button_right.setGeometry(QRect(690, 50, 80, 80)) self.button_right.setStyleSheet("QPushButton {" f" image: url({path_right});" " border: none;" "}" "QPushButton:hover {" f" image: url({path_right_hover});" "}")
class SCOUTS(QMainWindow): """Main Window Widget for SCOUTS.""" style = { 'title': 'QLabel {font-size: 18pt; font-weight: 600}', 'header': 'QLabel {font-size: 12pt; font-weight: 520}', 'label': 'QLabel {font-size: 10pt}', 'button': 'QPushButton {font-size: 10pt}', 'md button': 'QPushButton {font-size: 12pt}', 'run button': 'QPushButton {font-size: 18pt; font-weight: 600}', 'line edit': 'QLineEdit {font-size: 10pt}', 'checkbox': 'QCheckBox {font-size: 10pt}', 'radio button': 'QRadioButton {font-size: 10pt}' } def __init__(self) -> None: """SCOUTS Constructor. Defines all aspects of the GUI.""" # ### # ### Main Window setup # ### # Inherits from QMainWindow super().__init__() self.rootdir = get_project_root() self.threadpool = QThreadPool() # Sets values for QMainWindow self.setWindowTitle("SCOUTS") self.setWindowIcon( QIcon( os.path.abspath(os.path.join(self.rootdir, 'src', 'scouts.ico')))) # Creates StackedWidget as QMainWindow's central widget self.stacked_pages = QStackedWidget(self) self.setCentralWidget(self.stacked_pages) # Creates Widgets for individual "pages" and adds them to the StackedWidget self.main_page = QWidget() self.samples_page = QWidget() self.gating_page = QWidget() self.pages = (self.main_page, self.samples_page, self.gating_page) for page in self.pages: self.stacked_pages.addWidget(page) # ## Sets widget at program startup self.stacked_pages.setCurrentWidget(self.main_page) # ### # ### MAIN PAGE # ### # Main page layout self.main_layout = QVBoxLayout(self.main_page) # Title section # Title self.title = QLabel(self.main_page) self.title.setText('SCOUTS - Single Cell Outlier Selector') self.title.setStyleSheet(self.style['title']) self.title.adjustSize() self.main_layout.addWidget(self.title) # ## Input section # Input header self.input_header = QLabel(self.main_page) self.input_header.setText('Input settings') self.input_header.setStyleSheet(self.style['header']) self.main_layout.addChildWidget(self.input_header) self.input_header.adjustSize() self.main_layout.addWidget(self.input_header) # Input frame self.input_frame = QFrame(self.main_page) self.input_frame.setFrameShape(QFrame.StyledPanel) self.input_frame.setLayout(QFormLayout()) self.main_layout.addWidget(self.input_frame) # Input button self.input_button = QPushButton(self.main_page) self.input_button.setStyleSheet(self.style['button']) self.set_icon(self.input_button, 'x-office-spreadsheet') self.input_button.setObjectName('input') self.input_button.setText(' Select input file (.xlsx or .csv)') self.input_button.clicked.connect(self.get_path) # Input path box self.input_path = QLineEdit(self.main_page) self.input_path.setObjectName('input_path') self.input_path.setStyleSheet(self.style['line edit']) # Go to sample naming page self.samples_button = QPushButton(self.main_page) self.samples_button.setStyleSheet(self.style['button']) self.set_icon(self.samples_button, 'preferences-other') self.samples_button.setText(' Name samples...') self.samples_button.clicked.connect(self.goto_samples_page) # Go to gating page self.gates_button = QPushButton(self.main_page) self.gates_button.setStyleSheet(self.style['button']) self.set_icon(self.gates_button, 'preferences-other') self.gates_button.setText(' Gating && outlier options...') self.gates_button.clicked.connect(self.goto_gates_page) # Add widgets above to input frame Layout self.input_frame.layout().addRow(self.input_button, self.input_path) self.input_frame.layout().addRow(self.samples_button) self.input_frame.layout().addRow(self.gates_button) # ## Analysis section # Analysis header self.analysis_header = QLabel(self.main_page) self.analysis_header.setText('Analysis settings') self.analysis_header.setStyleSheet(self.style['header']) self.analysis_header.adjustSize() self.main_layout.addWidget(self.analysis_header) # Analysis frame self.analysis_frame = QFrame(self.main_page) self.analysis_frame.setFrameShape(QFrame.StyledPanel) self.analysis_frame.setLayout(QVBoxLayout()) self.main_layout.addWidget(self.analysis_frame) # Cutoff text self.cutoff_text = QLabel(self.main_page) self.cutoff_text.setText('Type of outlier to select:') self.cutoff_text.setToolTip( 'Choose whether to select outliers using the cutoff value from a reference\n' 'sample (OutR) or by using the cutoff value calculated for each sample\n' 'individually (OutS)') self.cutoff_text.setStyleSheet(self.style['label']) # Cutoff button group self.cutoff_group = QButtonGroup(self) # Cutoff by sample self.cutoff_sample = QRadioButton(self.main_page) self.cutoff_sample.setText('OutS') self.cutoff_sample.setObjectName('sample') self.cutoff_sample.setStyleSheet(self.style['radio button']) self.cutoff_sample.setChecked(True) self.cutoff_group.addButton(self.cutoff_sample) # Cutoff by reference self.cutoff_reference = QRadioButton(self.main_page) self.cutoff_reference.setText('OutR') self.cutoff_reference.setObjectName('ref') self.cutoff_reference.setStyleSheet(self.style['radio button']) self.cutoff_group.addButton(self.cutoff_reference) # Both cutoffs self.cutoff_both = QRadioButton(self.main_page) self.cutoff_both.setText('both') self.cutoff_both.setObjectName('sample ref') self.cutoff_both.setStyleSheet(self.style['radio button']) self.cutoff_group.addButton(self.cutoff_both) # Markers text self.markers_text = QLabel(self.main_page) self.markers_text.setStyleSheet(self.style['label']) self.markers_text.setText('Show results for:') self.markers_text.setToolTip( 'Individual markers: for each marker, select outliers\n' 'Any marker: select cells that are outliers for AT LEAST one marker' ) # Markers button group self.markers_group = QButtonGroup(self) # Single marker self.single_marker = QRadioButton(self.main_page) self.single_marker.setText('individual markers') self.single_marker.setObjectName('single') self.single_marker.setStyleSheet(self.style['radio button']) self.single_marker.setChecked(True) self.markers_group.addButton(self.single_marker) # Any marker self.any_marker = QRadioButton(self.main_page) self.any_marker.setText('any marker') self.any_marker.setObjectName('any') self.any_marker.setStyleSheet(self.style['radio button']) self.markers_group.addButton(self.any_marker) # Both methods self.both_methods = QRadioButton(self.main_page) self.both_methods.setText('both') self.both_methods.setObjectName('single any') self.both_methods.setStyleSheet(self.style['radio button']) self.markers_group.addButton(self.both_methods) # Tukey text self.tukey_text = QLabel(self.main_page) self.tukey_text.setStyleSheet(self.style['label']) # Tukey button group self.tukey_text.setText('Tukey factor:') self.tukey_group = QButtonGroup(self) # Low Tukey value self.tukey_low = QRadioButton(self.main_page) self.tukey_low.setText('1.5') self.tukey_low.setStyleSheet(self.style['radio button']) self.tukey_low.setChecked(True) self.tukey_group.addButton(self.tukey_low) # High Tukey value self.tukey_high = QRadioButton(self.main_page) self.tukey_high.setText('3.0') self.tukey_high.setStyleSheet(self.style['radio button']) self.tukey_group.addButton(self.tukey_high) # Add widgets above to analysis frame layout self.analysis_frame.layout().addWidget(self.cutoff_text) self.cutoff_buttons = QHBoxLayout() for button in self.cutoff_group.buttons(): self.cutoff_buttons.addWidget(button) self.analysis_frame.layout().addLayout(self.cutoff_buttons) self.analysis_frame.layout().addWidget(self.markers_text) self.markers_buttons = QHBoxLayout() for button in self.markers_group.buttons(): self.markers_buttons.addWidget(button) self.analysis_frame.layout().addLayout(self.markers_buttons) self.analysis_frame.layout().addWidget(self.tukey_text) self.tukey_buttons = QHBoxLayout() for button in self.tukey_group.buttons(): self.tukey_buttons.addWidget(button) self.tukey_buttons.addWidget(QLabel()) # aligns row with 2 buttons self.analysis_frame.layout().addLayout(self.tukey_buttons) # ## Output section # Output header self.output_header = QLabel(self.main_page) self.output_header.setText('Output settings') self.output_header.setStyleSheet(self.style['header']) self.output_header.adjustSize() self.main_layout.addWidget(self.output_header) # Output frame self.output_frame = QFrame(self.main_page) self.output_frame.setFrameShape(QFrame.StyledPanel) self.output_frame.setLayout(QFormLayout()) self.main_layout.addWidget(self.output_frame) # Output button self.output_button = QPushButton(self.main_page) self.output_button.setStyleSheet(self.style['button']) self.set_icon(self.output_button, 'folder') self.output_button.setObjectName('output') self.output_button.setText(' Select output folder') self.output_button.clicked.connect(self.get_path) # Output path box self.output_path = QLineEdit(self.main_page) self.output_path.setStyleSheet(self.style['line edit']) # Generate CSV checkbox self.output_csv = QCheckBox(self.main_page) self.output_csv.setText('Export multiple text files (.csv)') self.output_csv.setStyleSheet(self.style['checkbox']) self.output_csv.setChecked(True) # Generate XLSX checkbox self.output_excel = QCheckBox(self.main_page) self.output_excel.setText('Export multiple Excel spreadsheets (.xlsx)') self.output_excel.setStyleSheet(self.style['checkbox']) self.output_excel.clicked.connect(self.enable_single_excel) # Generate single, large XLSX checkbox self.single_excel = QCheckBox(self.main_page) self.single_excel.setText( 'Also save one multi-sheet Excel spreadsheet') self.single_excel.setToolTip( 'After generating all Excel spreadsheets, SCOUTS combines them into ' 'a single\nExcel spreadsheet where each sheet corresponds to an output' 'file from SCOUTS') self.single_excel.setStyleSheet(self.style['checkbox']) self.single_excel.setEnabled(False) self.single_excel.clicked.connect(self.memory_warning) # Add widgets above to output frame layout self.output_frame.layout().addRow(self.output_button, self.output_path) self.output_frame.layout().addRow(self.output_csv) self.output_frame.layout().addRow(self.output_excel) self.output_frame.layout().addRow(self.single_excel) # ## Run & help-quit section # Run button (stand-alone) self.run_button = QPushButton(self.main_page) self.set_icon(self.run_button, 'system-run') self.run_button.setText(' Run!') self.run_button.setStyleSheet(self.style['run button']) self.main_layout.addWidget(self.run_button) self.run_button.clicked.connect(self.run) # Help-quit frame (invisible) self.helpquit_frame = QFrame(self.main_page) self.helpquit_frame.setLayout(QHBoxLayout()) self.helpquit_frame.layout().setMargin(0) self.main_layout.addWidget(self.helpquit_frame) # Help button self.help_button = QPushButton(self.main_page) self.set_icon(self.help_button, 'help-about') self.help_button.setText(' Help') self.help_button.setStyleSheet(self.style['md button']) self.help_button.clicked.connect(self.get_help) # Quit button self.quit_button = QPushButton(self.main_page) self.set_icon(self.quit_button, 'process-stop') self.quit_button.setText(' Quit') self.quit_button.setStyleSheet(self.style['md button']) self.quit_button.clicked.connect(self.close) # Add widgets above to help-quit layout self.helpquit_frame.layout().addWidget(self.help_button) self.helpquit_frame.layout().addWidget(self.quit_button) # ### # ### SAMPLES PAGE # ### # Samples page layout self.samples_layout = QVBoxLayout(self.samples_page) # ## Title section # Title self.samples_title = QLabel(self.samples_page) self.samples_title.setText('Name your samples') self.samples_title.setStyleSheet(self.style['title']) self.samples_title.adjustSize() self.samples_layout.addWidget(self.samples_title) # Subtitle self.samples_subtitle = QLabel(self.samples_page) string = ( 'Please name the samples to be analysed by SCOUTS.\n\nSCOUTS searches the first ' 'column of your data\nand locates the exact string as part of the sample name.' ) self.samples_subtitle.setText(string) self.samples_subtitle.setStyleSheet(self.style['label']) self.samples_subtitle.adjustSize() self.samples_layout.addWidget(self.samples_subtitle) # ## Sample addition section # Sample addition frame self.samples_frame = QFrame(self.samples_page) self.samples_frame.setFrameShape(QFrame.StyledPanel) self.samples_frame.setLayout(QGridLayout()) self.samples_layout.addWidget(self.samples_frame) # Sample name box self.sample_name = QLineEdit(self.samples_page) self.sample_name.setStyleSheet(self.style['line edit']) self.sample_name.setPlaceholderText('Sample name ...') # Reference check self.is_reference = QCheckBox(self.samples_page) self.is_reference.setText('Reference?') self.is_reference.setStyleSheet(self.style['checkbox']) # Add sample to table self.add_sample_button = QPushButton(self.samples_page) QShortcut(QKeySequence("Return"), self.add_sample_button, self.write_to_sample_table) self.set_icon(self.add_sample_button, 'list-add') self.add_sample_button.setText(' Add sample (Enter)') self.add_sample_button.setStyleSheet(self.style['button']) self.add_sample_button.clicked.connect(self.write_to_sample_table) # Remove sample from table self.remove_sample_button = QPushButton(self.samples_page) QShortcut(QKeySequence("Delete"), self.remove_sample_button, self.remove_from_sample_table) self.set_icon(self.remove_sample_button, 'list-remove') self.remove_sample_button.setText(' Remove sample (Del)') self.remove_sample_button.setStyleSheet(self.style['button']) self.remove_sample_button.clicked.connect( self.remove_from_sample_table) # Add widgets above to sample addition layout self.samples_frame.layout().addWidget(self.sample_name, 0, 0) self.samples_frame.layout().addWidget(self.is_reference, 1, 0) self.samples_frame.layout().addWidget(self.add_sample_button, 0, 1) self.samples_frame.layout().addWidget(self.remove_sample_button, 1, 1) # ## Sample table self.sample_table = QTableWidget(self.samples_page) self.sample_table.setColumnCount(2) self.sample_table.setHorizontalHeaderItem(0, QTableWidgetItem('Sample')) self.sample_table.setHorizontalHeaderItem( 1, QTableWidgetItem('Reference?')) self.sample_table.horizontalHeader().setSectionResizeMode( 0, QHeaderView.Stretch) self.sample_table.horizontalHeader().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.samples_layout.addWidget(self.sample_table) # ## Save & clear buttons # Save & clear frame (invisible) self.saveclear_frame = QFrame(self.samples_page) self.saveclear_frame.setLayout(QHBoxLayout()) self.saveclear_frame.layout().setMargin(0) self.samples_layout.addWidget(self.saveclear_frame) # Clear samples button self.clear_samples = QPushButton(self.samples_page) self.set_icon(self.clear_samples, 'edit-delete') self.clear_samples.setText(' Clear table') self.clear_samples.setStyleSheet(self.style['md button']) self.clear_samples.clicked.connect(self.prompt_clear_data) # Save samples button self.save_samples = QPushButton(self.samples_page) self.set_icon(self.save_samples, 'document-save') self.save_samples.setText(' Save samples') self.save_samples.setStyleSheet(self.style['md button']) self.save_samples.clicked.connect(self.goto_main_page) # Add widgets above to save & clear layout self.saveclear_frame.layout().addWidget(self.clear_samples) self.saveclear_frame.layout().addWidget(self.save_samples) # ### # ### GATING PAGE # ### # Gating page layout self.gating_layout = QVBoxLayout(self.gating_page) # ## Title section # Title self.gates_title = QLabel(self.gating_page) self.gates_title.setText('Gating & outlier options') self.gates_title.setStyleSheet(self.style['title']) self.gates_title.adjustSize() self.gating_layout.addWidget(self.gates_title) # ## Gating options section # Gating header self.gate_header = QLabel(self.gating_page) self.gate_header.setText('Gating') self.gate_header.setStyleSheet(self.style['header']) self.gate_header.adjustSize() self.gating_layout.addWidget(self.gate_header) # Gating frame self.gate_frame = QFrame(self.gating_page) self.gate_frame.setFrameShape(QFrame.StyledPanel) self.gate_frame.setLayout(QFormLayout()) self.gating_layout.addWidget(self.gate_frame) # Gating button group self.gating_group = QButtonGroup(self) # Do not gate samples self.no_gates = QRadioButton(self.gating_page) self.no_gates.setObjectName('no_gate') self.no_gates.setText("Don't gate samples") self.no_gates.setStyleSheet(self.style['radio button']) self.no_gates.setChecked(True) self.gating_group.addButton(self.no_gates) self.no_gates.clicked.connect(self.activate_gate) # CyToF gating self.cytof_gates = QRadioButton(self.gating_page) self.cytof_gates.setObjectName('cytof') self.cytof_gates.setText('Mass Cytometry gating') self.cytof_gates.setStyleSheet(self.style['radio button']) self.cytof_gates.setToolTip( 'Exclude cells for which the average expression of all\n' 'markers is below the selected value') self.gating_group.addButton(self.cytof_gates) self.cytof_gates.clicked.connect(self.activate_gate) # CyToF gating spinbox self.cytof_gates_value = QDoubleSpinBox(self.gating_page) self.cytof_gates_value.setMinimum(0) self.cytof_gates_value.setMaximum(1) self.cytof_gates_value.setValue(0.1) self.cytof_gates_value.setSingleStep(0.05) self.cytof_gates_value.setEnabled(False) # scRNA-Seq gating self.rnaseq_gates = QRadioButton(self.gating_page) self.rnaseq_gates.setText('scRNA-Seq gating') self.rnaseq_gates.setStyleSheet(self.style['radio button']) self.rnaseq_gates.setToolTip( 'When calculating cutoff, ignore reads below the selected value') self.rnaseq_gates.setObjectName('rnaseq') self.gating_group.addButton(self.rnaseq_gates) self.rnaseq_gates.clicked.connect(self.activate_gate) # scRNA-Seq gating spinbox self.rnaseq_gates_value = QDoubleSpinBox(self.gating_page) self.rnaseq_gates_value.setMinimum(0) self.rnaseq_gates_value.setMaximum(10) self.rnaseq_gates_value.setValue(0) self.rnaseq_gates_value.setSingleStep(1) self.rnaseq_gates_value.setEnabled(False) # export gated population checkbox self.export_gated = QCheckBox(self.gating_page) self.export_gated.setText('Export gated cells as an output file') self.export_gated.setStyleSheet(self.style['checkbox']) self.export_gated.setEnabled(False) # Add widgets above to Gate frame layout self.gate_frame.layout().addRow(self.no_gates, QLabel()) self.gate_frame.layout().addRow(self.cytof_gates, self.cytof_gates_value) self.gate_frame.layout().addRow(self.rnaseq_gates, self.rnaseq_gates_value) self.gate_frame.layout().addRow(self.export_gated, QLabel()) # ## Outlier options section # Outlier header self.outlier_header = QLabel(self.gating_page) self.outlier_header.setText('Outliers') self.outlier_header.setStyleSheet(self.style['header']) self.outlier_header.adjustSize() self.gating_layout.addWidget(self.outlier_header) # Outlier frame self.outlier_frame = QFrame(self.gating_page) self.outlier_frame.setFrameShape(QFrame.StyledPanel) self.outlier_frame.setLayout(QVBoxLayout()) self.gating_layout.addWidget(self.outlier_frame) # Top outliers information self.top_outliers = QLabel(self.gating_page) self.top_outliers.setStyleSheet(self.style['label']) self.top_outliers.setText( 'By default, SCOUTS selects the top outliers from the population') self.top_outliers.setStyleSheet(self.style['label']) # Bottom outliers data self.bottom_outliers = QCheckBox(self.gating_page) self.bottom_outliers.setText('Include results for low outliers') self.bottom_outliers.setStyleSheet(self.style['checkbox']) # Non-outliers data self.not_outliers = QCheckBox(self.gating_page) self.not_outliers.setText('Include results for non-outliers') self.not_outliers.setStyleSheet(self.style['checkbox']) # Add widgets above to Gate frame layout self.outlier_frame.layout().addWidget(self.top_outliers) self.outlier_frame.layout().addWidget(self.bottom_outliers) self.outlier_frame.layout().addWidget(self.not_outliers) # ## Save/back button self.save_gates = QPushButton(self.gating_page) self.set_icon(self.save_gates, 'go-next') self.save_gates.setText(' Back to main menu') self.save_gates.setStyleSheet(self.style['md button']) self.gating_layout.addWidget(self.save_gates) self.save_gates.clicked.connect(self.goto_main_page) # ## Add empty label to take vertical space self.empty_label = QLabel(self.gating_page) self.empty_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.gating_layout.addWidget(self.empty_label) # ### # ### ICON SETTING # ### def set_icon(self, widget: QWidget, icon: str) -> None: """Associates an icon to a widget.""" i = QIcon() i.addPixmap( QPixmap( os.path.abspath( os.path.join(self.rootdir, 'src', 'default_icons', f'{icon}.svg')))) widget.setIcon(QIcon.fromTheme(icon, i)) # ### # ### STACKED WIDGET PAGE SWITCHING # ### def goto_main_page(self) -> None: """Switches stacked widget pages to the main page.""" self.stacked_pages.setCurrentWidget(self.main_page) def goto_samples_page(self) -> None: """Switches stacked widget pages to the samples table page.""" self.stacked_pages.setCurrentWidget(self.samples_page) def goto_gates_page(self) -> None: """Switches stacked widget pages to the gating & other options page.""" self.stacked_pages.setCurrentWidget(self.gating_page) # ### # ### MAIN PAGE GUI LOGIC # ### def get_path(self) -> None: """Opens a dialog box and sets the chosen file/folder path, depending on the caller widget.""" options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog sender_name = self.sender().objectName() if sender_name == 'input': query, _ = QFileDialog.getOpenFileName(self, "Select file", "", "All Files (*)", options=options) elif sender_name == 'output': query = QFileDialog.getExistingDirectory(self, "Select Directory", options=options) else: return if query: getattr(self, f'{sender_name}_path').setText(query) def enable_single_excel(self) -> None: """Enables checkbox for generating a single Excel output.""" if self.output_excel.isChecked(): self.single_excel.setEnabled(True) else: self.single_excel.setEnabled(False) self.single_excel.setChecked(False) # ### # ### SAMPLE NAME/SAMPLE TABLE GUI LOGIC # ### def write_to_sample_table(self) -> None: """Writes data to sample table.""" table = self.sample_table ref = 'no' sample = self.sample_name.text() if sample: for cell in range(table.rowCount()): item = table.item(cell, 0) if item.text() == sample: self.same_sample() return if self.is_reference.isChecked(): for cell in range(table.rowCount()): item = table.item(cell, 1) if item.text() == 'yes': self.more_than_one_reference() return ref = 'yes' sample = QTableWidgetItem(sample) is_reference = QTableWidgetItem(ref) is_reference.setFlags(Qt.ItemIsEnabled) row_position = table.rowCount() table.insertRow(row_position) table.setItem(row_position, 0, sample) table.setItem(row_position, 1, is_reference) self.is_reference.setChecked(False) self.sample_name.setText('') def remove_from_sample_table(self) -> None: """Removes data from sample table.""" table = self.sample_table rows = set(index.row() for index in table.selectedIndexes()) for index in sorted(rows, reverse=True): self.sample_table.removeRow(index) def prompt_clear_data(self) -> None: """Prompts option to clear all data in the sample table.""" if self.confirm_clear_data(): table = self.sample_table while table.rowCount(): self.sample_table.removeRow(0) # ### # ### GATING GUI LOGIC # ### def activate_gate(self) -> None: """Activates/deactivates buttons related to gating.""" if self.sender().objectName() == 'no_gate': self.cytof_gates_value.setEnabled(False) self.rnaseq_gates_value.setEnabled(False) self.export_gated.setEnabled(False) self.export_gated.setChecked(False) elif self.sender().objectName() == 'cytof': self.cytof_gates_value.setEnabled(True) self.rnaseq_gates_value.setEnabled(False) self.export_gated.setEnabled(True) elif self.sender().objectName() == 'rnaseq': self.cytof_gates_value.setEnabled(False) self.rnaseq_gates_value.setEnabled(True) self.export_gated.setEnabled(True) # ### # ### CONNECT SCOUTS TO ANALYTICAL MODULES # ### def run(self) -> None: """Runs SCOUTS as a Worker, based on user input in the GUI.""" try: data = self.parse_input() except Exception as error: trace = traceback.format_exc() self.propagate_error((error, trace)) else: data['widget'] = self worker = Worker(func=start_scouts, **data) worker.signals.started.connect(self.analysis_has_started) worker.signals.finished.connect(self.analysis_has_finished) worker.signals.success.connect(self.success_message) worker.signals.error.connect(self.propagate_error) self.threadpool.start(worker) def parse_input(self) -> Dict: """Returns user input on the GUI as a dictionary.""" # Input and output input_dict = { 'input_file': str(self.input_path.text()), 'output_folder': str(self.output_path.text()) } if not input_dict['input_file'] or not input_dict['output_folder']: raise NoIOPathError # Set cutoff by reference or by sample rule input_dict['cutoff_rule'] = self.cutoff_group.checkedButton( ).objectName() # 'sample', 'ref', 'sample ref' # Outliers for each individual marker or any marker in row input_dict['marker_rule'] = self.markers_group.checkedButton( ).objectName() # 'single', 'any', 'single any' # Tukey factor used for calculating cutoff input_dict['tukey_factor'] = float( self.tukey_group.checkedButton().text()) # '1.5', '3.0' # Output settings input_dict['export_csv'] = True if self.output_csv.isChecked( ) else False input_dict['export_excel'] = True if self.output_excel.isChecked( ) else False input_dict['single_excel'] = True if self.single_excel.isChecked( ) else False # Retrieve samples from sample table input_dict['sample_list'] = [] for tuples in self.yield_samples_from_table(): input_dict['sample_list'].append(tuples) if not input_dict['sample_list']: raise NoSampleError # Set gate cutoff (if any) input_dict['gating'] = self.gating_group.checkedButton().objectName( ) # 'no_gate', 'cytof', 'rnaseq' input_dict['gate_cutoff_value'] = None if input_dict['gating'] != 'no_gate': input_dict['gate_cutoff_value'] = getattr( self, f'{input_dict["gating"]}_gates_value').value() input_dict['export_gated'] = True if self.export_gated.isChecked( ) else False # Generate results for non-outliers input_dict['non_outliers'] = False if self.not_outliers.isChecked(): input_dict['non_outliers'] = True # Generate results for bottom outliers input_dict['bottom_outliers'] = False if self.bottom_outliers.isChecked(): input_dict['bottom_outliers'] = True # return dictionary with all gathered inputs return input_dict def yield_samples_from_table( self) -> Generator[Tuple[str, str], None, None]: """Yields sample names from the sample table.""" table = self.sample_table for cell in range(table.rowCount()): sample_name = table.item(cell, 0).text() sample_type = table.item(cell, 1).text() yield sample_name, sample_type # ### # ### MESSAGE BOXES # ### def analysis_has_started(self) -> None: """Disables run button while SCOUTS analysis is underway.""" self.run_button.setText(' Working...') self.run_button.setEnabled(False) def analysis_has_finished(self) -> None: """Enables run button after SCOUTS analysis has finished.""" self.run_button.setEnabled(True) self.run_button.setText(' Run!') def success_message(self) -> None: """Info message box used when SCOUTS finished without errors.""" title = "Analysis finished!" mes = "Your analysis has finished. No errors were reported." if self.stacked_pages.isEnabled() is True: QMessageBox.information(self, title, mes) def memory_warning(self) -> None: """Warning message box used when user wants to generate a single excel file.""" if self.sender().isChecked(): title = 'Memory warning!' mes = ( "Depending on your dataset, this option can consume a LOT of memory and take" " a long time to process. Please make sure that your computer can handle it!" ) QMessageBox.information(self, title, mes) def same_sample(self) -> None: """Error message box used when the user tries to input the same sample twice in the sample table.""" title = 'Error: sample name already in table' mes = ( "Sorry, you can't do this because this sample name is already in the table. " "Please select a different name.") QMessageBox.critical(self, title, mes) def more_than_one_reference(self) -> None: """Error message box used when the user tries to input two reference samples in the sample table.""" title = "Error: more than one reference selected" mes = ( "Sorry, you can't do this because there is already a reference column in the table. " "Please remove it before adding a reference.") QMessageBox.critical(self, title, mes) def confirm_clear_data(self) -> bool: """Question message box used to confirm user action of clearing sample table.""" title = 'Confirm Action' mes = "Table will be cleared. Are you sure?" reply = QMessageBox.question(self, title, mes, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: return True return False # ### # ### EXCEPTIONS & ERRORS # ### def propagate_error(self, error: Tuple[Exception, str]) -> None: """Calls the appropriate error message box based on type of Exception raised.""" if isinstance(error[0], NoIOPathError): self.no_io_path_error_message() elif isinstance(error[0], NoReferenceError): self.no_reference_error_message() elif isinstance(error[0], NoSampleError): self.no_sample_error_message() elif isinstance(error[0], PandasInputError): self.pandas_input_error_message() elif isinstance(error[0], SampleNamingError): self.sample_naming_error_message() else: self.generic_error_message(error) def no_io_path_error_message(self) -> None: """Message displayed when the user did not include an input file path, or an output folder path.""" title = 'Error: no file/folder' message = ("Sorry, no input file and/or output folder was provided. " "Please add the path to the necessary file/folder.") QMessageBox.critical(self, title, message) def no_reference_error_message(self) -> None: """Message displayed when the user wants to analyse cutoff based on a reference, but did not specify what sample corresponds to the reference.""" title = "Error: No reference selected" message = ( "Sorry, no reference sample was found on the sample list, but analysis was set to " "reference. Please add a reference sample, or change the rule for cutoff calculation." ) QMessageBox.critical(self, title, message) def no_sample_error_message(self) -> None: """Message displayed when the user did not add any samples to the sample table.""" title = "Error: No samples selected" message = ( "Sorry, the analysis cannot be performed because no sample names were input. " "Please add your sample names.") QMessageBox.critical(self, title, message) def pandas_input_error_message(self) -> None: """Message displayed when the input file cannot be read (likely because it is not a Excel or csv file).""" title = 'Error: unexpected input file' message = ( "Sorry, the input file could not be read. Please make sure that " "the data is save in a valid format (supported formats are: " ".csv, .xlsx).") QMessageBox.critical(self, title, message) def sample_naming_error_message(self) -> None: """Message displayed when none of the sample names passed by the user are found in the input DataFrame.""" title = 'Error: sample names not in input file' message = ( "Sorry, your sample names were not found in the input file. Please " "make sure that the names were typed correctly (case-sensitive).") QMessageBox.critical(self, title, message) def generic_error_message(self, error: Tuple[Exception, str]) -> None: """Error message box used to display any error message (including traceback) for any uncaught errors.""" title = 'An error occurred!' name, trace = error QMessageBox.critical(self, title, f"{str(name)}\n\nfull traceback:\n{trace}") def not_implemented_error_message(self) -> None: """Error message box used when the user accesses a functionality that hasn't been implemented yet.""" title = "Not yet implemented" mes = "Sorry, this functionality has not been implemented yet." QMessageBox.critical(self, title, mes) # ### # ### HELP & QUIT # ### @staticmethod def get_help() -> None: """Opens SCOUTS documentation on the browser. Called when the user clicks the "help" button""" webbrowser.open('https://scouts.readthedocs.io/en/master/') def closeEvent(self, event: QEvent) -> None: """Defines the message box for when the user wants to quit SCOUTS.""" title = 'Quit SCOUTS' mes = "Are you sure you want to quit?" reply = QMessageBox.question(self, title, mes, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.stacked_pages.setEnabled(False) message = self.quit_message() waiter = Waiter(waiter_func=self.threadpool.activeThreadCount) waiter.signals.started.connect(message.show) waiter.signals.finished.connect(message.destroy) waiter.signals.finished.connect(sys.exit) self.threadpool.start(waiter) event.ignore() def quit_message(self) -> QDialog: """Displays a window while SCOUTS is exiting""" message = QDialog(self) message.setWindowTitle('Exiting SCOUTS') message.resize(300, 50) label = QLabel('SCOUTS is exiting, please wait...', message) label.setStyleSheet(self.style['label']) label.adjustSize() label.setAlignment(Qt.AlignCenter) label.move(int((message.width() - label.width()) / 2), int((message.height() - label.height()) / 2)) return message
class PropertyTreeDelegateEditor(QFrame): """A special editor that handles renaming blocks and groups.""" sizeHintChanged = Signal(object) """Emitted when the widget changes sizeHint. Delegate should update it's geometry.""" def __init__(self, parent=None): super().__init__(parent) layout = QVBoxLayout() self.setLayout(layout) self.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self.setAutoFillBackground(True) self.setFocusPolicy(Qt.StrongFocus) self.setFrameStyle(QFrame.Panel | QFrame.Plain) self._fallback_text = None self._experiment = None self.line_edit = QLineEdit() self.line_edit.setFrame(False) self.message_label = QLabel() self.message_label.hide() # Divider line self.divider_line = QFrame() self.divider_line.setFrameShape(QFrame.HLine) self.divider_line.setFrameShadow(QFrame.Plain) self.divider_line.setLineWidth(1) layout.addWidget(self.line_edit) layout.addWidget(self.divider_line) layout.addWidget(self.message_label) self.line_edit.textChanged.connect(self._updateMessage) def experiment(self): return self._experiment def setExperiment(self, ex): self._experiment = ex def fallbackText(self): return self._fallback_text def text(self): """Get the current text value of the editor widget. If editing has not been finished succesfully, returns fallbackText(). """ (text_ok, _) = self.experiment().checkName(self.line_edit.text()) if text_ok: return self.line_edit.text() else: return self.fallbackText() def setFallbackText(self, text): """Set the fallback text value to be used if the editing was not succesfully finished. The text() method returns this value or the line_edit text. """ self._fallback_text = text def setText(self, text): """Set currently editable text. Equivalent to self.line_edit.setText.""" self.line_edit.setText(text) def _updateMessage(self): """Update the displayed message in response to changed text.""" if self.line_edit.text() == self.fallbackText(): # Perform no check text_ok = True else: (text_ok, reason) = self.experiment().checkName(self.line_edit.text()) if text_ok: self.message_label.hide() self.divider_line.hide() else: self.message_label.setText(reason) self.message_label.show() self.divider_line.show() self.sizeHintChanged.emit(self) def focusInEvent(self, event): super().focusInEvent(event) self.line_edit.setFocus()
class Ui_FE14CharacterEditor(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.search_bar = QLineEdit() self.search_bar.setPlaceholderText("Search...") self.search_bar.setFixedWidth(225) self.characters_list_view = QListView() self.characters_list_view.setContextMenuPolicy( QtCore.Qt.CustomContextMenu) self.characters_list_view.setFixedWidth(225) self.characters_list_layout = QVBoxLayout() self.characters_list_layout.addWidget(self.search_bar) self.characters_list_layout.addWidget(self.characters_list_view) self.character_details_box = QGroupBox(title="Character Details") self.portrait_display = QGraphicsView() self.portrait_display.setFixedSize(140, 140) self.character_details_form_contents_1 = QWidget() self.character_details_form_contents_2 = QWidget() self.character_details_layout = QHBoxLayout() self.character_details_layout.addWidget(self.portrait_display) self.character_details_layout.addWidget( self.character_details_form_contents_1) self.character_details_layout.addWidget( self.character_details_form_contents_2) self.character_details_box.setLayout(self.character_details_layout) self.character_details_box.setFixedHeight(200) self.tab_widget = QTabWidget() self.ids_tab = QWidget() self.classes_tab = QWidget() self.stats_tab = QScrollArea() self.skills_tab = QScrollArea() self.misc_tab = QScrollArea() self.portraits_tab = PortraitViewer() self.stats_contents = QWidget() self.stats_tab.setWidget(self.stats_contents) self.stats_tab.setWidgetResizable(True) self.stats_layout = QVBoxLayout() self.stats_layout.setAlignment(QtCore.Qt.AlignTop) self.stats_contents.setLayout(self.stats_layout) self.skills_contents = QWidget() self.skills_tab.setWidget(self.skills_contents) self.skills_tab.setWidgetResizable(True) self.misc_contents = QWidget() self.misc_tab.setWidget(self.misc_contents) self.misc_tab.setWidgetResizable(True) self.misc_layout = QVBoxLayout() self.misc_layout.setAlignment(QtCore.Qt.AlignTop) self.misc_contents.setLayout(self.misc_layout) self.tab_widget.addTab(self.ids_tab, "IDs") self.tab_widget.addTab(self.classes_tab, "Classes") self.tab_widget.addTab(self.stats_tab, "Stats") self.tab_widget.addTab(self.skills_tab, "Skills") self.tab_widget.addTab(self.misc_tab, "Misc.") self.tab_widget.addTab(self.portraits_tab, "Portraits") self.editor_layout = QVBoxLayout() self.editor_layout.addWidget(self.character_details_box) self.editor_layout.addWidget(self.tab_widget) self.main_layout = QHBoxLayout() self.main_layout.addLayout(self.characters_list_layout) self.visual_splitter = QFrame() self.visual_splitter.setFrameShape(QFrame.VLine) self.visual_splitter.setFrameShadow(QFrame.Sunken) self.main_layout.addWidget(self.visual_splitter) self.main_layout.addLayout(self.editor_layout) self.tool_bar = QToolBar() self.action_add = QAction(text="Add") self.action_remove = QAction(text="Remove") self.action_copy_to = QAction(text="Copy To") self.tool_bar.addActions( [self.action_add, self.action_remove, self.action_copy_to]) self.addToolBar(self.tool_bar) self.resize(1000, 600) central_widget = QWidget() central_widget.setLayout(self.main_layout) self.setWindowTitle("Character Editor") self.setWindowIcon(QIcon("paragon.ico")) self.setCentralWidget(central_widget)