Пример #1
1
class MdiAplicacion(QMainWindow):

    contador = 0

    def __init__(self):
        super().__init__()

        self.inicializarGui()
    
    def inicializarGui(self):
        self.setWindowTitle('Ventanas MDI - Multiple Document Interface')

        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)

        mbr_principal = self.menuBar()
        mnu_archivo = mbr_principal.addMenu('Archivo')

        mni_agregar_ventana = QAction('Agregar ventana', self)
        mni_agregar_ventana.triggered.connect(self.agregar_ventana)

        mni_salir = QAction('Salir', self)
        mni_salir.setShortcut('Ctrl+Q')
        mni_salir.triggered.connect(self.close)

        mnu_archivo.addAction(mni_agregar_ventana)
        mnu_archivo.addAction(mni_salir)
    
    def agregar_ventana(self):
        MdiAplicacion.contador += 1

        subventana = QMdiSubWindow()
        subventana.setWindowTitle(f'Subventana {MdiAplicacion.contador}')
        self.mdi.addSubWindow(subventana)
        subventana.show()
Пример #2
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # create sub windows
        self.mdi_area = QMdiArea()

        start_widget = StartWidget()
        start_widget.start_signal.connect(self.create_arithmetic_widget)
        self.start_window = self.mdi_area.addSubWindow(start_widget)
        self.start_window.setWindowFlags(Qt.FramelessWindowHint)
        self.start_window.showMaximized()

        self.arithmetic_widget = None

        self.setCentralWidget(self.mdi_area)

    def create_arithmetic_widget(self, operand_range: tuple, operators: tuple):
        arithmetic_widget = ArithmeticWidget(operand_range, operators)
        arithmetic_widget.stop_signal.connect(self.reshow_start_widget)
        self.arithmetic_widget = self.mdi_area.addSubWindow(arithmetic_widget)
        self.arithmetic_widget.setWindowFlags(Qt.FramelessWindowHint)
        self.start_window.hide()
        self.arithmetic_widget.showMaximized()

    def move_to_center(self):
        """Move window to center desktop"""
        point = QPoint(self.width() // 2, self.height() // 2 + 100)
        pos = QApplication.desktop().availableGeometry().center()
        self.move(pos - point)

    def reshow_start_widget(self):
        self.mdi_area.activeSubWindow().close()
        self.start_window.showMaximized()
Пример #3
0
class MDIWindow(QMainWindow):

    count = 0

    def __init__(self):
        super().__init__()

        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        bar = self.menuBar()

        file = bar.addMenu("File")
        file.addAction("New")
        file.addAction("cascade")
        file.addAction("Tiled")
        file.triggered[QAction].connect(self.WindowTrig)
        self.setWindowTitle("MDI Application")

    def WindowTrig(self, p):

        if p.text() == "New":
            MDIWindow.count = MDIWindow.count + 1
            sub = QMdiSubWindow()
            sub.setWidget(QTextEdit())
            sub.setWindowTitle("Sub Window" + str(MDIWindow.count))
            self.mdi.addSubWindow(sub)
            sub.show()

        if p.text() == "cascade":
            self.mdi.cascadeSubWindows()

        if p.text() == "Tiled":
            self.mdi.tileSubWindows()
class Demo(QMainWindow):
    def __init__(self):
        super(Demo, self).__init__()
        self.mdi_area = QMdiArea(self)  # 1
        self.setCentralWidget(self.mdi_area)

        self.toolbar = self.addToolBar('Tool Bar')

        self.new_action = QAction(QIcon('images/new.ico'), 'New', self)  # 2
        self.close_action = QAction(QIcon('images/close.ico'), 'Close', self)
        self.close_all_action = QAction(QIcon('images/close_all.ico'),
                                        'Close All', self)
        self.mode1_action = QAction(QIcon('cascade.ico'), 'Cascade', self)
        self.mode2_action = QAction(QIcon('tile.ico'), 'Tile', self)

        self.new_action.triggered.connect(self.new_func)  # 3
        self.close_action.triggered.connect(self.mdi_area.closeActiveSubWindow)
        self.close_all_action.triggered.connect(
            self.mdi_area.closeAllSubWindows)
        self.mode1_action.triggered.connect(self.mdi_area.cascadeSubWindows)
        self.mode2_action.triggered.connect(self.mdi_area.tileSubWindows)

        self.toolbar.addAction(self.new_action)  # 4
        self.toolbar.addAction(self.close_action)
        self.toolbar.addAction(self.close_all_action)
        self.toolbar.addAction(self.mode1_action)
        self.toolbar.addAction(self.mode2_action)

    def new_func(self):
        text = QTextEdit()
        sub = QMdiSubWindow()
        sub.setWidget(text)
        self.mdi_area.addSubWindow(sub)
        sub.show()
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.title = 'event annotation tool'
        self.left = 50
        self.top = 50
        self.v_width = 640-200 #1400#
        self.v_height = 480-200 #1000#
        self.set_input=0

        self.setWindowTitle(self.title)

        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        self.mdi.tileSubWindows()

        PATH_FILE = '/home/barbara/Desktop/demo'#'/home/barbara/Desktop/car_data/Normal/Nevsky prospect traffic surveillance video'
        video_feed=action_time_antation_tool.annotation_openCV(PATH_FILE)

        v_sub = SubWindow(video_feed)  # QMdiSubWindow()
        v_sub.setWidget(video_feed)
        v_sub.resize(self.v_width+25, self.v_height+75)
        v_sub.setMaximumSize(self.v_width+25, self.v_height+75)
        v_sub.setWindowTitle("Feed " + str(len(self.label_v_list)))
        self.mdi.addSubWindow(v_sub)  # self.mdi
        self.mdi.tileSubWindows()
        v_sub.show()
Пример #6
0
class MainWindow(QMainWindow):
    count = 0

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        bar = self.menuBar()

        file = bar.addMenu("File")
        file.addAction("New")
        file.triggered[QAction].connect(self.windowaction)
        self.setWindowTitle("MDI demo")

    @pyqtSlot(str)
    def windowclosed(self, text):
        print(text)

    def windowaction(self, q):
        if q.text() == "New":
            MainWindow.count = MainWindow.count + 1
            sub = MdiSubWindow()
            sub.setWidget(QTextEdit())
            sub.setAttribute(Qt.WA_DeleteOnClose)
            sub.setWindowTitle("subwindow" + str(MainWindow.count))
            sub.sigClosed.connect(self.windowclosed)
            self.mdi.addSubWindow(sub)
            sub.show()
Пример #7
0
class App(QMainWindow):
    def __init__(self, parent=None):
        super(App, self).__init__(parent)
        self.title = "DndTool"
        self.width, self.height = 1280, 720
        self.x, self.y = 100, 100
        self.mdi = QMdiArea()
        self.menu = self.menuBar()
        self.status = self.statusBar()

        windows_menu = self.menu.addMenu('Windows')
        windows_menu.addAction("Players")
        windows_menu.addAction("Debug")
        windows_menu.triggered.connect(self.open_windows)

        self.setWindowTitle(self.title)
        self.setGeometry(self.x, self.y, self.width, self.height)
        self.setCentralWidget(self.mdi)

        self.show()

    def open_windows(self, action):
        if action.text() == "Players":
            sub = PlayersSubWindow()
            self.mdi.addSubWindow(sub)
            sub.show()
        elif action.text() == "Debug":
            print(
                [window.windowTitle() for window in self.mdi.subWindowList()])
class MainWin(QMainWindow):
    """主窗口"""
    count = 0

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setWindowTitle("QMdiArea QMdiSubWidow 使用")

        self.mdi_area = QMdiArea()
        self.setCentralWidget(self.mdi_area)

        menu_bar = self.menuBar()
        menu_file = menu_bar.addMenu("文件")
        action_new = menu_file.addAction("新建")
        action_new.setData("new")
        action_save = menu_file.addAction("保存")
        action_save.setData("save")
        action_cascade = menu_file.addAction("级联&Cascade")
        action_cascade.setData("cascade")
        action_tiled = menu_file.addAction("平铺&Tiled")
        action_tiled.setData("tiled")
        menu_file.triggered.connect(self.window_action)

    def window_action(self, action):
        print("点击", action.data())
        if action.data() == "new":
            MainWin.count += 1
            sub_win = QMdiSubWindow()
            sub_win.setWidget(QTextEdit())
            sub_win.setWindowTitle("子窗口 %d" % MainWin.count)
            self.mdi_area.addSubWindow(sub_win)
        if action.data() == "csscade":
            self.mdi_area.cascadeSubWindows()  # 级联模式排列
        if action.data() == "tiled":
            self.mdi_area.tileSubWindows()  # 平铺排列
Пример #9
0
    def setupWindows(self):
        """
        Set up QMdiArea parent and subwindows.
        Add available cameras on local system as items to 
        list widget.
        """
        # Create images directory if it does not already exist
        path = 'images'
        if not os.path.exists(path):
            os.makedirs(path)

        # Set up list widget that will display identified
        # cameras on your computer.
        picture_label = QLabel("Press 'Spacebar' to take pictures.")
        camera_label = QLabel("Available Cameras")
        self.camera_list_widget = QListWidget()
        self.camera_list_widget.setAlternatingRowColors(True)

        # Add availableCameras to a list to be displayed in
        # list widget. Use QCameraInfo() to list available cameras.
        self.cameras = list(QCameraInfo().availableCameras())
        for camera in self.cameras:
            self.list_item = QListWidgetItem()
            self.list_item.setText(camera.deviceName())
            self.camera_list_widget.addItem(self.list_item)

        # Create button that will allow user to select camera
        choose_cam_button = QPushButton("Select Camera")
        choose_cam_button.clicked.connect(self.selectCamera)

        # Create child widgets and layout for camera controls subwindow
        controls_gbox = QGroupBox()
        controls_gbox.setTitle("Camera Controls")

        v_box = QVBoxLayout()
        v_box.addWidget(picture_label, alignment=Qt.AlignCenter)
        v_box.addWidget(camera_label)
        v_box.addWidget(self.camera_list_widget)
        v_box.addWidget(choose_cam_button)

        controls_gbox.setLayout(v_box)

        controls_sub_window = QMdiSubWindow()
        controls_sub_window.setWidget(controls_gbox)
        controls_sub_window.setAttribute(Qt.WA_DeleteOnClose)

        # Create view finder subwindow
        self.view_finder_window = QMdiSubWindow()
        self.view_finder_window.setWindowTitle("Camera View")
        self.view_finder_window.setAttribute(Qt.WA_DeleteOnClose)

        # Create QMdiArea widget to manage subwindows
        mdi_area = QMdiArea()
        mdi_area.tileSubWindows()
        mdi_area.addSubWindow(self.view_finder_window)
        mdi_area.addSubWindow(controls_sub_window)

        # Set mdi_area widget as the central widget of main window
        self.setCentralWidget(mdi_area)
Пример #10
0
class SubWin(QMainWindow):
    count = 0
    def __init__(self):
        super().__init__()
        self.initUI()
    def initUI(self):
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        self.toolBar = QToolBar()
        self.addToolBar(self.toolBar)
        self.toolBar.addAction("新建")
        self.toolBar.addAction("级联")
        self.toolBar.addAction("平铺")
        self.toolBar.addAction("关闭全部")
        self.toolBar.addAction("关闭活动窗口")
        self.toolBar.addAction("测试")
        self.toolBar.actionTriggered[QAction].connect(self.windowaction)
        bar = self.menuBar()
        file = bar.addMenu("File")
        # 添加子菜单
        file.addAction("新建")
        file.addAction("级联")
        file.addAction("平铺")
        file.triggered[QAction].connect(self.windowaction)
        self.setWindowTitle("MDI Demo")
        #self.showFullScreen() #全屏显示
        self.showMaximized() #窗口最大化
        #self.showNormal() #正常显示
        # self.setGeometry(QDesktopWidget().screenGeometry())
    def windowaction(self, q):
        type = q.text()
        print("Triggered : %s" % type)
        if type == "新建":
            # 子窗口增加一个
            self.count = self.count + 1
            # 实例化多文档界面对象
            sub = QMdiSubWindow()
            # 向sub内部添加控件
            sub.setWidget(QTextEdit())
            sub.setWindowTitle("subWindow %d" % self.count)
            self.mdi.addSubWindow(sub)
            sub.show()
            #sub.hide()
        elif type == "级联":
            self.mdi.cascadeSubWindows()
        elif type == "平铺":
            self.mdi.tileSubWindows()
        elif type == "关闭全部":
            self.mdi.closeAllSubWindows()
        elif type == "关闭活动窗口":
            self.mdi.closeActiveSubWindow()
        elif type == "测试":
            lst = self.mdi.subWindowList()
            print(lst)
    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
Пример #11
0
class MDIWindow(QMainWindow):
    count = 0

    def __init__(self):
        super().__init__()

        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        bar = self.menuBar()

        self.current_dir = None

        file = bar.addMenu("File")
        file.addAction("New")
        file.addAction("cascade")
        file.addAction("Tiled")
        file.triggered[QAction].connect(self.WindowTrig)
        self.setWindowTitle("MDI Application")

        load = bar.addMenu("Load")
        load.addAction("2D")
        load.addAction("3D")
        load.triggered[QAction].connect(self.self.dir_open)



    def WindowTrig(self, p):

        if p.text() == "New":
            MDIWindow.count = MDIWindow.count + 1
            sub = QMdiSubWindow()
            sub.setWidget(QTextEdit())
            sub.setWindowTitle("Sub Window" + str(MDIWindow.count))
            self.mdi.addSubWindow(sub)
            sub.show()

        if p.text() == "cascade":
            self.mdi.cascadeSubWindows()

        if p.text() == "Tiled":
            self.mdi.tileSubWindows()


    def dir_open(self, p):

        if p.text() == "1D":
            self.current_dir = dlg.File_dlg.openDirNameDialog(self)
            files_ls = glob.glob(self.current_dir + '/*.ibw')
            fls = [f[len(self.current_dir) + 1:] for f in files_ls]
            print(fls)
#            self.twoD_list.addItems(fls)
#            self.threeD_list.addItems(zip)
        if p.text() == "2D":
            self.current_dir = dlg.File_dlg.openDirNameDialog(self)
            zip_ls = glob.glob(self.current_dir + '/*.zip')
            zp = [f[len(self.current_dir) + 1:] for f in zip_ls]
            print(zp)
Пример #12
0
    class MyMainWindow(QMainWindow):
        count = 0

        def __init__(self, widgets):
            super().__init__()

            self.widget_classes = widget_classes

            self.init_ui()

        def init_ui(self):
            self.setWindowTitle('MDI Application')
            self.setWindowIcon(QIcon('pyicon.png'))
            self.setGeometry(100, 100, 800, 600)

            # Create an instance of MDI.
            self.mdi = QMdiArea()
            self.setCentralWidget(self.mdi)

            # Menu bar.
            menu_bar = self.menuBar()

            file_menu = menu_bar.addMenu('File')
            file_menu.addAction('New')
            file_menu.addAction('Cascade')
            file_menu.addAction('Tiled')

            file_menu.triggered[QAction].connect(self.window_triggered)

            # Exit QAction.
            exit_action = QAction('Exit', self)
            exit_action.setShortcut(QKeySequence.Quit)
            exit_action.triggered.connect(self.close)

            file_menu.addAction(exit_action)

            # Status bar.
            status = self.statusBar()
            status.showMessage('Status bar')

        def window_triggered(self, p):
            if p.text() == 'New':
                MyMainWindow.count += 1

                sub = QMdiSubWindow()
                widget = self.widget_classes[MyMainWindow.count % 2]()
                sub.setWidget(widget)
                sub.setWindowTitle('Sub Window {}'.format(MyMainWindow.count))

                self.mdi.addSubWindow(sub)
                sub.show()

            if p.text() == 'Cascade':
                self.mdi.cascadeSubWindows()

            if p.text() == 'Tiled':
                self.mdi.tileSubWindows()
Пример #13
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()
Пример #14
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.sub_window_1 = QMdiSubWindow()
        self.sub_window_1.setWidget(QTextEdit("<h1>Hello World!</h1>"))

        self.sub_window_2 = QMdiSubWindow()
        self.sub_window_2.setWidget(QPushButton('Click!'))

        self.mdi_area = QMdiArea()
        self.mdi_area.addSubWindow(self.sub_window_1)
        self.mdi_area.addSubWindow(self.sub_window_2)

        self.setCentralWidget(self.mdi_area)
Пример #15
0
class mainwindow(QMainWindow):
    def __init__(self):
        super(mainwindow, self).__init__()

        # 主界面的布局
        layout = QHBoxLayout()
        w = QWidget()
        w.setLayout(layout)
        self.setCentralWidget(w)

        # 显示弹出的子窗口
        self.new_subwindow_btn = QPushButton("新建")
        layout.addWidget(self.new_subwindow_btn)
        self.new_subwindow_btn.clicked.connect(self.count)

        # 读取子窗口数据
        self.read_content_btn = QPushButton("读取")
        layout.addWidget(self.read_content_btn)
        self.read_content_btn.clicked.connect(self.get_content)

        # 创建多文档区域
        self.mdi = QMdiArea()
        layout.addWidget(self.mdi)

        # 要被创建的子窗口
        self.w = QWidget()

    def count(self):
        # 使用 mdi 类来管理,判断当前窗口是否包含对象
        # 如果不包含,创建。包含,不创建。
        if self.mdi.currentSubWindow() == None:
            sub = QMdiSubWindow()
            # 每次 sub 页面关闭,都会销毁包含进来的对象
            # 所以将包含的 半径、角度 等对象封装为一个类,或每次都新建
            self.w = PopWindow()
            sub.setWidget(self.w.get_window())
            sub.setWindowTitle("弹出窗口")
            # 如果不包含,弹出对话框可以浮动于任何位置,否则只能位于 mdi 区域内
            self.mdi.addSubWindow(sub)
            sub.show()

    def get_content(self):
        if self.mdi.currentSubWindow() != None:
            angle, radis, dis = self.w.get_angle(), self.w.get_radis(
            ), self.w.get_dis()
            print(angle, radis, dis)
Пример #16
0
class MainWindow(QMainWindow):
    def __init__(self, application_name):
        super(MainWindow, self).__init__()
        self.title = application_name
        self.mdi = QMdiArea()
        self.initialize_ui()

    def initialize_ui(self):
        self.setCentralWidget(self.mdi)
        self.setWindowTitle(self.title)
        self.showMaximized()

    def add_tile(self, module):
        self.mdi.addSubWindow(module)

    def tile(self):
        self.mdi.tileSubWindows()
Пример #17
0
class mainwindow(QMainWindow):
    def __init__(self):
        super(mainwindow, self).__init__()

        layout = QHBoxLayout()
        w = QWidget()
        w.setLayout(layout)
        self.setCentralWidget(w)

        self.new_subwindow_btn = QPushButton("新建")
        layout.addWidget(self.new_subwindow_btn)
        self.new_subwindow_btn.clicked.connect(self.count)

        self.mdi = QMdiArea()

        layout.addWidget(self.mdi)

    def count(self):
        subwindow_widget = QWidget()
        subwindow_layout = QGridLayout()
        self.sub = QMdiSubWindow()

        radis_label = QLabel("半径")
        radis_line = QLineEdit()
        subwindow_layout.addWidget(radis_label, 0, 0)
        subwindow_layout.addWidget(radis_line, 0, 1)

        angle_label = QLabel("角度")
        angle_line = QLineEdit()
        subwindow_layout.addWidget(angle_label, 1, 0)
        subwindow_layout.addWidget(angle_line, 1, 1)

        radis_label = QLabel("螺距")
        radis_line = QLineEdit()
        subwindow_layout.addWidget(radis_label, 2, 0)
        subwindow_layout.addWidget(radis_line, 2, 1)

        subwindow_widget.setLayout(subwindow_layout)
        self.sub.setWidget(subwindow_widget)

        self.sub.setWindowTitle("Sub Window")
        self.mdi.addSubWindow(self.sub)
        self.sub.show()

    def re_open(self):
        self.new_subwindow_btn.setEnabled(True)
Пример #18
0
class NetMainWindow(QMainWindow):
    def __init__(self):
        super(NetMainWindow, self).__init__()
        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)
        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.readSettings()
        self.setWindowTitle('Net')

    def newScan(self):
        child = IpRangeScanGUI(self)
        self.mdiArea.addSubWindow(child)
        child.show()
        return child

    def createActions(self):
        self.newIPScanAct = QAction("&Start a Scan",
                                    self,
                                    shortcut=QKeySequence.New,
                                    statusTip="Start a Scan",
                                    triggered=self.newScan)

    def createMenus(self):
        self.serverMenu = self.menuBar().addMenu('&IP Scan')
        self.serverMenu.addAction(self.newIPScanAct)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(500, 500))
        self.move(pos)
        self.resize(size)

    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)
