Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
class QtWindowCanvas(QMainWindow):
    '''generic app window to display a figure with a toolbar'''
    def __init__(self, bottom_dock=True, left_dock=True):
        # initialsie window
        QMainWindow.__init__(self)
        self.main_widget = QWidget(self)

        # add dock widget
        if bottom_dock:
            self.bottom_dock = QDockWidget()
            self.addDockWidget(Qt.BottomDockWidgetArea, self.bottom_dock)
            self.bottom_dock.setFeatures(QDockWidget.DockWidgetFloatable)

        if left_dock:
            self.left_dock = QDockWidget()
            self.addDockWidget(Qt.LeftDockWidgetArea, self.left_dock)
            self.left_dock.setFeatures(QDockWidget.DockWidgetFloatable)

        # define layout
        self.grid = QGridLayout(self.main_widget)

        # create figure on window
        self.canvas = MPLCanvas()
        self.grid.addWidget(self.canvas, 0, 0, 1, 1)  # all rows

        # figure toolbar
        toolbar = NavigationToolbar2QT(self.canvas, self)
        self.grid.addWidget(toolbar, 1, 0, 1, 1)

        self.setCentralWidget(self.main_widget)
Ejemplo n.º 4
0
    def __init__(self, src, dst):
        """
        打码界面
        :param src: 验证码所在目录或url
        :param dst: 验证码输出目录
        """
        super().__init__()
        self.save = 0
        self.passed = -1
        self.img_queue = ImageQueue(src, dst)
        self.setGeometry(300, 300, 400, 200)
        self.setWindowTitle("打码器")

        self.et = QLineEdit()
        self.lbl = QLabel("hello, press enter to start!")

        self.et.setAlignment(Qt.AlignCenter)
        self.et.returnPressed.connect(self._submit)
        dock = QDockWidget('输入框')
        dock.setFeatures(QDockWidget.DockWidgetFloatable
                         | QDockWidget.DockWidgetMovable)
        dock.setWidget(self.et)
        self.lbl.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(self.lbl)
        self.addDockWidget(Qt.BottomDockWidgetArea, dock)
    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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
def sliceManager(var):

    sliceDock = QDockWidget('图像调节', var)
    sliceGroup = QGroupBox()
    vbox = QVBoxLayout()
    sliceHBox = QHBoxLayout()
    luminanceHBox = QHBoxLayout()

    contrastLabel = QLabel('对比度: ', var)
    luminanceLabel = QLabel('亮    度: ', var)

    var.contrastSlide = QSlider(Qt.Horizontal, var)
    var.luminanceSlide = QSlider(Qt.Horizontal, var)

    var.contrastSpin = QSpinBox(var)
    var.luminanceSpin = QSpinBox(var)

    var.contrastSlide.setFocusPolicy(Qt.NoFocus)
    var.contrastSlide.setSingleStep(1)
    var.contrastSlide.setMinimum(1)
    var.contrastSlide.setTickPosition(QSlider.TicksAbove)  # 设置刻度信息
    var.contrastSlide.setEnabled(False)
    # sliceSlide.setFixedSize(1, 100)

    var.luminanceSlide.setFocusPolicy(Qt.NoFocus)
    var.luminanceSlide.setSingleStep(1)
    var.luminanceSlide.setMinimum(1)
    var.luminanceSlide.setTickPosition(QSlider.TicksLeft)  # 设置刻度信息
    var.luminanceSlide.valueChanged.connect(var.luminanceSpin.setValue)
    var.luminanceSlide.setEnabled(False)

    var.contrastSpin.setSingleStep(1)
    # var.sliceSpin.setWrapping(True)   #是否循环
    var.contrastSpin.setValue(1)
    var.contrastSpin.setEnabled(False)

    var.luminanceSpin.setSingleStep(1)
    # var.luminanceSpin.setWrapping(True)
    var.luminanceSpin.setValue(1)
    var.luminanceSpin.setEnabled(False)
    var.luminanceSpin.valueChanged.connect(var.luminanceSlide.setValue)

    sliceHBox.addWidget(contrastLabel)
    sliceHBox.addWidget(var.contrastSlide)
    sliceHBox.addWidget(var.contrastSpin)

    luminanceHBox.addWidget(luminanceLabel)
    luminanceHBox.addWidget(var.luminanceSlide)
    luminanceHBox.addWidget(var.luminanceSpin)

    vbox.addLayout(sliceHBox)
    vbox.addLayout(luminanceHBox)
    vbox.addStretch()

    sliceGroup.setLayout(vbox)
    sliceDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
    sliceDock.setWidget(sliceGroup)

    return sliceDock
Ejemplo n.º 9
0
	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)
Ejemplo n.º 10
0
class ToolsWidget:
    def __init__(self, parent, config):
        self.parent = parent
        self.config = config
        self.widget = QWidget(self.parent)
        self.widget.setGeometry(1200, 0, 400, 900)
        self.widget.setStyleSheet("background-color:#717171")

        self.dock = QDockWidget("Tools", self.parent)
        self.dock.setWidget(self.widget)
        self.dock.setFeatures(QDockWidget.DockWidgetFloatable
                              | QDockWidget.DockWidgetMovable)

        self.tools_layout = QVBoxLayout(self.widget)
        self.tools_layout.setAlignment(Qt.AlignTop)
        self.tools_layout.setSpacing(15)

        self.controller = ToolsController(self.parent, self)

        self.address = AddressWidget(self.widget, self.controller)
        self.tools_layout.addWidget(self.address.get_address_widget())

        self.buttons = ButtonsWidget(self.widget, self.controller)
        self.tools_layout.addWidget(self.buttons.get_buttons_widget())

        self.slider_movement = SliderMovementWidget(self.widget,
                                                    self.controller)
        self.tools_layout.addWidget(self.slider_movement.get_slider_widget())

        self.slider_area = SliderCachedAreaWidget(self.widget, self.controller)
        self.tools_layout.addWidget(self.slider_area.get_slider_widget())

        self.slider_history = SliderHistorySizeWidget(self.widget,
                                                      self.controller)
        self.tools_layout.addWidget(self.slider_history.get_slider_widget())

        self.slider_blurr = SliderBlurrWidget(self.widget, self.controller)
        self.tools_layout.addWidget(self.slider_blurr.get_slider_widget())

        self.slider_dilate = SliderDilatedKernel(self.widget, self.controller)
        self.tools_layout.addWidget(self.slider_dilate.get_slider_widget())

        self.slider_epsilon = SliderEpsilonWidget(self.widget, self.controller)
        self.tools_layout.addWidget(self.slider_epsilon.get_slider_widget())

        self.slider_threshold = SliderPixelThresholdWidget(
            self.widget, self.controller)
        self.tools_layout.addWidget(self.slider_threshold.get_slider_widget())

        #        self.coordinates = CoordinatesWidget(self.widget, self.controller)
        #        self.tools_layout.addWidget(self.coordinates.get_coordinates_widget())
        #        self.tools_layout.addWidget(self.coordinates.get_coordinates_button())

        self.debug = DebugWidget(self.widget, self.controller)
        self.parent.enabled = False
        self.tools_layout.addWidget(self.debug.get_debug_widget())

    def get_tools_area(self):
        return self.dock
