class ViewWidget(QWidget): background_color = "#424A52" WIDTH = Settings.WIDTH.value HEIGHT = Settings.HEIGHT.value def __init__(self): super(ViewWidget, self).__init__() self.v_layout = QVBoxLayout() def init_gui(self): self.setGeometry(0, 0, Settings.WIDTH.value, Settings.HEIGHT.value) self.setLayout(self.v_layout) self.setContentsMargins(0, 0, 0, 0) self.setStyleSheet("background-color: %s;" "color:#FFFFFF" % self.background_color) def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setDirection(QVBoxLayout.TopToBottom) self.v_layout.setSpacing(0) self.v_layout.setContentsMargins(0, 0, 0, 0) def clear_layout(self): for i in reversed(range(self.v_layout.count())): self.v_layout.itemAt(i).widget().setParent(None)
def __init__(self, scrolled_layout: QVBoxLayout, direction=QBoxLayout.BottomToTop, scrolled_spacing=0, *args, **kwargs): super().__init__(*args, **kwargs) scrolled_layout.setDirection(direction) scrolled_layout.setSpacing(scrolled_spacing) # First we put the layout into a widget container_widget = QWidget() container_widget.setLayout(scrolled_layout) # Then we create a scrollarea containing that widget # (if the scrollarea contained only the layout, it would not work) display_column_scroll_area = QScrollArea() display_column_scroll_area.setWidget(container_widget) display_column_scroll_area.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOn) display_column_scroll_area.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff) display_column_scroll_area.setWidgetResizable(True) # At the end, we bundle the scrollarea into the layout self.addWidget(display_column_scroll_area)
def __init__(self, name: str, parent: QWidget): super(Group, self).__init__(parent) # self.setFrameShape(QFrame.NoFrame) # self.setLineWidth(0) self.setContentsMargins(0, 0, 0, 0) self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) seperator_layout = QHBoxLayout(self) seperator_layout.setContentsMargins(0, 0, 0, 0) seperator_layout.setSpacing(0) seperator_layout.setDirection(QBoxLayout.LeftToRight) self.setLayout(seperator_layout) outer_layout = QVBoxLayout() outer_layout.setContentsMargins(0, 0, 0, 0) outer_layout.setSpacing(0) outer_layout.setDirection(QBoxLayout.TopToBottom) seperator_layout.addLayout(outer_layout) seperator_layout.addWidget(self.create_separator()) inner_frame = QFrame(self) inner_frame.setFrameShape(QFrame.NoFrame) inner_frame.setLineWidth(0) inner_frame.setContentsMargins(0, 0, 0, 0) inner_frame.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) self.inner_layout = QHBoxLayout(inner_frame) self.inner_layout.setContentsMargins(2, 4, 2, 0) self.inner_layout.setSpacing(4) self.inner_layout.setDirection(QBoxLayout.LeftToRight) inner_frame.setLayout(self.inner_layout) outer_layout.addWidget(inner_frame) self.group_name = QLabel(name, self) self.group_name.setProperty("TTGroupName", QtCore.QVariant(True)) self.group_name.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.group_name.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter # type: ignore ) self.group_name.adjustSize() outer_layout.addWidget(self.group_name) parent_tabtoolbar = tabtoolbar.find_tabtoolbar(self) if not parent_tabtoolbar: raise Exception("Could not find Parent Tabtoolbar") group_maxheight = parent_tabtoolbar.group_maxheight rowcount = parent_tabtoolbar.rowcount() height = group_maxheight + self.group_name.height() + rowcount - 1 self.setMinimumHeight(height) self.setMaximumHeight(height)
def add_block(self): widget = QWidget() widget.setBaseSize(QSize(600, self.HEIGHT)) widget.setMinimumWidth(400) v_layout = QVBoxLayout() v_layout.setDirection(QVBoxLayout.TopToBottom) widget.setLayout(v_layout) widget.setStyleSheet("background-color: #424A52;") self.h_layout.addWidget(widget) self.left_menu_layout = v_layout self.left_menu_layout.setSpacing(0) self.left_menu_layout.setContentsMargins(0, 0, 0, 0) self.left_menu_layout.setAlignment(Qt.AlignTop)
class _CompactToolButton(QFrame): def __init__(self, action: QAction, menu: QMenu, parent): super(_CompactToolButton, self).__init__(parent) self.overlay = _TTOverlayToolButton(self) iconsize = int( get_pixelmetric(QStyle.PM_LargeIconSize) * get_scalefactor(self)) self.upButton = QToolButton(self) self.upButton.setProperty("TTInternal", QtCore.QVariant(True)) self.upButton.setAutoRaise(True) self.upButton.setDefaultAction(action) self.upButton.setIconSize(QtCore.QSize(iconsize, iconsize)) self.upButton.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.upButton.setStyle(TTToolButtonStyle()) self.upButton.setMaximumHeight(iconsize + 5) self.vlayout = QVBoxLayout(self) self.vlayout.setContentsMargins(0, 0, 0, 0) self.vlayout.setSpacing(0) self.vlayout.setDirection(QBoxLayout.TopToBottom) self.upButton.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) self.upButton.setPopupMode(QToolButton.DelayedPopup) self.vlayout.addWidget(self.upButton) self.downButton = QToolButton(self) self.downButton.setProperty("TTInternal", QtCore.QVariant(True)) self.downButton.setAutoRaise(True) self.downButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly) self.downButton.setPopupMode(QToolButton.InstantPopup) self.downButton.setMinimumHeight(25) self.downButton.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) self.downButton.setText(action.text()) self.downButton.setToolTip(action.toolTip()) self.downButton.setStyle(TTToolButtonStyle()) if menu: self.downButton.setMenu(menu) menu.aboutToHide.connect(lambda: self.set_hover(False)) self.vlayout.addWidget(self.downButton) self.setLayout(self.vlayout) self.hover = _TTHover(self, self.upButton, self.downButton) self.upButton.installEventFilter(self.hover) self.downButton.installEventFilter(self.hover) def set_hover(self, hover: bool): self.overlay.paint = hover self.update()
class GraphYieldView(QWidget): chart_views = None def __init__(self): super().__init__() self.v_layout = QVBoxLayout() self.model = GraphYieldModel() self.controller = GraphYieldController(self, self.model) self.init_main_layout() self.init_gui() self.init_graphs() def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setContentsMargins(0, 0, 0, 0) self.v_layout.setDirection(QVBoxLayout.TopToBottom) def init_gui(self): self.setMinimumWidth(Settings.WIDTH.value) self.setMinimumHeight(Settings.HEIGHT.value + 1800) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setLayout(self.v_layout) def init_graphs(self): years = self.model.get_all_years() self.setMinimumHeight(len(years) * 800) self.chart_views = [] for year in years: pairs = self.model.get_pairs_by_year(year) series = QBarSeries() for pair in pairs: q_bar_set = QBarSet(pair[0]) q_bar_set.append(pair[1]) series.append(q_bar_set) chart = QChart() axis_y = QValueAxis() axis_y.setTickCount(10) axis_y.setVisible(True) chart.addAxis(axis_y, Qt.AlignLeft) chart.addSeries(series) series.attachAxis(axis_y) chart.setTitle("Отчет за %s год" % year) chart.setAnimationOptions(QChart.SeriesAnimations) chart_view = QChartView(chart) chart_view.setRenderHint(QPainter.Antialiasing) self.chart_views.append(chart_view) self.v_layout.addWidget(chart_view, 0)
class GraphYieldView(QWidget): HEIGHT = 1080 WIDTH = 1600 def __init__(self): super().__init__() self.v_layout = QVBoxLayout() self.model = GraphYieldModel() self.controller = GraphYieldController(self) self.init_main_layout() self.init_gui() self.init_graphs() def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setContentsMargins(0, 0, 0, 0) self.v_layout.setDirection(QVBoxLayout.TopToBottom) def init_gui(self): self.setGeometry(0, 0, self.WIDTH, self.HEIGHT) self.setLayout(self.v_layout) def init_graphs(self): years = self.model.get_all_years() for year in years: pairs = self.model.get_pairs_by_year(year) series = QBarSeries() for pair in pairs: q_bar_set = QBarSet(pair[0]) q_bar_set.append(pair[1]) series.append(q_bar_set) chart = QChart() axis_y = QValueAxis() axis_y.setTickCount(10) axis_y.setVisible(True) chart.addAxis(axis_y, Qt.AlignLeft) chart.addSeries(series) series.attachAxis(axis_y) chart.setTitle("Отчет за %s год" % year) chart.setAnimationOptions(QChart.SeriesAnimations) chart_view = QChartView(chart) chart_view.setRenderHint(QPainter.Antialiasing) self.v_layout.addWidget(chart_view)
class TechniqueView(QWidget): HEIGHT = 1080 WIDTH = 1600 isLogin = True name = "kostya05983" stacked_widgets = None def __init__(self): super().__init__() self.model = TechniqueModel() self.controller = TechniqueController(self) self.v_layout = QVBoxLayout() self.grid_layout = None self.init_main_layout() self.init_gui() self.init_grid_technique() def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setDirection(QVBoxLayout.TopToBottom) self.setContentsMargins(0, 0, 0, 0) def init_gui(self): self.setGeometry(0, 0, self.WIDTH, self.HEIGHT) self.setLayout(self.v_layout) def init_grid_technique(self): qwidget = QWidget() qwidget.setStyleSheet("margin-left:20px") technique_list = self.model.get_technique() grid_layout = QGridLayout() qwidget.setLayout(grid_layout) for i in range(len(technique_list)): grid_layout.addWidget(technique_list[i], i // 4, i % 4) self.grid_layout = grid_layout self.v_layout.addWidget(qwidget, 0)
class ImportDialog(QDialog): paramsChanged = pyqtSignal(list) def __init__(self, name, file): super(QDialog, self).__init__() self.setWindowTitle(name) self.file = file self.checkBoxList = [] self.setMinimumSize(800, 500) self.drawWindow() def drawWindow(self): VLayout = QVBoxLayout() scrollArea = QScrollArea() scrollArea.setWidgetResizable(True) scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) #scrollArea.setStyleSheet('QScrollArea {border: 0px;}') self.scrollVlayout = QVBoxLayout() self.scrollVlayout.setDirection(QBoxLayout.TopToBottom) self.scrollVlayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet('QGroupBox {padding: 0px; margin: 0px;}') dummyBox.setLayout(self.scrollVlayout) scrollArea.setWidget(dummyBox) VLayout.addWidget(scrollArea) btnLayout = QHBoxLayout() btnLayout.setAlignment(Qt.AlignRight) doneBtn = QPushButton("Done") doneBtn.setFixedWidth(80) doneBtn.clicked.connect(self.doneClicked) btnLayout.addWidget(doneBtn) VLayout.addLayout(btnLayout) self.addStates(self.scrollVlayout, self.file[0], None, root=True) self.setLayout(VLayout) def addStates(self, layout, state, parentStateUIs, root=False): titleLblStyleSheet = 'QLabel:enabled{font-weight:bold; color:black;} ' \ 'QLabel:disabled{font-weight:bold; color:grey;}' childTitleLblStyleSheet = 'QLabel {font:italic; font-weight:bold;}' bulletLblStyleSheet = 'QLabel {font-size: 25px; font-weight:bold;}' stateUIs = [] if not root: rowLayout = QHBoxLayout() rowLayout.setAlignment(Qt.AlignLeft) rowLayout.addSpacing(5) checkBox = QCheckBox() checkBox.setFixedWidth(20) checkBox.setStyleSheet(bulletLblStyleSheet) checkBox.setChecked(True) checkBox.stateChanged.connect( partial(self.setStateEnabled, stateUIs)) if len(self.checkBoxList) < state.id: self.checkBoxList.extend([None] * (state.id - len(self.checkBoxList))) self.checkBoxList[state.id - 1] = checkBox if parentStateUIs is not None: parentStateUIs.append(checkBox) rowLayout.addWidget(checkBox) nameLbl = QLabel(state.getName()) nameLbl.setStyleSheet(titleLblStyleSheet) rowLayout.addWidget(nameLbl) stateUIs.append(nameLbl) if len(state.getNamespace().getParams()) > 0 or len( state.getChildren()) > 0: viewLbl = ClickableLabel(u'\u25BE') viewLbl.setMinimumWidth(20) rowLayout.addWidget(viewLbl) layout.addLayout(rowLayout) if len(state.getNamespace().getParams()) > 0 or len( state.getChildren()) > 0: rowLayout = QHBoxLayout() rowLayout.addSpacing(14) stateLayout = QVBoxLayout() stateLayout.setDirection(QBoxLayout.TopToBottom) stateLayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet( 'QGroupBox {padding: 0px; margin: 0px; border-left: 1px solid gray; ' 'border-top: 0px;}') dummyBox.setLayout(stateLayout) rowLayout.addWidget(dummyBox) viewLbl.clicked.connect(partial(self.toggleView, dummyBox)) layout.addLayout(rowLayout) else: stateLayout = layout if len(state.getNamespace().getParams()) > 0: self.displayStateParams(state, stateLayout, stateUIs, childTitleLblStyleSheet) if len(state.getChildren()) > 0: childStatesTitleLbl = QLabel('Child States:') childStatesTitleLbl.setStyleSheet(childTitleLblStyleSheet) stateLayout.addWidget(childStatesTitleLbl) stateUIs.append(childStatesTitleLbl) for child in state.getChildren(): if root: self.addStates(stateLayout, child, None) else: self.addStates(stateLayout, child, stateUIs) dummyBox = QGroupBox() dummyBox.setStyleSheet( 'QGroupBox {background-color: white; border: 0px;}') dummyBox.setMinimumWidth(100) dummyBox.setFixedHeight(0) stateLayout.addWidget(dummyBox) def setStateEnabled(self, stateUIs, state): for UI in stateUIs: if UI is not None: if type(UI) == list: self.setStateEnabled(UI, state) else: UI.setEnabled(state) if isinstance(UI, QCheckBox): UI.setChecked(state) def toggleView(self, widget): label = self.sender() if widget.isHidden(): widget.setHidden(False) label.setText(u'\u25BE') else: widget.setHidden(True) label.setText(u'\u25B8') label.setMinimumWidth(20) def displayStateParams(self, state, stateLayout, stateUIs, childTitleLblStyleSheet): rowLayout = QHBoxLayout() rowLayout.setAlignment(Qt.AlignLeft) paramTitleLbl = QLabel('Parameters') paramTitleLbl.setStyleSheet(childTitleLblStyleSheet) rowLayout.addWidget(paramTitleLbl) viewLbl = ClickableLabel(u'\u25BE') viewLbl.setMinimumWidth(20) rowLayout.addWidget(viewLbl) stateLayout.addLayout(rowLayout) stateUIs.append(paramTitleLbl) rowLayout = QHBoxLayout() rowLayout.addSpacing(10) paramLayout = QVBoxLayout() paramLayout.setDirection(QBoxLayout.TopToBottom) paramLayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet( 'QGroupBox {background-color: white; border: 0px; border-radius:3px;}' ) dummyBox.setLayout(paramLayout) rowLayout.addWidget(dummyBox) viewLbl.clicked.connect(partial(self.toggleView, dummyBox)) stateLayout.addLayout(rowLayout) titleLblStyleSheet = 'QLabel {font: italic;}' rowLayout = QHBoxLayout() titleLbl = QLabel('') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(20) rowLayout.addWidget(titleLbl) titleLbl = QLabel('Name') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(150) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) rowLayout.addSpacing(5) titleLbl = QLabel('Type') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(60) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) rowLayout.addSpacing(5) titleLbl = QLabel('Value') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(100) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) rowLayout.addSpacing(5) titleLbl = QLabel('Description') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setMinimumWidth(300) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) paramLayout.addLayout(rowLayout) for param in state.getNamespace().getParams(): paramUIs = self.addParam(paramLayout, param) stateUIs.append(paramUIs) def addParam(self, layout, param): paramUIs = [] rowLayout = QHBoxLayout() showLbl = ClickableLabel(u'\U0001F441') showLbl.setToolTip("View") showLbl.clicked.connect(partial(self.showParam, param)) showLbl.setFixedWidth(20) rowLayout.addWidget(showLbl) nameLbl = ElidedLabel(param.name) nameLbl.setToolTip(param.name) nameLbl.setFixedWidth(150) rowLayout.addWidget(nameLbl) paramUIs.append(nameLbl) rowLayout.addSpacing(5) typeLbl = ElidedLabel(param.type) typeLbl.setFixedWidth(60) rowLayout.addWidget(typeLbl) paramUIs.append(typeLbl) rowLayout.addSpacing(5) valueLbl = ElidedLabel(param.value) valueLbl.setToolTip(param.value) valueLbl.setFixedWidth(100) rowLayout.addWidget(valueLbl) paramUIs.append(valueLbl) rowLayout.addSpacing(5) descLbl = ElidedLabel(param.desc) descLbl.setAlignment(Qt.AlignTop) descLbl.setFixedHeight(17) descLbl.setToolTip(param.desc) descLbl.setMinimumWidth(300) rowLayout.addWidget(descLbl) paramUIs.append(descLbl) layout.addLayout(rowLayout) return paramUIs def showParam(self, param): paramPropDialog = ParamPropDialog(param=param, modify=False) paramPropDialog.exec_() def removeStates(self, parentState): remList = [] for child in parentState.getChildren(): if not self.checkBoxList[child.id - 1].isChecked(): remList.append(child) else: self.removeStates(child) for child in remList: for transition in child.getDestTransitions(): transition.origin.removeOriginTransition(transition) parentState.removeChild(child) def doneClicked(self): self.removeStates(self.file[0]) self.accept()
def displayStateParams(self, state, stateLayout, stateUIs, childTitleLblStyleSheet): rowLayout = QHBoxLayout() rowLayout.setAlignment(Qt.AlignLeft) paramTitleLbl = QLabel('Parameters') paramTitleLbl.setStyleSheet(childTitleLblStyleSheet) rowLayout.addWidget(paramTitleLbl) viewLbl = ClickableLabel(u'\u25BE') viewLbl.setMinimumWidth(20) rowLayout.addWidget(viewLbl) stateLayout.addLayout(rowLayout) stateUIs.append(paramTitleLbl) rowLayout = QHBoxLayout() rowLayout.addSpacing(10) paramLayout = QVBoxLayout() paramLayout.setDirection(QBoxLayout.TopToBottom) paramLayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet( 'QGroupBox {background-color: white; border: 0px; border-radius:3px;}' ) dummyBox.setLayout(paramLayout) rowLayout.addWidget(dummyBox) viewLbl.clicked.connect(partial(self.toggleView, dummyBox)) stateLayout.addLayout(rowLayout) titleLblStyleSheet = 'QLabel {font: italic;}' rowLayout = QHBoxLayout() titleLbl = QLabel('') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(20) rowLayout.addWidget(titleLbl) titleLbl = QLabel('Name') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(150) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) rowLayout.addSpacing(5) titleLbl = QLabel('Type') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(60) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) rowLayout.addSpacing(5) titleLbl = QLabel('Value') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setFixedWidth(100) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) rowLayout.addSpacing(5) titleLbl = QLabel('Description') titleLbl.setStyleSheet(titleLblStyleSheet) titleLbl.setMinimumWidth(300) rowLayout.addWidget(titleLbl) stateUIs.append(titleLbl) paramLayout.addLayout(rowLayout) for param in state.getNamespace().getParams(): paramUIs = self.addParam(paramLayout, param) stateUIs.append(paramUIs)
class WorkspaceTab(QWidget): def __init__(self): super(QWidget, self).__init__() layout = QVBoxLayout() self.setLayout(layout) scrollArea = QScrollArea() scrollArea.setMinimumHeight(200) scrollArea.setWidgetResizable(True) scrollArea.setStyleSheet('QScrollArea {border: 0;}') layout.addWidget(scrollArea) workspaceBox = QGroupBox('Catkin Workspaces') scrollArea.setWidget(workspaceBox) self.workspaceLayout = QVBoxLayout() self.workspaceLayout.setDirection(QBoxLayout.TopToBottom) self.workspaceLayout.setAlignment(Qt.AlignTop) workspaceBox.setLayout(self.workspaceLayout) buildRowLayout = QHBoxLayout() self.workspaceLayout.addLayout(buildRowLayout) chooseDirButton = QPushButton('Choose File') chooseDirButton.setMaximumWidth(100) chooseDirButton.setObjectName('choose') chooseDirButton.clicked.connect(self.chooseDir) buildRowLayout.addWidget(chooseDirButton) self.dirLabel = QLabel() self.dirLabel.setMinimumWidth(400) buildRowLayout.addWidget(self.dirLabel) addButton = QPushButton('Add') addButton.setMaximumWidth(100) addButton.setObjectName('build') addButton.clicked.connect(self.addWorkspace) buildRowLayout.addWidget(addButton) # load current workspaces self.workspaceUIs = [] self.drawWorkspaces(readWorkspaces()) def chooseDir(self): selectedDir = QFileDialog.getExistingDirectory( self, 'Choose Catkin Workspace Directory') self.dirLabel.setText(selectedDir) def addWorkspace(self): newDir = self.dirLabel.text() if newDir == '': QMessageBox.warning( self, 'Invalid Workspace', 'This is not a catkin workspace or specified path was not found' ) elif self.isValidWorkspace(newDir): workspaces = readWorkspaces() if newDir in workspaces: QMessageBox.information( self, 'Workspace present', 'The workspace entered is already present in the list') return workspaces.append(newDir) writeWorkspaces(workspaces) self.drawWorkspaces(workspaces) else: QMessageBox.warning( self, 'Invalid Workspace', 'The catkin workspace dir:' + newDir + ' is not a valid. Please make sure that the directory has src, devel and build directories.' ) def isValidWorkspace(self, dir): files = os.listdir(dir) return '.catkin_workspace' in files def addWorkspaceUI(self, layout, dir, workspaceUIs, removeCallback): uiData = {} rowLayout = QHBoxLayout() uiData['layout'] = rowLayout layout.addLayout(rowLayout) label = QLabel(dir) label.setStyleSheet('QLabel { border: 1px solid black; }') uiData['label'] = label removeBtn = QPushButton('Remove') removeBtn.setMaximumWidth(80) removeBtn.clicked.connect(removeCallback) removeBtn.setObjectName(dir) uiData['btn'] = removeBtn rowLayout.addWidget(label) rowLayout.addWidget(removeBtn) workspaceUIs.append(uiData) def removeWorkspace(self): dir = self.sender().objectName() workspaces = readWorkspaces() workspaces.remove(dir) writeWorkspaces(workspaces) self.drawWorkspaces(workspaces) def drawWorkspaces(self, workspaces): # remove previous UIs for uiData in self.workspaceUIs: uiData['label'].deleteLater() uiData['btn'].deleteLater() uiData['layout'].deleteLater() self.workspaceUIs = [] for dir in workspaces: self.addWorkspaceUI(self.workspaceLayout, dir, self.workspaceUIs, self.removeWorkspace)
class DiscordOverlay(Overlay): def __init__(self, parent): super(DiscordOverlay, self).__init__(name='DiscordOverlay', pos_x=0, pos_y=0, width=200, height=200, parent=parent) self.image_getter = ImageGetter() self.setAttribute(Qt.WA_AlwaysShowToolTips) self.is_visible = True self.header_widget = None self.content_widget = None self.users = {} self.avatars = {} self.default_avatar = self.get_avatar('def') self.add_header() self.add_content_widget_layout() def launch(self): self.show() #QTimer.singleShot(3000, self.activate_bg) def activate_bg(self): self.parent().sys_tray_icon.showMessage( 'Discord Overlay', 'Hidding the frame but running in background.\nSee the Menu (Right click) to move/resize' ) self.toggle() def add_header(self): self.header_widget = OverlayHeaderWidget(parent=self, title=self.name) self.layout.addWidget(self.header_widget) self.header_widget.show() def add_content_widget_layout(self): self.content_layout = QVBoxLayout() self.content_layout.setDirection(QVBoxLayout.BottomToTop) self.content_layout.setAlignment(Qt.AlignTop) self.content_layout.setContentsMargins(0, 0, 0, 0) self.content_layout.setSpacing(0) self.content_widget = QWidget(self) self.content_widget.setObjectName('content_widget') self.content_widget.setLayout(self.content_layout) self.content_widget.setStyleSheet( '#content_widget{border: 1px dotted pink;}') self.layout.addWidget(self.content_widget) def get_user_widget(self, user, avatar_data): user_widget = UserWidget(user=user, avatar_data=avatar_data, parent=self) return user_widget def get_avatar(self, identifier, avatar=None): if identifier == 'def' or not avatar: url = 'https://cdn.discordapp.com/embed/avatars/3.png' else: url = 'https://cdn.discordapp.com/avatars/%s/%s.jpg' % (identifier, avatar) data = self.image_getter.from_url(url) return data def toggle(self): if self.is_visible: self.header_widget.hide() self.content_widget.setStyleSheet('#content_widget{border: none;}') else: self.header_widget.show() self.content_widget.setStyleSheet( '#content_widget{border: 1px dotted pink;}') self.is_visible = not self.is_visible def you_left_voice_channel(self): self.clear_users() def clear_users(self): self.users = {} for i in reversed(range(self.content_layout.count())): widget = self.content_layout.itemAt(i).widget() self.content_layout.removeWidget(widget) if widget: widget.setParent(None) def someone_joined_channel(self, data): user = data['data']['user'] user['nick'] = data['data']['nick'] user['voice_state'] = data['data']['voice_state'] if self.users.get(user['id']): return self.update_user(user) else: self.users[user['id']] = user user['avatar_data'] = self.get_avatar(user['id'], user['avatar']) user_widget = self.get_user_widget( self.users[user['id']], self.users[user['id']]['avatar_data']) self.content_layout.addWidget(user_widget) self.update_user(user) def someone_left_channel(self, data): user_id = data['data']['user']['id'] if self.parent().discord_connector.user['id'] == user_id: self.clear_users() return del self.users[user_id] widget = self.find_user_widget(user_id) if not widget: return self.content_layout.removeWidget(widget) widget.setParent(None) def update_user(self, user): # TODO: WTF widget = self.find_user_widget(user['id']) if user['nick'] != widget.nick_label.text(): widget.nick_label.setText(user['nick']) if user['voice_state']['deaf'] \ or user['voice_state']['self_deaf'] \ or ( \ (user['voice_state']['deaf'] or user['voice_state']['self_deaf']) \ and (user['voice_state']['mute'] or user['voice_state']['self_mute']) \ ): if user.get('deafen'): return pixmap = QPixmap(':/images/deaf.png') for qlabel in widget.findChildren(QLabel): if qlabel.objectName() == 'mute_user': qlabel.setParent(None) image = QLabel(widget, text='d') image.setObjectName('deaf_user') image.setPixmap( pixmap.scaled(20, 20, Qt.KeepAspectRatio, Qt.FastTransformation)) image.setFixedSize(20, 20) widget.layout().addWidget(image, 0, 1, Qt.AlignRight | Qt.AlignBottom) user['deafen'] = True return if user['voice_state']['mute'] or user['voice_state']['self_mute']: pixmap = QPixmap(':/images/mute.png') for qlabel in widget.findChildren(QLabel): if qlabel.objectName() == 'deaf_user': qlabel.setParent(None) image = QLabel(widget, text='d') image.setObjectName('mute_user') image.setPixmap( pixmap.scaled(20, 20, Qt.KeepAspectRatio, Qt.FastTransformation)) image.setFixedSize(20, 20) widget.layout().addWidget(image, 0, 1, Qt.AlignRight | Qt.AlignBottom) user['muted'] = True if not user['voice_state']['mute'] and not user['voice_state'][ 'self_mute']: for qlabel in widget.findChildren(QLabel): if qlabel.objectName() == 'mute_user': qlabel.setParent(None) user['mute'] = False if not user['voice_state']['deaf'] and not user['voice_state'][ 'self_deaf']: for qlabel in widget.findChildren(QLabel): if qlabel.objectName() == 'deaf_user': qlabel.setParent(None) user['deafen'] = False def you_joined_voice_channel_signal(self, data=None): self.clear_users() def speaking_start_signal(self, data): user_id = data['data']['user_id'] self.set_user_widget_border(user_id, '2px solid green') def speaking_stop_signal(self, data): user_id = data['data']['user_id'] self.set_user_widget_border(user_id, '0px') def set_user_widget_border(self, user_id, border): widget = self.find_user_widget(user_id) if not widget: return widget.setStyleSheet('#user_widget_%s { border: %s}' % (user_id, border)) def find_user_widget(self, user_id): for widget in self.content_widget.findChildren(QWidget): if widget.objectName() == 'user_widget_%s' % user_id: return widget return None
class MainTableWidget(QWidget): def __init__(self, parent): super(QWidget, self).__init__(parent) self.layout = QVBoxLayout(self) self.layout.setDirection(QVBoxLayout.Direction.LeftToRight) # Initialize tab screen self.tabs = QTabWidget() self.tab1 = AddFunctionWidget(self) self.tab2 = FunctionPlotWidget(self) self.tab3 = SolidRevWidget(self) self.tab4 = CalculateVolumeWidget(self) # Array of indices of tabs with plots (for making updates when switching to them) self.tabsWithPlots = [1,2,3] # Function whenever a new tab is clicked self.tabs.currentChanged.connect(self.updatePlot) # Add tabs self.tabs.addTab(self.tab1,"Agrega Funciones") self.tabs.addTab(self.tab2,"Ver Función") self.tabs.addTab(self.tab3,"Ver Sólido de Revolución") self.tabs.addTab(self.tab4,"Cálculo de Volumen") # Add tabs to widget self.layout.addWidget(self.tabs) self.tableWidget = None #self.checkBoxLayout = QVBoxLayout() self.checkBoxGroup = QButtonGroup() self.updateListWidget() # Function to be used for function titles self.functionTitleFont = QFont() self.functionTitleFont.setBold(True) self.functionTitleFont.setPointSize(14) # Function for updatting math functions widget when new functions are added def updateListWidget(self, addCheckBox = False): # Delete existing layouts if(self.tableWidget != None): self.layout.removeWidget(self.tableWidget) listLength = len(GlobalVariables.mathFunctionsList) # Row added for each function, and row added for each function part rowAmount = listLength for mathFunction in GlobalVariables.mathFunctionsList: rowAmount += len(mathFunction) self.tableWidget = QTableWidget(rowAmount, 3, self) header = self.tableWidget.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) rowIndex = 0 for i in range(listLength): mathFunction = GlobalVariables.mathFunctionsList[i] rowLabel = QLabel() self.tableWidget.setSpan(rowIndex, 0, 1, 2) # Mix 2 columns for function title rowLabel.setText("Función " + str(i+1)) rowLabel.setFont(self.functionTitleFont) rowLabel.setAlignment(Qt.AlignCenter) self.tableWidget.setCellWidget(rowIndex, 0, rowLabel) # Add name of this function as a whole self.tableWidget.setSpan(rowIndex, 2, len(mathFunction) + 1, 1) # Mix rows depending on number of parts of this function # Add Checkbox for this function newCheckBox = QCheckBox("F" + str(i+1)) newCheckBox.released.connect(self.selectFunction) # Set first checkbox to be on if(listLength==1): newCheckBox.setChecked(True) GlobalVariables.selectedIndex = 0 # Set the currently selected Checkbox if(GlobalVariables.selectedIndex == i): newCheckBox.setChecked(True) self.tableWidget.setCellWidget(rowIndex, 2, newCheckBox) self.checkBoxGroup.addButton(newCheckBox, i) rowIndex += 1 for j in range(rowIndex, rowIndex + len(mathFunction)): part = mathFunction[j-rowIndex] createLatexFormula(r'$f(x) = '+ latex(part.f_expression) +'$', 'equations/function_part_' + str(j), 90) createLatexFormula(r'$ x \in ('+str(part.x0)+', '+str(part.x1)+')$', 'equations/interval_' + str(j), 90) partLabel = QLabel() partLabel.setPixmap(QPixmap('equations/function_part_' + str(j))) self.tableWidget.setCellWidget(j, 0, partLabel) partInterval = QLabel() partInterval.setPixmap(QPixmap('equations/interval_' + str(j))) self.tableWidget.setCellWidget(j, 1, partInterval) rowIndex += len(mathFunction) self.tableWidget.setMaximumWidth(0.4 * GlobalVariables.screenWidth) self.layout.addWidget(self.tableWidget) self.setLayout(self.layout) # Function to set index of the selected function def selectFunction(self): GlobalVariables.selectedIndex = self.checkBoxGroup.checkedId() if(self.tabs.currentIndex() in self.tabsWithPlots): self.tabs.currentWidget().updatePlot() # Function to update Plot of the current tab (must have at least one function added) def updatePlot(self, index): if(index in self.tabsWithPlots and GlobalVariables.selectedIndex != -1): self.tabs.widget(index).updatePlot()
class MainWindow(QMainWindow): """ This class represents the main window of the kollektiv5gui. It contains a table, which displays an overview of all classes in the dataset, a menu at the top, and a read-only textbox below the table. """ # Signal used to append logging output, allows printing from another thread sig = pyqtSignal(str) def __init__(self): super().__init__() self.__initDataset() self.__initWindow() self.__initTopBar() self.__initMenuBar() self.__initTable() self.__initConsole() # Sizes of the splitterWidget (the vertical splitter) need to be set # after all elements have been added to it. This is slightly ugly, # but the best way to solve this (I think). self.splitterWidget.setSizes([512, 128]) self.show() logging.setLoggingFunction(lambda x: self.sig.emit(x)) self.sig.connect(self.log) def __initWindow(self): """ Initialize the main properties of the window. """ self.setWindowTitle('Kollektiv 5 GUI') self.resize(1280, 720) self.mainWidget = QWidget() self.layout = QVBoxLayout() self.layout.setDirection(QVBoxLayout.BottomToTop) self.mainWidget.setLayout(self.layout) self.setCentralWidget(self.mainWidget) self.splitterWidget = QSplitter() self.splitterWidget.setOrientation(Qt.Vertical) self.splitterWidgetLayout = QVBoxLayout(self.splitterWidget) self.splitterWidget.setLayout(self.splitterWidgetLayout) self.layout.addWidget(self.splitterWidget) def __initMenuBar(self): """ Initialize the menu bar for the window. """ self.menu = self.menuBar() actionQuit = QAction('Close', self) actionQuit.triggered.connect(self.close) actionViewHelp = QAction('View Documentation', self) actionViewHelp.triggered.connect(self.help) actionApiPrefs = QAction('API', self) actionApiPrefs.triggered.connect(self.openApiSettings) # top-level menus menuFile = self.menu.addMenu('File') menuPrefs = self.menu.addMenu('Preferences') menuHelp = self.menu.addMenu('Help') # "File" menu menuFile.addAction(actionQuit) # "Preferences" menu menuPrefs.addAction(actionApiPrefs) # "Help" menu menuHelp.addAction(actionViewHelp) def __initTopBar(self): """ Initialize the two buttons atop the dataset table """ self.topBar = QHBoxLayout() self.generateButtonAny = QPushButton('Generate Any') self.generateButtonAny.clicked.connect( self.openGeneratingWindowNoTarget) self.topBar.addWidget(self.generateButtonAny) self.generateButtonSelected = QPushButton('Generate Selected') self.generateButtonSelected.setEnabled(False) self.generateButtonSelected.clicked.connect(self.openGeneratingWindow) self.topBar.addWidget(self.generateButtonSelected) self.layout.addLayout(self.topBar) def __initTable(self): """ Create the dataset table and place it at the top of the vertical splitter. """ self.table = DatasetTableWidget(self, self.splitterWidget) self.splitterWidgetLayout.addWidget(self.table) def __initConsole(self): """ Create a read-only textbox at the bottom of the vertical splitter. It is used to print text-based information. """ self.console = QTextEdit(self.splitterWidget) self.console.setReadOnly(True) self.log('Started...') self.splitterWidgetLayout.addWidget(self.console) def __initDataset(self): """ Load the dataset from the default path """ self.__dataset = Dataset() self.__dataset.loadFromFile( os.path.join(getResourcePath(), 'dataset.json')) def getDataset(self): return self.__dataset def openGeneratingWindowNoTarget(self): """ Open the generating window without any target classes specified. """ self.generatingWindow = GeneratingWindow(self, []) def openGeneratingWindow(self): """ Open the generating window with a set of target classes specified. """ selectedClasses = self.table.getSelectedClasses() selectedClassesNames = [c.name for c in selectedClasses] unknownClasses = list(filter(lambda x: not x.known, selectedClasses)) if len(unknownClasses) > 0: # display a warning if classes may be unknown in the API msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setText('At least one of the classes you are trying to ' 'generate may not be recognized by the API!') msg.setWindowTitle('Warning!') msg.setDetailedText('\n'.join([c.name for c in unknownClasses])) msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) retval = msg.exec_() if retval & QMessageBox.Ok == 0: return self.generatingWindow = GeneratingWindow(self, selectedClassesNames) def openApiSettings(self): """ Open the window to modify the API settings """ self.configureApiWindow = ConfigureApiWindow(self) def log(self, text): """ Print a text to the read-only textbox at the bottom of the window. """ date = time.strftime('%H:%M:%S') text = '%s: %s' % (date, text) print(text) self.console.setText('%s\n%s' % (self.console.toPlainText(), text)) self.console.verticalScrollBar().setValue( self.console.verticalScrollBar().maximum()) self.statusBar().showMessage(text) def help(self): """ Open the handbook in the system's PDF reader """ # webbrowser.open does not necessarily open the file in a webbrowser # it opens it in whatever program the user has set as their pdf reader webbrowser.open('file://%s' % os.path.join(getResourcePath(), 'handbook.pdf'))
class PackageTab(QWidget): def __init__(self, config): super(QWidget, self).__init__() # the list of packages for build and run dependencies self.buildDependencies = config.getBuildDependencies() self.buildDependenciesUI = [] self.runDependencies = config.getRunDependencies() self.runDependenciesUI = [] layout = QVBoxLayout() self.setLayout(layout) buildDependenciesScroll = QScrollArea() buildDependenciesScroll.setMinimumHeight(200) buildDependenciesScroll.setWidgetResizable(True) buildDependenciesScroll.setStyleSheet('QScrollArea {border: 0;}') layout.addWidget(buildDependenciesScroll) buildDependenciesBox = QGroupBox('Build Dependencies') buildDependenciesScroll.setWidget(buildDependenciesBox) self.buildLayout = QVBoxLayout() self.buildLayout.setDirection(QBoxLayout.TopToBottom) self.buildLayout.setAlignment(Qt.AlignTop) buildDependenciesBox.setLayout(self.buildLayout) buildRowLayout = QHBoxLayout() self.buildLayout.addLayout(buildRowLayout) self.buildDependenciesCb = QComboBox() self.buildDependenciesCb.setEditable(True) buildRowLayout.addWidget(self.buildDependenciesCb) buildAddButton = QPushButton('Add') buildAddButton.setMaximumWidth(80) buildAddButton.setObjectName('build') buildAddButton.clicked.connect(self.addDependency) buildRowLayout.addWidget(buildAddButton) runDependenciesScroll = QScrollArea() runDependenciesScroll.setMinimumHeight(200) runDependenciesScroll.setWidgetResizable(True) runDependenciesScroll.setStyleSheet('QScrollArea { border: 0;}') layout.addWidget(runDependenciesScroll) runDependenciesBox = QGroupBox('Run Dependencies') runDependenciesScroll.setWidget(runDependenciesBox) self.runLayout = QVBoxLayout() self.runLayout.setDirection(QBoxLayout.TopToBottom) self.runLayout.setAlignment(Qt.AlignTop) runDependenciesBox.setLayout(self.runLayout) runRowLayout = QHBoxLayout() self.runLayout.addLayout(runRowLayout) self.runDependenciesCb = QComboBox() self.runDependenciesCb.setEditable(True) runRowLayout.addWidget(self.runDependenciesCb) runAddButton = QPushButton('Add') runAddButton.setMaximumWidth(80) runAddButton.setObjectName('run') runAddButton.clicked.connect(self.addDependency) runRowLayout.addWidget(runAddButton) # fill the packages packages = getAllPackages() packages = sorted(packages) for pkg in packages: self.runDependenciesCb.addItem(pkg) self.buildDependenciesCb.addItem(pkg) self.drawDependenciesUI() def addDependency(self): layout = None dependency = None removeCallback = None dependenciesUI = None if self.sender().objectName() == 'build': layout = self.buildLayout dependency = self.buildDependenciesCb.currentText() if len(dependency) > 0: removeCallback = self.removeBuildDependency dependenciesUI = self.buildDependenciesUI self.buildDependencies.append(dependency) elif self.sender().objectName() == 'run': layout = self.runLayout dependency = self.runDependenciesCb.currentText() if len(dependency) > 0: removeCallback = self.removeRunDependency dependenciesUI = self.runDependenciesUI self.runDependencies.append(dependency) if dependenciesUI is not None: self.addDependencyUIs(layout, dependency, dependenciesUI, removeCallback) def addDependencyUIs(self, layout, dependency, dependenciesUI, removeCallback): dep = {} rowLayout = QHBoxLayout() dep['layout'] = rowLayout layout.addLayout(rowLayout) label = QLabel(dependency) label.setStyleSheet('QLabel { border: 1px solid black; }') dep['label'] = label removeBtn = QPushButton('Remove') removeBtn.setMaximumWidth(80) removeBtn.clicked.connect(removeCallback) removeBtn.setObjectName(dependency) dep['btn'] = removeBtn rowLayout.addWidget(label) rowLayout.addWidget(removeBtn) dependenciesUI.append(dep) def removeDep(self, dep, dependenciesUI): removeItem = None for runDep in dependenciesUI: if runDep['label'].text() == dep: removeItem = runDep break if removeItem is not None: dependenciesUI.remove(removeItem) removeItem['label'].deleteLater() removeItem['btn'].deleteLater() removeItem['layout'].deleteLater() def removeRunDependency(self): dep = self.sender().objectName() self.runDependencies.remove(dep) self.removeDep(dep, self.runDependenciesUI) def removeBuildDependency(self): dep = self.sender().objectName() self.buildDependencies.remove(dep) self.removeDep(dep, self.buildDependenciesUI) def drawDependenciesUI(self): # remove previous UIs if exists for depUI in self.runDependenciesUI: depUI['label'].deleteLater() depUI['btn'].deleteLater() depUI['layout'].deleteLater() for depUI in self.buildDependenciesUI: depUI['label'].deleteLater() depUI['btn'].deleteLater() depUI['layout'].deleteLater() # add dependency for given for dep in self.runDependencies: self.addDependencyUIs(self.runLayout, dep, self.runDependenciesUI, self.removeRunDependency) for dep in self.buildDependencies: self.addDependencyUIs(self.buildLayout, dep, self.buildDependenciesUI, self.removeBuildDependency)
class ActionWidget(QWidget): def __init__(self): super().__init__() self.layout = QVBoxLayout() self.layout.setDirection(QVBoxLayout.LeftToRight) self.labels = [] self.avaliable_actions = [ 'Pick action:', 'Pick up:', 'Travel to:', 'Leave cars at:' ] self.set_combobox() self.setLayout(self.layout) def set_combobox(self): self.combobox = QComboBox() for action in self.avaliable_actions: self.combobox.addItem(action) self.layout.addWidget(self.combobox) self.combobox.activated.connect(self.set_labels_by_combobox) def set_labels(self, label_text): if len(self.labels) != 0: self.purge_old_labels() self.update() for i in range(len(label_text)): label_name = 'label_{}'.format(i) label = DropInLabel(label_text[i]) label.setObjectName(label_name) self.labels.append(label) for label in self.labels: self.layout.addWidget(label) self.update() def purge_old_labels(self): for i in reversed(range(self.layout.count())): if i != 0: widgetToRemove = self.layout.itemAt(i).widget() self.layout.removeWidget(widgetToRemove) widgetToRemove.setParent(None) self.labels.clear() self.layout.update() def set_labels_by_combobox(self): if self.combobox.currentText() == 'Pick up:': self.set_labels( ['drop loco here', 'drop wagon here', 'drop station here']) elif self.combobox.currentText() == 'Travel to:': self.set_labels(['drop loco here', 'station from', 'station to']) elif self.combobox.currentText() == 'Leave cars at:': self.set_labels(['drop car here', 'drop station here']) def get_filler_text(self): filler_words = [] if self.combobox.currentText() == 'Pick up:': filler_words = [ 'Locomotive number ', 'pick up wagons ', 'at station ' ] elif self.combobox.currentText() == 'Travel to:': filler_words = [ 'Locomotive number ', 'travel from station ', 'to station ' ] elif self.combobox.currentText() == 'Leave cars at:': filler_words = ['Leave wagons ', 'at station '] return filler_words def get_composed_string(self): composed_string = "" filler_text = self.get_filler_text() i = 0 for label in self.labels: composed_string += filler_text[i] composed_string += label.text() composed_string += " " i += 1 return composed_string
class LibrariesDialog(QDialog): librariesChanged = pyqtSignal(list) def __init__(self, name, libraries): super(QDialog, self).__init__() self.setWindowTitle(name) self.setMinimumHeight(500) self.setMinimumWidth(500) self.libraries = libraries self.libraryNameEdit = QLineEdit() self.addButton = QPushButton("Add") self.addButton.setMinimumWidth(100) # create gui of verticalLayout = QVBoxLayout() self.setLayout(verticalLayout) scrollArea = QScrollArea() scrollArea.setMinimumHeight(400) scrollArea.setWidgetResizable(True) scrollArea.setStyleSheet('QScrollArea {border: 0;}') verticalLayout.addWidget(scrollArea) groupBox = QGroupBox("Libraries") scrollArea.setWidget(groupBox) self.groupLayout = QVBoxLayout() self.groupLayout.setDirection(QBoxLayout.TopToBottom) self.groupLayout.setAlignment(Qt.AlignTop) groupBox.setLayout(self.groupLayout) # add row to group layout rowLayout = QHBoxLayout() self.groupLayout.addLayout(rowLayout) rowLayout.addWidget(self.libraryNameEdit) rowLayout.addWidget(self.addButton) self.addButton.clicked.connect(self.addClicked) self.libraryUIs = {} # add libraries to the ui for libraryName in self.libraries: self.addLibraryItem(libraryName) def removed(self, libraryName): if libraryName in self.libraryUIs: libRow = self.libraryUIs[libraryName] libRow.disconnect() self.groupLayout.removeWidget(libRow) del self.libraryUIs[libraryName] libRow.deleteLater() self.libraries.remove(libraryName) self.librariesChanged.emit(self.libraries) def updated(self, oldLibraryName, newLibraryName): if oldLibraryName in self.libraryUIs: libRow = self.libraryUIs[oldLibraryName] del self.libraryUIs[oldLibraryName] self.libraryUIs[newLibraryName] = libRow # update library list for i in range(len(self.libraries)): if self.libraries[i] == oldLibraryName: self.libraries[i] = newLibraryName break self.librariesChanged.emit(self.libraries) def addClicked(self): libraryInp = self.libraryNameEdit.text().strip() if libraryInp in self.libraries: QMessageBox.information(self, "Library Present", "Library already present in the list") return if libraryInp: self.libraries.append(self.libraryNameEdit.text()) self.librariesChanged.emit(self.libraries) self.addLibraryItem(self.libraryNameEdit.text()) self.libraryNameEdit.setText('') def addLibraryItem(self, libraryName): libRow = EditableStringWidget(libraryName) self.libraryUIs[libraryName] = libRow libRow.removed.connect(self.removed) libRow.updated.connect(self.updated) self.groupLayout.addWidget(libRow)
class ParamsTab(QDialog): paramsChanged = pyqtSignal(list) def __init__(self, params): super(QDialog, self).__init__() self.params = OrderedDict() for param in params: self.params[param.name] = param self.paramUIs = {} self.removeIds = [] self.drawWindow() def drawWindow(self): VLayout = QVBoxLayout() btnLayout = QHBoxLayout() btnLayout.setAlignment(Qt.AlignLeft) newBtn = QPushButton("New") newBtn.setFixedWidth(200) newBtn.clicked.connect(self.newClicked) btnLayout.addWidget(newBtn) VLayout.addLayout(btnLayout) rowLayout = QHBoxLayout() rowLayout.setAlignment(Qt.AlignLeft) rowLayout.addSpacing(10) titleLblStyleSheet = 'QLabel {font-weight: bold;}' nameLbl = QLabel('Name') nameLbl.setStyleSheet(titleLblStyleSheet) nameLbl.setFixedWidth(100) rowLayout.addWidget(nameLbl) typeLbl = QLabel('Type') typeLbl.setStyleSheet(titleLblStyleSheet) typeLbl.setFixedWidth(60) rowLayout.addWidget(typeLbl) valueLbl = QLabel('Value') valueLbl.setStyleSheet(titleLblStyleSheet) valueLbl.setFixedWidth(100) rowLayout.addWidget(valueLbl) descLbl = QLabel('Description') descLbl.setStyleSheet(titleLblStyleSheet) descLbl.setMinimumWidth(280) rowLayout.addWidget(descLbl) VLayout.addLayout(rowLayout) scrollArea = QScrollArea() scrollArea.setWidgetResizable(True) scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) #scrollArea.setStyleSheet('QScrollArea {border: 0px;}') self.scrollVlayout = QVBoxLayout() self.scrollVlayout.setDirection(QBoxLayout.TopToBottom) self.scrollVlayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet('QGroupBox {padding-top: 20px; margin-top: -20px;}') dummyBox.setLayout(self.scrollVlayout) scrollArea.setWidget(dummyBox) VLayout.addWidget(scrollArea) for param in self.params.values(): self.addParam(param) self.setLayout(VLayout) def addParam(self, param): rowLayout = QHBoxLayout() nameLbl = ElidedLabel(param.name) nameLbl.setToolTip(param.name) nameLbl.setFixedWidth(100) rowLayout.addWidget(nameLbl) typeLbl = ElidedLabel(param.type) typeLbl.setFixedWidth(60) rowLayout.addWidget(typeLbl) valueLbl = ElidedLabel(param.value) valueLbl.setToolTip(param.value) valueLbl.setFixedWidth(100) rowLayout.addWidget(valueLbl) descLbl = ElidedLabel(param.desc) descLbl.setAlignment(Qt.AlignTop) descLbl.setFixedHeight(17) descLbl.setToolTip(param.desc) descLbl.setMinimumWidth(280) rowLayout.addWidget(descLbl) editBtn = QPushButton('Edit') editBtn.setFixedWidth(80) editBtn.setObjectName(param.name) editBtn.clicked.connect(self.editHandler) rowLayout.addWidget(editBtn) removeBtn = QPushButton('Remove') removeBtn.setFixedWidth(80) removeBtn.setObjectName(param.name) removeBtn.clicked.connect(self.removeHandler) rowLayout.addWidget(removeBtn) self.scrollVlayout.addLayout(rowLayout) UI = [nameLbl, typeLbl, valueLbl, descLbl, editBtn, removeBtn] self.paramUIs[param.name] = UI def newClicked(self): dialog = ParamPropDialog(params=self.params) dialog.paramAdded.connect(self.paramAddedHandler) dialog.exec_() def paramAddedHandler(self, params, name): self.params = params self.emitParams() self.addParam(self.params[name]) def removeHandler(self): removeId = self.sender().objectName() self.params.pop(removeId, None) self.emitParams() for uiItem in self.paramUIs[removeId]: uiItem.deleteLater() def editHandler(self): editID = self.sender().objectName() dialog = ParamPropDialog(params=self.params, id=editID) dialog.paramUpdated.connect(self.paramUpdatedHandler) dialog.exec_() def paramUpdatedHandler(self, params, id): self.params = params self.emitParams() param = self.params[id] UI = self.paramUIs[id] UI[0].setText(param.name) UI[0].setToolTip(param.name) UI[1].setText(param.type) UI[1].setToolTip(param.type) UI[2].setText(param.value) UI[2].setToolTip(param.value) UI[3].setText(param.desc) UI[3].setToolTip(param.desc) self.params.pop(id, None) self.params[param.name] = param self.paramUIs.pop(id, None) self.paramUIs[param.name] = UI def emitParams(self): params = [] for param in self.params.values(): params.append(param) self.paramsChanged.emit(params)
class CEditorContent ( QWidget ): def __init__ ( self, editor ): super ().__init__ () self.editor = editor self.toolBarAreaManager = CToolBarAreaManager ( editor ) self.mainLayout = QVBoxLayout () self.mainLayout.setContentsMargins ( 0, 0, 0, 0 ) self.mainLayout.setSpacing ( 0 ) self.contentLayout = QHBoxLayout () self.contentLayout.setContentsMargins ( 0, 0, 0, 0 ) self.contentLayout.setSpacing ( 0 ) self.content = QWidget () self.content.setSizePolicy ( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.editor.signalAdaptiveLayoutChanged.connect ( self.onAdaptiveLayoutChanged ) self.setLayout ( self.mainLayout ) def initialize ( self ): self.toolBarAreaManager.initialize () self.mainLayout.addWidget ( self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Top ) ) self.mainLayout.addLayout ( self.contentLayout ) self.mainLayout.addWidget ( self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Bottom ) ) self.contentLayout.addWidget ( self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Left ) ) self.contentLayout.addWidget ( self.content ) self.contentLayout.addWidget ( self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Right ) ) def getContent ( self ): return self.content def setContent ( self, content ): if isinstance ( content, QWidget ): self.content.setSizePolicy ( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.contentLayout.replaceWidget ( self.content, content ) self.content.setObjectName ( "CEditorContent" ) self.content.deleteLater () self.content = content elif isinstance ( content, QLayout ): contentLayout = content content = QWidget () content.setSizePolicy ( QSizePolicy.Expanding, QSizePolicy.Expanding ) content.setLayout ( contentLayout ) content.setObjectName ( "CEditorContent" ) contentLayout.setContentsMargins ( 0, 0, 0, 0 ) contentLayout.setSpacing ( 0 ) self.contentLayout.replaceWidget ( self.content, content ) self.content.deleteLater () self.content = content def customizeToolBar ( self ): # TODO: CToolBarCustomizeDialog return self.content def toggleToolBarLock ( self ): return self.toolBarAreaManager.toggleLock () def addExpandingSpacer ( self ): return self.toolBarAreaManager.addExpandingSpacer () def addFixedSpacer ( self ): return self.toolBarAreaManager.addFixedSpacer () def getMinimumSizeForOrientation ( self, orientation ) -> QSize: isDefaultOrientation = orientation == self.editor.GetDefaultOrientation () contentMinSize = self.content.layout ().minimumSize () topArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Top ) bottomArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Bottom ) leftArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Left ) rightArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Right ) result = QSize ( 0, 0 ) if isDefaultOrientation: # Take width from left and right areas if we're switching to the editor's default orientation result.setWidth ( result.width () + leftArea.getLargestItemMinimumSize ().width () ) result.setWidth ( result.width () + rightArea.getLargestItemMinimumSize ().width () ) # Use top and bottom area to calculate min height result.setHeight ( result.height () + leftArea.getLargestItemMinimumSize ().height () ) result.setHeight ( result.height () + rightArea.getLargestItemMinimumSize ().height () ) # Add content min size result += contentMinSize # Take the area layout size hints into account. Expand the current result with the toolbar area layout's size hint. # We use size hint rather than minimum size since toolbar area item's size policy is set to preferred. result = result.expandedTo ( QSize ( topArea.layout ().sizeHint ().height (), leftArea.layout ().sizeHint ().width () ) ) result = result.expandedTo ( QSize ( bottomArea.layout ().sizeHint ().height (), rightArea.layout ().sizeHint ().width () ) ) else: # If we're not switching to the default orientation, then we need to use the top and bottom toolbar areas' width # since these areas will be placed at the left and right of the editor content in this case of adaptive layouts result.setWidth ( result.width () + topArea.getLargestItemMinimumSize ().width () ) result.setWidth ( result.width () + bottomArea.getLargestItemMinimumSize ().width () ) # We must also flip where we get toolbar area min height from result.setHeight ( result.height () + leftArea.getLargestItemMinimumSize ().height () ) result.setHeight ( result.height () + rightArea.getLargestItemMinimumSize ().height () ) # Add flipped content min size result += QSize ( contentMinSize.height (), contentMinSize.width () ) result = result.expandedTo ( QSize ( leftArea.layout ().sizeHint ().height (), topArea.layout ().sizeHint ().width () ) ) result = result.expandedTo ( QSize ( rightArea.layout ().sizeHint ().height (), bottomArea.layout ().sizeHint ().width () ) ) return result def onAdaptiveLayoutChanged ( self ): isDefaultOrientation = self.editor.GetOrientation () == self.editor.GetDefaultOrientation () self.mainLayout.setDirection ( QBoxLayout.TopToBottom if isDefaultOrientation else QBoxLayout.LeftToRight ) self.contentLayout.setDirection ( QBoxLayout.LeftToRight if isDefaultOrientation else QBoxLayout.TopToBottom ) def paintEvent ( self, event ): styleOption = QStyleOption () styleOption.initFrom ( self ) painter = QPainter ( self ) self.style ().drawPrimitive ( QStyle.PE_Widget, styleOption, painter, self )
class TopicsTab(QWidget): def __init__(self, config): super(QWidget, self).__init__() self.config = config self.count = 0 self.topicRows = {} self.topicUIs = {} layout = QVBoxLayout() self.setLayout(layout) publishersBox = QGroupBox('Publishers') pubVLayout = QVBoxLayout() publishersBox.setLayout(pubVLayout) layout.addWidget(publishersBox) addPublisherBtn = QPushButton('Add Publisher') addPublisherBtn.setMaximumWidth(200) addPublisherBtn.clicked.connect(self.addPublisher) pubVLayout.addWidget(addPublisherBtn) pubRowLayout = QHBoxLayout() pubVLayout.addLayout(pubRowLayout) # publisher headers pubRowLayout.addSpacing(10) titleLblStyleSheet = 'QLabel { font-weight: bold;}' methodLbl = QLabel('Method Name') methodLbl.setStyleSheet(titleLblStyleSheet) methodLbl.setMinimumWidth(200) pubRowLayout.addWidget(methodLbl) topicLbl = QLabel('Topic') topicLbl.setStyleSheet(titleLblStyleSheet) topicLbl.setMinimumWidth(200) pubRowLayout.addWidget(topicLbl) typeLbl = QLabel('Type') typeLbl.setStyleSheet(titleLblStyleSheet) typeLbl.setMinimumWidth(200) pubRowLayout.addWidget(typeLbl) actionLbl = QLabel('Actions') actionLbl.setStyleSheet(titleLblStyleSheet) actionLbl.setMaximumWidth(200) actionLbl.setMinimumWidth(200) pubRowLayout.addWidget(actionLbl) pubRowLayout.addSpacing(10) pubScrollArea = QScrollArea() pubScrollArea.setWidgetResizable(True) # pubScrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) pubScrollArea.setStyleSheet('QScrollArea {border: 0px;}') self.pubScrollVlayout = QVBoxLayout() self.pubScrollVlayout.setDirection(QBoxLayout.TopToBottom) self.pubScrollVlayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet('QGroupBox {padding: 0px; margin: 0px;}') dummyBox.setLayout(self.pubScrollVlayout) pubScrollArea.setWidget(dummyBox) pubVLayout.addWidget(pubScrollArea) subscribersBox = QGroupBox('Subscribers') subsVLayout = QVBoxLayout() subscribersBox.setLayout(subsVLayout) layout.addWidget(subscribersBox) addSubscriberBtn = QPushButton('Add Subscriber') addSubscriberBtn.setMaximumWidth(200) addSubscriberBtn.clicked.connect(self.addSubscriber) subsVLayout.addWidget(addSubscriberBtn) subsRowLayout = QHBoxLayout() subsVLayout.addLayout(subsRowLayout) # publisher headers subsRowLayout.addSpacing(10) titleLblStyleSheet = 'QLabel {font-weight: bold;}' varLbl = QLabel('Variable Name') varLbl.setStyleSheet(titleLblStyleSheet) varLbl.setMinimumWidth(200) subsRowLayout.addWidget(varLbl) topicLbl = QLabel('Topic') topicLbl.setStyleSheet(titleLblStyleSheet) topicLbl.setMinimumWidth(200) subsRowLayout.addWidget(topicLbl) typeLbl = QLabel('Type') typeLbl.setStyleSheet(titleLblStyleSheet) typeLbl.setMinimumWidth(200) subsRowLayout.addWidget(typeLbl) actionLbl = QLabel('Actions') actionLbl.setStyleSheet(titleLblStyleSheet) actionLbl.setMaximumWidth(200) actionLbl.setMinimumWidth(200) subsRowLayout.addWidget(actionLbl) subsRowLayout.addSpacing(10) subsScrollArea = QScrollArea() subsScrollArea.setWidgetResizable(True) # subsScrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) subsScrollArea.setStyleSheet('QScrollArea {border: 0px;}') self.subsScrollVlayout = QVBoxLayout() self.subsScrollVlayout.setDirection(QBoxLayout.TopToBottom) self.subsScrollVlayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet('QGroupBox {padding: 0px; margin: 0px;}') dummyBox.setLayout(self.subsScrollVlayout) subsScrollArea.setWidget(dummyBox) subsVLayout.addWidget(subsScrollArea) # draw by the current config for topic in self.config.topics: self.addTopic(topic) def addPublisher(self): dialog = PubSubDialog(config=self.config, isPublisher=True) dialog.topicAdded.connect(self.topicAddedHandler) dialog.exec_() def addSubscriber(self): dialog = PubSubDialog(config=self.config, isPublisher=False) dialog.topicAdded.connect(self.topicAddedHandler) dialog.exec_() def addTopic(self, topic): rowLayout = QHBoxLayout() topicStyle = 'QLabel {border: 1px solid black;}' nameLbl = QLabel() nameLbl.setStyleSheet(topicStyle) nameLbl.setMinimumWidth(200) rowLayout.addWidget(nameLbl) topicLbl = QLabel(topic['name']) topicLbl.setStyleSheet(topicStyle) topicLbl.setMinimumWidth(200) rowLayout.addWidget(topicLbl) typeLbl = QLabel(topic['type']) typeLbl.setStyleSheet(topicStyle) typeLbl.setMinimumWidth(200) rowLayout.addWidget(typeLbl) editBtn = QPushButton('Edit') editBtn.setMinimumWidth(96) editBtn.setMaximumWidth(96) editBtn.setObjectName(str(topic['id'])) editBtn.clicked.connect(self.editHandler) rowLayout.addWidget(editBtn) removeBtn = QPushButton('Remove') removeBtn.setMinimumWidth(96) removeBtn.setMaximumWidth(96) removeBtn.setObjectName(str(topic['id'])) removeBtn.clicked.connect(self.removeHandler) rowLayout.addWidget(removeBtn) UIs = [nameLbl, topicLbl, typeLbl, editBtn, removeBtn, rowLayout] self.topicUIs[topic['id']] = UIs if topic['opType'] == RosConfig.PUBLISH: nameLbl.setText(topic['methodname']) self.pubScrollVlayout.addLayout(rowLayout) elif topic['opType'] == RosConfig.SUBSCRIBE: nameLbl.setText(topic['variablename']) self.subsScrollVlayout.addLayout(rowLayout) def topicAddedHandler(self): addedTopic = self.config.topics[len(self.config.topics) - 1] self.addTopic(addedTopic) def editHandler(self): editID = int(self.sender().objectName()) editTopic = None dialog = None for topic in self.config.topics: if topic['id'] == editID: editTopic = topic break if editTopic is not None: if editTopic['opType'] == RosConfig.PUBLISH: dialog = PubSubDialog(topic=editTopic, config=self.config, isPublisher=True) elif editTopic['opType'] == RosConfig.SUBSCRIBE: dialog = PubSubDialog(topic=editTopic, config=self.config, isPublisher=False) dialog.topicUpdated.connect(self.topicUpdatedHandler) dialog.exec_() def topicUpdatedHandler(self, updatedID): updatedTopic = None for topic in self.config.topics: if topic['id'] == updatedID: updatedTopic = topic break if updatedTopic is not None: UIs = self.topicUIs[updatedID] if updatedTopic['opType'] == RosConfig.PUBLISH: UIs[0].setText(updatedTopic['methodname']) elif updatedTopic['opType'] == RosConfig.SUBSCRIBE: UIs[0].setText(updatedTopic['variablename']) UIs[1].setText(updatedTopic['name']) UIs[2].setText(updatedTopic['type']) def removeHandler(self): removeID = int(self.sender().objectName()) removeItem = None for topic in self.config.topics: if topic['id'] == removeID: removeItem = topic break if removeItem is not None: self.config.topics.remove(removeItem) UIs = self.topicUIs[removeID] for uiItem in UIs: uiItem.deleteLater()
def addStates(self, layout, state, parentStateUIs, root=False): titleLblStyleSheet = 'QLabel:enabled{font-weight:bold; color:black;} ' \ 'QLabel:disabled{font-weight:bold; color:grey;}' childTitleLblStyleSheet = 'QLabel {font:italic; font-weight:bold;}' bulletLblStyleSheet = 'QLabel {font-size: 25px; font-weight:bold;}' stateUIs = [] if not root: rowLayout = QHBoxLayout() rowLayout.setAlignment(Qt.AlignLeft) rowLayout.addSpacing(5) checkBox = QCheckBox() checkBox.setFixedWidth(20) checkBox.setStyleSheet(bulletLblStyleSheet) checkBox.setChecked(True) checkBox.stateChanged.connect( partial(self.setStateEnabled, stateUIs)) if len(self.checkBoxList) < state.id: self.checkBoxList.extend([None] * (state.id - len(self.checkBoxList))) self.checkBoxList[state.id - 1] = checkBox if parentStateUIs is not None: parentStateUIs.append(checkBox) rowLayout.addWidget(checkBox) nameLbl = QLabel(state.getName()) nameLbl.setStyleSheet(titleLblStyleSheet) rowLayout.addWidget(nameLbl) stateUIs.append(nameLbl) if len(state.getNamespace().getParams()) > 0 or len( state.getChildren()) > 0: viewLbl = ClickableLabel(u'\u25BE') viewLbl.setMinimumWidth(20) rowLayout.addWidget(viewLbl) layout.addLayout(rowLayout) if len(state.getNamespace().getParams()) > 0 or len( state.getChildren()) > 0: rowLayout = QHBoxLayout() rowLayout.addSpacing(14) stateLayout = QVBoxLayout() stateLayout.setDirection(QBoxLayout.TopToBottom) stateLayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet( 'QGroupBox {padding: 0px; margin: 0px; border-left: 1px solid gray; ' 'border-top: 0px;}') dummyBox.setLayout(stateLayout) rowLayout.addWidget(dummyBox) viewLbl.clicked.connect(partial(self.toggleView, dummyBox)) layout.addLayout(rowLayout) else: stateLayout = layout if len(state.getNamespace().getParams()) > 0: self.displayStateParams(state, stateLayout, stateUIs, childTitleLblStyleSheet) if len(state.getChildren()) > 0: childStatesTitleLbl = QLabel('Child States:') childStatesTitleLbl.setStyleSheet(childTitleLblStyleSheet) stateLayout.addWidget(childStatesTitleLbl) stateUIs.append(childStatesTitleLbl) for child in state.getChildren(): if root: self.addStates(stateLayout, child, None) else: self.addStates(stateLayout, child, stateUIs) dummyBox = QGroupBox() dummyBox.setStyleSheet( 'QGroupBox {background-color: white; border: 0px;}') dummyBox.setMinimumWidth(100) dummyBox.setFixedHeight(0) stateLayout.addWidget(dummyBox)
class AddCropRotationView(QDialog): HEIGHT = 780 WIDTH = 430 stacked_widgets = None def __init__(self): super().__init__() self.model = AddCropRotationModel() self.controller = AddCropRotationController(self, self.model) self.v_layout = QVBoxLayout() self.start_year = QLineEdit() self.culture_combo_box = [ QComboBox(), QComboBox(), QComboBox(), QComboBox(), QComboBox() ] self.location_combo_box = [ QComboBox(), QComboBox(), QComboBox(), QComboBox(), QComboBox() ] self.amount_seed = [ QLineEdit(), QLineEdit(), QLineEdit(), QLineEdit(), QLineEdit() ] self.init_gui() self.init_main_layout() self.init_input_forms() def init_gui(self): self.setGeometry(0, 0, self.WIDTH, self.HEIGHT) self.setLayout(self.v_layout) self.setContentsMargins(0, 0, 0, 0) self.setStyleSheet("background-color: #424A52;" "color:#FFFFFF") def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setDirection(QVBoxLayout.TopToBottom) self.v_layout.setSpacing(0) self.v_layout.setContentsMargins(0, 0, 0, 0) def init_input_forms(self): self.init_start_year() strs_label = [ "Первый год", "Второй год", "Третий год", "Четвертый год", "Пятый год" ] for i in range(5): self.add_label(strs_label[i]) self.init_combo_box("Выберите культуру", self.culture_combo_box[i], self.model.get_cultures) self.init_combo_box("Выберите землю", self.location_combo_box[i], self.model.get_locations) self.add_amount_seed("Введите количество посева", self.amount_seed[i]) self.init_ok_button() def add_label(self, label_str): label = QLabel(label_str) label.setAlignment(Qt.AlignCenter) self.v_layout.addWidget(label) def add_amount_seed(self, label, line): widget = QWidget() h_layout = QHBoxLayout() label = QLabel(label) h_layout.addWidget(label) h_layout.addWidget(line) widget.setLayout(h_layout) line.setStyleSheet("background-color:#888888") line.setMaximumWidth(200) self.v_layout.addWidget(widget) def init_start_year(self): widget = QWidget() h_layout = QHBoxLayout() label = QLabel("Введите первый год пятилетки") h_layout.addWidget(label) h_layout.addWidget(self.start_year) self.start_year.setStyleSheet("background-color:#888888") self.start_year.setMaximumWidth(200) widget.setLayout(h_layout) self.v_layout.addWidget(widget) def init_combo_box(self, label_str, combo_box, items_fun): widget = QWidget() h_layout = QHBoxLayout() label = QLabel(label_str) h_layout.addWidget(label) cultures = items_fun() for (id, name) in cultures: combo_box.addItem(name, id) h_layout.addWidget(combo_box) widget.setLayout(h_layout) self.v_layout.addWidget(widget) def init_ok_button(self): icon = QIcon(os.getcwd() + "/icons/ok_icon.png") add_button = QPushButton(icon, "") add_button.setIconSize(QSize(40, 40)) add_button.setFlat(True) self.v_layout.addWidget(add_button, 0, Qt.AlignCenter) add_button.clicked.connect(partial(self.controller.add_to_db)) def close_window(self): self.close()
class mainWindow(): def __init__(self): self.scanNumber = 4 self.selectedDataset = 1 self.datasets = 0 self.lowerLimit = 100 self.upperLimit = 200 self.roiChanged = 0 #main figures DPI = 100 heightMM = 160.0 widthMM = 280.0 self.app = QtGui.QApplication([]) #self.window = QWidget() self.window = pg.GraphicsWindow(title="Thickness calculations") greyValue = 200 self.window.setBackground((greyValue, greyValue, greyValue)) self.fullPlot = pg.ImageView() self.fullPlot.fullRoi = self.fullPlot.getRoiPlot() self.roi = pg.ROI([200, 200], [100, 100]) self.roi.addScaleHandle([1, 1], [0, 0]) self.roi.addScaleHandle([1, 0], [0, 1]) self.roi.addScaleHandle([0, 1], [1, 0]) self.roi.addScaleHandle([0, 0], [1, 1]) def updateRoi(): if self.datasets: self.roiChanged = 1 self.guiData.rois[self.selectedDataset] = [ self.roi.pos()[1], self.roi.pos()[0], self.roi.size()[1], self.roi.size()[0] ] self.plotWindow(0) #print('roi changed') def updateEdges(): if self.datasets: self.findCurrentEdges() self.plotWindow(0) self.roi.sigRegionChanged.connect(updateRoi) self.roi.sigRegionChangeFinished.connect(updateEdges) self.fullPlot.addItem(self.roi) self.fullPlot.fullRoi = self.roi self.roiPlot = pg.ImageView() self.edgePlot = pg.ImageView() self.resultPlot = pg.PlotWidget() #self.Roi = pg.LineSegmentROI([10,20], [110,100], pen='r') #self.fullPlot.addItem(self.Roi) self.layout = QVBoxLayout() self.layout.setDirection(2) self.layout.addWidget( self.fullPlot) # plot goes on right side, spanning 3 rows self.layout.addWidget( self.roiPlot) # plot goes on right side, spanning 3 rows self.layout.addWidget( self.edgePlot) # plot goes on right side, spanning 3 rows self.layout.addWidget(self.resultPlot) #self.layout.addPlot() #self.layout.addWidget(self.resultPlot) #Buttons layout self.buttonGroupBox = QGroupBox('buttons') self.buttonLayout = QVBoxLayout() self.buttonLayout.setDirection(0) self.buttonGroupBox.setLayout(self.buttonLayout) self.leftButtonBox = QGroupBox() self.leftButtonLayout = QVBoxLayout() self.leftButtonLayout.setDirection(2) self.searchDataButton = QPushButton('Search Data') self.searchDataButton.clicked.connect(self.searchDataCallback) self.leftButtonLayout.addWidget(self.searchDataButton) self.loadAllDataButton = QPushButton('Load All Data') self.loadAllDataButton.clicked.connect(self.loadAllDataCallback) self.leftButtonLayout.addWidget(self.loadAllDataButton) self.leftButtonBox.setLayout(self.leftButtonLayout) self.rightButtonBox = QGroupBox() self.rightButtonLayout = QVBoxLayout() self.rightButtonLayout.setDirection(2) self.upButton = QPushButton('up') self.upButton.clicked.connect(self.raiseScanCallback) self.downButton = QPushButton('down') self.downButton.clicked.connect(self.lowerScanCallback) self.rightButtonLayout.addWidget(self.upButton) self.rightButtonLayout.addWidget(self.downButton) self.rightButtonBox.setLayout(self.rightButtonLayout) self.calculateThicknessButton = QPushButton('Calculate Thickness') self.calculateThicknessButton.clicked.connect(self.calculateThickness) self.rightButtonLayout.addWidget(self.calculateThicknessButton) self.calculateAllThicknessesButton = QPushButton( 'Calculate all Thicknessses') self.calculateAllThicknessesButton.clicked.connect( self.calculateAllThicknesses) self.rightButtonLayout.addWidget(self.calculateAllThicknessesButton) #self.upButton = QPushButton('up') #Jself.upButton.clicked.connect(self.raiseScanCallback) self.dataTextBox = QLineEdit() self.dataTextBox.setText(dataText) self.scanNumberTextBox = QLineEdit() self.scanNumberTextBox.setText(str(self.scanNumber)) self.datasetList = QTableWidget() self.datasetList.setColumnCount(3) self.datasetList.setHorizontalHeaderLabels(['Dataset', 'Loaded', '']) self.datasetList.setColumnWidth(0, 500) self.datasetList.itemSelectionChanged.connect(self.setDatasetCallback) self.datasetList.resizeRowsToContents() self.layout.addWidget(self.buttonGroupBox) self.buttonLayout.addWidget(self.leftButtonBox) self.buttonLayout.addWidget(self.rightButtonBox) self.layout.addWidget(self.dataTextBox) self.layout.addWidget(self.datasetList) #self.layout.addWidget(self.leftButtonBox) #QPushButton #layout.addWidget(plot, 0, 1, 1, 1) # plot goes on right side, spanning 3 rows self.window.setLayout(self.layout) self.window.show() #w.show() ## Start the Qt event loop #self.datasetList = tkinter.Listbox(self.top) #self.datasetList.grid(row=8, column=4, sticky = tkinter.W + tkinter.E)#, selectmode=EXTENDED) #def onSelection(event): # eventWidget = event.widget # self.selectedDataset = int(eventWidget.curselection()[0]) # print(self.selectedDataset) # #self.plotWindow() #self.datasetList.bind('<<ListboxSelect>>', print('selected')) #self.datasetList.bind('<<ListboxSelect>>', onSelection) ###close main Window ##invoke main window self.app.exec_() #self.top.mainloop() def browseCallback(self): newDataFile = '' if self.runtimeFolder: newDataFile = filedialog.askopenfilename( initialdir=self.runtimeFolder, title='Please select a file') else: newDataFile = filedialog.askopenfilename( initialdir='/raid/home/extern/rovedo/radial_recon/', title='Please select a data directory') self.runtimeFolder = os.path.dirname(newDataFile) self.saveString = self.runtimeFolder self.dataTextBox.delete("1.0", tkinter.END) self.dataTextBox.insert(tkinter.END, newDataFile) self.saveStringTextBox.delete("1.0", tkinter.END) self.saveStringTextBox.insert(tkinter.END, self.saveString) def loadSetCallback(self): self.dataString = self.dataTextBox.text().strip() print('dataset: ', self.selectedDataset) self.guiData = dataStruct.data(self.dataString) self.guiData.findDataDirs() self.guiData.initializeData() self.guiData.readSet(self.selectedDataset) self.datasetList.clear() for dataset in self.guiData.rootFolders: print(dataset) self.datasetList.insertRow(self.datasetList.rowCount()) #[os.path.basename(os.path.normpath(dataset))] self.plotWindow(1) def loadAllDataCallback(self): self.dataString = self.dataTextBox.text().strip() self.guiData = dataStruct.data(self.dataString) self.guiData.readAll() self.datasetList.clear() for dataset in self.guiData.rootFolders: print(dataset) #self.datasetList.insert(tkinter.END, os.path.basename(os.path.normpath(dataset))) self.datasetList.insertRow(self.datasetList.rowCount()) self.plotWindow(1) #pdb.set_trace() def searchDataCallback(self): self.dataString = self.dataTextBox.text().strip() self.guiData = dataStruct.data(self.dataString) self.guiData.findDataDirs() self.guiData.initializeData() #self.datasetList.clear() for row in np.arange(self.datasetList.rowCount() - 1, -1, -1): print('row:', row) self.datasetList.removeRow(row) for dataset in self.guiData.rootFolders: self.datasets += 1 row = self.datasetList.rowCount() self.datasetList.insertRow(row) self.datasetList.setItem( row, 0, QTableWidgetItem(os.path.basename(os.path.normpath(dataset)))) self.guiData.rois[self.selectedDataset] = [100, 50, 200, 200] self.plotWindow(1) def fftGuiData(self): self.guiData.fft(omitSamples=int( self.omitSamplesTextBox.get("1.0", tkinter.END).strip()), sumScans=self.sumDataVar.get(), zeroFill=int(self.zeroFillStringVar.get())) if self.sumDataVar.get(): self.plotWindow(1) else: self.plotWindow(1) def raiseScanCallback(self): if self.scanNumber < len(self.guiData.data[self.selectedDataset]) - 1: self.scanNumber += 1 #self.scanNumberString.set(self.scanNumber) self.setScanCallback() def lowerScanCallback(self): if self.scanNumber > 0: self.scanNumber -= 1 #self.scanNumberString.set(self.scanNumber) self.setScanCallback() def setDatasetCallback(self): if (self.datasetList.selectedItems()): self.selectedDataset = self.datasetList.selectedItems()[0].row() self.plotWindow(1) def setScanCallback(self): #newNumber = int(self.scanNumberTextBox.text().strip()) newNumber = self.scanNumber if newNumber < len(self.guiData.data[ self.selectedDataset]) - 1 and newNumber >= 0: self.scanNumber = newNumber self.plotWindow(1) def fitFunction(self, data, *parameters): #return np.zeros(data.shape[0]) #real fit function is returned by self.guiData.fit return parameters[0] / (np.pi * (data - parameters[1])**2 / parameters[2] + (parameters[2])) def setPhase(self, scanNumber): if self.sumDataVar.get(): self.guiData.summedPhase = float(self.phaseStringVar.get()) self.plotWindow(1) else: self.guiData.phase[scanNumber] = float(self.phaseStringVar.get()) self.plotWindow(1) def fitGuiData(self): frequency = float( self.frequencyParameter.get()) if self.frequencyParameter.get( ) else (int(self.maxFrequencyEntry.get()) + int(self.minFrequencyEntry.get())) / 2 width = float(self.widthParameter.get()) if self.widthParameter.get( ) else (int(self.maxFrequencyEntry.get()) - int(self.minFrequencyEntry.get())) / 100 #height = self.heightParameter.get() if self.heightParameter.get() else np.max(self.guiData.fftData[self.scanNumber]) if self.heightParameter.get(): height = float(self.heightParameter.get()) elif self.guiData.summedFftData.any(): height = np.real( np.max(self.guiData.summedFftData[self.guiData.getIndex( int(self.minFrequencyEntry.get()) ):self.guiData.getIndex(int(self.maxFrequencyEntry.get()))])) elif self.guiData.fftData.any(): height = np.real( np.max(self.guiData.fftData[ self.scanNumber, self.guiData.getIndex(int(self.minFrequencyEntry.get())): self.guiData.getIndex(int(self.maxFrequencyEntry.get()))])) else: height = 1 if self.sumDataVar.get(): self.guiData.summedFitParameters = [height, frequency, width] else: self.guiData.fitParameters[self.scanNumber] = [ height, frequency, width ] self.fitFunction, tempParameters = self.guiData.fit( int(self.minFrequencyEntry.get()), int(self.maxFrequencyEntry.get()), self.scanNumber, self.guiData.function, self.sumDataVar.get()) if self.sumDataVar.get(): self.guiData.summedFitParameters = tempParameters[0] else: self.guiData.fitParameters[self.scanNumber] = tempParameters[0] self.frequencyParameter.delete(0, tkinter.END) self.widthParameter.delete(0, tkinter.END) self.heightParameter.delete(0, tkinter.END) self.frequencyParameter.insert(0, tempParameters[0][1]) self.widthParameter.insert(0, tempParameters[0][2]) self.heightParameter.insert(0, tempParameters[0][0]) self.plotWindow(1) self.guiData.saveParameters() def plotExternal(self): if plt.fignum_exists(0): plt.clf() plt.figure(0, figsize=[6, 3]) plt.xlabel('f / MHz') plt.ylabel('signal / a.u.') if self.guiData: lowerIndex = self.guiData.getIndex( int(self.minFrequencyEntry.get())) upperIndex = self.guiData.getIndex( int(self.maxFrequencyEntry.get())) if self.sumDataVar.get(): self.guiData.fft(omitSamples=1000, sumScans=self.sumDataVar.get(), zeroFill=int(self.zeroFillStringVar.get())) plt.plot(self.guiData.frequencies[lowerIndex:upperIndex] / 1e6, 100 * np.real( cmath.exp(1j * self.guiData.summedPhase) * self.guiData.summedFftData[ -self.guiData.frequencies.size + lowerIndex:-self.guiData.frequencies.size + upperIndex]), label='1000 samples x 100') self.guiData.fft(omitSamples=500, sumScans=self.sumDataVar.get(), zeroFill=int(self.zeroFillStringVar.get())) plt.plot(self.guiData.frequencies[lowerIndex:upperIndex] / 1e6, np.real( cmath.exp(1j * self.guiData.summedPhase) * self.guiData.summedFftData[ -self.guiData.frequencies.size + lowerIndex:-self.guiData.frequencies.size + upperIndex]), label='500 samples') plt.legend() #plt.savefig('/home/philipp/Documents/thesis/figures/experiments/lowFieldSpectrometer/niNetworkAnalysis.pdf') plt.show() def plotWindow(self, plotMain): #try: if not self.guiData.data[self.selectedDataset][self.scanNumber].any(): self.guiData.readSingle(self.selectedDataset, self.scanNumber) print('plot: reading single') #self.fullPlot.clear() if (plotMain): self.fullPlot.setImage( self.guiData.data[self.selectedDataset][self.scanNumber][:, :, 1]) #self.fullPlot.plot(self.guiData.data[self.selectedDataset][self.scanNumber]) if self.guiData.rois[self.selectedDataset][2] + self.guiData.rois[ self.selectedDataset][3]: self.roiPlot.setImage( self.guiData.data[self.selectedDataset][self.scanNumber] [self.guiData.rois[self.selectedDataset][1]:self.guiData. rois[self.selectedDataset][1] + self.guiData.rois[self.selectedDataset][3], self.guiData.rois[self.selectedDataset][0]:self.guiData. rois[self.selectedDataset][0] + self.guiData.rois[self.selectedDataset][2], :][:, :, 0]) else: self.roiPlot.setImage( self.guiData.data[self.selectedDataset][self.scanNumber][:, :, 0]) if self.guiData.edgeData[self.selectedDataset][self.scanNumber].any(): self.edgePlot.setImage( self.guiData.edgeData[self.selectedDataset][self.scanNumber]) #self.subplotEdges.setImage(self.guiData.data[self.selectedDataset][self.scanNumber]) elif self.guiData.rois[self.selectedDataset][2] + self.guiData.rois[ self.selectedDataset][3]: self.findCurrentEdges() self.edgePlot.setImage( self.guiData.edgeData[self.selectedDataset][self.scanNumber]) #self.plotCanvas.draw() #image = pyqtgraph.imageview(self.guiData.edgeData[self.selectedDataset][self.scanNumber]) #image.show() #self.findCurrentEdges()for testing only #plt.imshow(self.guiData.data[self.selectedDataset][scanNumber]) #plt.show() #except AttributeError: # print("Please load a dataset") #except IndexError: # print("Please check parameters") #except ValueError: # print("wrong parameters entered") #self.minFrequencyEntry.focus_set() def defineRoi(self): subImageRoi = cv2.selectROI( 'ROI selection', self.guiData.data[self.selectedDataset][self.scanNumber]) self.guiData.rois[self.selectedDataset] = subImageRoi self.findCurrentEdges() cv2.destroyWindow('ROI selection') self.plotWindow(1) def findCurrentEdges(self): if self.guiData.rois[self.selectedDataset][2] + self.guiData.rois[ self.selectedDataset][3]: print('roi found') labelImage = self.guiData.data[self.selectedDataset][ self.scanNumber][self.guiData.rois[self.selectedDataset][1]: self.guiData.rois[self.selectedDataset][1] + self.guiData.rois[self.selectedDataset][3], self.guiData.rois[self.selectedDataset][0]: self.guiData.rois[self.selectedDataset][0] + self.guiData.rois[self.selectedDataset][2], :] edges = cv2.Canny( self.guiData.data[self.selectedDataset][self.scanNumber] [self.guiData.rois[self.selectedDataset][1]:self.guiData. rois[self.selectedDataset][1] + self.guiData.rois[self.selectedDataset][3], self.guiData.rois[self.selectedDataset][0]:self.guiData. rois[self.selectedDataset][0] + self.guiData.rois[self.selectedDataset][2], :], self.lowerLimit, self.upperLimit) edges, labelImage = cv2.connectedComponents(edges) self.guiData.edgeData[self.selectedDataset][ self.scanNumber] = labelImage #self.subplotEdges.imshow(self.guiData.edgeData[self.selectedDataset][self.scanNumber]) #self.plotCanvas.draw() else: print('Roi misdefinded or no roi found') def calculateThickness(self): if self.guiData.edgeData[self.selectedDataset][self.scanNumber].any(): readVectorY = np.arange(self.guiData.edgeData[self.selectedDataset] [self.scanNumber].shape[0]) readVectorX = np.arange(self.guiData.edgeData[self.selectedDataset] [self.scanNumber].shape[1]) edge1 = np.where( self.guiData.edgeData[self.selectedDataset][self.scanNumber] == 1, 1, 0) edge2 = np.where( self.guiData.edgeData[self.selectedDataset][self.scanNumber] == 2, 1, 0) n1 = np.sum(edge1) n2 = np.sum(edge2) x1 = np.sum(np.dot(edge1, readVectorX) / n1) y1 = np.sum(np.dot(np.transpose(edge1), readVectorY)) / n1 x2 = np.sum(np.dot(edge2, readVectorX) / n2) y2 = np.sum(np.dot(np.transpose(edge2), readVectorY)) / n2 #pdb.set_trace() print(np.abs(x2 - x1)) return (np.abs(x2 - x1)) else: return (np.nan) def findAllEdges(self): for scanNumber in np.arange( 4, len(self.guiData.data[self.selectedDataset])): self.scanNumber = scanNumber self.findCurrentEdges() #self.plotCanvas.draw() def calculateAllThicknesses(self): if self.roiChanged: self.findAllEdges() self.scanNumber = 0 for image in self.guiData.data[self.selectedDataset]: if image.any(): print('image found, calc...') self.guiData.thicknesses[self.selectedDataset][ self.scanNumber] = self.calculateThickness() else: print('image not found, laoding and calc...') self.guiData.readSingle(self.selectedDataset, self.scanNumber) self.findCurrentEdges() self.guiData.thicknesses[self.selectedDataset][ self.scanNumber] = self.calculateThickness() self.scanNumber += 1 self.scanNumber = 4 print('thicknesses calculated') print(self.guiData.thicknesses[self.selectedDataset]) #self.resultPlot.plot(np.arange(len(self.guiData.thicknesses[self.selectedDataset])), self.guiData.thicknesses[self.selectedDataset]) self.resultPlot.clear() self.resultPlot.plot( self.guiData.thicknesses[self.selectedDataset][4:-1]) #pdb.set_trace() def saveCallback(self): self.saveString = self.saveStringTextBox.get("1.0", tkinter.END).rstrip() print('saveString' + self.saveString) print(self.saveString + '/' + os.path.splitext(os.path.basename(self.dataString))[0] + '.pdf') self.figure.savefig( self.saveString + '/' + os.path.splitext(os.path.basename(self.dataString))[0] + '.pdf') def closeCallback(self): self.top.destroy()
class FileImportDialog(QDialog): fileStr = pyqtSignal('QString') def __init__(self): super(QDialog, self).__init__() self.setWindowTitle("Import behaviour from online library") self.setMinimumSize(700, 450) self.drawWindow() def drawWindow(self): VLayout = QVBoxLayout() rowLayout = QHBoxLayout() titleLblStyleSheet = 'QLabel {font-weight: bold;}' rowLayout.setAlignment(Qt.AlignLeft) rowLayout.addSpacing(10) titleLbl = QLabel('Select the behaviour to import:') titleLbl.setStyleSheet(titleLblStyleSheet) rowLayout.addWidget(titleLbl) VLayout.addLayout(rowLayout) scrollArea = QScrollArea() scrollArea.setWidgetResizable(True) scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scrollVlayout = QVBoxLayout() self.scrollVlayout.setDirection(QBoxLayout.TopToBottom) self.scrollVlayout.setAlignment(Qt.AlignTop) dummyBox = QGroupBox() dummyBox.setStyleSheet('QGroupBox {padding: 0px; margin: 0px;}') dummyBox.setLayout(self.scrollVlayout) scrollArea.setWidget(dummyBox) VLayout.addWidget(scrollArea) btnLayout = QHBoxLayout() btnLayout.setAlignment(Qt.AlignRight) cancelBtn = QPushButton("Cancel") cancelBtn.setFixedWidth(80) cancelBtn.clicked.connect(self.cancelClicked) btnLayout.addWidget(cancelBtn) VLayout.addLayout(btnLayout) self.statusLbl = QLabel('') VLayout.addWidget(self.statusLbl) self.setLayout(VLayout) self.show() self.setStatus("Fetching Catalogue . . .") self.getCatalogue = DownloadFile("Catalogue.xml") self.getCatalogue.fileStr.connect(self.displayCatalogue) self.getCatalogue.start() def displayCatalogue(self, catalogue): if catalogue == "": self.setStatus("Error occurred in fetching Catalogue") return self.setStatus("Displaying Catalogue . . .") self.doc = minidom.parseString(catalogue) behaviourList = self.doc.getElementsByTagName( 'Catalogue')[0].getElementsByTagName('behaviour') count = 0 for behElement in behaviourList: name = behElement.getAttribute('name') description = behElement.getElementsByTagName( 'description')[0].childNodes[0].nodeValue self.addBehaviour(count, name, description) count += 1 self.setStatus("") def addBehaviour(self, id, name, description): nameLblStyleSheet = 'QLabel {font-weight: bold;}' rowLayout = QHBoxLayout() behLayout = QVBoxLayout() nameLbl = ElidedLabel(name) nameLbl.setMinimumWidth(530) nameLbl.setToolTip(name) nameLbl.setStyleSheet(nameLblStyleSheet) behLayout.addWidget(nameLbl) descLbl = ElidedLabel(description) descLbl.setMinimumWidth(530) descLbl.setFixedHeight(17) descLbl.setAlignment(Qt.AlignTop) behLayout.addWidget(descLbl) rowLayout.addLayout(behLayout) selectBtn = QPushButton('Select') selectBtn.setObjectName(str(id)) selectBtn.setFixedWidth(100) selectBtn.clicked.connect(self.selected) rowLayout.addWidget(selectBtn) self.scrollVlayout.addLayout(rowLayout) def selected(self): id = int(self.sender().objectName()) behElement = self.doc.getElementsByTagName( 'Catalogue')[0].getElementsByTagName('behaviour')[id] name = behElement.getAttribute('name') description = behElement.getElementsByTagName( 'description')[0].childNodes[0].nodeValue behDialog = FilePropertiesDialog(name, description) if behDialog.exec_(): self.fileStr.emit(behDialog.fileStr) self.accept() def setStatus(self, text): self.statusLbl.setText(text) self.statusLbl.repaint() def cancelClicked(self): self.close()
class MyWindow(QWidget): def __init__(self): super().__init__() Fixed = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) #... self.updateButton = QPushButton('Set') self.updateButton.clicked.connect(self.OnUpdate) #Связываем сигнал со слотом; self.updateButton.setEnabled(False) #... self.insertButton = QPushButton('Add') self.insertButton.clicked.connect(self.OnInsert) #... self.deleteButton = QPushButton('Del') self.deleteButton.clicked.connect(self.OnDelete) #... self.spinRowID = QSpinBox() self.spinRowID.lineEdit().setReadOnly(True) self.spinRowID.valueChanged.connect(self.OnRowChanged) self.spinRowID.setSizePolicy(Fixed) #... self.editName = QLineEdit() #... self.vbox = QVBoxLayout() self.is_female = QRadioButton('FEMALE'); self.is_male = QRadioButton('MALE'); self.is_male.click() self.vbox.addWidget(self.is_female) self.vbox.addWidget(self.is_male) self.vbox.setDirection(QVBoxLayout.LeftToRight) #Задаем направление компоновки; self.chckSex = QGroupBox() self.chckSex.setLayout(self.vbox) #... self.listAge = QComboBox() self.listAge.setSizePolicy(Fixed) #Устанавливаем фиксированный размер виджета; for i in range(16, 31): self.listAge.addItem(str(i), i) #... self.editCity = QLineEdit() #... self.view = View(self) self.view.clicked.connect(self.OnViewClicked) self.view.sortByColumn(0, Qt.AscendingOrder) #Используем компоновщики для позиционирования виджетов: self.lay2 = QGridLayout() self.lay2.addWidget(self.updateButton, 0, 0) self.lay2.addWidget(self.insertButton, 1, 0) self.lay2.addWidget(self.deleteButton, 2, 0) self.lay2.addWidget(self.spinRowID, 0, 1) self.lay2.addWidget(self.editName, 0, 2) self.lay2.addWidget(self.listAge, 0, 3) self.lay2.addWidget(self.chckSex, 0, 4) self.lay2.addWidget(self.editCity, 0, 5) #... self.lay1 = QGridLayout(self) self.lay1.addLayout(self.lay2, 0, 0) self.lay1.addWidget(self.view, 1, 0) self.setGeometry(0, 0, 800, 500) self.setWindowTitle('Test Application') self.show() def update(self): temp = self.view.getDataByID(self.spinRowID.value()) if not temp: self.updateButton.setEnabled(False) return self.updateButton.setEnabled(True) self.editName.setText(temp[1]) if temp[2] == 'F': self.is_female.click() else: self.is_male.click() self.listAge.setCurrentText(str(temp[3])) self.editCity.setText(temp[4]) self.repaint() def record(self): rec = [self.editName.text()] rec.append(1 if self.is_male.isChecked() else 0) rec.append(int(self.listAge.currentText())) rec.append(self.editCity.text()) return tuple(rec) def OnViewClicked(self, index): temp = self.view.getRowData(index.row()) self.spinRowID.setValue(temp[0]) def OnRowChanged(self, rowid): self.update() def OnUpdate(self): rec = self.record() self.view.updateRow(self.spinRowID.value(), rec) self.update() def OnInsert(self): rec = self.record() self.view.insertRow(rec) self.update() def OnDelete(self): self.view.removeRow(self.spinRowID.value()) self.update()
class SubwindowConnections(QWidget): """Show connections settings sub window.""" def createWindow(self, mainWindow): """Create window.""" try: parent = None super().__init__(parent) # self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowIcon( QIcon(hwctool.settings.getResFile('twitch.png'))) self.setWindowModality(Qt.ApplicationModal) self.mainWindow = mainWindow self.passEvent = False self.controller = mainWindow.controller self.__dataChanged = False self.createButtonGroup() self.createTabs() mainLayout = QVBoxLayout() mainLayout.addWidget(self.tabs) mainLayout.addLayout(self.buttonGroup) self.setLayout(mainLayout) self.resize(QSize(mainWindow.size().width() * 0.8, self.sizeHint().height())) relativeChange = QPoint(mainWindow.size().width() / 2, mainWindow.size().height() / 3) -\ QPoint(self.size().width() / 2, self.size().height() / 3) self.move(mainWindow.pos() + relativeChange) self.setWindowTitle(_("Twitch")) except Exception as e: module_logger.exception("message") def createTabs(self): """Create tabs.""" self.tabs = QTabWidget() self.createFormGroupTwitch() self.createFormGroupNightbot() # Add tabs self.tabs.addTab(self.formGroupTwitch, QIcon( hwctool.settings.getResFile('twitch.png')), _("Twitch")) # self.tabs.addTab(self.formGroupNightbot, QIcon( # hwctool.settings.getResFile('nightbot.ico')), _("Nightbot")) def createFormGroupTwitch(self): """Create forms for twitch.""" self.formGroupTwitch = QWidget() layout = QFormLayout() self.twitchChannel = MonitoredLineEdit() self.twitchChannel.textModified.connect(self.changed) self.twitchChannel.setText( hwctool.settings.config.parser.get("Twitch", "channel")) self.twitchChannel.setAlignment(Qt.AlignCenter) self.twitchChannel.setPlaceholderText( _("Name of the Twitch channel that should be updated")) self.twitchChannel.setToolTip( _('The connected twitch user needs to have editor' ' rights for this channel.')) layout.addRow(QLabel( "Twitch-Channel:"), self.twitchChannel) container = QHBoxLayout() self.twitchToken = MonitoredLineEdit() self.twitchToken.textModified.connect(self.changed) self.twitchToken.setText( hwctool.settings.config.parser.get("Twitch", "oauth")) self.twitchToken.setAlignment(Qt.AlignCenter) self.twitchToken.setPlaceholderText( _("Press 'Get' to generate a token")) self.twitchToken.setEchoMode(QLineEdit.Password) self.twitchToken.setToolTip(_("Press 'Get' to generate a new token.")) container.addWidget(self.twitchToken) self.pb_getTwitch = QPushButton(_('Get')) self.pb_getTwitch.setFixedWidth(100) self.pb_getTwitch.clicked.connect( lambda: self.controller.authThread.requestToken('twitch')) container.addWidget(self.pb_getTwitch) layout.addRow(QLabel(_("Access-Token:")), container) container = QHBoxLayout() self.twitchTemplate = MonitoredLineEdit() self.twitchTemplate.textModified.connect(self.changed) self.twitchTemplate.setText( hwctool.settings.config.parser.get("Twitch", "title_template")) self.twitchTemplate.setAlignment(Qt.AlignCenter) self.twitchTemplate.setPlaceholderText("(League) – (Team1) vs (Team2)") self.twitchTemplate.setToolTip( _('Available placeholders:') + " " + ', '.join(self.controller.placeholders.available())) completer = Completer( self.controller.placeholders.available(), self.twitchTemplate) self.twitchTemplate.setCompleter(completer) container.addWidget(self.twitchTemplate) button = QPushButton(_('Test')) button.setFixedWidth(100) button.clicked.connect( lambda: self.testPlaceholder(self.twitchTemplate.text())) container.addWidget(button) label = QLabel(_("Title Template:")) label.setFixedWidth(100) layout.addRow(label, container) container = QVBoxLayout() self.cb_set_game = QCheckBox(_("Set twitch game to the selected game")) self.cb_set_game.setChecked( hwctool.settings.config.parser.getboolean("Twitch", "set_game")) self.cb_set_game.stateChanged.connect(self.changed) container.addWidget(self.cb_set_game) self.cb_set_community = QCheckBox( _("Add to Community 'StarCraft Casting Tool'")) self.cb_set_community.setChecked( hwctool.settings.config.parser.getboolean( "Twitch", "set_community")) self.cb_set_community.stateChanged.connect(self.changed) # container.addWidget(self.cb_set_community) label = QLabel(_("Options:") + " ") label.setMinimumWidth(120) layout.addRow(label, container) layout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupTwitch.setLayout(layout) def createFormGroupNightbot(self): """Create forms for nightbot.""" self.formGroupNightbot = QWidget() mainLayout = QVBoxLayout() tokenBox = QGroupBox("Access-Token") container = QHBoxLayout() self.nightbotToken = MonitoredLineEdit() self.nightbotToken.textModified.connect(self.changed) self.nightbotToken.setText( hwctool.settings.config.parser.get("Nightbot", "token")) self.nightbotToken.setAlignment(Qt.AlignCenter) self.nightbotToken.setEchoMode(QLineEdit.Password) self.nightbotToken.setPlaceholderText( _("Press 'Get' to generate a token")) self.nightbotToken.setToolTip( _("Press 'Get' to generate a token.")) container.addWidget(self.nightbotToken) self.pb_getNightbot = QPushButton(_('Get')) self.pb_getNightbot.clicked.connect( lambda: self.controller.authThread.requestToken('nightbot')) self.pb_getNightbot.setFixedWidth(100) # self.pb_getNightbot.setEnabled(False) container.addWidget(self.pb_getNightbot) tokenBox.setLayout(container) mainLayout.addWidget(tokenBox, 0) # scroll area widget contents - layout self.scrollLayout = QVBoxLayout() self.scrollLayout.setDirection(QBoxLayout.BottomToTop) self.scrollLayout.addStretch(0) buttonLayout = QHBoxLayout() buttonLayout.addStretch(0) self.scrollLayout.addLayout(buttonLayout) # scroll area widget contents self.scrollWidget = QWidget() self.scrollWidget.setLayout(self.scrollLayout) # scroll area self.scrollArea = QScrollArea() self.scrollArea.setWidgetResizable(True) self.scrollArea.setWidget(self.scrollWidget) self.scrollArea.setFixedHeight(180) mainLayout.addWidget(self.scrollArea, 1) layout = QHBoxLayout() layout.addWidget(QLabel("")) addButton = QPushButton(_('Add Command')) addButton.clicked.connect(lambda: self.addCommand()) layout.addWidget(addButton) mainLayout.addLayout(layout, 0) data = hwctool.settings.nightbot_commands if len(data) == 0: self.addCommand() else: for cmd, msg in data.items(): self.addCommand(cmd, msg) mainLayout.addItem(QSpacerItem( 0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)) self.formGroupNightbot.setLayout(mainLayout) def addCommand(self, cmd="", msg=""): if msg != "__DELETE__": dropbox = CommandDropBox(self.controller, cmd=cmd, msg=msg) dropbox.connect(self.changed) self.scrollLayout.insertWidget(1, dropbox) else: CommandDropBox.addDeletedCommand(cmd) def createButtonGroup(self): """Create buttons.""" try: layout = QHBoxLayout() layout.addWidget(QLabel("")) buttonCancel = QPushButton(_('Cancel')) buttonCancel.clicked.connect(self.closeWindow) layout.addWidget(buttonCancel) buttonSave = QPushButton(_('&Save && Close')) buttonSave.setToolTip(_("Shortcut: {}").format("Ctrl+S")) self.shortcut = QShortcut(QKeySequence("Ctrl+S"), self) self.shortcut.setAutoRepeat(False) self.shortcut.activated.connect(self.saveCloseWindow) buttonSave.clicked.connect(self.saveCloseWindow) layout.addWidget(buttonSave) self.buttonGroup = layout except Exception as e: module_logger.exception("message") def changed(self, *values): """Handle changed data.""" self.__dataChanged = True def saveData(self): """Save the data to config.""" if(self.__dataChanged): hwctool.settings.config.parser.set( "Twitch", "channel", self.twitchChannel.text().strip()) hwctool.settings.config.parser.set( "Twitch", "oauth", self.twitchToken.text().strip()) hwctool.settings.config.parser.set( "Twitch", "title_template", self.twitchTemplate.text().strip()) hwctool.settings.config.parser.set( "Twitch", "set_game", str(self.cb_set_game.isChecked())) # hwctool.settings.config.parser.set( # "Twitch", # "set_community", # str(self.cb_set_community.isChecked())) hwctool.settings.config.parser.set( "Nightbot", "token", self.nightbotToken.text().strip()) self.__dataChanged = False self.controller.refreshButtonStatus() hwctool.settings.nightbot_commands = CommandDropBox.getData() def saveCloseWindow(self): """Save and close window.""" self.saveData() self.closeWindow() def closeWindow(self): """Close window without save.""" self.passEvent = True self.close() def closeEvent(self, event): """Handle close event.""" try: if(not self.__dataChanged): CommandDropBox.clean() event.accept() return if(not self.passEvent): if(self.isMinimized()): self.showNormal() buttonReply = QMessageBox.question( self, _('Save data?'), _("Do you want to save the data?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if buttonReply == QMessageBox.Yes: self.saveData() CommandDropBox.clean() event.accept() except Exception as e: module_logger.exception("message") def testPlaceholder(self, string): """Test placeholders.""" string = self.controller.placeholders.replace(string) QMessageBox.information(self, _("Output:"), string)
class ShopView(QWidget): HEIGHT = 1080 WIDTH = 1600 stacked_widgets = None session_id = None def __init__(self): super().__init__() self.model = ShopModel() self.session_id = uuid.uuid1() self.controller = ShopController(self, self.model, self.session_id) self.grid_layout = None self.v_layout = QVBoxLayout() self.init_header() self.init_gui() self.init_main_layout() self.init_grid(0) def init_gui(self): self.setGeometry(0, 0, self.WIDTH, self.HEIGHT) self.setStyleSheet("background-color:#F2F2F2") self.setLayout(self.v_layout) def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setContentsMargins(0, 0, 0, 0) self.v_layout.setDirection(QVBoxLayout.TopToBottom) def init_header(self): qwidget = QWidget() qwidget.setFixedSize(QSize(self.WIDTH, 60)) qwidget.setStyleSheet("background-color:#424A52;") horizontal_layout = QHBoxLayout() horizontal_layout.setAlignment(Qt.AlignLeft) qwidget.setLayout(horizontal_layout) self.init_wheat(horizontal_layout) self.init_cucumber(horizontal_layout) self.init_cart(horizontal_layout) self.v_layout.addWidget(qwidget) def init_wheat(self, horizontal_layout): wheat_icon = QIcon(os.getcwd() + "/icons/wheat.png") wheat_button = QPushButton(wheat_icon, "Зерновые") wheat_button.setIconSize(QSize(40, 40)) wheat_button.setFlat(True) wheat_button.setStyleSheet("margin-left:100px;" "color:#FFFFFF;" "font-size:22px") wheat_button.clicked.connect(partial(self.controller.change_layout, 0)) horizontal_layout.addWidget(wheat_button) def init_cucumber(self, horizontal_layout): cucumber_icon = QIcon(os.getcwd() + "/icons/cucumber.png") cucumber_button = QPushButton(cucumber_icon, "Овощи", self) cucumber_button.setIconSize(QSize(30, 30)) cucumber_button.setFlat(True) cucumber_button.setStyleSheet("color:#FFFFFF;" "font-size:22px") cucumber_button.clicked.connect( partial(self.controller.change_layout, 1)) horizontal_layout.addWidget(cucumber_button) def init_cart(self, horizontal_layout): cart_icon = QIcon(os.getcwd() + "/icons/cart.png") cart_button = QPushButton(cart_icon, "") cart_button.setIconSize(QSize(40, 40)) cart_button.setFlat(True) cart_button.setStyleSheet("margin-left:1000px") cart_button.clicked.connect(partial(self.controller.change_layout, 3)) horizontal_layout.addWidget(cart_button) def init_grid(self, type): qwidget = QWidget() qwidget.setStyleSheet("margin-left:20px") products_list = self.model.get_products(type, self.session_id) grid_layout = QGridLayout() qwidget.setLayout(grid_layout) for i in range(len(products_list)): grid_layout.addWidget(products_list[i], i // 4, i % 4) self.grid_layout = grid_layout self.v_layout.addWidget(qwidget, 0) def update_view_grid(self, type): self.clear_layout() self.init_header() self.init_grid(type) def update_view_shop(self): self.clear_layout() self.init_header() self.init_amount_goods_label() self.init_goods() self.init_sum() def update_view_shop_nothing(self): self.clear_layout() self.init_header() self.show_nothing() def show_nothing(self): label = QLabel("В вашей корзине ничего нет") label.setStyleSheet("font-size:24px") self.v_layout.addWidget(label, 0, Qt.AlignCenter | Qt.AlignTop) def init_amount_goods_label(self): label = QLabel("Количество товаров %s" % str(len(self.model.get_goods(self.session_id)))) label.setStyleSheet("font-size: 24px") self.v_layout.addWidget(label, 0, Qt.AlignCenter | Qt.AlignTop) def init_sum(self): widget = QWidget() h_layout = QHBoxLayout() h_layout.setAlignment(Qt.AlignCenter) label = QLabel("Сумма %s рублей" % self.model.get_sum(self.session_id)) label.setStyleSheet("font-size:24px") h_layout.addWidget(label, 0, Qt.AlignCenter) h_layout.setContentsMargins(0, 0, 0, 0) self.init_ok_button(h_layout) widget.setLayout(h_layout) self.v_layout.addWidget(widget, 24, Qt.AlignTop | Qt.AlignCenter) def init_ok_button(self, horizontal_layout): cart_icon = QIcon(os.getcwd() + "/icons/ok_black.png") ok_button = QPushButton(cart_icon, "") ok_button.setIconSize(QSize(30, 30)) ok_button.setFlat(True) ok_button.setStyleSheet("margin-left:300px;" "border:0px;" "margin-left:0px;") ok_button.clicked.connect( partial(self.controller.show_deal_treaty, self.session_id)) horizontal_layout.addWidget(ok_button, 0, Qt.AlignLeft) def init_goods(self): goods = self.model.get_goods(self.session_id) widget = QWidget() widget.setStyleSheet("border: 1px outset black") v_layout = QVBoxLayout() for (id, name, amount, price) in goods: row_widget = QWidget() row_widget.setStyleSheet("background-color: #424a52;" "color:#FFFFFF;" "text-align:center;") h_layout = QHBoxLayout() name = QLabel(name) name.setStyleSheet("border:0 px;") amount = QLabel("Количество %d кг" % amount) amount.setStyleSheet("border: 0 px;") price = QLabel("Цена %d руб" % price) price.setStyleSheet("border:0 px;") h_layout.addWidget(name) h_layout.addWidget(amount) h_layout.addWidget(price) self.init_delete_button(h_layout, id) row_widget.setLayout(h_layout) v_layout.setSpacing(0) v_layout.setContentsMargins(0, 0, 0, 0) v_layout.addWidget(row_widget, 0, Qt.AlignTop) widget.setLayout(v_layout) self.v_layout.addWidget(widget, 2, Qt.AlignTop) def init_delete_button(self, horizontal_layout, id): cart_icon = QIcon(os.getcwd() + "/icons/delete.png") delete_button = QPushButton(cart_icon, "") delete_button.setIconSize(QSize(30, 30)) delete_button.setFlat(True) delete_button.setStyleSheet("margin-left:300px;" "border:0px;") delete_button.clicked.connect( partial(self.controller.delete_from_cart, id)) horizontal_layout.addWidget(delete_button) def clear_layout(self): for i in reversed(range(self.v_layout.count())): self.v_layout.itemAt(i).widget().setParent(None)
class RigView(QWidget): HEIGHT = 1080 WIDTH = 1600 def __init__(self): super().__init__() self.model = RigModel() self.controller = RigController(self, self.model) self.v_layout = QVBoxLayout() self.init_gui() self.init_main_layout() self.show_labels() self.controller.show_rigs() self.init_add_button() self.show() def init_gui(self): self.setGeometry(0, 0, self.WIDTH, self.HEIGHT) self.setLayout(self.v_layout) self.setContentsMargins(0, 0, 0, 0) def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setDirection(QVBoxLayout.TopToBottom) self.v_layout.setSpacing(0) self.v_layout.setContentsMargins(0, 0, 0, 0) def show_rigs(self): for view in self.model.get_rigs(): self.v_layout.addWidget(view) def show_labels(self): widget = QWidget() layout = QHBoxLayout() self.add_label(layout, "Время работы") self.add_label(layout, "Имя") self.add_label(layout, "Произведена") self.add_label(layout, "Дата ремонта") self.add_label(layout, "Дата починки") self.add_label(layout, "Длина участка") self.add_label(layout, "Ширина участка") widget.setLayout(layout) widget.setStyleSheet("background-color: #424A52;" "color: #FFFFFF;" "text-align:center;") self.v_layout.addWidget(widget) def show_nothing(self): label = QLabel("Ничего не найдено") label.setAlignment(Qt.AlignCenter) label.setStyleSheet("font-size:20px;") self.v_layout.addWidget(label) def add_label(self, layout, str): label = QLabel(str) label.setAlignment(Qt.AlignCenter) layout.addWidget(label) def init_add_button(self): icon = QIcon(os.getcwd() + "/icons/add_icon.png") add_button = QPushButton(icon, "") add_button.setIconSize(QSize(40, 40)) add_button.setFlat(True) self.v_layout.addWidget(add_button, 0, Qt.AlignCenter) add_button.clicked.connect(partial(self.controller.show_add_rig_view)) def update_view(self): self.clear_layout() self.show_labels() self.controller.show_rigs() self.init_add_button() self.update() def clear_layout(self): for i in reversed(range(self.v_layout.count())): self.v_layout.itemAt(i).widget().setParent(None)
class AddRigView(QDialog): HEIGHT = 190 WIDTH = 430 stacked_widgets = None def __init__(self, update): super().__init__() self.update = update self.model = AddRigModel() self.controller = AddRigController(self, self.model) self.v_layout = QVBoxLayout() self.technique_combo_box = QComboBox() self.location_combo_box = QComboBox() self.time_line = QLineEdit() self.init_gui() self.init_main_layout() self.init_inputs_forms() def init_gui(self): self.setGeometry(0, 0, self.WIDTH, self.HEIGHT) self.setLayout(self.v_layout) self.setContentsMargins(0, 0, 0, 0) self.setStyleSheet("background-color: #424A52;" "color:#FFFFFF") def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setDirection(QVBoxLayout.TopToBottom) self.v_layout.setSpacing(0) self.v_layout.setContentsMargins(0, 0, 0, 0) def init_inputs_forms(self): self.add_technique_combo_box() self.add_location_combo_box() self.init_input_time_work() self.init_ok_button() def add_technique_combo_box(self): widget = QWidget() h_layout = QHBoxLayout() label = QLabel("Техника") h_layout.addWidget(label) techniques = self.model.get_technique() for (id, text) in techniques: self.technique_combo_box.addItem(text, id) h_layout.addWidget(self.technique_combo_box) widget.setLayout(h_layout) self.v_layout.addWidget(widget) def add_location_combo_box(self): widget = QWidget() h_layout = QHBoxLayout() label = QLabel("Участок") h_layout.addWidget(label) locations = self.model.get_locations() for (id, text) in locations: self.location_combo_box.addItem(text, id) h_layout.addWidget(self.location_combo_box) widget.setLayout(h_layout) self.v_layout.addWidget(widget) def init_input_time_work(self): widget = QWidget() h_layout = QHBoxLayout() label = QLabel("Время работы") h_layout.addWidget(label) self.time_line.setMaximumWidth(200) self.time_line.setStyleSheet("background-color:#888888") h_layout.addWidget(self.time_line) widget.setLayout(h_layout) self.v_layout.addWidget(widget) def init_ok_button(self): icon = QIcon(os.getcwd() + "/icons/ok_icon.png") add_button = QPushButton(icon, "") add_button.setIconSize(QSize(40, 40)) add_button.setFlat(True) self.v_layout.addWidget(add_button, 0, Qt.AlignCenter) add_button.clicked.connect(partial(self.controller.add_to_db)) def close_window(self): self.update() self.close()
class PlanCropRotationView(QWidget): WIDTH = 1600 HEIGHT = 1080 def __init__(self): super().__init__() self.v_layout = QVBoxLayout() self.q_line_edit = QLineEdit() self.model = PlanCropRotationModel() self.controller = PlanCropRotationController(self, self.model) self.init_gui() self.init_main_layout() self.init_input_form() self.init_add_button() def init_main_layout(self): self.v_layout.setAlignment(Qt.AlignTop) self.v_layout.setContentsMargins(0, 0, 0, 0) self.v_layout.setDirection(QVBoxLayout.TopToBottom) self.v_layout.setSpacing(0) def init_gui(self): self.setGeometry(0, 0, self.WIDTH, self.HEIGHT) self.setLayout(self.v_layout) def init_input_form(self): label = QLabel() label.setText("Введите год") label.setStyleSheet("font-size:20px") self.v_layout.addWidget(label, 0, Qt.AlignCenter) self.q_line_edit.setMaximumWidth(100) self.q_line_edit.setStyleSheet("text-align:center;") self.q_line_edit.keyReleaseEvent = self.controller.key_input_form_event self.v_layout.addWidget(self.q_line_edit, 0, Qt.AlignCenter) def show_labels(self): result = QWidget() result.setStyleSheet("background-color: #424a52;" "color:#FFFFFF;" "text-align:center;") up_layout = QHBoxLayout() self.add_label(up_layout, "Длина") self.add_label(up_layout, "Ширина") self.add_label(up_layout, "Название посева") self.add_label(up_layout, "Засеяно") self.add_label(up_layout, "Собрано") result.setLayout(up_layout) self.v_layout.addWidget(result) def add_label(self, layout, name): label = QLabel(name) label.setAlignment(Qt.AlignCenter) layout.addWidget(label) def show_crop_rotation(self): crop_rotation_data = self.model.get_crop_rotation() for crop_view in crop_rotation_data: self.v_layout.addWidget(crop_view) def clear(self): for i in reversed(range(self.v_layout.count())): self.v_layout.itemAt(i).widget().setParent(None) def show_nothing(self): label = QLabel("Ничего не найдено") label.setAlignment(Qt.AlignCenter) label.setStyleSheet("font-size:20px;") self.v_layout.addWidget(label) def init_add_button(self): icon = QIcon(os.getcwd() + "/icons/add_icon.png") add_button = QPushButton(icon, "") add_button.setIconSize(QSize(40, 40)) add_button.setFlat(True) self.v_layout.addWidget(add_button, 0, Qt.AlignCenter) add_button.clicked.connect( partial(self.controller.show_add_crop_rotation_view))