Пример #19
0
class GuiMenu(Menu):
    def eventFilter(self, source, event):

        if event.type() == QtCore.QEvent.MouseMove:
            newClickPosition = source.mapTo(self.mdi, event.pos())
            for s in self.mdi.subWindowList():
                if source == s.widget() and self.moving:
                    newWidgetX = self.prevWidgetPosition.x() + newClickPosition.x() - self.downPosition.x()
                    newWidgetY = self.prevWidgetPosition.y() + newClickPosition.y() - self.downPosition.y()
                    s.move(newWidgetX, newWidgetY)

        elif event.type() == QtCore.QEvent.MouseButtonPress:
            if (source.cursor().shape() == QtCore.Qt.SizeVerCursor or source.cursor().shape() == QtCore.Qt.SizeHorCursor):
                # resizing hack: resizing works as some mdi feature, just don't set moving parameters here.
                pass
            else:
                self.downPosition = source.mapTo(self.mdi, event.pos())
                self.prevWidgetPosition = source.mapTo(self.mdi, source.pos())
                self.moving = True

        elif event.type() == QtCore.QEvent.MouseButtonRelease:
            self.moving = False

        return QWidget.eventFilter(self, source, event)

    def __init__(self):
        a = QTextEdit('some gui settings')
        b = QTextEdit('some gui settings too')

        widgets = [a, b]

        self.mdi = QMdiArea()
        self.moving = False
        layout = QVBoxLayout()
        layout.addWidget(self.mdi)

        super().__init__('GUI', layout)

        for w in widgets:
            self.mdi.addSubWindow(w, QtCore.Qt.FramelessWindowHint)
            w.setEnabled(False)
            w.setMouseTracking(True)
            w.installEventFilter(self)  # only called on subwindows -> no collision detection needed
Пример #20
0
class NetMainWindow(QMainWindow):
    def __init__(self):
        super(NetMainWindow, self).__init__()
        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)
        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.readSettings()
        self.setWindowTitle('Net')

    def newScan(self):
        child = IpRangeScanGUI(self)
        self.mdiArea.addSubWindow(child)
        child.show()
        return child

    def createActions(self):
        self.newIPScanAct = QAction("&Start a Scan", self, shortcut=QKeySequence.New, statusTip="Start a Scan",
                                    triggered=self.newScan)

    def createMenus(self):
        self.serverMenu = self.menuBar().addMenu('&IP Scan')
        self.serverMenu.addAction(self.newIPScanAct)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(500, 500))
        self.move(pos)
        self.resize(size)

    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)
Пример #21
0
class Example(QMainWindow):
    def __init__(self, parent=parent):
        super().__init__(self, parent)
        screen_resolution = app.desktop().screenGeometry()
        width, height = screen_resolution.width(), screen_resolution.height()

        self.initUI()

    def initUI(self):

        self.statusBar().showMessage('Ready')

        self.btn = QPushButton("Button", self)
        self.btn.setToolTip("Test Button")
        self.btn.setIcon(QIcon("/home/hsa/PycharmProjects/test12/home-6x.png"))
        #btn.setIconSize(QSize(24,24))
        self.btn.move(50, 50)
        self.btn.clicked.connect(self.on_clicked)

        self.setGeometry(0, 0, width, height)
        self.setWindowTitle('MainWindow')
        #self.mysubwindow()

    def mysubwindow(self):
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        self.sub = QMdiSubWindow()
        self.sub.setGeometry(10, 10, width - 30, height - 100)
        self.tabbar = QTabBar()
        self.sub.setWidget(self.tabbar)
        self.tabbar.addTab("Test1")
        self.tabbar.addTab("Test2")
        self.sub.setWindowTitle("subwindow")
        self.mdi.addSubWindow(self.sub)
        self.sub.show()

    @pyqtSlot()
    def on_clicked(self):
        print("Button clicked")
Пример #22
0
    def init_window(self):
        """
        Set up QMdiArea parent and sub_windows.
        Add available cameras on local system as items to
        list widget.
        """
        # Load image in sub_window_view
        self.load_image("images/chameleon.png")
        self.sub_window_view.setWidget(self.label_image)
        self.sub_window_models.setWidget(self.gbox_model)

        # Create QMdiArea widget to manage sub_windows
        mdi_area = QMdiArea()
        mdi_area.tileSubWindows()

        # mdi_area.addSubWindow(self.sub_window_camera)
        mdi_area.addSubWindow(self.sub_window_models)
        mdi_area.addSubWindow(self.sub_window_view)

        # Set up dock widget
        self.dock_camera.setWindowTitle("Camera Control")
        self.dock_camera.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.dock_camera.setWidget(self.camera_contents)

        self.dock_filter.setWindowTitle("Camera Filter")
        self.dock_filter.setWidget(self.filter_contents)

        self.dock_color.setWindowTitle("Camera Color")
        self.dock_color.setWidget(self.color_contents)
        self.dock_color.setVisible(False)

        # Set initial location of dock widget in main window
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_camera)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_filter)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_color)

        # Set mdi_area widget as the central widget of main window
        self.setCentralWidget(mdi_area)
Пример #23
0
class Ventana_Principal(QMainWindow):
    def __init__(self, parent=None):

        QMainWindow.__init__(self, parent)
        self.num_ventanas = 0
        self.setWindowTitle('Ejemplo de aplicacio MDI para getphones')
        self.setGeometry(0, 0, 800, 600)
        self.centraEnPantalla()

        self.mdi_area = QMdiArea()
        self.setCentralWidget(self.mdi_area)

    #personPhoto_FilePath is a string
    #personData is a tuple: #(name, surname, ubication, phone ext)
    #personExtension is a string
    def addNewFichaPersona(self, personPhoto_FilePath, personData,
                           personExtension):

        fichaPersona = Ficha_Persona()
        fichaPersona.setPersonPhoto(personPhoto_FilePath)
        fichaPersona.setPersonData(personData)
        fichaPersona.setPersonPhonenumber(personExtension)

        subventana = QMdiSubWindow()
        subventana.setWidget(fichaPersona)
        subventana.setWindowTitle('Subventana nº {}'.format(self.num_ventanas))
        self.mdi_area.addSubWindow(subventana)
        subventana.show()
        self.mdi_area.tileSubWindows()

    def centraEnPantalla(self):
        resolucion_pantalla = QDesktopWidget().screenGeometry()
        self.move(
            int(resolucion_pantalla.width() / 2 -
                self.frameSize().width() / 2),
            int(resolucion_pantalla.height() / 2 -
                self.frameSize().height() / 2))
class MDIWindow(QMainWindow):
    count = 0

    def __init__(self):

        super().__init__()
        uic.loadUi("mainwindow.ui", self)
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        self.menu_File.triggered[QAction].connect(self.WindowTrig)
        #self.setWindowTitle("MDI Application")

    def WindowTrig(self, p):
        if p.text() == "&New":
            MDIWindow.count = MDIWindow.count + 1
            sub = QMdiSubWindow()
            sub.setWidget(QTextEdit())
            sub.setWindowTitle("Sub Window" + str(MDIWindow.count))
            self.mdi.addSubWindow(sub)
            sub.show()
        if p.text() == "&Cascade":
            self.mdi.cascadeSubWindows()
        if p.text() == "&Tile":
            self.mdi.tileSubWindows()
Пример #25
0
class MdiQWebViewWindows(BaseQWebViewWindows):
    def __init__(self):
        super().__init__()
        self._mdi_area = None

    def add_webview(self, webview):
        if self._mdi_area is None:
            self._mdi_area = QMdiArea()
            self._mdi_area.resize(1024, 768)
            # self._mdi_area.setWindowTitle()
            self._mdi_area.show()
        subwindow = self._mdi_area.addSubWindow(webview)
        webview.titleChanged.connect(subwindow.setWindowTitle)
        subwindow.show()
        self._mdi_area.tileSubWindows()

    def remove_webview(self, webview):
        subwindow = webview.parentWidget()
        webview.close()
        self._mdi_area.removeSubWindow(subwindow)
        self._mdi_area.tileSubWindows()