Ejemplo n.º 11
0
def imageInforShow(var):

    imageInforDock = QDockWidget('图像信息', var)

    imageInforDock.setFeatures(QDockWidget.DockWidgetClosable)
    imageInforDock.setWidget(imageInfor(var))

    return imageInforDock
Ejemplo n.º 12
0
 def add_youtubedownloader(self):
     widget = YoutubeDownloaderGUI()
     dockwidget = QDockWidget(parent = self,)
     dockwidget.setWidget(widget)
     dockwidget.setObjectName("Youtube Downloader")
     dockwidget.setWindowTitle("Youtube Downloader")
     dockwidget.setFeatures(dockwidget.DockWidgetMovable | dockwidget.DockWidgetClosable)
     self.addDockWidget(Qt.TopDockWidgetArea, dockwidget)
Ejemplo n.º 13
0
 def add_calc(self):
     widget = PyCalcCtrl()
     dockwidget = QDockWidget(parent = self,)
     dockwidget.setWidget(widget)
     dockwidget.setObjectName("Taschenrechner")
     dockwidget.setWindowTitle("Taschenrechner")
     dockwidget.setFeatures(dockwidget.DockWidgetMovable | dockwidget.DockWidgetClosable)
     self.addDockWidget(Qt.TopDockWidgetArea, dockwidget)
Ejemplo n.º 14
0
Archivo: app.py Proyecto: ipapi/ipap
    def initoptionspanel(self):
        label = QLabel('Filter')

        filtertype = QComboBox()
        filtertype.addItem('None')
        filtertype.addItem('Lowpass')
        filtertype.addItem('Highpass')
        filtertype.addItem('Bandreject')
        filtertype.addItem('Bandpass')
        filtertype.currentIndexChanged.connect(self.filtertypelistener)

        self.filterfunction = QComboBox()
        self.filterfunction.addItem('Ideal')
        self.filterfunction.addItem('Butterworth')
        self.filterfunction.addItem('Gaussian')
        self.filterfunction.currentIndexChanged.connect(self.filterfunctionlistener)
        self.filterfunction.setEnabled(False)

        self.filtercutoff = QDoubleSpinBox()
        self.filtercutoff.setValue(0.0)
        self.filtercutoff.setRange(0.0, 10000.0)
        self.filtercutoff.valueChanged.connect(self.filtercutofflistener)
        self.filtercutoff.setEnabled(False)

        self.filterbandwidth = QDoubleSpinBox()
        self.filterbandwidth.setValue(1.0)
        self.filterbandwidth.setRange(0.0, 10000.0)
        self.filterbandwidth.valueChanged.connect(self.filterbandwidthlistener)
        self.filterbandwidth.setEnabled(False)

        self.filterorder = QDoubleSpinBox()
        self.filterorder.setValue(1.0)
        self.filterorder.setRange(0.0, 10000.0)
        self.filterorder.valueChanged.connect(self.filterorderlistener)
        self.filterorder.setEnabled(False)

        loader = QMovie('loader.gif')
        loader.start()
        self.loadercontainer = QLabel()
        self.loadercontainer.setMovie(loader)
        self.loadercontainer.setVisible(False)

        formlayout = QFormLayout()
        formlayout.addRow('Type', filtertype)
        formlayout.addRow('Function', self.filterfunction)
        formlayout.addRow('Cut off', self.filtercutoff)
        formlayout.addRow('Bandwidth', self.filterbandwidth)
        formlayout.addRow('Order', self.filterorder)
        formlayout.addRow('', self.loadercontainer)

        filterbox = QGroupBox('Filter')
        filterbox.setLayout(formlayout)

        options = QDockWidget('Options')
        options.setFeatures(QDockWidget.DockWidgetFloatable)
        options.setFeatures(QDockWidget.DockWidgetMovable)
        options.setWidget(filterbox)
        self.addDockWidget(Qt.RightDockWidgetArea, options)
Ejemplo n.º 15
0
 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)
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
0
    def _createDock(self, widgetClass, widgetName, widgetArea, *param):
        """创建停靠组件"""

        widget = widgetClass(*param)

        dock = QDockWidget(widgetName, self)
        dock.setWidget(widget)
        dock.setObjectName(widgetName)
        dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(widgetArea, dock)
        return widget, dock
Ejemplo n.º 18
0
    def _createDock(self, widgetClass, widgetName, widgetArea, *param):
        """创建停靠组件"""

        widget = widgetClass(*param)

        dock = QDockWidget(widgetName, self)
        dock.setWidget(widget)
        dock.setObjectName(widgetName)
        dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(widgetArea, dock)
        return widget, dock
Ejemplo n.º 19
0
 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)
