def __init__(self, parent, xml): super().__init__(parent) self.setWindowTitle("Information") tree = QTreeWidget() tree.setColumnCount(2) tree.setHeaderLabels(["Name", "Value"]) tree.setColumnWidth(0, 200) tree.setColumnWidth(1, 350) for stream in xml: header = xml[stream][2] header.tag = "Header" footer = xml[stream][6] footer.tag = "Footer" root = et.Element(f"Stream {stream}") root.extend([header, footer]) populate_tree(tree, root) tree.expandAll() vbox = QVBoxLayout(self) vbox.addWidget(tree) buttonbox = QDialogButtonBox(QDialogButtonBox.Ok) vbox.addWidget(buttonbox) buttonbox.accepted.connect(self.accept) self.resize(650, 550)
class Editor(QDialog): """Basic scene editor.""" def __init__(self, parent: MainWindow, renderers: List[Renderer]) -> None: """Initialize the Editor.""" super().__init__(parent=parent) self.renderers = renderers self.tree_widget = QTreeWidget() self.tree_widget.setHeaderHidden(True) self.stacked_widget = QStackedWidget() self.layout = QHBoxLayout() self.layout.addWidget(self.tree_widget) self.layout.addWidget(self.stacked_widget) def _selection_callback() -> None: for item in self.tree_widget.selectedItems(): widget_idx = item.data(0, Qt.ItemDataRole.UserRole) self.stacked_widget.setCurrentIndex(widget_idx) self.tree_widget.itemSelectionChanged.connect(_selection_callback) self.setLayout(self.layout) self.setWindowTitle("Editor") self.setModal(True) self.update() def update(self) -> None: """Update the internal widget list.""" self.tree_widget.clear() for idx, renderer in enumerate(self.renderers): actors = renderer._actors # pylint: disable=protected-access widget_idx = self.stacked_widget.addWidget( _get_renderer_widget(renderer)) top_item = QTreeWidgetItem(self.tree_widget, ["Renderer {}".format(idx)]) top_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx) self.tree_widget.addTopLevelItem(top_item) for name, actor in actors.items(): if actor is not None: widget_idx = self.stacked_widget.addWidget( _get_actor_widget(actor)) child_item = QTreeWidgetItem(top_item, [name]) child_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx) top_item.addChild(child_item) self.tree_widget.expandAll() def toggle(self) -> None: """Toggle the editor visibility.""" self.update() if self.isVisible(): self.hide() else: self.show()
def __init__(self, parent: QWidget, filename: str, torrent_info: TorrentInfo, control_thread: 'ControlManagerThread'): super().__init__(parent) self._torrent_info = torrent_info download_info = torrent_info.download_info self._control_thread = control_thread self._control = control_thread.control vbox = QVBoxLayout(self) self._download_dir = get_directory(self._control.last_download_dir) vbox.addWidget(QLabel('Download directory:')) vbox.addWidget(self._get_directory_browse_widget()) #tracker lists.. vbox.addWidget(QLabel('Announce URLs:')) url_tree = QTreeWidget() url_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) url_tree.header().close() vbox.addWidget(url_tree) for i, tier in enumerate(torrent_info.announce_list): tier_item = QTreeWidgetItem(url_tree) #level 1 urls tier_item.setText(0, 'Tier {}'.format(i + 1)) for url in tier: url_item = QTreeWidgetItem(tier_item) url_item.setText(0, url) url_tree.expandAll() vbox.addWidget(url_tree, 1) file_tree = QTreeWidget() file_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) file_tree.setHeaderLabels(('Name', 'Size')) file_tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self._file_items = [] self._traverse_file_tree(download_info.suggested_name, download_info.file_tree, file_tree) file_tree.sortItems(0, Qt.AscendingOrder) file_tree.expandAll() file_tree.itemClicked.connect(self._update_checkboxes) vbox.addWidget(file_tree, 3) self._selection_label = QLabel(TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( len(download_info.files), humanize_size(download_info.total_size))) vbox.addWidget(self._selection_label) self._button_box = QDialogButtonBox(self) self._button_box.setOrientation(Qt.Horizontal) self._button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._button_box.button(QDialogButtonBox.Ok).clicked.connect(self.submit_torrent) self._button_box.button(QDialogButtonBox.Cancel).clicked.connect(self.close) vbox.addWidget(self._button_box) self.setFixedSize(470, 550) self.setWindowTitle('Adding "{}"'.format(filename))
def __init__(self, parent: QWidget, filename: str, torrent_info: TorrentInfo, control_thread: 'ControlManagerThread'): super().__init__(parent) self._torrent_info = torrent_info download_info = torrent_info.download_info self._control_thread = control_thread self._control = control_thread.control vbox = QVBoxLayout(self) self._download_dir = get_directory(self._control.last_download_dir) vbox.addWidget(QLabel('Download directory:')) vbox.addWidget(self._get_directory_browse_widget()) vbox.addWidget(QLabel('Announce URLs:')) url_tree = QTreeWidget() url_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) url_tree.header().close() vbox.addWidget(url_tree) for i, tier in enumerate(torrent_info.announce_list): tier_item = QTreeWidgetItem(url_tree) tier_item.setText(0, 'Tier {}'.format(i + 1)) for url in tier: url_item = QTreeWidgetItem(tier_item) url_item.setText(0, url) url_tree.expandAll() vbox.addWidget(url_tree, 1) file_tree = QTreeWidget() file_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) file_tree.setHeaderLabels(('Name', 'Size')) file_tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self._file_items = [] self._traverse_file_tree(download_info.suggested_name, download_info.file_tree, file_tree) file_tree.sortItems(0, Qt.AscendingOrder) file_tree.expandAll() file_tree.itemClicked.connect(self._update_checkboxes) vbox.addWidget(file_tree, 3) self._selection_label = QLabel(TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( len(download_info.files), humanize_size(download_info.total_size))) vbox.addWidget(self._selection_label) self._button_box = QDialogButtonBox(self) self._button_box.setOrientation(Qt.Horizontal) self._button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._button_box.button(QDialogButtonBox.Ok).clicked.connect(self.submit_torrent) self._button_box.button(QDialogButtonBox.Cancel).clicked.connect(self.close) vbox.addWidget(self._button_box) self.setFixedSize(450, 550) self.setWindowTitle('Adding "{}"'.format(filename))
class BasicTreeWidgetDemo(QMainWindow): def __init__(self, parent=None): super(BasicTreeWidgetDemo, self).__init__(parent) self.tree = QTreeWidget() self.initUI() def initUI(self): self.setWindowTitle('QTreeWidget控件') self.resize(500, 400) # 指定列数 self.tree.setColumnCount(2) # 指定列标签 self.tree.setHeaderLabels(['key', 'value']) # 绑定事件 self.tree.clicked.connect(self.clicked) # 根节点 root = QTreeWidgetItem(self.tree) root.setText(0, '根') # 设置文本 root.setIcon(0, QIcon('./img/root.png')) # 设置图标 self.tree.setColumnWidth(0, 220) # 设置列宽 # 添加子节点 child1 = QTreeWidgetItem(root) child1.setText(0, '子节点1') child1.setText(1, '这是子节点1') child1.setIcon(0, QIcon('./img/child1.png')) child1.setCheckState(0, Qt.Checked) # 设置复选框 # 添加子节点 child2 = QTreeWidgetItem(root) child2.setText(0, '子节点2') child2.setText(1, '这是子节点2') child2.setIcon(0, QIcon('./img/child2.png')) # 添加孙节点 g_child = QTreeWidgetItem(child2) g_child.setText(0, '孙节点1') g_child.setText(1, '孙节点1的值') g_child.setIcon(0, QIcon('./img/gChild.png')) # 展开所有节点 self.tree.expandAll() self.setCentralWidget(self.tree) def clicked(self, item): pass
class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.tree = QTreeWidget(self) self.tree.setColumnCount(2) self.tree.setHeaderLabels(["key","values"]) root = QTreeWidgetItem() root.setText(0,"root") root.setCheckState(0, Qt.Checked) child1 = QTreeWidgetItem(root) child1.setText(0, 'child1') child1.setText(1, 'ios') child1.setCheckState(0, Qt.Checked) # root.addChild(child1) child2 = QTreeWidgetItem(root) child2.setText(0, 'child2') child2.setText(1, '') child2.setCheckState(0, Qt.Checked) child3 = QTreeWidgetItem(child2) child3.setText(0, 'child3') child3.setText(1, 'android') self.tree.addTopLevelItem(root) self.tree.expandAll() # self.setCentralWidget(self.tree) self.tree.clicked.connect(self.onClicked) self.setGeometry(300, 300, 280, 170) self.setWindowTitle('QTreeWidget') self.show() def onClicked(self, qmodeLindex): item = self.tree.currentItem() print('Key=%s,value=%s,parent=%s,index=%s' % (item.text(0), item.text(1),item.parent().text(0),item.parent().indexOfChild(item)))
class InfoDialog(QDialog): def __init__(self, parent, info, title): super().__init__(parent) self.setWindowTitle( translate('MediaInfo', 'Media Info') + ' - ' + title) self.setWindowModality(QtCore.Qt.ApplicationModal) self.setMinimumSize(550, 300) self.resize(550, 500) self.vLayout = QVBoxLayout(self) self.infoTree = QTreeWidget(self) self.infoTree.setColumnCount(2) self.infoTree.setHeaderLabels( [translate('MediaInfo', 'Info'), translate('MediaInfo', 'Value')]) self.infoTree.setAlternatingRowColors(True) self.infoTree.setSelectionMode(QAbstractItemView.NoSelection) self.infoTree.setEditTriggers(QAbstractItemView.NoEditTriggers) self.infoTree.header().setStretchLastSection(False) self.infoTree.header().setSectionResizeMode( QHeaderView.ResizeToContents) self.vLayout.addWidget(self.infoTree) self.__generate_items(info) self.infoTree.expandAll() self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Close) self.vLayout.addWidget(self.buttonBox) self.buttonBox.rejected.connect(self.close) def __generate_items(self, info, parent=None): for key in sorted(info.keys()): if isinstance(info[key], dict): widget = QTreeWidgetItem([key]) self.__generate_items(info[key], widget) else: widget = QTreeWidgetItem([key, info[key]]) if parent is not None: parent.addChild(widget) else: self.infoTree.addTopLevelItem(widget)
class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.resize(500, 300) # 1 self.tree = QTreeWidget(self) # 2 self.tree.setColumnCount(2) self.tree.setHeaderLabels(['Item', 'Path']) #self.tree.itemClicked.connect(self.change_func)#点击触发槽函数 self._1stlevel = [] self._2stlevel = [] self._3stlevel = [] self._4stlevel = [] self._5stlevel = [] self._6stlevel = [] self.tree.expandAll() self.h_layout = QHBoxLayout() #页面布局 self.h_layout.addWidget(self.tree) # self.h_layout.addWidget(self.label) self.setLayout(self.h_layout) def tree_process(self, path_list): path_root = path_list[0] self._1stlevel = QTreeWidgetItem(self.tree) first_item = path_root.split('\\') # 3 self._1stlevel.setText(0, first_item[-1]) self._1stlevel.setCheckState(0, Qt.Unchecked) self._1stlevel.setText(1, path_root) #显示根目录下文件 if path_list[1] != []: for files in path_list[1]: item = QTreeWidgetItem(self._1stlevel) item.setText(0, files) for item_tmp in path_list[2::2]: folder = item_tmp.split('\\') if folder.__len__ > first_item.__len__: self._2stlevel = QTreeWidgetItem() self._2stlevel.setText(0, folder[-1]) self._2stlevel.setText(1, item_tmp) self._2stlevel.setCheckState(0, Qt.Unchecked) self._1stlevel.addChild(self._2stlevel)
def setTreeWidgetJsonData(treeWidget: QTreeWidget, data={}, isExpand=True): """ 给TreeWidget设置数据 :param treeWidget: TreeWidget :param data: json数据 :param isExpand: isExpand是否全部展开 """ treeWidget.clear() root = None if DataTypeUtil.isDict(data): root = WidgetUtil.createTreeWidgetItem("{}") elif DataTypeUtil.isList(data): root = WidgetUtil.createTreeWidgetItem("[]") else: print("data is not json data") return items = WidgetUtil.createTreeWidgetItems(data) root.addChildren(items) treeWidget.addTopLevelItem(root) if isExpand: treeWidget.expandAll() pass
class EditFilesDialog: def __init__(self, model, owner_object): self.model = model self.__owner_object = owner_object self.__added_files = [] self.__window = QDialog() layout = QVBoxLayout() self.__window.setLayout(layout) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.__window.accept) button_box.rejected.connect(self.__window.reject) self.__group_widget = QComboBox() self.__group_widget.addItem("- all -", None) for teacher in model.subject.teachers: for group in teacher.taught_groups: self.__group_widget.addItem(group.moodle_name, group) layout.addWidget(self.__group_widget) self.__files_widget = QTreeWidget() self.__files_widget.setHeaderHidden(True) layout.addWidget(self.__files_widget) layout.addWidget(button_box) self.__refresh_students() self.__group_widget.currentIndexChanged.connect( lambda *args: self.__refresh_students()) def __refresh_students(self): self.__files_widget.clear() group = self.__group_widget.itemData( self.__group_widget.currentIndex()) if group is None: students = self.model.subject.students else: students = list(group.get_students()) for no, student in enumerate(students): name_item = QTreeWidgetItem() self.__files_widget.addTopLevelItem(name_item) name_widget = QWidget() name_layout = QHBoxLayout() name_layout.setAlignment(Qt.AlignLeft) name_layout.setContentsMargins(0, 0, 0, 0) name_layout.addWidget(QLabel(f"{student.name} {student.surname}")) add_button = QPushButton("Add") add_button.clicked.connect( partial(self.__choose_and_add_file, name_item, student)) name_layout.addWidget(add_button) name_widget.setLayout(name_layout) self.__add_files(student.get_points_for(self.__owner_object), name_item) self.__files_widget.setItemWidget(name_item, 0, name_widget) self.__files_widget.expandAll() def __add_files(self, points_object, parent_item): if points_object is None: return for file in points_object.files: self.__add_one_file(file, parent_item, False) def __add_one_file(self, file, parent_item, changed): file_item = QTreeWidgetItem([file.file_name]) file_item.setIcon(0, fip.icon(QFileInfo(file.file_name))) if changed: file_item.setBackground(0, QBrush(QColor(255, 255, 0))) parent_item.addChild(file_item) def __choose_and_add_file(self, parent_item, student, *args): file_name, filter = QFileDialog.getOpenFileName(self.__window, caption="Add File") if file_name: file = ExternalFile(file_name) self.__added_files.append((student, file)) self.__add_one_file(file, parent_item, True) def run(self): if self.__window.exec() == QDialog.Accepted: for student, file in self.__added_files: student.add_file_for(self.__owner_object, file) self.model.data_edited()
class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.resize(500, 300) self.label = QLabel('No Click') # 1 self.tree = QTreeWidget(self) # 2 self.tree.setColumnCount(2) self.tree.setHeaderLabels(['Install Components', 'Test']) self.tree.itemClicked.connect(self.change_func) self.preview = QTreeWidgetItem(self.tree) # 3 self.preview.setText(0, 'Preview') # self.preview = QTreeWidgetItem() # self.preview.setText(0, 'Preview') # self.tree.addTopLevelItem(self.preview) self.qt5112 = QTreeWidgetItem() # 4 self.qt5112.setText(0, 'Qt 5.11.2 snapshot') self.qt5112.setCheckState(0, Qt.Unchecked) self.preview.addChild(self.qt5112) choice_list = ['macOS', 'Android x86', 'Android ARMv7', 'Sources', 'iOS'] self.item_list = [] for i, c in enumerate(choice_list): # 5 item = QTreeWidgetItem(self.qt5112) item.setText(0, c) item.setCheckState(0, Qt.Unchecked) self.item_list.append(item) self.test_item = QTreeWidgetItem(self.qt5112) # 6 self.test_item.setText(0, 'test1') self.test_item.setText(1, 'test2') self.tree.expandAll() # 7 self.h_layout = QHBoxLayout() self.h_layout.addWidget(self.tree) self.h_layout.addWidget(self.label) self.setLayout(self.h_layout) def change_func(self, item, column): self.label.setText(item.text(column)) # 8 print(item.text(column)) print(column) if item == self.qt5112: # 9 if self.qt5112.checkState(0) == Qt.Checked: [x.setCheckState(0, Qt.Checked) for x in self.item_list] else: [x.setCheckState(0, Qt.Unchecked) for x in self.item_list] else: # 10 check_count = 0 for x in self.item_list: if x.checkState(0) == Qt.Checked: check_count += 1 if check_count == 5: self.qt5112.setCheckState(0, Qt.Checked) elif 0 < check_count < 5: self.qt5112.setCheckState(0, Qt.PartiallyChecked) else: self.qt5112.setCheckState(0, Qt.Unchecked)
class MenuEditor(AnimateableEditor): contentChanged = pyqtSignal(object) menuChanged = pyqtSignal(str) def __init__(self, win, menu, site): AnimateableEditor.__init__(self) self.win = win self.menu = menu self.site = site self.changed = False self.setAutoFillBackground(True) titleLabel = QLabel("Menu Editor") fnt = titleLabel.font() fnt.setPointSize(20) fnt.setBold(True) titleLabel.setFont(fnt) self.close = FlatButton(":/images/close_normal.png", ":/images/close_hover.png") self.close.setToolTip("Close Content Editor") self.undo = FlatButton(":/images/undo_normal.png", ":/images/undo_hover.png", "", ":/images/undo_disabled.png") self.redo = FlatButton(":/images/redo_normal.png", ":/images/redo_hover.png", "", ":/images/redo_disabled.png") self.undo.setToolTip("Undo") self.redo.setToolTip("Redo") self.undo.setEnabled(False) self.redo.setEnabled(False) hbox = QHBoxLayout() hbox.addStretch(0) hbox.addWidget(self.undo) hbox.addWidget(self.redo) hbox.addWidget(self.close) addButton = QPushButton("Add Menuitem") addButton.setMaximumWidth(120) self.name = QLineEdit() self.name.setText(menu.name) self.name.setMaximumWidth(200) labels = ["Title", "Url", "Icon", "", "Sort"] self.tree = QTreeWidget() self.tree.setHeaderLabels(labels) self.tree.header().setSectionResizeMode(0, QHeaderView.Stretch) self.tree.header().hideSection(4) self.tree.setSelectionMode(QAbstractItemView.NoSelection) self.tree.setToolTip("Double Click To Edit") self.tree.setColumnWidth(2, 40) layout = QGridLayout() layout.addWidget(titleLabel, 0, 0) layout.addLayout(hbox, 0, 2) layout.addWidget(QLabel("Name"), 1, 0) layout.addWidget(self.name, 2, 0) layout.addWidget(addButton, 3, 0) layout.addWidget(self.tree, 4, 0, 1, 3) self.setLayout(layout) self.reloadMenu(menu) addButton.clicked.connect(self.addButtonClicked) self.close.clicked.connect(self.closeEditor) self.name.editingFinished.connect(self.nameChanged) self.redo.clicked.connect(self.redoEdit) self.undo.clicked.connect(self.undoEdit) self.tree.itemChanged.connect(self.itemChanged) def reloadMenu(self, menu): if not menu: self.close.emit() return self.menu = menu self.tree.clear() self.name.setText(menu.name) for i in range(0, len(self.menu.items)): item = self.menu.items[i] self.addTreeItem(item) self.tree.expandAll() self.tree.sortItems(4, Qt.AscendingOrder) self.updateButtonStates() def addTreeItem(self, item): twi = QTreeWidgetItem() twi.setFlags(twi.flags() | Qt.ItemIsEditable) twi.setText(0, item.title) twi.setText(1, item.url) twi.setText(4, str(self.tree.topLevelItemCount())) twi.setData(0, Qt.UserRole, item) self.tree.addTopLevelItem(twi) self.addTableCellButtons(item, twi) for i in range(len(item.items)): sub = item.items[i] stwi = QTreeWidgetItem() stwi.setFlags(stwi.flags() | Qt.ItemIsEditable) stwi.setText(0, sub.title) stwi.setText(1, sub.url) stwi.setText(4, str(i)) stwi.setData(0, Qt.UserRole, sub) twi.addChild(stwi) self.addTableCellButtons(sub, stwi) def addTableCellButtons(self, item, twi): tcb = MenuEditorTableCellButtons() tcb.setMenuItem(item) self.tree.setItemWidget(twi, 3, tcb) self.tree.setColumnWidth(3, tcb.sizeHint().width()) if item.isSubitem(): tcb.deleteItem.connect(self.deleteSubItem) tcb.itemLeft.connect(self.itemLeft) else: tcb.deleteItem.connect(self.deleteItem) tcb.itemUp.connect(self.itemUp) tcb.itemDown.connect(self.itemDown) tcb.itemRight.connect(self.itemRight) tcb.editItem.connect(self.editItem) imgs = ImageSelector() imgs.setToolTip("Click to select image, right click to reset image") imgs.setItem(item) imgs.setMaximumSize(24, 24) isw = QWidget() vbox = QVBoxLayout() vbox.addWidget(imgs) isw.setLayout(vbox) if not item.icon: imgs.setImage(QImage(":/images/image_placeholder.png")) else: imgs.setImage(QImage(self.site.source_path + "/" + item.icon)) self.tree.setItemWidget(twi, 2, isw) imgs.clicked.connect(self.iconClicked) def registerUndoStack(self, stack): self.undoStack = stack self.undoStack.canUndoChanged.connect(self.canUndoChanged) self.undoStack.canRedoChanged.connect(self.canRedoChanged) self.undoStack.undoTextChanged.connect(self.undoTextChanged) self.undoStack.redoTextChanged.connect(self.redoTextChanged) self.undo.setEnabled(self.undoStack.canUndo()) self.redo.setEnabled(self.undoStack.canRedo()) self.undo.setToolTip("Undo " + self.undoStack.undoText()) self.redo.setToolTip("Redo " + self.undoStack.redoText()) def canUndoChanged(self, can): self.undo.setEnabled(can) def canRedoChanged(self, can): self.redo.setEnabled(can) def undoTextChanged(self, text): self.undo.setToolTip("Undo " + text) def redoTextChanged(self, text): self.redo.setToolTip("Redo " + text) def getUndoRedoText(self, item, action): return "menuitem (" + item.title + ") from menu (" + self.menu.name + ") " + action def undoEdit(self): self.undoStack.undo() def redoEdit(self): self.undoStack.redo() def addButtonClicked(self): menuitem = MenuItem() self.menu.addMenuitem(menuitem) self.addTreeItem(menuitem) self.menuChanged.emit(self.getUndoRedoText(menuitem, "added")) self.updateButtonStates() item = self.tree.topLevelItem(self.getRow(menuitem)) self.tree.editItem(item, 0) def closeEditor(self): self.closes.emit() def nameChanged(self): if self.menu.name != self.name.text: action = "menu name changed from \"" + self.menu.name + "\" to \"" + self.name.text + "\"" self.menu.setName(self.name.text()) self.contentChanged.emit(self.menu) self.menuChanged.emit(action) def itemChanged(self, twi, column): action = "" item = twi.data(0, Qt.UserRole) if column == 0: item.title = twi.text(0) action = "title changed" elif column == 1: item.url = twi.text(1) action = "url changed" self.menuChanged.emit(self.getUndoRedoText(item, action)) def getRow(self, menuitem): for i in range(0, self.tree.topLevelItemCount()): item = self.tree.topLevelItem(i) mi = item.data(0, Qt.UserRole) if mi == menuitem: return i return -1 def deleteSubItem(self, menuitem): row = self.getRow(menuitem.parentItem) parent = self.tree.topLevelItem(row) if parent: for i in range(0, parent.childCount()): child = parent.child(i) mi = child.data(0, Qt.UserRole) if mi == menuitem: parent.removeChild(child) del child break if menuitem.parentItem: menuitem.parentItem.removeMenuitem(menuitem) self.updateButtonStates() self.menuChanged.emit(self.getUndoRedoText(menuitem, "deleted")) def itemLeft(self, menuitem): row = self.getRow(menuitem.parentItem()) parent = self.tree.topLevelItem(row) for i in range(parent.childCount()): child = parent.child(i) mi = child.data(0, Qt.UserRole) if mi == menuitem: menuitem.parentItem().removeMenuitem(menuitem) menuitem.setSubitem(False) self.menu.addMenuitem(menuitem) parent.takeChild(i) self.addTreeItem(menuitem) break self.updateButtonStates() self.menuChanged.emit( self.getUndoRedoText(menuitem, "changed to top item")) def iconClicked(self, itemselector, button): mi = itemselector.item() action = "" if button == Qt.LeftButton: fileName = "" dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setNameFilter("Images (*.png *.gif *.jpg)All (*)") dialog.setWindowTitle("Load Image") dialog.setOption(QFileDialog.DontUseNativeDialog, True) dialog.setAcceptMode(QFileDialog.AcceptOpen) if dialog.exec_(): fileName = dialog.selectedFiles().first() del dialog if not fileName: return # copy file to assets dir info = QFileInfo(fileName) name = info.fileName().replace(" ", "_") path = self.site.source_path + "/assets/images/" + name QFile.copy(fileName, path) # also copy file to deploy dir for previews dpath = self.site.deploy_path + "/assets/images/" + name QFile.copy(fileName, dpath) mi.setIcon(path.mid(path.indexOf("assets/images/"))) itemselector.setImage(QImage(path)) action = "icon changed" elif button == Qt.RightButton: action = "icon removed" mi.setIcon("") itemselector.setImage(QImage(":/images/image_placeholder.png")) self.menuChanged.emit(self.getUndoRedoText(mi, action)) def updateButtonStates(self): for i in range(0, self.tree.topLevelItemCount()): twi = self.tree.topLevelItem(i) tcb = self.tree.itemWidget(twi, 3) menuitem = twi.data(0, Qt.UserRole) tcb.setEnableDown(i != self.tree.topLevelItemCount() - 1) tcb.setEnableUp(i != 0) tcb.setEnableRight(i != 0 and len(menuitem.items) == 0) tcb.setEnableLeft(False) for j in range(0, twi.childCount()): stwi = twi.child(j) stcb = self.tree.itemWidget(stwi, 3) stcb.setEnableLeft(True)
class HomeWorksTab: model: GuiModel def __init__(self, model): self.__home_work_list = QTreeWidget() self.__home_work_list.setHeaderLabel("Name") self.__home_work_list.itemSelectionChanged.connect( self.__home_work_selected) self.__home_work_list.setContextMenuPolicy(Qt.CustomContextMenu) self.__home_work_list.customContextMenuRequested.connect( self.__home_work_context_menu) self.__home_work_details = QTreeWidget() self.__home_work_details.setColumnCount(2) self.__home_work_details.setHeaderLabels(["Student", "Points"]) self.__home_work_details.itemActivated.connect( lambda item, column: file_double_clicked(self.model, item)) self.__home_work_details.itemSelectionChanged.connect( self.__home_work_file_selected) self.__home_work_file_details = FileDetailsWidget(model) details_splitter = QSplitter(Qt.Horizontal) details_splitter.addWidget(self.__home_work_details) details_splitter.addWidget(self.__home_work_file_details.widget) self.widget = QSplitter(Qt.Vertical) self.widget.addWidget(self.__home_work_list) self.widget.addWidget(details_splitter) self.widget.setStretchFactor(0, 3) self.widget.setStretchFactor(1, 1) self.model = model self.__load_home_works() self.model.subject_changed.connect(self.__subject_changed) def __subject_changed(self): self.__load_home_works() def __load_home_works(self): self.__home_work_list.clear() self.__home_work_details.clear() self.__home_work_file_details.master_selection_changed([]) if self.model.subject is not None: for category in self.model.subject.home_work_categories: category_item = QTreeWidgetItem([category.name]) self.__home_work_list.addTopLevelItem(category_item) for home_work in category.home_works: home_work_item = HomeWorkItem([home_work.name], home_work) category_item.addChild(home_work_item) self.__home_work_list.expandAll() def __home_work_selected(self): self.__home_work_details.clear() self.__home_work_file_details.master_selection_changed([]) home_work_items = self.__home_work_list.selectedItems() if home_work_items and isinstance(home_work_items[0], HomeWorkItem): home_work: HomeWork = home_work_items[0].home_work for home_work_points in home_work.get_submissions(): student_item = StudentItem([ f"{home_work_points.student.surname} {home_work_points.student.name}", points_or_none(home_work_points.points) ], home_work_points.student) self.__home_work_details.addTopLevelItem(student_item) add_file_items(home_work_points.files, student_item) self.__home_work_details.expandAll() def __home_work_file_selected(self): self.__home_work_file_details.master_selection_changed( self.__home_work_details.selectedItems()) def __home_work_context_menu(self, pos): item = self.__home_work_list.itemAt(pos) if isinstance(item, HomeWorkItem): menu = QMenu() menu.addAction("Edit points...").triggered.connect( lambda *args: EditPointsDialog(self.model, item.home_work).run( )) menu.addAction("Edit files...").triggered.connect( lambda *args: EditFilesDialog(self.model, item.home_work).run( )) menu.exec(self.__home_work_list.viewport().mapToGlobal(pos))
class TemplateManagementTab(QWidget): def __init__(self, obj_mng: ObjectManager, tpl_mng: TemplateManager, sgn_mng: SignageManager, mtm_mng: MultimediaManager, chn_mng: ChannelManager): super().__init__() self._obj_mng = obj_mng self._tpl_mng = tpl_mng self._sgn_mng = sgn_mng self._mtm_mng = mtm_mng self._chn_mng = chn_mng self._multimedia_list = QTreeWidget() self._res = ResourceManager() def template_change_handler(change_type: utils.ChangeType, tpl_text: str = ''): get_selected = self._multimedia_list.selectedItems() if get_selected: item = get_selected[0] if change_type == utils.ChangeType.DELETE: parent = item.parent() parent.removeChild(item) self._template_widget = TemplateWidget(self._tpl_mng, template_change_handler) self.init_ui() def template_to_tree_item(self) -> [QTreeWidgetItem]: frame_label_item = QTreeWidgetItem([self._res['frameLabel']]) for frame_tpl_id in self._tpl_mng.frame_templates.keys(): frame_tpl = self._tpl_mng.get_frame_template(frame_tpl_id) frame_text = utils.gen_ui_text(frame_tpl.definition.name, frame_tpl.id) frame_item = QTreeWidgetItem([frame_text]) frame_label_item.addChild(frame_item) scene_label_item = QTreeWidgetItem([self._res['sceneLabel']]) for scene_tpl_id in self._tpl_mng.scene_templates.keys(): scene_tpl = self._tpl_mng.get_scene_template(scene_tpl_id) scene_text = utils.gen_ui_text(scene_tpl.definition.name, scene_tpl.id) scene_item = QTreeWidgetItem([scene_text]) scene_label_item.addChild(scene_item) return [frame_label_item, scene_label_item] def init_ui(self) -> None: # Left side of screen self._multimedia_list.setHeaderLabel(self._res['templateListLabel']) self._multimedia_list.addTopLevelItems(self.template_to_tree_item()) self._multimedia_list.expandAll() self._multimedia_list.itemSelectionChanged.connect( self.list_item_clicked) # Gather altogether hbox_outmost = QHBoxLayout() hbox_outmost.addWidget(self._multimedia_list, 1) hbox_outmost.addWidget(self._template_widget, 4) self.setLayout(hbox_outmost) def list_item_clicked(self) -> None: get_selected = self.sender().selectedItems() if get_selected: item = get_selected[0] item_text = item.text(0) if item.parent() is None: # It is at topmost level # Selected one is Scene/Frame self._template_widget.clear_data_on_ui() else: # Selected one is frame/scene tpl_id = utils.ui_text_to_id(item_text) if item.parent().text(0) == self._res['frameLabel']: # Selected one is frame template tpl = self._tpl_mng.get_frame_template(tpl_id) else: # Selected one is scene template tpl = self._tpl_mng.get_scene_template(tpl_id) self._template_widget.load_data_on_ui(tpl)
class TorrentPreferencesDialog(QDialog): dataReady = pyqtSignal(dict) def __init__(self, parent, torrent_info): super().__init__(parent) self.torrentInfo = torrent_info self.setUp() def setUp(self): self.setWindowTitle("Torrent settings") parentRect = self.parentWidget().geometry() self.resize(parentRect.width() * 0.75, parentRect.height() * 0.9) self.setMinimumSize(self.size()) # Create the dialog layout self.layout = QVBoxLayout(self) # Set up the destination folder selector self.setUpDialogHeader() # Set up the file lister for the torrent file self.setUpFileLister() # Set up the whole torrent priority combo box and buttons self.setUpDialogFooter() def setUpDialogHeader(self): headerLayout = QGridLayout() self.destinationFolder = paths.writableLocation(paths.DownloadLocation) torrentName = self.torrentInfo.name() # Show the torrent name row nameLabel = QLabel("Torrent name:", self) headerLayout.addWidget(nameLabel, 0, 0) nameEdit = QLineEdit(torrentName, self) nameEdit.setReadOnly(True) headerLayout.addWidget(nameEdit, 0, 1) # Show the destination folder row dirLabel = QLabel("Destination folder:", self) headerLayout.addWidget(dirLabel, 1, 0) self.textField = QLineEdit(self.destinationFolder, self) self.textField.setReadOnly(True) headerLayout.addWidget(self.textField, 1, 1) button = QPushButton("Browse", self) button.clicked.connect(self.selectFolder) headerLayout.addWidget(button, 1, 2) self.layout.addLayout(headerLayout) def selectFolder(self): newDir = str(QFileDialog.getExistingDirectory(self, "Select Directory")) if newDir: self.textField.setText(newDir) self.destinationFolder = newDir def setUpFileLister(self): self.files = [(f.path, f.size) for f in self.torrentInfo.files()] self.treeView = QTreeWidget(self) self.treeView.setColumnCount(3) self.treeView.setColumnWidth(0, 350) self.treeView.setColumnWidth(1, 80) self.treeView.setHeaderLabels(["Name", "size", "Priority"]) self.treeView.setExpandsOnDoubleClick(False) if len(self.files) == 1: tree = file_tree.FileTree(self.files[0][0], self.files[0][1]) else: tree = file_tree.FileTree(self.files[0][0].split('/')[0], 0) for f in self.files: tree.add_file(f[0], f[1]) rootItem = TreeNodeItem(tree.get_root(), self.treeView) self.treeView.addTopLevelItem(rootItem) self.treeView.expandAll() self.treeView.itemClicked.connect(self.rowClicked) self.layout.addWidget(self.treeView) def rowClicked(self, item, column): if item.checkState(0) == Qt.PartiallyChecked: item.setCheckState(0, Qt.Checked) if column == 2: priorityChanges = {'Normal': 'High', 'High': 'Low', 'Low': 'Normal', 'Mixed': 'Normal'} newPriority = priorityChanges[item.text(2)] self.changeTextOfAllChildren(item, 2, newPriority) self.reprioritize(item) def changeTextOfAllChildren(self, item, column, text): item.setText(column, text) for i in range(0, item.childCount()): self.changeTextOfAllChildren(item.child(i), column, text) def reprioritize(self, start_node): parent = start_node.parent() if parent: if self.allChildrenHaveSamePriority(parent): parent.setText(2, start_node.text(2)) else: parent.setText(2, "Mixed") self.reprioritize(parent) def allChildrenHaveSamePriority(self, node): for i in range(1, node.childCount()): if node.child(i - 1).text(2) != node.child(i).text(2): return False return True def setUpDialogFooter(self): footerLayout = QGridLayout() footerLayout.setColumnStretch(0, 4) footerLayout.addWidget(QLabel("Torrent priority"), 0, 1) self.priorityComboBox = QComboBox(self) self.priorityComboBox.addItems(["High", "Normal", "Low"]) self.priorityComboBox.setCurrentIndex(1) footerLayout.addWidget(self.priorityComboBox, 0, 2) secondRowLayout = QHBoxLayout() OKButton = QPushButton("Open", self) OKButton.setFocus() OKButton.clicked.connect(self.accept) cancelButton = QPushButton("Cancel", self) cancelButton.clicked.connect(self.reject) secondRowLayout.addWidget(OKButton) secondRowLayout.addWidget(cancelButton) footerLayout.addLayout(secondRowLayout, 1, 2) self.layout.addLayout(footerLayout) def accept(self): torrentPriorities = {"Low": 0, "Normal": 127, "High": 255} filePriorities = {"Low": 1, "Normal": 4, "High": 7} it = QTreeWidgetItemIterator(self.treeView, QTreeWidgetItemIterator.NoChildren) itemsInfo = {} while it.value(): currentItem = it.value() if currentItem.checkState(0) == Qt.Unchecked: priority = 0 else: priority = filePriorities[currentItem.text(2)] itemsInfo[self.getFullPath(currentItem)] = priority it += 1 paths = [f.path for f in self.torrentInfo.files()] self.prioritiesList = [itemsInfo[p] for p in paths] comboBoxIndex = self.priorityComboBox.currentIndex() self.priority = torrentPriorities[self.priorityComboBox.itemText( comboBoxIndex)] self.hide() self.dataReady.emit(self.getData()) super().accept() def getFullPath(self, treeItem): items = [treeItem.text(0)] parent = treeItem.parent() while parent: items.append(parent.text(0)) parent = parent.parent() return '/'.join(reversed(items)) def getData(self): return {'info': self.torrentInfo, 'destination_folder': self.destinationFolder, 'torrent_priority': self.priority, 'file_priorities': self.prioritiesList}
class Preferences(QDialog): # configuration = {} weight = 0 # savePreferences = pyqtSignal() # def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(900, 600)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) # self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) # hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) # self.tree.itemSelectionChanged.connect(self._change_current) self._btnCancel.clicked['bool'].connect(self.close) self._btnSave.clicked['bool'].connect(self._save_preferences) # self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0)) # def _save_preferences(self): self.savePreferences.emit() self.close() # def load_ui(self): sections = sorted( list(Preferences.configuration.keys()), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # #Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted(list(subcontent.keys()), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) # self.tree.expandAll() # def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) # @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if not subsection: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config
class TreeSymbolsWidget(QDialog): """ Class of Dialog for Tree Symbols """ dockWidget = pyqtSignal('PyQt_PyObject') undockWidget = pyqtSignal('PyQt_PyObject') def __init__(self, parent=None): super(TreeSymbolsWidget, self).__init__(parent) vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.tree = QTreeWidget() self.tree.setFrameShape(0) vbox.addWidget(self.tree) self.tree.header().setHidden(True) self.tree.setSelectionMode(self.tree.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.actualSymbols = ('', {}) self.docstrings = {} self.collapsedItems = {} self.__icons = { "function": QIcon(":img/function"), "attribute": QIcon(":img/statement"), "class": QIcon(":img/class") } self.tree.itemClicked.connect(self._go_to_definition) self.tree.itemActivated.connect(self._go_to_definition) self.tree.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested['const QPoint &'].connect( self._menu_context_tree) # self.connect( # self, # SIGNAL("customContextMenuRequested(const QPoint &)"), # self._menu_context_tree) # self.connect(self, SIGNAL("itemCollapsed(QTreeWidgetItem *)"), # self._item_collapsed) # self.connect(self, SIGNAL("itemExpanded(QTreeWidgetItem *)"), # self._item_expanded) IDE.register_service('symbols_explorer', self) ExplorerContainer.register_tab(translations.TR_TAB_SYMBOLS, self) def install_tab(self): """ Connect signals for goingdown """ ide = IDE.get_service('ide') ide.goingDown.connect(self.close) def _menu_context_tree(self, point): """Context menu""" index = self.tree.indexAt(point) if not index.isValid(): return menu = QMenu(self) f_all = menu.addAction(translations.TR_FOLD_ALL) u_all = menu.addAction(translations.TR_UNFOLD_ALL) menu.addSeparator() u_class = menu.addAction(translations.TR_UNFOLD_CLASSES) u_class_method = menu.addAction( translations.TR_UNFOLD_CLASSES_AND_METHODS) u_class_attr = menu.addAction( translations.TR_UNFOLD_CLASSES_AND_ATTRIBUTES) menu.addSeparator() # save_state = menu.addAction(self.tr("Save State")) # self.connect(f_all, SIGNAL("triggered()"), # lambda: self.tree.collapseAll()) # self.connect(u_all, SIGNAL("triggered()"), # lambda: self.tree.expandAll()) # self.connect(u_class, SIGNAL("triggered()"), self._unfold_class) # self.connect(u_class_method, SIGNAL("triggered()"), # self._unfold_class_method) # self.connect(u_class_attr, SIGNAL("triggered()"), # self._unfold_class_attribute) # self.connect(save_state, SIGNAL("triggered()"), # self._save_symbols_state) menu.exec_(QCursor.pos()) def _get_classes_root(self): """Return the root of classes""" class_root = None for i in range(self.tree.topLevelItemCount()): item = self.tree.topLevelItem(i) if item.isClass and not item.isClickable: class_root = item break return class_root def _unfold_class(self): """Method to Unfold Classes""" self.tree.collapseAll() classes_root = self._get_classes_root() if not classes_root: return classes_root.setExpanded(True) def _unfold_class_method(self): """Method to Unfold Methods""" self.tree.expandAll() classes_root = self._get_classes_root() if not classes_root: return # for each class! for i in range(classes_root.childCount()): class_item = classes_root.child(i) # for each attribute or functions for j in range(class_item.childCount()): item = class_item.child(j) # METHODS ROOT!! if not item.isMethod and not item.isClickable: item.setExpanded(False) break def _unfold_class_attribute(self): """Method to Unfold Attributes""" self.tree.expandAll() classes_root = self._get_classes_root() if not classes_root: return # for each class! for i in range(classes_root.childCount()): class_item = classes_root.child(i) # for each attribute or functions for j in range(class_item.childCount()): item = class_item.child(j) # ATTRIBUTES ROOT!! if not item.isAttribute and not item.isClickable: item.setExpanded(False) break def _save_symbols_state(self): """Method to Save a persistent Symbols state""" # filename = self.actualSymbols[0] # TODO: persist self.collapsedItems[filename] in QSettings pass def _get_expand(self, item): """ Returns True or False to be used as setExpanded() with the items It method is based on the click that the user made in the tree """ name = self._get_unique_name(item) filename = self.actualSymbols[0] collapsed_items = self.collapsedItems.get(filename, []) can_check = (not item.isClickable) or item.isClass or item.isMethod if can_check and name in collapsed_items: return False return True @staticmethod def _get_unique_name(item): """ Returns a string used as unique name """ # className_Attributes/className_Functions parent = item.parent() if parent: return "%s_%s" % (parent.text(0), item.text(0)) return "_%s" % item.text(0) def clear(self): self.tree.clear() def update_symbols_tree(self, symbols, filename='', parent=None): """Method to Update the symbols on the Tree""" TIP = "{} {}" if not parent: if filename == self.actualSymbols[0] and \ self.actualSymbols[1] and not symbols: return if symbols == self.actualSymbols[1]: # Nothing new then return return # we have new symbols refresh it self.tree.clear() self.actualSymbols = (filename, symbols) self.docstrings = symbols.get('docstrings', {}) parent = self.tree if 'attributes' in symbols: globalAttribute = ItemTree(parent, [translations.TR_ATTRIBUTES]) globalAttribute.isClickable = False globalAttribute.isAttribute = True globalAttribute.setExpanded(self._get_expand(globalAttribute)) globalAttribute.setToolTip( 0, TIP.format(len(symbols['attributes']), translations.TR_ATTRIBUTES)) for glob in sorted(symbols['attributes']): globItem = ItemTree(globalAttribute, [glob], lineno=symbols['attributes'][glob]) globItem.isAttribute = True globItem.setIcon(0, self.__icons["attribute"]) globItem.setExpanded(self._get_expand(globItem)) if 'functions' in symbols and symbols['functions']: functionsItem = ItemTree(parent, [translations.TR_FUNCTIONS]) functionsItem.isClickable = False functionsItem.isMethod = True functionsItem.setExpanded(self._get_expand(functionsItem)) functionsItem.setToolTip(0, TIP.format(len(symbols['functions']), translations.TR_FUNCTIONS)) for func in sorted(symbols['functions']): item = ItemTree(functionsItem, [func], lineno=symbols['functions'][func]['lineno']) tooltip = self.create_tooltip( func, symbols['functions'][func]['lineno']) item.isMethod = True item.setIcon(0, self.__icons["function"]) # item.setIcon( # 0, ui_tools.colored_icon(":img/function", "#9FA8DA")) item.setToolTip(0, tooltip) item.setExpanded(self._get_expand(item)) self.update_symbols_tree( symbols['functions'][func]['functions'], parent=item) if 'classes' in symbols and symbols['classes']: classItem = ItemTree(parent, [translations.TR_CLASSES]) classItem.isClickable = False classItem.isClass = True classItem.setExpanded(self._get_expand(classItem)) classItem.setToolTip(0, TIP.format(len(symbols['classes']), translations.TR_CLASSES)) for claz in sorted(symbols['classes']): line_number = symbols['classes'][claz]['lineno'] item = ItemTree(classItem, [claz], lineno=line_number) item.isClass = True tooltip = self.create_tooltip(claz, line_number) item.setToolTip(0, tooltip) # item.setIcon(0, ui_tools.colored_icon(":img/class", "#FFCC80")) # item.setIcon(0, ui_tools.get_icon('class', '#FFCC80')) item.setIcon(0, self.__icons["class"]) item.setExpanded(self._get_expand(item)) self.update_symbols_tree(symbols['classes'][claz]['members'], parent=item) def _go_to_definition(self, item): """ Takes and item object and goes to definition on the editor """ main_container = IDE.get_service('main_container') if item.isClickable and main_container: main_container.editor_go_to_line(item.lineno - 1) def create_tooltip(self, name, lineno): """Takes a name and line number and returns a tooltip""" doc = self.docstrings.get(lineno, None) if doc is None: doc = '' else: doc = '\n' + doc tooltip = name + doc return tooltip def _item_collapsed(self, item): """When item collapsed""" super(TreeSymbolsWidget, self).collapseItem(item) can_check = (not item.isClickable) or item.isClass or item.isMethod if can_check: n = self._get_unique_name(item) filename = self.actualSymbols[0] self.collapsedItems.setdefault(filename, []) if n not in self.collapsedItems[filename]: self.collapsedItems[filename].append(n) def _item_expanded(self, item): """When item expanded""" super(TreeSymbolsWidget, self).expandItem(item) n = self._get_unique_name(item) filename = self.actualSymbols[0] if n in self.collapsedItems.get(filename, []): self.collapsedItems[filename].remove(n) if not len(self.collapsedItems[filename]): # no more items, free space del self.collapsedItems[filename] def clean(self): """ Reset the tree and reset attributes """ self.tree.clear() self.collapsedItems = {} def reject(self): if self.parent() is None: self.dockWidget.emit(self) def closeEvent(self, event): """On Close event handling""" self.dockWidget.emit(self) # self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) event.ignore()
class ClientForm(QMainWindow): """主页面""" def __init__(self): super().__init__() self.init = 0 # 0 代表初始情况,需要建立websocket连接,其他不用 self.cur_user_t = ('', '') # 当前用户的工号和姓名 self.initUI() def initUI(self): """ 初始化UI :return: """ self.setObjectName("mainWindow") self.setStyleSheet('#mainWindow{background-color:white}') self.setFixedSize(400, 770) self.setWindowTitle("cssrc消息盒子") self.setWindowIcon(QIcon('static/logo_title.png')) # 获取屏幕信息 desktop = QApplication.desktop() self.move(desktop.width() - 400 - 10, 5) # 创建状态栏 self.statusBar().showMessage("copyright@cssrc") # 创建菜单栏 self.create_menu() # 创建用户信息部分 uwidget = QWidget(self) uwidget.setObjectName("usrpart") uwidget.setStyleSheet( "#usrpart{border:1px solid #e1e2e2;border-left:none;border-right:none;}" ) uwidget.setGeometry(0, 26, 400, 80) hbox_user = QHBoxLayout() uwidget.setLayout(hbox_user) # 创建用户头像 pixmap = QPixmap("static/usr.png") label = QLabel(self) label.setPixmap(pixmap) hbox_user.addWidget(label, 1) # 用户信息 uvbox = QVBoxLayout() usrname = self.cur_user_t[1] if self.cur_user_t is not None else "暂无" self.lbl_usrname = QLabel("%s, %s好" % (usrname, "下午")) self.lbl_usrname.setFont(QFont("Microsoft YaHei")) self.lbl_usrname.setStyleSheet("margin-left:10px") uvbox.addWidget(self.lbl_usrname) # 消息logo msg_logo_num = QWidget() msg_logo_num_lay = QHBoxLayout() msg_logo_num.setLayout(msg_logo_num_lay) # 消息条数部分组件 lbl_msgnum = QLabel() msgpixmap = QPixmap("static/msg_sm.png") lbl_msgnum.setPixmap(msgpixmap) msg_logo_num_lay.addWidget(lbl_msgnum) lbl_msg_number = QLabel("(12)") lbl_msg_number.setFont(QFont("Microsoft YaHei")) msg_logo_num_lay.addWidget(lbl_msg_number, 1) uvbox.addWidget(msg_logo_num) hbox_user.addLayout(uvbox, 4) # 创建消息列表部分 unread_label = QLabel(self) unread_label.setObjectName("unread_label") unread_label.setText("未读消息") unread_label.setFont(QFont("Microsoft YaHei")) unread_label.setStyleSheet( "#%s{border:1px solid #e1e2e2;border-left:none;border-right:none;padding-left:20px;}" % "unread_label") unread_label.setGeometry(0, 105, 400, 50) # 消息列表具体内容 self.msglist_widget = QWidget(self) self.msglist_widget.setGeometry(0, 155, 400, 580) self.msglist_widget.setObjectName("msglist") self.msglist_widget.setStyleSheet("#msglist{border:1px solid red}") # 在此动态添加内容 self.tree = QTreeWidget(self.msglist_widget) # 创建tree组件 # 设置列数 self.tree.setColumnCount(3) # 设置列数 # 设置树形控件的头部标题 self.tree.setHeaderLabels(["消息描述", "推送时间", "url"]) # 给treeview设置标题 # 设置隐藏 self.tree.setColumnHidden(2, True) # 设置属性控件列的宽度 self.tree.setColumnWidth(0, 280) self.tree.setColumnWidth(1, 80) def create_menu(self): """ 创建菜单 :return: """ menubar = self.menuBar() # 创建菜单栏 # 新建菜单项 fileMenu = menubar.addMenu("&文件(F)") # 添加菜单子项 selfAct = QAction(QIcon('exit.png'), '&个人设置(P)', self) selfAct.setShortcut('Ctrl+P') selfAct.setStatusTip("个人设置") selfAct.triggered.connect(self.go_self_setting) # 查看个人信息页面 fileMenu.addAction(selfAct) # 系统设置 syssetAct = QAction("&系统设置(S)", self) syssetAct.setShortcut("Ctrl+S") syssetAct.setStatusTip("系统设置") syssetAct.triggered.connect(self.go_sys_setting) # 去系统设置页面 fileMenu.addAction(syssetAct) # 退出 exitAct = QAction("&退出(X)", self) exitAct.setShortcut("Ctrl+X") exitAct.setStatusTip("退出系统") exitAct.triggered.connect(qApp.quit) # 退出系统 fileMenu.addAction(exitAct) # 新建帮助菜单项 helpMenu = menubar.addMenu("&帮助(H)") # 添加帮助菜单项 seeAct = QAction("&查看消息记录(M)", self) seeAct.setShortcut("Ctrl+M") seeAct.setStatusTip("查看消息记录") seeAct.triggered.connect(self.go_see_history) # 查看历史消息 helpMenu.addAction(seeAct) # 刷新系统组织 refreshSys = QAction("&刷新系统组织(U)", self) refreshSys.setShortcut("Ctrl+U") refreshSys.setStatusTip("刷新系统组织") refreshSys.triggered.connect(self.go_fresh_sys) # 刷新系统组织 helpMenu.addAction(refreshSys) # 关于 aboutAct = QAction("&关于(A)", self) aboutAct.setShortcut("Ctrl+A") aboutAct.setStatusTip("关于系统") aboutAct.triggered.connect(self.go_about) # 关于系统 helpMenu.addAction(aboutAct) def go_self_setting(self): """ 个人设置页面 :return: """ print("查看个人设置 页面") def go_sys_setting(self): """ 系统设置页面 :return: """ print("系统设置 页面") def go_see_history(self): """ 查看历史消息 :return: """ print("历史消息 页面") def go_fresh_sys(self): """ 刷新系统组织 :return: """ print("系统组织") def go_about(self): """ 查看关于系统 :return: """ print("关于系统") def do_fetch_data(self): """ 加载用户数据 :return: """ self.cur_user_t = getUsrTuples() print(self.cur_user_t) def onClicked(self, index): """ 点击单个选项事件 :param index: :return: """ item = self.tree.currentItem() # 获取当前选中的节点 if item and item.text(2) != "": param = item.text(2).split("|") if param is not None and param[2] != "WAITTING_READ": QtGui.QDesktopServices.openUrl(QtCore.QUrl(param[1])) return button = QMessageBox.warning(self, "提示", "是否前去查看?", QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok) if button == QMessageBox.Ok: # 如果确定,就打开网页 QtGui.QDesktopServices.openUrl(QtCore.QUrl(param[1])) # 发起一个Http请求告知后端该消息已被查看 if param is not None and param[2] == "WAITTING_READ": try: result = update_msg_read(param[0]) print(result) except: pass def showEvent(self, *args, **kwargs): """ 显示 1.建立socket连接 2.加载数据 3.绑定数据 :param args: :param kwargs: :return: """ if self.init == 0: # 初次加载 print("show...") self.do_fetch_data() self.lbl_usrname.setText( "%s, %s好" % (self.cur_user_t[1], MyDateInfoHelper.getTimeRange())) self.init += 1 # 累加 # 建立socket连接,开启新线程自动刷新列表 ChatNamespace.ContainerWidget = self.msglist_widget ChatNamespace.Parent = self refresh_thread = TreeRenderThread(self.cur_user_t[0]) # 传递工号 refresh_thread.breakSignal.connect(self.createmsg_list) refresh_thread.start() # 开启新线程 def createmsg_list(self, msg_info_data): """ 添加信息列表 :param msg_info_data: 消息列表 :return: """ # 先清空root根下面的所有的历史消息 self.tree.clear() # 设置根节点 self.root = QTreeWidgetItem(self.tree) # 设置根节点 self.root.setText(0, "cssrc消息盒子(未读消息)") # 设置根节点的名字 self.root.setIcon(0, QIcon("static/loc.png")) # 设置 根节点的图片 try: msg_list = msg_info_data.get('data').get('msgs') sys_list = msg_info_data.get('data').get('sys') for sys in sys_list: child = QTreeWidgetItem() child.setText(0, sys.get("sysname")) child.setIcon(0, QIcon("static/app.png")) child.setText(1, "") child.setText(2, "") # 添加到根节点上 self.root.addChild(child) # 添加二级节点 for msg in msg_list: # 将该系统下的所有的消息加载到节点上 if msg.get("from_sys") == sys.get("id"): status = msg.get("msg_status") sec_child = QTreeWidgetItem(child) # sec_child.setToolTip("") sec_child.setText(0, msg.get("msg_title")) sec_child.setText(1, msg.get("msg_push_time")) sec_child.setText( 2, str(msg.get("id")) + "|" + str(msg.get("msg_url")) + "|" + status) if status == "WAITTING_READ": sec_child.setIcon(0, QIcon("static/msg_alert.png")) else: sec_child.setIcon(0, QIcon("static/xx.png")) except Exception as e: print("解析异常") # 加载根节点的所有属性 与子控件 self.tree.addTopLevelItem(self.root) # 给节点点击添加响应事件 try: self.tree.clicked.disconnect(self.onClicked) # 先取消绑定 except: pass self.tree.clicked.connect(self.onClicked) # 节点全部展开看 self.tree.expandAll() # 添加到父容器中设置位置 self.tree.setGeometry(0, 0, 400, 580)
class Preferences(QDialog): configuration = {} weight = 0 # Signals savePreferences = pyqtSignal() def __init__(self, parent=None): super().__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(900, 600) box = QVBoxLayout(self) box.setContentsMargins(5, 5, 5, 5) # Header self._header_label = QLabel("") header_font = self._header_label.font() header_font.setBold(True) header_font.setPointSize(header_font.pointSize() + 4) self._header_label.setFont(header_font) hbox = QHBoxLayout() hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.tree.setFixedWidth(200) hbox.addWidget(self.tree) self.stacked = QStackedLayout() header_layout = QVBoxLayout() header_layout.addWidget(self._header_label) header_layout.addLayout(self.stacked) hbox.addLayout(header_layout) box.addLayout(hbox) # Footer buttons button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) box.addWidget(button_box) # Connections button_box.rejected.connect(self.close) button_box.accepted.connect(self._save_preferences) self.tree.selectionModel().currentRowChanged.connect( self._change_current) self.load_ui() @pyqtSlot() def _save_preferences(self): self.savePreferences.emit() self.close() def load_ui(self): sections = sorted( Preferences.configuration.keys(), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = subcontent.keys() for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) self.tree.expandAll() self.tree.setCurrentIndex(self.tree.model().index(0, 0)) def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) self._header_label.setText(item.text(0)) @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if subsection is None: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config
class FileExplorer(QWidget): PREVIEW_WIDTH = 450 def __init__(self, parent=None): super(FileExplorer, self).__init__(parent=parent) self.parent = parent self.new_folder_path = '' self.folder_to_filename = defaultdict(list) self.item_clicked = None self.item_selected_image = None self.image_selected_data = None self.button_add_folder = QPushButton('Add Folder', self) self.button_add_folder.clicked.connect(self.on_clicked_add_folder) self.button_remove_folder = QPushButton('Remove Folder', self) self.button_remove_folder.clicked.connect(self.on_clicked_remove_folder) self.widget_tree = QTreeWidget(self) self.widget_tree.setColumnCount(2) self.widget_tree.setHeaderLabels(['Files', 'Format']) self.widget_tree.setColumnWidth(0, 350) # self.tree.setMaximumWidth(500) self.widget_tree.itemClicked.connect(self.on_clicked_tree_item) self.item_preview = QTreeWidgetItem(self.widget_tree) self.item_preview.setText(0, 'ALL Folders') ft1 = QFont() ft1.setPointSize(15) self.label_image_preview = QLabel('No Info') self.label_image_preview.setFont(ft1) self.label_image_preview.setAlignment(Qt.AlignCenter) self.label_image_preview.setWordWrap(True) self.hbox_layout = QHBoxLayout() self.hbox_layout.addWidget(self.button_add_folder) self.hbox_layout.addWidget(self.button_remove_folder) self.grid_layout = QGridLayout() self.grid_layout.addLayout(self.hbox_layout, 0, 0, 1, 1) self.grid_layout.addWidget(self.widget_tree, 1, 0, 5, 5) self.grid_layout.addWidget(self.label_image_preview, 1, 5, 5, 5) self.setLayout(self.grid_layout) self.widget_tree.expandAll() def on_clicked_tree_item(self, item, column): from image_inpainting_demo import set_label_image self.label_image_preview.setText(item.text(column)) self.item_clicked = item # is select image if item.checkState(0) == Qt.Checked: if self.item_selected_image and self.item_selected_image is not item: self.item_selected_image.setCheckState(0, Qt.Unchecked) self.item_selected_image = item self.item_selected_image.setCheckState(0, Qt.Checked) image_path = self.item_selected_image.parent().text(0) + '/' + self.item_selected_image.text(0) print('select image path : ', image_path) # preview image new_img = Image.open(image_path) new_img = new_img.convert('RGB') self.image_selected_data = np.asarray(new_img) set_label_image(self.label_image_preview, self.PREVIEW_WIDTH, self.image_selected_data) self.parent.clip_area.set_image(self.image_selected_data) def on_clicked_add_folder(self): self.new_folder_path = QFileDialog.getExistingDirectory(self, "Add Folder", self.new_folder_path) if self.new_folder_path: if self.new_folder_path in self.folder_to_filename: QMessageBox.warning(self, 'warning', 'New folder has exist !') return print('add new folder path : ', self.new_folder_path) # add folder item folder_item = QTreeWidgetItem(self.item_preview) folder_item.setText(0, self.new_folder_path) folder_item.setText(1, 'Folder') images = os.listdir(self.new_folder_path) # filter images def is_image(path): suffix = path.split('.')[-1] if suffix in ('jpg', 'png', 'bmp', 'jpeg'): return True return False images = list(filter(is_image, images)) images.sort() self.folder_to_filename[self.new_folder_path] = images # add image item for i, image in enumerate(images): item = QTreeWidgetItem(folder_item) item.setText(0, image) item.setText(1, 'Image') item.setCheckState(0, Qt.Unchecked) def on_clicked_remove_folder(self): if self.item_clicked: if self.item_clicked.text(1) == 'Folder': if self.item_clicked.text(0) in self.folder_to_filename: if self.item_selected_image: self.item_selected_image.setCheckState(0, Qt.Unchecked) del self.folder_to_filename[self.item_clicked.text(0)] self.item_preview.removeChild(self.item_clicked) self.item_clicked = None self.item_selected_image = None self.parent.setTabEnabled(1, False) self.parent.setTabEnabled(2, False) self.parent.setTabEnabled(3, False) else: QMessageBox.warning(self, 'warning', 'only allow to remove folder !')
class MainWindow(object): def __init__(self): self.setWindowTitle("50ETF期权监控系统") self.resize(1000, 600) self.setWindowIcon(QIcon("50ETF.ico")) self.code_lbl = QLabel("代码") self.name_lbl = QLabel("名称") self.last_lbl = QLabel("现价") self.chg_lbl = QLabel("涨跌") self.pct_chg_lbl = QLabel("涨跌幅") self.open_lbl = QLabel("今开") self.high_lbl = QLabel("最高") self.low_lbl = QLabel("最低") self.vol_lbl = QLabel("成交量") self.amt_lbl = QLabel("成交额") self.time_lbl = QLabel("时间") self.code_data_lbl = QLabel("510050") self.name_data_lbl = QLabel("50ETF") self.last_data_lbl = QLabel() self.chg_data_lbl = QLabel() self.pct_chg_data_lbl = QLabel() self.open_data_lbl = QLabel() self.high_data_lbl = QLabel() self.low_data_lbl = QLabel() self.vol_data_lbl = QLabel() self.amt_data_lbl = QLabel() self.time_data_lbl = QLabel() etf_layout = QGridLayout() etf_layout.setSpacing(10) etf_layout.addWidget(self.code_lbl, 0, 0) etf_layout.addWidget(self.code_data_lbl, 1, 0) etf_layout.addWidget(self.name_lbl, 0, 1) etf_layout.addWidget(self.name_data_lbl, 1, 1) etf_layout.addWidget(self.last_lbl, 0, 2) etf_layout.addWidget(self.last_data_lbl, 1, 2) etf_layout.addWidget(self.chg_lbl, 0, 3) etf_layout.addWidget(self.chg_data_lbl, 1, 3) etf_layout.addWidget(self.pct_chg_lbl, 0, 4) etf_layout.addWidget(self.pct_chg_data_lbl, 1, 4) etf_layout.addWidget(self.open_lbl, 0, 5) etf_layout.addWidget(self.open_data_lbl, 1, 5) etf_layout.addWidget(self.high_lbl, 0, 6) etf_layout.addWidget(self.high_data_lbl, 1, 6) etf_layout.addWidget(self.low_lbl, 0, 7) etf_layout.addWidget(self.low_data_lbl, 1, 7) etf_layout.addWidget(self.vol_lbl, 0, 8) etf_layout.addWidget(self.vol_data_lbl, 1, 8) etf_layout.addWidget(self.amt_lbl, 0, 9) etf_layout.addWidget(self.amt_data_lbl, 1, 9) etf_layout.addWidget(self.time_lbl, 0, 10) etf_layout.addWidget(self.time_data_lbl, 1, 10) self.call_lbl = QLabel("认购/看涨") self.put_lbl = QLabel("认沽/看跌") option_type_layout = QHBoxLayout() option_type_layout.addWidget(self.call_lbl) option_type_layout.addWidget(self.put_lbl) self.option_data_tree = QTreeWidget() self.option_data_tree.setColumnCount(13) self.option_data_tree.setHeaderLabels([ "最新价", "涨跌幅", "成交量", "持仓量", "隐含波动率", "Delta", "行权价", "Delta", "隐含波动率", "持仓量", "成交量", "涨跌幅", "最新价" ]) self.cur_month = QTreeWidgetItem(self.option_data_tree) self.cur_month.setText(0, "当月合约") self.cur_month_strike1 = QTreeWidgetItem(self.cur_month) self.cur_month_strike2 = QTreeWidgetItem(self.cur_month) self.cur_month_strike3 = QTreeWidgetItem(self.cur_month) self.cur_month_strike4 = QTreeWidgetItem(self.cur_month) self.cur_month_strike5 = QTreeWidgetItem(self.cur_month) self.cur_month_strike6 = QTreeWidgetItem(self.cur_month) self.cur_month_strike7 = QTreeWidgetItem(self.cur_month) self.cur_month_strike8 = QTreeWidgetItem(self.cur_month) self.cur_month_strike9 = QTreeWidgetItem(self.cur_month) self.cur_month_strike10 = QTreeWidgetItem(self.cur_month) self.cur_month_strike11 = QTreeWidgetItem(self.cur_month) self.next_month = QTreeWidgetItem(self.option_data_tree) self.next_month.setText(0, "下月合约") self.next_month_strike1 = QTreeWidgetItem(self.next_month) self.next_month_strike2 = QTreeWidgetItem(self.next_month) self.next_month_strike3 = QTreeWidgetItem(self.next_month) self.next_month_strike4 = QTreeWidgetItem(self.next_month) self.next_month_strike5 = QTreeWidgetItem(self.next_month) self.next_month_strike6 = QTreeWidgetItem(self.next_month) self.next_month_strike7 = QTreeWidgetItem(self.next_month) self.next_month_strike8 = QTreeWidgetItem(self.next_month) self.next_month_strike9 = QTreeWidgetItem(self.next_month) self.next_month_strike10 = QTreeWidgetItem(self.next_month) self.next_month_strike11 = QTreeWidgetItem(self.next_month) self.follew_quar_month1 = QTreeWidgetItem(self.option_data_tree) self.follew_quar_month1.setText(0, "随后季月1") self.follew_quar_month1_strike1 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike2 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike3 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike4 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike5 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike6 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike7 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike8 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike9 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike10 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month1_strike11 = QTreeWidgetItem( self.follew_quar_month1) self.follew_quar_month2 = QTreeWidgetItem(self.option_data_tree) self.follew_quar_month2.setText(0, "随后季月2") self.follew_quar_month2_strike1 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike2 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike3 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike4 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike5 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike6 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike7 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike8 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike9 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike10 = QTreeWidgetItem( self.follew_quar_month2) self.follew_quar_month2_strike11 = QTreeWidgetItem( self.follew_quar_month2) self.option_data_tree.expandAll() option_data_layout = QVBoxLayout() option_data_layout.addWidget(self.option_data_tree) option_layout = QVBoxLayout() option_layout.addLayout(option_type_layout) option_layout.addLayout(option_data_layout) self.etf_mpl = MyMplCanvas() self.option_mpl = MyMplCanvas() self.iv_mpl = MyMplCanvas() plot_layout = QHBoxLayout() plot_layout.addWidget(self.etf_mpl) plot_layout.addWidget(self.option_mpl) plot_layout.addWidget(self.iv_mpl) main_layout = QGridLayout() main_layout.addLayout(etf_layout, 0, 0) main_layout.addLayout(option_layout, 1, 0) main_layout.addLayout(plot_layout, 2, 0) self.setLayout(main_layout) self.showMaximized()
class Shortcuts(preferences.Page): def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.searchEntry = LineEdit() self.searchEntry.setPlaceholderText(_("Search...")) layout.addWidget(self.searchEntry) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton(icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.searchEntry.textChanged.connect(self.updateFilter) self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager(win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = list(allactions.keys()) def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelerator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0) def items(self): """Yield all the items in the actions tree.""" def children(item): for i in range(item.childCount()): c = item.child(i) if c.childCount(): for c1 in children(c): yield c1 else: yield c for c in children(self.tree.invisibleRootItem()): yield c def item(self, collection, name): for item in self.items(): if item.collection.name == collection and item.name == name: return item def saveSettings(self): self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts") for item in self.items(): for scheme in self.scheme.schemes(): item.save(scheme) item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def loadSettings(self): self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes") # clear the settings in all the items for item in self.items(): item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def slotSchemeChanged(self): """Called when the Scheme combobox is changed by the user.""" for item in self.items(): item.switchScheme(self.scheme.currentScheme()) def slotCurrentItemChanged(self, item): if isinstance(item, ShortcutItem): self.edit.setText( _("&Edit Shortcut for \"{name}\"").format(name=item.text(0))) self.edit.setEnabled(True) global _lastaction _lastaction = item.name else: self.edit.setText(_("(no shortcut)")) self.edit.setEnabled(False) def import_(self, filename): from . import import_export import_export.importShortcut(filename, self, self.scheme) def export(self, name, filename): from . import import_export try: import_export.exportShortcut(self, self.scheme.currentScheme(), name, filename) except (IOError, OSError) as e: QMessageBox.critical(self, _("Error"), _( "Can't write to destination:\n\n{url}\n\n{error}").format( url=filename, error=e.strerror)) def findShortcutConflict(self, shortcut): """Find the possible shortcut conflict and return the conflict name.""" if shortcut: item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return None scheme = self.scheme.currentScheme() for i in self.items(): a = i.action(scheme) if i != item and a.shortcuts(): for s1 in a.shortcuts(): if s1.matches(shortcut) or shortcut.matches(s1): return qutil.removeAccelerator(a.text()) return None def editCurrentItem(self): item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return dlg = ShortcutEditDialog(self, self.findShortcutConflict) scheme = self.scheme.currentScheme() action = item.action(scheme) default = item.defaultShortcuts() or None if dlg.editAction(action, default): shortcuts = action.shortcuts() # check for conflicts conflicting = [] for i in self.items(): if i is not item: for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts): if s1.matches(s2) or s2.matches(s1): conflicting.append(i) if conflicting: for i in conflicting: l = i.shortcuts(scheme) for s1 in list(l): # copy for s2 in shortcuts: if s1.matches(s2) or s2.matches(s1): l.remove(s1) i.setShortcuts(l, scheme) # store the shortcut item.setShortcuts(shortcuts, scheme) self.changed.emit() def updateFilter(self): """Called when the search text changes.""" search = self.searchEntry.text() scheme = self.scheme.currentScheme() def hidechildren(item): hideparent = True for n in range(item.childCount()): c = item.child(n) if c.childCount(): # submenu item if hidechildren(c): c.setHidden(True) else: c.setHidden(False) c.setExpanded(True) hideparent = False elif isinstance(c, ShortcutItem): # shortcut item, should be the case if c.matches(scheme, search): c.setHidden(False) hideparent = False else: c.setHidden(True) return hideparent hidechildren(self.tree.invisibleRootItem())
class PFSNet(QWidget): changed = pyqtSignal() def __init__(self, id: str, window, tempName=None): super(QWidget, self).__init__() self._filename = None self._filepath = None self._tempName = tempName self._id = id layout = QHBoxLayout() self._tab = QTabWidget() self._tab.currentChanged.connect(self.changeTab) self._tab.setTabsClosable(True) self._tab.tabCloseRequested.connect(self.closeTab) layout.addWidget(self._tab) self.setLayout(layout) self._prop = QTableWidget(20, 2) self._prop.itemChanged.connect(self.propertiesItemChanged) self._prop.verticalHeader().hide() self._prop.setColumnWidth(1, 180) self._prop.setMaximumWidth(300) lv = QVBoxLayout() lv.addWidget(self._prop) self._tree = QTreeWidget() self._tree.itemClicked.connect(self.treeItemClicked) self._tree.setMaximumWidth(300) lv.addWidget(self._tree) layout.addLayout(lv) self._pages = [] self._idPage = 0 self._sm = window._sm self._window = window self._distributorId = 0 self._activityId = 0 self._relationId = 0 self._otherId = 0 self._pageId = 0 self._page = None self._elements = {} self.undoStack = QUndoStack(self) self.undoAction = self.undoStack.createUndoAction(self, "Desfazer") self.undoAction.setShortcuts(QKeySequence.Undo) self.undoAction.setIcon( QIcon.fromTheme("edit-undo", QIcon("icons/edit-undo.svg"))) self.redoAction = self.undoStack.createRedoAction(self, "Refazer") self.redoAction.setShortcuts(QKeySequence.Redo) self.redoAction.setIcon( QIcon.fromTheme("edit-redo", QIcon("icons/edit-redo.svg"))) self._pasteList = [] def tree(self): tree = QTreeWidgetItem(self._tree, ["Net " + self._id], 0) child = self._page.tree(tree) self._tree.expandAll() return tree def prepareTree(self): self._tree.clear() self.tree() def showPage(self, widget): if widget in self._pages: self._tab.setCurrentWidget(widget) else: self._tab.addTab(widget, widget.name()) self._pages.append(widget) self._tab.setCurrentWidget(widget) def removeTabWidget(self, widget): for i in range(self._tab.count()): if self._tab.widget(i) == widget: self._tab.removeTab(i) self._pages.remove(widget) def propertiesItemChanged(self, item: PFSTableValueText): if item.comparePrevious(): item.edited.emit(item) def getAllPages(self): ans = [] ans.append(self._page) aux = self._page.getAllSubPages() if len(aux) > 0: ans = ans + aux return ans def generateXml(self, xml: QXmlStreamWriter): xml.writeStartDocument() xml.writeStartElement("PetriNetDoc") xml.writeStartElement("net") xml.writeAttribute("id", self._id) pages = self.getAllPages() for p in pages: p.generateXml(xml) xml.writeEndElement() xml.writeEndElement() xml.writeEndDocument() def treeItemClicked(self, item, col): if isinstance(item, PFSTreeItem): item.clicked.emit() def createFromXml(doc: QDomDocument, window): el = doc.documentElement() nodes = el.childNodes() nets = [] for i in range(nodes.count()): node = nodes.at(i) if node.nodeName() != "net": continue if not (node.hasAttributes() and node.attributes().contains("id")): continue id = node.attributes().namedItem("id").nodeValue() net = PFSNet(id, window) nodesPage = node.childNodes() pages = [] for j in range(nodesPage.count()): nodePage = nodesPage.at(j) if nodePage.nodeName() != "page": continue page = PFSPage.createFromXml(nodePage) if page is not None: pages.append(page) if len(pages) == 0: continue aux = {} for page in pages: p = PFSPage.createFromContent(page, window._sm, net) if p is not None: i = page._ref if i is None or not i: i = "main" aux[i] = p if "main" not in aux.keys(): continue for indice, page in aux.items(): ids = page.getMaxIds() if net._activityId < ids[0] + 1: net._activityId = ids[0] + 1 if net._distributorId < ids[1] + 1: net._distributorId = ids[1] + 1 if net._relationId < ids[2] + 1: net._relationId = ids[2] + 1 if net._otherId < ids[3] + 1: net._otherId = ids[3] + 1 if net._pageId < int(page._id[1:]) + 1: net._pageId = int(page._id[1:]) + 1 if indice == "main": net._tab.blockSignals(True) net._tab.addTab(page, page.name()) net._tab.blockSignals(False) for indice2, page2 in aux.items(): elem = page2.getElementById(indice) if elem is not None: page._subRef = elem elem.setSubPage(page) page.setName("Ref_" + elem._id) break net._page = aux["main"] net._pages.append(aux["main"]) net.tree() nets.append(net) return nets def getTabName(self) -> str: if self._filename is None and self._tempName is None: ans = "New model" elif self._filename is None: ans = self._tempName else: ans = self._filename if self.undoStack.isClean(): return ans return ans + "*" def newNet(id, window, tempName="newmodel.xml"): ans = PFSNet(id, window, tempName) page = PFSPage.newPage(ans.requestId(PFSPage), window._sm, ans) ans._page = page ans._pages.append(page) ans._tab.addTab(page, page.name()) return ans def openPage(self, element): if isinstance(element, PFSPage): page = element elif isinstance(element, PFSActivity): page = element.subPage() else: return if page not in self._pages: self._tab.addTab(page, page.name()) self._pages.append(page) self._tab.setCurrentWidget(page) def createPage(self, element=None): page = PFSPage.newPage(self.requestId(PFSPage), self._sm, self, 600, 120) if element is not None and element.setSubPage(page): page.setName("Ref_" + element._id) page._subRef = element openac = PFSOpenActivity(self.requestId(PFSOpenActivity), 20, 10, 100) self.addItemNoUndo(openac, page) closeac = PFSCloseActivity(self.requestId(PFSCloseActivity), page._scene.sceneRect().width() - 20, 10, 100) self.addItemNoUndo(closeac, page) self._idPage = self._idPage + 1 self._sm.fixTransitions(page._scene) return page return None def deleteElements(self): if len(self._pages) == 0: return scene = self._tab.currentWidget()._scene itemsSeleted = scene.selectedItems() if len(itemsSeleted) == 0: if self._tab.currentWidget() == self._page: return x = PFSUndoDeletePage(self._tab.currentWidget()) self.undoStack.push(x) return itemsDeleted = [] for item in itemsSeleted: if not item.canDelete(): continue if isinstance(item, PFSNode): item.deleted.emit() itemsDeleted.append(item) if len(itemsDeleted) > 0: x = PFSUndoDelete(itemsDeleted) self.undoStack.push(x) def pasteElements(self, elements): self._pasteList = elements def pasteItems(self, pos): ans = [] aux = {} for elem in self._pasteList: if isinstance(elem, PFSRelationContent) or isinstance( elem, PFSSecondaryFlowContent): continue oldId = elem._id id = self.requestId(elem) if isinstance(elem, PFSActivityContent): e = PFSActivity.paste(elem, id, pos.x(), pos.y()) ans.append(e) aux[oldId] = e elif isinstance(elem, PFSDistributorContent): e = PFSDistributor.paste(elem, id, pos.x(), pos.y()) ans.append(e) aux[oldId] = e for elem in self._pasteList: if isinstance(elem, PFSRelationContent): oldId = elem._id id = self.requestId(elem) e = PFSRelation.paste(elem, id, pos.x(), pos.y(), aux) ans.append(e) elif isinstance(elem, PFSSecondaryFlowContent): oldId = elem._id id = self.requestId(elem) e = PFSSecondaryFlow.paste(elem, id, pos.x(), pos.y(), aux) ans.append(e) x = PFSUndoAdd(ans, self._tab.currentWidget()._scene) self.undoStack.push(x) def export(self, filename): if len(self._pages) > 1: scene = self._tab.currentWidget()._scene elif len(self._pages) == 1: scene = self._pages[0]._scene else: return if filename.endswith(".png"): PFSImage.gravaPng(scene, filename) else: PFSImage.gravaSvg(scene, filename) def addItem(self, element, page: PFSPage): if isinstance(element, PFSRelation): if isinstance(element._source, PFSActive) and isinstance( element._target, PFSActive): return False if isinstance(element._source, PFSPassive) and isinstance( element._target, PFSPassive): return False x = PFSUndoAdd([element], page._scene) self.undoStack.push(x) return True def addItemNoUndo(self, element, page: PFSPage): if isinstance(element, PFSRelation): if isinstance(element._source, PFSActive) and isinstance( element._target, PFSActive): return False if isinstance(element._source, PFSPassive) and isinstance( element._target, PFSPassive): return False page._scene.addItem(element) page._scene.update() return True def requestId(self, element): if element == PFSActivity or isinstance(element, PFSActivityContent): ans = "A" + str(self._activityId) self._activityId = self._activityId + 1 elif element == PFSDistributor or isinstance(element, PFSDistributorContent): ans = "D" + str(self._distributorId) self._distributorId = self._distributorId + 1 elif element == PFSRelation: ans = "R" + str(self._relationId) self._relationId = self._relationId + 1 elif element == PFSPage: ans = "P" + str(self._pageId) self._pageId = self._pageId + 1 else: ans = "O" + str(self._otherId) self._otherId = self._otherId + 1 return ans def changeTab(self, index: int): self._prop.clear() self._tree.clear() self.tree() if index < 0: return self._tab.widget(index)._scene.clearSelection() self._window._main.tabChanged.emit() def fillProperties(self, props): if len(props) > 0: self._prop.setRowCount(0) self._prop.setRowCount(len(props)) i = 0 for line in props: if isinstance(line[0], QTableWidgetItem): self._prop.setItem(i, 0, line[0]) else: self._prop.setCellWidget(i, 0, line[0]) if isinstance(line[1], QTableWidgetItem): self._prop.setItem(i, 1, line[1]) else: self._prop.setCellWidget(i, 1, line[1]) if isinstance(line[0], PFSTableLabelTags): self._prop.setRowHeight(i, 100) i = i + 1 def closeTab(self, ind): w = self._tab.widget(ind) self._pages.remove(w) self._tab.removeTab(ind)
class BookmarksWindow(QDialog): """ A simple UI for showing bookmarks and navigating to them. FIXME: For now, this window is tied to a particular lane. If your project has more than one lane, then each one will have it's own bookmark window, which is kinda dumb. """ def __init__(self, parent, topLevelOperatorView): super(BookmarksWindow, self).__init__(parent) self.setWindowTitle("Bookmarks") self.topLevelOperatorView = topLevelOperatorView self.bookmark_tree = QTreeWidget(self) self.bookmark_tree.setHeaderLabels( ["Location", "Notes"] ) self.bookmark_tree.setSizePolicy( QSizePolicy.Preferred, QSizePolicy.Preferred ) self.bookmark_tree.setColumnWidth(0, 200) self.bookmark_tree.setColumnWidth(1, 300) self.note_edit = QLineEdit(self) self.add_bookmark_button = QPushButton("Add Bookmark", self, clicked=self.add_bookmark) geometry = self.geometry() geometry.setSize( QSize(520, 520) ) self.setGeometry(geometry) layout = QVBoxLayout() layout.addWidget(self.bookmark_tree) layout.addWidget(self.note_edit) layout.addWidget(self.add_bookmark_button) self.setLayout(layout) self._load_bookmarks() self.bookmark_tree.setContextMenuPolicy( Qt.CustomContextMenu ) self.bookmark_tree.customContextMenuRequested.connect( self.showContextMenu ) self.bookmark_tree.itemDoubleClicked.connect(self._handle_doubleclick) def _handle_doubleclick(self, item, col): """ Navigate to the bookmark """ data = item.data(0, Qt.UserRole).toPyObject() if data is None: return (coord, notes) = data axes = self.topLevelOperatorView.InputImages.meta.getAxisKeys() axes = axes[:-1] # drop channel axes = sorted(axes) assert len(axes) == len(coord) tagged_coord = dict(list(zip(axes, coord))) tagged_location = OrderedDict(list(zip('txyzc', (0,0,0,0,0)))) tagged_location.update(tagged_coord) t = list(tagged_location.values())[0] coord3d = list(tagged_location.values())[1:4] self.parent().editor.posModel.time = t self.parent().editor.navCtrl.panSlicingViews( coord3d, [0,1,2] ) self.parent().editor.posModel.slicingPos = coord3d def showContextMenu(self, pos): item = self.bookmark_tree.itemAt(pos) data = item.data(0, Qt.UserRole).toPyObject() if data is None: return def delete_bookmark(): (coord, notes) = data bookmarks = list(self.topLevelOperatorView.Bookmarks.value) i = bookmarks.index((coord, notes)) bookmarks.pop(i) self.topLevelOperatorView.Bookmarks.setValue(bookmarks) self._load_bookmarks() menu = QMenu(parent=self) menu.addAction( QAction("Delete", menu, triggered=delete_bookmark) ) globalPos = self.bookmark_tree.viewport().mapToGlobal( pos ) menu.exec_( globalPos ) #selection = menu.exec_( globalPos ) #if selection is removeLanesAction: # self.removeLanesRequested.emit( self._selectedLanes ) def add_bookmark(self): coord_txyzc = self.parent().editor.posModel.slicingPos5D tagged_coord_txyzc = dict( list(zip('txyzc', coord_txyzc)) ) axes = self.topLevelOperatorView.InputImages.meta.getAxisKeys() axes = axes[:-1] # drop channel axes = sorted(axes) coord = tuple(tagged_coord_txyzc[c] for c in axes) notes = str(self.note_edit.text()) bookmarks = list(self.topLevelOperatorView.Bookmarks.value) bookmarks.append((coord, notes)) self.topLevelOperatorView.Bookmarks.setValue(bookmarks) self._load_bookmarks() def _load_bookmarks(self): self.bookmark_tree.clear() lane_index = self.topLevelOperatorView.current_view_index() lane_nickname = self.topLevelOperatorView.InputImages.meta.nickname or "Lane {}".format(lane_index) bookmarks = self.topLevelOperatorView.Bookmarks.value group_item = QTreeWidgetItem( self.bookmark_tree, [lane_nickname] ) for coord, notes in bookmarks: item = QTreeWidgetItem( group_item, [] ) item.setText(0, str(coord)) item.setData(0, Qt.UserRole, (coord, notes)) item.setText(1, notes) self.bookmark_tree.expandAll()
class show_help_browser(QDialog): def __init__(self, parent=None): super(show_help_browser, self).__init__(parent) self.resize(900, 600) self.setWindowTitle('Functions help') ssDir = os.path.join(HERE, "..", "_tools", "") self.setWindowIcon(QIcon(os.path.join(ssDir, 'toto.ico'))) sshFile = os.path.join(ssDir, 'TCobra.qss') with open(sshFile, "r") as fh: self.setStyleSheet(fh.read()) layout = QHBoxLayout() self.tree = QTreeWidget() layout.addWidget(self.tree) self.message = QTextBrowser() #self.message.setReadOnly(False) self.message.setOpenExternalLinks(True) layout.addWidget(self.message) self.setLayout(layout) self.initTree() self.tree.selectionModel().selectionChanged.connect( self.update_message) def initTree(self): all_dirs = dir(toto) modules = [ x for x in all_dirs if not x.startswith('_') and x != 'core' ] for module in modules: parent = QTreeWidgetItem(self.tree.invisibleRootItem()) parent.setText(0, module) fcts = dir(getattr(toto, module)) fcts = [x for x in fcts if not x.startswith('_')] for fct in fcts: child = QTreeWidgetItem(parent) child.setText(0, fct) if module == 'plugins': subs = dir(getattr(getattr(toto, module), fct)) subs = [ x.replace('_', ' ') for x in subs if not x.startswith('_') ] for sub in subs: child2 = QTreeWidgetItem(child) child2.setText(0, sub) self.tree.expandAll() self.tree.setHeaderLabel('Module') def update_message(self): item = self.tree.currentItem() if item: if item.parent(): module = item.parent().text(0) fct = item.text(0) if item.parent().parent(): fct = fct.replace(' ', '_') module0 = item.parent().parent().text(0) f = getattr(getattr(getattr(toto, module0), module), fct) else: f = getattr(getattr(toto, module), fct) mms = _str2html(inspect.getdoc(f)) self.message.setText(mms)
class Preferences(QDialog): # configuration = {} weight = 0 # savePreferences = pyqtSignal() # def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(900, 600)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) # self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) # hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) # self.tree.itemSelectionChanged.connect(self._change_current) self._btnCancel.clicked['bool'].connect(self.close) self._btnSave.clicked['bool'].connect(self._save_preferences) # self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0)) # def _save_preferences(self): self.savePreferences.emit() self.close() # def load_ui(self): sections = sorted( list(Preferences.configuration.keys()), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # #Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted(list(subcontent.keys()), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) # self.tree.expandAll() # def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) # @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if not subsection: Preferences.configuration[section] = {'widget': widget, 'weight': weight, 'text': text} else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = {'widget': widget, 'weight': weight, 'text': text} config['subsections'] = subconfig Preferences.configuration[section] = config
class May2SynthWidget(QWidget): paramChanged = pyqtSignal(Param) randomsChanged = pyqtSignal(list) activated = pyqtSignal() def __init__(self, parent): super().__init__() self.parent = parent self.synth = None self.params = [] self.selectedParam = None self.selectedSegment = None self.randoms = [] self.selectedRandom = None self.active = False self.justUpdatingRandomWidget = False self.initLayout() self.initSignals() def initLayout(self): self.mainLayout = QHBoxLayout(self) self.paramEditLayout = QVBoxLayout() self.reloadFromSynButton = QPushButton("Reload from .syn", self) self.reloadFromSynButton.setEnabled(False) self.paramEditButton = QPushButton("Edit Selected", self) self.paramEditButton.setEnabled(False) self.newSegmentButton = QPushButton("New Segment", self) self.newSegmentButton.setEnabled(False) self.paramEditLayout.addWidget(self.reloadFromSynButton) self.paramEditLayout.addWidget(self.paramEditButton) self.paramEditLayout.addWidget(self.newSegmentButton) self.mainLayout.addLayout(self.paramEditLayout) self.paramWidget = QTreeWidget(self) self.paramWidget.setHeaderHidden(True) self.paramWidget.setItemsExpandable(False) self.mainLayout.addWidget(self.paramWidget) self.randomEditLayout = QVBoxLayout() self.reshuffleButton = QPushButton("reshuffle", self) self.reshuffleButton.setEnabled(False) self.hardcopyButton = QPushButton("hardcopy", self) self.hardcopyButton.setEnabled(False) self.setFixedButton = QPushButton("fix/free all", self) self.setFixedButton.setEnabled(False) self.randomEditLayout.addWidget(self.reshuffleButton) self.randomEditLayout.addWidget(self.hardcopyButton) self.randomEditLayout.addWidget(self.setFixedButton) self.mainLayout.addLayout(self.randomEditLayout) self.randomWidget = QTableWidget(self) self.randomWidget.setColumnCount(6) self.randomWidget.verticalHeader().hide() self.mainLayout.addWidget(self.randomWidget) self.setLayout(self.mainLayout) def initSignals(self): self.paramWidget.itemClicked.connect(self.selectParam) self.paramWidget.itemDoubleClicked.connect(self.editSelectedParam) self.reloadFromSynButton.clicked.connect(self.reloadFromSyn) self.paramEditButton.clicked.connect(self.editSelectedParam) self.newSegmentButton.clicked.connect(self.newSegment) self.randomWidget.currentItemChanged.connect(self.selectRandom) self.randomWidget.itemChanged.connect(self.editRandom) self.reshuffleButton.clicked.connect(self.reshuffleRandoms) self.hardcopyButton.clicked.connect(self.hardcopySynth) self.setFixedButton.clicked.connect(self.setAllFixedOrFree) def getSynthName(self): return self.synth.name if self.synth is not None else None def setSynth(self, synth): self.synth = synth self.params = [] if self.synth is not None: for paramID in self.synth.usedParams: param = self.getParamOverride(paramID) if param is None: param = Param(self.synth.usedParams[paramID]) self.params.append(param) self.selectedParam = None self.selectedSegment = None self.updateParamWidget() self.randoms = [] if self.synth is not None: for randomID in self.synth.usedRandoms: random = self.getRandom(randomID) if random is None: random = RandomValue(self.synth.usedRandoms[randomID]) self.randoms.append(random) self.selectedRandom = None self.updateRandomWidget() ############################## PARAMS ############################### def updateParamWidget(self): self.paramWidget.clear() for param in self.params: paramItem = QTreeWidgetItem([param.__str__()]) for seg in param.segments: paramItem.addChild(QTreeWidgetItem([seg.__str__()])) self.paramWidget.addTopLevelItem(paramItem) self.paramWidget.expandAll() self.paramWidget.setStyleSheet("background-color: red;" if self. findParamSegmentCollisions() else "") self.updateParamButtons() def updateParamButtons(self): self.reloadFromSynButton.setEnabled(self.selectedParam is not None) self.paramEditButton.setEnabled(self.selectedParam is not None) self.newSegmentButton.setEnabled(self.selectedParam is not None) def selectParam(self, item, column=None): self.selectedParam = self.params[self.paramWidget.indexOfTopLevelItem( item)] if item.parent() is None: self.selectedSegment = None else: segmentIndex = self.paramWidget.indexFromItem(item).row() self.selectedSegment = self.selectedParam.getSegmentAtIndex( segmentIndex) self.updateParamButtons() def editSelectedParam(self, item=None, column=0): if self.selectedSegment is None: paramDefault, ok = QInputDialog.getDouble( self, 'Edit Parameter Default', f'Default Value for Parameter:\n{self.selectedParam.id}', self.selectedParam.default, decimals=3) if not ok: return self.selectedParam.default = paramDefault else: print(self.selectedSegment) segmentDialog = SegmentDialog(self.parent, self.selectedParam, segment=self.selectedSegment) if not segmentDialog.exec_(): return self.selectedParam.updateSegment(self.selectedSegment, segmentDialog.getSegment()) self.paramChanged.emit(self.selectedParam) self.updateParamWidget() def newSegment(self): segmentDialog = SegmentDialog(self.parent, self.selectedParam) if segmentDialog.exec_(): self.selectedParam.addSegment(segmentDialog.getSegment()) self.paramChanged.emit(self.selectedParam) self.updateParamWidget() def findParamSegmentCollisions(self): for param in self.params: if param.hasCollidingSegments(): return True return False def getParamOverride(self, paramID): return self.parent.synthModel.paramOverrides.get(paramID, None) def reloadFromSyn(self): if self.selectedParam is None: return print( "Reload From .Syn is not properly implemented yet. For now, just erase the paramOverride in the synthModel..." ) self.parent.synthModel.deleteParamOverride( self.selectedParam.id) # TODO: actually, do it via signal as well self.setSynth(self.synth) ############################## RANDOM VALUES ############################### def updateRandomWidget(self): self.randomWidget.clear() self.justUpdatingRandomWidget = True self.randomWidget.setRowCount(0) for row, random in enumerate(self.randoms): self.randomWidget.insertRow(row) for col, content in enumerate(random.getRow()): item = QTableWidgetItem(str(content)) if col == random.idColumn: item.setFlags(Qt.ItemIsEnabled) elif col == random.fixedColumn: item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setText('fixed') item.setCheckState(Qt.Checked if content else Qt.Unchecked) else: item.setFlags(Qt.ItemIsEditable | Qt.ItemIsEnabled) self.randomWidget.setItem(row, col, item) self.randomWidget.resizeColumnsToContents() self.randomWidget.setHorizontalHeaderLabels( ['ID', 'value', 'min', 'max', 'digits', 'fixed?']) self.justUpdatingRandomWidget = False self.updateRandomButtons() def updateRandomWidgetColumn(self, col): self.justUpdatingRandomWidget = True for row in range(self.randomWidget.rowCount()): item = self.randomWidget.item(row, col) newContent = self.randoms[row].getRow()[col] if col == RandomValue.fixedColumn: item.setCheckState(Qt.Checked if newContent else Qt.Unchecked) else: item.setText(str(newContent)) self.randomWidget.resizeColumnsToContents() self.justUpdatingRandomWidget = False def updateRandomButtons(self): self.reshuffleButton.setEnabled(len(self.randoms) > 0) self.hardcopyButton.setEnabled(len(self.randoms) > 0) self.setFixedButton.setEnabled(len(self.randoms) > 0) def getRandom(self, randomID): return self.parent.synthModel.randomValues.get(randomID, None) def selectRandom(self, item, prevItem=None): validItem = item is not None and len(self.randoms) > item.row() self.selectedRandom = self.randoms[item.row()] if validItem else None def editRandom(self, item): if self.justUpdatingRandomWidget: return self.selectRandom(item) if self.selectedRandom is not None: if item.column() == RandomValue.idColumn: pass elif item.column() == RandomValue.valueColumn: self.selectedRandom.value = float(item.text()) elif item.column() == RandomValue.minColumn: self.selectedRandom.min = float(item.text()) elif item.column() == RandomValue.maxColumn: self.selectedRandom.max = float(item.text()) elif item.column() == RandomValue.digitsColumn: self.selectedRandom.digits = int(item.text()) elif item.column() == RandomValue.fixedColumn: self.selectedRandom.fixed = (item.checkState() == Qt.Checked) self.randomsChanged.emit([self.selectedRandom]) def reshuffleRandoms(self): for random in self.randoms: random.reshuffle() self.randomsChanged.emit(self.randoms) self.updateRandomWidgetColumn(RandomValue.valueColumn) def hardcopySynth(self): print( "should implement this, but for now, just write the values to this terminal:" ) for random in self.randoms: print(random.getRow()) self.parent.hardcopySynth(self.synth, self.randoms) #TODO: "softcopy": connect this with storeValue def setAllFixedOrFree(self): anyFixed = any([random.fixed for random in self.randoms]) for random in self.randoms: random.fixed = not anyFixed self.updateRandomWidgetColumn(RandomValue.fixedColumn) ################################################################################ def debugOutput(self): print("RANDOM VALUES STORED IN SYNTH MODEL:") for r in self.parent.synthModel.randomValues: print(r) print("SYNTH FORMS WITH ARGUMENTS") for s in self.parent.synthModel.synths: print(s.name, ' --> ', s.args)
class ManageRooms(QWidget): """ Summary: This class will display the manage rooms window """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # TODO: Fix table so that it only has entries for how many devices are in each room # TODO: Make add and remove device functions. # TODO: Add function to count devices based on room in db_interface self.path = os.path.dirname(os.path.abspath(__file__)) os.chdir(self.path) # Connects the application to the database self.db = Database() self.db.connectToDatabase() # Initiates a layout and a tree widget self.layout = QVBoxLayout(self) self.roomTree = QTreeWidget() self.roomTree.setHeaderLabels(["Bedrooms"]) self.populateTable() self.buttonLayout = QHBoxLayout() self.addDevice = QPushButton("Add Device") self.removeButton = QPushButton("Remove Device") self.buttonLayout.addWidget(self.addDevice) self.buttonLayout.addWidget(self.removeButton) self.addDevice.clicked.connect(self.deviceAdd) self.removeButton.clicked.connect(self.deviceRemove) # Adds the dock widget to the main layout for the manage room plane self.layout.addWidget(self.roomTree) self.layout.addLayout(self.buttonLayout) def populateTable(self): """ Summary: Since this table will be updated regularly via adding and removing devices, it is given its own function which first destroys the table then rebuilds it from the top """ rooms = self.db.getRooms() self.roomTree.clear() for room in range(0, len(rooms)): roomName = rooms[room][0] root = QTreeWidgetItem(self.roomTree, [roomName]) devices = self.db.getDevices(roomName) # Adds all of the devices to the room specific tree for dev in range(0, len(devices)): deviceName = devices[dev][0] child = QTreeWidgetItem(root, [deviceName]) self.roomTree.expandAll() #///////////////////////////////////////////////////////////////////// Device add functions def deviceAdd(self): """ """ # Add to Custom Dialog class newAddition = QDialog() dialogLayout = QVBoxLayout(newAddition) # Widget for the access combo box self.accessBox = QComboBox() self.accessBox.setEditable(False) # Gets rooms from the database and adds them to the combo box rooms = self.db.getRooms() for room_index in range(0, self.db.countRooms()[0]): self.accessBox.addItem(rooms[room_index][0]) self.deviceName = QLineEdit() self.deviceImportance = QLineEdit() self.devicePurpose = QLineEdit() # Form for the user to enter in new device information formLayout = QFormLayout() formLayout.addRow(QLabel("Device Name"), self.deviceName) formLayout.addRow(QLabel("Device Importance"), self.deviceImportance) formLayout.addRow(QLabel("Device Purpose"), self.devicePurpose) formLayout.addRow(QLabel("Device Location"), self.accessBox) # Adds the okay and cancel button at the bottom QBtn = QDialogButtonBox.Ok buttonBox = QDialogButtonBox(QBtn) buttonBox.accepted.connect(self.accept) dialogLayout.addLayout(formLayout) dialogLayout.addWidget(buttonBox) newAddition.setWindowTitle("Add Device") newAddition.exec_() def accept(self): """ Summary: Loads new device information into the database """ # adds the device to the database self.db.addDevice(self.deviceName.text(), self.devicePurpose.text(), self.deviceImportance.text(), self.accessBox.currentText()) self.db.commitChanges() self.populateTable() # Logs the new addition logging.info("Added new device: {}".format(self.deviceName.text())) # Clears the from on the add button dialog self.deviceName.setText("") self.deviceImportance.setText("") self.devicePurpose.setText("") self.accessBox.setCurrentIndex(0) #///////////////////////////////////////////////////////////////////// Device Remove Functions def deviceRemove(self): """ Summary: Displays a table of ever device for users to remove """ removeDeviceDialog = QDialog() dialogLayout = QVBoxLayout(removeDeviceDialog) devices = self.db.getDevices() deviceCount = len(devices) self.removeDeviceTable = QTableWidget(self.db.countDevices()[0], 5, self) self.removeDeviceTable.setHorizontalHeaderLabels( ["Name", "Purpose", "Importance", "Location", "Remove"]) # Formats the table to fill up all avaliable space self.removeDeviceTable.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeMode(1)) self.removeDeviceTable.horizontalHeader().setSectionResizeMode( 4, QHeaderView.ResizeMode(2)) # Here is where all of the information is unpacked and inserted into the table for deviceIndex in range(0, deviceCount): deviceName = QTableWidgetItem("{}".format(devices[deviceIndex][0])) devicePurpose = QTableWidgetItem("{}".format( devices[deviceIndex][1])) deviceImportance = QTableWidgetItem("{}".format( devices[deviceIndex][2])) deviceLocation = QTableWidgetItem("{}".format( devices[deviceIndex][3])) deviceRemove = QPushButton("Kill") self.removeDeviceTable.setItem(deviceIndex, 0, deviceName) self.removeDeviceTable.setItem(deviceIndex, 1, devicePurpose) self.removeDeviceTable.setItem(deviceIndex, 2, deviceImportance) self.removeDeviceTable.setItem(deviceIndex, 3, deviceLocation) self.removeDeviceTable.setCellWidget(deviceIndex, 4, deviceRemove) deviceRemove.clicked.connect(self.killDevice) dialogLayout.addWidget(self.removeDeviceTable) removeDeviceDialog.exec_() def killDevice(self): buttonClicked = self.sender() index = self.removeDeviceTable.indexAt(buttonClicked.pos()) deviceRow = index.row() # User name is extracted from the table then removed item = self.removeDeviceTable.item(deviceRow, 0) deviceName = item.text() self.removeDeviceTable.removeRow(deviceRow) self.db.removeDevice(deviceName) self.db.commitChanges() self.populateTable()
class CenterWindow(QWidget): position_pattern = re.compile(".*?(\d+).*?(\d+).*") laster_status = 0 # 0是关闭 1是打开 biglaster_status=0 # 0是关闭 1是打开 movie_pattern = re.compile("[A-Za-z]+_(?P<time>\d+).avi") tree_firsttext_pattern = re.compile("\((.*?),(.*?)\)") def __init__(self): super().__init__() self.bag_positions_childs = [] self.setupUi() # self.dock = QDockWidget("move_direct", self) # self.dock.resize(300,300) # self.dock_img =QLabel(self.dock) # self.dock_img.resize(300,300) # self.dock.setWidget(self.dock_img) self.plchandle = PlcHandle(plc_port=PLC_COM) self.step = 20 # 默认步长 # self.process = IntelligentProcess(IMGHANDLE=None, img_play=self.final_picture_label, plchandle=self.plchandle, # error_widget=self.checkerror_widget,dock_img_player=self.dock_img) self.process = IntelligentProcess(IMGHANDLE=None, img_play=self.final_picture_label, plchandle=self.plchandle) self.process.intelligentthread.add_scan_bag_signal.connect(self.add_scan_bag) self.process.intelligentthread.move_to_bag_signal.connect(self.move_to_bag_slot) self.process.intelligentthread.error_show_signal.connect(self.show_error_info) self.process.intelligentthread.ariver_advice.connect(self.arrive_show) self.process.intelligentthread.detectorhandle.send_warn_info.connect(self.show_warn_info) self.init_button() self.positions = set() self.big = True def mousePressEvent(self, event): if event.buttons() == Qt.LeftButton: if event.buttons() == Qt.LeftButton: self.big = not self.big if not self.isMaximized(): self.showMaximized() else: self.showNormal() def setupUi(self): self.setObjectName("Form") all_layout = QHBoxLayout() # self.videoBox = QtWidgets.QGroupBox(self) # self.videoBox.setObjectName("videoBox") # all_layout.addWidget(self.videoBox) self.show_all = ShowWidget() # self.final_picture_label = QLabel(self) # self.final_picture_label.setObjectName("final_picture_label") self.final_picture_label = self.show_all.final_picture_label # video_layout = QtWidgets.QGridLayout() # video_layout.addWidget(self.show_all, 0, 0) # self.videoBox.setLayout(video_layout) all_layout.addWidget(self.show_all) # 右侧按钮操作区域 self.operatorBox = QGroupBox(self) self.operatorBox.setObjectName("operatorBox") all_layout.addWidget(self.operatorBox) operator_layout = QVBoxLayout() # 准备区 self.prepareBox = QGroupBox(self) self.prepareBox.setObjectName("prepareBox") self.prepareBox.setTitle("准备区") prepare_layout = QGridLayout() self.prepareBox.setLayout(prepare_layout) self.load_button = QPushButton(self) self.load_button.setToolTip("行车初始化") self.load_button.setText("行车加载") self.load_button.setIcon(QIcon(":icons/load.png")) self.load_button.setIconSize(QSize(40, 40)) self.load_button.setObjectName("init_button") prepare_layout.addWidget(self.load_button, *(0, 0, 1, 1)) self.open_sdkcamera_button = QPushButton(self) self.open_sdkcamera_button.setToolTip("打开摄像") self.open_sdkcamera_button.setText("打开摄像") self.open_sdkcamera_button.setIcon(QIcon(":icons/camera.png")) self.open_sdkcamera_button.setIconSize(QSize(40, 40)) # self.open_sdkcamera_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.open_sdkcamera_button.setObjectName("open_sdkcamera_button") # self.open_sdkcamera_button.setStyleSheet("border:none") prepare_layout.addWidget(self.open_sdkcamera_button, 0, 1, 1, 1) self.lamp_open_button = QPushButton(self) # self.lamp_open_button.setToolTip("打开照明灯") self.lamp_open_button.setText("打开照明灯") self.lamp_open_button.setIcon(QIcon(":icons/lamp.png")) self.lamp_open_button.setIconSize(QSize(40, 40)) # self.x_center_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.lamp_open_button.setObjectName("lamp_open_button") # self.x_center_button.setStyleSheet("border:none") prepare_layout.addWidget(self.lamp_open_button, *(0, 2, 1, 1)) self.turnon_laster_button = QPushButton(self) self.turnon_laster_button.setToolTip("开启激光灯") self.turnon_laster_button.setText("开启激光灯") self.turnon_laster_button.setIcon(QIcon(":icons/laster.png")) self.turnon_laster_button.setIconSize(QSize(40, 40)) self.turnon_laster_button.setObjectName("turnon_laster_button") prepare_layout.addWidget(self.turnon_laster_button, *(0, 3, 1, 1)) self.turnon_biglaster_button = QPushButton(self) self.turnon_biglaster_button.setToolTip("开启大射灯") self.turnon_biglaster_button.setText("开启大射灯") self.turnon_biglaster_button.setIcon(QIcon(":icons/laster.png")) self.turnon_biglaster_button.setIconSize(QSize(40, 40)) self.turnon_biglaster_button.setObjectName("turnon_biglaster_button") prepare_layout.addWidget(self.turnon_biglaster_button, *(1, 0, 1, 1)) self.speed_label = QLabel(self) self.speed_label.setText("行车速度") prepare_layout.addWidget(self.speed_label, *(2, 0, 1, 1)) # 步数设置 self.speed_slide = QSlider(Qt.Horizontal) self.speed_slide.setToolTip("设置行车速度") # 最小值 self.speed_slide.setMinimum(650) # # 设置最大值 self.speed_slide.setMaximum(950) # self.speed_slide.setSingleStep(10) self.speed_slide.setValue(700) self.speed_slide.setTickPosition(QSlider.TicksBelow) self.speed_slide.setTickInterval(100) self.speed_slide.setStyleSheet(""" QSlider:sub-page:horizontal { border: 1px solid yellow; background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 yellow, stop:1 yellow); border-radius: 3px; height: 8px; } """) prepare_layout.addWidget(self.speed_slide, 2, 1, 1, 2) self.speed_value = QLCDNumber(3, self) self.speed_value.display(700) prepare_layout.addWidget(self.speed_value, 2, 3, 1, 1) prepare_layout.setAlignment(Qt.AlignLeft) self.prepareBox.setLayout(prepare_layout) # self.prepareBox.setStyleSheet("""background: gray; color: #fff;""") # 手动区域 self.manual_operation_box = QGroupBox() self.manual_operation_box.setTitle("手动区") manual_operation_layout = QGridLayout() self.forward_button = QPushButton(self) # self.forward_button.setToolTip("向东") self.forward_button.setText("向东") # self.forward_button.setIcon(QIcon(":icons/forward.png")) self.forward_button.setIconSize(QSize(60, 60)) # self.forward_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.forward_button.setObjectName("forward_button") self.forward_button.setStyleSheet("border:none") # manual_operation_layout.addWidget(self.forward_button, *(0, 1)) manual_operation_layout.addWidget(self.forward_button, *(0, 0)) self.backward_button = QPushButton(self) self.backward_button.setText("向西") # self.backward_button.setIcon(QIcon(":icons/backward.png")) self.backward_button.setIconSize(QSize(60, 60)) # self.backward_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.backward_button.setObjectName("backward_button") self.backward_button.setStyleSheet("border:none") manual_operation_layout.addWidget(self.backward_button, *(0, 1)) # self.manual_operation_box.resize(300,300) self.left_button = QPushButton(self) self.left_button.setText("向北") # self.left_button.setIcon(QIcon(":icons/left.png")) self.left_button.setIconSize(QSize(60, 60)) # self.left_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.left_button.setObjectName("left_button") self.left_button.setStyleSheet("border:none") manual_operation_layout.addWidget(self.left_button, *(0, 2)) self.right_button = QPushButton(self) self.right_button.setText("向南") # self.right_button.setIcon(QIcon(":icons/right.png")) self.right_button.setIconSize(QSize(60, 60)) # self.right_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.right_button.setObjectName("right_button") self.right_button.setStyleSheet("border:none") manual_operation_layout.addWidget(self.right_button, *(0, 3)) self.manual_operation_box.setLayout(manual_operation_layout) # self.manual_operation_box.resize(300,300) self.up_hock_button = QPushButton(self) self.up_hock_button.setText("定位上升") # self.up_hock_button.setIcon(QIcon(":icons/up_hock.png")) self.up_hock_button.setIconSize(QSize(60, 60)) # self.up_hock_button.resize(60,60) # self.up_hock_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.up_hock_button.setObjectName("up_hock_button") self.up_hock_button.setStyleSheet("border:none") manual_operation_layout.addWidget(self.up_hock_button, *(1, 0, 1, 1)) self.down_hock_button = QPushButton(self) self.down_hock_button.setText("定位下降") # self.down_hock_button.setIcon(QIcon(":icons/down_hock.png")) self.down_hock_button.setIconSize(QSize(60, 60)) # self.down_hock_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.down_hock_button.setObjectName("down_hock_button") self.down_hock_button.setStyleSheet("border:none") manual_operation_layout.addWidget(self.down_hock_button, 1, 1, 1, 1) # self.up_cargohook_button = QPushButton(self) self.up_cargohook_button.setText("货钩上升") # self.up_cargohook_button.setIcon(QIcon(":icons/up_hock.png")) self.up_cargohook_button.setIconSize(QSize(60, 60)) # self.up_cargohook_button.resize(60,60) # self.up_cargohook_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.up_cargohook_button.setObjectName("up_cargohook_button") self.up_cargohook_button.setStyleSheet("border:none") manual_operation_layout.addWidget(self.up_cargohook_button, 1, 2, 1, 1) self.down_cargohook_button = QPushButton(self) self.down_cargohook_button.setText("货钩下降") # self.down_cargohook_button.setIcon(QIcon(":icons/down_hock.png")) self.down_cargohook_button.setIconSize(QSize(60, 60)) # self.down_cargohook_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.down_cargohook_button.setObjectName("down_cargohook_button") self.down_cargohook_button.setStyleSheet("border:none") manual_operation_layout.addWidget(self.down_cargohook_button, 1, 3, 1, 1) self.step_label = QLabel(self) self.step_label.setText("设置步长") # self.step_label.setStyleSheet(""" # color: rgb(0,0,255); # # """) manual_operation_layout.addWidget(self.step_label, *(2, 0, 1, 1)) self.step_slide = QSlider(Qt.Horizontal) self.step_slide.setToolTip("设置步数") self.step_slide.setMinimum(0) self.step_slide.setMaximum(200) self.step_slide.setSingleStep(10) self.step_slide.setValue(20) self.step_slide.setTickPosition(QSlider.TicksBelow) self.step_slide.setTickInterval(50) self.step_slide.setStyleSheet(""" QSlider:sub-page:horizontal { border: 1px solid yellow; background:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 yellow, stop:1 yellow); border-radius: 3px; height: 8px; } """) manual_operation_layout.addWidget(self.step_slide, *(2, 1, 1, 2)) self.step_value = QLCDNumber(3, self) self.step_value.display(20) manual_operation_layout.addWidget(self.step_value, *(2, 3, 1, 1)) self.manual_operation_box.setLayout(manual_operation_layout) # self.manual_operation_box.setStyleSheet("""background: gray; color: #fff;""") # 执行区域 self.carryout_box = QGroupBox() self.carryout_box.setTitle("扫描区") carryout_layout = QVBoxLayout(self) carryout_horizotal_layout = QGridLayout(self) self.zero_button = QPushButton(self) self.zero_button.setText("重置") self.zero_button.setObjectName("zero_button") carryout_horizotal_layout.addWidget(self.zero_button, 0, 0, 1, 1) self.clear_button = QPushButton(self) self.clear_button.setText("清零") self.clear_button.setObjectName("zero_button") carryout_horizotal_layout.addWidget(self.clear_button, 0, 1, 1, 1) self.stop_button = QPushButton(self) self.stop_button.setText("急停") self.stop_button.setObjectName("stop_button") carryout_horizotal_layout.addWidget(self.stop_button, 0, 2, 1, 1) self.scan_button = QPushButton(self) self.scan_button.setText("自动扫描袋子") self.scan_button.setObjectName("zero_button") carryout_horizotal_layout.addWidget(self.scan_button, 1, 0, 1, 1) self.scan_handmove_button = QPushButton(self) self.scan_handmove_button.setText("手动扫描袋子") self.scan_handmove_button.setObjectName("zero_button") carryout_horizotal_layout.addWidget(self.scan_handmove_button, 1, 1, 1, 1) self.clean_bags_button = QPushButton(self) self.clean_bags_button.setText("清空袋子坐标") self.clean_bags_button.setObjectName("clean_bags_button") carryout_horizotal_layout.addWidget(self.clean_bags_button, 1, 2, 1, 1) carryout_layout.addLayout(carryout_horizotal_layout) self.carryout_box.setLayout(carryout_layout) self.moveandput_box = QGroupBox() self.moveandput_box.setTitle("搬运区") moveandput_layout = QGridLayout() self.build_bagpositions_tree() moveandput_layout.addWidget(self.position_tree, 0, 0, 4, 3) self.giveup_close_pushbutton = QPushButton(self) self.giveup_close_pushbutton.setText("放弃抓取") # self.grab_bag_pushbutton.setIcon(QIcon(":icons/grab.png")) self.giveup_close_pushbutton.setIconSize(QSize(60, 60)) self.giveup_close_pushbutton.setObjectName("grab_bag_pushbutton") self.giveup_close_pushbutton.setStyleSheet("border:none") moveandput_layout.addWidget(self.giveup_close_pushbutton, 4, 0, 1, 1) # 抓取袋子 self.grab_bag_pushbutton = QPushButton(self) self.grab_bag_pushbutton.setText("抓取袋子") # self.grab_bag_pushbutton.setIcon(QIcon(":icons/grab.png")) self.grab_bag_pushbutton.setIconSize(QSize(60, 60)) self.grab_bag_pushbutton.setObjectName("grab_bag_pushbutton") self.grab_bag_pushbutton.setStyleSheet("border:none") moveandput_layout.addWidget(self.grab_bag_pushbutton, 4, 1, 1, 1) # 放下袋子按钮 self.putdown_bag_pushbutton = QPushButton(self) self.putdown_bag_pushbutton.setText("放下袋子") # self.putdown_bag_pushbutton.setIcon(QIcon(":icons/putdown.png")) self.putdown_bag_pushbutton.setIconSize(QSize(60, 60)) self.putdown_bag_pushbutton.setObjectName("putdown_bag_pushbutton") self.putdown_bag_pushbutton.setStyleSheet("border:none") moveandput_layout.addWidget(self.putdown_bag_pushbutton, 4, 2, 1, 1) self.moveandput_box.setLayout(moveandput_layout) operator_layout.addWidget(self.prepareBox) operator_layout.addWidget(self.manual_operation_box) operator_layout.addWidget(self.carryout_box) operator_layout.addWidget(self.moveandput_box) # operator_layout.addWidget(self.check_error_box) self.operatorBox.setLayout(operator_layout) # self.operatorBox.setStyleSheet("""background: gray; color: #fff;""") self.setStyleSheet(""" QPushButton { height: 37px; } """) # all_layout.setStretch(0, 2) all_layout.setStretch(0, 7) all_layout.setStretch(1, 3) self.setLayout(all_layout) self.retranslateUi() # 构建视频树形列表 def build_bagpositions_tree(self): self.position_tree = QTreeWidget() self.position_tree.setHeaderLabels(['袋子坐标', '抵达状态', '抓取状态']) self.position_tree.setColumnCount(3) self.position_tree.setColumnWidth(0, 150) self.position_tree.setColumnWidth(1, 150) self.position_tree.setColumnWidth(2, 150) self.saved_root = QTreeWidgetItem(self.position_tree) self.saved_root.setText(0, "点击执行") # self.saved_root.setText(1, "点击执行") self.position_tree.clicked.connect(self.onTreeClicked) self.position_tree.expandAll() def retranslateUi(self): self.setWindowTitle("视频识别机械手") self.operatorBox.setTitle("操作区域") # self.videoBox.setTitle(_translate("MainWindow", "视频区域")) def turn_on_off_biglaster(self): if self.biglaster_status == 1: self.biglaster_status = 0 self.turnon_biglaster_button.setIcon(QIcon(":icons/turnoff.png")) self.turnon_biglaster_button.setText('关闭激光灯') self.turnon_biglaster_button.setToolTip("关闭激光灯") # self.plchandle.laster = 0 self.plchandle.biglaster = 0 self.process.intelligentthread.detectorhandle.laster_status = False else: self.biglaster_status = 1 self.plchandle.biglaster = 1 self.turnon_biglaster_button.setIcon(QIcon(":icons/laster.png")) self.turnon_biglaster_button.setText('打开激光灯') self.turnon_biglaster_button.setToolTip("打开激光灯") self.process.intelligentthread.detectorhandle.laster_status = True # 打开或关闭激光灯 def turn_on_off_laster(self): if self.laster_status == 1: self.laster_status = 0 self.turnon_laster_button.setIcon(QIcon(":icons/turnoff.png")) self.turnon_laster_button.setText('关闭激光灯') self.turnon_laster_button.setToolTip("关闭激光灯") self.plchandle.laster = 0 # self.plchandle.biglaster = 0 self.process.intelligentthread.detectorhandle.laster_status = False else: self.laster_status = 1 self.turnon_laster_button.setIcon(QIcon(":icons/laster.png")) self.turnon_laster_button.setText('打开激光灯') self.turnon_laster_button.setToolTip("打开激光灯") self.plchandle.laster = 1 self.process.intelligentthread.detectorhandle.laster_status = True def arrive_show(self, X, Y): info = "->->->已经抵达该袋子,坐标X:{},Y:{}".format(X, Y) self.show_all.workrecord.append(info) for item in self.bag_positions_childs: self.saved_root.removeChild(item) self.bag_positions_childs.clear() X, Y = int(X), int(Y) for index, point in enumerate(self.bagpositions): child = QTreeWidgetItem(self.saved_root) child.setText(0, "({},{})".format(point[0], point[1])) if abs(X - point[0]) < 20 and abs(Y - point[1]) < 20: child.setText(1, "已抵达") else: child.setText(1, "未抵达") child.setText(2, "未抓取") self.bag_positions_childs.append(child) # ------------------------------------------------ # show_warn_info # 功能:展示所有异常 # 状态:在用 # 参数: [wraninfo] ---警告信息 # 返回: [None] ---无 # 作者:王杰 2020-7-* # ------------------------------------------------ def show_warn_info(self, wraninfo): infoBox = QMessageBox() infoBox.setIcon(QMessageBox.Information) infoBox.setText(wraninfo) infoBox.setWindowTitle("提示") infoBox.setStandardButtons(QMessageBox.Ok) infoBox.button(QMessageBox.Ok).animateClick(1 * 1000) # 3秒自动关闭 infoBox.exec_() def move_to_bag_slot(self, position): self.show_all.workrecord.append("\n") self.show_all.workrecord.append("命令移到行车到指定位置:({},{})".format(position[0], position[1])) # ------------------------------------------------ # show_error_info # 功能:展示所有错误 # 状态:在用 # 参数: [None] --- # 返回: [None] --- # 作者:王杰 2020-7-* # ------------------------------------------------ def show_error_info(self, error_info): # self.show_all.text.clear() if 'south_north' in error_info: SOUTH_NORTH_SERVER_FLAG = error_info['south_north'] # self.show_all.text.append( # '南北伺服报警' if SOUTH_NORTH_SERVER_FLAG is not None and SOUTH_NORTH_SERVER_FLAG == 1 else "南北伺服正常") if SOUTH_NORTH_SERVER_FLAG == 1: self.show_all.south_north_server.setIcon(QIcon(":icons/sifu1.png")) if 'south' in error_info: SOUTH_LIMIT_FLAG = error_info['south'] # self.show_all.text.append( # '->->->南限位报警' if SOUTH_LIMIT_FLAG is not None and SOUTH_LIMIT_FLAG == 1 else '->->->南限位正常') if SOUTH_LIMIT_FLAG == 1: self.show_all.south_xianwei.setIcon(QIcon(":icons/xianweiqi1.png")) if 'north' in error_info: NORTH_LIMIT_FLAG = error_info['north'] # self.show_all.text.append( # '->->->北限位报警' if NORTH_LIMIT_FLAG is not None and NORTH_LIMIT_FLAG == 1 else '->->->北限位正常') if NORTH_LIMIT_FLAG == 1: self.show_all.north_xianwei.setIcon(QIcon(":icons/xianweiqi1.png")) if 'east_server' in error_info: EAST_SERVER_FLAG = error_info['east_server'] # self.show_all.text.append( # '东伺服报警' if EAST_SERVER_FLAG is not None and EAST_SERVER_FLAG == 1 else '东伺服正常') if EAST_SERVER_FLAG == 1: self.show_all.east_server.setIcon(QIcon(":icons/sifu1.png")) if 'east' in error_info: EAST_LIMIT_FLAG = error_info['east'] # self.show_all.text.append( # '->->->东限位报警' if EAST_LIMIT_FLAG is not None and EAST_LIMIT_FLAG == 1 else '->->->东限位正常') if EAST_LIMIT_FLAG == 1: self.show_all.east_xianwei.setIcon(QIcon(":icons/xianweiqi1.png")) if 'west_server' in error_info: WEST_SERVER_FLAG = error_info['west_server'] # self.show_all.text.append( # '西伺服报警' if WEST_SERVER_FLAG is not None and WEST_SERVER_FLAG == 1 else '西伺服正常') if WEST_SERVER_FLAG is not None and WEST_SERVER_FLAG == 1: self.show_all.west_server.setIcon(QIcon(":icons/sifu1.png")) if 'west' in error_info: WEST_LIMIT_FLAG = error_info['west'] # self.show_all.text.append( # '->->->西限位报警' if WEST_LIMIT_FLAG is not None and WEST_LIMIT_FLAG == 1 else '->->->西限位正常') if WEST_LIMIT_FLAG == 1: self.show_all.west_xianwei.setIcon(QIcon(":icons/xianweiqi1.png")) # 跳闸报警 if 'sourth_north_server_trip_warn' in error_info: sourth_north_server_trip_warn = error_info['sourth_north_server_trip_warn'] # self.show_all.text.append( # '南北伺服跳闸' if sourth_north_server_trip_warn is not None and sourth_north_server_trip_warn == 1 else '南北伺服通电正常') if sourth_north_server_trip_warn == 1: self.show_all.south_north_server_trip.setIcon(QIcon(":icons/sifu1.png")) if 'east_west_server1_trip_warn' in error_info: east_west_server1_trip_warn = error_info['east_west_server1_trip_warn'] # self.show_all.text.append( # '东西伺服1跳闸' if east_west_server1_trip_warn is not None and east_west_server1_trip_warn == 1 else '东西伺服1通电正常') if east_west_server1_trip_warn == 1: self.show_all.eastwest_server1_trip.setIcon(QIcon(":icons/dianzha1.png")) if 'east_west_server2_trip_warn' in error_info: east_west_server2_trip_warn = error_info['east_west_server2_trip_warn'] # self.show_all.text.append( # '东西伺服2跳闸' if east_west_server2_trip_warn is not None and east_west_server2_trip_warn == 1 else '东西伺服2通电正常') if east_west_server2_trip_warn == 1: self.show_all.eastwest_server2_trip.setIcon(QIcon(":icons/dianzha1.png")) # ------------------------------------------------ # 名称:init_button # 功能:初始化所有的按钮 # 状态:在用 # 参数: [None] --- # 返回: [None] --- # 作者:王杰 2020-7-01 # ------------------------------------------------ def init_button(self): self.load_button.clicked.connect(self.load_plc_module) self.open_sdkcamera_button.clicked.connect(self.open_haikang_camera) self.lamp_open_button.clicked.connect(self.open_lamp) self.turnon_laster_button.clicked.connect(self.turn_on_off_laster) self.turnon_biglaster_button.clicked.connect(self.turn_on_off_biglaster) # self.save_video_button.clicked.connect(self.save_video) self.speed_slide.valueChanged.connect(self.speed_change) self.forward_button.clicked.connect(self.forward) self.backward_button.clicked.connect(self.backward) self.left_button.clicked.connect(self.left) self.right_button.clicked.connect(self.right) self.up_hock_button.clicked.connect(self.up_hock) self.down_hock_button.clicked.connect(self.down_hock) self.up_cargohook_button.clicked.connect(self.up_cargohook) self.down_cargohook_button.clicked.connect(self.down_cargohook) self.step_slide.valueChanged.connect(self.step_change) self.zero_button.clicked.connect(self.reset_plc) self.clear_button.clicked.connect(self.clear_plc) self.stop_button.clicked.connect(self.quickly_stop_work) self.scan_button.clicked.connect(self.scan_bags) self.scan_handmove_button.clicked.connect(self.scan_bag_byhand) self.clean_bags_button.clicked.connect(self.clean_bag_positions) self.giveup_close_pushbutton.clicked.connect(self.giveup_close_bag) self.grab_bag_pushbutton.clicked.connect(self.grab_bag) self.putdown_bag_pushbutton.clicked.connect(self.putdown_bag) # -------------------------------------------------------------------------------- # 方法名:clean_bag_positions # 用途:清除上依次检索的袋子坐标 # 参数:---None------- # 作者:王杰 # --------------------------------------------------------------------------------# def clean_bag_positions(self): for item in self.bag_positions_childs: self.saved_root.removeChild(item) self.process.intelligentthread.detectorhandle.bags.clear() self.process.intelligentthread.detectorhandle.bag_detect.bags.clear() self.process.intelligentthread.detectorhandle.temp_bag_positions.clear() self.process.intelligentthread.detectorhandle.hock_detect.has_stable = False def scan_bag_byhand(self): self.handmove_window = ScanBagByHandWindow(self.process) self.handmove_window.show() def add_scan_bag(self, bagpositions: list): for item in self.bag_positions_childs: self.saved_root.removeChild(item) self.show_all.workrecord.clear() self.show_all.workrecord.append("扫描到的袋子坐标为:") self.bagpositions = bagpositions for index, point in enumerate(bagpositions): child = QTreeWidgetItem(self.saved_root) child.setText(0, "({},{})".format(point[0], point[1])) child.setText(1, "未抵达") child.setText(2, "未抓取") self.bag_positions_childs.append(child) self.show_all.workrecord.append("->->->第{}个袋子坐标为:({},{})".format(index + 1, point[0], point[1])) def giveup_close_bag(self): print("stop") self.process.intelligentthread.detectorhandle.keep_y_move = False self.process.intelligentthread.detectorhandle.keep_x_move = False self.process.intelligentthread.move_close = False if self.process.intelligentthread.target_bag_position is not None or len( self.process.intelligentthread.target_bag_position) > 0: self.process.intelligentthread.detectorhandle.bags.clear() self.process.intelligentthread.detectorhandle.bag_detect.bags.clear() self.process.intelligentthread.detectorhandle.temp_bag_positions.clear() self.process.intelligentthread.detectorhandle.hock_detect.has_stable = False def grab_bag(self): # TODO 抓取袋子 if self.process.intelligentthread.move_to_bag_x == False and self.process.intelligentthread.move_to_bag_y == False: self.process.intelligentthread.grab_bag = True QMessageBox.about(self, '提示', '抓取成功!') else: QMessageBox.about(self, '错误提示', '还未到达袋子,无法执行放下指令!') # TODO 放下袋子 def putdown_bag(self): if self.process.intelligentthread.grab_bag == True and self.process.intelligentthread.putdown_bag == False: # TODO 袋子区域计算是实时的,也是十分无序的,想一个完全之策 # TODO 计算放置袋子的X,Y坐标,以及需要摆放的层数 # TODO 计算当前袋子与放置坐标的距离 # TODO 计算最高障碍物高度(不一定准确),让钩子吊着袋子顺利过去 # TODO 位移到摆放区域X,Y 向下落钩,直到拉力传感器数值为0,控制PLC释放袋子 self.process.intelligentthread.putdown_bag = True else: QMessageBox.about(self, '错误提示', '抓取袋子还未成功,无法执行放下指令!') # ------------------------------------------------ # 名称:save_video # 功能:录制视频 # 状态:在用 # 参数: [None] --- # 返回: [None] --- # 作者:王杰 2020-7-23 # ------------------------------------------------ def save_video(self): if self.process is not None and self.process.intelligentthread is not None and \ self.process.intelligentthread.play == True: self.process.intelligentthread.save_video = True # ------------------------------------------------ # 名称:open_haikang_camera # 功能:打开海康摄像头 # 状态:在用 # 参数: [None] # 返回: [None] # 作者:王杰 2020-7-02 # ------------------------------------------------ def open_haikang_camera(self): try: imagehandle = ImageProvider() self.process.IMGHANDLE = imagehandle if self.process.IMGHANDLE: self.process.IMGHANDLE = imagehandle self.process.intelligentthread.play = True self.process.intelligentthread.start() except Exception as e: QMessageBox.about(self, '警告信息', '打开失败') # ------------------------------------------------ # 名称:scan # 功能:扫描袋子 # 状态:在用 # 参数: [None] # 返回: [None] # 作者:王杰 2020-7-01 # ------------------------------------------------ def scan_bags(self): scan_status = self.process.intelligentthread.scan_bag self.process.intelligentthread.detectorhandle.bags.clear() self.process.intelligentthread.detectorhandle.bag_detect.bags.clear() self.process.intelligentthread.detectorhandle.temp_bag_positions.clear() if scan_status == False: self.process.plchandle.go_and_back() self.scan_button.setIcon(QIcon(":icons/stop_scan.png")) self.scan_button.setText('停止扫描') self.scan_button.setToolTip("停止扫描") self.process.intelligentthread.detectorhandle.hock_detect.has_stable = False else: self.scan_button.setIcon(QIcon(":icons/scan.png")) self.scan_button.setText('扫描袋子') self.scan_button.setToolTip("扫描袋子") self.process.intelligentthread.scan_bag = not scan_status def step_change(self): value = self.step_slide.value() self.step = value self.step_value.display(value) def speed_change(self): value = self.speed_slide.value() self.plchandle.speed = value self.speed_value.display(value) # ------------------------------------------------ # 名称:forward # 功能:向前移动 # 状态:在用 # 参数: [None] # 返回: [None] # 作者:王杰 2020-7-1 # ------------------------------------------------ def forward(self): self.process.move(east=self.step) # ------------------------------------------------ # 名称:backward # 功能:向后移动 # 状态:在用 # 参数: [None] # 返回: [None] # 作者:王杰 2020-7-1 # ------------------------------------------------ def backward(self): self.process.move(west=self.step) # ------------------------------------------------ # 名称:left # 功能:向左移动 # 状态:在用 # 参数: [None] --- # 返回: [None] --- # 作者:王杰 2020-7-1 # ------------------------------------------------ def left(self): self.process.move(nourth=self.step) # ------------------------------------------------ # 名称:right # 功能:向左移动 # 状态:在用 # 参数: [None] --- # 返回: [None] --- # 作者:王杰 2020-7-1 # ------------------------------------------------ def right(self): self.process.move(south=self.step) # ------------------------------------------------ # 名称:load_plc_module # 功能:开启plc梯形图 # 状态:在用 # 参数: [None] --- # 返回: [None] --- # 作者:王杰 2020-7-1 # ------------------------------------------------ def load_plc_module(self): reply = QMessageBox.information(self, # 使用infomation信息框 "加载", "加载系统启动参数", QMessageBox.Yes | QMessageBox.No) finish = reload() if reply == QMessageBox.Yes: self.process.switch_power() QMessageBox.about(self, '反馈', '已重新加载系统参数') # ------------------------------------------------ # 名称:open_lamp # 功能:打开照明灯 # 状态:在用 # 参数: [None] --- # 返回: [None] --- # 作者:王杰 2020-7-1 # ------------------------------------------------ def open_lamp(self): # reply = QMessageBox.information(self, # 使用infomation信息框 # "准备工作", # "钩子移动到X轴中心", # QMessageBox.Yes | QMessageBox.No) # if reply == QMessageBox.Yes: # self.process.turnon_lamp() # QMessageBox.about(self, '反馈', '已置中') self.process.turnon_lamp() def check_test_status(self): self.test_status_edit.setText('测试' if DEBUG else "正式") def check_plc_status(self): ''' 检测plc状态 ''' print(self.plchandle.is_open()) self.plc_status_edit.setText('连接' if self.plchandle.is_open() else "断开") def check_ladder_status(self): '''检测梯形图开启状态''' self.ladder_edit.setText('启动' if self.plchandle.power else "未开启") def onTreeClicked(self, qmodeLindex): item = self.position_tree.currentItem() self.process.intelligentthread.detectorhandle.hock_detect.has_stable = False match_result = re.match(self.position_pattern, item.text(0)) try: if match_result is not None: QMessageBox.about(self, '反馈', '定位坐标({},{})'.format(match_result.group(1), match_result.group(2))) self.process.intelligentthread.target_bag_position = [match_result.group(1), match_result.group(2)] self.process.intelligentthread.move_close = True self.process.intelligentthread.move_to_bag_x = True self.process.intelligentthread.move_to_bag_y = True except: print("not match") def play(self): '''开始播放''' if self.process.IMGHANDLE: self.process.intelligentthread.play = True self.process.intelligentthread.start() else: QMessageBox.warning(self, "警告", self.tr("还没有开启摄像头或者选择播放视频!")) print("关闭") def step_to_millsecond(self): # 20cm/1000ms speed = 20 / 1000 millseconds = int(self.step / speed) return millseconds # 定位钩上升 def up_hock(self): # self.final_picture_label.resize(IMG_WIDTH, IMG_HEIGHT) millseconds = self.step_to_millsecond() self.process.move(up=millseconds) # 定位钩下降 def down_hock(self): # self.final_picture_label.resize(IMG_WIDTH, IMG_HEIGHT) millseconds = self.step_to_millsecond() self.process.move(down=millseconds) # 货钩上升 def up_cargohook(self): # self.final_picture_label.resize(IMG_WIDTH, IMG_HEIGHT) millseconds = self.step_to_millsecond() self.process.move(up_cargohook=millseconds) # 货钩下降 def down_cargohook(self): # self.final_picture_label.resize(IMG_WIDTH, IMG_HEIGHT) millseconds = self.step_to_millsecond() self.process.move(down_cargohook=millseconds) def startwork(self): self.process.intelligentthread.work = True try: if self.process.IMGHANDLE is not None: self.process.intelligentthread.play = True self.process.intelligentthread.start() else: imagehandle = ImageProvider(videofile=None) self.process.IMGHANDLE = imagehandle if self.process.IMGHANDLE: self.process.IMGHANDLE = imagehandle self.process.intelligentthread.play = True self.process.intelligentthread.start() except: QMessageBox.warning(self, "警告", self.tr("您只是在模拟行车软件,因为没有连接行车摄像头!")) def init_process_status_show(self): pass # 启动行车梯形图 def switch_power(self): print("切换梯形图power") self.process.switch_power() def quickly_stop_work(self): self.process.quickly_stop_work() def re_work(self): self.process.re_work() # QMessageBox.about(self, '反馈', '紧急停止,防止行车越界') def reset_plc(self): ''' PLC复位 :return: ''' self.process.resetplc() QMessageBox.about(self, '反馈', '重置PLC') def clear_plc(self): ''' PLC清零 ''' self.process.clear_plc() def save_video(self): ''' 留存,数据处理留存 :return: ''' self.process.save_video() def stop(self): '''暂停摄像机''' print("关闭摄像") self.process.intelligentthread.play = False self.process.intelligentthread.move_to_bag_x = False self.process.intelligentthread.move_to_bag_y = False self.process.intelligentthread.scan_bag = False self.process.intelligentthread.detectorhandle.hock_detect.has_stable = False def fresh_all(self): self.check_test_status() self.check_plc_status() self.check_ladder_status()
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.dbm_obj = Dbm() self.curFile = '' self.textEdit = QTextEdit() self.sectionTreeWidget = QTreeWidget() self.notesListWidget = QListWidget() self.createHorizontalGroupBox() self.setCentralWidget(self.horizontalGroupBox) self.createActions() self.createMenus() # self.createToolBars() self.createStatusBar() self.readSettings() [self.hierarchy_dict, self.notebook_dict, self.section_dict, self.page_dict] = [{}, {}, {}, {}] self.setCurrentFile('') # For binding slots and signals self.fetchPageThread = FetchPage() self.fetchPageThread.setObjectName('fetchPageThread') self.syncAllThread = SyncAllThread() self.syncAllThread.setObjectName('syncAllThread') self.textEdit.document().contentsChanged.connect(self.documentWasModified) self.sectionTreeWidget.setObjectName("sectionTreeWidget") self.notesListWidget.setObjectName("notesListWidget") QMetaObject.connectSlotsByName(self) self.readDB() @pyqtSlot() def on_sectionTreeWidget_itemSelectionChanged(self): for x in self.sectionTreeWidget.selectedItems(): if x.text(1) in self.section_dict.keys(): self.populate_notes_list(x.parent().text(1), x.text(1)) @pyqtSlot() def on_notesListWidget_itemSelectionChanged(self): for x in self.notesListWidget.selectedItems(): self.fetchPageThread.fetchSignal.connect(self.on_fetchPageThread_fetchComplete) self.titleLabel.setText("Syncing") self.statusBar().showMessage("Syncing") # self.fetchPageThread.fetchSignal.connect(lambda:self.view.setHtml("<body>hello world</body>")) self.fetchPageThread.fetch(self.page_dict[x.data(1)]) def on_fetchPageThread_fetchComplete(self, string): self.view.setHtml(string) self.titleLabel.setText(self.view.title()) self.statusBar().showMessage("Page fetched") def on_syncAllThread_syncComplete(self, dbm): self.dbm_obj = dbm self.statusBar().showMessage("Sync complete") def createHorizontalGroupBox(self): self.horizontalGroupBox = QGroupBox() layout = QHBoxLayout() self.sectionTreeWidget.setHeaderHidden(1) layout.addWidget(self.sectionTreeWidget, 0) self.sectionTreeWidget.setStyleSheet("background-color: rgb(215,227,229)") self.notesListWidget.setWindowTitle('Notes') layout.addWidget(self.notesListWidget, 0) self.notesListWidget.setStyleSheet("QListWidget {background-color: rgb(196,226,233)}") subVBox = QGroupBox() vLayout = QVBoxLayout() self.titleLabel = QLabel() vLayout.addWidget(self.titleLabel, 0) self.view = QWebView() vLayout.addWidget(self.view, 1) subVBox.setLayout(vLayout) layout.addWidget(subVBox, 1) self.horizontalGroupBox.setLayout(layout) def closeEvent(self, event): if self.maybeSave(): self.writeSettings() event.accept() else: event.ignore() def newFile(self): self.readDB() # if self.maybeSave(): # self.textEdit.clear() # self.setCurrentFile('') def open(self): if self.maybeSave(): fileName, _ = QFileDialog.getOpenFileName(self) if fileName: self.loadFile(fileName) def save(self): if self.curFile: return self.saveFile(self.curFile) return self.saveAs() def saveAs(self): fileName, _ = QFileDialog.getSaveFileName(self) if fileName: return self.saveFile(fileName) return False def on_sectionList_selection_changed(self): print('selected item index changed '), def populate_section_list(self, hierarchy, notebook_dict, section_dict): self.sectionTreeWidget.clear() for notebook_id in hierarchy.keys(): notebook_sectionTreeWidget = QTreeWidgetItem(self.sectionTreeWidget, [notebook_dict[notebook_id].name, notebook_id]) for section_id in hierarchy[notebook_id].keys(): QTreeWidgetItem(notebook_sectionTreeWidget, [section_dict[section_id].name, section_id]) self.sectionTreeWidget.show() self.sectionTreeWidget.expandAll() def populate_notes_list(self, notebook_id, section_id): self.notesListWidget.clear() for page_id in self.hierarchy_dict[notebook_id][section_id]: item = QListWidgetItem(self.page_dict[page_id].title, self.notesListWidget) item.setData(1, QVariant(page_id)) def readDB(self): self.dbm_obj.read() [self.hierarchy_dict, self.notebook_dict, self.section_dict, self.page_dict] = self.dbm_obj.get_hierarchy_dict() self.populate_section_list(self.hierarchy_dict, self.notebook_dict, self.section_dict) def sync(self): self.syncAllThread.syncCompleteSignal.connect(self.on_syncAllThread_syncComplete) self.statusBar().showMessage("Syncing") self.syncAllThread.sync() def about(self): QMessageBox.about(self, "About Application", "The <b>Application</b> example demonstrates how to write " "modern GUI applications using Qt, with a menu bar, " "toolbars, and a status bar.") def documentWasModified(self): self.setWindowModified(self.textEdit.document().isModified()) def createActions(self): root = QFileInfo(__file__).absolutePath() self.newAct = QAction(QIcon(root + '/images/new.png'), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openAct = QAction(QIcon(root + '/images/open.png'), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.saveAct = QAction(QIcon(root + '/images/save.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction("Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.syncAct = QAction("S&ync", self, statusTip="Sync everything", triggered=self.sync) self.readDBAct = QAction("Read DB", self, statusTip="Read stored DB", triggered=self.readDB) self.exitAct = QAction("E&xit", self, shortcut="Ctrl+Q", statusTip="Exit the application", triggered=self.close) self.cutAct = QAction(QIcon(root + '/images/cut.png'), "Cu&t", self, shortcut=QKeySequence.Cut, statusTip="Cut the current selection's contents to the clipboard", triggered=self.textEdit.cut) self.copyAct = QAction(QIcon(root + '/images/copy.png'), "&Copy", self, shortcut=QKeySequence.Copy, statusTip="Copy the current selection's contents to the clipboard", triggered=self.textEdit.copy) self.pasteAct = QAction(QIcon(root + '/images/paste.png'), "&Paste", self, shortcut=QKeySequence.Paste, statusTip="Paste the clipboard's contents into the current selection", triggered=self.textEdit.paste) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) self.aboutQtAct = QAction("About &Qt", self, statusTip="Show the Qt library's About box", triggered=QApplication.instance().aboutQt) self.cutAct.setEnabled(False) self.copyAct.setEnabled(False) self.textEdit.copyAvailable.connect(self.cutAct.setEnabled) self.textEdit.copyAvailable.connect(self.copyAct.setEnabled) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addAction(self.syncAct) self.fileMenu.addAction(self.readDBAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openAct) self.fileToolBar.addAction(self.saveAct) self.editToolBar = self.addToolBar("Edit") self.editToolBar.addAction(self.cutAct) self.editToolBar.addAction(self.copyAct) self.editToolBar.addAction(self.pasteAct) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings("Trolltech", "Application Example") pos = settings.value("pos", QPoint(200, 200)) size = settings.value("size", QSize(400, 400)) self.resize(size) self.move(pos) def writeSettings(self): settings = QSettings("Trolltech", "Application Example") settings.setValue("pos", self.pos()) settings.setValue("size", self.size()) def maybeSave(self): if self.textEdit.document().isModified(): ret = QMessageBox.warning(self, "Application", "The document has been modified.\nDo you want to save " "your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.save() if ret == QMessageBox.Cancel: return False return True def loadFile(self, fileName): file = QFile(fileName) if not file.open(QFile.ReadOnly | QFile.Text): QMessageBox.warning(self, "Application", "Cannot read file %s:\n%s." % (fileName, file.errorString())) return inf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) self.textEdit.setPlainText(inf.readAll()) QApplication.restoreOverrideCursor() self.setCurrentFile(fileName) self.statusBar().showMessage("File loaded", 2000) def saveFile(self, fileName): file = QFile(fileName) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning(self, "Application", "Cannot write file %s:\n%s." % (fileName, file.errorString())) return False outf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) outf << self.textEdit.toPlainText() QApplication.restoreOverrideCursor() self.setCurrentFile(fileName); self.statusBar().showMessage("File saved", 2000) return True def setCurrentFile(self, fileName): self.curFile = fileName self.textEdit.document().setModified(False) self.setWindowModified(False) if self.curFile: shownName = self.strippedName(self.curFile) else: shownName = 'OneNote for linux' self.setWindowTitle(shownName) def strippedName(self, fullFileName): return QFileInfo(fullFileName).fileName() def write_at_exit(self): self.dbm_obj.write([self.hierarchy_dict, self.notebook_dict, self.section_dict, self.page_dict])
class DataManagementTab(QWidget): def __init__(self, obj_mng: ObjectManager, tpl_mng: TemplateManager, sgn_mng: SignageManager, mtm_mng: MultimediaManager, chn_mng: ChannelManager): super().__init__() self._obj_mng = obj_mng self._tpl_mng = tpl_mng self._sgn_mng = sgn_mng self._mtm_mng = mtm_mng self._chn_mng = chn_mng self._data_list = QTreeWidget() self._res = ResourceManager() self._stacked_widget = QStackedWidget() self._widget_idx = dict() self.init_ui() def data_to_tree_item(self): data_type_items = [] # For all data type for data_type_id in self._obj_mng.object_types.keys(): data_type = self._obj_mng.get_object_type(data_type_id) data_type_text = utils.gen_ui_text(data_type.name, data_type.id) data_type_item = QTreeWidgetItem([data_type_text]) # Add data for data_id in self._obj_mng.get_object_values(data_type).keys(): data_item = QTreeWidgetItem([data_id]) data_type_item.addChild(data_item) data_addition_item = QTreeWidgetItem(["+"]) data_type_item.addChild(data_addition_item) data_type_items.append(data_type_item) return data_type_items def init_ui(self): # Left side of screen self._data_list.setHeaderLabel(self._res['dataTypeListLabel']) self._data_list.addTopLevelItems(self.data_to_tree_item()) self._data_list.expandAll() self._data_list.itemSelectionChanged.connect(self.list_item_clicked) def data_type_change_handler(change_type: utils.ChangeType, data_text: str = '') -> None: # Get selected signage item get_selected = self._data_list.selectedItems() if get_selected: item = get_selected[0] if change_type == utils.ChangeType.DELETE: # Remove QTreeWidgetItem self._data_list.removeItemWidget(item) data_type_widget = DataTypeWidget(self._obj_mng, data_type_change_handler) self._widget_idx['type'] = self._stacked_widget.addWidget( data_type_widget) def data_change_handler(change_type: utils.ChangeType, data_text: str = '') -> None: # Get selected signage item get_selected = self._data_list.selectedItems() if get_selected: item = get_selected[0] if change_type == utils.ChangeType.SAVE: # Update QTreeWidgetItem item.setText(0, data_text) elif change_type == utils.ChangeType.DELETE: # Remove QTreeWidgetItem parent = item.parent() parent.removeChild(parent.child(parent.childCount() - 1)) parent.removeChild(item) parent.addChild(QTreeWidgetItem(['+'])) data_widget = DataWidget(self._obj_mng, self._mtm_mng, data_change_handler) self._widget_idx['data'] = self._stacked_widget.addWidget(data_widget) # Gather altogether hbox_outmost = QHBoxLayout() hbox_outmost.addWidget(self._data_list, 1) hbox_outmost.addWidget(self._stacked_widget, 4) self.setLayout(hbox_outmost) def list_item_clicked(self): get_selected = self.sender().selectedItems() if get_selected: item = get_selected[0] item_text = item.text(0) if item.parent() is None: # It is at topmost level # Selected one is data type idx = self._widget_idx['type'] data_type_id = utils.ui_text_to_id(item_text) data_type = self._obj_mng.get_object_type(data_type_id) self._stacked_widget.widget(idx).load_data_on_ui(data_type) self._stacked_widget.setCurrentIndex(idx) else: if item_text == '+': item.setSelected(False) text, ok = QInputDialog.getText( self, self._res['idDialogTitle'], self._res['idDialogDescription']) if ok: try: utils.validate_id(text) except AttributeError: QMessageBox.warning( self, self._res['idInvalidTitle'], self._res['idInvalidDescription'], QMessageBox.Ok, QMessageBox.Ok) return # Invalid ID. Do not create signage data_type_id = utils.ui_text_to_id( item.parent().text(0)) data_type = self._obj_mng.get_object_type(data_type_id) self._obj_mng.add_object_value( ObjectValue(text, data_type, self._obj_mng, self._mtm_mng)) item.setText(0, text) item.parent().addChild(QTreeWidgetItem(['+'])) else: # Selected one is data idx = self._widget_idx['data'] data_type_id = utils.ui_text_to_id(item.parent().text(0)) data_type = self._obj_mng.get_object_type(data_type_id) data = self._obj_mng.get_object_value(data_type, item_text) self._stacked_widget.widget(idx).load_data_on_ui(data) self._stacked_widget.setCurrentIndex(idx)
class Shortcuts(preferences.Page): def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.searchEntry = LineEdit() self.searchEntry.setPlaceholderText(_("Search...")) layout.addWidget(self.searchEntry) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton( icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.searchEntry.textChanged.connect(self.updateFilter) self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager( win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = list(allactions.keys()) def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelerator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0) def items(self): """Yield all the items in the actions tree.""" def children(item): for i in range(item.childCount()): c = item.child(i) if c.childCount(): for c1 in children(c): yield c1 else: yield c for c in children(self.tree.invisibleRootItem()): yield c def item(self, collection, name): for item in self.items(): if item.collection.name == collection and item.name == name: return item def saveSettings(self): self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts") for item in self.items(): for scheme in self.scheme.schemes(): item.save(scheme) item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def loadSettings(self): self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes") # clear the settings in all the items for item in self.items(): item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def slotSchemeChanged(self): """Called when the Scheme combobox is changed by the user.""" for item in self.items(): item.switchScheme(self.scheme.currentScheme()) def slotCurrentItemChanged(self, item): if isinstance(item, ShortcutItem): self.edit.setText( _("&Edit Shortcut for \"{name}\"").format(name=item.text(0))) self.edit.setEnabled(True) global _lastaction _lastaction = item.name else: self.edit.setText(_("(no shortcut)")) self.edit.setEnabled(False) def import_(self, filename): from . import import_export import_export.importShortcut(filename, self, self.scheme) def export(self, name, filename): from . import import_export try: import_export.exportShortcut(self, self.scheme.currentScheme(), name, filename) except (IOError, OSError) as e: QMessageBox.critical( self, _("Error"), _("Can't write to destination:\n\n{url}\n\n{error}").format( url=filename, error=e.strerror)) def findShortcutConflict(self, shortcut): """Find the possible shortcut conflict and return the conflict name.""" if shortcut: item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return None scheme = self.scheme.currentScheme() for i in self.items(): a = i.action(scheme) if i != item and a.shortcuts(): for s1 in a.shortcuts(): if s1.matches(shortcut) or shortcut.matches(s1): return qutil.removeAccelerator(a.text()) return None def editCurrentItem(self): item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return dlg = ShortcutEditDialog(self, self.findShortcutConflict) scheme = self.scheme.currentScheme() action = item.action(scheme) default = item.defaultShortcuts() or None if dlg.editAction(action, default): shortcuts = action.shortcuts() # check for conflicts conflicting = [] for i in self.items(): if i is not item: for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts): if s1.matches(s2) or s2.matches(s1): conflicting.append(i) if conflicting: for i in conflicting: l = i.shortcuts(scheme) for s1 in list(l): # copy for s2 in shortcuts: if s1.matches(s2) or s2.matches(s1): l.remove(s1) i.setShortcuts(l, scheme) # store the shortcut item.setShortcuts(shortcuts, scheme) self.changed.emit() def updateFilter(self): """Called when the search text changes.""" search = self.searchEntry.text() scheme = self.scheme.currentScheme() def hidechildren(item): hideparent = True for n in range(item.childCount()): c = item.child(n) if c.childCount(): # submenu item if hidechildren(c): c.setHidden(True) else: c.setHidden(False) c.setExpanded(True) hideparent = False elif isinstance(c, ShortcutItem): # shortcut item, should be the case if c.matches(scheme, search): c.setHidden(False) hideparent = False else: c.setHidden(True) return hideparent hidechildren(self.tree.invisibleRootItem())
def __init__(self, parent: QWidget, filename: str, torrent_info: TorrentInfo, control_thread: 'ControlManagerThread'): super().__init__(parent) self.app = QApplication.instance() self._torrent_filepath = Path(filename) self._torrent_info = torrent_info download_info = torrent_info.download_info self._control_thread = control_thread self._control = control_thread.control vbox = QVBoxLayout(self) self._download_dir = self.get_directory( self._control.last_download_dir) vbox.addWidget(QLabel('Download directory:')) vbox.addWidget(self._get_directory_browse_widget()) vbox.addWidget(QLabel('Announce URLs:')) url_tree = QTreeWidget() url_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) url_tree.header().close() vbox.addWidget(url_tree) for i, tier in enumerate(torrent_info.announce_list): tier_item = QTreeWidgetItem(url_tree) tier_item.setText(0, 'Tier {}'.format(i + 1)) for url in tier: url_item = QTreeWidgetItem(tier_item) url_item.setText(0, url) url_tree.expandAll() vbox.addWidget(url_tree, 1) file_tree = QTreeWidget() file_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) file_tree.setHeaderLabels(('Name', 'Size')) file_tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self._file_items = [] self._traverse_file_tree(download_info.suggested_name, download_info.file_tree, file_tree) file_tree.sortItems(0, Qt.AscendingOrder) file_tree.expandAll() file_tree.itemClicked.connect(self._update_checkboxes) vbox.addWidget(file_tree, 3) self._selection_label = QLabel( TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( len(download_info.files), humanize_size(download_info.total_size))) vbox.addWidget(self._selection_label) self._ipfsadd_checkbox = QCheckBox( 'Import files to IPFS when download is complete') self._ipfsadd_checkbox.setCheckState(Qt.Unchecked) # vbox.addWidget(self._ipfsadd_checkbox) self._button_box = QDialogButtonBox(self) self._button_box.setOrientation(Qt.Horizontal) self._button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._button_box.button(QDialogButtonBox.Ok).clicked.connect( self.submit_torrent) self._button_box.button(QDialogButtonBox.Cancel).clicked.connect( self.close) vbox.addWidget(self._button_box) self.setWindowTitle('Add Torrent') self.setMinimumSize( QSize(self.app.desktopGeometry.width() / 3, (2 * self.app.desktopGeometry.height()) / 3))
class TestsTab: model: GuiModel def __init__(self, model): self.__test_list = QTreeWidget() self.__test_list.setHeaderLabel("Name") self.__test_list.itemSelectionChanged.connect(self.__test_selected) self.__test_details = QTreeWidget() self.__test_details.setColumnCount(2) self.__test_details.setHeaderLabels(["Student", "Points"]) self.__test_details.itemActivated.connect( lambda item, column: file_double_clicked(self.model, item)) self.__test_details.itemSelectionChanged.connect( self.__test_file_selected) self.__test_file_details = FileDetailsWidget(model) details_splitter = QSplitter(Qt.Horizontal) details_splitter.addWidget(self.__test_details) details_splitter.addWidget(self.__test_file_details.widget) self.widget = QSplitter(Qt.Vertical) self.widget.addWidget(self.__test_list) self.widget.addWidget(details_splitter) self.widget.setStretchFactor(0, 3) self.widget.setStretchFactor(1, 1) self.model = model self.__load_tests() self.model.subject_changed.connect(self.__subject_changed) def __subject_changed(self): self.__load_tests() def __load_tests(self): self.__test_list.clear() self.__test_details.clear() if self.model.subject is not None: for test in self.model.subject.tests: test_item = TestItem([test.name], test) self.__test_list.addTopLevelItem(test_item) def __test_selected(self): self.__test_details.clear() home_work_items = self.__test_list.selectedItems() if home_work_items: test: Test = home_work_items[0].test for test_points in test.get_submissions(): student_item = StudentItem([ f"{test_points.student.surname} {test_points.student.name}", points_or_none(test_points.points) ], test_points.student) self.__test_details.addTopLevelItem(student_item) add_file_items(test_points.files, student_item) self.__test_details.expandAll() def __test_file_selected(self): self.__test_file_details.master_selection_changed( self.__test_details.selectedItems())
class InfoServicePageCollector(QWidget): def __init__(self, *args, **kwargs): super(InfoServicePageCollector, self).__init__(*args, **kwargs) layout = QHBoxLayout(margin=0) # 左侧管理菜单 self.left_tree = QTreeWidget(clicked=self.left_tree_clicked, objectName='leftTree') self.left_tree.header().hide() layout.addWidget(self.left_tree, alignment=Qt.AlignLeft) # 右侧显示窗口 self.right_frame = LoadedPage() layout.addWidget(self.right_frame) self.setLayout(layout) self._addLeftTreeContentes() self.setStyleSheet(""" #leftTree::item{ height:22px; } """) # 添加管理菜单 def _addLeftTreeContentes(self): contents = [ { 'name': u'咨询服务', 'subs': [ { 'id': 1, 'name': u'短信通' }, { 'id': 2, 'name': u'市场分析' }, { 'id': 3, 'name': u'专题研究' }, { 'id': 4, 'name': u'调研报告' }, { 'id': 5, 'name': u'市场路演' }, ] }, { 'name': u'顾问服务', 'subs': [ { 'id': 6, 'name': u'人才培养' }, { 'id': 7, 'name': u'部门组建' }, { 'id': 8, 'name': u'制度考核' }, ] }, { 'name': u'策略服务', 'subs': [ { 'id': 9, 'name': u'交易策略' }, { 'id': 10, 'name': u'投资方案' }, { 'id': 11, 'name': u'套保方案' }, ] }, { 'name': u'培训服务', 'subs': [ { 'id': 12, 'name': u'品种介绍' }, { 'id': 13, 'name': u'基本分析' }, { 'id': 14, 'name': u'技术分析' }, { 'id': 15, 'name': u'制度规则' }, { 'id': 16, 'name': u'交易管理' }, { 'id': 17, 'name': u'经验分享' }, ] }, ] # 填充树 for group_item in contents: group = QTreeWidgetItem(self.left_tree) group.setText(0, group_item['name']) # 添加子节点 for variety_item in group_item['subs']: child = QTreeWidgetItem() child.setText(0, variety_item['name']) child.sid = variety_item['id'] group.addChild(child) self.left_tree.expandAll() # 展开所有 # 点击左侧菜单 def left_tree_clicked(self): item = self.left_tree.currentItem() if item.childCount(): # has children open the root if item.isExpanded(): item.setExpanded(False) else: item.setExpanded(True) return service_id = item.sid text = item.text(0) # print(service_id) if service_id == 1: # 短信通 page = MessageServiceMaintain() page.getCurrentSMS() elif service_id == 2: # 市场分析 page = MarketAnalysisMaintain() page.getFileContents() elif service_id == 3: # 专题研究 page = TopicSearchMaintain() page.getFileContents() elif service_id == 4: # 调研报告 page = SearchReportMaintain() page.getFileContents() elif service_id == 6: # 人才培养 page = PersonnelTrainMaintain() elif service_id == 7: # 部门组建 page = DeptBuildMaintain() elif service_id == 8: # 制度考核 page = InstExamineMaintain() elif service_id == 9: # 交易策略 page = TradePolicyMaintain() elif service_id == 10: # 投资方案 page = InvestPlanMaintain() page.getFileContents() elif service_id == 11: # 套保方案 page = HedgePlanMaintain() page.getFileContents() elif service_id == 12: # 培训服务-品种介绍 page = VarietyIntroMaintain() else: page = QLabel( '【' + text + '】还不能进行数据管理...', styleSheet= 'color:rgb(50,180,100); font-size:15px;font-weight:bold', alignment=Qt.AlignCenter) self.right_frame.clear() self.right_frame.addWidget(page)
class Preferences(QDialog): configuration = {} weight = 0 # Signals savePreferences = pyqtSignal() def __init__(self, parent=None): super().__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(900, 650) box = QVBoxLayout(self) box.setContentsMargins(3, 3, 3, 3) self.setAutoFillBackground(True) # Header self._header_label = QLabel("") header_font = self._header_label.font() header_font.setBold(True) header_font.setPointSize(header_font.pointSize() + 4) self._header_label.setFont(header_font) hbox = QHBoxLayout() hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.tree.setFixedWidth(200) hbox.addWidget(self.tree) self.stacked = QStackedLayout() header_layout = QVBoxLayout() header_layout.setContentsMargins(0, 0, 0, 0) header_layout.addWidget(self._header_label) header_layout.addLayout(self.stacked) hbox.addLayout(header_layout) box.addLayout(hbox) # Footer buttons button_box = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel) box.addWidget(button_box) # Connections button_box.rejected.connect(self.close) button_box.accepted.connect(self._save_preferences) self.tree.selectionModel().currentRowChanged.connect( self._change_current) self.load_ui() @pyqtSlot() def _save_preferences(self): self.savePreferences.emit() self.close() def load_ui(self): sections = sorted( Preferences.configuration.keys(), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted( subcontent.keys(), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) self.tree.expandAll() self.tree.setCurrentIndex(self.tree.model().index(0, 0)) def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) self._header_label.setText(item.text(0)) @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if subsection is None: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = { 'widget': None, 'weight': 100 } subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config