Пример #26
0
class KOWRaidEditor(QMainWindow):
    def __init__(self, parent=None):
        super(KOWRaidEditor, self).__init__(parent)

        self.setWindowTitle("Raid Editor v0.1")
        self.setGeometry(100, 100, 1280, 960)  #changed basic geom to 1280*960
        self.center()
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)

        # todo: file import/export system 추가 필요
        self.init_ui()

        self._methods = []
        self._popup = QDialog()

        # test
        self.test_data()

        #
        self.__top_splitter = self.create_top_group_box()
        self.__top_splitter.setStretchFactor(1, 1)

        #
        main_layout = QVBoxLayout()
        main_layout.addWidget(self.__top_splitter)

        central_widget = QWidget()
        central_widget.setLayout(main_layout)

        #self.setCentralWidget(central_widget) // central widget 교체

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def test_data(self):
        self._methods.append(PyJavaMethod("test1", "sfsfsfs"))
        self._methods.append(PyJavaMethod("test2", "gasdfwqerasdf"))
        self._methods.append(PyJavaMethod("test3", "basdfinerlih"))
        self._methods.append(PyJavaMethod("test4", "gqwerasdf\nqfwe"))
        self._methods.append(
            PyJavaMethod(
                "test5",
                "sfsfsfs\nhgqwrgaswwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwdf\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhgqw\nhg3qw\nhgq412w"
            ))

    def init_ui(self):
        # menu bar
        act_newfile = QAction(QIcon('newfile.png'), '새로운 기사', self)
        act_newfile.setShortcut('Ctrl+N')
        act_newfile.setStatusTip('Create New File')
        act_newfile.triggered.connect(self.new_windows)
        # todo: link action creating new document

        act_openfile = QAction(QIcon('openfile.png'), '기사 불러오기', self)
        act_openfile.setShortcut('Ctrl+O')
        act_openfile.setStatusTip('Open Existing Article')

        act_savefile = QAction(QIcon('savefile.png'), '기사 저장하기', self)
        act_savefile.setShortcut('Ctrl+S')
        act_savefile.setStatusTip('Save Current Article')

        act_export = QAction(QIcon('export.png'), '&Export', self)
        act_export.setShortcut('Ctrl+E')
        act_export.setStatusTip('Export to Java SourceCode')
        act_export.triggered.connect(self.export_java)

        act_import = QAction(QIcon('import.png'), '&Import', self)
        act_import.setShortcut('Ctrl+I')
        act_import.setStatusTip('Import lua code')
        act_import.triggered.connect(self.import_lua)

        status_bar = self.statusBar()
        status_bar.showMessage('글자 수 표시 장소')
        menu_bar = self.menuBar()
        menu_bar.setNativeMenuBar(False)
        print(menu_bar.height())

        menu_file = menu_bar.addMenu('&File')
        menu_file.addAction(act_newfile)
        menu_file.addAction(act_openfile)
        menu_file.addAction(act_export)
        menu_file.addAction(act_import)

        #tool bar
        fontbox = QFontComboBox(self)
        fontbox.InsertPolicy()
        fontbox.setMinimumContentsLength(3)

        format_bar = self.addToolBar('Format')
        format_bar.addAction(act_newfile)
        format_bar.addAction(act_openfile)
        format_bar.addAction(act_savefile)
        format_bar.addSeparator()
        format_bar.addWidget(fontbox)

    def import_lua(self):
        return

    def export_java(self):
        return

    def new_windows(self):
        sub = QMdiSubWindow()
        sub.setWidget(QTextEdit())
        sub.setWindowTitle("New Article")
        sub.setGeometry(100, 100, 600, 320)

        self.mdi.addSubWindow(sub)
        sub.show()

    def create_top_group_box(self):
        top_splitter = QSplitter()
        top_splitter.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)

        # 좌
        top_left_group_box = QGroupBox("레이드 함수 목록")
        top_left_group_box.setSizePolicy(QSizePolicy.Expanding,
                                         QSizePolicy.Expanding)

        names = list(map(lambda i: i.get_name(), self._methods))
        model = QStringListModel(names)
        view = QListView()
        view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        view.setModel(model)
        view.clicked.connect(self.on_show_method)

        add_function = QPushButton("함수 추가")

        layout = QVBoxLayout()
        layout.addWidget(add_function)
        layout.addWidget(view)

        top_left_group_box.setLayout(layout)

        # 우
        top_right_group_box = QGroupBox("레이드 함수")

        # 우 - 텍스트
        tab_method_body = QTabWidget()

        tab_block = QWidget()

        tab_plain = QWidget()
        self._edit_method_body_plain = QTextEdit()
        tab_hbox_plain = QHBoxLayout()
        tab_hbox_plain.setContentsMargins(5, 5, 5, 5)
        tab_hbox_plain.addWidget(self._edit_method_body_plain)

        self._edit_method_body_block = PyJavaCode()
        self._edit_method_body_block.set_plain_view(
            self._edit_method_body_plain)
        tab_hbox_block = QHBoxLayout()
        tab_hbox_block.setContentsMargins(5, 5, 5, 5)
        tab_hbox_block.addWidget(self._edit_method_body_block)

        tab_block.setLayout(tab_hbox_block)
        tab_plain.setLayout(tab_hbox_plain)

        tab_method_body.addTab(tab_block, "&Block")
        tab_method_body.addTab(tab_plain, "&Plain")

        # 배치
        label_method_name = QLabel("name")
        self._edit_method_name = QLineEdit()
        label_method_body = QLabel("body")
        self._edit_method_body = tab_method_body

        #
        layout = QVBoxLayout()
        layout.addWidget(label_method_name)
        layout.addWidget(self._edit_method_name)
        layout.addWidget(label_method_body)
        layout.addWidget(self._edit_method_body)

        top_right_group_box.setLayout(layout)

        # test
        # top_left_group_box.setStyleSheet("color: blue;"
        #                       "background-color: #87CEFA;"
        #                       "border-style: dashed;"
        #                       "border-width: 3px;"
        #                       "border-color: #1E90FF")
        #
        # top_right_group_box.setStyleSheet("color: blue;"
        #                       "background-color: #87CEFA;"
        #                       "border-style: dashed;"
        #                       "border-width: 3px;"
        #                       "border-color: #1E90FF")

        # spliter
        top_splitter.addWidget(top_left_group_box)
        top_splitter.addWidget(top_right_group_box)

        return top_splitter

    def on_show_method(self, index):
        method = self._methods[index.row()]
        self._edit_method_name.setText(method.get_name())

        self.plain_to_block(method.get_body())
        self._edit_method_body_plain.setText(method.get_body())

        #
        pos_x = QCursor.pos().x() - self.pos().x()
        pos_y = QCursor.pos().y() - self.pos().y() - 30

        if self._popup:
            self._popup.hide()

        # self._popup = method.display_overlay(self, pos_x, pos_y)

    def plain_to_block(self, plain):
        self._edit_method_body_block.clear_widgets()

        for row in plain.split('\n'):
            self._edit_method_body_block.append_plain(row)
Пример #27
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("MDI Test")

    def closeEvent(self, event):
        self.mdiArea.closeAllSubWindows()
        if self.mdiArea.currentSubWindow():
            event.ignore()
        else:
            self.writeSettings()
            event.accept()

    def newFile(self):
        child = self.createMdiChild()
        child.newFile()
        child.show()

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self)
        if fileName:
            existing = self.findMdiChild(fileName)
            if existing:
                self.mdiArea.setActiveSubWindow(existing)
                return

            child = self.createMdiChild()
            if child.loadFile(fileName):
                self.statusBar().showMessage("File loaded", 2000)
                child.show()
            else:
                child.close()

    def save(self):
        if self.activeMdiChild() and self.activeMdiChild().save():
            self.statusBar().showMessage("File saved", 2000)

    def saveAs(self):
        if self.activeMdiChild() and self.activeMdiChild().saveAs():
            self.statusBar().showMessage("File saved", 2000)

    def cut(self):
        if self.activeMdiChild():
            self.activeMdiChild().cut()

    def copy(self):
        if self.activeMdiChild():
            self.activeMdiChild().copy()

    def paste(self):
        if self.activeMdiChild():
            self.activeMdiChild().paste()

    def about(self):
        QMessageBox.about(
            self, "About MDI",
            "The <b>MDI</b> example demonstrates how to write multiple "
            "document interface applications using Qt.")

    def updateMenus(self):
        hasMdiChild = (self.activeMdiChild() is not None)
        #self.saveAct.setEnabled(hasMdiChild)
        #self.saveAsAct.setEnabled(hasMdiChild)
        self.pasteAct.setEnabled(hasMdiChild)
        self.closeAct.setEnabled(hasMdiChild)
        self.closeAllAct.setEnabled(hasMdiChild)
        self.tileAct.setEnabled(hasMdiChild)
        self.cascadeAct.setEnabled(hasMdiChild)
        self.nextAct.setEnabled(hasMdiChild)
        self.previousAct.setEnabled(hasMdiChild)
        self.separatorAct.setVisible(hasMdiChild)

        hasSelection = (self.activeMdiChild() is not None
                        and self.activeMdiChild().textCursor().hasSelection())
        self.cutAct.setEnabled(hasSelection)
        self.copyAct.setEnabled(hasSelection)

    def updateWindowMenu(self):
        self.windowMenu.clear()
        self.windowMenu.addAction(self.closeAct)
        self.windowMenu.addAction(self.closeAllAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.tileAct)
        self.windowMenu.addAction(self.cascadeAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.nextAct)
        self.windowMenu.addAction(self.previousAct)
        self.windowMenu.addAction(self.separatorAct)

        windows = self.mdiArea.subWindowList()
        self.separatorAct.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            child = window.widget()

            text = "%d %s" % (i + 1, child.userFriendlyCurrentFile())
            if i < 9:
                text = '&' + text

            action = self.windowMenu.addAction(text)
            action.setCheckable(True)
            action.setChecked(child is self.activeMdiChild())
            action.triggered.connect(self.windowMapper.map)
            self.windowMapper.setMapping(action, window)

    def createMdiChild(self):
        child = MdiChild()
        self.mdiArea.addSubWindow(child)

        child.copyAvailable.connect(self.cutAct.setEnabled)
        child.copyAvailable.connect(self.copyAct.setEnabled)

        return child

    # showntell
    def createMdiChild15(self):
        child = MdiChild_ShowNTell()
        self.mdiArea.addSubWindow(child)
        return child

    #MNIST
    def show_n_tell(self):
        print('show_n_tell....')
        child = self.createMdiChild15()
        print('self.createMdiChild15')
        #child.resize(830,480)
        #print('self.createMdiChild15')
        child.show
        print('child.show()')

    def createActions(self):

        self.cutAct = QAction(
            QIcon(':/images/cut.png'),
            "Cu&t",
            self,
            shortcut=QKeySequence.Cut,
            statusTip="Cut the current selection's contents to the clipboard",
            triggered=self.cut)

        self.copyAct = QAction(
            QIcon(':/images/copy.png'),
            "&Copy",
            self,
            shortcut=QKeySequence.Copy,
            statusTip="Copy the current selection's contents to the clipboard",
            triggered=self.copy)

        self.pasteAct = QAction(
            QIcon(':/images/paste.png'),
            "&Paste",
            self,
            shortcut=QKeySequence.Paste,
            statusTip=
            "Paste the clipboard's contents into the current selection",
            triggered=self.paste)

        self.closeAct = QAction("Cl&ose",
                                self,
                                statusTip="Close the active window",
                                triggered=self.mdiArea.closeActiveSubWindow)

        self.closeAllAct = QAction("Close &All",
                                   self,
                                   statusTip="Close all the windows",
                                   triggered=self.mdiArea.closeAllSubWindows)

        self.tileAct = QAction("&Tile",
                               self,
                               statusTip="Tile the windows",
                               triggered=self.mdiArea.tileSubWindows)

        self.cascadeAct = QAction("&Cascade",
                                  self,
                                  statusTip="Cascade the windows",
                                  triggered=self.mdiArea.cascadeSubWindows)

        self.nextAct = QAction("Ne&xt",
                               self,
                               shortcut=QKeySequence.NextChild,
                               statusTip="Move the focus to the next window",
                               triggered=self.mdiArea.activateNextSubWindow)

        self.previousAct = QAction(
            "Pre&vious",
            self,
            shortcut=QKeySequence.PreviousChild,
            statusTip="Move the focus to the previous window",
            triggered=self.mdiArea.activatePreviousSubWindow)

        self.separatorAct = QAction(self)
        self.separatorAct.setSeparator(True)

        # 메뉴 ACTION을 다이나믹하게 연결해준다
        self.MenuActRef = {
            'NewFileAct': 0,
            'OpnFileAct': 0,
            'SavFileAct': 0,
            'SavASFileAct': 0,
            'AboutAct': 0,
            'AboutQTAct': 0,
            'ExitAct': 0,
            'SwitchLayout': 0,
            'ShowNTell': 0
        }

        # ******* Create the File Menu *******
        self.NewFileAct = QAction(QIcon(':/images/new.png'), '&New File', self)
        self.NewFileAct.setShortcut("Ctrl+N")
        self.NewFileAct.setStatusTip('Create a New  File')
        self.NewFileAct.triggered.connect(self.newFile)
        self.MenuActRef['NewFileAct'] = self.NewFileAct

        #self.newAct = QAction(QIcon(':/images/new.png'), "&New", self,
        #        shortcut=QKeySequence.New, statusTip="Create a new file",
        #        triggered=self.newFile)

        # ******* Open File Menu Items *******
        self.OpnFileAct = QAction(QIcon(':/images/open.png'), '&Open File',
                                  self)
        self.OpnFileAct.setShortcut("Ctrl+O")
        self.OpnFileAct.setStatusTip('Open an Existing File')
        self.OpnFileAct.triggered.connect(self.open)
        self.MenuActRef['OpnFileAct'] = self.OpnFileAct

        #self.openAct = QAction(QIcon(':/images/open.png'), "&Open...", self,
        #        shortcut=QKeySequence.Open, statusTip="Open an existing file",
        #        triggered=self.open)

        # ******* Save File Menu Items *******
        self.SavFileAct = QAction(QIcon(':/images/save.png'), '&Save File',
                                  self)
        self.SavFileAct.setShortcut("Ctrl+S")
        self.SavFileAct.setStatusTip('Save Current  File')
        self.SavFileAct.triggered.connect(self.save)
        self.MenuActRef['SavFileAct'] = self.SavFileAct

        #self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self,
        #        shortcut=QKeySequence.Save,
        #        statusTip="Save the document to disk", triggered=self.save)

        # ******* SaveAS File Menu Items *******
        self.SavASFileAct = QAction('Save &As File', self)
        self.SavASFileAct.setShortcut("Ctrl+A")
        self.SavASFileAct.setStatusTip('Save Current  File  under a new name ')
        self.SavASFileAct.triggered.connect(self.saveAs)
        self.MenuActRef['SavASFileAct'] = self.SavASFileAct

        #self.saveAsAct = QAction("Save &As...", self,
        #        shortcut=QKeySequence.SaveAs,
        #        statusTip="Save the document under a new name",
        #        triggered=self.saveAs)

        # ******* About Menu Items *******
        self.aboutAct = QAction("&About", self)
        self.aboutAct.setStatusTip("Show the application's About box")
        self.aboutAct.triggered.connect(self.about)
        self.MenuActRef['AboutAct'] = self.aboutAct

        # ******* About QT Menu Items *******
        self.aboutAct = QAction("About &Qt", self)
        self.aboutAct.setStatusTip("Show the Qt library's About box")
        self.aboutAct.triggered.connect(QApplication.instance().aboutQt)
        self.MenuActRef['AboutQTAct'] = self.aboutAct

        # ******* Exit Menu Items *******
        self.exitAct = QAction("E&xit", self)
        self.exitAct.setStatusTip("Exit the application")
        self.exitAct.triggered.connect(QApplication.instance().closeAllWindows)
        self.MenuActRef['ExitAct'] = self.exitAct

        #self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit,
        #        statusTip="Exit the application",
        #        triggered=QApplication.instance().closeAllWindows)

        # ******* Switch layout Items *******
        self.SwitchLayout = QAction("&Switch layout direction", self)
        self.SwitchLayout.setStatusTip("Switch layout direction")
        self.SwitchLayout.triggered.connect(self.switchLayoutDirection)
        self.MenuActRef['SwitchLayout'] = self.SwitchLayout

        #self.SwitchLayout = QAction("&Switch layout direction", self,
        #        statusTip="Switch layout direction",
        #        triggered=self.switchLayoutDirection)

        # ******* Switch layout Items *******
        self.ShowNTell = QAction("&ShowNTell", self)
        self.ShowNTell.setStatusTip("&ShowNTell")
        self.ShowNTell.triggered.connect(self.show_n_tell)
        self.MenuActRef['ShowNTell'] = self.ShowNTell

    #self.ShowNTell = QAction("&show_n_tell", self,
    #        statusTip="show_n_tell",
    #         triggered=self.show_n_tell)

    def createMenus(self):

        # 메뉴를 다이나믹하게 생성하고 연결함
        self.MenuLayout = {
            0: {
                'addMenu': '&File',
                'addToolMenu': 'File'
            },
            1: {
                'addDynamic': 'NewFileAct',
                'addToolbar': 'NewFileAct'
            },
            2: {
                'addDynamic': 'OpnFileAct',
                'addToolbar': 'OpnFileAct'
            },
            3: {
                'addDynamic': 'SavFileAct',
                'addToolbar': 'SavFileAct'
            },
            4: {
                'addDynamic': 'SavASFileAct'
            },
            5: {
                'addSeparator': ''
            },
            6: {
                'addDynamic': 'SwitchLayout'
            },
            7: {
                'addDynamic': 'ExitAct'
            },
            8: {
                'addMenu': '&Edit'
            },
            9: {
                'addAction': self.cutAct
            },
            10: {
                'addAction': self.copyAct
            },
            11: {
                'addAction': self.pasteAct
            },
            12: {
                'addMenu': '&Window'
            },
            13: {
                'updateMenu': ''
            },
            14: {
                'addSeparator': ''
            },
            15: {
                'addMenu': '&Help'
            },
            16: {
                'addDynamic': 'AboutAct'
            },
            17: {
                'addDynamic': 'AboutQTAct'
            },
            18: {
                'addMenu': '&MNIST'
            },
            19: {
                'addDynamic': 'ShowNTell'
            }
        }

        for idx in self.MenuLayout:
            item = self.MenuLayout[idx]

            if 'addMenu' in item.keys():
                self.windowMenu = self.menuBar().addMenu(item['addMenu'])

            elif 'addAction' in item.keys():
                self.windowMenu.addAction(item['addAction'])

            elif 'addSeparator' in item.keys():
                self.windowMenu.addSeparator()

            elif 'updateMenu' in item.keys():
                self.updateWindowMenu()
                self.windowMenu.aboutToShow.connect(self.updateWindowMenu)

            # 메뉴 ACTION을 다이나믹하게
            elif 'addDynamic' in item.keys():
                self.windowMenu.addAction(self.MenuActRef[item['addDynamic']])

    def createToolBars(self):

        for idx in self.MenuLayout:
            item = self.MenuLayout[idx]

            if 'addToolMenu' in item.keys():
                self.fileToolBar = self.addToolBar(item['addToolMenu'])

            elif 'addToolbar' in item.keys():
                self.fileToolBar.addAction(self.MenuActRef[item['addDynamic']])

        #self.fileToolBar = self.addToolBar("File")
        #self.fileToolBar.addAction(self.MenuActRef['NewFileAct'])
        #self.fileToolBar.addAction(self.MenuActRef['OpnFileAct'])
        #self.fileToolBar.addAction(self.MenuActRef['SavFileAct'])
        #self.fileToolBar.addAction(self.newAct)
        #self.fileToolBar.addAction(self.openAct)
        #self.fileToolBar.addAction(self.saveAct)

        self.editToolBar = self.addToolBar("Edit")
        self.editToolBar.addAction(self.cutAct)
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.pasteAct)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings('NH-Soft', 'MDI Example')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(400, 400))
        self.move(pos)
        self.resize(size)

    def writeSettings(self):
        settings = QSettings('NH-Soft', 'MDI Example')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())

    def activeMdiChild(self):
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        return None

    def findMdiChild(self, fileName):
        canonicalFilePath = QFileInfo(fileName).canonicalFilePath()

        for window in self.mdiArea.subWindowList():
            if window.widget().currentFile() == canonicalFilePath:
                return window
        return None

    def switchLayoutDirection(self):
        if self.layoutDirection() == Qt.LeftToRight:
            QApplication.setLayoutDirection(Qt.RightToLeft)
        else:
            QApplication.setLayoutDirection(Qt.LeftToRight)

    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)