Ejemplo n.º 20
0
class main_win(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(main_win, self).__init__()
        self.setupUi(self)
        self.my_setupUi()  # 优化界面

        # self.trigger_connection()#信号与槽连接
        # self.view_dock_closeEvent()#重写dock关闭函数

    def my_setupUi(self):
        self.tree.setColumnCount(1)  # 设置列数
        self.tree.header().hide()
        self.mdi = QMdiArea()

        self.tabWidget = QTabWidget()
        self.tabWidget.setTabsClosable(True)
        #self.mdi.setViewMode(QMdiArea.TabbedView)  # 设置为Tab多页显示模式
        #self.mdi.setTabsClosable(1)
        self.text_browser = QTextEdit(
            self)  # QtextEditClick继承自QTextEdit,内置于信息输出视图
        self.text_browser.setReadOnly(True)  # 仅作为信息输出,设置“只读”属性
        self.serial_info = QTextEdit(
            self)  # QtextEditClick继承自QTextEdit,内置于信息输出视图
        self.serial_info.setReadOnly(True)
        #self.loadFile(self.filename)
        # 1.3创建信息输出视图
        self.dock_serial = QDockWidget('Serial monitor', self)
        # self.dock_connection.setText("connnnn")
        # self.dock_serial.setMinimumSize(600, 150)
        self.dock_serial.setWidget(self.serial_info)
        self.dockBuilt = QDockWidget('Built output', self)
        # self.dockBuilt.setFearures(DockWidgetClosable)
        self.dockBuilt.setFeatures(QDockWidget.DockWidgetClosable
                                   | QDockWidget.DockWidgetMovable)
        self.dockBuilt.setMinimumSize(600, 150)  # 宽=600,高=   150
        self.dockBuilt.setWidget(self.text_browser)
        self.tabifyDockWidget(self.dockBuilt, self.dock_serial)
        splitter1 = QSplitter(Qt.Vertical)
        splitter1.addWidget(self.mdi)  # 多文档视图占布局右上
        splitter1.addWidget(self.dockBuilt)  # 信息输出视图占布局右下
        # self.addDockWidget(Qt.LeftDockWidgetArea, self.dockProject)  # 工程视图占布局左边
        self.setCentralWidget(splitter1)
        self.tabifyDockWidget(self.dock_connection, self.dock_serial)

        self.tree.setIconSize(QSize(25, 25))
        self.tree.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.sub = QMdiSubWindow()
        self.sub.setWidget(self.tabWidget)
        self.mdi.addSubWindow(self.sub)
        self.sub.showMaximized()
        self.sub.setWindowFlags(Qt.FramelessWindowHint)
        self.set_tree()
Ejemplo n.º 21
0
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("计算几何 测试")
        """
        菜单栏
        """
        newAct = QAction("&新建", self)
        newAct.setShortcuts(QKeySequence.New)
        newAct.setStatusTip("新建一个工程")
        newAct.triggered.connect(self.newProject)

        openAct = QAction("&打开", self)
        openAct.setShortcuts(QKeySequence.Open)
        openAct.setStatusTip("打开存在的工程")
        openAct.triggered.connect(self.openProject)

        fileMenu = self.menuBar().addMenu("&工程")
        fileMenu.addAction(newAct)
        fileMenu.addAction(openAct)
        """
        工具栏
        """
        fileToolBar = self.addToolBar("工程")
        fileToolBar.addAction(newAct)
        fileToolBar.addAction(openAct)

        fileToolBar.setAllowedAreas(Qt.TopToolBarArea | Qt.BottomToolBarArea)
        self.addToolBar(Qt.TopToolBarArea, fileToolBar)
        """
        中心画布
        """
        self.mCanvas = MainCanvas()
        self.setCentralWidget(self.mCanvas)
        """
        状态栏
        """
        self.mStatusBar = StatusBar()
        self.setStatusBar(self.mStatusBar)
        """
        控制(dock)框
        """
        self.mCtrlWidget = CtrlWidget()
        ctrlDock = QDockWidget("控制")
        self.addDockWidget(Qt.RightDockWidgetArea, ctrlDock)
        ctrlDock.setWidget(self.mCtrlWidget)
        ctrlDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        """
        绑定信号和槽
        """
        self.mCanvas.msCurrentChanged.connect(self.CurrentChanged)
        self.mCanvas.msMove.connect(self.mStatusBar.Move)
        self.mCtrlWidget.msRun.connect(self.Run)
Ejemplo n.º 22
0
    def start_lexer(self):
        dock_name = QFileInfo(self.filename).fileName()
        token = QListWidget()
        error = QListWidget()
        sign = QListWidget()
        log = QListWidget()
        quaternary = QListWidget()
        self.docwidget[dock_name] = {"token": token, "error": error, "sign": sign, "log": log, 'quaternary': quaternary}
        token.itemDoubleClicked.connect(self.token_list_double_clicked_fun)
        error.itemDoubleClicked.connect(self.error_list_double_clicked_fun)
        self.lexer = Lexer(self.filename)
        try:
            self.lexer.sinOut.connect(self.show_toker_error_sign)
            self.lexer.start()
        except Exception as e:
            print("Start Lexer Error:", e)
        dock_token = QDockWidget(dock_name+"_Token")  # 实例化dockwidget类
        dock_token.setWidget(self.docwidget[dock_name]["token"])  # 带入的参数为一个QWidget窗体实例,将该窗体放入dock中
        dock_token.setObjectName(dock_name)
        dock_token.setFeatures(dock_token.AllDockWidgetFeatures)  # 设置dockwidget的各类属性
        self.addDockWidget(Qt.RightDockWidgetArea, dock_token)  # 设置dockwidget放置在QMainWindow中的位置,并且将dockwidget添加至QMainWindow中

        dock_error = QDockWidget(dock_name+"_Error")
        dock_error.setWidget(self.docwidget[dock_name]["error"])
        dock_error.setObjectName(dock_name)
        dock_error.setFeatures(dock_error.AllDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, dock_error)

        dock_sign = QDockWidget(dock_name+"_sign")
        dock_sign.setWidget(self.docwidget[dock_name]["sign"])
        dock_sign.setObjectName(dock_name)
        dock_sign.setFeatures(dock_sign.AllDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, dock_sign)

        dock_log = QDockWidget(dock_name + "_log")
        dock_log.setWidget(self.docwidget[dock_name]["log"])
        dock_log.setObjectName(dock_name)
        dock_log.setFeatures(dock_log.AllDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, dock_log)

        dock_quaternary = QDockWidget(dock_name + "_quaternary")
        dock_quaternary.setWidget(self.docwidget[dock_name]["quaternary"])
        dock_quaternary.setObjectName(dock_name)
        dock_quaternary.setFeatures(dock_log.AllDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, dock_quaternary)

        self.tabifyDockWidget(dock_token, dock_error)
        self.tabifyDockWidget(dock_error, dock_sign)
        self.tabifyDockWidget(dock_sign, dock_log)
        self.tabifyDockWidget(dock_log, dock_quaternary)
        print('ui')
Ejemplo n.º 23
0
Archivo: app.py Proyecto: ipapi/ipap
    def initinformationpanel(self):
        self.mselabel = QLabel('No image selected')

        infoform = QFormLayout()
        infoform.addRow('MSE:', self.mselabel)

        imagebox = QGroupBox('Image')
        imagebox.setLayout(infoform)

        information = QDockWidget('Information')
        information.setFeatures(QDockWidget.DockWidgetFloatable)
        information.setFeatures(QDockWidget.DockWidgetMovable)
        information.setWidget(imagebox)
        self.addDockWidget(Qt.RightDockWidgetArea, information)
def show(var):

    fileDock = QDockWidget(var)
    var.fileDirectory = QListWidget(var)

    var.fileDirectory.verticalScrollBar()  # 垂直滚动条
    var.fileDirectory.horizontalScrollBar()  # 水平滚动条
    # var.fileDirectory.setFixedSize(500, 300)
    # var.fileDirectory.itemDoubleClicked.connect(lambda: fileDirectoryDoubleClicked(var))

    fileDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
    fileDock.setWidget(var.fileDirectory)
    # var.fileDirectory.setStyleSheet("QListWidget{ color:red; }")

    return fileDock
Ejemplo n.º 25
0
    def __init_ui(self):
        self.create_menu()

        self.port_list = QListWidget(self)
        dock = QDockWidget(self.tr('Port list'), self)
        dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        dock.setFeatures(QDockWidget.DockWidgetMovable)
        dock.setWidget(self.port_list)
        self.addDockWidget(Qt.LeftDockWidgetArea, dock)

        self.central_widget = QTabWidget(self)
        self.setCentralWidget(self.central_widget)

        self.setMinimumSize(1000, 700)
        self.setWindowTitle('TRex Panel')
        self.show()
Ejemplo n.º 26
0
def helpInforShow(var):

    helpInforDock = QDockWidget('帮助信息', var)

    helpContent = QTextEdit(var)
    helpContent.setFrameShape(QFrame.Panel | QFrame.Sunken)  # 边框样式
    helpContent.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)  # 内容显示样式
    helpContent.setEnabled(False)
    helpContent.setFocusPolicy(Qt.NoFocus)
    helpContent.setLineWrapMode(QTextEdit.NoWrap)  # 一行文本不换行
    helpContent.verticalScrollBar()  # 垂直滚动
    helpContent.horizontalScrollBar()  # 水平滚动
    helpContent.setPlaceholderText('此处显示帮助文档')

    helpInforDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
    helpInforDock.setWidget(helpContent)

    return helpInforDock
