def create_dock_widget(self): dock_widget = QDockWidget(self) dock_widget.setMaximumWidth(50) dock_widget.setAllowedAreas(Qt.LeftDockWidgetArea) vbox = QVBoxLayout() button_bold = QPushButton() button_bold.setIcon(QIcon('bold.png')) button_bold.setFixedSize(32, 32) button_bold.clicked.connect(self.on_bold_button_clicked) button_italic = QPushButton() button_italic.setIcon(QIcon('italic.png')) button_italic.setFixedSize(32, 32) button_italic.clicked.connect(self.on_italic_button_clicked) vbox.addWidget(button_bold) vbox.addWidget(button_italic) vbox.addStretch() group_box = QGroupBox() group_box.setLayout(vbox) dock_widget.setWidget(group_box) self.addDockWidget(Qt.LeftDockWidgetArea, dock_widget)
def createTreeView(self): dockWidget = QDockWidget() dockWidget.setAllowedAreas(Qt.LeftDockWidgetArea) dockWidget.setFeatures(QDockWidget.NoDockWidgetFeatures) dockWidget.setTitleBarWidget(QWidget()) self.treeView = QTreeView() self.treeView.clicked.connect(self.treeItemClicked) self.treeModel = TreeModel() self.treeView.setModel(self.treeModel) self.logo = QLabel() logoPixmap = QPixmap(CMAKE_INSTALL_PREFIX + '/share/jderobot/resources/jderobot.png') self.logo.setPixmap(logoPixmap) self.upButton = QPushButton() self.upButton.setText('Up') self.upButton.clicked.connect(self.upButtonClicked) leftContainer = QWidget() leftLayout = QVBoxLayout() leftLayout.addWidget(self.treeView) leftLayout.addWidget(self.upButton) leftLayout.addWidget(self.logo) leftContainer.setLayout(leftLayout) dockWidget.setWidget(leftContainer) self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)
def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.tool_bar = self.addToolBar('Main Toolbar') self.central_widget = CentralWidget(self) self.setCentralWidget(self.central_widget) self.min_time_points = 4 self.bin_box = QSpinBox() self.filter_box = QSpinBox() self.update_toolbar() # output window self.output_widget = QTextEdit() self.output_widget.setReadOnly(True) b_dock = QDockWidget('Output') b_dock.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea) b_dock.setWidget(self.output_widget) self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, b_dock) self.tool_bar.addAction(b_dock.toggleViewAction()) # Analyzer container tab widget self.analyzer_container = QTabWidget(self) self.analyzer_container.setTabPosition(QTabWidget.West) self.analyzer_container.setMovable(True) l_dock = QDockWidget('Analyzer container') l_dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) l_dock.setWidget(self.analyzer_container) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, l_dock) self.tool_bar.addAction(l_dock.toggleViewAction()) # status bar self.status_bar = QStatusBar(self) self.setStatusBar(self.status_bar)
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # Inicializa janela self.figure = plt.figure(figsize=(10, 6)) # Define figura e seu tamanho # Caracteristicas do mapa m = Basemap( resolution='i', # c, l, i, h, f or None projection='merc', lat_0=-22.525, lon_0=-48.865, llcrnrlon=-53.25, llcrnrlat=-25.1, urcrnrlon=-44.48, urcrnrlat=-19.5) m.drawmapboundary(fill_color='aqua') # Contorno m.fillcontinents(color='gray', lake_color='aqua') # Continente m.drawcoastlines() # Costa m.readshapefile('SP_Municipios/Sao_Paulo_Municipios', 'Sao_Paulo_Municipios') self.canvas = FigureCanvas(self.figure) self.setCentralWidget(self.canvas) simulParamDockWidget = QDockWidget('Simulação', self) simulParamDockWidget.setObjectName('simulParamDockWidget') simulParamDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) simulParamDockWidget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) # Menu Bar self.menu_bar = self.menuBar() self.file_menu = self.menu_bar.addMenu("File") self.edit_menu = self.menu_bar.addMenu("Edit") self.view_menu = self.menu_bar.addMenu("View") self.tools_menu = self.menu_bar.addMenu("Tools") # Project Browser self.project_dock = QDockWidget("Project", self) self.project_dock.setFloating(False) self.project_dock.setAllowedAreas(Qt.AllDockWidgetAreas) self.project = QListWidget(self) # Mock Project Browser self.project.addItem("main.py") self.project.addItem("test.java") self.project.addItem("stats.r") self.project_dock.setWidget(self.project) self.addDockWidget(Qt.LeftDockWidgetArea, self.project_dock) # Workspace self.workspace = QTabWidget() self.workspace.setTabPosition(QTabWidget.South) self.setCentralWidget(self.workspace) # Editor self.editor_tabs = EditorTabs() self.workspace.addTab(self.editor_tabs, "Editor") # Monitor self.monitor = QWidget() self.workspace.addTab(self.monitor, "Monitor") # Jupyter Widget self.jupyter_dock = QDockWidget("Jupyter", self) self.jupyter_dock.setFloating(False) self.jupyter_dock.setAllowedAreas(Qt.AllDockWidgetAreas) self.jupyter = TabbedJupyterWidget() self.jupyter_dock.setWidget(self.jupyter) self.addDockWidget(Qt.RightDockWidgetArea, self.jupyter_dock) # Window Properties self.setWindowTitle("Mock Layout for Glia") # Status Bar self.status_bar = QStatusBar(self) self.setStatusBar(self.status_bar) def closeEvent(self, event): """ Finish up any tasks. Stop all running widgets, it's threads and any I/O tasks. """ for child in self.findChildren(QObject): if hasattr(child, "stop_running"): child.stop_running()
class JetTrackerView(QWidget): def __init__(self, context, signals, parent=None): super(JetTrackerView, self).__init__(parent) self.signals = signals self.context = context self.parent = parent self.mainLayout = QHBoxLayout() self.createGraphWidget() self.createDockWidgets() self.mainLayout.addWidget(self.controlsDock) self.mainLayout.addWidget(self.graphWidget) # self.parent.resizeDocks([self.controlsDock], [45], Qt.Horizontal) print(self.parent) self.setLayout(self.mainLayout) def createGraphWidget(self): self.graphWidget = GraphsWidget(context=self.context, signals=self.signals) self.graphWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) def createDockWidgets(self): self.parent.setDockNestingEnabled(True) self.controlsDock = QDockWidget("Controls", self) self.controlsDock.setAllowedAreas(Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea) self.controlsDock.setFeatures(QDockWidget.DockWidgetFloatable) self.controlsWidget = ControlsWidget(self.context, self.signals) self.controlsDock.setWidget(self.controlsWidget) self.controlsDock.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
def createDockWindows(self): dock = QDockWidget("Log Files", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) dock.setWidget(self.lastree.tree) # self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.set_category_button = QPushButton('Set Category', self) self.slect_files_button = QPushButton( 'Select files for further process', self) # self.layout.addWidget(self.logtree.tree) dock = QDockWidget("Set", self) btn_w = QWidget() self.btn_layout = QVBoxLayout() btn_w.setLayout(self.btn_layout) dock.setWidget(btn_w) self.btn_layout.addWidget(self.set_category_button) self.btn_layout.addWidget(self.slect_files_button) self.addDockWidget(Qt.LeftDockWidgetArea, dock) dock = QDockWidget("Logs", self) dock.setWidget(self.logtree.tree) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.set_category_button.clicked.connect(self.set_category) self.slect_files_button.clicked.connect(self.retain4FurtherAnalysis)
def createDockWindows(self): dock = QDockWidget("Archivo intermedio", self) #dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.customerList = QListWidget(dock) dock.setWidget(self.customerList) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Tabla de símbolos", self) self.paragraphsList = QListWidget(dock) dock.setWidget(self.paragraphsList) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Errores", self) dock.setAllowedAreas(Qt.BottomDockWidgetArea) self.customerList = QListWidget(dock) dock.setWidget(self.customerList) self.addDockWidget(Qt.BottomDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Código objeto", self) #dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.customerList = QListWidget(dock) dock.setWidget(self.customerList) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction())
def init(self): self.pic = Picture(self) self.setCentralWidget(self.pic) self.panel = Panel(self.pic) self.dock = QDockWidget('info panel') self.dock.setWidget(self.panel) self.dock.setAllowedAreas(Qt.RightDockWidgetArea) self.addDockWidget(Qt.RightDockWidgetArea, self.dock) self.dock.setFeatures(QDockWidget.NoDockWidgetFeatures) self.dock.setFixedWidth(300) self.setWindowTitle('Untitled') dock = QDockWidget('command line', self) dock.setWidget(TwoLines()) dock.setAllowedAreas(Qt.BottomDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, dock) dock.setFeatures(QDockWidget.NoDockWidgetFeatures) dock.setFixedHeight(60) dock.setFixedWidth(800) desktop = QApplication.desktop() self.setGeometry(300, 100, desktop.width(), desktop.height()) self.setFixedSize(1100, 705)
def createClipboard(self): """ Set up clipboard and dock widget to display text from the clipboard. """ # Create dock widget clipboard_dock = QDockWidget() clipboard_dock.setWindowTitle("Display Clipboard Contents") clipboard_dock.setAllowedAreas(Qt.TopDockWidgetArea) dock_frame = QFrame() self.cb_text = QTextEdit() paste_button = QPushButton("Paste") paste_button.clicked.connect(self.pasteText) dock_v_box = QVBoxLayout() dock_v_box.addWidget(self.cb_text) dock_v_box.addWidget(paste_button) # set the main layout for the dock widget, # then set the main widget of the dock widget dock_frame.setLayout(dock_v_box) clipboard_dock.setWidget(dock_frame) # set initial location of dock widget self.addDockWidget(Qt.TopDockWidgetArea, clipboard_dock) # Create instance of the clipboard self.clipboard = QApplication.clipboard() self.clipboard.dataChanged.connect(self.copyFromClipboard)
def addROI(self,roi = None): if self.roiwidget is None: self.roiwidget = ROIPlotWidget(roi_target = self.p1, view = self.view, parent = self) roiTab = QDockWidget("roi cam {0}".format(self.iCam), self) roiTab.setWidget(self.roiwidget) roiTab.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea) roiTab.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetClosable) self.parent.addDockWidget(Qt.BottomDockWidgetArea ,roiTab) roiTab.setFloating(True) roiTab.resize(600,150) def closetab(ev): # This probably does not clean up memory... if not self.roiwidget is None: [self.p1.removeItem(r) for r in self.roiwidget.items()] del self.roiwidget self.roiwidget = None ev.accept() roiTab.closeEvent = closetab self.roiwidget.add_roi(roi)
def __setup_sub_window_dock(self, window: QWidget, config: dict, sub_window_data: SimpleNamespace): dock_name = config.get('DockName', '') dock_area = config.get('DockArea', Qt.NoDockWidgetArea) dock_show = config.get('DockShow', False) dock_float = config.get('DockFloat', False) dock_wnd = QDockWidget(dock_name, self) dock_wnd.setAllowedAreas( Qt.RightDockWidgetArea | Qt.LeftDockWidgetArea | Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea) # With this setting, the dock widget cannot be closed # dock_wnd.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) if dock_area != Qt.NoDockWidgetArea: if dock_area == Qt.AllDockWidgetAreas: self.addDockWidget(Qt.TopDockWidgetArea, dock_wnd) dock_wnd.setFloating(True) dock_wnd.move(QApplication.desktop().screen().rect().center() - self.rect().center()) else: self.addDockWidget(dock_area, dock_wnd) else: self.addDockWidget(Qt.TopDockWidgetArea, dock_wnd) dock_wnd.setFloating(True) dock_wnd.setAllowedAreas(Qt.NoDockWidgetArea) dock_wnd.move(QApplication.desktop().screen().rect().center() - self.rect().center()) dock_wnd.setWidget(window) if dock_float: dock_wnd.setFloating(True) # self.geometry().center() - dock_wnd.rect().center() # dock_wnd.move() if dock_show: dock_wnd.show() else: dock_wnd.hide() sub_window_data.dock_wnd = dock_wnd
def createDockWindows(self): # 正常邮件部分 dock = QDockWidget("normal",self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) # 设置属性, self.normalList = myListWidget(dock) self.normalList.setDragEnabled(True) self.normalList.setAcceptDrops(True) # 添加列表内容 # 默认打开一些正常邮件,显示内容为主题,点击主题时,获得文件名,进而展现内容 self.normalSub = self.getSubject('normal') self.normalList.addItems(self.normalSub) dock.setWidget(self.normalList) self.addDockWidget(Qt.RightDockWidgetArea, dock) # 垃圾邮件部分 dock = QDockWidget("trash",self) self.trashList = myListWidget(dock) self.trashList.setDragEnabled(True) self.trashList.setAcceptDrops(True) self.trashSub = self.getSubject('trash') self.trashList.addItems(self.trashSub) dock.setWidget(self.trashList) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.normalList.itemClicked.connect(self.normalShow) self.trashList.itemClicked.connect(self.trashShow) self.normalList.itemChanged.connect(self.normalChange) self.trashList.itemChanged.connect(self.trashChange)
def createDockWindows(self): dock = QDockWidget("Folders", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) #Code to Create FileView Colums and FolderTree self.FileView = QtWidgets.QColumnView() self.FileView.setGeometry(QtCore.QRect(240, 10, 291, 281)) self.FolderTree = QtWidgets.QTreeView() self.FolderTree.setGeometry(QtCore.QRect(10, 10, 221, 281)) FolderTree = self.FolderTree #FolderTree.hidecolumn(1),... ?? to show only name column #include FolderTree to a Dock at the left side dock.setWidget(FolderTree) self.addDockWidget(Qt.LeftDockWidgetArea, dock) #set the model and rootpath for filling the FolderTree from self.ui dirmodel = QFileSystemModel() #set filter to show only folders dirmodel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs) dirmodel.setRootPath(rootpath) #filemodel and filter for only files on right side filemodel = QFileSystemModel() filemodel.setFilter(QDir.NoDotAndDotDot | QDir.Files) filemodel.setRootPath(rootpath) FolderView = self.FolderTree FolderView.setModel(dirmodel) FolderView.setRootIndex(dirmodel.index(rootpath)) FileView = self.FileView FileView.setModel(filemodel) dock = QDockWidget("Files", self) dock.setWidget(FileView) self.addDockWidget(Qt.RightDockWidgetArea, dock) #important lines for the connection, which does not work self.FolderTree.clicked['QModelIndex'].connect(self.setpathonclick)
def createWidgets(self): """Cette fonction permet la création de tous les widgets de la mainWindow""" #Création toolbar toolBar = self.addToolBar("Tools") #Création bar recherche self.lineEditSearch = QLineEdit() self.lineEditSearch.setPlaceholderText("Recherche") self.lineEditSearch.setStyleSheet("background-color:white") toolBar.addWidget(self.lineEditSearch) self.lineEditSearch.setMaximumWidth(300) #Création séparateur toolBar.addSeparator() #Création icon add contact self.actionAdd = QAction("Ajouter (Ctrl+P)",self) toolBar.addAction(self.actionAdd) self.actionAdd.setShortcut("Ctrl+P") self.actionAdd.setIcon(QIcon("Pictures/sign.png")) #Création icon delete contact self.actionDelete = QAction("supprimer (Ctrl+D)",self) toolBar.addAction(self.actionDelete) self.actionDelete.setShortcut("Ctrl+D") self.actionDelete.setIcon(QIcon("Pictures/contacts.png")) #Création icon quit self.actionQuitter = QAction("Quitter (Ctrl+Q)",self) toolBar.addAction(self.actionQuitter) self.actionQuitter.setShortcut("Ctrl+Q") self.actionQuitter.setIcon(QIcon("Pictures/arrows.png")) #Création widget central self.centralWidget = QWidget() self.centralWidget.setStyleSheet("background-color:white") self.setCentralWidget(self.centralWidget) #Création dockWidget left dockDisplay = QDockWidget("Répertoire") dockDisplay.setStyleSheet("background-color:white") dockDisplay.setFeatures(QDockWidget.DockWidgetFloatable) dockDisplay.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.LeftDockWidgetArea,dockDisplay) containDock = QWidget(dockDisplay) dockDisplay.setWidget(containDock) dockLayout = QVBoxLayout() displayWidget = QScrollArea() displayWidget.setWidgetResizable(1) dockLayout.addWidget(displayWidget) containDock.setLayout(dockLayout) #Ajouter la list au dockwidget self.listContact = QListWidget() displayWidget.setWidget(self.listContact)
def createExperimentTasksVisualizationWgt(self): dockWin = QDockWidget("Experiment Tasks Visualization", self) dockWin.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.wgtExperimentTasksVisualizer = dockWin.setWidget(self.wgtExperimentTasksVisualizer) # self.addDockWidget(Qt.NoDockWidgetArea, dockWin) self.viewMenu.addAction(dockWin.toggleViewAction()) return dockWin
def createExperimentConsoleWgt(self): dockWin = QDockWidget("Experiment Console", self) dockWin.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.wgtExperimentConsole = eco.ExperimentConsoleOutput() dockWin.setWidget(self.wgtExperimentConsole) # self.addDockWidget(Qt.NoDockWidgetArea, dockWin) self.viewMenu.addAction(dockWin.toggleViewAction()) return dockWin
def createExperimentStatisticsPanelWgt(self): dockWin = QDockWidget("Experiment Statistics Panel", self) dockWin.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.wgtExperimentStatisticsPanel = esp.ExperimentStatisticsPanel() dockWin.setWidget(self.wgtExperimentStatisticsPanel) self.addDockWidget(Qt.RightDockWidgetArea, dockWin) self.viewMenu.addAction(dockWin.toggleViewAction()) return dockWin
def createFileViewerWgt(self): dockWin = QDockWidget("File Viewer", self) dockWin.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) # self.wgtFileContentViewer = fcv.FileContentViewer() # dockWin.setWidget(self.wgtFileContentViewer) self.addDockWidget(Qt.LeftDockWidgetArea, dockWin) self.viewMenu.addAction(dockWin.toggleViewAction()) return dockWin
def dockBottom(self, txt, widget): dock = QDockWidget(txt, self) self.addDockWidget(Qt.BottomDockWidgetArea, dock) dock.setAllowedAreas(Qt.BottomDockWidgetArea) dock.setWidget(widget) if (self.bottomDock != None): self.tabifyDockWidget(self.bottomDock, dock) self.bottomDock = dock
def setupToolsDockWidget(self): """Set up the dock widget that displays different tools and themes for interacting with the chart. Also displays the data values in a table view object.""" tools_dock = QDockWidget() tools_dock.setWindowTitle("Tools") tools_dock.setMinimumWidth(400) tools_dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) # Create widgets for dock widget area themes_cb = QComboBox() themes_cb.addItems(["Light", "Cerulean Blue", "Dark", "Sand Brown", "NCS Blue", "High Contrast", "Icy Blue", "Qt"]) themes_cb.currentTextChanged.connect(self.changeChartTheme) self.animations_cb = QComboBox() self.animations_cb.addItem("No Animation", QChart.NoAnimation) self.animations_cb.addItem("Grid Animation", QChart.GridAxisAnimations) self.animations_cb.addItem("Series Animation", QChart.SeriesAnimations) self.animations_cb.addItem("All Animations", QChart.AllAnimations) self.animations_cb.currentIndexChanged.connect(self.changeAnimations) self.legend_cb = QComboBox() self.legend_cb.addItem("No Legend") self.legend_cb.addItem("Align Left", Qt.AlignLeft) self.legend_cb.addItem("Align Top", Qt.AlignTop) self.legend_cb.addItem("Align Right", Qt.AlignRight) self.legend_cb.addItem("Align Bottom", Qt.AlignBottom) self.legend_cb.currentTextChanged.connect(self.changeLegend) self.antialiasing_check_box = QCheckBox() self.antialiasing_check_box.toggled.connect(self.toggleAntialiasing) reset_button = QPushButton("Reset Chart Axes") reset_button.clicked.connect(self.resetChartZoom) # Create table view and set its model data_table_view = QTableView() data_table_view.setModel(self.model) data_table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) data_table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) dock_form = QFormLayout() dock_form.setAlignment(Qt.AlignTop) dock_form.addRow("Themes:", themes_cb) dock_form.addRow("Animations:", self.animations_cb) dock_form.addRow("Legend:", self.legend_cb) dock_form.addRow("Anti-Aliasing", self.antialiasing_check_box) dock_form.addRow(reset_button) dock_form.addRow(data_table_view) # Create QWidget object to act as a container for dock widgets tools_container = QWidget() tools_container.setLayout(dock_form) tools_dock.setWidget(tools_container) self.addDockWidget(Qt.LeftDockWidgetArea, tools_dock) # Handles the visibility of the dock widget self.toggle_dock_tools_act = tools_dock.toggleViewAction()
def testInPlotImage(self): dock = QDockWidget("In plot image", self) dock.setAllowedAreas(Qt.BottomDockWidgetArea) dock.setWidget(self.inplot) #self.treeView.setRootIsDecorated(False) #self.treeView.setAlternatingRowColors(True) #self.dock.setWidget(self.treeView) self.addDockWidget(Qt.BottomDockWidgetArea, dock)
def __init__(self): super().__init__() self.data_dict = {} self.mdi = QMdiArea() self.setCentralWidget(self.mdi) # self.mdi.resize(950,950) bar = self.menuBar() self.current_dir = None self.opened_wd_names = [] file = bar.addMenu("File") file.addAction("New") file.addAction("cascade") file.addAction("Tiled") file.triggered[QAction].connect(self.WindowTrig) load = bar.addMenu("Load") load.addAction("2D") load.addAction("3D") load.triggered[QAction].connect(self.dir_open) toolbar = QToolBar() self.addToolBar(toolbar) bw_button_action = QAction('base_wnd', self) bw_button_action.setStatusTip('base window button') bw_button_action.triggered.connect(self.onclicktb) toolbar.addAction(bw_button_action) self.setWindowTitle("MDI Application") self.base_wd = QMdiSubWindow() self.base_wd.setAttribute(Qt.WA_DeleteOnClose, False) self.base_wd.resize(400, 400) self.base_wd.plt_i = pg.PlotItem(labels={ 'left': ('slits', 'degrees'), 'bottom': ('Kin. Energy', 'eV') }) self.base_wd.plt_iv = pg.ImageView(view=self.base_wd.plt_i) self.base_wd.setWidget(self.base_wd.plt_iv) self.base_wd.setWindowTitle("plot window") self.mdi.addSubWindow(self.base_wd) self.base_wd.show() data_DockWidget = QDockWidget('data', self) data_DockWidget.setObjectName(('data window')) data_DockWidget.setAllowedAreas(Qt.RightDockWidgetArea) self.data_list = QListWidget() data_DockWidget.setWidget(self.data_list) self.addDockWidget(Qt.RightDockWidgetArea, data_DockWidget) self.data_list.itemClicked.connect(self.show_data) self.data_list.itemDoubleClicked.connect(self.get_data) self.mdi.subWindowActivated.connect(self.get_data)
def addDock(self): dock1 = QDockWidget('DockWidget') dock1.setFeatures(QDockWidget.DockWidgetFloatable) dock1.setAllowedAreas(Qt.LeftDockWidgetArea) listwidget = QListWidget() listwidget.addItems(self.items) listwidget.currentRowChanged.connect(self.onDockListIndexChanged) dock1.setWidget(listwidget) self.addDockWidget(Qt.LeftDockWidgetArea, dock1)
def init_file_tree(self, directory, title, action, filtered=False): widget = DirectoryDockWidget(directory, filtered=filtered, parent=self) widget.path_label.addAction(action, QLineEdit.LeadingPosition) widget.tree_view.activated.connect( partial(self.handle_directory_tree_view_activated, directory)) dock = QDockWidget(title, self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) dock.setFeatures(QDockWidget.DockWidgetMovable) dock.setWidget(widget) self.addDockWidget(Qt.LeftDockWidgetArea, dock)
def init_file_list(self): names = self.sweep_dict.keys() self.file_list = FileList(names) self.file_list.itemClicked.connect(self.set_new_sweep) self.file_list.itemActivated.connect(self.set_new_sweep) dock_widget = QDockWidget('Browser', self) dock_widget.setWidget(self.file_list) dock_widget.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas) self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, dock_widget) self.dock_widgets.append(dock_widget)
def createDockWidget(self): """ Create Dock wudget to the right""" # Set up dock widget dock_widget = QDockWidget() dock_widget.setWindowTitle("Example Dock") dock_widget.setAllowedAreas(Qt.AllDockWidgetAreas) # Set main widget for the dock widget dock_widget.setWidget(QTextEdit()) # Set initial location of dock widget in main window self.addDockWidget(Qt.LeftDockWidgetArea, dock_widget)
def add_view(self, name, widget,parent,first): dock = QDockWidget(name, self) dock.setAllowedAreas(Qt.AllDockWidgetAreas) dock.setWidget(widget) widget.show() if first : self.addDockWidget(Qt.TopDockWidgetArea, dock) else : self.tabifyDockWidget(parent,dock) return dock
class SpadeMainWindow(QMainWindow): """Spade's main window.""" def __init__(self): super().__init__() self._init_ui() self._create_central_widget() self._create_projectview() self._create_templateview() def center(self): """Place the window in the center of the screen.""" qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def _init_menubar(self): """Set up the menu bar.""" action_exit = QAction("Exit", self) action_exit.setStatusTip("Exit application") action_exit.triggered.connect(qApp.quit) menubar = self.menuBar() menu_file = menubar.addMenu("File") menu_file.addAction(action_exit) def _init_ui(self): """Set up main window attributes.""" self.resize(1200, 800) self.center() self.setWindowTitle("Spade") self._init_menubar() self.statusBar().showMessage("Ready") def _create_central_widget(self): """Set up the central widget.""" self.central_widget = EditorWidget() self.setCentralWidget(self.central_widget) def _create_projectview(self): """Spawn projectview.""" self.dock_projectview = QDockWidget() self.dock_projectview.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.dock_projectview.setWidget(QTextEdit()) self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_projectview) def _create_templateview(self): """Spawn templateview.""" self.dock_templateview = QDockWidget() self.dock_templateview.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea) self.dock_templateview.setWidget(QTextEdit()) self.addDockWidget(Qt.BottomDockWidgetArea, self.dock_templateview)
class Main(QMainWindow): def __init__(self): super(Main, self).__init__() self.layout = MainWidget() self.layout.MainSig.connect(self.__addTable) self.TableWid = ShowDBWidget() self.setCentralWidget(self.layout) self.__initUI() def __addTable(self, path): self.TableWid = ShowDBWidget(path) self.TableDock = QDockWidget("Tables", self) self.TableDock.setWidget(self.TableWid) self.TableDock.setMinimumSize(500, 500) self.TableDock.setAllowedAreas(Qt.AllDockWidgetAreas) self.addDockWidget(Qt.RightDockWidgetArea, self.TableDock, Qt.Horizontal) self.TableWid.TableSig.connect(self.__addSub) def __addSub(self, path, name): self.SubTableWid = ShowDBSubWidget(path, name) self.SubTableDock = QDockWidget("Elements", self) self.SubTableDock.setWidget(self.SubTableWid) self.SubTableDock.setMinimumSize(1000, 500) self.SubTableDock.setAllowedAreas(Qt.AllDockWidgetAreas) self.addDockWidget(Qt.RightDockWidgetArea, self.SubTableDock, Qt.Horizontal) def __initUI(self): menubar = self.menuBar() deleteAct = QAction('Delete', self) deleteAct.setShortcut('Delete') deleteAct.triggered.connect(self.layout.clickedDelete) clearAct = QAction('Clear', self) clearAct.setShortcut('Ctrl+W') clearAct.triggered.connect(self.layout.clickedClear) addAct = QAction('Add', self) addAct.setShortcut('Ctrl+O') addAct.triggered.connect(self.layout.clickedAdd) exitAct = QAction('Exit', self) exitAct.setShortcut('Esc') exitAct.triggered.connect(self.layout.clickedExit) fileMenu = menubar.addMenu('&File') fileMenu.addAction(addAct) fileMenu.addAction(deleteAct) fileMenu.addAction(clearAct) fileMenu.addAction(exitAct) self.setGeometry(1000, 500, 2000, 800)
def createFitnessFunctionVisualizationWgt(self): dockWin = QDockWidget("Fitness Function Visualization", self) dockWin.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.wgtFitnessFunctionVisualizer = QListWidget(dockWin) self.wgtFitnessFunctionVisualizer.addItems(( "File 1", "File 2")) dockWin.setWidget(self.wgtFitnessFunctionVisualizer) # self.addDockWidget(Qt.NoDockWidgetArea, dockWin) self.viewMenu.addAction(dockWin.toggleViewAction()) return dockWin
def createDockStats(self): dock = QDockWidget('stats',self) dock.setAllowedAreas(Qt.TopDockWidgetArea) dock.setFeatures(dock.DockWidgetClosable|dock.DockWidgetVerticalTitleBar) self.statsui = StatsWin(dock,cur=self) self.statsui.setMaximumHeight(100) dock.setWidget(self.statsui) self.addDockWidget(Qt.TopDockWidgetArea, dock) a = dock.toggleViewAction() self.viewMenu.addAction(a) a.setEnabled(True)
def createDockWindows(self): # dock for project files dock = QDockWidget("Project", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.projectTreeView= TreeView(dock) dock.setWidget(self.projectTreeView) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) # dock for html preview dock = QDockWidget("Preview", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.previewView= HtmlView(dock) dock.setWidget(self.previewView) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction())
def createDockWindows(self): dock = QDockWidget("Customers", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.customerList = QListWidget(dock) self.customerList.addItems(( "John Doe, Harmony Enterprises, 12 Lakeside, Ambleton", "Jane Doe, Memorabilia, 23 Watersedge, Beaton", "Tammy Shea, Tiblanka, 38 Sea Views, Carlton", "Tim Sheen, Caraba Gifts, 48 Ocean Way, Deal", "Sol Harvey, Chicos Coffee, 53 New Springs, Eccleston", "Sally Hobart, Tiroli Tea, 67 Long River, Fedula")) dock.setWidget(self.customerList) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Paragraphs", self) self.paragraphsList = QListWidget(dock) self.paragraphsList.addItems(( "Thank you for your payment which we have received today.", "Your order has been dispatched and should be with you within " "28 days.", "We have dispatched those items that were in stock. The rest of " "your order will be dispatched once all the remaining items " "have arrived at our warehouse. No additional shipping " "charges will be made.", "You made a small overpayment (less than $5) which we will keep " "on account for you, or return at your request.", "You made a small underpayment (less than $1), but we have sent " "your order anyway. We'll add this underpayment to your next " "bill.", "Unfortunately you did not send enough money. Please remit an " "additional $. Your order will be dispatched as soon as the " "complete amount has been received.", "You made an overpayment (more than $5). Do you wish to buy more " "items, or should we return the excess to you?")) dock.setWidget(self.paragraphsList) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) self.customerList.currentTextChanged.connect(self.insertCustomer) self.paragraphsList.currentTextChanged.connect(self.addParagraph)
def __init__(self,mainwin): te = QPlainTextEdit() hilighter = hilite.Highlighter(te.document()) qd = QDockWidget("Dae:Xgm") qd.setWidget(te) qd.setMinimumSize(480,240) qd.setFeatures(QDockWidget.DockWidgetMovable|QDockWidget.DockWidgetVerticalTitleBar|QDockWidget.DockWidgetFloatable) qd.setAllowedAreas(Qt.LeftDockWidgetArea) qdss = "QWidget{background-color: rgb(64,64,128); color: rgb(160,160,192);}" qdss += "QDockWidget::title {background-color: rgb(32,32,48); color: rgb(255,0,0);}" qd.setStyleSheet(qdss) mainwin.addDockWidget(Qt.LeftDockWidgetArea,qd) if mainwin.prevDockWidget!=None: mainwin.tabifyDockWidget(mainwin.prevDockWidget,qd) mainwin.prevDockWidget = qd self.stdout = "" self.stderr = "" def onSubProcStdout(): bytes = self.process.readAllStandardOutput() self.stdout += str(bytes, encoding='ascii') te.setPlainText(self.stdout+self.stderr) def onSubProcStderr(): bytes = self.process.readAllStandardError() self.stderr += str(bytes, encoding='ascii') te.setPlainText(self.stdout+self.stderr) def finished(text): print( "process done...\n") self.process = QProcess() self.process.readyReadStandardError.connect(onSubProcStderr) self.process.readyReadStandardOutput.connect(onSubProcStdout); self.process.finished.connect(finished); self.process.start(cmd)
def createDockWindows(self): dock = QDockWidget("Sensors", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.sensors= Sensors(dock) dock.setWidget(self.sensors) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Environment", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.environmentList = QListWidget(dock) self.environmentList.addItems(( "Omnidirectional Sensor Networks", "Directional Sensor Networks", "Directional Path Tracking", "Big Target Coverage")) dock.setWidget(self.environmentList) self.addDockWidget(Qt.RightDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Simulation", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.simulation= Simulation(dock) dock.setWidget(self.simulation) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) dock = QDockWidget("Console", self) dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.console= Console(dock) dock.setWidget(self.console) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.viewMenu.addAction(dock.toggleViewAction()) self.console.applyButton.clicked.connect(self.applyButtonState) self.console.playButton.clicked.connect(self.playButtonState) self.console.pauseButton.clicked.connect(self.pauseButtonState) self.environmentList.currentTextChanged.connect(self.changeEnvironment)
class Window(QMainWindow): """ Defines the look and characteristics of the application's main window. """ title = _("Mu {}").format(__version__) icon = "icon" timer = None usb_checker = None serial = None repl = None plotter = None _zoom_in = pyqtSignal(int) _zoom_out = pyqtSignal(int) close_serial = pyqtSignal() write_to_serial = pyqtSignal(bytes) data_received = pyqtSignal(bytes) def zoom_in(self): """ Handles zooming in. """ self._zoom_in.emit(2) def zoom_out(self): """ Handles zooming out. """ self._zoom_out.emit(2) def connect_zoom(self, widget): """ Connects a referenced widget to the zoom related signals. """ self._zoom_in.connect(widget.zoomIn) self._zoom_out.connect(widget.zoomOut) @property def current_tab(self): """ Returns the currently focussed tab. """ return self.tabs.currentWidget() def set_read_only(self, is_readonly): """ Set all tabs read-only. """ self.read_only_tabs = is_readonly for tab in self.widgets: tab.setReadOnly(is_readonly) def get_load_path(self, folder): """ Displays a dialog for selecting a file to load. Returns the selected path. Defaults to start in the referenced folder. """ path, _ = QFileDialog.getOpenFileName(self.widget, 'Open file', folder, '*.py *.PY *.hex') logger.debug('Getting load path: {}'.format(path)) return path def get_save_path(self, folder): """ Displays a dialog for selecting a file to save. Returns the selected path. Defaults to start in the referenced folder. """ path, _ = QFileDialog.getSaveFileName(self.widget, 'Save file', folder) logger.debug('Getting save path: {}'.format(path)) return path def get_microbit_path(self, folder): """ Displays a dialog for locating the location of the BBC micro:bit in the host computer's filesystem. Returns the selected path. Defaults to start in the referenced folder. """ path = QFileDialog.getExistingDirectory(self.widget, 'Locate BBC micro:bit', folder, QFileDialog.ShowDirsOnly) logger.debug('Getting micro:bit path: {}'.format(path)) return path def add_tab(self, path, text, api): """ Adds a tab with the referenced path and text to the editor. """ new_tab = EditorPane(path, text) new_tab.connect_margin(self.breakpoint_toggle) new_tab_index = self.tabs.addTab(new_tab, new_tab.label) new_tab.set_api(api) @new_tab.modificationChanged.connect def on_modified(): modified_tab_index = self.tabs.currentIndex() self.tabs.setTabText(modified_tab_index, new_tab.label) self.update_title(new_tab.label) self.tabs.setCurrentIndex(new_tab_index) self.connect_zoom(new_tab) self.set_theme(self.theme) new_tab.setFocus() if self.read_only_tabs: new_tab.setReadOnly(self.read_only_tabs) def focus_tab(self, tab): index = self.tabs.indexOf(tab) self.tabs.setCurrentIndex(index) tab.setFocus() @property def tab_count(self): """ Returns the number of active tabs. """ return self.tabs.count() @property def widgets(self): """ Returns a list of references to the widgets representing tabs in the editor. """ return [self.tabs.widget(i) for i in range(self.tab_count)] @property def modified(self): """ Returns a boolean indication if there are any modified tabs in the editor. """ for widget in self.widgets: if widget.isModified(): return True return False def on_serial_read(self): """ Called when the connected device is ready to send data via the serial connection. It reads all the available data, emits the data_received signal with the received bytes and, if appropriate, emits the tuple_received signal with the tuple created from the bytes received. """ data = bytes(self.serial.readAll()) # get all the available bytes. self.data_received.emit(data) def open_serial_link(self, port): """ Creates a new serial link instance. """ self.input_buffer = [] self.serial = QSerialPort() self.serial.setPortName(port) if self.serial.open(QIODevice.ReadWrite): self.serial.dataTerminalReady = True if not self.serial.isDataTerminalReady(): # Using pyserial as a 'hack' to open the port and set DTR # as QtSerial does not seem to work on some Windows :( # See issues #281 and #302 for details. self.serial.close() pyser = serial.Serial(port) # open serial port w/pyserial pyser.dtr = True pyser.close() self.serial.open(QIODevice.ReadWrite) self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) else: raise IOError("Cannot connect to device on port {}".format(port)) def close_serial_link(self): """ Close and clean up the currently open serial link. """ self.serial.close() self.serial = None def add_filesystem(self, home, file_manager): """ Adds the file system pane to the application. """ self.fs_pane = FileSystemPane(home) self.fs = QDockWidget(_('Filesystem on micro:bit')) self.fs.setWidget(self.fs_pane) self.fs.setFeatures(QDockWidget.DockWidgetMovable) self.fs.setAllowedAreas(Qt.BottomDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.fs) self.fs_pane.setFocus() file_manager.on_list_files.connect(self.fs_pane.on_ls) self.fs_pane.list_files.connect(file_manager.ls) self.fs_pane.microbit_fs.put.connect(file_manager.put) self.fs_pane.microbit_fs.delete.connect(file_manager.delete) self.fs_pane.microbit_fs.list_files.connect(file_manager.ls) self.fs_pane.local_fs.get.connect(file_manager.get) self.fs_pane.local_fs.list_files.connect(file_manager.ls) file_manager.on_put_file.connect(self.fs_pane.microbit_fs.on_put) file_manager.on_delete_file.connect(self.fs_pane.microbit_fs.on_delete) file_manager.on_get_file.connect(self.fs_pane.local_fs.on_get) file_manager.on_list_fail.connect(self.fs_pane.on_ls_fail) file_manager.on_put_fail.connect(self.fs_pane.on_put_fail) file_manager.on_delete_fail.connect(self.fs_pane.on_delete_fail) file_manager.on_get_fail.connect(self.fs_pane.on_get_fail) self.connect_zoom(self.fs_pane) return self.fs_pane def add_micropython_repl(self, port, name): """ Adds a MicroPython based REPL pane to the application. """ if not self.serial: self.open_serial_link(port) # Send a Control-C / keyboard interrupt. self.serial.write(b'\x03') repl_pane = MicroPythonREPLPane(serial=self.serial, theme=self.theme) self.data_received.connect(repl_pane.process_bytes) self.add_repl(repl_pane, name) def add_micropython_plotter(self, port, name): """ Adds a plotter that reads data from a serial connection. """ if not self.serial: self.open_serial_link(port) plotter_pane = PlotterPane(theme=self.theme) self.data_received.connect(plotter_pane.process_bytes) self.add_plotter(plotter_pane, name) def add_jupyter_repl(self, kernel_manager, kernel_client): """ Adds a Jupyter based REPL pane to the application. """ kernel_manager.kernel.gui = 'qt4' kernel_client.start_channels() ipython_widget = JupyterREPLPane(theme=self.theme) ipython_widget.kernel_manager = kernel_manager ipython_widget.kernel_client = kernel_client self.add_repl(ipython_widget, _('Python3 (Jupyter)')) def add_repl(self, repl_pane, name): """ Adds the referenced REPL pane to the application. """ self.repl_pane = repl_pane self.repl = QDockWidget(_('{} REPL').format(name)) self.repl.setWidget(repl_pane) self.repl.setFeatures(QDockWidget.DockWidgetMovable) self.repl.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.repl) self.connect_zoom(self.repl_pane) self.repl_pane.set_theme(self.theme) self.repl_pane.setFocus() def add_plotter(self, plotter_pane, name): """ Adds the referenced plotter pane to the application. """ self.plotter_pane = plotter_pane self.plotter = QDockWidget(_('{} Plotter').format(name)) self.plotter.setWidget(plotter_pane) self.plotter.setFeatures(QDockWidget.DockWidgetMovable) self.plotter.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.plotter) self.plotter_pane.set_theme(self.theme) self.plotter_pane.setFocus() def add_python3_runner(self, script_name, working_directory, interactive=False, debugger=False, command_args=None, runner=None): """ Display console output for the referenced Python script. The script will be run within the workspace_path directory. If interactive is True (default is False) the Python process will run in interactive mode (dropping the user into the REPL when the script completes). If debugger is True (default is False) the script will be run within a debug runner session. The debugger overrides the interactive flag (you cannot run the debugger in interactive mode). If there is a list of command_args (the default is None) then these will be passed as further arguments into the command run in the new process. If runner is give, this is used as the command to start the Python process. """ self.process_runner = PythonProcessPane(self) self.runner = QDockWidget(_("Running: {}").format( os.path.basename(script_name))) self.runner.setWidget(self.process_runner) self.runner.setFeatures(QDockWidget.DockWidgetMovable) self.runner.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.runner) self.process_runner.start_process(script_name, working_directory, interactive, debugger, command_args, runner) self.process_runner.setFocus() self.connect_zoom(self.process_runner) return self.process_runner def add_debug_inspector(self): """ Display a debug inspector to view the call stack. """ self.debug_inspector = DebugInspector() self.debug_model = QStandardItemModel() self.debug_inspector.setModel(self.debug_model) self.debug_inspector.setUniformRowHeights(True) self.inspector = QDockWidget(_('Debug Inspector')) self.inspector.setWidget(self.debug_inspector) self.inspector.setFeatures(QDockWidget.DockWidgetMovable) self.inspector.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.RightDockWidgetArea, self.inspector) self.connect_zoom(self.debug_inspector) def update_debug_inspector(self, locals_dict): """ Given the contents of a dict representation of the locals in the current stack frame, update the debug inspector with the new values. """ excluded_names = ['__builtins__', '__debug_code__', '__debug_script__', ] names = sorted([x for x in locals_dict if x not in excluded_names]) self.debug_model.clear() self.debug_model.setHorizontalHeaderLabels([_('Name'), _('Value'), ]) for name in names: try: # DANGER! val = eval(locals_dict[name]) except Exception: val = None if isinstance(val, list): # Show a list consisting of rows of position/value list_item = QStandardItem(name) for i, i_val in enumerate(val): list_item.appendRow([ QStandardItem(str(i)), QStandardItem(repr(i_val)) ]) self.debug_model.appendRow([ list_item, QStandardItem(_('(A list of {} items.)').format(len(val))) ]) elif isinstance(val, dict): # Show a dict consisting of rows of key/value pairs. dict_item = QStandardItem(name) for k, k_val in val.items(): dict_item.appendRow([ QStandardItem(repr(k)), QStandardItem(repr(k_val)) ]) self.debug_model.appendRow([ dict_item, QStandardItem(_('(A dict of {} items.)').format(len(val))) ]) else: self.debug_model.appendRow([ QStandardItem(name), QStandardItem(locals_dict[name]), ]) def remove_filesystem(self): """ Removes the file system pane from the application. """ if hasattr(self, 'fs') and self.fs: self.fs_pane = None self.fs.setParent(None) self.fs.deleteLater() self.fs = None def remove_repl(self): """ Removes the REPL pane from the application. """ if self.repl: self.repl_pane = None self.repl.setParent(None) self.repl.deleteLater() self.repl = None if not self.plotter: self.serial = None def remove_plotter(self): """ Removes the plotter pane from the application. """ if self.plotter: self.plotter_pane = None self.plotter.setParent(None) self.plotter.deleteLater() self.plotter = None if not self.repl: self.serial = None def remove_python_runner(self): """ Removes the runner pane from the application. """ if hasattr(self, 'runner') and self.runner: self.process_runner = None self.runner.setParent(None) self.runner.deleteLater() self.runner = None def remove_debug_inspector(self): """ Removes the debug inspector pane from the application. """ if hasattr(self, 'inspector') and self.inspector: self.debug_inspector = None self.debug_model = None self.inspector.setParent(None) self.inspector.deleteLater() self.inspector = None def set_theme(self, theme): """ Sets the theme for the REPL and editor tabs. """ self.theme = theme if theme == 'contrast': self.setStyleSheet(CONTRAST_STYLE) new_theme = ContrastTheme new_icon = 'theme_day' elif theme == 'night': new_theme = NightTheme new_icon = 'theme_contrast' self.setStyleSheet(NIGHT_STYLE) else: self.setStyleSheet(DAY_STYLE) new_theme = DayTheme new_icon = 'theme' for widget in self.widgets: widget.set_theme(new_theme) self.button_bar.slots['theme'].setIcon(load_icon(new_icon)) if hasattr(self, 'repl') and self.repl: self.repl_pane.set_theme(theme) if hasattr(self, 'plotter') and self.plotter: self.plotter_pane.set_theme(theme) def show_logs(self, log, theme): """ Display the referenced content of the log. """ log_box = LogDisplay() log_box.setup(log, theme) log_box.exec() def show_message(self, message, information=None, icon=None): """ Displays a modal message to the user. If information is passed in this will be set as the additional informative text in the modal dialog. Since this mechanism will be used mainly for warning users that something is awry the default icon is set to "Warning". It's possible to override the icon to one of the following settings: NoIcon, Question, Information, Warning or Critical. """ message_box = QMessageBox(self) message_box.setText(message) message_box.setWindowTitle('Mu') if information: message_box.setInformativeText(information) if icon and hasattr(message_box, icon): message_box.setIcon(getattr(message_box, icon)) else: message_box.setIcon(message_box.Warning) logger.debug(message) logger.debug(information) message_box.exec() def show_confirmation(self, message, information=None, icon=None): """ Displays a modal message to the user to which they need to confirm or cancel. If information is passed in this will be set as the additional informative text in the modal dialog. Since this mechanism will be used mainly for warning users that something is awry the default icon is set to "Warning". It's possible to override the icon to one of the following settings: NoIcon, Question, Information, Warning or Critical. """ message_box = QMessageBox() message_box.setText(message) message_box.setWindowTitle(_('Mu')) if information: message_box.setInformativeText(information) if icon and hasattr(message_box, icon): message_box.setIcon(getattr(message_box, icon)) else: message_box.setIcon(message_box.Warning) message_box.setStandardButtons(message_box.Cancel | message_box.Ok) message_box.setDefaultButton(message_box.Cancel) logger.debug(message) logger.debug(information) return message_box.exec() def update_title(self, filename=None): """ Updates the title bar of the application. If a filename (representing the name of the file currently the focus of the editor) is supplied, append it to the end of the title. """ title = self.title if filename: title += ' - ' + filename self.setWindowTitle(title) def autosize_window(self): """ Makes the editor 80% of the width*height of the screen and centres it. """ screen = QDesktopWidget().screenGeometry() w = int(screen.width() * 0.8) h = int(screen.height() * 0.8) self.resize(w, h) size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def reset_annotations(self): """ Resets the state of annotations on the current tab. """ self.current_tab.reset_annotations() def annotate_code(self, feedback, annotation_type): """ Given a list of annotations about the code in the current tab, add the annotations to the editor window so the user can make appropriate changes. """ self.current_tab.annotate_code(feedback, annotation_type) def show_annotations(self): """ Show the annotations added to the current tab. """ self.current_tab.show_annotations() def setup(self, breakpoint_toggle, theme): """ Sets up the window. Defines the various attributes of the window and defines how the user interface is laid out. """ self.theme = theme self.breakpoint_toggle = breakpoint_toggle # Give the window a default icon, title and minimum size. self.setWindowIcon(load_icon(self.icon)) self.update_title() self.read_only_tabs = False self.setMinimumSize(800, 400) self.widget = QWidget() widget_layout = QVBoxLayout() self.widget.setLayout(widget_layout) self.button_bar = ButtonBar(self.widget) self.tabs = FileTabs() self.tabs.setMovable(True) self.setCentralWidget(self.tabs) self.status_bar = StatusBar(parent=self) self.setStatusBar(self.status_bar) self.addToolBar(self.button_bar) self.show() self.autosize_window() def resizeEvent(self, resizeEvent): """ Respond to window getting too small for the button bar to fit well. """ size = resizeEvent.size() self.button_bar.set_responsive_mode(size.width(), size.height()) def select_mode(self, modes, current_mode, theme): """ Display the mode selector dialog and return the result. """ mode_select = ModeSelector() mode_select.setup(modes, current_mode, theme) mode_select.exec() try: return mode_select.get_mode() except Exception as ex: return None def change_mode(self, mode): """ Given a an object representing a mode, recreates the button bar with the expected functionality. """ self.button_bar.change_mode(mode) # Update the autocomplete / tooltip APIs for each tab to the new mode. api = mode.api() for widget in self.widgets: widget.set_api(api) def set_usb_checker(self, duration, callback): """ Sets up a timer that polls for USB changes via the "callback" every "duration" seconds. """ self.usb_checker = QTimer() self.usb_checker.timeout.connect(callback) self.usb_checker.start(duration * 1000) def set_timer(self, duration, callback): """ Set a repeating timer to call "callback" every "duration" seconds. """ self.timer = QTimer() self.timer.timeout.connect(callback) self.timer.start(duration * 1000) # Measured in milliseconds. def stop_timer(self): """ Stop the repeating timer. """ if self.timer: self.timer.stop() self.timer = None def connect_tab_rename(self, handler, shortcut): """ Connect the double-click event on a tab and the keyboard shortcut to the referenced handler (causing the Save As dialog). """ self.tabs.shortcut = QShortcut(QKeySequence(shortcut), self) self.tabs.shortcut.activated.connect(handler) self.tabs.tabBarDoubleClicked.connect(handler) def open_directory_from_os(self, path): """ Given the path to a directoy, open the OS's built in filesystem explorer for that path. Works with Windows, OSX and Linux. """ if sys.platform == 'win32': # Windows os.startfile(path) elif sys.platform == 'darwin': # OSX os.system('open "{}"'.format(path)) else: # Assume freedesktop.org on unix-y. os.system('xdg-open "{}"'.format(path))
def create_widgets(MAIN): """Create all the widgets and dockwidgets. It also creates actions to toggle views of dockwidgets in dockwidgets. """ """ ------ CREATE WIDGETS ------ """ MAIN.labels = Labels(MAIN) MAIN.channels = Channels(MAIN) MAIN.notes = Notes(MAIN) MAIN.overview = Overview(MAIN) MAIN.spectrum = Spectrum(MAIN) MAIN.traces = Traces(MAIN) MAIN.video = Video(MAIN) MAIN.settings = Settings(MAIN) # depends on all widgets apart from Info MAIN.info = Info(MAIN) # this has to be the last, it depends on settings MAIN.setCentralWidget(MAIN.traces) """ ------ LIST DOCKWIDGETS ------ """ new_docks = [{'name': 'Information', 'widget': MAIN.info, 'main_area': Qt.LeftDockWidgetArea, 'extra_area': Qt.RightDockWidgetArea, }, {'name': 'Labels', 'widget': MAIN.labels, 'main_area': Qt.RightDockWidgetArea, 'extra_area': Qt.LeftDockWidgetArea, }, {'name': 'Channels', 'widget': MAIN.channels, 'main_area': Qt.RightDockWidgetArea, 'extra_area': Qt.LeftDockWidgetArea, }, {'name': 'Spectrum', 'widget': MAIN.spectrum, 'main_area': Qt.RightDockWidgetArea, 'extra_area': Qt.LeftDockWidgetArea, }, {'name': 'Annotations', 'widget': MAIN.notes, 'main_area': Qt.LeftDockWidgetArea, 'extra_area': Qt.RightDockWidgetArea, }, {'name': 'Video', 'widget': MAIN.video, 'main_area': Qt.LeftDockWidgetArea, 'extra_area': Qt.RightDockWidgetArea, }, {'name': 'Overview', 'widget': MAIN.overview, 'main_area': Qt.BottomDockWidgetArea, 'extra_area': Qt.TopDockWidgetArea, }, ] """ ------ CREATE DOCKWIDGETS ------ """ idx_docks = {} actions = MAIN.action actions['dockwidgets'] = [] for dock in new_docks: dockwidget = QDockWidget(dock['name'], MAIN) dockwidget.setWidget(dock['widget']) dockwidget.setAllowedAreas(dock['main_area'] | dock['extra_area']) dockwidget.setObjectName(dock['name']) # savestate idx_docks[dock['name']] = dockwidget MAIN.addDockWidget(dock['main_area'], dockwidget) dockwidget_action = dockwidget.toggleViewAction() dockwidget_action.setIcon(QIcon(ICON['widget'])) actions['dockwidgets'].append(dockwidget_action) """ ------ ORGANIZE DOCKWIDGETS ------ """ MAIN.tabifyDockWidget(idx_docks['Information'], idx_docks['Video']) MAIN.tabifyDockWidget(idx_docks['Channels'], idx_docks['Labels']) idx_docks['Information'].raise_()
class DocumentController(): """ Connects UI buttons to their corresponding actions in the model. """ ### INIT METHODS ### def __init__(self, document): """docstring for __init__""" # initialize variables self._document = document print("the doc", self._document) self._document.setController(self) self._active_part = None self._filename = None self._file_open_path = None # will be set in _readSettings self._has_no_associated_file = True self._path_view_instance = None self._slice_view_instance = None self._undo_stack = None self.win = None self.fileopendialog = None self.filesavedialog = None self.settings = QSettings() self._readSettings() # call other init methods self._initWindow() app().document_controllers.add(self) def _initWindow(self): """docstring for initWindow""" self.win = DocumentWindow(doc_ctrlr=self) # self.win.setWindowIcon(app().icon) app().documentWindowWasCreatedSignal.emit(self._document, self.win) self._connectWindowSignalsToSelf() self.win.show() app().active_document = self def _initMaya(self): """ Initialize Maya-related state. Delete Maya nodes if there is an old document left over from the same session. Set up the Maya window. """ # There will only be one document if (app().active_document and app().active_document.win and not app().active_document.win.close()): return del app().active_document app().active_document = self import maya.OpenMayaUI as OpenMayaUI import sip ptr = OpenMayaUI.MQtUtil.mainWindow() mayaWin = sip.wrapinstance(int(ptr), QMainWindow) self.windock = QDockWidget("cadnano") self.windock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.windock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.windock.setWidget(self.win) mayaWin.addDockWidget(Qt.DockWidgetArea(Qt.LeftDockWidgetArea), self.windock) self.windock.setVisible(True) def _connectWindowSignalsToSelf(self): """This method serves to group all the signal & slot connections made by DocumentController""" self.win.action_new.triggered.connect(self.actionNewSlot) self.win.action_open.triggered.connect(self.actionOpenSlot) self.win.action_close.triggered.connect(self.actionCloseSlot) self.win.action_save.triggered.connect(self.actionSaveSlot) self.win.action_save_as.triggered.connect(self.actionSaveAsSlot) self.win.action_SVG.triggered.connect(self.actionSVGSlot) self.win.action_autostaple.triggered.connect(self.actionAutostapleSlot) self.win.action_export_staples.triggered.connect(self.actionExportStaplesSlot) self.win.action_preferences.triggered.connect(self.actionPrefsSlot) self.win.action_modify.triggered.connect(self.actionModifySlot) self.win.action_new_honeycomb_part.triggered.connect(\ self.actionAddHoneycombPartSlot) self.win.action_new_square_part.triggered.connect(\ self.actionAddSquarePartSlot) self.win.closeEvent = self.windowCloseEventHandler self.win.action_about.triggered.connect(self.actionAboutSlot) self.win.action_cadnano_website.triggered.connect(self.actionCadnanoWebsiteSlot) self.win.action_feedback.triggered.connect(self.actionFeedbackSlot) self.win.action_filter_handle.triggered.connect(self.actionFilterHandleSlot) self.win.action_filter_endpoint.triggered.connect(self.actionFilterEndpointSlot) self.win.action_filter_strand.triggered.connect(self.actionFilterStrandSlot) self.win.action_filter_xover.triggered.connect(self.actionFilterXoverSlot) self.win.action_filter_scaf.triggered.connect(self.actionFilterScafSlot) self.win.action_filter_stap.triggered.connect(self.actionFilterStapSlot) self.win.action_renumber.triggered.connect(self.actionRenumberSlot) ### SLOTS ### def undoStackCleanChangedSlot(self): """The title changes to include [*] on modification.""" self.win.setWindowModified(not self.undoStack().isClean()) self.win.setWindowTitle(self.documentTitle()) def actionAboutSlot(self): """Displays the about cadnano dialog.""" from ui.dialogs.ui_about import Ui_About dialog = QDialog() dialog_about = Ui_About() # reusing this dialog, should rename dialog.setStyleSheet("QDialog { background-image: url(ui/dialogs/images/cadnano2-about.png); background-repeat: none; }") dialog_about.setupUi(dialog) dialog.exec_() filter_list = ["strand", "endpoint", "xover", "virtual_helix"] def actionFilterHandleSlot(self): """Disables all other selection filters when active.""" fH = self.win.action_filter_handle fE = self.win.action_filter_endpoint fS = self.win.action_filter_strand fX = self.win.action_filter_xover fH.setChecked(True) if fE.isChecked(): fE.setChecked(False) if fS.isChecked(): fS.setChecked(False) if fX.isChecked(): fX.setChecked(False) self._document.documentSelectionFilterChangedSignal.emit(["virtual_helix"]) def actionFilterEndpointSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.action_filter_handle fE = self.win.action_filter_endpoint fS = self.win.action_filter_strand fX = self.win.action_filter_xover if fH.isChecked(): fH.setChecked(False) if not fS.isChecked() and not fX.isChecked(): fE.setChecked(True) self._strandFilterUpdate() # end def def actionFilterStrandSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.action_filter_handle fE = self.win.action_filter_endpoint fS = self.win.action_filter_strand fX = self.win.action_filter_xover if fH.isChecked(): fH.setChecked(False) if not fE.isChecked() and not fX.isChecked(): fS.setChecked(True) self._strandFilterUpdate() # end def def actionFilterXoverSlot(self): """ Disables handle filters when activated. Remains checked if no other item-type filter is active. """ fH = self.win.action_filter_handle fE = self.win.action_filter_endpoint fS = self.win.action_filter_strand fX = self.win.action_filter_xover if fH.isChecked(): fH.setChecked(False) if not fE.isChecked() and not fS.isChecked(): fX.setChecked(True) self._strandFilterUpdate() # end def def actionFilterScafSlot(self): """Remains checked if no other strand-type filter is active.""" fSc = self.win.action_filter_scaf fSt = self.win.action_filter_stap if not fSc.isChecked() and not fSt.isChecked(): fSc.setChecked(True) self._strandFilterUpdate() def actionFilterStapSlot(self): """Remains checked if no other strand-type filter is active.""" fSc = self.win.action_filter_scaf fSt = self.win.action_filter_stap if not fSc.isChecked() and not fSt.isChecked(): fSt.setChecked(True) self._strandFilterUpdate() # end def def _strandFilterUpdate(self): win = self.win filter_list = [] if win.action_filter_endpoint.isChecked(): filter_list.append("endpoint") if win.action_filter_strand.isChecked(): filter_list.append("strand") if win.action_filter_xover.isChecked(): filter_list.append("xover") if win.action_filter_scaf.isChecked(): filter_list.append("scaffold") if win.action_filter_stap.isChecked(): filter_list.append("staple") self._document.documentSelectionFilterChangedSignal.emit(filter_list) # end def def actionNewSlot(self): """ 1. If document is has no parts, do nothing. 2. If document is dirty, call maybeSave and continue if it succeeds. 3. Create a new document and swap it into the existing ctrlr/window. """ # clear/reset the view! if len(self._document.parts()) == 0: return # no parts if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if self.filesavedialog != None: self.filesavedialog.finished.connect(self.newClickedCallback) else: # user did not save self.newClickedCallback() # finalize new def actionOpenSlot(self): """ 1. If document is untouched, proceed to open dialog. 2. If document is dirty, call maybesave and continue if it succeeds. Downstream, the file is selected in openAfterMaybeSave, and the selected file is actually opened in openAfterMaybeSaveCallback. """ if self.maybeSave() == False: return # user canceled in maybe save else: # user did not cancel if hasattr(self, "filesavedialog"): # user did save if self.filesavedialog != None: self.filesavedialog.finished.connect(self.openAfterMaybeSave) else: self.openAfterMaybeSave() # windows else: # user did not save self.openAfterMaybeSave() # finalize new def actionCloseSlot(self): """This will trigger a Window closeEvent.""" # if util.isWindows(): self.win.close() app().qApp.exit(0) def actionSaveSlot(self): """SaveAs if necessary, otherwise overwrite existing file.""" if self._has_no_associated_file: self.saveFileDialog() return self.writeDocumentToFile() def actionSaveAsSlot(self): """Open a save file dialog so user can choose a name.""" self.saveFileDialog() def actionSVGSlot(self): """docstring for actionSVGSlot""" fname = os.path.basename(str(self.filename())) if fname == None: directory = "." else: directory = QFileInfo(fname).path() fdialog = QFileDialog( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.svg)" % QApplication.applicationName()) fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.svgsavedialog = fdialog self.svgsavedialog.filesSelected.connect(self.saveSVGDialogCallback) fdialog.open() class DummyChild(QGraphicsItem): def boundingRect(self): return QRect(200, 200) # self.parentObject().boundingRect() def paint(self, painter, option, widget=None): pass def saveSVGDialogCallback(self, selected): if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected print("da fname", fname) if fname is None or os.path.isdir(fname): return False if not fname.lower().endswith(".svg"): fname += ".svg" if self.svgsavedialog != None: self.svgsavedialog.filesSelected.disconnect(self.saveSVGDialogCallback) del self.svgsavedialog # prevents hang self.svgsavedialog = None generator = QSvgGenerator() generator.setFileName(fname) generator.setSize(QSize(200, 200)) generator.setViewBox(QRect(0, 0, 2000, 2000)) painter = QPainter() # Render through scene # painter.begin(generator) # self.win.pathscene.render(painter) # painter.end() # Render item-by-item painter = QPainter() style_option = QStyleOptionGraphicsItem() q = [self.win.pathroot] painter.begin(generator) while q: graphics_item = q.pop() transform = graphics_item.itemTransform(self.win.sliceroot)[0] painter.setTransform(transform) if graphics_item.isVisible(): graphics_item.paint(painter, style_option, None) q.extend(graphics_item.childItems()) painter.end() def actionExportStaplesSlot(self): """ Triggered by clicking Export Staples button. Opens a file dialog to determine where the staples should be saved. The callback is exportStaplesCallback which collects the staple sequences and exports the file. """ # Validate that no staple oligos are loops. part = self.activePart() if part is None: return stap_loop_olgs = part.getStapleLoopOligos() if stap_loop_olgs: from ui.dialogs.ui_warning import Ui_Warning dialog = QDialog() dialogWarning = Ui_Warning() # reusing this dialog, should rename dialog.setStyleSheet("QDialog { background-image: url(ui/dialogs/images/cadnano2-about.png); background-repeat: none; }") dialogWarning.setupUi(dialog) locs = ", ".join([o.locString() for o in stap_loop_olgs]) msg = "Part contains staple loop(s) at %s.\n\nUse the break tool to introduce 5' & 3' ends before exporting. Loops have been colored red; use undo to revert." % locs dialogWarning.title.setText("Staple validation failed") dialogWarning.message.setText(msg) for o in stap_loop_olgs: o.applyColor(styles.stapColors[0].name()) dialog.exec_() return # Proceed with staple export. fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)") self.saveStaplesDialog = None self.exportStaplesCallback(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "%s - Export As" % QApplication.applicationName(), directory, "(*.csv)") fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.saveStaplesDialog = fdialog self.saveStaplesDialog.filesSelected.connect(self.exportStaplesCallback) fdialog.open() # end def def actionPrefsSlot(self): app().prefsClicked() def actionAutostapleSlot(self): part = self.activePart() if part: self.win.path_graphics_view.setViewportUpdateOn(False) part.autoStaple() self.win.path_graphics_view.setViewportUpdateOn(True) def actionModifySlot(self): """ Notifies that part root items that parts should respond to modifier selection signals. """ pass # uncomment for debugging # isChecked = self.win.actionModify.isChecked() # self.win.pathroot.setModifyState(isChecked) # self.win.sliceroot.setModifyState(isChecked) # if app().isInMaya(): # isChecked = self.win.actionModify.isChecked() # self.win.pathroot.setModifyState(isChecked) # self.win.sliceroot.setModifyState(isChecked) # self.win.solidroot.setModifyState(isChecked) def actionAddHoneycombPartSlot(self): """docstring for actionAddHoneycombPartSlot""" part = self._document.addHoneycombPart() self.setActivePart(part) def actionAddSquarePartSlot(self): """docstring for actionAddSquarePartSlot""" part = self._document.addSquarePart() self.setActivePart(part) def actionRenumberSlot(self): coordList = self.win.pathroot.getSelectedPartOrderedVHList() part = self.activePart() part.renumber(coordList) # end def ### ACCESSORS ### def document(self): return self._document def window(self): return self.win def setDocument(self, doc): """ Sets the controller's document, and informs the document that this is its controller. """ self._document = doc doc.setController(self) def activePart(self): if self._active_part == None: self._active_part = self._document.selectedPart() return self._active_part def setActivePart(self, part): self._active_part = part def undoStack(self): return self._document.undoStack() ### PRIVATE SUPPORT METHODS ### def newDocument(self, doc=None, fname=None): """Creates a new Document, reusing the DocumentController.""" if fname is not None and self._filename == fname: setReopen(True) self._document.resetViews() setBatch(True) self._document.removeAllParts() # clear out old parts setBatch(False) self._document.undoStack().clear() # reset undostack self._filename = fname if fname else "untitled.json" self._has_no_associated_file = fname == None self._active_part = None self.win.setWindowTitle(self.documentTitle() + '[*]') def saveFileDialog(self): fname = self.filename() if fname == None: directory = "." else: directory = QFileInfo(fname).path() if util.isWindows(): # required for native looking file window fname = QFileDialog.getSaveFileName( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.json)" % QApplication.applicationName()) self.writeDocumentToFile(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "%s - Save As" % QApplication.applicationName(), directory, "%s (*.json)" % QApplication.applicationName()) fdialog.setAcceptMode(QFileDialog.AcceptSave) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.filesavedialog = fdialog self.filesavedialog.filesSelected.connect( self.saveFileDialogCallback) fdialog.open() # end def def _readSettings(self): self.settings.beginGroup("FileSystem") self._file_open_path = self.settings.value("openpath", QDir().homePath()) self.settings.endGroup() def _writeFileOpenPath(self, path): """docstring for _writePath""" self._file_open_path = path self.settings.beginGroup("FileSystem") self.settings.setValue("openpath", path) self.settings.endGroup() ### SLOT CALLBACKS ### def actionNewSlotCallback(self): """ Gets called on completion of filesavedialog after newClicked's maybeSave. Removes the dialog if necessary, but it was probably already removed by saveFileDialogCallback. """ if self.filesavedialog != None: self.filesavedialog.finished.disconnect(self.actionNewSlotCallback) del self.filesavedialog # prevents hang (?) self.filesavedialog = None self.newDocument() def exportStaplesCallback(self, selected): """Export all staple sequences to selected CSV file.""" if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected if fname is None or os.path.isdir(fname): return False if not fname.lower().endswith(".csv"): fname += ".csv" if self.saveStaplesDialog != None: self.saveStaplesDialog.filesSelected.disconnect(self.exportStaplesCallback) # manual garbage collection to prevent hang (in osx) del self.saveStaplesDialog self.saveStaplesDialog = None # write the file output = self.activePart().getStapleSequences() with open(fname, 'w') as f: f.write(output) # end def def newClickedCallback(self): """ Gets called on completion of filesavedialog after newClicked's maybeSave. Removes the dialog if necessary, but it was probably already removed by saveFileDialogCallback. """ if self.filesavedialog != None: self.filesavedialog.finished.disconnect(self.newClickedCallback) del self.filesavedialog # prevents hang (?) self.filesavedialog = None self.newDocument() def openAfterMaybeSaveCallback(self, selected): """ Receives file selection info from the dialog created by openAfterMaybeSave, following user input. Extracts the file name and passes it to the decode method, which returns a new document doc, which is then set as the open document by newDocument. Calls finalizeImport and disconnects dialog signaling. """ if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected if fname is None or os.path.isdir(fname): return False self._writeFileOpenPath(os.path.dirname(fname)) self.win.path_graphics_view.setViewportUpdateOn(False) self.win.slice_graphics_view.setViewportUpdateOn(False) self.newDocument(fname=fname) decodeFile(fname, document=self._document) self.win.path_graphics_view.setViewportUpdateOn(True) self.win.slice_graphics_view.setViewportUpdateOn(True) self.win.path_graphics_view.update() self.win.slice_graphics_view.update() if hasattr(self, "filesavedialog"): # user did save if self.fileopendialog != None: self.fileopendialog.filesSelected.disconnect(\ self.openAfterMaybeSaveCallback) # manual garbage collection to prevent hang (in osx) del self.fileopendialog self.fileopendialog = None def saveFileDialogCallback(self, selected): """If the user chose to save, write to that file.""" if isinstance(selected, (list, tuple)): fname = selected[0] else: fname = selected if fname is None or os.path.isdir(fname): return False if not fname.lower().endswith(".json"): fname += ".json" if self.filesavedialog != None: self.filesavedialog.filesSelected.disconnect( self.saveFileDialogCallback) del self.filesavedialog # prevents hang self.filesavedialog = None self.writeDocumentToFile(fname) self._writeFileOpenPath(os.path.dirname(fname)) ### EVENT HANDLERS ### def windowCloseEventHandler(self, event): """Intercept close events when user attempts to close the window.""" if self.maybeSave(): event.accept() # if app().isInMaya(): # self.windock.setVisible(False) # del self.windock # self.windock = None app().document_controllers.remove(self) else: event.ignore() self.actionCloseSlot() ### FILE INPUT ## def documentTitle(self): fname = os.path.basename(str(self.filename())) if not self.undoStack().isClean(): fname += '[*]' return fname def filename(self): return self._filename def setFilename(self, proposed_fname): if self._filename == proposed_fname: return True self._filename = proposed_fname self._has_no_associated_file = False self.win.setWindowTitle(self.documentTitle()) return True def openAfterMaybeSave(self): """ This is the method that initiates file opening. It is called by actionOpenSlot to spawn a QFileDialog and connect it to a callback method. """ path = self._file_open_path if util.isWindows(): # required for native looking file window#"/", fname = QFileDialog.getOpenFileName( None, "Open Document", path, "cadnano1 / cadnano2 Files (*.nno *.json *.cadnano)") self.filesavedialog = None self.openAfterMaybeSaveCallback(fname) else: # access through non-blocking callback fdialog = QFileDialog( self.win, "Open Document", path, "cadnano1 / cadnano2 Files (*.nno *.json *.cadnano)") fdialog.setAcceptMode(QFileDialog.AcceptOpen) fdialog.setWindowFlags(Qt.Sheet) fdialog.setWindowModality(Qt.WindowModal) self.fileopendialog = fdialog self.fileopendialog.filesSelected.connect(self.openAfterMaybeSaveCallback) fdialog.open() # end def ### FILE OUTPUT ### def maybeSave(self): """Save on quit, check if document changes have occured.""" if app().dontAskAndJustDiscardUnsavedChanges: return True if not self.undoStack().isClean(): # document dirty? savebox = QMessageBox(QMessageBox.Warning, "Application", "The document has been modified.\nDo you want to save your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, self.win, Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet) savebox.setWindowModality(Qt.WindowModal) save = savebox.button(QMessageBox.Save) discard = savebox.button(QMessageBox.Discard) cancel = savebox.button(QMessageBox.Cancel) save.setShortcut("Ctrl+S") discard.setShortcut(QKeySequence("D,Ctrl+D")) cancel.setShortcut(QKeySequence("C,Ctrl+C,.,Ctrl+.")) ret = savebox.exec_() del savebox # manual garbage collection to prevent hang (in osx) if ret == QMessageBox.Save: return self.actionSaveAsSlot() elif ret == QMessageBox.Cancel: return False return True def writeDocumentToFile(self, filename=None): if filename == None: assert(not self._has_no_associated_file) filename = self.filename() try: with open(filename, 'w') as f: helix_order_list = self.win.pathroot.getSelectedPartOrderedVHList() encode(self._document, helix_order_list, f) except IOError: flags = Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.Sheet errorbox = QMessageBox(QMessageBox.Critical, "cadnano", "Could not write to '%s'." % filename, QMessageBox.Ok, self.win, flags) errorbox.setWindowModality(Qt.WindowModal) errorbox.open() return False self.undoStack().setClean() self.setFilename(filename) return True def actionCadnanoWebsiteSlot(self): import webbrowser webbrowser.open("http://cadnano.org/") def actionFeedbackSlot(self): import webbrowser webbrowser.open("http://cadnano.org/feedback")