Пример #28
0
class MainWindow(QMainWindow):
    count = 0

    def __init__(self, parent=None, qtapp=None):
        super().__init__(parent)
        self.qtapp = qtapp
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)

        self.app_manager = AppManager(None, gui_parent=self)
        self.mdi.subWindowActivated.connect(self.app_manager.
                                            on_view_activated)

        self.is_dark = self.light_or_dark(False)

        self.left = 100
        self.top = 50
        self.width = 1800
        self.height = 1200
        self.setGeometry(self.left, self.top, self.width, self.height)

        bar = self.menuBar()

        file_menu = bar.addMenu("File")
        file_menu.addAction("New")
        file_menu.addAction("Open...")
        file_menu.addSeparator()
        file_menu.addAction("Save")
        file_menu.addAction("Save As...")
        file_menu.addAction("Close")
        file_menu.triggered[QAction].connect(self.file_action)

        view_menu = bar.addMenu("Data View")
        view_menu.addAction("Spec Sheet")
        view_menu.addAction("Optical Layout")
        view_menu.addAction("Lens Table")
        view_menu.addAction("Element Table")
        view_menu.addAction("Glass Map")
        # view_menu.addAction("Lens View")
        view_menu.triggered[QAction].connect(self.view_action)

        parax_menu = bar.addMenu("Paraxial Model")
        parax_menu.addAction("Paraxial Model")
        parax_menu.addAction("y-ybar View")
        parax_menu.addAction("nu-nubar View")
        parax_menu.addAction("yui Ray Table")
        parax_menu.addAction("3rd Order Aberrations")
        parax_menu.triggered[QAction].connect(self.view_action)

        analysis_menu = bar.addMenu("Analysis")
        analysis_menu.addAction("Ray Table")
        analysis_menu.addAction("Ray Fans")
        analysis_menu.addAction("OPD Fans")
        analysis_menu.addAction("Spot Diagram")
        analysis_menu.addAction("Wavefront Map")
        analysis_menu.addAction("Astigmatism Curves")
        analysis_menu.triggered[QAction].connect(self.view_action)

        tools_menu = bar.addMenu("Tools")
        tools_menu.addAction("Paraxial Vignetting")
        tools_menu.triggered[QAction].connect(self.view_action)

        wnd_menu = bar.addMenu("Window")
        wnd_menu.addAction("Cascade")
        wnd_menu.addAction("Tiled")
        wnd_menu.addSeparator()
        wnd_menu.addAction("Light UI")
        wnd_menu.addAction("Dark UI")
        wnd_menu.addSeparator()

        dock.create_dock_windows(self)
        for pi in dock.panels.values():
            wnd_menu.addAction(pi.menu_action)

        wnd_menu.triggered[QAction].connect(self.window_action)

        self.setWindowTitle("Ray Optics")
        self.show()

        path = Path(rayoptics.__file__).parent
        self.cur_dir = path / "models"

        if False:
            # create new model
            self.new_model()

        else:
            # restore a default model

            # self.cur_dir = path / "codev/tests"
            # self.open_file(path / "codev/tests/asp46.seq")
            # self.open_file(path / "codev/tests/dar_test.seq")
            # self.open_file(path / "codev/tests/paraboloid.seq")
            # self.open_file(path / "codev/tests/paraboloid_f8.seq")
            # self.open_file(path / "codev/tests/schmidt.seq")
            # self.open_file(path / "codev/tests/questar35.seq")
            # self.open_file(path / "codev/tests/rc_f16.seq")
            # self.open_file(path / "codev/tests/ag_dblgauss.seq")
            # self.open_file(path / "codev/tests/threemir.seq")
            # self.open_file(path / "codev/tests/folded_lenses.seq")
            # self.open_file(path / "codev/tests/lens_reflection_test.seq")
            # self.open_file(path / "codev/tests/dec_tilt_test.seq")
            # self.open_file(path / "codev/tests/landscape_lens.seq")
            # self.open_file(path / "codev/tests/mangin.seq")
            # self.open_file(path / "codev/tests/CODV_32327.seq")
            # self.open_file(path / "codev/tests/dar_test.seq")
            # self.open_file(path / "optical/tests/cell_phone_camera.roa")
            # self.open_file(path / "optical/tests/singlet_f3.roa")

            # self.cur_dir = path / "models"
            # self.open_file(path / "models/Cassegrain.roa")
            # self.open_file(path / "models/collimator.roa")
            # self.open_file(path / "models/Dall-Kirkham.roa")
            # self.open_file(path / "models/petzval.roa")
            # self.open_file(path / "models/Ritchey_Chretien.roa")
            # self.open_file(path / "models/Sasian Triplet.roa")
            # self.open_file(path / "models/singlet_f5.roa")
            # self.open_file(path / "models/thinlens.roa")
            # self.open_file(path / "models/telephoto.roa")
            # self.open_file(path / "models/thin_triplet.roa")
            # self.open_file(path / "models/TwoMirror.roa")
            # self.open_file(path / "models/TwoSphericalMirror.roa")

            self.cur_dir = path / "zemax/tests"
            # self.open_file(path / "zemax/tests/US08427765-1.ZMX")
            # self.open_file(path / "zemax/tests/US00583336-2-scaled.zmx")
            # self.open_file(path / "zemax/tests/HoO-V2C18Ex03.zmx")
            # self.open_file(path / "zemax/tests/HoO-V2C18Ex27.zmx")
            # self.open_file(path / "zemax/tests/HoO-V2C18Ex46.zmx")
            # self.open_file(path / "zemax/tests/HoO-V2C18Ex66.zmx")
            # self.open_file(path / "zemax/tests/US05831776-1.zmx")
            self.open_file(path / "zemax/tests/354710-C-Zemax(ZMX).zmx")

            # self.cur_dir = path / "zemax/models/telescopes"
            # self.open_file(path / "zemax/models/telescopes/Figure4.zmx")
            # self.open_file(path / "zemax/models/telescopes/HoO-V2C18Ex11.zmx")

            # self.cur_dir = path / "zemax/models/PhotoPrime"
            # self.open_file(path / "zemax/models/PhotoPrime/US05321554-4.ZMX")
            # self.open_file(path / "zemax/models/PhotoPrime/US06476982-1.ZMX")
            # self.open_file(path / "zemax/models/PhotoPrime/US07190532-1.ZMX")
            # self.open_file(path / "zemax/models/PhotoPrime/US04331391-1.zmx")
            # self.open_file(path / "zemax/models/PhotoPrime/US05331467-1.zmx")

    def add_subwindow(self, widget, model_info):
        sub_wind = self.mdi.addSubWindow(widget)
        self.app_manager.add_view(sub_wind, widget, model_info)
        MainWindow.count += 1
        return sub_wind

    def delete_subwindow(self, sub_wind):
        self.app_manager.delete_view(sub_wind)
        self.mdi.removeSubWindow(sub_wind)
        MainWindow.count -= 1

    def add_ipython_subwindow(self):
        try:
            create_ipython_console(self, 'iPython console', 800, 600)
        except MultipleInstanceError:
            logging.debug("Unable to open iPython console. "
                          "MultipleInstanceError")
        except Exception as inst:
            print(type(inst))    # the exception instance
            print(inst.args)     # arguments stored in .args
            print(inst)          # __str__ allows args to be printed directly,
            pass                 # but may be overridden in exception subclasses

    def initial_window_offset(self):
        offset_x = 50
        offset_y = 25
        orig_x = (MainWindow.count - 1)*offset_x
        orig_y = (MainWindow.count - 1)*offset_y
        return orig_x, orig_y

    def file_action(self, q):
        if q.text() == "New":
            self.new_model()

        if q.text() == "Open...":
            options = QFileDialog.Options()
            # options |= QFileDialog.DontUseNativeDialog
            fileName, _ = QFileDialog.getOpenFileName(
                          self,
                          "QFileDialog.getOpenFileName()",
                          str(self.cur_dir),
                          "All files (*.seq *.zmx *.roa);;"
                          "CODE V files (*.seq);;"
                          "Ray-Optics files (*.roa);;"
                          "Zemax files (*.zmx)",
                          options=options)
            if fileName:
                logging.debug("open file: %s", fileName)
                filename = Path(fileName)
                self.cur_dir = filename.parent
                self.open_file(filename)

        if q.text() == "Save As...":
            options = QFileDialog.Options()
            # options |= QFileDialog.DontUseNativeDialog
            fileName, _ = QFileDialog.getSaveFileName(
                          self,
                          "QFileDialog.getSaveFileName()",
                          "",
                          "Ray-Optics Files (*.roa);;All Files (*)",
                          options=options)
            if fileName:
                logging.debug("save file: %s", fileName)
                self.save_file(fileName)

        if q.text() == "Close":
            self.close_model()

    def new_model(self):
        iid = cmds.create_new_ideal_imager(gui_parent=self,
                                           conjugate_type='infinite')

        self.add_ipython_subwindow()
        self.refresh_app_ui()

    def open_file(self, file_name, **kwargs):
        self.cur_filename = file_name
        opt_model = cmds.open_model(file_name, **kwargs)
        self.app_manager.set_model(opt_model)
        self.is_changed = True
        self.create_lens_table()
        cmds.create_live_layout_view(self.app_manager.model, gui_parent=self)
        self.add_ipython_subwindow()
        self.refresh_app_ui()

    def save_file(self, file_name):
        self.app_manager.model.save_model(file_name)
        self.cur_filename = file_name
        self.is_changed = False

    def close_model(self):
        """ NOTE: this does not check to save a modified model """
        self.app_manager.close_model(self.delete_subwindow)

    def view_action(self, q):
        opt_model = self.app_manager.model

        if q.text() == "Spec Sheet":
            cmds.create_new_ideal_imager(opt_model=opt_model, gui_parent=self)

        if q.text() == "Optical Layout":
            cmds.create_live_layout_view(opt_model, gui_parent=self)

        if q.text() == "Lens Table":
            self.create_lens_table()

        if q.text() == "Element Table":
            model = cmds.create_element_table_model(opt_model)
            self.create_table_view(model, "Element Table")

        if q.text() == "Glass Map":
            cmds.create_glass_map_view(opt_model, gui_parent=self)

        if q.text() == "Ray Fans":
            cmds.create_ray_fan_view(opt_model, "Ray", gui_parent=self)

        if q.text() == "OPD Fans":
            cmds.create_ray_fan_view(opt_model, "OPD", gui_parent=self)

        if q.text() == "Spot Diagram":
            cmds.create_ray_grid_view(opt_model, gui_parent=self)

        if q.text() == "Wavefront Map":
            cmds.create_wavefront_view(opt_model, gui_parent=self)

        if q.text() == "Astigmatism Curves":
            cmds.create_field_curves(opt_model, gui_parent=self)

        if q.text() == "3rd Order Aberrations":
            cmds.create_3rd_order_bar_chart(opt_model, gui_parent=self)

        if q.text() == "y-ybar View":
            cmds.create_paraxial_design_view_v2(opt_model, 'ht',
                                                gui_parent=self)

        if q.text() == "nu-nubar View":
            cmds.create_paraxial_design_view_v2(opt_model, 'slp',
                                                gui_parent=self)

        if q.text() == "yui Ray Table":
            model = cmds.create_parax_table_model(opt_model)
            self.create_table_view(model, "Paraxial Ray Table")

        if q.text() == "Paraxial Model":
            model = cmds.create_parax_model_table(opt_model)
            self.create_table_view(model, "Paraxial Model")

        if q.text() == "Ray Table":
            self.create_ray_table(opt_model)

        if q.text() == "Paraxial Vignetting":
            trace.apply_paraxial_vignetting(opt_model)
            self.refresh_gui()

    def window_action(self, q):
        if q.text() == "Cascade":
            self.mdi.cascadeSubWindows()

        if q.text() == "Tiled":
            self.mdi.tileSubWindows()

        if q.text() == "Light UI":
            self.is_dark = self.light_or_dark(False)
            self.app_manager.sync_light_or_dark(self.is_dark)

        if q.text() == "Dark UI":
            self.is_dark = self.light_or_dark(True)
            self.app_manager.sync_light_or_dark(self.is_dark)

    def light_or_dark(self, is_dark):
        """ set the UI to a light or dark scheme.

        Qt doesn't seem to support controlling the MdiArea's background from a
        style sheet. Set the widget directly and save the original color
        to reset defaults.
        """
        if not hasattr(self, 'mdi_background'):
            self.mdi_background = self.mdi.background()

        if is_dark:
            self.qtapp.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
            rgb = DarkPalette.color_palette()
            self.mdi.setBackground(QColor(rgb['COLOR_BACKGROUND_NORMAL']))
        else:
            self.qtapp.setStyleSheet('')
            self.mdi.setBackground(self.mdi_background)
        return is_dark

    def create_lens_table(self):
        seq_model = self.app_manager.model.seq_model

        def set_stop_surface(stop_surface):
            seq_model.stop_surface = stop_surface
            self.refresh_gui()

        def handle_context_menu(point):
            try:
                vheader = view.verticalHeader()
                row = vheader.logicalIndexAt(point.y())
            except NameError:
                pass
            else:
                # show menu about the row
                menu = QMenu(self)
                if row != seq_model.stop_surface:
                    menu.addAction('Set Stop Surface',
                                   lambda: set_stop_surface(row))
                if seq_model.stop_surface is not None:
                    menu.addAction('Float Stop Surface',
                                   lambda: set_stop_surface(None))
                menu.popup(vheader.mapToGlobal(point))

        model = cmds.create_lens_table_model(seq_model)
        view = self.create_table_view(model, "Surface Data Table")
        vheader = view.verticalHeader()
        vheader.setContextMenuPolicy(qt.CustomContextMenu)
        vheader.customContextMenuRequested.connect(handle_context_menu)

    def create_ray_table(self, opt_model):
        osp = opt_model.optical_spec
        pupil = [0., 1.]
        fi = 0
        wl = osp.spectral_region.reference_wvl
        fld, wvl, foc = osp.lookup_fld_wvl_focus(fi, wl)
        ray, ray_op, wvl = trace.trace_base(opt_model, pupil, fld, wvl)