Ejemplo n.º 27
0
 def addDock(self):
     dock1 = QDockWidget('Items')
     # dock1.setFeatures(QDockWidget.DockWidgetFloatable)
     # dock1.setFeatures(QDockWidget.DockWidgetClosable)
     # dock1.setFeatures(QDockWidget.DockWidgetMovable)
     dock1.setFeatures(QDockWidget.DockWidgetMovable
                       | QDockWidget.DockWidgetFloatable
                       | QDockWidget.DockWidgetClosable)
     # dock1.setFeatures(QDockWidget.DockWidgetVerticalTitleBar)
     # dock1.setFeatures(QDockWidget.NoDockWidgetFeatures)
     dock1.setAllowedAreas(Qt.RightDockWidgetArea
                           | Qt.LeftDockWidgetArea)  # 可停靠位置为左右
     listwidget = QListWidget()
     listwidget.addItems(self.items)
     listwidget.currentRowChanged.connect(
         self.onDockListIndexChanged)  # 当选择有变化时的动作
     dock1.setWidget(listwidget)
     self.addDockWidget(Qt.LeftDockWidgetArea, dock1)  # 初始显示位置
Ejemplo n.º 28
0
class Main(QMainWindow):

    def __init__(self):
        super(Main, self).__init__()
        self.tabw = QTabWidget(self)

        self.cw1 = MoveRename()
        self.tabw.addTab(self.cw1, 'Mover/Renombrar')

        self.cw2 = Falta()
        self.tabw.addTab(self.cw2, 'Falta')

        # self.cw3 = FTPGui()
        # self.tabw.addTab(self.cw3,'FTP')

        self.cw4 = FileGui()
        self.tabw.addTab(self.cw4, 'Sync')

        self.cw5 = About()
        self.tabw.addTab(self.cw5, 'About')

        self.tabw.setTabShape(QTabWidget.Triangular)
        self.tabw.setTabPosition(QTabWidget.West)
        self.setCentralWidget(self.tabw)
        self.logs = QTextEdit()
        self.logs.setReadOnly(True)
        self.logsdock = QDockWidget("Logs", self)
        self.logsdock.setAllowedAreas(
            Qt.BottomDockWidgetArea | Qt.TopDockWidgetArea)
        self.logsdock.setWidget(self.logs)
        self.logsdock.setFeatures(QDockWidget.DockWidgetMovable)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.logsdock)
        self.cw1.logginn.connect(self.loggin)
        self.cw2.logginn.connect(self.loggin)
        # self.cw3.logginn.connect(self.loggin)
        self.cw4.logginn.connect(self.loggin)

    @pyqtSlot(str, str, int)
    def loggin(self, name, txt, level):
        if self.logs.document().lineCount() > 1000:
            self.logs.clear()
        txtt = logcolor(name + ': ', NAME)
        txtt += logcolor(txt, level)
        self.logs.append(txtt)
Ejemplo n.º 29
0
 def histogramWin(self):
     if self.hist is None:
         histTab = QDockWidget("histogram cam {0}".format(self.iCam), self)
         widget = QWidget()
         layout = QGridLayout()
         widget.setLayout(layout)
         win = pg.GraphicsLayoutWidget()
         p1 = win.addPlot()
         p1.getViewBox().invertY(True)
         p1.hideAxis('left')
         p1.hideAxis('bottom')
         
         self.hist = pg.HistogramLUTItem()
         self.hist.axis.setPen('k')
         p1.addItem(self.hist)
         self.hist.setImageItem(self.view)
         layout.addWidget(win,0,0)
         histTab.setWidget(widget)
         histTab.setAllowedAreas(Qt.LeftDockWidgetArea |
                                 Qt.RightDockWidgetArea |
                                 Qt.BottomDockWidgetArea |
                                 Qt.TopDockWidgetArea)
         histTab.setFeatures(QDockWidget.DockWidgetMovable |
                             QDockWidget.DockWidgetFloatable |
                             QDockWidget.DockWidgetClosable)
         self.parent.addDockWidget(Qt.BottomDockWidgetArea
                                   ,histTab)
         histTab.setFloating(True)
     
         histTab.resize(200,200)
     try:
         histstate = self.hist.saveState()
     except Exception as err:
         display('[ERROR] - could not save histogram state. "pip install pyqtgraph --upgrade" might solve it.')
         print(err)
     def closefun(ev):
         try:
             self.hist.restoreState(histstate)
         except Exception as err:
             print(err)
             pass
         self.hist = None
         ev.accept()
     histTab.closeEvent = closefun
Ejemplo n.º 30
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        # Main Window Toolbar
        self.tool_bar = QToolBar()
        self.addToolBar(QtCore.Qt.TopToolBarArea, self.tool_bar)
        self.database_open = QAction(self)
        database_open_ico = self.style().standardIcon(QStyle.SP_DirOpenIcon)
        self.database_open.setIcon(database_open_ico)
        self.database_open.setToolTip('Выбрать базу данных')
        self.database_open.triggered.connect(self.on_database_open)
        self.tool_bar.addAction(self.database_open)

        # Central widget - query table
        self.tdw = QDockWidget()
        self.tdw.setFeatures(self.tdw.NoDockWidgetFeatures)
        self.tdw_grid = QGridLayout()
        self.tdw_grid.setColumnStretch(2, 1)
        self.tdw_frame = QFrame()
        self.tdw_frame.setStyleSheet(
            "background-color: ghostwhite;"
            "border-width: 0.5px;"
            "border-style: solid;"
            "border-color: silver;")
        self.tdw_frame.setLayout(self.tdw_grid)
        self.tdw.setWidget(self.tdw_frame)

        # Bottom widget
        self.serv_mes = QDockWidget()
        self.serv_mes.setFixedSize(1400, 80)
        self.serv_mes.setFeatures(self.serv_mes.NoDockWidgetFeatures)
        self.listWidget = QListWidget()

    # Function of form opening
    def on_database_open(self):
        db_choose_win = DBChooseClass(self)
        db_choose_win.setWindowTitle('Форма выбора режима работы с программой')
        db_choose_win.show()
        screen = QDesktopWidget().screenGeometry()
        x = int((screen.width() - db_choose_win.width()) / 2)
        y = int((screen.height() - db_choose_win.height()) / 2)
        db_choose_win.move(x, y)
Ejemplo n.º 31
0
    def createSubwindow(self, title, position, closeable=True, widget=None):
        area_classes = {
            "left": Qt.LeftDockWidgetArea,
            "right": Qt.RightDockWidgetArea,
            "top": Qt.TopDockWidgetArea,
            "bottom": Qt.BottomDockWidgetArea,
        }
        area = area_classes[position]

        window = QDockWidget(title, self)
        features = QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable
        if closeable:
            features |= QDockWidget.DockWidgetClosable

        window.setFeatures(features)
        if widget is not None:
            window.setWidget(widget)

        self.addDockWidget(area, window)
        return window