#        ray, ray_op, wvl, opd = trace.trace_with_opd(opt_model, pupil,
#                                                     fld, wvl, foc)

#        cr = trace.RayPkg(ray, ray_op, wvl)
#        s, t = trace.trace_coddington_fan(opt_model, cr, foc)

        ray = [RaySeg(*rs) for rs in ray]
        model = cmds.create_ray_table_model(opt_model, ray)
        self.create_table_view(model, "Ray Table")

    def create_table_view(self, table_model, table_title, close_callback=None):
        # construct the top level widget
        widget = QWidget()
        # construct the top level layout
        layout = QVBoxLayout(widget)

        table_view = TableView(table_model)
        table_view.setAlternatingRowColors(True)

        # Add table to box layout
        layout.addWidget(table_view)

        # set the layout on the widget
        widget.setLayout(layout)

        sub = self.add_subwindow(widget, ModelInfo(self.app_manager.model,
                                                   cmds.update_table_view,
                                                   (table_view,)))
        sub.setWindowTitle(table_title)

        sub.installEventFilter(self)

        table_view.setMinimumWidth(table_view.horizontalHeader().length() +
                                   table_view.horizontalHeader().height())
#                                  The following line should work but returns 0
#                                  table_view.verticalHeader().width())

        view_width = table_view.width()
        view_ht = table_view.height()
        orig_x, orig_y = self.initial_window_offset()
        sub.setGeometry(orig_x, orig_y, view_width, view_ht)

        # table data updated successfully
        table_model.update.connect(self.on_data_changed)

        sub.show()

        return table_view

    def eventFilter(self, obj, event):
        """Used by table_view in response to installEventFilter."""
        if (event.type() == QEvent.Close):
            print('close event received:', obj)
        return False

    def refresh_gui(self, **kwargs):
        self.app_manager.refresh_gui(**kwargs)

    def refresh_app_ui(self):
        dock.update_dock_windows(self)

    def handle_ideal_imager_command(self, iid, command, specsheet):
        ''' link Ideal Imager Dialog buttons to model actions
        iid: ideal imager dialog
        command: text field with the action - same as button label
        specsheet: the input specsheet used to drive the actions
        '''
        if command == 'Apply':
            opt_model = self.app_manager.model
            opt_model.set_from_specsheet(specsheet)
            self.refresh_gui()
        elif command == 'Close':
            for view, info in self.app_manager.view_dict.items():
                if iid == info[0]:
                    self.delete_subwindow(view)
                    view.close()
                    break
        elif command == 'Update':
            opt_model = self.app_manager.model
            specsheet = opt_model.specsheet
            firstorder.specsheet_from_parax_data(opt_model, specsheet)
            iid.specsheet_dict[specsheet.conjugate_type] = specsheet
            iid.update_values()
        elif command == 'New':
            opt_model = cmds.create_new_optical_model_from_specsheet(specsheet)
            self.app_manager.set_model(opt_model)
            for view, info in self.app_manager.view_dict.items():
                if iid == info[0]:
                    w = iid
                    mi = info[1]
                    args = (iid, opt_model)
                    new_mi = ModelInfo(model=opt_model, fct=mi.fct,
                                       args=args, kwargs=mi.kwargs)
                    self.app_manager.view_dict[view] = w, new_mi
            self.refresh_gui()
            self.create_lens_table()
            cmds.create_live_layout_view(opt_model, gui_parent=self)
            cmds.create_paraxial_design_view_v2(opt_model, 'ht',
                                                gui_parent=self)
            self.refresh_gui()

    @pyqtSlot(object, int)
    def on_data_changed(self, rootObj, index):
        self.refresh_gui()
Пример #29
0
class MyMainWindow(QMainWindow):

    window_index = 1

    def __init__(self):
        super(QMainWindow, self).__init__()

        self.mdi_area = QMdiArea()
        self.setCentralWidget(self.mdi_area)

        self.__init_menu()

    def __init_menu(self):
        menu_bar = self.menuBar()

        file_menu = menu_bar.addMenu('File')

        open_action = QAction('Open', self)
        open_action.setShortcut('Ctrl+O')
        open_action.triggered.connect(self.__on_open)
        file_menu.addAction(open_action)

        exit_action = QAction('Exit', self)
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)

        window_menu = menu_bar.addMenu('Windows')

        close_current_action = QAction('Close Current Window', self)
        close_current_action.triggered.connect(self.mdi_area.closeActiveSubWindow)
        window_menu.addAction(close_current_action)

        close_all_action = QAction('Close All', self)
        close_all_action.triggered.connect(self.mdi_area.closeAllSubWindows)
        window_menu.addAction(close_all_action)

        cascade_action = QAction('Cascade Windows', self)
        cascade_action.triggered.connect(self.mdi_area.cascadeSubWindows)
        window_menu.addAction(cascade_action)

        tile_action = QAction('Title Windows', self)
        tile_action.triggered.connect(self.mdi_area.tileSubWindows)
        window_menu.addAction(tile_action)

        self.__window_list_menu = window_menu.addMenu('Window List')
        self.__window_list_menu.aboutToShow.connect(self.__window_list_menu_about_to_show)

    def __window_list_menu_about_to_show(self):
        self.__window_list_menu.clear()
        windows = self.mdi_area.subWindowList()
        index = 1
        for window in windows:
            action = QAction(str(index) + '. ' + window.windowTitle(), self.__window_list_menu)
            action.setProperty('WindowObject', window)
            action.triggered.connect(self.__on_select_window)
            self.__window_list_menu.addAction(action)
            index += 1

    def __on_select_window(self):
        action = self.sender()
        window = action.property('WindowObject')
        self.mdi_area.setActiveSubWindow(window)

    def __on_open(self):
        window = QMdiSubWindow()
        window.setAttribute(Qt.WA_DeleteOnClose, True)
        window.setWindowTitle('Sub Window ' + str(MyMainWindow.window_index))
        window.resize(300, 200)
        self.mdi_area.addSubWindow(window)
        window.show()

        MyMainWindow.window_index += 1
Пример #30
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("MDI")

    def closeEvent(self, event):
        self.mdiArea.closeAllSubWindows()
        if self.mdiArea.currentSubWindow():
            event.ignore()
        else:
            self.writeSettings()
            event.accept()

    def newFile(self):
        child = self.createMdiChild()
        child.newFile()
        child.show()

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self)
        if fileName:
            existing = self.findMdiChild(fileName)
            if existing:
                self.mdiArea.setActiveSubWindow(existing)
                return

            child = self.createMdiChild()
            if child.loadFile(fileName):
                self.statusBar().showMessage("File loaded", 2000)
                child.show()
            else:
                child.close()

    def save(self):
        if self.activeMdiChild() and self.activeMdiChild().save():
            self.statusBar().showMessage("File saved", 2000)

    def saveAs(self):
        if self.activeMdiChild() and self.activeMdiChild().saveAs():
            self.statusBar().showMessage("File saved", 2000)

    def cut(self):
        if self.activeMdiChild():
            self.activeMdiChild().cut()

    def copy(self):
        if self.activeMdiChild():
            self.activeMdiChild().copy()

    def paste(self):
        if self.activeMdiChild():
            self.activeMdiChild().paste()

    def about(self):
        QMessageBox.about(self, "About MDI",
                "The <b>MDI</b> example demonstrates how to write multiple "
                "document interface applications using Qt.")

    def updateMenus(self):
        hasMdiChild = (self.activeMdiChild() is not None)
        self.saveAct.setEnabled(hasMdiChild)
        self.saveAsAct.setEnabled(hasMdiChild)
        self.pasteAct.setEnabled(hasMdiChild)
        self.closeAct.setEnabled(hasMdiChild)
        self.closeAllAct.setEnabled(hasMdiChild)
        self.tileAct.setEnabled(hasMdiChild)
        self.cascadeAct.setEnabled(hasMdiChild)
        self.nextAct.setEnabled(hasMdiChild)
        self.previousAct.setEnabled(hasMdiChild)
        self.separatorAct.setVisible(hasMdiChild)

        hasSelection = (self.activeMdiChild() is not None and
                        self.activeMdiChild().textCursor().hasSelection())
        self.cutAct.setEnabled(hasSelection)
        self.copyAct.setEnabled(hasSelection)

    def updateWindowMenu(self):
        self.windowMenu.clear()
        self.windowMenu.addAction(self.closeAct)
        self.windowMenu.addAction(self.closeAllAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.tileAct)
        self.windowMenu.addAction(self.cascadeAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.nextAct)
        self.windowMenu.addAction(self.previousAct)
        self.windowMenu.addAction(self.separatorAct)

        windows = self.mdiArea.subWindowList()
        self.separatorAct.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            child = window.widget()

            text = "%d %s" % (i + 1, child.userFriendlyCurrentFile())
            if i < 9:
                text = '&' + text

            action = self.windowMenu.addAction(text)
            action.setCheckable(True)
            action.setChecked(child is self.activeMdiChild())
            action.triggered.connect(self.windowMapper.map)
            self.windowMapper.setMapping(action, window)

    def createMdiChild(self):
        child = MdiChild()
        self.mdiArea.addSubWindow(child)

        child.copyAvailable.connect(self.cutAct.setEnabled)
        child.copyAvailable.connect(self.copyAct.setEnabled)

        return child

    def createActions(self):
        self.newAct = QAction(QIcon(':/images/new.png'), "&New", self,
                shortcut=QKeySequence.New, statusTip="Create a new file",
                triggered=self.newFile)

        self.openAct = QAction(QIcon(':/images/open.png'), "&Open...", self,
                shortcut=QKeySequence.Open, statusTip="Open an existing file",
                triggered=self.open)

        self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self,
                shortcut=QKeySequence.Save,
                statusTip="Save the document to disk", triggered=self.save)

        self.saveAsAct = QAction("Save &As...", self,
                shortcut=QKeySequence.SaveAs,
                statusTip="Save the document under a new name",
                triggered=self.saveAs)

        self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit,
                statusTip="Exit the application",
                triggered=QApplication.instance().closeAllWindows)

        self.cutAct = QAction(QIcon(':/images/cut.png'), "Cu&t", self,
                shortcut=QKeySequence.Cut,
                statusTip="Cut the current selection's contents to the clipboard",
                triggered=self.cut)

        self.copyAct = QAction(QIcon(':/images/copy.png'), "&Copy", self,
                shortcut=QKeySequence.Copy,
                statusTip="Copy the current selection's contents to the clipboard",
                triggered=self.copy)

        self.pasteAct = QAction(QIcon(':/images/paste.png'), "&Paste", self,
                shortcut=QKeySequence.Paste,
                statusTip="Paste the clipboard's contents into the current selection",
                triggered=self.paste)

        self.closeAct = QAction("Cl&ose", self,
                statusTip="Close the active window",
                triggered=self.mdiArea.closeActiveSubWindow)

        self.closeAllAct = QAction("Close &All", self,
                statusTip="Close all the windows",
                triggered=self.mdiArea.closeAllSubWindows)

        self.tileAct = QAction("&Tile", self, statusTip="Tile the windows",
                triggered=self.mdiArea.tileSubWindows)

        self.cascadeAct = QAction("&Cascade", self,
                statusTip="Cascade the windows",
                triggered=self.mdiArea.cascadeSubWindows)

        self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild,
                statusTip="Move the focus to the next window",
                triggered=self.mdiArea.activateNextSubWindow)

        self.previousAct = QAction("Pre&vious", self,
                shortcut=QKeySequence.PreviousChild,
                statusTip="Move the focus to the previous window",
                triggered=self.mdiArea.activatePreviousSubWindow)

        self.separatorAct = QAction(self)
        self.separatorAct.setSeparator(True)

        self.aboutAct = QAction("&About", self,
                statusTip="Show the application's About box",
                triggered=self.about)

        self.aboutQtAct = QAction("About &Qt", self,
                statusTip="Show the Qt library's About box",
                triggered=QApplication.instance().aboutQt)

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addSeparator()
        action = self.fileMenu.addAction("Switch layout direction")
        action.triggered.connect(self.switchLayoutDirection)
        self.fileMenu.addAction(self.exitAct)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.addAction(self.cutAct)
        self.editMenu.addAction(self.copyAct)
        self.editMenu.addAction(self.pasteAct)

        self.windowMenu = self.menuBar().addMenu("&Window")
        self.updateWindowMenu()
        self.windowMenu.aboutToShow.connect(self.updateWindowMenu)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)
        self.helpMenu.addAction(self.aboutQtAct)

    def createToolBars(self):
        self.fileToolBar = self.addToolBar("File")
        self.fileToolBar.addAction(self.newAct)
        self.fileToolBar.addAction(self.openAct)
        self.fileToolBar.addAction(self.saveAct)

        self.editToolBar = self.addToolBar("Edit")
        self.editToolBar.addAction(self.cutAct)
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.pasteAct)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(400, 400))
        self.move(pos)
        self.resize(size)

    def writeSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())

    def activeMdiChild(self):
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        return None

    def findMdiChild(self, fileName):
        canonicalFilePath = QFileInfo(fileName).canonicalFilePath()

        for window in self.mdiArea.subWindowList():
            if window.widget().currentFile() == canonicalFilePath:
                return window
        return None

    def switchLayoutDirection(self):
        if self.layoutDirection() == Qt.LeftToRight:
            QApplication.setLayoutDirection(Qt.RightToLeft)
        else:
            QApplication.setLayoutDirection(Qt.LeftToRight)

    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)