Ejemplo n.º 32
0
            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)
Ejemplo n.º 33
0
         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)
Ejemplo n.º 34
0
Archivo: main.py Proyecto: lordmauve/mu
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))
Ejemplo n.º 35
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__()
        self.setWindowTitle("RainbowBB")
        self.setParent(parent)
        self.initUI()

    def initUI(self):
        self.setStyleSheet("QCheckBox { background: palette(window); border-radius: 4px; padding: 2px; margin-right: 2px; }")

        self.toolBar = QToolBar(self)
        self.toolBar.setStyleSheet(stylesheet % (create_gradient("pastel"),))
        self.toolBar.setMovable(False)
        self.toolBar.setContextMenuPolicy(Qt.CustomContextMenu)
        self.addToolBar(self.toolBar)

        self.reverseBox = QCheckBox("&Reverse", self)
        self.reverseBox.clicked.connect(lambda: self.updateGradient())
        self.toolBar.addWidget(self.reverseBox)

        self.byWordBox = QCheckBox("By &word", self)
        self.toolBar.addWidget(self.byWordBox)

        self.bounceBox = QCheckBox("&Bounce", self)
        self.bounceBox.clicked.connect(lambda: self.updateGradient())
        self.toolBar.addWidget(self.bounceBox)
        
        self.sizeList = QComboBox(self)
        self.sizeList.addItem("None")
        for num in range(1, 8):
            self.sizeList.addItem(str(num))
        self.toolBar.addWidget(self.sizeList)
        
        self.cycleList = QComboBox(self)
        self.toolBar.addWidget(self.cycleList)
        self.cycleList.currentIndexChanged.connect(self.updateGradient)
        self.loadCycles()
        
        self.convertButton = QPushButton("&Convert", self)
        self.convertButton.clicked.connect(self.convert)
        self.toolBar.addWidget(self.convertButton)

        self.reloadButton = QPushButton("Reload", self)
        self.reloadButton.setShortcut("Alt+Shift+R")
        self.reloadButton.clicked.connect(self.loadCycles)
        self.toolBar.addWidget(self.reloadButton)

        self.inputDock = QDockWidget("Input", self)
        self.inputDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.inputDock.setContextMenuPolicy(Qt.CustomContextMenu)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.inputDock)

        self.inputField = QTextEdit(self)
        self.inputField.setAcceptRichText(False)
        self.inputDock.setWidget(self.inputField)

        self.outputField = QTextEdit(self)
        self.outputField.setReadOnly(True)
        self.setCentralWidget(self.outputField)

    def updateGradient(self, index=None):
        if not index:
            index = self.cycleList.currentIndex()
        self.toolBar.setStyleSheet(stylesheet % (create_gradient(self.cycleList.itemText(index), self.reverseBox.isChecked(), self.bounceBox.isChecked()),))

    def loadCycles(self):
        rainbowbb.load_cycles()
        self.cycleList.clear()
        self.cycleList.addItem("pastel")
        for cycle in sorted(list(rainbowbb.cycles.keys())):
            if cycle != "pastel":
                self.cycleList.addItem(cycle)

    def show(self):
        self.setVisible(True)
        self.inputField.setFocus()

    def convert(self):
        self.outputField.setPlainText(rainbowbb.size(rainbowbb.colorize(self.inputField.toPlainText(), self.cycleList.currentText(), self.reverseBox.isChecked(), not self.byWordBox.isChecked(), self.bounceBox.isChecked()), self.sizeList.currentText() if self.sizeList.currentText() != "None" else None))
Ejemplo n.º 36
0
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")
Ejemplo n.º 37
0
class MusicPlayer(QMainWindow):
    """MusicPlayer houses all of elements that directly interact with the main window."""

    def __init__(self, parent=None):
        """Initialize the QMainWindow widget.

        The window title, window icon, and window size are initialized here as well
        as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar,
        QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and
        QVBoxLayout. The connect signals for relavant widgets are also initialized.
        """
        super(MusicPlayer, self).__init__(parent)
        self.setWindowTitle('Mosaic')

        window_icon = utilities.resource_filename('mosaic.images', 'icon.png')
        self.setWindowIcon(QIcon(window_icon))
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

        # Initiates Qt objects to be used by MusicPlayer
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist_location = defaults.Settings().playlist_path
        self.content = QMediaContent()
        self.menu = self.menuBar()
        self.toolbar = QToolBar()
        self.art = QLabel()
        self.pixmap = QPixmap()
        self.slider = QSlider(Qt.Horizontal)
        self.duration_label = QLabel()
        self.playlist_dock = QDockWidget('Playlist', self)
        self.library_dock = QDockWidget('Media Library', self)
        self.playlist_view = QListWidget()
        self.library_view = library.MediaLibraryView()
        self.library_model = library.MediaLibraryModel()
        self.preferences = configuration.PreferencesDialog()
        self.widget = QWidget()
        self.layout = QVBoxLayout(self.widget)
        self.duration = 0
        self.playlist_dock_state = None
        self.library_dock_state = None

        # Sets QWidget() as the central widget of the main window
        self.setCentralWidget(self.widget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        # Initiates the playlist dock widget and the library dock widget
        self.addDockWidget(defaults.Settings().dock_position, self.playlist_dock)
        self.playlist_dock.setWidget(self.playlist_view)
        self.playlist_dock.setVisible(defaults.Settings().playlist_on_start)
        self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable)

        self.addDockWidget(defaults.Settings().dock_position, self.library_dock)
        self.library_dock.setWidget(self.library_view)
        self.library_dock.setVisible(defaults.Settings().media_library_on_start)
        self.library_dock.setFeatures(QDockWidget.DockWidgetClosable)
        self.tabifyDockWidget(self.playlist_dock, self.library_dock)

        # Sets the range of the playback slider and sets the playback mode as looping
        self.slider.setRange(0, self.player.duration() / 1000)
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

        # OSX system menu bar causes conflicts with PyQt5 menu bar
        if sys.platform == 'darwin':
            self.menu.setNativeMenuBar(False)

        # Initiates Settings in the defaults module to give access to settings.toml
        defaults.Settings()

        # Signals that connect to other methods when they're called
        self.player.metaDataChanged.connect(self.display_meta_data)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.song_duration)
        self.player.positionChanged.connect(self.song_position)
        self.player.stateChanged.connect(self.set_state)
        self.playlist_view.itemActivated.connect(self.activate_playlist_item)
        self.library_view.activated.connect(self.open_media_library)
        self.playlist.currentIndexChanged.connect(self.change_index)
        self.playlist.mediaInserted.connect(self.initialize_playlist)
        self.playlist_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.library_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.preferences.dialog_media_library.media_library_line.textChanged.connect(self.change_media_library_path)
        self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect(self.change_window_size)
        self.art.mousePressEvent = self.press_playback

        # Creating the menu controls, media controls, and window size of the music player
        self.menu_controls()
        self.media_controls()
        self.load_saved_playlist()

    def menu_controls(self):
        """Initiate the menu bar and add it to the QMainWindow widget."""
        self.file = self.menu.addMenu('File')
        self.edit = self.menu.addMenu('Edit')
        self.playback = self.menu.addMenu('Playback')
        self.view = self.menu.addMenu('View')
        self.help_ = self.menu.addMenu('Help')

        self.file_menu()
        self.edit_menu()
        self.playback_menu()
        self.view_menu()
        self.help_menu()

    def media_controls(self):
        """Create the bottom toolbar and controls used for media playback."""
        self.addToolBar(Qt.BottomToolBarArea, self.toolbar)
        self.toolbar.setMovable(False)

        play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
        self.play_action = QAction(QIcon(play_icon), 'Play', self)
        self.play_action.triggered.connect(self.player.play)

        stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png')
        self.stop_action = QAction(QIcon(stop_icon), 'Stop', self)
        self.stop_action.triggered.connect(self.player.stop)

        previous_icon = utilities.resource_filename('mosaic.images', 'md_previous.png')
        self.previous_action = QAction(QIcon(previous_icon), 'Previous', self)
        self.previous_action.triggered.connect(self.previous)

        next_icon = utilities.resource_filename('mosaic.images', 'md_next.png')
        self.next_action = QAction(QIcon(next_icon), 'Next', self)
        self.next_action.triggered.connect(self.playlist.next)

        repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
        self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self)
        self.repeat_action.setShortcut('R')
        self.repeat_action.triggered.connect(self.repeat_song)

        self.toolbar.addAction(self.play_action)
        self.toolbar.addAction(self.stop_action)
        self.toolbar.addAction(self.previous_action)
        self.toolbar.addAction(self.next_action)
        self.toolbar.addAction(self.repeat_action)
        self.toolbar.addWidget(self.slider)
        self.toolbar.addWidget(self.duration_label)

    def file_menu(self):
        """Add a file menu to the menu bar.

        The file menu houses the Open File, Open Multiple Files, Open Playlist,
        Open Directory, and Exit Application menu items.
        """
        self.open_action = QAction('Open File', self)
        self.open_action.setShortcut('O')
        self.open_action.triggered.connect(self.open_file)

        self.open_multiple_files_action = QAction('Open Multiple Files', self)
        self.open_multiple_files_action.setShortcut('M')
        self.open_multiple_files_action.triggered.connect(self.open_multiple_files)

        self.open_playlist_action = QAction('Open Playlist', self)
        self.open_playlist_action.setShortcut('CTRL+P')
        self.open_playlist_action.triggered.connect(self.open_playlist)

        self.open_directory_action = QAction('Open Directory', self)
        self.open_directory_action.setShortcut('D')
        self.open_directory_action.triggered.connect(self.open_directory)

        self.save_playlist_action = QAction('Save Playlist', self)
        self.save_playlist_action.setShortcut('CTRL+S')
        self.save_playlist_action.triggered.connect(self.save_playlist)

        self.exit_action = QAction('Quit', self)
        self.exit_action.setShortcut('CTRL+Q')
        self.exit_action.triggered.connect(self.closeEvent)

        self.file.addAction(self.open_action)
        self.file.addAction(self.open_multiple_files_action)
        self.file.addAction(self.open_playlist_action)
        self.file.addAction(self.open_directory_action)
        self.file.addSeparator()
        self.file.addAction(self.save_playlist_action)
        self.file.addSeparator()
        self.file.addAction(self.exit_action)

    def edit_menu(self):
        """Add an edit menu to the menu bar.

        The edit menu houses the preferences item that opens a preferences dialog
        that allows the user to customize features of the music player.
        """
        self.preferences_action = QAction('Preferences', self)
        self.preferences_action.setShortcut('CTRL+SHIFT+P')
        self.preferences_action.triggered.connect(lambda: self.preferences.exec_())

        self.edit.addAction(self.preferences_action)

    def playback_menu(self):
        """Add a playback menu to the menu bar.

        The playback menu houses
        """
        self.play_playback_action = QAction('Play', self)
        self.play_playback_action.setShortcut('P')
        self.play_playback_action.triggered.connect(self.player.play)

        self.stop_playback_action = QAction('Stop', self)
        self.stop_playback_action.setShortcut('S')
        self.stop_playback_action.triggered.connect(self.player.stop)

        self.previous_playback_action = QAction('Previous', self)
        self.previous_playback_action.setShortcut('B')
        self.previous_playback_action.triggered.connect(self.previous)

        self.next_playback_action = QAction('Next', self)
        self.next_playback_action.setShortcut('N')
        self.next_playback_action.triggered.connect(self.playlist.next)

        self.playback.addAction(self.play_playback_action)
        self.playback.addAction(self.stop_playback_action)
        self.playback.addAction(self.previous_playback_action)
        self.playback.addAction(self.next_playback_action)

    def view_menu(self):
        """Add a view menu to the menu bar.

        The view menu houses the Playlist, Media Library, Minimalist View, and Media
        Information menu items. The Playlist item toggles the playlist dock into and
        out of view. The Media Library items toggles the media library dock into and
        out of view. The Minimalist View item resizes the window and shows only the
        menu bar and player controls. The Media Information item opens a dialog that
        shows information relevant to the currently playing song.
        """
        self.dock_action = self.playlist_dock.toggleViewAction()
        self.dock_action.setShortcut('CTRL+ALT+P')

        self.library_dock_action = self.library_dock.toggleViewAction()
        self.library_dock_action.setShortcut('CTRL+ALT+L')

        self.minimalist_view_action = QAction('Minimalist View', self)
        self.minimalist_view_action.setShortcut('CTRL+ALT+M')
        self.minimalist_view_action.setCheckable(True)
        self.minimalist_view_action.triggered.connect(self.minimalist_view)

        self.view_media_info_action = QAction('Media Information', self)
        self.view_media_info_action.setShortcut('CTRL+SHIFT+M')
        self.view_media_info_action.triggered.connect(self.media_information_dialog)

        self.view.addAction(self.dock_action)
        self.view.addAction(self.library_dock_action)
        self.view.addSeparator()
        self.view.addAction(self.minimalist_view_action)
        self.view.addSeparator()
        self.view.addAction(self.view_media_info_action)

    def help_menu(self):
        """Add a help menu to the menu bar.

        The help menu houses the about dialog that shows the user information
        related to the application.
        """
        self.about_action = QAction('About', self)
        self.about_action.setShortcut('H')
        self.about_action.triggered.connect(lambda: about.AboutDialog().exec_())

        self.help_.addAction(self.about_action)

    def open_file(self):
        """Open the selected file and add it to a new playlist."""
        filename, success = QFileDialog.getOpenFileName(self, 'Open File', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            file_info = QFileInfo(filename).fileName()
            playlist_item = QListWidgetItem(file_info)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(filename)))
            self.player.setPlaylist(self.playlist)
            playlist_item.setToolTip(file_info)
            self.playlist_view.addItem(playlist_item)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_multiple_files(self):
        """Open the selected files and add them to a new playlist."""
        filenames, success = QFileDialog.getOpenFileNames(self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            self.playlist.clear()
            self.playlist_view.clear()
            for file in natsort.natsorted(filenames, alg=natsort.ns.PATH):
                file_info = QFileInfo(file).fileName()
                playlist_item = QListWidgetItem(file_info)
                self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                self.player.setPlaylist(self.playlist)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)
                self.playlist_view.setCurrentRow(0)
                self.player.play()

    def open_playlist(self):
        """Load an M3U or PLS file into a new playlist."""
        playlist, success = QFileDialog.getOpenFileName(self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '', QFileDialog.ReadOnly)

        if success:
            playlist = QUrl.fromLocalFile(playlist)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def save_playlist(self):
        """Save the media in the playlist dock as a new M3U playlist."""
        playlist, success = QFileDialog.getSaveFileName(self, 'Save Playlist', '', 'Playlist (*.m3u)', '')
        if success:
            saved_playlist = "{}.m3u" .format(playlist)
            self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u")

    def load_saved_playlist(self):
        """Load the saved playlist if user setting permits."""
        saved_playlist = "{}/.m3u" .format(self.playlist_location)
        if os.path.exists(saved_playlist):
            playlist = QUrl().fromLocalFile(saved_playlist)
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)

    def open_directory(self):
        """Open the selected directory and add the files within to an empty playlist."""
        directory = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ReadOnly)

        if directory:
            self.playlist.clear()
            self.playlist_view.clear()
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

            self.player.setPlaylist(self.playlist)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_media_library(self, index):
        """Open a directory or file from the media library into an empty playlist."""
        self.playlist.clear()
        self.playlist_view.clear()

        if self.library_model.fileName(index).endswith(('mp3', 'flac')):
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(self.library_model.filePath(index))))
            self.playlist_view.addItem(self.library_model.fileName(index))

        elif self.library_model.isDir(index):
            directory = self.library_model.filePath(index)
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

        self.player.setPlaylist(self.playlist)
        self.player.play()

    def display_meta_data(self):
        """Display the current song's metadata in the main window.

        If the current song contains metadata, its cover art is extracted and shown in
        the main window while the track number, artist, album, and track title are shown
        in the window title.
        """
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
            (album, artist, title, track_number, *__, artwork) = metadata.metadata(file_path)

            try:
                self.pixmap.loadFromData(artwork)
            except TypeError:
                self.pixmap = QPixmap(artwork)

            meta_data = '{} - {} - {} - {}' .format(track_number, artist, album, title)

            self.setWindowTitle(meta_data)
            self.art.setScaledContents(True)
            self.art.setPixmap(self.pixmap)
            self.layout.addWidget(self.art)

    def initialize_playlist(self, start):
        """Display playlist and reset playback mode when media inserted into playlist."""
        if start == 0:
            if self.library_dock.isVisible():
                self.playlist_dock.setVisible(True)
                self.playlist_dock.show()
                self.playlist_dock.raise_()

            if self.playlist.playbackMode() != QMediaPlaylist.Sequential:
                self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
                repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
                self.repeat_action.setIcon(QIcon(repeat_icon))

    def press_playback(self, event):
        """Change the playback of the player on cover art mouse event.

        When the cover art is clicked, the player will play the media if the player is
        either paused or stopped. If the media is playing, the media is set
        to pause.
        """
        if event.button() == 1 and configuration.Playback().cover_art_playback.isChecked():
            if (self.player.state() == QMediaPlayer.StoppedState or
                    self.player.state() == QMediaPlayer.PausedState):
                self.player.play()
            elif self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()

    def seek(self, seconds):
        """Set the position of the song to the position dragged to by the user."""
        self.player.setPosition(seconds * 1000)

    def song_duration(self, duration):
        """Set the slider to the duration of the currently played media."""
        duration /= 1000
        self.duration = duration
        self.slider.setMaximum(duration)

    def song_position(self, progress):
        """Move the horizontal slider in sync with the duration of the song.

        The progress is relayed to update_duration() in order
        to display the time label next to the slider.
        """
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.update_duration(progress)

    def update_duration(self, current_duration):
        """Calculate the time played and the length of the song.

        Both of these times are sent to duration_label() in order to display the
        times on the toolbar.
        """
        duration = self.duration

        if current_duration or duration:
            time_played = QTime((current_duration / 3600) % 60, (current_duration / 60) % 60,
                                (current_duration % 60), (current_duration * 1000) % 1000)
            song_length = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60),
                                (duration * 1000) % 1000)

            if duration > 3600:
                time_format = "hh:mm:ss"
            else:
                time_format = "mm:ss"

            time_display = "{} / {}" .format(time_played.toString(time_format), song_length.toString(time_format))

        else:
            time_display = ""

        self.duration_label.setText(time_display)

    def set_state(self, state):
        """Change the icon in the toolbar in relation to the state of the player.

        The play icon changes to the pause icon when a song is playing and
        the pause icon changes back to the play icon when either paused or
        stopped.
        """
        if self.player.state() == QMediaPlayer.PlayingState:
            pause_icon = utilities.resource_filename('mosaic.images', 'md_pause.png')
            self.play_action.setIcon(QIcon(pause_icon))
            self.play_action.triggered.connect(self.player.pause)

        elif (self.player.state() == QMediaPlayer.PausedState or self.player.state() == QMediaPlayer.StoppedState):
            self.play_action.triggered.connect(self.player.play)
            play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
            self.play_action.setIcon(QIcon(play_icon))

    def previous(self):
        """Move to the previous song in the playlist.

        Moves to the previous song in the playlist if the current song is less
        than five seconds in. Otherwise, restarts the current song.
        """
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def repeat_song(self):
        """Set the current media to repeat and change the repeat icon accordingly.

        There are four playback modes: repeat none, repeat all, repeat once, and shuffle.
        Clicking the repeat button cycles through each playback mode.
        """
        if self.playlist.playbackMode() == QMediaPlaylist.Sequential:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_all.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Loop:
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_once.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop:
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_shuffle.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Random:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

    def activate_playlist_item(self, item):
        """Set the active media to the playlist item dobule-clicked on by the user."""
        current_index = self.playlist_view.row(item)
        if self.playlist.currentIndex() != current_index:
            self.playlist.setCurrentIndex(current_index)

        if self.player.state() != QMediaPlayer.PlayingState:
            self.player.play()

    def change_index(self, row):
        """Highlight the row in the playlist of the active media."""
        self.playlist_view.setCurrentRow(row)

    def minimalist_view(self):
        """Resize the window to only show the menu bar and audio controls."""
        if self.minimalist_view_action.isChecked():

            if self.playlist_dock.isVisible():
                self.playlist_dock_state = True
            if self.library_dock.isVisible():
                self.library_dock_state = True

            self.library_dock.close()
            self.playlist_dock.close()

            QTimer.singleShot(10, lambda: self.resize(500, 0))

        else:
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

            if self.library_dock_state:
                self.library_dock.setVisible(True)

            if self.playlist_dock_state:
                self.playlist_dock.setVisible(True)

    def dock_visiblity_change(self, visible):
        """Change the size of the main window when the docks are toggled."""
        if visible and self.playlist_dock.isVisible() and not self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.playlist_dock.width() + 6,
                        self.height())

        elif visible and not self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif visible and self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif (not visible and not self.playlist_dock.isVisible() and not
                self.library_dock.isVisible()):
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def media_information_dialog(self):
        """Show a dialog of the current song's metadata."""
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
        else:
            file_path = None
        dialog = information.InformationDialog(file_path)
        dialog.exec_()

    def change_window_size(self):
        """Change the window size of the music player."""
        self.playlist_dock.close()
        self.library_dock.close()
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def change_media_library_path(self, path):
        """Change the media library path to the new path selected in the preferences dialog."""
        self.library_model.setRootPath(path)
        self.library_view.setModel(self.library_model)
        self.library_view.setRootIndex(self.library_model.index(path))

    def closeEvent(self, event):
        """Override the PyQt close event in order to handle save playlist on close."""
        playlist = "{}/.m3u" .format(self.playlist_location)
        if defaults.Settings().save_playlist_on_close:
            self.playlist.save(QUrl().fromLocalFile(playlist), "m3u")
        else:
            if os.path.exists(playlist):
                os.remove(playlist)
        QApplication.quit()