Пример #31
0
class appWindow(QMainWindow):
    """
    Application entry point, subclasses QMainWindow and implements the main widget,
    sets necessary window behaviour etc.
    """
    def __init__(self, parent=None):
        super(appWindow, self).__init__(parent)

        #create the menu bar
        self.createMenuBar()

        self.mdi = QMdiArea(self)  #create area for files to be displayed
        self.mdi.setObjectName('mdi area')

        #create toolbar and add the toolbar plus mdi to layout
        self.createToolbar()

        #set flags so that window doesnt look weird
        self.mdi.setOption(QMdiArea.DontMaximizeSubWindowOnActivation, True)
        self.mdi.setTabsClosable(True)
        self.mdi.setTabsMovable(True)
        self.mdi.setDocumentMode(False)

        #declare main window layout
        self.setCentralWidget(self.mdi)
        # self.resize(1280, 720) #set collapse dim
        self.mdi.subWindowActivated.connect(self.tabSwitched)
        self.readSettings()

    def createMenuBar(self):
        # Fetches a reference to the menu bar in the main window, and adds actions to it.

        titleMenu = self.menuBar()  #fetch reference to current menu bar

        self.menuFile = titleMenu.addMenu('File')  #File Menu
        newAction = self.menuFile.addAction("New", self.newProject)
        openAction = self.menuFile.addAction("Open", self.openProject)
        saveAction = self.menuFile.addAction("Save", self.saveProject)

        newAction.setShortcut(QKeySequence.New)
        openAction.setShortcut(QKeySequence.Open)
        saveAction.setShortcut(QKeySequence.Save)

        self.menuEdit = titleMenu.addMenu('Edit')
        undoAction = self.undo = self.menuEdit.addAction(
            "Undo", lambda x=self: x.activeScene.painter.undoAction.trigger())
        redoAction = self.redo = self.menuEdit.addAction(
            "Redo", lambda x=self: x.activeScene.painter.redoAction.trigger())

        undoAction.setShortcut(QKeySequence.Undo)
        redoAction.setShortcut(QKeySequence.Redo)

        self.menuEdit.addAction(
            "Show Undo Stack",
            lambda x=self: x.activeScene.painter.createUndoView(self))
        self.menuEdit.addSeparator()
        self.menuEdit.addAction("Add new symbols", self.addSymbolWindow)

        self.menuGenerate = titleMenu.addMenu('Generate')  #Generate menu
        imageAction = self.menuGenerate.addAction("Image", self.saveImage)
        reportAction = self.menuGenerate.addAction("Report",
                                                   self.generateReport)

        imageAction.setShortcut(QKeySequence("Ctrl+P"))
        reportAction.setShortcut(QKeySequence("Ctrl+R"))

    def createToolbar(self):
        #place holder for toolbar with fixed width, layout may change
        self.toolbar = toolbar(self)
        self.toolbar.setObjectName("Toolbar")
        # self.addToolBar(Qt.LeftToolBarArea, self.toolbar)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.toolbar)
        self.toolbar.toolbuttonClicked.connect(self.toolButtonClicked)
        self.toolbar.populateToolbar()

    def toolButtonClicked(self, object):
        # To add the corresponding symbol for the clicked button to active scene.
        if self.mdi.currentSubWindow():
            currentDiagram = self.mdi.currentSubWindow().tabber.currentWidget(
            ).painter
            if currentDiagram:
                graphic = getattr(shapes, object['object'])(*map(
                    lambda x: int(x) if x.isdigit() else x, object['args']))
                graphic.setPos(50, 50)
                currentDiagram.addItemPlus(graphic)

    def addSymbolWindow(self):
        # Opens the add symbol window when requested
        from utils.custom import ShapeDialog
        ShapeDialog(self).exec()

    def newProject(self):
        #call to create a new file inside mdi area
        project = FileWindow(self.mdi)
        project.setObjectName("New Project")
        self.mdi.addSubWindow(project)
        if not project.tabList:  # important when unpickling a file instead
            project.newDiagram()  #create a new tab in the new file
        project.fileCloseEvent.connect(
            self.fileClosed)  #closed file signal to switch to sub window view
        if self.count > 1:  #switch to tab view if needed
            self.mdi.setViewMode(QMdiArea.TabbedView)
        project.show()

    def openProject(self):
        #show the open file dialog to open a saved file, then unpickle it.
        name = QFileDialog.getOpenFileNames(self, 'Open File(s)', '',
                                            'Process Flow Diagram (*pfd)')
        if name:
            for files in name[0]:
                with open(files, 'r') as file:
                    projectData = load(file)
                    project = FileWindow(self.mdi)
                    self.mdi.addSubWindow(project)
                    #create blank window and set its state
                    project.__setstate__(projectData)
                    project.resizeHandler()
                    project.fileCloseEvent.connect(self.fileClosed)
                    project.show()
        if self.count > 1:
            # self.tabSpace.setVisible(True)
            self.mdi.setViewMode(QMdiArea.TabbedView)

    def saveProject(self):
        #serialize all files in mdi area
        for j, i in enumerate(self.activeFiles
                              ):  #get list of all windows with atleast one tab
            if i.tabCount:
                name = QFileDialog.getSaveFileName(
                    self, 'Save File', f'New Diagram {j}',
                    'Process Flow Diagram (*.pfd)')
                i.saveProject(name)
            else:
                return False
        return True

    def saveImage(self):
        #place holder for future implementaion
        pass

    def generateReport(self):
        #place holder for future implementaion
        pass

    def tabSwitched(self, window):
        #handle window switched edge case
        if window and window.tabCount:
            window.resizeHandler()

    def resizeEvent(self, event):
        #overload resize to also handle resize on file windows inside
        for i in self.mdi.subWindowList():
            i.resizeHandler()
        self.toolbar.resize()
        super(appWindow, self).resizeEvent(event)

    def closeEvent(self, event):
        #save alert on window close
        if len(self.activeFiles) and not dialogs.saveEvent(self):
            event.ignore()
        else:
            event.accept()
        self.writeSettings()

    def fileClosed(self, index):
        #checks if the file tab menu needs to be removed
        if self.count <= 2:
            self.mdi.setViewMode(QMdiArea.SubWindowView)

    def writeSettings(self):
        # write window state on window close
        settings.beginGroup("MainWindow")
        settings.setValue("maximized", self.isMaximized())
        if not self.isMaximized():
            settings.setValue("size", self.size())
            settings.setValue("pos", self.pos())
        settings.endGroup()

    def readSettings(self):
        # read window state when app launches
        settings.beginGroup("MainWindow")
        self.resize(settings.value("size", QSize(1280, 720)))
        self.move(settings.value("pos", QPoint(320, 124)))
        if settings.value("maximized", False, type=bool):
            self.showMaximized()
        settings.endGroup()

    #useful one liner properties for getting data
    @property
    def activeFiles(self):
        return [i for i in self.mdi.subWindowList() if i.tabCount]

    @property
    def count(self):
        return len(self.mdi.subWindowList())

    @property
    def activeScene(self):
        return self.mdi.currentSubWindow().tabber.currentWidget()

    #Key input handler
    def keyPressEvent(self, event):
        #overload key press event for custom keyboard shortcuts
        if event.modifiers() & Qt.ControlModifier:
            if event.key() == Qt.Key_A:
                #todo implement selectAll
                for item in self.mdi.activeSubWindow().tabber.currentWidget(
                ).items:
                    item.setSelected(True)

            #todo copy, paste, undo redo
            else:
                return
            event.accept()
        elif event.key() == Qt.Key_Q:
            if self.mdi.activeSubWindow() and self.mdi.activeSubWindow(
            ).tabber.currentWidget():
                for item in self.mdi.activeSubWindow().tabber.currentWidget(
                ).painter.selectedItems():
                    item.rotation -= 1

        elif event.key() == Qt.Key_E:
            if self.mdi.activeSubWindow() and self.mdi.activeSubWindow(
            ).tabber.currentWidget():
                for item in self.mdi.activeSubWindow().tabber.currentWidget(
                ).painter.selectedItems():
                    item.rotation += 1
Пример #32
0
class Example(QMainWindow):
    def __init__(self):
        super().__init__()
        self.InitUI()

    def InitUI(self):
        self.setWindowTitle('扑克牌模拟')

        self.mid = QMdiArea()
        self.setCentralWidget(self.mid)

        sendOnecardAct = QAction(QIcon('./res/sendOnecard.ico'), '发1张牌', self)
        sendOnecardAct.triggered.connect(self.sendOnecard)

        sendFivecardsAct = QAction(QIcon('./res/sendFivecard.ico'), '随机5张牌',
                                   self)
        sendFivecardsAct.triggered.connect(self.sendFivecards)

        clearcardAct = QAction(QIcon('./res/clear.ico'), '清除牌', self)
        clearcardAct.triggered.connect(self.clearCards)

        foldcardAct = QAction(QIcon('./res/fold.ico'), '收牌', self)
        foldcardAct.triggered.connect(self.foldCards)

        toolbar = self.addToolBar('工具栏')
        toolbar.addAction(sendOnecardAct)
        toolbar.addAction(sendFivecardsAct)
        toolbar.addAction(clearcardAct)
        toolbar.addAction(foldcardAct)
        toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

    def sendOnecard(self):
        randomflag = self.randomsend(1)
        subcard = QMdiSubWindow()
        subcard.setWidget(Card(randomflag))
        self.mid.addSubWindow(subcard)
        subcard.setWindowFlags(Qt.WindowMinimizeButtonHint)
        subcard.show()

    def sendFivecards(self):
        randomflag = self.randomsend(5)
        for card in randomflag:
            subcard = QMdiSubWindow()
            subcard.setWidget(Card(card))
            self.mid.addSubWindow(subcard)
            subcard.setWindowFlags(Qt.WindowMinimizeButtonHint)
            subcard.show()

    def clearCards(self):
        self.mid.closeAllSubWindows()

    def foldCards(self):
        self.mid.cascadeSubWindows()

    def randomsend(self, num):
        cardlist = [
            "2", "3", "4", "5", "6", "7", "8", "9", "10", "a", "j", "joker",
            "k", "q"
        ]
        if num == 1:
            return random.choice(cardlist)
        elif num == 5:
            return random.sample(cardlist, 5)
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("MDI")

    def closeEvent(self, event):
        self.mdiArea.closeAllSubWindows()
        if self.mdiArea.currentSubWindow():
            event.ignore()
        else:
            self.writeSettings()
            event.accept()

    def newFile(self):
        child = self.createMdiChild()
        child.newFile()
        child.show()

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self)
        if fileName:
            existing = self.findMdiChild(fileName)
            if existing:
                self.mdiArea.setActiveSubWindow(existing)
                return

            child = self.createMdiChild()
            if child.loadFile(fileName):
                self.statusBar().showMessage("File loaded", 2000)
                child.show()
            else:
                child.close()

    def save(self):
        if self.activeMdiChild() and self.activeMdiChild().save():
            self.statusBar().showMessage("File saved", 2000)

    def saveAs(self):
        if self.activeMdiChild() and self.activeMdiChild().saveAs():
            self.statusBar().showMessage("File saved", 2000)

    def cut(self):
        if self.activeMdiChild():
            self.activeMdiChild().cut()

    def copy(self):
        if self.activeMdiChild():
            self.activeMdiChild().copy()

    def paste(self):
        if self.activeMdiChild():
            self.activeMdiChild().paste()

    def about(self):
        QMessageBox.about(
            self, "About MDI",
            "The <b>MDI</b> example demonstrates how to write multiple "
            "document interface applications using Qt.")

    def updateMenus(self):
        hasMdiChild = (self.activeMdiChild() is not None)
        self.saveAct.setEnabled(hasMdiChild)
        self.saveAsAct.setEnabled(hasMdiChild)
        self.pasteAct.setEnabled(hasMdiChild)
        self.closeAct.setEnabled(hasMdiChild)
        self.closeAllAct.setEnabled(hasMdiChild)
        self.tileAct.setEnabled(hasMdiChild)
        self.cascadeAct.setEnabled(hasMdiChild)
        self.nextAct.setEnabled(hasMdiChild)
        self.previousAct.setEnabled(hasMdiChild)
        self.separatorAct.setVisible(hasMdiChild)

        hasSelection = (self.activeMdiChild() is not None
                        and self.activeMdiChild().textCursor().hasSelection())
        self.cutAct.setEnabled(hasSelection)
        self.copyAct.setEnabled(hasSelection)

    def updateWindowMenu(self):
        self.windowMenu.clear()
        self.windowMenu.addAction(self.closeAct)
        self.windowMenu.addAction(self.closeAllAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.tileAct)
        self.windowMenu.addAction(self.cascadeAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.nextAct)
        self.windowMenu.addAction(self.previousAct)
        self.windowMenu.addAction(self.separatorAct)

        windows = self.mdiArea.subWindowList()
        self.separatorAct.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            child = window.widget()

            text = "%d %s" % (i + 1, child.userFriendlyCurrentFile())
            if i < 9:
                text = '&' + text

            action = self.windowMenu.addAction(text)
            action.setCheckable(True)
            action.setChecked(child is self.activeMdiChild())
            action.triggered.connect(self.windowMapper.map)
            self.windowMapper.setMapping(action, window)

    def createMdiChild(self):
        child = MdiChild()
        self.mdiArea.addSubWindow(child)

        child.copyAvailable.connect(self.cutAct.setEnabled)
        child.copyAvailable.connect(self.copyAct.setEnabled)

        return child

    def createActions(self):
        self.newAct = QAction(QIcon(':/images/new.png'),
                              "&New",
                              self,
                              shortcut=QKeySequence.New,
                              statusTip="Create a new file",
                              triggered=self.newFile)

        self.openAct = QAction(QIcon(':/images/open.png'),
                               "&Open...",
                               self,
                               shortcut=QKeySequence.Open,
                               statusTip="Open an existing file",
                               triggered=self.open)

        self.saveAct = QAction(QIcon(':/images/save.png'),
                               "&Save",
                               self,
                               shortcut=QKeySequence.Save,
                               statusTip="Save the document to disk",
                               triggered=self.save)

        self.saveAsAct = QAction(
            "Save &As...",
            self,
            shortcut=QKeySequence.SaveAs,
            statusTip="Save the document under a new name",
            triggered=self.saveAs)

        self.exitAct = QAction(
            "E&xit",
            self,
            shortcut=QKeySequence.Quit,
            statusTip="Exit the application",
            triggered=QApplication.instance().closeAllWindows)

        self.cutAct = QAction(
            QIcon(':/images/cut.png'),
            "Cu&t",
            self,
            shortcut=QKeySequence.Cut,
            statusTip="Cut the current selection's contents to the clipboard",
            triggered=self.cut)
        self.suggestAct = QAction(
            "Suggest",
            self,
            shortcut=QKeySequence.Copy,
            statusTip="Cut the current selection's contents to the clipboard",
            triggered=self.copy)
        self.copyAct = QAction(
            QIcon(':/images/copy.png'),
            "&Copy",
            self,
            shortcut=QKeySequence.Copy,
            statusTip="Copy the current selection's contents to the clipboard",
            triggered=self.copy)

        self.pasteAct = QAction(
            QIcon(':/images/paste.png'),
            "&Paste",
            self,
            shortcut=QKeySequence.Paste,
            statusTip=
            "Paste the clipboard's contents into the current selection",
            triggered=self.paste)

        self.closeAct = QAction("Cl&ose",
                                self,
                                statusTip="Close the active window",
                                triggered=self.mdiArea.closeActiveSubWindow)

        self.closeAllAct = QAction("Close &All",
                                   self,
                                   statusTip="Close all the windows",
                                   triggered=self.mdiArea.closeAllSubWindows)

        self.tileAct = QAction("&Tile",
                               self,
                               statusTip="Tile the windows",
                               triggered=self.mdiArea.tileSubWindows)

        self.cascadeAct = QAction("&Cascade",
                                  self,
                                  statusTip="Cascade the windows",
                                  triggered=self.mdiArea.cascadeSubWindows)

        self.nextAct = QAction("Ne&xt",
                               self,
                               shortcut=QKeySequence.NextChild,
                               statusTip="Move the focus to the next window",
                               triggered=self.mdiArea.activateNextSubWindow)

        self.previousAct = QAction(
            "Pre&vious",
            self,
            shortcut=QKeySequence.PreviousChild,
            statusTip="Move the focus to the previous window",
            triggered=self.mdiArea.activatePreviousSubWindow)

        self.separatorAct = QAction(self)
        self.separatorAct.setSeparator(True)

        self.aboutAct = QAction("&About",
                                self,
                                statusTip="Show the application's About box",
                                triggered=self.about)

        self.aboutQtAct = QAction("About &Qt",
                                  self,
                                  statusTip="Show the Qt library's About box",
                                  triggered=QApplication.instance().aboutQt)

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addSeparator()
        action = self.fileMenu.addAction("Switch layout direction")
        action.triggered.connect(self.switchLayoutDirection)
        self.fileMenu.addAction(self.exitAct)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.addAction(self.cutAct)
        self.editMenu.addAction(self.copyAct)
        self.editMenu.addAction(self.pasteAct)

        self.windowMenu = self.menuBar().addMenu("&Window")
        self.updateWindowMenu()
        self.windowMenu.aboutToShow.connect(self.updateWindowMenu)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)
        self.helpMenu.addAction(self.aboutQtAct)

    def createToolBars(self):
        self.fileToolBar = self.addToolBar("File")
        self.fileToolBar.addAction(self.newAct)
        self.fileToolBar.addAction(self.openAct)
        self.fileToolBar.addAction(self.saveAct)

        self.editToolBar = self.addToolBar("Edit")
        self.editToolBar.addAction(self.cutAct)
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.pasteAct)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(400, 400))
        self.move(pos)
        self.resize(size)

    def writeSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())

    def activeMdiChild(self):
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        return None

    def findMdiChild(self, fileName):
        canonicalFilePath = QFileInfo(fileName).canonicalFilePath()

        for window in self.mdiArea.subWindowList():
            if window.widget().currentFile() == canonicalFilePath:
                return window
        return None

    def switchLayoutDirection(self):
        if self.layoutDirection() == Qt.LeftToRight:
            QApplication.setLayoutDirection(Qt.RightToLeft)
        else:
            QApplication.setLayoutDirection(Qt.LeftToRight)

    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)

    def contextMenuEvent(self, event):
        menu = QMenu(self)
        menu.addAction(self.cutAct)
        menu.addAction(self.copyAct)
        menu.addAction(self.pasteAct)
        menu.addAction(self.suggestAct)
        menu.exec_(event.globalPos())