Ejemplo n.º 38
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)

        self.centralwidget.hide()

        self.parser = argparse.ArgumentParser("playground")
        self.parser.add_argument("-d", "--data-dir", type=str, help="data dir")
        self.parser.add_argument("-a", "--console-address", type=str, help="console address", default='localhost')
        self.parser.add_argument("-p", "--console-port", type=int, help="console port", default=2222)
        self.args = self.parser.parse_args()

        self.data_dir = self.args.data_dir
        self.console_port = self.args.console_port
        self.console_address = self.args.console_address

        self.project = CetechProject()

        self.api = QtConsoleAPI(self.console_address, self.console_port)

        self.setTabPosition(Qt.AllDockWidgetAreas, QTabWidget.North)

        self.script_editor_widget = ScriptEditor(project_manager=self.project, api=self.api)
        self.script_editor_dock_widget = QDockWidget(self)
        self.script_editor_dock_widget.setWindowTitle("Script editor")
        self.script_editor_dock_widget.hide()
        self.script_editor_dock_widget.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.script_editor_dock_widget.setWidget(self.script_editor_widget)
        self.addDockWidget(Qt.TopDockWidgetArea, self.script_editor_dock_widget)

        self.log_widget = LogWidget(self.api, self.script_editor_widget)
        self.log_dock_widget = QDockWidget(self)
        self.log_dock_widget.hide()
        self.log_dock_widget.setWindowTitle("Log")
        self.log_dock_widget.setWidget(self.log_widget)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.log_dock_widget)

        self.assetb_widget = AssetBrowser()
        self.assetb_dock_widget = QDockWidget(self)
        self.assetb_dock_widget.hide()
        self.assetb_dock_widget.setWindowTitle("Asset browser")
        self.assetb_dock_widget.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.assetb_dock_widget.setWidget(self.assetb_widget)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.assetb_dock_widget)

        self.recorded_event_widget = RecordEventWidget(api=self.api)
        self.recorded_event_dock_widget = QDockWidget(self)
        self.recorded_event_dock_widget.setWindowTitle("Recorded events")
        self.recorded_event_dock_widget.hide()
        self.recorded_event_dock_widget.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.recorded_event_dock_widget.setWidget(self.recorded_event_widget)
        self.addDockWidget(Qt.RightDockWidgetArea, self.recorded_event_dock_widget)

        #TODO bug #114 workaround. Disable create sub engine...
        if platform.system().lower() != 'darwin':
            self.ogl_widget = CetechWidget(self, self.api)
            self.ogl_dock = QDockWidget(self)
            self.ogl_dock.hide()
            self.ogl_dock.setWidget(self.ogl_widget)
            self.addDockWidget(Qt.TopDockWidgetArea, self.ogl_dock)

        self.tabifyDockWidget(self.assetb_dock_widget, self.log_dock_widget)

        self.assetb_widget.asset_clicked.connect(self.open_asset)

        self.file_watch = QFileSystemWatcher(self)
        self.file_watch.fileChanged.connect(self.file_changed)
        self.file_watch.directoryChanged.connect(self.dir_changed)

        self.build_file_watch = QFileSystemWatcher(self)
        self.build_file_watch.fileChanged.connect(self.build_file_changed)
        self.build_file_watch.directoryChanged.connect(self.build_dir_changed)

    def open_asset(self, path, ext):
        if self.script_editor_widget.support_ext(ext):
            self.script_editor_widget.open_file(path)
            self.script_editor_dock_widget.show()
            self.script_editor_dock_widget.focusWidget()

    def open_project(self, name, dir):
        self.project.open_project(name, dir)

        # self.project.run_cetech(build_type=CetechProject.BUILD_DEBUG, compile=True, continu=True, daemon=True)

        if platform.system().lower() == 'darwin':
            wid = None
        else:
            wid = self.ogl_widget.winId()

        self.project.run_cetech(build_type=CetechProject.BUILD_DEBUG, compile_=True, continue_=True,
                                wid=wid)


        self.api.start(QThread.LowPriority)

        self.assetb_widget.open_project(self.project.project_dir)
        self.assetb_dock_widget.show()
        self.log_dock_widget.show()

        #TODO bug #114 workaround. Disable create sub engine...
        if platform.system().lower() != 'darwin':
            self.ogl_dock.show()

        self.watch_project_dir()

    def watch_project_dir(self):
        files = self.file_watch.files()
        directories = self.file_watch.directories()

        if len(files):
            self.file_watch.removePaths(files)

        if len(directories):
            self.file_watch.removePaths(directories)

        files = self.build_file_watch.files()
        directories = self.build_file_watch.directories()

        if len(files):
            self.build_file_watch.removePaths(files)

        if len(directories):
            self.build_file_watch.removePaths(directories)

        files = []
        it = QDirIterator(self.project.source_dir, QDirIterator.Subdirectories)
        while it.hasNext():
            files.append(it.next())

        self.file_watch.addPaths(files)

        files = []
        it = QDirIterator(self.project.build_dir, QDirIterator.Subdirectories)
        while it.hasNext():
            files.append(it.next())

        self.build_file_watch.addPaths(files)

    def file_changed(self, path):
        self.api.compile_all()

    def dir_changed(self, path):
        self.watch_project_dir()

    def build_file_changed(self, path):
        self.api.autocomplete_list()

    def build_dir_changed(self, path):
        pass

    def open_script_editor(self):
        self.script_editor_dock_widget.show()

    def open_recorded_events(self):
        self.recorded_event_dock_widget.show()

    def closeEvent(self, evnt):
        self.api.disconnect()

        self.project.killall_process()

        self.statusbar.showMessage("Disconnecting ...")

        while self.api.connected:
            self.api.tick()

        self.statusbar.showMessage("Disconnected")

        evnt.accept()