Пример #34
0
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self._version = __version__
        self.setWindowIcon(QIcon(":/logo.png"))
        self.setWindowTitle("Tasmota Device Manager {}".format(self._version))

        self.unknown = []
        self.env = TasmotaEnvironment()
        self.device = None

        self.topics = []
        self.mqtt_queue = []
        self.fulltopic_queue = []

        # ensure TDM directory exists in the user directory
        if not os.path.isdir("{}/TDM".format(QDir.homePath())):
            os.mkdir("{}/TDM".format(QDir.homePath()))

        self.settings = QSettings("{}/TDM/tdm.cfg".format(QDir.homePath()),
                                  QSettings.IniFormat)
        self.devices = QSettings("{}/TDM/devices.cfg".format(QDir.homePath()),
                                 QSettings.IniFormat)
        self.setMinimumSize(QSize(1000, 600))

        # configure logging
        logging.basicConfig(filename="{}/TDM/tdm.log".format(QDir.homePath()),
                            level=self.settings.value("loglevel", "INFO"),
                            datefmt="%Y-%m-%d %H:%M:%S",
                            format='%(asctime)s [%(levelname)s] %(message)s')
        logging.info("### TDM START ###")

        # load devices from the devices file, create TasmotaDevices and add the to the envvironment
        for mac in self.devices.childGroups():
            self.devices.beginGroup(mac)
            device = TasmotaDevice(self.devices.value("topic"),
                                   self.devices.value("full_topic"),
                                   self.devices.value("friendly_name"))
            device.debug = self.devices.value("debug", False, bool)
            device.p['Mac'] = mac.replace("-", ":")
            device.env = self.env
            self.env.devices.append(device)

            # load device command history
            self.devices.beginGroup("history")
            for k in self.devices.childKeys():
                device.history.append(self.devices.value(k))
            self.devices.endGroup()

            self.devices.endGroup()

        self.device_model = TasmotaDevicesModel(self.env)

        self.setup_mqtt()
        self.setup_main_layout()
        self.add_devices_tab()
        self.build_mainmenu()
        # self.build_toolbars()
        self.setStatusBar(QStatusBar())

        pbSubs = QPushButton("Show subscriptions")
        pbSubs.setFlat(True)
        pbSubs.clicked.connect(self.showSubs)
        self.statusBar().addPermanentWidget(pbSubs)

        self.queue_timer = QTimer()
        self.queue_timer.timeout.connect(self.mqtt_publish_queue)
        self.queue_timer.start(250)

        self.auto_timer = QTimer()
        self.auto_timer.timeout.connect(self.auto_telemetry)

        self.load_window_state()

        if self.settings.value("connect_on_startup", False, bool):
            self.actToggleConnect.trigger()

        self.tele_docks = {}
        self.consoles = []

    def setup_main_layout(self):
        self.mdi = QMdiArea()
        self.mdi.setActivationOrder(QMdiArea.ActivationHistoryOrder)
        self.mdi.setTabsClosable(True)
        self.setCentralWidget(self.mdi)

    def setup_mqtt(self):
        self.mqtt = MqttClient()
        self.mqtt.connecting.connect(self.mqtt_connecting)
        self.mqtt.connected.connect(self.mqtt_connected)
        self.mqtt.disconnected.connect(self.mqtt_disconnected)
        self.mqtt.connectError.connect(self.mqtt_connectError)
        self.mqtt.messageSignal.connect(self.mqtt_message)

    def add_devices_tab(self):
        self.devices_list = ListWidget(self)
        sub = self.mdi.addSubWindow(self.devices_list)
        sub.setWindowState(Qt.WindowMaximized)
        self.devices_list.deviceSelected.connect(self.selectDevice)
        self.devices_list.openConsole.connect(self.openConsole)
        self.devices_list.openRulesEditor.connect(self.openRulesEditor)
        self.devices_list.openTelemetry.connect(self.openTelemetry)
        self.devices_list.openWebUI.connect(self.openWebUI)

    def load_window_state(self):
        wndGeometry = self.settings.value('window_geometry')
        if wndGeometry:
            self.restoreGeometry(wndGeometry)

    def build_mainmenu(self):
        mMQTT = self.menuBar().addMenu("MQTT")
        self.actToggleConnect = QAction(QIcon(":/disconnect.png"), "Connect")
        self.actToggleConnect.setCheckable(True)
        self.actToggleConnect.toggled.connect(self.toggle_connect)
        mMQTT.addAction(self.actToggleConnect)

        mMQTT.addAction(QIcon(), "Broker", self.setup_broker)
        mMQTT.addAction(QIcon(), "Autodiscovery patterns", self.patterns)

        mMQTT.addSeparator()
        mMQTT.addAction(QIcon(), "Clear obsolete retained LWTs",
                        self.clear_LWT)

        mMQTT.addSeparator()
        mMQTT.addAction(QIcon(), "Auto telemetry period",
                        self.auto_telemetry_period)

        self.actToggleAutoUpdate = QAction(QIcon(":/auto_telemetry.png"),
                                           "Auto telemetry")
        self.actToggleAutoUpdate.setCheckable(True)
        self.actToggleAutoUpdate.toggled.connect(self.toggle_autoupdate)
        mMQTT.addAction(self.actToggleAutoUpdate)

        mSettings = self.menuBar().addMenu("Settings")
        mSettings.addAction(QIcon(), "BSSId aliases", self.bssid)
        mSettings.addSeparator()
        mSettings.addAction(QIcon(), "Preferences", self.prefs)

        # mExport = self.menuBar().addMenu("Export")
        # mExport.addAction(QIcon(), "OpenHAB", self.openhab)

    def build_toolbars(self):
        main_toolbar = Toolbar(orientation=Qt.Horizontal,
                               iconsize=24,
                               label_position=Qt.ToolButtonTextBesideIcon)
        main_toolbar.setObjectName("main_toolbar")

    def initial_query(self, device, queued=False):
        for c in initial_commands():
            cmd, payload = c
            cmd = device.cmnd_topic(cmd)

            if queued:
                self.mqtt_queue.append([cmd, payload])
            else:
                self.mqtt.publish(cmd, payload, 1)

    def setup_broker(self):
        brokers_dlg = BrokerDialog()
        if brokers_dlg.exec_(
        ) == QDialog.Accepted and self.mqtt.state == self.mqtt.Connected:
            self.mqtt.disconnect()

    def toggle_autoupdate(self, state):
        if state == True:
            if self.mqtt.state == self.mqtt.Connected:
                for d in self.env.devices:
                    self.mqtt.publish(d.cmnd_topic('STATUS'), payload=8)
            self.auto_timer.setInterval(
                self.settings.value("autotelemetry", 5000, int))
            self.auto_timer.start()
        else:
            self.auto_timer.stop()

    def toggle_connect(self, state):
        if state and self.mqtt.state == self.mqtt.Disconnected:
            self.broker_hostname = self.settings.value('hostname', 'localhost')
            self.broker_port = self.settings.value('port', 1883, int)
            self.broker_username = self.settings.value('username')
            self.broker_password = self.settings.value('password')

            self.mqtt.hostname = self.broker_hostname
            self.mqtt.port = self.broker_port

            if self.broker_username:
                self.mqtt.setAuth(self.broker_username, self.broker_password)
            self.mqtt.connectToHost()
        elif not state and self.mqtt.state == self.mqtt.Connected:
            self.mqtt_disconnect()

    def auto_telemetry(self):
        if self.mqtt.state == self.mqtt.Connected:
            for d in self.env.devices:
                self.mqtt.publish(d.cmnd_topic('STATUS'), payload=8)

    def mqtt_connect(self):
        self.broker_hostname = self.settings.value('hostname', 'localhost')
        self.broker_port = self.settings.value('port', 1883, int)
        self.broker_username = self.settings.value('username')
        self.broker_password = self.settings.value('password')

        self.mqtt.hostname = self.broker_hostname
        self.mqtt.port = self.broker_port

        if self.broker_username:
            self.mqtt.setAuth(self.broker_username, self.broker_password)

        if self.mqtt.state == self.mqtt.Disconnected:
            self.mqtt.connectToHost()

    def mqtt_disconnect(self):
        self.mqtt.disconnectFromHost()

    def mqtt_connecting(self):
        self.statusBar().showMessage("Connecting to broker")

    def mqtt_connected(self):
        self.actToggleConnect.setIcon(QIcon(":/connect.png"))
        self.actToggleConnect.setText("Disconnect")
        self.statusBar().showMessage("Connected to {}:{} as {}".format(
            self.broker_hostname, self.broker_port,
            self.broker_username if self.broker_username else '[anonymous]'))

        self.mqtt_subscribe()

    def mqtt_subscribe(self):
        # clear old topics
        self.topics.clear()
        custom_patterns.clear()

        # load custom autodiscovery patterns
        self.settings.beginGroup("Patterns")
        for k in self.settings.childKeys():
            custom_patterns.append(self.settings.value(k))
        self.settings.endGroup()

        # expand fulltopic patterns to subscribable topics
        for pat in default_patterns:  # tasmota default and SO19
            self.topics += expand_fulltopic(pat)

        # check if custom patterns can be matched by default patterns
        for pat in custom_patterns:
            if pat.startswith("%prefix%") or pat.split('/')[1] == "%prefix%":
                continue  # do nothing, default subcriptions will match this topic
            else:
                self.topics += expand_fulltopic(pat)

        for d in self.env.devices:
            # if device has a non-standard pattern, check if the pattern is found in the custom patterns
            if not d.is_default() and d.p['FullTopic'] not in custom_patterns:
                # if pattern is not found then add the device topics to subscription list.
                # if the pattern is found, it will be matched without implicit subscription
                self.topics += expand_fulltopic(d.p['FullTopic'])

        # passing a list of tuples as recommended by paho
        self.mqtt.subscribe([(topic, 0) for topic in self.topics])

    @pyqtSlot(str, str)
    def mqtt_publish(self, t, p):
        self.mqtt.publish(t, p)

    def mqtt_publish_queue(self):
        for q in self.mqtt_queue:
            t, p = q
            self.mqtt.publish(t, p)
            self.mqtt_queue.pop(self.mqtt_queue.index(q))

    def mqtt_disconnected(self):
        self.actToggleConnect.setIcon(QIcon(":/disconnect.png"))
        self.actToggleConnect.setText("Connect")
        self.statusBar().showMessage("Disconnected")

    def mqtt_connectError(self, rc):
        reason = {
            1: "Incorrect protocol version",
            2: "Invalid client identifier",
            3: "Server unavailable",
            4: "Bad username or password",
            5: "Not authorized",
        }
        self.statusBar().showMessage("Connection error: {}".format(reason[rc]))
        self.actToggleConnect.setChecked(False)

    def mqtt_message(self, topic, msg):
        # try to find a device by matching known FullTopics against the MQTT topic of the message
        device = self.env.find_device(topic)
        if device:
            if topic.endswith("LWT"):
                if not msg:
                    msg = "Offline"
                device.update_property("LWT", msg)

                if msg == 'Online':
                    # known device came online, query initial state
                    self.initial_query(device, True)

            else:
                # forward the message for processing
                device.parse_message(topic, msg)
                if device.debug:
                    logging.debug("MQTT: %s %s", topic, msg)

        else:  # unknown device, start autodiscovery process
            if topic.endswith("LWT"):
                self.env.lwts.append(topic)
                logging.info("DISCOVERY: LWT from an unknown device %s", topic)

                # STAGE 1
                # load default and user-provided FullTopic patterns and for all the patterns,
                # try matching the LWT topic (it follows the device's FullTopic syntax

                for p in default_patterns + custom_patterns:
                    match = re.fullmatch(
                        p.replace("%topic%", "(?P<topic>.*?)").replace(
                            "%prefix%", "(?P<prefix>.*?)") + ".*$", topic)
                    if match:
                        # assume that the matched topic is the one configured in device settings
                        possible_topic = match.groupdict().get('topic')
                        if possible_topic not in ('tele', 'stat'):
                            # if the assumed topic is different from tele or stat, there is a chance that it's a valid topic
                            # query the assumed device for its FullTopic. False positives won't reply.
                            possible_topic_cmnd = p.replace(
                                "%prefix%", "cmnd").replace(
                                    "%topic%", possible_topic) + "FullTopic"
                            logging.debug(
                                "DISCOVERY: Asking an unknown device for FullTopic at %s",
                                possible_topic_cmnd)
                            self.mqtt_queue.append([possible_topic_cmnd, ""])

            elif topic.endswith("RESULT") or topic.endswith(
                    "FULLTOPIC"):  # reply from an unknown device
                # STAGE 2
                full_topic = loads(msg).get('FullTopic')
                if full_topic:
                    # the device replies with its FullTopic
                    # here the Topic is extracted using the returned FullTopic, identifying the device
                    parsed = parse_topic(full_topic, topic)
                    if parsed:
                        # got a match, we query the device's MAC address in case it's a known device that had its topic changed
                        logging.debug(
                            "DISCOVERY: topic %s is matched by fulltopic %s",
                            topic, full_topic)

                        d = self.env.find_device(topic=parsed['topic'])
                        if d:
                            d.update_property("FullTopic", full_topic)
                        else:
                            logging.info(
                                "DISCOVERY: Discovered topic=%s with fulltopic=%s",
                                parsed['topic'], full_topic)
                            d = TasmotaDevice(parsed['topic'], full_topic)
                            self.env.devices.append(d)
                            self.device_model.addDevice(d)
                            logging.debug(
                                "DISCOVERY: Sending initial query to topic %s",
                                parsed['topic'])
                            self.initial_query(d, True)
                            self.env.lwts.remove(d.tele_topic("LWT"))
                        d.update_property("LWT", "Online")

    def export(self):
        fname, _ = QFileDialog.getSaveFileName(self,
                                               "Export device list as...",
                                               directory=QDir.homePath(),
                                               filter="CSV files (*.csv)")
        if fname:
            if not fname.endswith(".csv"):
                fname += ".csv"

            with open(fname, "w", encoding='utf8') as f:
                column_titles = [
                    'mac', 'topic', 'friendly_name', 'full_topic',
                    'cmnd_topic', 'stat_topic', 'tele_topic', 'module',
                    'module_id', 'firmware', 'core'
                ]
                c = csv.writer(f)
                c.writerow(column_titles)

                for r in range(self.device_model.rowCount()):
                    d = self.device_model.index(r, 0)
                    c.writerow([
                        self.device_model.mac(d),
                        self.device_model.topic(d),
                        self.device_model.friendly_name(d),
                        self.device_model.fullTopic(d),
                        self.device_model.commandTopic(d),
                        self.device_model.statTopic(d),
                        self.device_model.teleTopic(d),
                        # modules.get(self.device_model.module(d)),
                        self.device_model.module(d),
                        self.device_model.firmware(d),
                        self.device_model.core(d)
                    ])

    def bssid(self):
        BSSIdDialog().exec_()

    def patterns(self):
        PatternsDialog().exec_()

    # def openhab(self):
    #     OpenHABDialog(self.env).exec_()

    def showSubs(self):
        QMessageBox.information(self, "Subscriptions",
                                "\n".join(sorted(self.topics)))

    def clear_LWT(self):
        dlg = ClearLWTDialog(self.env)
        if dlg.exec_() == ClearLWTDialog.Accepted:
            for row in range(dlg.lw.count()):
                itm = dlg.lw.item(row)
                if itm.checkState() == Qt.Checked:
                    topic = itm.text()
                    self.mqtt.publish(topic, retain=True)
                    self.env.lwts.remove(topic)
                    logging.info("MQTT: Cleared %s", topic)

    def prefs(self):
        dlg = PrefsDialog()
        if dlg.exec_() == QDialog.Accepted:
            update_devices = False

            devices_short_version = self.settings.value(
                "devices_short_version", True, bool)
            if devices_short_version != dlg.cbDevShortVersion.isChecked():
                update_devices = True
                self.settings.setValue("devices_short_version",
                                       dlg.cbDevShortVersion.isChecked())

            update_consoles = False

            console_font_size = self.settings.value("console_font_size", 9)
            if console_font_size != dlg.sbConsFontSize.value():
                update_consoles = True
                self.settings.setValue("console_font_size",
                                       dlg.sbConsFontSize.value())

            console_word_wrap = self.settings.value("console_word_wrap", True,
                                                    bool)
            if console_word_wrap != dlg.cbConsWW.isChecked():
                update_consoles = True
                self.settings.setValue("console_word_wrap",
                                       dlg.cbConsWW.isChecked())

            if update_consoles:
                for c in self.consoles:
                    c.console.setWordWrapMode(dlg.cbConsWW.isChecked())
                    new_font = QFont(c.console.font())
                    new_font.setPointSize(dlg.sbConsFontSize.value())
                    c.console.setFont(new_font)

        self.settings.sync()

    def auto_telemetry_period(self):
        curr_val = self.settings.value("autotelemetry", 5000, int)
        period, ok = QInputDialog.getInt(
            self, "Set AutoTelemetry period",
            "Values under 5000ms may cause increased ESP LoadAvg", curr_val,
            1000)
        if ok:
            self.settings.setValue("autotelemetry", period)
            self.settings.sync()

    @pyqtSlot(TasmotaDevice)
    def selectDevice(self, d):
        self.device = d

    @pyqtSlot()
    def openTelemetry(self):
        if self.device:
            tele_widget = TelemetryWidget(self.device)
            self.addDockWidget(Qt.RightDockWidgetArea, tele_widget)
            self.mqtt_publish(self.device.cmnd_topic('STATUS'), "8")

    @pyqtSlot()
    def openConsole(self):
        if self.device:
            console_widget = ConsoleWidget(self.device)
            self.mqtt.messageSignal.connect(console_widget.consoleAppend)
            console_widget.sendCommand.connect(self.mqtt.publish)
            self.addDockWidget(Qt.BottomDockWidgetArea, console_widget)
            console_widget.command.setFocus()
            self.consoles.append(console_widget)

    @pyqtSlot()
    def openRulesEditor(self):
        if self.device:
            rules = RulesWidget(self.device)
            self.mqtt.messageSignal.connect(rules.parseMessage)
            rules.sendCommand.connect(self.mqtt_publish)
            self.mdi.setViewMode(QMdiArea.TabbedView)
            self.mdi.addSubWindow(rules)
            rules.setWindowState(Qt.WindowMaximized)
            rules.destroyed.connect(self.updateMDI)
            self.mqtt_queue.append((self.device.cmnd_topic("ruletimer"), ""))
            self.mqtt_queue.append((self.device.cmnd_topic("rule1"), ""))
            self.mqtt_queue.append((self.device.cmnd_topic("Var"), ""))
            self.mqtt_queue.append((self.device.cmnd_topic("Mem"), ""))

    @pyqtSlot()
    def openWebUI(self):
        if self.device and self.device.p.get('IPAddress'):
            url = QUrl("http://{}".format(self.device.p['IPAddress']))

            try:
                webui = QWebEngineView()
                webui.load(url)

                frm_webui = QFrame()
                frm_webui.setWindowTitle("WebUI [{}]".format(
                    self.device.p['FriendlyName1']))
                frm_webui.setFrameShape(QFrame.StyledPanel)
                frm_webui.setLayout(VLayout(0))
                frm_webui.layout().addWidget(webui)
                frm_webui.destroyed.connect(self.updateMDI)

                self.mdi.addSubWindow(frm_webui)
                self.mdi.setViewMode(QMdiArea.TabbedView)
                frm_webui.setWindowState(Qt.WindowMaximized)

            except NameError:
                QDesktopServices.openUrl(
                    QUrl("http://{}".format(self.device.p['IPAddress'])))

    def updateMDI(self):
        if len(self.mdi.subWindowList()) == 1:
            self.mdi.setViewMode(QMdiArea.SubWindowView)
            self.devices_list.setWindowState(Qt.WindowMaximized)

    def closeEvent(self, e):
        self.settings.setValue("version", self._version)
        self.settings.setValue("window_geometry", self.saveGeometry())
        self.settings.setValue("views_order",
                               ";".join(self.devices_list.views.keys()))

        self.settings.beginGroup("Views")
        for view, items in self.devices_list.views.items():
            self.settings.setValue(view, ";".join(items[1:]))
        self.settings.endGroup()

        self.settings.sync()

        for d in self.env.devices:
            mac = d.p.get('Mac')
            topic = d.p['Topic']
            full_topic = d.p['FullTopic']
            friendly_name = d.p['FriendlyName1']

            if mac:
                self.devices.beginGroup(mac.replace(":", "-"))
                self.devices.setValue("topic", topic)
                self.devices.setValue("full_topic", full_topic)
                self.devices.setValue("friendly_name", friendly_name)

                for i, h in enumerate(d.history):
                    self.devices.setValue("history/{}".format(i), h)
                self.devices.endGroup()
        self.devices.sync()

        e.accept()
Пример #35
0
class MainWindow(QMainWindow):
    """This create the main window of the application"""
    def __init__(self):
        super(MainWindow, self).__init__()
        # remove close & maximize window buttons
        #self.setWindowFlags(Qt.CustomizeWindowHint|Qt.WindowMinimizeButtonHint)
        self.setMinimumSize(500, 666)
        #self.setMaximumSize(1000,666)
        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)

        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.child = None

        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.updateMenus()
        self.readSettings()
        self.setWindowTitle("LEKTURE")

        mytoolbar = QToolBar()
        #self.toolbar = self.addToolBar()
        mytoolbar.addAction(self.newAct)
        mytoolbar.addAction(self.openAct)
        mytoolbar.addAction(self.saveAct)
        mytoolbar.addAction(self.saveAsAct)
        mytoolbar.addSeparator()
        mytoolbar.addAction(self.outputsAct)
        mytoolbar.addAction(self.scenarioAct)
        self.scenarioAct.setVisible(False)
        mytoolbar.setMovable(False)
        mytoolbar.setFixedWidth(60)
        self.addToolBar(Qt.LeftToolBarArea, mytoolbar)

    def closeEvent(self, scenario):
        """method called when the main window wants to be closed"""
        self.mdiArea.closeAllSubWindows()
        if self.mdiArea.currentSubWindow():
            scenario.ignore()
        else:
            self.writeSettings()
            scenario.accept()

    def newFile(self):
        """creates a new project"""
        child = self.createProjekt()
        child.newFile()
        child.show()
        self.child = child

    def open(self):
        """open a project"""
        fileName, _ = QFileDialog.getOpenFileName(self)
        if fileName:
            existing = self.findProjekt(fileName)
            if existing:
                self.mdiArea.setActiveSubWindow(existing)
                return

            child = self.createProjekt()
            if child.loadFile(fileName):
                self.statusBar().showMessage("File loaded", 2000)
                child.show()
            else:
                child.close()

    def save(self):
        """called when user save a project"""
        if self.activeProjekt() and self.activeProjekt().save():
            self.statusBar().showMessage("File saved", 2000)
        else:
            self.statusBar().showMessage("Error when trying to save the file")

    def saveAs(self):
        """called when user save AS a project"""
        if self.activeProjekt() and self.activeProjekt().saveAs():
            self.statusBar().showMessage("File saved", 2000)
        else:
            self.statusBar().showMessage("Error when trying to save the file")

    def openFolder(self):
        """called when user calls 'reveal in finder' function"""
        if self.activeProjekt() and self.activeProjekt().openFolder():
            self.statusBar().showMessage("File revealed in Finder", 2000)

    def about(self):
        """called when user wants to know a bit more on the app"""
        import sys
        python_version = str(sys.version_info[0])
        python_version_temp = sys.version_info[1:5]
        for item in python_version_temp:
            python_version = python_version + "." + str(item)
        QMessageBox.about(self, "About Lekture",
                            "pylekture build " + str(pylekture.__version__ + "\n" + \
                            "python version " + str(python_version)))

    def updateMenus(self):
        """update menus"""
        hasProjekt = (self.activeProjekt() is not None)
        self.saveAct.setEnabled(hasProjekt)
        self.saveAsAct.setEnabled(hasProjekt)
        self.outputsAct.setEnabled(hasProjekt)
        self.scenarioAct.setEnabled(hasProjekt)
        self.openFolderAct.setEnabled(hasProjekt)
        self.closeAct.setEnabled(hasProjekt)
        self.closeAllAct.setEnabled(hasProjekt)
        self.nextAct.setEnabled(hasProjekt)
        self.previousAct.setEnabled(hasProjekt)
        self.separatorAct.setVisible(hasProjekt)

    def updateWindowMenu(self):
        """unpates menus on the window toolbar"""
        self.windowMenu.clear()
        self.windowMenu.addAction(self.closeAct)
        self.windowMenu.addAction(self.closeAllAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.nextAct)
        self.windowMenu.addAction(self.previousAct)
        self.windowMenu.addAction(self.separatorAct)

        windows = self.mdiArea.subWindowList()
        self.separatorAct.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            child = window.widget()

            text = "%d %s" % (i + 1, child.userFriendlyCurrentFile())
            if i < 9:
                text = '&' + text

            action = self.windowMenu.addAction(text)
            action.setCheckable(True)
            action.setChecked(child is self.activeProjekt())
            action.triggered.connect(self.windowMapper.map)
            self.windowMapper.setMapping(action, window)

    def createProjekt(self):
        """create a new project"""
        child = Projekt()
        self.mdiArea.addSubWindow(child)
        self.child = child
        return child

    def createActions(self):
        """create all actions"""
        self.newAct = QAction("&New", self,
                              shortcut=QKeySequence.New, statusTip="Create a new file",
                              triggered=self.newFile)

        self.openAct = QAction("&Open...", self,
                               shortcut=QKeySequence.Open, statusTip="Open an existing file",
                               triggered=self.open)

        self.saveAct = QAction("&Save", self,
                               shortcut=QKeySequence.Save,
                               statusTip="Save the document to disk", triggered=self.save)

        self.saveAsAct = QAction("Save &As...", self,
                                 shortcut=QKeySequence.SaveAs,
                                 statusTip="Save the document under a new name",
                                 triggered=self.saveAs)

        self.openFolderAct = QAction("Open Project Folder", self,
                                     statusTip="Reveal Project in Finder",
                                     triggered=self.openFolder)

        self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit,
                               statusTip="Exit the application",
                               triggered=QApplication.instance().closeAllWindows)

        self.closeAct = QAction("Cl&ose", self,
                                statusTip="Close the active window",
                                triggered=self.mdiArea.closeActiveSubWindow)

        self.outputsAct = QAction("Outputs", self,
                                  statusTip="Open the outputs panel",
                                  triggered=self.openOutputsPanel)

        self.scenarioAct = QAction("Scenario", self,
                                   statusTip="Open the scenario panel",
                                   triggered=self.openScenarioPanel)

        self.closeAllAct = QAction("Close &All", self,
                                   statusTip="Close all the windows",
                                   triggered=self.mdiArea.closeAllSubWindows)

        self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild,
                               statusTip="Move the focus to the next window",
                               triggered=self.mdiArea.activateNextSubWindow)

        self.previousAct = QAction("Pre&vious", self,
                                   shortcut=QKeySequence.PreviousChild,
                                   statusTip="Move the focus to the previous window",
                                   triggered=self.mdiArea.activatePreviousSubWindow)

        self.separatorAct = QAction(self)
        self.separatorAct.setSeparator(True)

        self.aboutAct = QAction("&About", self,
                                statusTip="Show the application's About box",
                                triggered=self.about)

    def createMenus(self):
        """create all menus"""
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.openFolderAct)
        self.fileMenu.addAction(self.exitAct)

        self.viewMenu = self.menuBar().addMenu("&View")
        self.viewMenu.addAction(self.outputsAct)
        self.viewMenu.addAction(self.scenarioAct)

        self.windowMenu = self.menuBar().addMenu("&Window")
        self.updateWindowMenu()
        self.windowMenu.aboutToShow.connect(self.updateWindowMenu)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)

    def createStatusBar(self):
        """create the status bar"""
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        """read the settings"""
        settings = QSettings('Pixel Stereo', 'lekture')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(1000, 650))
        self.move(pos)
        self.resize(size)

    def writeSettings(self):
        """write settings"""
        settings = QSettings('Pixel Stereo', 'lekture')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())

    def activeProjekt(self):
        """return the active project object"""
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        else:
            return None

    def findProjekt(self, fileName):
        """return the project"""
        canonicalFilePath = QFileInfo(fileName).canonicalFilePath()

        for window in self.mdiArea.subWindowList():
            if window.widget().currentFile() == canonicalFilePath:
                return window
        return None

    def setActiveSubWindow(self, window):
        """set the active sub window"""
        if window:
            self.mdiArea.setActiveSubWindow(window)

    def openOutputsPanel(self):
        """switch to the outputs editor"""
        if self.child:
            project = self.activeProjekt()
            project.scenario_events_group.setVisible(False)
            project.outputs_group.setVisible(True)
            self.scenarioAct.setVisible(True)
            self.outputsAct.setVisible(False)

    def openScenarioPanel(self):
        """switch to the scenario editors"""
        if self.child:
            project = self.activeProjekt()
            project.outputs_group.setVisible(False)
            project.scenario_events_group.setVisible(True)
            self.scenarioAct.setVisible(False)
            self.outputsAct.setVisible(True)