Beispiel #1
0
    def init_tray(self):
        """
            Initializes the systray menu
        """
        traymenu = QMenu("Menu")
        self.tray.setContextMenu(traymenu)
        self.tray.show()
        self.tray.activated.connect(self.tray_click)
        self.tray.setToolTip("Pomodori: "+str(self.pom.pomodori))

        set_timer_tray = QLineEdit()
        set_timer_tray.setPlaceholderText("Set timer")
        set_timer_tray.textChanged.connect(lambda:
                                           self.update_timer_text(set_timer_tray.text()))
        traywidget = QWidgetAction(set_timer_tray)
        traywidget.setDefaultWidget(set_timer_tray)
        traymenu.addAction(traywidget)

        start_timer_action = QAction("&Start Timer", self)
        start_timer_action.triggered.connect(self.start_timer_click)
        traymenu.addAction(start_timer_action)

        exit_action = QAction("&Exit", self)
        exit_action.triggered.connect(QCoreApplication.instance().quit)
        traymenu.addAction(exit_action)
Beispiel #2
0
 def initUI(self):
     self.setPopupMode(QToolButton.MenuButtonPopup)
     self.menu = QMenu(self)
     self.setMenu(self.menu)
     self.setFixedSize(*self.BUTTON_SIZE)
     self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
     self.listWidget = self.createListWidget()
     self.listWidget.installEventFilter(self)
     action = QWidgetAction(self)
     action.setDefaultWidget(self.listWidget)
     self.menu.addAction(action)
     self.updateIcon()
Beispiel #3
0
def TitledMenu(titles, padding=5, with_separator=True):
    """

    :param title: the title for menu
    :param padding: the padding defaults to 5 px
    :param with_separator: if true adds a separator
    :return: the QMenu with a title
    """
    menu = QMenu()

    for title in titles:
        label = QLabel(title)
        label.setStyleSheet("padding: {}px; background-color: rgba(0, 0, 0, 0);".format(padding))
        title_widget = QWidgetAction(menu)
        title_widget.setDefaultWidget(label)
        menu.addAction(title_widget)

    if with_separator:
        menu.addSeparator()

    return menu
Beispiel #4
0
    def setup_context_menu(self):
        """

        :return:
        """

        self.custMenu = QMenu("Options")
        self.gridMenu = QMenu('Grid')


        # Grid Menu:
        # -----------------------------------------------------------
        # Y-Grid checkbox
        self.xGrid_Checkbox = QCheckBox()
        self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)
        self.xGrid_Checkbox.setText('X-Grid')
        self.xGrid_Action = QWidgetAction(self.__plotWidget__)
        self.xGrid_Action.setDefaultWidget(self.xGrid_Checkbox)
        self.gridMenu.addAction(self.xGrid_Action)
        # Check config for startup  state
        if self.__show_grid_x__:
            self.xGrid_Checkbox.setChecked(True)

        # X-Grid checkbox
        self.yGrid_Checkbox = QCheckBox()
        self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)
        self.yGrid_Checkbox.setText('Y-Grid')
        self.yGrid_Action = QWidgetAction(self.__plotWidget__)
        self.yGrid_Action.setDefaultWidget(self.yGrid_Checkbox)
        self.gridMenu.addAction(self.yGrid_Action)
        # Check config for startup  state
        if self.__show_grid_y__:
            self.yGrid_Checkbox.setChecked(True)

        # add Menus
        self.custMenu.addMenu(self.gridMenu)

        self.__plotWidget__.getPlotItem().getViewBox().menu.clear()

        self.__plotWidget__.getPlotItem().ctrlMenu = [self.pl_create_control_context_menu(), self.custMenu]
Beispiel #5
0
    def createCheckBoxes(self):
         #Create checkbox
        data_unique = []
        
        self.table=QTableWidget()

        self.table.setColumnCount(1)
        self.table.verticalHeader().hide()
        self.table.horizontalHeader().hide()
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.setRowCount(self.rowCount())
       
       
        #Assign the action a create the list of checkbox
        self.checkBoxs = []
        checkBox = QCheckBox("Seleccionar todo", self.menu)
        
        checkableAction = QWidgetAction(self.menu)
        checkableAction.setDefaultWidget(checkBox)
        self.menu.addAction(checkableAction)
        checkBox.setChecked(Qt.Checked)
        checkBox.stateChanged.connect(self.slotSelect)
        j=0
        for i in range(self.rowCount()):
            if not self.isRowHidden(i):
                item = self.item(i, self.col )
                if item.text() not in data_unique:
                    data_unique.append(item.text())
                    
                    it = QTableWidgetItem(item.text())
                    it.setFlags(Qt.ItemIsUserCheckable |Qt.ItemIsEnabled)
                    it.setCheckState(Qt.Checked)
                    
                    self.checkBoxs.append(it)
                    j=j+1

        #Sort the element of the list 
        self.checkBoxs=sorted(self.checkBoxs, key=lambda it: it.text())
       # self.sort(self.checkBoxs[i])
        j=0
        for i in range(len(self.checkBoxs)):
                #print(self.checkBoxs[i].text())
                self.table.setItem(j,0,  self.checkBoxs[i])
                j=j+1
        self.table.update()


        self.table.setRowCount(len(self.checkBoxs))
        checkableAction = QWidgetAction(self.menu)
        checkableAction.setDefaultWidget(self.table)
        self.menu.addAction(checkableAction)
Beispiel #6
0
 def create_widget_action(self, icon, text, data=None):
     act = QWidgetAction(self)
     act.setText(text)
     if data is not None:
         act.setData(data)
     widget = QWidget(self)
     layout = QHBoxLayout()
     layout.setContentsMargins(13, -1, -1, 11)
     layout.setSpacing(13)
     lb_icon = QLabel(widget)
     lb_icon.resize(18, 18)
     lb_text = QLabel(text, widget)
     if icon != "":
         lb_icon.setPixmap(QPixmap(icon))
     widget.setStyleSheet("QWidget:hover{background:#ededef}")
     layout.addWidget(lb_icon)
     layout.addWidget(lb_text)
     layout.addStretch()
     widget.setLayout(layout)
     act.setDefaultWidget(widget)
     return act
    def context_menu(self):
        menu = QMenu()
        font_box = QFontComboBox()
        font_box.setCurrentFont(self.post_text_font)
        font_box.currentFontChanged.connect(
            lambda: self.set_post_text_font(font=font_box.currentFont()))
        font_box.currentFontChanged.connect(menu.close)
        font_box_label = QLabel('Font:')
        layout = QHBoxLayout()
        layout.addWidget(font_box_label)
        layout.addWidget(font_box)
        font_box_widget = QWidget(self)
        font_box_widget.setLayout(layout)
        font_box_item = QWidgetAction(self)
        font_box_item.setDefaultWidget(font_box_widget)

        font_size_box = QComboBox()
        font_size_box.addItems(str(x) for x in range(4, 30))
        font_size_box.setCurrentText(str(self.post_text_font_size))
        font_size_label = QLabel('Font Size:')
        size_layout = QHBoxLayout()
        size_layout.addWidget(font_size_label)
        size_layout.addWidget(font_size_box)
        font_size_widget = QWidget(self)
        font_size_widget.setLayout(size_layout)
        font_size_box.currentIndexChanged.connect(
            lambda: self.set_post_text_font(size=int(font_size_box.currentText(
            ))))
        font_size_box.currentIndexChanged.connect(menu.close)
        font_size_item = QWidgetAction(self)
        font_size_item.setDefaultWidget(font_size_widget)

        menu.addAction(font_box_item)
        menu.addAction(font_size_item)
        menu.addSeparator()
        if not self.stand_alone:
            menu.addAction('Detach Text Box',
                           lambda: self.detach_signal.emit())
        menu.exec_(QCursor.pos())
Beispiel #8
0
    def on_view_horizontalHeader_sectionClicked(self, index):
        
        self.menu = QMenu(self)
       
        self.col = index
        


       
        self.createCheckBoxes()

        
        #Accept and cancel button
        btn = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
                                     Qt.Horizontal, self.menu)
        btn.accepted.connect(self.menuClose)
        btn.rejected.connect(self.menu.close)
        checkableAction = QWidgetAction(self.menu)
        checkableAction.setDefaultWidget(btn)
        self.menu.addAction(checkableAction)

        ##Clear Button
        btnClr = QPushButton(QIcon(),"Limpiar Filtro", self.menu)
        btnClr.clicked.connect(self.clearFilter)
        checkableAction = QWidgetAction(self.menu)
        checkableAction.setDefaultWidget(btnClr)
        self.menu.addAction(checkableAction)







        headerPos = self.mapToGlobal(self.horizontalHeader().pos())

        posY = headerPos.y() + self.horizontalHeader().height()
        posX = headerPos.x() + self.horizontalHeader().sectionPosition(index)
        self.menu.exec_(QPoint(posX, posY))
Beispiel #9
0
    def __init__(self):
        super().__init__()

        arguments = self.parseArguments()

        self.DEBUG = arguments.debug

        os.chdir(os.path.dirname(os.path.realpath(__file__)))

        self.MIN_WIDTH = 600
        self.MIN_HEIGHT = 350

        self.setMinimumWidth(self.MIN_WIDTH)
        self.setMinimumHeight(self.MIN_HEIGHT)

        self.ROOT_FOLDER = os.path.expanduser("~/.florodoro/")

        self.HISTORY_FILE_PATH = self.ROOT_FOLDER + "history" + ("" if not self.DEBUG else "-debug") + ".yaml"
        self.CONFIGURATION_FILE_PATH = self.ROOT_FOLDER + "config" + ("" if not self.DEBUG else "-debug") + ".yaml"

        self.history = History(self.HISTORY_FILE_PATH)

        self.SOUNDS_FOLDER = "sounds/"
        self.PLANTS_FOLDER = "plants/"
        self.IMAGE_FOLDER = "images/"

        self.TEXT_COLOR = self.palette().text().color()
        self.BREAK_COLOR = "#B37700"

        self.APP_NAME = "Florodoro"

        self.STUDY_ICON = qtawesome.icon('fa5s.book', color=self.TEXT_COLOR)
        self.BREAK_ICON = qtawesome.icon('fa5s.coffee', color=self.BREAK_COLOR)
        self.CONTINUE_ICON = qtawesome.icon('fa5s.play', color=self.TEXT_COLOR)
        self.PAUSE_ICON = qtawesome.icon('fa5s.pause', color=self.TEXT_COLOR)
        self.RESET_ICON = qtawesome.icon('fa5s.undo', color=self.TEXT_COLOR)

        self.PLANTS = [GreenTree, DoubleGreenTree, OrangeTree, CircularFlower]
        self.PLANT_NAMES = ["Spruce", "Double spruce", "Maple", "Flower"]

        self.MAX_PLANT_AGE = 90  # maximum number of minutes to make the plant optimal in size

        self.WIDGET_SPACING = 10

        self.MAX_TIME = 180
        self.STEP = 5

        self.INITIAL_TEXT = "Start!"

        self.menuBar = QMenuBar(self)
        self.presets_menu = self.menuBar.addMenu('&Presets')

        self.presets = {
            "Classic": (25, 5, 4),
            "Extended": (45, 12, 2),
            "Sitcomodoro": (65, 25, 1),
        }

        for name in self.presets:
            study_time, break_time, cycles = self.presets[name]

            self.presets_menu.addAction(
                QAction(f"{name} ({study_time} : {break_time} : {cycles})", self,
                        triggered=partial(self.load_preset, study_time, break_time, cycles)))

        self.DEFAULT_PRESET = "Classic"

        self.options_menu = self.menuBar.addMenu('&Options')

        self.notify_menu = self.options_menu.addMenu("&Notify")

        self.sound_action = QAction("&Sound", self, checkable=True, checked=not self.DEBUG,
                                    triggered=lambda _: self.volume_slider.setDisabled(
                                        not self.sound_action.isChecked()))

        self.notify_menu.addAction(self.sound_action)

        self.volume_slider = QSlider(Qt.Horizontal, minimum=0, maximum=100, value=85)
        slider_action = QWidgetAction(self)
        slider_action.setDefaultWidget(SpacedQWidget(self.volume_slider))
        self.notify_menu.addAction(slider_action)

        self.popup_action = QAction("&Pop-up", self, checkable=True, checked=True)
        self.notify_menu.addAction(self.popup_action)

        self.menuBar.addAction(
            QAction(
                "&Statistics",
                self,
                triggered=lambda: self.statistics.show() if self.statistics.isHidden() else self.statistics.hide()
            )
        )

        self.menuBar.addAction(
            QAction(
                "&About",
                self,
                triggered=lambda: QMessageBox.information(
                    self,
                    "About",
                    "This application was created by Tomáš Sláma. It is heavily inspired by the Android app Forest, "
                    "but with all of the plants generated procedurally. It's <a href='https://github.com/xiaoxiae/Florodoro'>open source</a> and licensed "
                    "under MIT, so do as you please with the code and anything else related to the project.",
                ),
            )
        )

        self.plant_menu = self.options_menu.addMenu("&Plants")

        self.overstudy_action = QAction("Overstudy", self, checkable=True)
        self.options_menu.addAction(self.overstudy_action)

        self.plant_images = []
        self.plant_checkboxes = []

        # dynamically create widgets for each plant
        for plant, name in zip(self.PLANTS, self.PLANT_NAMES):
            self.plant_images.append(tempfile.NamedTemporaryFile(suffix=".svg"))
            tmp = plant()
            tmp.set_max_age(1)
            tmp.set_age(1)
            tmp.save(self.plant_images[-1].name, 200, 200)

            setattr(self.__class__, name,
                    QAction(self, icon=QIcon(self.plant_images[-1].name), text=name, checkable=True, checked=True))

            action = getattr(self.__class__, name)

            self.plant_menu.addAction(action)
            self.plant_checkboxes.append(action)

        # the current plant that we're growing
        # if set to none, no plant is growing
        self.plant = None

        self.menuBar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum)

        main_vertical_layout = QVBoxLayout(self)
        main_vertical_layout.setContentsMargins(0, 0, 0, 0)
        main_vertical_layout.setSpacing(0)
        main_vertical_layout.addWidget(self.menuBar)

        self.canvas = Canvas(self)

        self.statistics = Statistics(self.history)

        font = self.font()
        font.setPointSize(100)

        self.main_label = QLabel(self, alignment=Qt.AlignCenter)
        self.main_label.setFont(font)
        self.main_label.setText(self.INITIAL_TEXT)

        font.setPointSize(26)
        self.cycle_label = QLabel(self)
        self.cycle_label.setAlignment(Qt.AlignTop)
        self.cycle_label.setMargin(20)
        self.cycle_label.setFont(font)

        main_horizontal_layout = QHBoxLayout(self)

        self.study_time_spinbox = QSpinBox(self, prefix="Study for: ", suffix="min.", minimum=1, maximum=self.MAX_TIME,
                                           singleStep=self.STEP)

        self.break_time_spinbox = QSpinBox(self, prefix="Break for: ", suffix="min.", minimum=1, maximum=self.MAX_TIME,
                                           singleStep=self.STEP,
                                           styleSheet=f'color:{self.BREAK_COLOR};')

        self.cycles_spinbox = QSpinBox(self, prefix="Cycles: ", minimum=1, value=1)

        # keep track of remaining number of cycles and the starting number of cycles
        self.remaining_cycles = 0
        self.total_cycles = 0

        # whether we're currently studying
        self.is_study_ongoing = False

        # whether we notified the user already during overstudy
        self.already_notified_during_overstudy = False

        stacked_layout = QStackedLayout(self, stackingMode=QStackedLayout.StackAll)
        stacked_layout.addWidget(self.main_label)
        stacked_layout.addWidget(self.cycle_label)
        stacked_layout.addWidget(self.canvas)

        main_vertical_layout.addLayout(stacked_layout)

        self.setStyleSheet("")

        self.study_button = QPushButton(self, clicked=self.start, icon=self.STUDY_ICON)
        self.break_button = QPushButton(self, clicked=self.start_break, icon=self.BREAK_ICON)
        self.pause_button = QPushButton(self, clicked=self.toggle_pause, icon=self.PAUSE_ICON)
        self.reset_button = QPushButton(self, clicked=self.reset, icon=self.RESET_ICON)

        main_horizontal_layout.addWidget(self.study_time_spinbox)
        main_horizontal_layout.addWidget(self.break_time_spinbox)
        main_horizontal_layout.addWidget(self.cycles_spinbox)
        main_horizontal_layout.addWidget(self.study_button)
        main_horizontal_layout.addWidget(self.break_button)
        main_horizontal_layout.addWidget(self.pause_button)
        main_horizontal_layout.addWidget(self.reset_button)

        main_vertical_layout.addLayout(main_horizontal_layout)

        self.setLayout(main_vertical_layout)

        self.study_timer_frequency = 1 / 60 * 1000
        self.study_timer = QTimer(self, interval=int(self.study_timer_frequency), timeout=self.decrease_remaining_time)

        self.player = QMediaPlayer(self)

        self.setWindowIcon(QIcon(self.IMAGE_FOLDER + "icon.svg"))
        self.setWindowTitle(self.APP_NAME)

        # set initial UI state
        self.reset()

        # a list of name, getter and setter things to load/save when the app opens/closes
        # also dynamically get settings for selecting/unselecting plants
        self.CONFIGURATION_ATTRIBUTES = [("study-time", self.study_time_spinbox.value,
                                          self.study_time_spinbox.setValue),
                                         ("break-time", self.break_time_spinbox.value,
                                          self.break_time_spinbox.setValue),
                                         ("cycles", self.cycles_spinbox.value, self.cycles_spinbox.setValue),
                                         ("sound", self.sound_action.isChecked, self.sound_action.setChecked),
                                         ("sound-volume", self.volume_slider.value, self.volume_slider.setValue),
                                         ("pop-ups", self.popup_action.isChecked, self.popup_action.setChecked),
                                         ("overstudy", self.overstudy_action.isChecked,
                                          self.overstudy_action.setChecked)] + \
                                        [(name.lower(), getattr(self.__class__, name).isChecked,
                                          getattr(self.__class__, name).setChecked) for _, name in
                                         zip(self.PLANTS, self.PLANT_NAMES)]
        # load the default preset
        self.load_preset(*self.presets[self.DEFAULT_PRESET])

        self.load_settings()
        self.show()
Beispiel #10
0
    def show_header_menu(self, col: int):
        """Pop up a mini entry menu for filtering on a column."""
        key = self._model._HEADERS[col]
        if key not in ["name", "flagging"] or self._block_header_menu:
            self._block_header_menu = False
            return
        self._filter_menu = QMenu(self.parent())
        self._filter_menu.aboutToHide.connect(
            self._check_mouse_on_header_menu_hide)

        def get_filter_cb(key, f):
            def cb():
                self.add_filter.emit(key, f)
                self._block_header_menu = False

            return cb

        if key == "flagging":
            group = QActionGroup(self)
            group.setExclusive(True)
            for filter_string in ["All", "F", "NF"]:
                action = QAction(filter_string, group, checkable=True)
                if filter_string == "All" and not self._state.flagging_filter:
                    action.setChecked(True)
                    filter_string = ""
                elif filter_string == self._state.flagging_filter:
                    action.setChecked(True)
                self._filter_menu.addAction(action)
                action.triggered.connect(get_filter_cb(key, filter_string))

        elif key == "name":
            # Make button for resetting filter (show all).
            all_action = QAction("All", checkable=True)
            if not self._model._filters["name"]:
                all_action.setChecked(True)
            all_action.triggered.connect(get_filter_cb(key, None))
            self._filter_menu.addAction(all_action)  # add to menu
            self._filter_menu.addSeparator(
            )  # patch highlighting with mouse movement
            ## Make entry bar for name filter.
            # Create the entry bar with the existing filter as the text.
            if self._state.name_hint:
                # Name in entry bar, if any.
                text = self._state.name_hint
            else:
                # If no name in entry bar, name currently filtered by.
                text = self._state.name_filter
            entry = QLineEdit(text, self)
            entry.selectAll()  # select all the text
            # Set focus to the entry bar when the menu is opened.
            self._filter_menu.aboutToShow.connect(entry.setFocus)

            def set_name_filter():
                self.add_filter.emit(key, entry.text().strip())
                self._filter_menu.hide()
                self._block_header_menu = False

            entry.returnPressed.connect(
                set_name_filter)  # enter applies filter
            name_action = QWidgetAction(
                self._filter_menu)  # to contain QLineEdit
            name_action.setDefaultWidget(entry)  # set widget on QWidgetAction
            self._filter_menu.addAction(name_action)  # add to menu
        self._filter_menu.index = col
        # Display menu in appropriate position, below header in column 'col'
        headerPos = self.mapToGlobal(self._header.pos())
        posY = headerPos.y() + self._header.height()
        posX = headerPos.x() + self._header.sectionPosition(col)
        pos = QPoint(posX, posY)
        self._filter_menu.exec_(pos)  # modal dialog
        self.resizeRowsToContents()
Beispiel #11
0
 def setupZoomWidget(self):
     self.zoom = QWidgetAction(self)
     self.zoomWidget = ZoomWidget()
     self.zoom.setDefaultWidget(self.zoomWidget)
     self.zoomWidget.setEnabled(False)
Beispiel #12
0
	def configure_menuBar(self):
		menubar = self.menuBar()

		menubar_items = {
			'&File': [
				("&New File", "Ctrl+N", self.add_new_tab),
				("&Open File", "Ctrl+O", self.file_open),
				("&Save File", "Ctrl+S", self.file_save),
				("&Save File as", "Ctrl+Shift+S", self.save_as),
				("&Print", "Ctrl+P", self.print_document),
				None,
				("&Quit", "Ctrl+Q", self.quit),
			],
			'&Edit': [
				("&Cut", "Ctrl+X", self.cut_document),
				("&Copy", "Ctrl+C", self.copy_document),
				("&Paste", "Ctrl+V", self.paste_document),
				None,
				("&Undo", "Ctrl+Z", self.undo_document),
				("&Redo", "Ctrl+Y", self.redo_document)
			],
			'&View': [
				("&Fullscreen", "F11", self.fullscreen),
				None,
				("&Align Left", "", self.align_left),
				("&Align Right", "", self.align_right),
				("&Align Center", "", self.align_center),
				("&Align Justify", "", self.align_justify)
			],
			'&About': [
				("&About Us", "Ctrl+H", self.about),
				None,
				("&Help", "", self.help)
			]
		}

		for menuitem, actions in menubar_items.items():
			menu = menubar.addMenu(menuitem)
			for act in actions:
				if act:
					text, shortcut, callback = act
					action = QAction(text, self)
					action.setShortcut(shortcut)
					action.triggered.connect(callback)
					menu.addAction(action)
				else:
					menu.addSeparator()

		# Font Family Input
		fontBox = QFontComboBox(self)
		fontBox.currentFontChanged.connect(self.fontfamily)

		fontSize = QComboBox(self)
		fontSize.setEditable(True)
		fontSize.setMinimumContentsLength(3)

		fontSize.activated.connect(self.fontsize)

		# Font Sizes
		fontSizes = [
			'6', '7', '8', '9', '10', '11', '12', '13', '14',
			'15', '16', '18', '20', '22', '24', '26', '28',
			'32', '36', '40', '44', '48', '54', '60', '66',
			'72', '80', '88', '96'
		]

		fontSize.addItems(fontSizes)
		font_family = QWidgetAction(self)
		font_family.setDefaultWidget(fontBox)
		# Settings Menubar
		settings = menubar.addMenu('&Font Settings')
		menu_font = settings.addMenu("&Font")
		menu_font.addAction(font_family)

		font_size = QWidgetAction(self)
		font_size.setDefaultWidget(fontSize)
		menu_size = settings.addMenu("&Font Size")
		menu_size.addAction(font_size)
Beispiel #13
0
    def __init__(self, font, parent=None):
        super().__init__(parent)
        auxiliaryWidth = self.fontMetrics().width('0') * 8
        self.leftTextField = MetricsSequenceEdit(font, self)
        self.leftTextField.setMaximumWidth(auxiliaryWidth)
        self.textField = MetricsSequenceComboBox(font, self)
        # XXX: had to use Maximum because Preferred did extend the widget(?)
        self.textField.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Maximum)
        self.rightTextField = MetricsSequenceEdit(font, self)
        self.rightTextField.setMaximumWidth(auxiliaryWidth)
        self.leftTextField.textEdited.connect(self.textField.editTextChanged)
        self.rightTextField.textEdited.connect(self.textField.editTextChanged)
        self.textField.editTextChanged.connect(self._textChanged)

        self.comboBox = QComboBox(self)
        self.comboBox.setEditable(True)
        self.comboBox.setCompleter(None)
        self.comboBox.setValidator(QIntValidator(self))
        for p in pointSizes:
            self.comboBox.addItem(str(p))
        self.pointSizeChanged = self.comboBox.currentIndexChanged[str]

        self.configBar = QPushButton(self)
        self.configBar.setFlat(True)
        self.configBar.setIcon(QIcon(":settings.svg"))
        self.configBar.setStyleSheet("padding: 2px 0px; padding-right: 10px")
        self.toolsMenu = QMenu(self)
        self._showKerning = self.toolsMenu.addAction(
            self.tr("Show Kerning"), self._kerningVisibilityChanged)
        self._showKerning.setCheckable(True)
        self._showMetrics = self.toolsMenu.addAction(
            self.tr("Show Metrics"), self._controlsTriggered)
        self._showMetrics.setCheckable(True)
        self.toolsMenu.addSeparator()
        self._verticalFlip = self.toolsMenu.addAction(
            self.tr("Vertical Flip"), self._controlsTriggered)
        self._verticalFlip.setCheckable(True)
        self._wrapLines = self.toolsMenu.addAction(
            self.tr("Wrap Lines"), self._controlsTriggered)
        self._wrapLines.setCheckable(True)
        self.toolsMenu.addSeparator()
        action = self.toolsMenu.addAction(self.tr("Line Height:"))
        action.setEnabled(False)
        lineHeight = QWidgetAction(self.toolsMenu)
        self._lineHeightSlider = slider = QSlider(Qt.Horizontal, self)
        # QSlider works with integers so we'll just divide what comes out of it
        # by 100
        slider.setMinimum(80)
        slider.setMaximum(160)
        slider.setValue(110)
        slider.valueChanged.connect(self._controlsTriggered)
        slider.valueChanged.connect(self._sliderLineHeightChanged)
        lineHeight.setDefaultWidget(slider)
        self.toolsMenu.addAction(lineHeight)
        self.configBar.setMenu(self.toolsMenu)

        self.addWidget(self.leftTextField)
        self.addWidget(self.textField)
        self.addWidget(self.rightTextField)
        self.addWidget(self.comboBox)
        self.addWidget(self.configBar)

        app = QApplication.instance()
        app.dispatcher.addObserver(
            self, "_currentGlyphChanged", "currentGlyphChanged")

        self.readSettings()
        color = QColor('#29AB87') if self.ok else QColor(255, 0, 0, 128)

        painter = QPainter(self)
        painter.setBrush(color)
        painter.setPen(color)
        painter.drawRect(self.rect())


# TODO: Нарисовать график
if __name__ == '__main__':
    app = QApplication([])
    app.setQuitOnLastWindowClosed(False)

    tray = QSystemTrayIcon(QIcon(TRAY_ICON))

    job_report_widget = JobReportWidget()
    job_report_widget.setFixedSize(230, 130)
    job_report_widget_action = QWidgetAction(job_report_widget)
    job_report_widget_action.setDefaultWidget(job_report_widget)

    menu = QMenu()
    menu.addAction(job_report_widget_action)

    tray.setContextMenu(menu)
    tray.activated.connect(lambda x: menu.exec(tray.geometry().center()))

    tray.setToolTip('Compass Plus. Рапорт учета рабочего времени')
    tray.show()

    app.exec()
Beispiel #15
0
class MovieWidget(QWidget):
    #-------------------------------------------------------------------------------
    # __init__()
    #-------------------------------------------------------------------------------
    def __init__(self, parent=None):
        super(MovieWidget, self).__init__(parent)
        mini = True
        self.parent = parent
        self.isVideoAvailable = False
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.videoAvailableChanged.connect(
            self.videoAvailableChanged)

        videoWidget = QVideoWidget(self)
        videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setContextMenuPolicy(Qt.CustomContextMenu)

        # Context Menu
        self.customContextMenuRequested.connect(self.openContextMenu)
        self.contextMenu = QMenu()

        self.openAction = self.contextMenu.addAction("Open file")
        icon = QIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton))
        self.openAction.setIcon(icon)

        self.urlAction = self.contextMenu.addAction("Open stream")
        icon = QIcon(self.style().standardIcon(QStyle.SP_DirLinkIcon))
        self.urlAction.setIcon(icon)

        self.playAction = self.contextMenu.addAction("Play/Pause")
        icon = QIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playAction.setEnabled(False)
        self.playAction.setIcon(icon)

        self.closeAction = self.contextMenu.addAction("Close")
        icon = QIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton))
        self.closeAction.setEnabled(False)
        self.closeAction.setIcon(icon)

        self.posSlider = QSlider(Qt.Horizontal)
        self.posSlider.setRange(0, 0)
        self.posSlider.sliderMoved.connect(self.setPosition)
        self.wac = QWidgetAction(self.contextMenu)
        self.wac.setDefaultWidget(self.posSlider)
        self.posAction = self.contextMenu.addAction(self.wac)

        self.lblFile = QLabel()
        self.wal = QWidgetAction(self.contextMenu)
        self.wal.setDefaultWidget(self.lblFile)
        self.posAction = self.contextMenu.addAction(self.wal)

        # Control box
        self.openButton = QPushButton()
        self.openButton.setIcon(self.style().standardIcon(
            QStyle.SP_DialogOpenButton))
        self.openButton.clicked.connect(self.openFile)

        self.urlButton = QPushButton()
        self.urlButton.setIcon(self.style().standardIcon(
            QStyle.SP_DirLinkIcon))
        self.urlButton.clicked.connect(self.openURL)

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Maximum)

        # Create layouts to place inside widget
        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(self.openButton)
        controlLayout.addWidget(self.urlButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.addWidget(videoWidget)
        if mini != True:
            vLayout.addLayout(controlLayout)
            vLayout.addWidget(self.errorLabel)

        self.setLayout(vLayout)

        # Set widget to contain window contents
        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        self.resize(180, 100)

#-------------------------------------------------------------------------------
# videoAvailableChanged()
#-------------------------------------------------------------------------------

    def videoAvailableChanged(self, available):
        self.isVideoAvailable = available
        print("Video available %s" % str(available))

#-------------------------------------------------------------------------------
# openContextMenu()
#-------------------------------------------------------------------------------

    def openContextMenu(self, position):
        action = self.contextMenu.exec_(self.mapToGlobal(position))
        if action == self.playAction:
            self.play()
        elif action == self.openAction:
            self.openFile()
        elif action == self.urlAction:
            self.openURL()
        elif action == self.closeAction:
            self.closeFile()

#-------------------------------------------------------------------------------
# openFile()
#-------------------------------------------------------------------------------

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self,
            "Open Media",
            QDir.homePath(),
            "All Files (*);;Movies (*.avi *.mp4);;Music (*.mp3 *.ogg)",
            options=QFileDialog.DontUseNativeDialog)
        if fileName != '':
            self.mediaSource = os.path.splitext(os.path.basename(fileName))[0]
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(fileName)))
            self.errorLabel.setText(
                os.path.splitext(os.path.basename(fileName))[0])
            self.lblFile.setText(" " + self.mediaSource)
            self.playButton.setEnabled(True)
            self.playAction.setEnabled(True)
            self.closeAction.setEnabled(True)
            self.play()

#-------------------------------------------------------------------------------
# openURL()
#-------------------------------------------------------------------------------

    def openURL(self):
        url, ok = QInputDialog.getText(self, 'Open Stream', 'URL of stream :')
        if ok:
            if url != '':
                self.mediaSource = url
                self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
                self.errorLabel.setText(url)
                self.lblFile.setText(" " + url)
                self.playButton.setEnabled(True)
                self.playAction.setEnabled(True)
                self.closeAction.setEnabled(True)
                self.play()

#-------------------------------------------------------------------------------
# closeFile()
#-------------------------------------------------------------------------------

    def closeFile(self):
        self.pauseForce()
        self.mediaPlayer.setMedia(QMediaContent())
        self.playButton.setEnabled(False)
        self.playAction.setEnabled(False)
        self.closeAction.setEnabled(False)
        self.lblFile.setText("")

#-------------------------------------------------------------------------------
# play()
#-------------------------------------------------------------------------------

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()
            self.parent.bigDisplay(self.mediaSource)

#-------------------------------------------------------------------------------
# playForce()
#-------------------------------------------------------------------------------

    def playForce(self):
        self.mediaPlayer.play()

#-------------------------------------------------------------------------------
# pauseForce()
#-------------------------------------------------------------------------------

    def pauseForce(self):
        self.mediaPlayer.pause()

#-------------------------------------------------------------------------------
# mediaStateChanged()
#-------------------------------------------------------------------------------

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
            self.playAction.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))
            self.playAction.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

#-------------------------------------------------------------------------------
# positionChanged()
#-------------------------------------------------------------------------------

    def positionChanged(self, position):
        self.posSlider.setValue(position)
        self.positionSlider.setValue(position)

#-------------------------------------------------------------------------------
# durationChanged()
#-------------------------------------------------------------------------------

    def durationChanged(self, duration):
        self.posSlider.setRange(0, duration)
        self.positionSlider.setRange(0, duration)

#-------------------------------------------------------------------------------
# setPosition()
#-------------------------------------------------------------------------------

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

#-------------------------------------------------------------------------------
# handleError()
#-------------------------------------------------------------------------------

    def handleError(self):
        self.playButton.setEnabled(False)
        self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
    def initUI(self):
        self.display_min = 0 # 图像显示最大值(对应灰度值为255)
        self.display_max = 1 # 图像显示最小值(对应灰度值为0)
        self.display_x = 0 # 显示图像的x坐标
        self.display_y = 0 # 显示图像的y坐标
        self.display_z = 0 # 显示图像的z坐标
        self.display_vol = -1 # 显示图像的volume序列
        self.ratio = [1, 1, 1.25] # 显示图像的比例

        self.idx_fname = -1 # 如果打开的是文件夹,则对应文件夹中实际显示的图像的序号,否则为-1
        self.fname = "" # 显示图像/文件夹的路径
        self.nii = "" # 对应图像的nii
        self.niilist = "" # 对应多个nii图像进行计算的结果
        self.nii_display = "" # 显示用的nii数据(值转换为对应的0-255)
        self.pixmap_a = ""
        self.pixmap_c = ""
        self.pixmap_s = "" # 用于在子窗口显示的单幅图像*3

        #显示图像的label
        self.label_axial = AxialLabel(self)
        self.label_axial.setStyleSheet("border: 1px solid black") # 设置label边框
        self.label_axial.setScaledContents(True) # 设置图像自适应修改大小
        self.label_axial.setMouseTracking(False) # 设置鼠标点击任意键时才捕捉鼠标位置
        self.label_axial.mousePressEvent = self.click_a # 鼠标点击时修改显示的另两个视图位置
        self.label_axial.mouseMoveEvent = self.click_a # 鼠标拖拽时修改显示的另两个试图位置
        self.label_axial.mouseDoubleClickEvent = self.double_click_a # 鼠标进行双击时显示对应slice的图像

        self.label_coronal = CoronalLabel(self) # 同上
        self.label_coronal.setStyleSheet("border: 1px solid black")
        self.label_coronal.setScaledContents(True)
        self.label_coronal.setMouseTracking(False)
        self.label_coronal.mousePressEvent = self.click_c
        self.label_coronal.mouseMoveEvent = self.click_c
        self.label_coronal.mouseDoubleClickEvent = self.double_click_c

        self.label_sagittal = SagittalLabel(self) # 同上
        self.label_sagittal.setStyleSheet("border: 1px solid black")
        self.label_sagittal.setScaledContents(True)
        self.label_sagittal.setMouseTracking(False)
        self.label_sagittal.mousePressEvent = self.click_s
        self.label_sagittal.mouseMoveEvent = self.click_s
        self.label_sagittal.mouseDoubleClickEvent = self.double_click_s

        # 显示图像信息的框架
        self.grid_info = QGridLayout() # 设置信息总框架
        # 显示图像文件路径
        if self.lan == 0:
            self.label_name_dir = QLabel("Directory:", self) # 设置显示文件路径信息条目的label
        elif self.lan == 1:
            self.label_name_dir = QLabel("文件路径:", self)
        self.label_val_dir = QLineEdit(self) # 设置显示文件路径具体信息的label
        self.label_val_dir.setText(self.fname)
        # 显示图像数据类型
        if self.lan == 0:
            self.label_name_datype = QLabel("Data Type:", self)
        elif self.lan == 1:
            self.label_name_datype = QLabel("数据类型:", self)
        self.label_val_datype = QLineEdit(self)
        self.label_val_datype.setEnabled(False) # 设置图像数据格式为不可修改
        try:
            self.label_val_datype.setText(str(self.nii.header.get("datatype").dtype))
        except AttributeError:
            pass

        # 显示图像维度信息
        if self.lan == 0:
            self.label_name_diminfo = QLabel("Dim:", self)
        elif self.lan == 1:
            self.label_name_diminfo = QLabel("图像维度:", self)
        self.label_val_diminfo = QLineEdit(self)
        self.label_val_diminfo.setEnabled(False) # 设置图像维度信息为不可修改
        try:
            self.label_val_diminfo.setText(str(self.nii.get_fdata().shape))
        except AttributeError:
            pass

        if self.lan == 0:
            self.label_name_resinfo = QLabel("Resolution", self)
        elif self.lan == 1:
            self.label_name_resinfo = QLabel("分辨率:", self)
        self.label_val_resinfo = QLineEdit(self)
        self.label_val_resinfo.setEnabled(False) # 设置图像分辨率信息为不可修改
        try:
            self.label_val_resinfo.setText("(" + str((self.nii.header.get("pixdim"))[1])+", "+str((self.nii.header.get("pixdim"))[2])+", "+str((self.nii.header.get("pixdim"))[3])+", "+str((self.nii.header.get("pixdim"))[0])+")")
        except AttributeError:
            pass

        # 显示图像显示比例
        if self.lan == 0:
            self.label_name_disratio = QLabel("Display Ratio:", self)
        elif self.lan == 1:
            self.label_name_disratio = QLabel("显示比例:", self)
        self.grid_val_disratio = QGridLayout()
        self.label_ratio_1 = QLineEdit(self)
        self.label_ratio_2 = QLineEdit(self)
        self.label_ratio_3 = QLineEdit(self)
        if self.lan == 0:
            self.but_ratio = QPushButton("RESET", self)
        elif self.lan == 1:
            self.but_ratio = QPushButton("重置", self)
        self.label_ratio_1.setText(str(self.ratio[0]))
        self.label_ratio_2.setText(str(self.ratio[1]))
        self.label_ratio_3.setText(str(self.ratio[2]))
        self.label_ratio_1.editingFinished.connect(self.modify_ratio_1) # 修改显示比例后,调节显示比例
        self.label_ratio_2.editingFinished.connect(self.modify_ratio_2)
        self.label_ratio_3.editingFinished.connect(self.modify_ratio_3)
        self.but_ratio.clicked.connect(self.reset_ratio) # 重置显示比例为默认值

        # 显示图像对应slice
        if self.lan == 0:
            self.label_name_disvol = QLabel("Display volume:", self)
        elif self.lan == 1:
            self.label_name_disvol = QLabel("显示位置:", self)
        self.grid_val_disvol = QGridLayout()
        self.spin_x = QSpinBox(self)
        self.spin_y = QSpinBox(self)
        self.spin_z = QSpinBox(self)
        # self.combox_x = QLineEdit(self)
        # self.combox_y = QLineEdit(self)
        # self.combox_z = QLineEdit(self)
        self.combox_t = QComboBox(self)
        self.combox_t.activated.connect(self.switch_vol) # 点击下拉菜单切换显示的volume
        # self.combox_x.editingFinished.connect(self.modify_slice_x) # 通过在文本框中输入坐标来完成显示切换
        # self.combox_y.editingFinished.connect(self.modify_slice_y)
        # self.combox_z.editingFinished.connect(self.modify_slice_z)
        self.spin_x.valueChanged.connect(self.modify_slice_x)
        self.spin_y.valueChanged.connect(self.modify_slice_y)
        self.spin_z.valueChanged.connect(self.modify_slice_z)
        self.spin_x.setWrapping(True)
        self.spin_y.setWrapping(True)
        self.spin_z.setWrapping(True)
        self.spin_x.setMinimum(1)
        self.spin_y.setMinimum(1)
        self.spin_z.setMinimum(1)
        self.spin_x.setMaximum(1)
        self.spin_y.setMaximum(1)
        self.spin_z.setMaximum(1)

        # 显示图像显示范围
        if self.lan == 0:
            self.label_name_disrange = QLabel("Display range:", self)
        elif self.lan == 1:
            self.label_name_disrange = QLabel("显示范围:", self)
        self.grid_val_disrange = QGridLayout()
        self.label_val_min = QLineEdit(self)
        self.label_val_max = QLineEdit(self)
        if self.lan == 0:
            self.but_range = QPushButton("RESET", self)
        elif self.lan == 1:
            self.but_range = QPushButton("重置", self)
        self.label_val_min.editingFinished.connect(self.modify_min) # 修改显示范围后,对应修改显示范围
        self.label_val_max.editingFinished.connect(self.modify_max)
        self.but_range.clicked.connect(self.reset_range) # 重置显示范围为默认值

        # 安排组件位置
        self.grid_val_disratio.addWidget(self.label_ratio_1, 0, 0)
        self.grid_val_disratio.addWidget(self.label_ratio_2, 0, 1)
        self.grid_val_disratio.addWidget(self.label_ratio_3, 0, 2)
        self.grid_val_disratio.addWidget(self.but_ratio, 0, 3)

        # self.grid_val_disvol.addWidget(self.combox_x, 0, 1)
        # self.grid_val_disvol.addWidget(self.combox_y, 0, 2)
        # self.grid_val_disvol.addWidget(self.combox_z, 0, 3)
        self.grid_val_disvol.addWidget(self.spin_x, 0, 1)
        self.grid_val_disvol.addWidget(self.spin_y, 0, 2)
        self.grid_val_disvol.addWidget(self.spin_z, 0, 3)
        self.grid_val_disvol.addWidget(self.combox_t, 0, 0)

        self.grid_val_disrange.addWidget(self.label_val_min, 0, 0)
        self.grid_val_disrange.addWidget(self.label_val_max, 0, 1)
        self.grid_val_disrange.addWidget(self.but_range, 0, 2)

        self.grid_info.addWidget(self.label_name_dir, 0, 0)
        self.grid_info.addWidget(self.label_val_dir, 0, 1)
        self.grid_info.addWidget(self.label_name_datype, 1, 0)
        self.grid_info.addWidget(self.label_val_datype, 1, 1)
        self.grid_info.addWidget(self.label_name_diminfo, 2, 0)
        self.grid_info.addWidget(self.label_val_diminfo, 2, 1)
        self.grid_info.addWidget(self.label_name_resinfo, 3, 0)
        self.grid_info.addWidget(self.label_val_resinfo, 3, 1)
        self.grid_info.addWidget(self.label_name_disratio, 4, 0)
        self.grid_info.addLayout(self.grid_val_disratio, 4, 1)
        self.grid_info.addWidget(self.label_name_disvol, 5, 0)
        self.grid_info.addLayout(self.grid_val_disvol, 5, 1)
        self.grid_info.addWidget(self.label_name_disrange, 6, 0)
        self.grid_info.addLayout(self.grid_val_disrange, 6, 1)

        # 设置菜单
        if self.lan == 0:
            openAction = QAction('&Open Nii File...', self) # 将对应功能加入菜单栏对应子项中
            openAction.setStatusTip('Select and open a Nifti file')
        elif self.lan == 1:
            openAction = QAction('打开nii文件...', self) # 将对应功能加入菜单栏对应子项中
            openAction.setStatusTip('选择并打开一个Nifti格式文件')
        openAction.setShortcut('Ctrl+O')
        openAction.triggered.connect(self.OpenFile)

        if self.lan == 0:
            saveAction = QAction('&Save...', self)
            saveAction.setStatusTip('Save current nii file in display')
        elif self.lan == 1:
            saveAction = QAction('保存文件...', self)
            saveAction.setStatusTip('将正在显示的图像保存为nii文件')
        saveAction.setShortcut('Ctrl+S')
        saveAction.triggered.connect(self.SaveFile)

        if self.lan == 0:
            exitAction = QAction('&Quit', self)
            exitAction.setStatusTip('Exit')
        elif self.lan == 1:
            exitAction = QAction('退出', self)
            exitAction.setStatusTip('退出程序')
        exitAction.setShortcut('Ctrl+Q')
        exitAction.triggered.connect(qApp.quit)

        self.bul_displaych = 1
        self.gapsizech = 4
        self.thicknessch = 2
        self.colorch = Qt.blue

        if self.lan == 0:
            crosshairMenu = QMenu('&Crosshair Settings', self)
            crosshairMenu.setStatusTip('Change settings with crosshair')
            ch_displayAction = QAction('Display Crosshair', self, checkable = True)
            ch_displayAction.setChecked(True)
            ch_displayAction.setStatusTip('Display crosshair in the image or not.')
            ch_gapsizeAction = QAction('Gap Size', self)
            ch_gapsizeAction.setStatusTip('Change gap size of crosshair')
            ch_thicknessAction = QAction('Thickness', self)
            ch_thicknessAction.setStatusTip('Change thickness of crosshair')
            ch_colorMenu = QMenu('Color', self)
            ch_colorMenu.setStatusTip('Change color of crosshair')
            ch_redAction = QWidgetAction(self)
            ch_redWidget = QLabel("Red")
            ch_redWidget.setStyleSheet("QLabel { color : red; padding: 4 4 4 30px;}QLabel:hover{background:#90c8f6;}")
            ch_redAction.setDefaultWidget(ch_redWidget)
            ch_blueAction = QWidgetAction(self)
            ch_blueWiget = QLabel("Blue")
            ch_blueWiget.setStyleSheet("QLabel {color:blue; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_blueAction.setDefaultWidget(ch_blueWiget)
            ch_grayAction = QWidgetAction(self)
            ch_grayWiget = QLabel("Gray")
            ch_grayWiget.setStyleSheet("QLabel {color:gray; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_grayAction.setDefaultWidget(ch_grayWiget)
            ch_cyanAction = QWidgetAction(self)
            ch_cyanWiget = QLabel("Cyan")
            ch_cyanWiget.setStyleSheet("QLabel {color:cyan; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_cyanAction.setDefaultWidget(ch_cyanWiget)
            ch_blackAction = QWidgetAction(self)
            ch_blackWiget = QLabel("Black")
            ch_blackWiget.setStyleSheet("QLabel {color:black; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_blackAction.setDefaultWidget(ch_blackWiget)
            ch_greenAction = QWidgetAction(self)
            ch_greenWiget = QLabel("Green")
            ch_greenWiget.setStyleSheet("QLabel {color:green; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_greenAction.setDefaultWidget(ch_greenWiget)
            ch_whiteAction = QWidgetAction(self)
            ch_whiteWiget = QLabel("White")
            ch_whiteWiget.setStyleSheet("QLabel {color:white; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_whiteAction.setDefaultWidget(ch_whiteWiget)
            ch_otherAction = QWidgetAction(self)
            ch_otherWiget = QLabel("Other...")
            ch_otherWiget.setStyleSheet("QLabel {color:black; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_otherAction.setDefaultWidget(ch_otherWiget)
        elif self.lan == 1:
            crosshairMenu = QMenu('设置十字线', self)
            crosshairMenu.setStatusTip('更改十字线相关设置')
            ch_displayAction = QAction('显示十字线', self, checkable = True)
            ch_displayAction.setChecked(True)
            ch_displayAction.setStatusTip('是否在图像上显示十字线')
            ch_gapsizeAction = QAction('空隙尺寸', self)
            ch_gapsizeAction.setStatusTip('更改十字线中心的空隙大小')
            ch_thicknessAction = QAction('线条宽度', self)
            ch_thicknessAction.setStatusTip('更改十字线线条的宽度')
            ch_colorMenu = QMenu('线条颜色', self)
            ch_colorMenu.setStatusTip('更改十字线线条的颜色')
            ch_redAction = QWidgetAction(self)
            ch_redWidget = QLabel("红色")
            ch_redWidget.setStyleSheet("QLabel { color : red; padding: 4 4 4 30px;}QLabel:hover{background:#90c8f6;}")
            ch_redAction.setDefaultWidget(ch_redWidget)
            ch_blueAction = QWidgetAction(self)
            ch_blueWiget = QLabel("蓝色")
            ch_blueWiget.setStyleSheet("QLabel {color:blue; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_blueAction.setDefaultWidget(ch_blueWiget)
            ch_grayAction = QWidgetAction(self)
            ch_grayWiget = QLabel("灰色")
            ch_grayWiget.setStyleSheet("QLabel {color:gray; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_grayAction.setDefaultWidget(ch_grayWiget)
            ch_cyanAction = QWidgetAction(self)
            ch_cyanWiget = QLabel("青色")
            ch_cyanWiget.setStyleSheet("QLabel {color:cyan; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_cyanAction.setDefaultWidget(ch_cyanWiget)
            ch_blackAction = QWidgetAction(self)
            ch_blackWiget = QLabel("黑色")
            ch_blackWiget.setStyleSheet("QLabel {color:black; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_blackAction.setDefaultWidget(ch_blackWiget)
            ch_greenAction = QWidgetAction(self)
            ch_greenWiget = QLabel("绿色")
            ch_greenWiget.setStyleSheet("QLabel {color:green; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_greenAction.setDefaultWidget(ch_greenWiget)
            ch_whiteAction = QWidgetAction(self)
            ch_whiteWiget = QLabel("白色")
            ch_whiteWiget.setStyleSheet("QLabel {color:white; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_whiteAction.setDefaultWidget(ch_whiteWiget)
            ch_otherAction = QWidgetAction(self)
            ch_otherWiget = QLabel("更多...")
            ch_otherWiget.setStyleSheet("QLabel {color:black; padding: 4 4 4 30px}QLabel:hover{background:#90c8f6;}")
            ch_otherAction.setDefaultWidget(ch_otherWiget)
        crosshairMenu.addAction(ch_displayAction)
        crosshairMenu.addAction(ch_gapsizeAction)
        crosshairMenu.addAction(ch_thicknessAction)
        crosshairMenu.addMenu(ch_colorMenu)
        ch_colorMenu.addAction(ch_blackAction)
        ch_colorMenu.addAction(ch_blueAction)
        ch_colorMenu.addAction(ch_cyanAction)
        ch_colorMenu.addAction(ch_grayAction)
        ch_colorMenu.addAction(ch_greenAction)
        ch_colorMenu.addAction(ch_redAction)
        ch_colorMenu.addAction(ch_whiteAction)
        ch_colorMenu.addAction(ch_otherAction)
        ch_displayAction.triggered.connect(self.Display_ch)
        ch_gapsizeAction.triggered.connect(self.Gap_ch)
        ch_thicknessAction.triggered.connect(self.Thickness_ch)
        ch_redAction.triggered.connect(self.Setred_ch)
        ch_blackAction.triggered.connect(self.Setblack_ch)
        ch_blueAction.triggered.connect(self.Setblue_ch)
        ch_cyanAction.triggered.connect(self.Setcyan_ch)
        ch_grayAction.triggered.connect(self.Setgray_ch)
        ch_greenAction.triggered.connect(self.Setgreen_ch)
        ch_whiteAction.triggered.connect(self.Setwhite_ch)
        ch_otherAction.triggered.connect(self.Setother_ch)

        if self.lan == 0:
            nextAction = QAction('&Next File', self)
            nextAction.setStatusTip('Display next file')
        elif self.lan == 1:
            nextAction = QAction('下一个文件', self)
            nextAction.setStatusTip('显示下一个文件')
        nextAction.setShortcut('Page Down')
        nextAction.triggered.connect(self.NextFile)

        if self.lan == 0:
            prevAction = QAction('&Previous File', self)
            prevAction.setStatusTip('Display previous file')
        elif self.lan == 1:
            prevAction = QAction('上一个文件', self)
            prevAction.setStatusTip('显示上一个文件')
        prevAction.setShortcut('Page Up')
        prevAction.triggered.connect(self.PrevFile)

        if self.lan == 0:
            SegmentAction = QAction('&Segment', self)
            SegmentAction.setStatusTip('Segment image into grey matter, white matter and csf')
        elif self.lan == 1:
            SegmentAction = QAction('分割', self)
            SegmentAction.setStatusTip('将图像分割为灰质、白质、脑脊液三部分')
        SegmentAction.setShortcut('Ctrl+E')
        SegmentAction.triggered.connect(qApp.quit)

        if self.lan == 0:
            CoregisterAction = QAction('&Coregister', self)
            CoregisterAction.setStatusTip('Coregister target image with reference image')
        elif self.lan == 1:
            CoregisterAction = QAction('配准', self)
            CoregisterAction.setStatusTip('将目标图像与参考图像进行配准')
        CoregisterAction.setShortcut('Ctrl+C')
        CoregisterAction.triggered.connect(qApp.quit)

        if self.lan == 0:
            QCAction = QAction('&Quality Analysis', self)
            QCAction.setStatusTip('Analyse Quality of Current Image')
        elif self.lan == 1:
            QCAction = QAction('质量分析', self)
            QCAction.setStatusTip('分析当前图像的质量')
        QCAction.setShortcut('Ctrl+U')
        QCAction.triggered.connect(self.QCGui)

        if self.lan == 0:
            CalcbfAction = QAction('&Calculate CBF from ASL', self)
            CalcbfAction.setStatusTip('Calculate CBF image from different ASL images or DWI image')
        elif self.lan == 1:
            CalcbfAction = QAction('通过ASL计算CBF', self)
            CalcbfAction.setStatusTip('通过不同时间的ASL像或DWI像计算CBF图像')
        CalcbfAction.setShortcut('Ctrl+A')
        CalcbfAction.triggered.connect(self.CalculateCbf)

        if self.lan == 0:
            PVEAction = QAction('&Partial Volume Correlation', self)
            PVEAction.setStatusTip('Operate Partial Volume Correlation for CBF image')
        elif self.lan == 1:
            PVEAction = QAction('局部空间校正', self)
            PVEAction.setStatusTip('对CBF图像进行局部空间校正')
        PVEAction.setShortcut('Ctrl+P')
        PVEAction.triggered.connect(self.PVECbf)


        QToolTip.setFont(QFont('SansSerif', 10)) # 没用的字体
        self.setGeometry(250, 100, 800, 650) # 修改窗口大小
        self.setWindowTitle('Toolkit_Test') #修改程序显示标题
        self.setWindowIcon(QIcon('source/images.jpg')) # 修改程序显示图标
        self.setMinimumSize(300,300) # 设置允许修改到的最小窗口大小

        # 显示状态栏,可用于显示菜单栏的备注
        self.statusBar()

        menubar = self.menuBar()
        if self.lan == 0:
            fileMenu = menubar.addMenu('&File') # 为菜单栏增加子项
        elif self.lan == 1:
            fileMenu = menubar.addMenu('文件')
        fileMenu.addAction(openAction)
        fileMenu.addAction(saveAction)
        fileMenu.addAction(exitAction)

        if self.lan == 0:
            dispMenu = menubar.addMenu('&Display')
        elif self.lan == 1:
            dispMenu = menubar.addMenu('显示')
        dispMenu.addMenu(crosshairMenu)
        dispMenu.addAction(prevAction)
        dispMenu.addAction(nextAction)

        if self.lan == 0:
            cbfMenu = menubar.addMenu('&Preprocess')
        elif self.lan == 1:
            cbfMenu = menubar.addMenu('预处理')
        cbfMenu.addAction(SegmentAction)
        cbfMenu.addAction(CoregisterAction)
        cbfMenu.addAction(QCAction)

        if self.lan == 0:
            calMenu = menubar.addMenu('&Calculation')
        elif self.lan == 1:
            calMenu = menubar.addMenu('计算')
        calMenu.addAction(CalcbfAction)
        calMenu.addAction(PVEAction)
Beispiel #17
0
class Plot(vip_base):
    """
    style_codes:
            0 : QtCore.Qt.SolidLine,
            1 : QtCore.Qt.DashDotDotLine,
            2 : QtCore.Qt.DashDotLine,
            3 : QtCore.Qt.DashLine,
            4 : QtCore.Qt.DotLine

    color_codes:
            0 : (255, 255, 255),
            1 : (255, 0  , 0  ),
            2 : (0  , 255, 0  ),
            3 : (0  , 0  , 255),
            4 : (100, 100, 100)
    """

    def __init__(self, debug=False):
        super(Plot, self).__init__()
        """
        Function init

        :param config:
        :return:
        """

        self.signals = {}

        self.__papi_debug__ = debug
        self.__buffer_size__ = None
        self.__downsampling_rate__ = 1
        self.__tbuffer__ = []

        self.__signals_have_same_length = True

        self.__append_at__ = 1
        self.__new_added_data__ = 0
        self.__input_size__ = 0
        self.__rolling_plot__ = False
        self.__colors_selected__ = []
        self.__styles_selected__ = []
        self.__width_selected__ = []

        self.__show_grid_x__ = None
        self.__show_grid_y__ = None
        self.__parameters__ = {}
        self.__update_intervall__ = None
        self.__last_time__ = None
        self.__last_plot_time__ = None
        self.__plotWidget__ = None
        self.__legend__ = None

        self.__stp_min_x = None
        self.__stp_max_x = None

        self.__stp_min_y = None
        self.__stp_max_y = None
        self.__stp_active__ = None

        self.__downsampling_rate_start__ = None;
        self.__downsampling_rate__ = None

        self.styles = {
            0: QtCore.Qt.SolidLine,
            1: QtCore.Qt.DashDotDotLine,
            2: QtCore.Qt.DashDotLine,
            3: QtCore.Qt.DashLine,
            4: QtCore.Qt.DotLine
        }

        self.colors = {
            0: (255, 255, 255),
            1: (255, 0, 0  ),
            2: (0, 255, 0  ),
            3: (0, 0, 255),
            4: (100, 100, 100)
        }

    def cb_initialize_plugin(self):
        """
        Function initiate layer 0

        :param config:
        :return:
        """
        self.config = self.pl_get_current_config_ref()


        self.startup_config = self.pl_get_current_config()

        # ---------------------------
        # Read configuration
        # ---------------------------
        int_re = re.compile(r'(\d+)')
        self.__show_legend__ = self.config['show_legend']['value'] == '1'
        self.__show_grid_x__ = self.config['x-grid']['value'] == '1'
        self.__show_grid_y__ = self.config['y-grid']['value'] == '1'
        self.__rolling_plot__ = self.config['rolling_plot']['value'] == '1'

        self.__plot_over__ = self.pl_get_config_element('plot_over')

        self.__colors_selected__ = int_re.findall(self.config['color']['value'])
        self.__styles_selected__ = int_re.findall(self.config['style']['value'])
        self.__width_selected__  = int_re.findall(self.config['width']['value'])

        self.__buffer_size__ = int(int_re.findall(self.config['buffersize']['value'])[0])

        self.__downsampling_rate__ = int(int_re.findall(self.config['downsampling_rate']['value'])[0])
        self.__downsampling_rate_start__ = 0

        self.__bgcolor = self.pl_get_config_element('bgcol')


        pos_re = re.compile(r'([0-9]+)')
        self.__legend_position__= pos_re.findall( self.pl_get_config_element('legend_position') )

        # ----------------------------
        # Set internal variables
        # ----------------------------

        self.__tbuffer__ = collections.deque([0.0] * 0, self.__buffer_size__)

        # ----------------------------
        # Set internal variables used for single timestamp plotting (stp)
        # ----------------------------

        self.__stp_min_x = 0
        self.__stp_max_x = 0

        self.__stp_min_y = 0
        self.__stp_max_y = 1

        self.__stp_active__ = False


        # --------------------------------
        # Create Layout and labels
        # --------------------------------

        self.central_widget = QWidget()
        self.central_widget.setContentsMargins(0,0,0,0)

        self.label_widget = QWidget()
        self.label_widget.setContentsMargins(0,0,0,0)

        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setContentsMargins(0,0,0,0)
        self.verticalLayout.setSpacing(0)

        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setContentsMargins(0,0,0,0)
        self.horizontalLayout.setSpacing(0)

        self.space_label = QLabel()
        self.space_label.setMargin(0)
        self.space_label.setAlignment(QtCore.Qt.AlignJustify)
        self.space_label.setStyleSheet("QLabel { background-color : black; color : grey;"
                                      "border : 0px solid black ; border-bottom-width : 5px }")

        self.time_label = QLabel()
        self.time_label.setMargin(0)
        self.time_label.setAlignment(QtCore.Qt.AlignJustify)
        self.time_label.setStyleSheet("QLabel { background-color : black; color : grey;"
                                      "border : 0px solid black ; border-bottom-width : 5px }")
        self.time_label.setMaximumWidth(55)


        self.unit_label = QLabel()
        self.unit_label.setMargin(0)
        self.unit_label.setAlignment(QtCore.Qt.AlignLeft)
        self.unit_label.setStyleSheet("QLabel { background-color : black; color : grey;"
                                      "border : 0px solid black ; border-bottom-width : 5px }")

        self.unit_label.setText('[s]')

        self.central_widget.setLayout(self.verticalLayout)
        self.label_widget.setLayout(self.horizontalLayout)

        # --------------------------------
        # Create PlotWidget
        # --------------------------------

        self.__plotWidget__ = PlotWidget()
        self.__plotWidget__.yRangeChanged.connect(self.plot_yrange_changed)
        self.__plotWidget__.setWindowTitle('PlotPerformanceTitle')

        self.__plotWidget__.showGrid(x=self.__show_grid_x__, y=self.__show_grid_y__)
        self.__plotWidget__.getPlotItem().getViewBox().disableAutoRange()
        self.__plotWidget__.getPlotItem().getViewBox().setYRange(0,6)

        self.__plotWidget__.getPlotItem().setDownsampling(auto=True)

        # ------------------------------
        # Add Widget to Layout
        # ------------------------------
        self.horizontalLayout.addWidget(self.space_label)
        self.horizontalLayout.addWidget(self.time_label)
        self.horizontalLayout.addWidget(self.unit_label)

        self.verticalLayout.addWidget(self.__plotWidget__)
        self.verticalLayout.addWidget(self.label_widget)


        if not self.__papi_debug__:
#            self.pl_set_widget_for_internal_usage(self.__plotWidget__)
            self.pl_set_widget_for_internal_usage(self.central_widget)

        self.__plotWidget__.getPlotItem().getViewBox().enableAutoRange(axis=pg.ViewBox.YAxis, enable=False)
        self.__plotWidget__.getPlotItem().getViewBox().enableAutoRange(axis=pg.ViewBox.XAxis, enable=False)

        self.__plotWidget__.getPlotItem().getViewBox().setMouseEnabled(x=False, y=True)

        # ---------------------------
        # Create Parameters
        # ---------------------------

        self.__parameters__['x-grid'] = \
            DParameter('x-grid', self.config['x-grid']['value'], Regex='^(1|0){1}$')
        self.__parameters__['y-grid'] = \
            DParameter('y-grid', self.config['y-grid']['value'], Regex='^(1|0){1}$')

        self.__parameters__['color'] = \
            DParameter('color', self.config['color']['value'], Regex='^\[(\s*\d\s*)+\]')
        self.__parameters__['style'] = \
            DParameter('style', self.config['style']['value'], Regex='^\[(\s*\d\s*)+\]')
        self.__parameters__['width'] = \
            DParameter('width', self.config['width']['value'], Regex='^\[(\s*\d\s*)+\]')

        self.__parameters__['rolling'] = \
            DParameter('rolling', self.config['rolling_plot']['value'], Regex='^(1|0){1}')

        self.__parameters__['downsampling_rate'] = \
            DParameter('downsampling_rate', self.__downsampling_rate__, Regex='^\d+$')
        self.__parameters__['buffersize'] = \
            DParameter('buffersize', self.__buffer_size__, Regex='^\d+$')

        self.__parameters__['yRange'] = \
            DParameter('yRange', self.config['yRange']['value'],  Regex='^\[(\d+\.\d+)\s+(\d+\.\d+)\]$')

        self.__parameters__['show_legend'] = \
            DParameter('show_legend', self.config['show_legend']['value'],  Regex=pc.REGEX_BOOL_BIN)

        self.__parameters__['legend_position'] = \
            DParameter('legend_position', self.pl_get_config_element('legend_position'), Regex='\(([0-9]+),([0-9]+)\)')
        self.__parameters__['legend_position'].connect(self.parameter_callback_legend_position)

        if not self.__papi_debug__:
            self.pl_send_new_parameter_list(list(self.__parameters__.values()))

        # ---------------------------
        # Create Legend
        # ---------------------------

        if self.__show_legend__:
            self.__legend__ = self.__plotWidget__.getPlotItem().addLegend()
        else:
            self.__legend__ = None


        self.__last_time__ = current_milli_time()

        self.__update_intervall__ = 20  # in milliseconds
        self.__last_plot_time__   = 0

        self.setup_context_menu()
        self.__plotWidget__.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.__plotWidget__.customContextMenuRequested.connect(self.showContextMenu)

        self.use_range_for_y(self.config['yRange']['value'])

        # ----------------------------
        # Initiate for default plotting
        # ----------------------------
        color_rgb = self.__bgcolor[1:-1]
        color_rgb = color_rgb.split(',')
        self.__plotWidget__.setBackground([int(color_rgb[0]),int(color_rgb[1]),int(color_rgb[2])])

        self.initiate_update_plot()
        return True

    def cb_pause(self):
        """
        Function pause

        :return:
        """
        self.__plotWidget__.getPlotItem().getViewBox().setMouseEnabled(x=True, y=True)

    def cb_resume(self):
        """
        Function resume

        :return:
        """
        self.__plotWidget__.getPlotItem().getViewBox().setMouseEnabled(x=False, y=True)

    def cb_execute(self, Data=None, block_name = None, plugin_uname = None):
        """
        Function cb_execute

        :param Data:
        :param block_name:
        :return:
        """

        t = Data[self.__plot_over__]

        self.__input_size__ = len(t)

        self.__signals_have_same_length = True

        now = pg.ptime.time()

        for key in Data:
            if key not in [pc.CORE_TIME_SIGNAL, self.__plot_over__]:
                y = Data[key]
                if key in self.signals:
                    if self.__downsampling_rate_start__ < len(y):
                        ds_y = y[self.__downsampling_rate_start__::self.__downsampling_rate__]

                        self.signals[key].add_data(ds_y)

                        self.__signals_have_same_length &= (len(y) == len(t))

        if self.__downsampling_rate_start__ >= len(t):
            self.__downsampling_rate_start__ -= len(t)
        else:
            ds_t = t[self.__downsampling_rate_start__::self.__downsampling_rate__]
            self.__downsampling_rate_start__ += self.__downsampling_rate__ - len(ds_t)
            self.__tbuffer__.extend(ds_t)

        self.__new_added_data__ += len(t)

        self.rolling_Checkbox.setDisabled(self.__stp_active__)

        if self.__input_size__ > 1 or self.__signals_have_same_length:

            if self.__stp_active__:
                self.initiate_update_plot()

            if current_milli_time() - self.__last_time__ > self.__update_intervall__ - self.__last_plot_time__:
                self.__last_time__ = current_milli_time()
                self.update_plot()
                self.__last_time__ = current_milli_time()
                self.__new_added_data__ = 0
        else:

            if not self.__stp_active__ :
                self.initiate_update_plot_single_timestamp()

            if current_milli_time() - self.__last_time__ > self.__update_intervall__ - self.__last_plot_time__:
                self.__last_time__ = current_milli_time()

                self.update_plot_single_timestamp(Data)

                self.__last_time__ = current_milli_time()
                self.__new_added_data__ = 0

        # print("Plot time: %0.5f sec" % (self.__last_plot_time__) )

    def cb_set_parameter(self, name, value):
        """
        Function set parameters

        :param name:
        :param value:
        :return:
        """
        if name == 'x-grid':
            self.config['x-grid']['value'] = value
            self.__plotWidget__.showGrid(x=value == '1')
            self.xGrid_Checkbox.stateChanged.disconnect()
            self.xGrid_Checkbox.setChecked(value=='1')
            self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)

        if name == 'y-grid':
            self.config['y-grid']['value'] = value
            self.__plotWidget__.showGrid(y=value == '1')
            self.yGrid_Checkbox.stateChanged.disconnect()
            self.yGrid_Checkbox.setChecked(value=='1')
            self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)

        if name == 'downsampling_rate':
            self.config['downsampling_rate']['value'] = value
            self.__downsampling_rate__ = int(value)
            self.__new_added_data__ = 0
            self.update_downsampling_rate()

        if name == 'rolling':
            self.clear()
            self.config['rolling_plot']['value'] = value
            self.update_rolling_plot()

        if name == 'color':
            self.clear()
            self.config['color']['value'] = value
            int_re = re.compile(r'(\d+)')
            self.__colors_selected__ = int_re.findall(self.config['color']['value'])
            self.update_pens()
            self.update_legend()

        if name == 'style':
            self.clear()
            self.config['style']['value'] = value
            int_re = re.compile(r'(\d+)')
            self.__styles_selected__ = int_re.findall(self.config['style']['value'])
            self.update_pens()
            self.update_legend()

        if name == 'width':
            self.clear()
            self.config['width']['value'] = value
            int_re = re.compile(r'(\d+)')
            self.__width_selected__ = int_re.findall(self.config['width']['value'])
            self.update_pens()
            self.update_legend()

        if name == 'show_legend':
            self.config['show_legend']['value'] = value
            if value == '0':
                if self.__legend__ is not None:
                    self.__legend__.scene().removeItem(self.__legend__)
                    del self.__legend__
                    self.__legend__ = None
            if value == '1':
                self.update_legend()

        if name == 'buffersize':
            self.config['buffersize']['value'] = value
            self.update_buffer_size(value)

        if name == 'yRange':
            self.config['yRange']['value'] = value
            self.use_range_for_y(value)

        # if name == 'legend_position':
        #     self.pl_set_config_element('legend_position',value)
        #     pos_re = re.compile(r'([0-9]+)')
        #     self.__legend_position__ = pos_re.findall(value)
        #     self.update_legend()
        #     print('POS:', self.__parameters__['legend_position'].value)

    def update_pens(self):
        """
        Function update pens

        :return:
        """

        for signal_name in self.signals.keys():
            signal_id = self.signals[signal_name].id
            new_pen = self.get_pen(signal_id)
            other_pen = self.get_pen(signal_id)

            o_color = other_pen.color()
            o_color.setAlpha(100)
            other_pen.setColor(o_color)

            self.signals[signal_name].pen = new_pen
            self.signals[signal_name].other_pen = other_pen

    def update_plot(self):
        """
        Function update_plot

        :return:
        """

        if len(self.__tbuffer__) == 0:
            return

        if not self.__rolling_plot__:
            tdata = list(self.__tbuffer__)

        if self.__rolling_plot__:
            tdata = list(range(0, len(self.__tbuffer__)))
            self.__append_at__ += self.signals[list(self.signals.keys())[0]].get_new_added_since_last_drawing()
            self.__append_at__ %= len(tdata)
            tdata = np.roll(tdata, -int(self.__append_at__))

        now = pg.ptime.time()

        for signal_name in self.signals:

            # get all no more needed graphic items
            graphics = self.signals[signal_name].get_old_graphics()
            for graphic in graphics:
                self.__plotWidget__.removeItem(graphic)

            # Create new new graphic items
            self.signals[signal_name].create_graphics(tdata)

            # Get new created graphic item and paint them
            graphics = self.signals[signal_name].get_graphics()
            for graphic in graphics:
                self.__plotWidget__.addItem(graphic)

        self.__last_plot_time__ = pg.ptime.time()-now

        if self.__rolling_plot__:
            self.__plotWidget__.getPlotItem().getViewBox().setXRange(0, len(tdata)-1)
            self.time_label.setNum(self.__tbuffer__[-1])
        else:
            self.__plotWidget__.getPlotItem().getViewBox().setXRange(tdata[0], tdata[-1])

        # if self.__papi_debug__:
        #     print("Plot time: %0.5f sec" % (self.__last_plot_time__) )

    def initiate_update_plot(self):
        """
        To all needed changes to use default plotting

        :return:
        """
        self.__stp_active__ = False

        if self.__rolling_plot__:
            self.time_label.setHidden(False)
        else:
            self.time_label.setHidden(True)

        pass

    def initiate_update_plot_single_timestamp(self):
        """
        To all needed changes to use single timestamp plotting

        :return:
        """

        self.__stp_active__ = True

        self.time_label.setHidden(False)

    def update_plot_single_timestamp(self, data):
        """
        Function update_plot_single_timestamp

        :return:
        """

        self.__plotWidget__.clear()

        cur_max_y = 0
        cur_min_y = 1000

        for signal_name in data:
            if signal_name not in [pc.CORE_TIME_SIGNAL, self.__plot_over__]:
                signal_data = data[signal_name]
                if signal_name in self.signals:

                    tdata = np.linspace(1, len(signal_data), len(signal_data))
                    if len(data[self.__plot_over__]) == len(signal_data):
                        plot_axis = data[self.__plot_over__]
                        tdata = np.linspace(1, plot_axis[-1], len(plot_axis))

                    plot_item = self.signals[signal_name]

                    if len(tdata) == 1:
                        graphic = GraphicItem(np.array([self.__stp_min_x, self.__stp_max_x]), np.array([signal_data[0], signal_data[0]]), 0, pen=plot_item.pen)
                    else:
                        graphic = GraphicItem(np.array(tdata), np.array(signal_data), 0, pen=plot_item.pen)

                    self.__plotWidget__.addItem(graphic)

                    self.__stp_max_x = max(self.__stp_max_x, max(tdata))
                    self.__stp_min_x = min(self.__stp_min_x, min(tdata))

                    cur_max_y = max(cur_max_y, max(signal_data))
                    cur_min_y = min(cur_min_y, min(signal_data))

        self.__stp_max_y = cur_max_y
        self.__stp_min_y = cur_min_y

        self.__plotWidget__.getPlotItem().getViewBox().setXRange(self.__stp_min_x, self.__stp_max_x)

        self.time_label.setNum(data[CORE_TIME_SIGNAL][0])

    def update_buffer_size(self, new_size):
        """
        Function set buffer size

        :param new_size:
        :return:
        """

        self.__buffer_size__ = int(new_size)

        start_size = len(self.__tbuffer__)

        for signal_name in self.signals:
            self.__tbuffer__ = collections.deque([0.0] * start_size, self.__buffer_size__)  # COLLECTION

            plot_item = self.signals[signal_name]
            plot_item.max_elements = self.__buffer_size__
            plot_item.clear()
            self.__plotWidget__.clear()

        self.update_rolling_plot()

        self.__new_added_data__ = 0

    def cb_plugin_meta_updated(self):
        """
        This function is called whenever meta information are changed.
        This enables the plot to handle more than one input for plotting.

        :return:
        """
        dp_info = self.pl_get_dplugin_info()
        subscriptions = dp_info.get_subscribtions()
        changes = False
        current_signals = {}
        index = 0

        for dpluginsub_id in subscriptions:
            for dblock_name in subscriptions[dpluginsub_id]:

                # get subscription for dblock
                subscription = subscriptions[dpluginsub_id][dblock_name]

                for signal_name in subscription.get_signals():

                    if signal_name not in [pc.CORE_TIME_SIGNAL, self.__plot_over__]:

                        signal = subscription.get_dblock().get_signal_by_uname(signal_name)
                        current_signals[signal_name] = {}
                        current_signals[signal_name]['signal'] = signal
                        current_signals[signal_name]['index'] = index
                        index += 1

        # ----------------------------
        # Add new subscribed signals
        # ----------------------------
        for signal_name in sorted(current_signals.keys()):
            if signal_name not in [pc.CORE_TIME_SIGNAL, self.__plot_over__]:
                if signal_name not in self.signals:
                    signal = current_signals[signal_name]['signal']
                    self.add_plot_item(signal, current_signals[signal_name]['index'])
                    changes = True

        # -------------------------------
        # Remove unsubscribed signals
        # -------------------------------
        for signal_name in self.signals.copy():
            if signal_name not in current_signals:
                if self.__legend__ is not None:
                    self.remove_plot_item(signal_name)
                changes = True


        if changes:
            self.update_pens()
            self.update_signals()
            self.update_legend()
            self.update_rolling_plot()
            self.update_downsampling_rate()
            self.update_parameters()
        else:
            self.update_signals()
            #self.update_legend()

    def add_plot_item(self, signal, signal_id):
        """
        Create a new plot item object for a given signal and internal id

        :param signal: DSignal object
        :param signal_id: plot internal signal id
        :return:
        """

        signal_name = signal.uname

        if signal_name not in self.signals:
            self.signals[signal_name] = {}

            plot_item = PlotItem(signal, signal_id, self.__buffer_size__)
            plot_item.set_downsampling_rate(self.__downsampling_rate__)

            self.signals[signal_name] = plot_item

    def remove_plot_item(self, signal_name):
        """
        Remove the plot item object for a given signal_name.

        :param signal_name:
        :return:
        """

        if signal_name in self.signals:
            plot_item = self.signals[signal_name]

            # Remove all graphic objects

            for graphic in plot_item.graphics:
                self.__plotWidget__.removeItem(graphic)

            # Remove from Legend
            self.__legend__.removeItem(plot_item.signal_name)
            del self.signals[signal_name]

    def get_pen(self, index):
        """
        Function get pen

        :param index:
        :return:
        """
        index = int(index)

        style_index = index % len(self.__styles_selected__)
        style_code = int(self.__styles_selected__[style_index])

        width_index = index % len(self.__width_selected__)
        width_code = int(self.__width_selected__[width_index])

        color_index = index % len(self.__colors_selected__)
        color_code = int(self.__colors_selected__[color_index])

        if style_code in self.styles:
            style = self.styles[style_code]
        else:
            style = self.styles[0]

        if color_code in self.colors:
            color = self.colors[color_code]
        else:
            color = self.colors[0]

        if width_code < 0:
            width_code = 0

        return pg.mkPen(color=color, style=style, width=width_code)

    def update_rolling_plot(self):
        """
        Used to update the rolling plot by resolving all dependencies.
        The configuration for the rolling plot depends on the current value in self.config['rolling_plot']['value']

        :return:
        """

        value = self.config['rolling_plot']['value']

        self.__rolling_plot__ = int(float(self.config['rolling_plot']['value'])) == int('1')

        self.rolling_Checkbox.stateChanged.disconnect()
        self.rolling_Checkbox.setChecked(value == '1')
        self.rolling_Checkbox.stateChanged.connect(self.contextMenu_rolling_toogled)

        self.clear()


        for signal_name in self.signals:
            self.signals[signal_name].rolling_plot = self.__rolling_plot__

        self.initiate_update_plot()


    def update_parameters(self):

        parameter_style = self.__parameters__['style']
        parameter_width = self.__parameters__['width']
        parameter_color = self.__parameters__['color']

        int_re = re.compile(r'(\d+)')

        # Styles
        current_styles = int_re.findall(parameter_style.value)
        original_style = int_re.findall(self.startup_config['style']['value'])

        # Width
        current_width = int_re.findall(parameter_width.value)
        original_width = int_re.findall(self.startup_config['width']['value'])

        # Color
        current_color = int_re.findall(parameter_color.value)
        original_color = int_re.findall(self.startup_config['color']['value'])

        min_len = min(len(current_styles), len(current_width), len(current_color))

        if len(self.signals) < min_len:
            style_new = current_styles[0:len(self.signals)]
            width_new = current_width[0:len(self.signals)]
            color_new = current_color[0:len(self.signals)]
        else:
            style_new = current_styles
            width_new = current_width
            color_new = current_color

            if len(self.signals) < len(original_style):
                style_new.extend(original_style[min_len:min_len+len(self.signals)-1])
                width_new.extend(original_width[min_len:min_len+len(self.signals)-1])
                color_new.extend(original_color[min_len:min_len+len(self.signals)-1])

            else:
                style_new.extend([0] * (len(self.signals)-len(original_style)))
                width_new.extend([0] * (len(self.signals)-len(original_style)))
                color_new.extend([0] * (len(self.signals)-len(original_style)))

        style_new = '[' + ' '.join(str(x) for x in style_new) + ']'
        width_new = '[' + ' '.join(str(x) for x in width_new) + ']'
        color_new = '[' + ' '.join(str(x) for x in color_new) + ']'

        parameter_style.value = str(style_new)
        parameter_width.value = str(width_new)
        parameter_color.value = str(color_new)

        self.control_api.do_set_parameter(self.__id__, parameter_style.name, parameter_style.value)
        self.control_api.do_set_parameter(self.__id__, parameter_width.name, parameter_width.value)
        self.control_api.do_set_parameter(self.__id__, parameter_color.name, parameter_color.value)

    def use_range_for_x(self, value):
        """

        :param value:
        :return:
        """
        reg = re.compile(r'(\d+\.\d+)')
        range = reg.findall(value)
        if len(range) == 2:
            #self.xRange_minEdit.setText(range[0])
            #self.xRange_maxEdit.setText(range[1])
            self.__plotWidget__.getPlotItem().getViewBox().setXRange(float(range[0]),float(range[1]))

    def use_range_for_y(self, value):
        """

        :param value:
        :return:
        """
        reg = re.compile(r'([-]{0,1}\d+\.\d+)')
        range = reg.findall(value)



        if len(range) == 2:

            self.yRange_minEdit.setText(range[0])
            self.yRange_maxEdit.setText(range[1])
            self.__plotWidget__.getPlotItem().getViewBox().setYRange(float(range[0]), float(range[1]))

    def setup_context_menu(self):
        """

        :return:
        """

        self.custMenu = QMenu("Options")
        self.axesMenu = QMenu('Y-Axis')
        self.gridMenu = QMenu('Grid')

        ##### Y-Range Actions
        self.yRange_Widget = QWidget()
        self.yRange_Layout = QVBoxLayout(self.yRange_Widget)
        self.yRange_Layout.setContentsMargins(2, 2, 2, 2)
        self.yRange_Layout.setSpacing(1)

        self.yAutoRangeButton = QPushButton()
        self.yAutoRangeButton.clicked.connect(self.contextMenu_yAutoRangeButton_clicked)
        self.yAutoRangeButton.setText('Use autorange')
        self.yRange_Layout.addWidget(self.yAutoRangeButton)

        ##### Y Line Edits
        # Layout
        self.yRange_EditWidget = QWidget()
        self.yRange_EditLayout = QHBoxLayout(self.yRange_EditWidget)
        self.yRange_EditLayout.setContentsMargins(2, 2, 2, 2)
        self.yRange_EditLayout.setSpacing(1)

        # get old values;
        reg = re.compile(r'(\d+\.\d+)')
        range = reg.findall(self.config['yRange']['value'])
        if len(range) == 2:
            y_min = range[0]
            y_max = range[1]
        else:
            y_min = '0.0'
            y_max = '1.0'

        rx = QRegExp(r'([-]{0,1}\d+\.\d+)')
        validator = QRegExpValidator(rx, self.__plotWidget__)

        # Min
        self.yRange_minEdit = QLineEdit()
        self.yRange_minEdit.setFixedWidth(80)
        self.yRange_minEdit.setText(y_min)
        self.yRange_minEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_minEdit.setValidator(validator)
        # Max
        self.yRange_maxEdit = QLineEdit()
        self.yRange_maxEdit.setFixedWidth(80)
        self.yRange_maxEdit.setText(y_max)
        self.yRange_maxEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_maxEdit.setValidator(validator)
        # addTo Layout
        self.yRange_EditLayout.addWidget(self.yRange_minEdit)
        self.yRange_EditLayout.addWidget(QLabel('<'))
        self.yRange_EditLayout.addWidget(self.yRange_maxEdit)
        self.yRange_Layout.addWidget(self.yRange_EditWidget)

        # build Action
        self.yRange_Action = QWidgetAction(self.__plotWidget__)
        self.yRange_Action.setDefaultWidget(self.yRange_Widget)

        ##### Rolling Plot
        self.rolling_Checkbox = QCheckBox()
        self.rolling_Checkbox.setText('Rolling plot')
        self.rolling_Checkbox.setChecked(self.config['rolling_plot']['value'] == '1')
        self.rolling_Checkbox.stateChanged.connect(self.contextMenu_rolling_toogled)
        self.rolling_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.rolling_Checkbox_Action.setDefaultWidget(self.rolling_Checkbox)
        if self.__stp_active__:
            self.rolling_Checkbox.setDisabled(True)

        # show legend

        self.legend_Checkbox = QCheckBox()
        self.legend_Checkbox.setText('Show legend')
        self.legend_Checkbox.setChecked(self.config['show_legend']['value'] == '1')
        self.legend_Checkbox.stateChanged.connect(self.contextMenu_legend_toogled)
        self.legend_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.legend_Checkbox_Action.setDefaultWidget(self.legend_Checkbox)

        ##### Build axes menu
        #self.axesMenu.addAction(self.xRange_Action)
        self.axesMenu.addSeparator().setText("Y-Range")
        self.axesMenu.addAction(self.yRange_Action)

        # Grid Menu:
        # -----------------------------------------------------------
        # Y-Grid checkbox
        self.xGrid_Checkbox = QCheckBox()
        self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)
        self.xGrid_Checkbox.setText('X-Grid')
        self.xGrid_Action = QWidgetAction(self.__plotWidget__)
        self.xGrid_Action.setDefaultWidget(self.xGrid_Checkbox)
        self.gridMenu.addAction(self.xGrid_Action)
        # Check config for startup  state
        if self.__show_grid_x__:
            self.xGrid_Checkbox.setChecked(True)

        # X-Grid checkbox
        self.yGrid_Checkbox = QCheckBox()
        self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)
        self.yGrid_Checkbox.setText('Y-Grid')
        self.yGrid_Action = QWidgetAction(self.__plotWidget__)
        self.yGrid_Action.setDefaultWidget(self.yGrid_Checkbox)
        self.gridMenu.addAction(self.yGrid_Action)
        # Check config for startup  state
        if self.__show_grid_y__:
            self.yGrid_Checkbox.setChecked(True)

        # add Menus
        self.custMenu.addMenu(self.axesMenu)
        self.custMenu.addMenu(self.gridMenu)
        self.custMenu.addSeparator().setText("Rolling Plot")
        self.custMenu.addAction(self.rolling_Checkbox_Action)
        self.custMenu.addAction(self.legend_Checkbox_Action)
        self.__plotWidget__.getPlotItem().getViewBox().menu.clear()

        if not self.__papi_debug__:
            self.__plotWidget__.getPlotItem().ctrlMenu = [self.pl_create_control_context_menu(), self.custMenu]

    def showContextMenu(self):
        self.setup_context_menu()


    def contextMenu_yAutoRangeButton_clicked(self):
        mi = None
        ma = None

        if self.__stp_active__:
            mi = self.__stp_min_y
            ma = self.__stp_max_y
        else:
            for sig in self.signals:
                graphics = self.signals[sig].graphics
                buf = []
                for graphic in graphics:
                    buf.extend(graphic.y)

                ma_buf = max(buf)
                mi_buf = min(buf)
                if ma is not None:
                    if ma_buf > ma:
                        ma = ma_buf
                else:
                    ma = ma_buf

                if mi is not None:
                    if mi_buf < mi:
                        mi = mi_buf
                else:
                    mi = mi_buf

        ma = str(float(ma))
        mi = str(float(mi))

        self.yRange_maxEdit.setText(ma)
        self.yRange_minEdit.setText(mi)
        self.control_api.do_set_parameter(self.__id__, 'yRange', '[' +mi + ' ' + ma + ']')

    def contextMenu_rolling_toogled(self):
        if self.rolling_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'rolling', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'rolling', '0')

    def contextMenu_legend_toogled(self):
        if self.legend_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'show_legend', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'show_legend', '0')

    def contextMenu_xGrid_toogle(self):
        if self.xGrid_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'x-grid', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'x-grid', '0')

    def contextMenu_yGrid_toogle(self):
        if self.yGrid_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'y-grid', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'y-grid', '0')

    def contextMenu_yRange_toogle(self):
        mi = self.yRange_minEdit.text()
        ma = self.yRange_maxEdit.text()
        if float(mi) < float(ma):
            self.control_api.do_set_parameter(self.__id__, 'yRange', '[' + mi + ' ' + ma + ']')

    def update_signals(self):
        """
        Used to update the signals as they are described in self.dplugin_info

        :return:
        """
        dp_info = self.pl_get_dplugin_info()
        subscriptions = dp_info.get_subscribtions()

        for dpluginsub_id in subscriptions:
            for dblock_name in subscriptions[dpluginsub_id]:

                # get subscription for dblock
                subscription = subscriptions[dpluginsub_id][dblock_name]

                for signal_name in subscription.get_signals():
                    if signal_name not in [pc.CORE_TIME_SIGNAL, self.__plot_over__]:
                        signal = subscription.get_dblock().get_signal_by_uname(signal_name)

                        self.signals[signal_name].update_signal(signal)

    def update_legend(self):
        """
        Used to update the legend.

        :return:
        """

        if not self.__show_legend__:
            return

        if self.__legend__ is not None:
            self.__legend__.scene().removeItem(self.__legend__)
            del self.__legend__
            self.__legend__ = None

        self.__legend__ = self.__plotWidget__.getPlotItem().addLegend()

        if not self.__papi_debug__:
            self.update_signals()

        for signal_name in sorted(self.signals.keys()):

            graphic = self.signals[signal_name].get_legend_item()

            if graphic is not None:
                signal = self.signals[signal_name].signal
                legend_name = signal.dname

                self.__legend__.addItem(graphic, legend_name)

        self.__legend__.setPos(int(self.__legend_position__[0]),int(self.__legend_position__[1]))

    def update_downsampling_rate(self):
        """
        Used to update the downsampling rate by resolving all dependencies.
        The new downsampling rate is taken by using the private attribute __downsampling_rate__.

        :return:
        """
        rate = self.__downsampling_rate__

        self.__downsampling_rate_start__ = 0
        self.__downsampling_rate__ = rate

        for signal_name in self.signals:
            self.signals[signal_name].set_downsampling_rate(rate)

    def plot_yrange_changed(self):

        viewbox = self.__plotWidget__.getPlotItem().getViewBox()
        [xRange, yRange] = viewbox.viewRange()
        self.control_api.do_update_parameter(self.__id__, 'yRange', '[' + str(yRange[0]) + ' ' + str(yRange[1]) + ']')

        self.config['yRange']['value'] = '[' + str(yRange[0]) + ' ' + str(yRange[1]) + ']'

    def cb_quit(self):
        """
        Function quit plugin

        :return:
        """
        print('PlotPerformance: will quit')

    def debug_papi(self):
        config = self.get_cb_plugin_configuration()

        config['yRange'] =  {
            'value': '[0.0 50.0]',
            'regex': '(\d+\.\d+)',
            'advanced': '1',
            'display_text': 'y: range'
        }
        config['buffersize'] =  {
            'value': '1000',
            'regex': '(\d+\.\d+)',
            'advanced': '1',
            'display_text': 'y: range'
        }
        config['downsampling_rate'] =  {
            'value': '10',
            'regex': '(\d+\.\d+)',
            'advanced': '1',
            'display_text': 'y: range'
        }

        self.config = config
        self.__id__ = 0
        self.cb_initialize_plugin(config)

        signal_1 = DSignal('signal_1')
        signal_2 = DSignal('signal_2')
        signal_3 = DSignal('signal_3')
        signal_4 = DSignal('signal_4')
        signal_5 = DSignal('signal_5')

        self.add_plot_item(signal_1, 1)
        self.add_plot_item(signal_2, 2)
        self.add_plot_item(signal_3, 3)
        self.add_plot_item(signal_4, 4)
        self.add_plot_item(signal_5, 5)

        self.update_pens()
        self.update_legend()

        pass

    def cb_get_plugin_configuration(self):
        """
        Function get plugin configuration

        :return {}:
        """
        config = {
        'x-grid': {
            'value': "0",
            'regex': '^(1|0)$',
            'type': 'bool',
            'display_text': 'Grid-X',
            'advanced': 'Style'
        }, 'y-grid': {
            'value': "0",
            'regex': '^(1|0)$',
            'type': 'bool',
            'display_text': 'Grid-Y',
            'advanced': 'Style'
        }, 'color': {
            'value': "[0 1 2 3 4]",
            'regex': '^\[(\s*\d\s*)+\]',
            'advanced': 'Style',
            'display_text': 'Color'
        }, 'style': {
            'value': "[0 0 0 0 0]",
            'regex': '^\[(\s*\d\s*)+\]',
            'advanced': 'Style',
            'display_text': 'Style'
        }, 'width': {
            'value': "[0 0 0 0 0]",
            'regex': '^\[(\s*\d\s*)+\]',
            'advanced': 'Style',
            'display_text': 'Width'
        }, 'buffersize': {
            'value': "100",
            'regex': '^(\d+)$',
            'advanced': 'Data',
            'display_text': 'Buffersize'
        }, 'downsampling_rate': {
            'value': "1",
            'regex': '(\d+)',
            'advanced': 'Data'
        }, 'rolling_plot': {
            'value': '0',
            'regex': '^(1|0)$',
            'type': 'bool',
            'advanced': 'Data',
            'display_text': 'Rolling Plot'
        }, 'yRange': {
            'value': '[0.0 1.0]',
            'regex': '^\[(\d+\.\d+)\s+(\d+\.\d+)\]$',
            'advanced': 'Data',
            'display_text': 'y: range'
        },  'show_legend' : {
            'value' : '1',
            'regex' : pc.REGEX_BOOL_BIN,
            'display_text' : 'Enable/Disable legend',
            'type' : pc.CFG_TYPE_BOOL,
            'advanced': 'Style'
        },  'legend_position' : {
            'value' : '(10,10)',
            'regex': '\(([0-9]+),([0-9]+)\)',
            'tooltip' : 'Set (X,Y) position of legend',
            'display_text' : 'Legend position',
            'advanced': 'Style'
        },
            'bgcol':{
            'value':'(0,0,0)',
            'type': pc.CFG_TYPE_COLOR,
            'advanced': 'Style'
        },
            'plot_over' : {
            'advanced' : 'Data',
            'value' : pc.CORE_TIME_SIGNAL,
            'display_text' : 'Plot signals over this x-axis'
            }
        }
        # http://www.regexr.com/
        return config

    def clear(self):
        """

        :return:
        """
        self.__plotWidget__.clear()
        self.__tbuffer__.clear()

        for signal_name in self.signals:
            self.signals[signal_name].clear()

    def parameter_callback_legend_position(self, value):
        self.pl_set_config_element('legend_position',value)
        pos_re = re.compile(r'([0-9]+)')
        self.__legend_position__ = pos_re.findall(value)
        self.update_legend()
Beispiel #18
0
    def setup_context_menu(self):
        """

        :return:
        """

        self.custMenu = QMenu("Options")
        self.axesMenu = QMenu('Y-Axis')
        self.gridMenu = QMenu('Grid')

        ##### Y-Range Actions
        self.yRange_Widget = QWidget()
        self.yRange_Layout = QVBoxLayout(self.yRange_Widget)
        self.yRange_Layout.setContentsMargins(2, 2, 2, 2)
        self.yRange_Layout.setSpacing(1)

        self.yAutoRangeButton = QPushButton()
        self.yAutoRangeButton.clicked.connect(self.contextMenu_yAutoRangeButton_clicked)
        self.yAutoRangeButton.setText('Use autorange')
        self.yRange_Layout.addWidget(self.yAutoRangeButton)

        ##### Y Line Edits
        # Layout
        self.yRange_EditWidget = QWidget()
        self.yRange_EditLayout = QHBoxLayout(self.yRange_EditWidget)
        self.yRange_EditLayout.setContentsMargins(2, 2, 2, 2)
        self.yRange_EditLayout.setSpacing(1)

        # get old values;
        reg = re.compile(r'(\d+\.\d+)')
        range = reg.findall(self.config['yRange']['value'])
        if len(range) == 2:
            y_min = range[0]
            y_max = range[1]
        else:
            y_min = '0.0'
            y_max = '1.0'

        rx = QRegExp(r'([-]{0,1}\d+\.\d+)')
        validator = QRegExpValidator(rx, self.__plotWidget__)

        # Min
        self.yRange_minEdit = QLineEdit()
        self.yRange_minEdit.setFixedWidth(80)
        self.yRange_minEdit.setText(y_min)
        self.yRange_minEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_minEdit.setValidator(validator)
        # Max
        self.yRange_maxEdit = QLineEdit()
        self.yRange_maxEdit.setFixedWidth(80)
        self.yRange_maxEdit.setText(y_max)
        self.yRange_maxEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_maxEdit.setValidator(validator)
        # addTo Layout
        self.yRange_EditLayout.addWidget(self.yRange_minEdit)
        self.yRange_EditLayout.addWidget(QLabel('<'))
        self.yRange_EditLayout.addWidget(self.yRange_maxEdit)
        self.yRange_Layout.addWidget(self.yRange_EditWidget)

        # build Action
        self.yRange_Action = QWidgetAction(self.__plotWidget__)
        self.yRange_Action.setDefaultWidget(self.yRange_Widget)

        ##### Rolling Plot
        self.rolling_Checkbox = QCheckBox()
        self.rolling_Checkbox.setText('Rolling plot')
        self.rolling_Checkbox.setChecked(self.config['rolling_plot']['value'] == '1')
        self.rolling_Checkbox.stateChanged.connect(self.contextMenu_rolling_toogled)
        self.rolling_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.rolling_Checkbox_Action.setDefaultWidget(self.rolling_Checkbox)
        if self.__stp_active__:
            self.rolling_Checkbox.setDisabled(True)

        # show legend

        self.legend_Checkbox = QCheckBox()
        self.legend_Checkbox.setText('Show legend')
        self.legend_Checkbox.setChecked(self.config['show_legend']['value'] == '1')
        self.legend_Checkbox.stateChanged.connect(self.contextMenu_legend_toogled)
        self.legend_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.legend_Checkbox_Action.setDefaultWidget(self.legend_Checkbox)

        ##### Build axes menu
        #self.axesMenu.addAction(self.xRange_Action)
        self.axesMenu.addSeparator().setText("Y-Range")
        self.axesMenu.addAction(self.yRange_Action)

        # Grid Menu:
        # -----------------------------------------------------------
        # Y-Grid checkbox
        self.xGrid_Checkbox = QCheckBox()
        self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)
        self.xGrid_Checkbox.setText('X-Grid')
        self.xGrid_Action = QWidgetAction(self.__plotWidget__)
        self.xGrid_Action.setDefaultWidget(self.xGrid_Checkbox)
        self.gridMenu.addAction(self.xGrid_Action)
        # Check config for startup  state
        if self.__show_grid_x__:
            self.xGrid_Checkbox.setChecked(True)

        # X-Grid checkbox
        self.yGrid_Checkbox = QCheckBox()
        self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)
        self.yGrid_Checkbox.setText('Y-Grid')
        self.yGrid_Action = QWidgetAction(self.__plotWidget__)
        self.yGrid_Action.setDefaultWidget(self.yGrid_Checkbox)
        self.gridMenu.addAction(self.yGrid_Action)
        # Check config for startup  state
        if self.__show_grid_y__:
            self.yGrid_Checkbox.setChecked(True)

        # add Menus
        self.custMenu.addMenu(self.axesMenu)
        self.custMenu.addMenu(self.gridMenu)
        self.custMenu.addSeparator().setText("Rolling Plot")
        self.custMenu.addAction(self.rolling_Checkbox_Action)
        self.custMenu.addAction(self.legend_Checkbox_Action)
        self.__plotWidget__.getPlotItem().getViewBox().menu.clear()

        if not self.__papi_debug__:
            self.__plotWidget__.getPlotItem().ctrlMenu = [self.pl_create_control_context_menu(), self.custMenu]
    def initToolbar(self, webview):
        pass
        ###使用QToolBar创建导航栏,并使用QAction创建按钮
        # 添加导航栏
        self.navigation_bar = QToolBar('Navigation')
        # 锁定导航栏
        self.navigation_bar.setMovable(False)
        # 设定图标的大小
        self.navigation_bar.setIconSize(QSize(2, 2))
        # 添加导航栏到窗口中
        self.addToolBar(self.navigation_bar)
        # 添加其它配置
        self.navigation_bar.setObjectName("navigation_bar")
        self.navigation_bar.setCursor(Qt.ArrowCursor)
        # QAction类提供了抽象的用户界面action,这些action可以被放置在窗口部件中
        # 添加前进、后退、停止加载和刷新的按钮
        self.reload_icon = unichr(0xf2f9)
        self.stop_icon = unichr(0xf00d)

        # 后退按钮
        self.back_action = QWidgetAction(self)
        self.back_button = QPushButton(unichr(0xf060), self,
                                       clicked=webview.back,
                                       font=fontawesome("far"),
                                       objectName='back_button')
        self.back_button.setToolTip("后退")
        self.back_button.setCursor(Qt.ArrowCursor)
        self.back_action.setDefaultWidget(self.back_button)

        # 前进按钮
        self.next_action = QWidgetAction(self)
        self.next_button = QPushButton(unichr(0xf061), self,
                                       clicked=webview.forward,
                                       font=fontawesome("far"),
                                       objectName='next_button')
        self.next_button.setToolTip("前进")
        self.next_button.setCursor(Qt.ArrowCursor)
        self.next_action.setDefaultWidget(self.next_button)

        # 刷新与停止按钮
        self.reload_action = QWidgetAction(self)

        self.reload_button = QPushButton(self.reload_icon, self,
                                         clicked=webview.reload,
                                         font=fontawesome("far"),
                                         objectName='reload_button')
        self.reload_button.setToolTip("刷新")
        self.reload_button.setCursor(Qt.ArrowCursor)
        self.reload_action.setDefaultWidget(self.reload_button)

        # 放大按钮
        self.zoom_in_button = QPushButton(unichr(0xf067), self,
                                          clicked=self.zoom_in_func,
                                          font=fontawesome("far"),
                                          objectName='zoom_in_btn')
        self.zoom_in_button.setToolTip("放大")
        self.zoom_in_button.setCursor(Qt.ArrowCursor)

        # 缩小按钮
        self.zoom_out_button = QPushButton(unichr(0xf068), self,
                                           clicked=self.zoom_out_func,
                                           font=fontawesome("far"),
                                           objectName='zoom_out_btn')
        self.zoom_out_button.setToolTip("缩小")
        self.zoom_out_button.setCursor(Qt.ArrowCursor)
        self.sf_label_rate = QLabel()
        self.sf_label_rate.setObjectName("sf_label_rate")
        self.sf_label_rate.setFixedWidth(30)
        self.sf_label_rate.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
        self.sf_label_rate.setProperty("class","qlabel")
        self.sf_label_rate.setText(str(int(self.webview.zoomFactor()*100))+"%")

        # 全屏按钮
        self.full_screen_button = QPushButton(unichr(0xe140), self,
                                           clicked=self.full_screen_func,
                                           font=fontawesome("boot"),
                                           objectName='full_screen_button')
        self.full_screen_button.setToolTip("全屏")
        self.full_screen_button.setCursor(Qt.ArrowCursor)

        # 其它按钮
        self.more_action = QWidgetAction(self)
        self.more_button = QPushButton(unichr(0xe235), self,
                                       clicked=self.moreMenuShow,
                                       font=fontawesome("boot"),
                                       objectName='more_button')
        self.more_button.setToolTip("页面控制及浏览器核心")
        self.more_button.setCursor(Qt.ArrowCursor)
        self.more_action.setDefaultWidget(self.more_button)

        # 首页按钮
        self.index_action = QWidgetAction(self)
        self.index_button = QPushButton(unichr(0xf015), self,
                                        # clicked=self.zoom_out_func,
                                        font=fontawesome("far"),
                                        objectName='index_button')
        self.index_button.setToolTip("主页")
        self.index_button.setCursor(Qt.ArrowCursor)
        self.index_action.setDefaultWidget(self.index_button)

        # self.back_button.triggered.connect(webview.back)
        # self.next_button.triggered.connect(webview.forward)
        # self.reload_button.triggered.connect(webview.reload)
        # self.zoom_in_btn.triggered.connect(self.zoom_in_func)
        # self.zoom_out_btn.triggered.connect(self.zoom_out_func)
        # 将按钮添加到导航栏上
        self.navigation_bar.addAction(self.back_action)
        self.navigation_bar.addAction(self.next_action)
        self.navigation_bar.addAction(self.reload_action)
        self.navigation_bar.addAction(self.index_action)
        # 添加URL地址栏
        self.urlbar = QLineEdit()
        # 让地址栏能响应回车按键信号
        self.urlbar.returnPressed.connect(self.navigate_to_url)
        # self.navigation_bar.addSeparator()
        self.navigation_bar.addWidget(self.urlbar)
        # self.navigation_bar.addSeparator()

        # self.navigation_bar.addAction(self.zoom_in_action)
        # self.navigation_bar.addAction(self.zoom_out_action)
        self.navigation_bar.addAction(self.more_action)
        # 让浏览器相应url地址的变化
        webview.urlChanged.connect(self.renew_urlbar)
        webview.loadProgress.connect(self.processLoad)
        webview.loadStarted.connect(self.loadPage)
        webview.loadFinished.connect(self.loadFinish)
        webview.titleChanged.connect(self.renew_title)
        webview.iconChanged.connect(self.renew_icon)
        self.webBind()
        webview.show()
        self.navigation_bar.setIconSize(QSize(20, 20))
        self.urlbar.setFont(QFont('SansSerif', 13))
class Browser(QMainWindow):
    def __init__(self, mainWin, webview=None):
        super().__init__(mainWin)
        self.showFullScreen()
        self.mainWin = mainWin
        self.webview = webview
        self.initUI()

    def initUI(self):
        global CREATE_BROWER
        # print("initUI")
        # self.setWindowFlags(Qt.FramelessWindowHint)  # 去掉标题栏的代码
        # 设置窗口标题
        # self.setWindowTitle('LingBrowser')
        # 设置窗口图标
        self.setWindowIcon(QIcon(':/icons/logo.png'))
        self.page = QWebEnginePage()
        self.page.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True)  # 支持视频播放
        self.page.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
        self.page.settings().setAttribute(QWebEngineSettings.FullScreenSupportEnabled, True)
        if self.webview == None:
            # 初始化一个 tab
            self.webview = WebView(self)  # self必须要有,是将主窗口作为参数,传给浏览器
            self.page.setUrl(QUrl(HOME_PAGE))
        self.page.windowCloseRequested.connect(self.on_windowCloseRequested)  # 页面关闭请求
        if CREATE_BROWER:
            CREATE_BROWER = False
            self.page.profile().downloadRequested.connect(self.on_downloadRequested)  # 页面下载请求

        self.t = WebEngineUrlRequestInterceptor()
        self.page.profile().setRequestInterceptor(self.t)
        self.webview.setPage(self.page)
        self.url = self.webview.page().url()
        self.initToolbar(self.webview)
        self.setCentralWidget(self.webview)
        self.center()

    def on_downloadRequested(self, downloadItem):
        # print("download..")
        # print(downloadItem.downloadFileName())
        # print('isFinished', downloadItem.isFinished())
        # print('isPaused', downloadItem.isPaused())
        # print('isSavePageDownload', downloadItem.isSavePageDownload())
        # print('path', downloadItem.path())
        # print('url', downloadItem.url())
        downloadFileName, ok2 = QFileDialog.getSaveFileName(self,
                                                            "文件保存",
                                                            downloadItem.path(),
                                                            "All Files (*)")
        print(downloadItem.path())
        downloadItem.setPath(downloadFileName)
        downloadItem.accept()
        downloadItem.finished.connect(self.on_downloadfinished)
        downloadItem.downloadProgress.connect(self.on_downloadProgress)

    def on_downloadfinished(self):
        print()

    def on_downloadProgress(self, int_1, int_2):
        rate = str(round(int_1 / int_2, 2) * 100).split(".")[0]
        self.mainWin.statusBarDownloadLabel.setText("文件下载 " + rate + "%")
        if int(rate) == 100:
            self.mainWin.statusBarDownloadLabel.setHidden(True)
            self.mainWin.statusBar.setHidden(True)
        else:
            self.mainWin.statusBarDownloadLabel.setHidden(False)
            self.mainWin.statusBar.setHidden(False)

    def on_windowCloseRequested(self):
        print("close tab")
        # self.webview.close()
        # del self.webview
        # sip.delete(self.webview)
        # self.webview
        # self.webview.page().profile().deleteLater()
        # self.deleteLater()
        pass

    def moreMenuShow(self):
        try:
            self.contextMenu = QMenu()
            self.contextMenu.setObjectName("moreMenu")
            self.contextMenu.setFont(fontawesome("far"))
            # self.actionA = self.contextMenu.addAction(self.zoom_in_action)
            # self.actionA = self.contextMenu.addAction(self.zoom_out_action)
            self.contextMenu.popup(
                QPoint(self.mainWin.x() + self.more_button.x() - 200, self.mainWin.y() + 75))  # 2菜单显示的位置 QCursor.pos()
            # print(self.more_button.x())
            # print(self.more_button.y())
            # print(self.frameGeometry())
            # print(self.mainWin.x())
            # print(self.mainWin.y())
            self.contextMenu.setContentsMargins(25,0,0,0)
            self.contextMenu.addMenu("打印")
            self.contextMenu.addSeparator()
            # 缩放组合
            sf_widget = QWidget(self)
            sf_widget.setProperty("class","qwidget")
            sf_widget.setObjectName("sf_widget")
            sf_widget.setContentsMargins(0,0,0,0)
            # sf_widget.setFixedHeight(20)
            sf_layout = QHBoxLayout()
            sf_layout.setContentsMargins(0,0,0,0)
            sf_widget.setLayout(sf_layout)
            sf_label = QLabel("缩放")
            sf_label.setObjectName("sf_item_label")
            sf_layout.addWidget(sf_label)
            sf_layout.addWidget(self.zoom_out_button)
            sf_layout.addWidget(self.sf_label_rate)
            sf_layout.addWidget(self.zoom_in_button)
            sf_layout.addWidget(self.full_screen_button)
            sf_action = QWidgetAction(self)
            sf_action.setDefaultWidget(sf_widget)
            self.actionA = self.contextMenu.addAction(sf_action)
            # self.actionA.triggered.connect(self.actionHandler)
            sf_layout.setSpacing(0)

            self.contextMenu.show()
        except Exception as e:
            print(e)

    def initToolbar(self, webview):
        pass
        ###使用QToolBar创建导航栏,并使用QAction创建按钮
        # 添加导航栏
        self.navigation_bar = QToolBar('Navigation')
        # 锁定导航栏
        self.navigation_bar.setMovable(False)
        # 设定图标的大小
        self.navigation_bar.setIconSize(QSize(2, 2))
        # 添加导航栏到窗口中
        self.addToolBar(self.navigation_bar)
        # 添加其它配置
        self.navigation_bar.setObjectName("navigation_bar")
        self.navigation_bar.setCursor(Qt.ArrowCursor)
        # QAction类提供了抽象的用户界面action,这些action可以被放置在窗口部件中
        # 添加前进、后退、停止加载和刷新的按钮
        self.reload_icon = unichr(0xf2f9)
        self.stop_icon = unichr(0xf00d)

        # 后退按钮
        self.back_action = QWidgetAction(self)
        self.back_button = QPushButton(unichr(0xf060), self,
                                       clicked=webview.back,
                                       font=fontawesome("far"),
                                       objectName='back_button')
        self.back_button.setToolTip("后退")
        self.back_button.setCursor(Qt.ArrowCursor)
        self.back_action.setDefaultWidget(self.back_button)

        # 前进按钮
        self.next_action = QWidgetAction(self)
        self.next_button = QPushButton(unichr(0xf061), self,
                                       clicked=webview.forward,
                                       font=fontawesome("far"),
                                       objectName='next_button')
        self.next_button.setToolTip("前进")
        self.next_button.setCursor(Qt.ArrowCursor)
        self.next_action.setDefaultWidget(self.next_button)

        # 刷新与停止按钮
        self.reload_action = QWidgetAction(self)

        self.reload_button = QPushButton(self.reload_icon, self,
                                         clicked=webview.reload,
                                         font=fontawesome("far"),
                                         objectName='reload_button')
        self.reload_button.setToolTip("刷新")
        self.reload_button.setCursor(Qt.ArrowCursor)
        self.reload_action.setDefaultWidget(self.reload_button)

        # 放大按钮
        self.zoom_in_button = QPushButton(unichr(0xf067), self,
                                          clicked=self.zoom_in_func,
                                          font=fontawesome("far"),
                                          objectName='zoom_in_btn')
        self.zoom_in_button.setToolTip("放大")
        self.zoom_in_button.setCursor(Qt.ArrowCursor)

        # 缩小按钮
        self.zoom_out_button = QPushButton(unichr(0xf068), self,
                                           clicked=self.zoom_out_func,
                                           font=fontawesome("far"),
                                           objectName='zoom_out_btn')
        self.zoom_out_button.setToolTip("缩小")
        self.zoom_out_button.setCursor(Qt.ArrowCursor)
        self.sf_label_rate = QLabel()
        self.sf_label_rate.setObjectName("sf_label_rate")
        self.sf_label_rate.setFixedWidth(30)
        self.sf_label_rate.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
        self.sf_label_rate.setProperty("class","qlabel")
        self.sf_label_rate.setText(str(int(self.webview.zoomFactor()*100))+"%")

        # 全屏按钮
        self.full_screen_button = QPushButton(unichr(0xe140), self,
                                           clicked=self.full_screen_func,
                                           font=fontawesome("boot"),
                                           objectName='full_screen_button')
        self.full_screen_button.setToolTip("全屏")
        self.full_screen_button.setCursor(Qt.ArrowCursor)

        # 其它按钮
        self.more_action = QWidgetAction(self)
        self.more_button = QPushButton(unichr(0xe235), self,
                                       clicked=self.moreMenuShow,
                                       font=fontawesome("boot"),
                                       objectName='more_button')
        self.more_button.setToolTip("页面控制及浏览器核心")
        self.more_button.setCursor(Qt.ArrowCursor)
        self.more_action.setDefaultWidget(self.more_button)

        # 首页按钮
        self.index_action = QWidgetAction(self)
        self.index_button = QPushButton(unichr(0xf015), self,
                                        # clicked=self.zoom_out_func,
                                        font=fontawesome("far"),
                                        objectName='index_button')
        self.index_button.setToolTip("主页")
        self.index_button.setCursor(Qt.ArrowCursor)
        self.index_action.setDefaultWidget(self.index_button)

        # self.back_button.triggered.connect(webview.back)
        # self.next_button.triggered.connect(webview.forward)
        # self.reload_button.triggered.connect(webview.reload)
        # self.zoom_in_btn.triggered.connect(self.zoom_in_func)
        # self.zoom_out_btn.triggered.connect(self.zoom_out_func)
        # 将按钮添加到导航栏上
        self.navigation_bar.addAction(self.back_action)
        self.navigation_bar.addAction(self.next_action)
        self.navigation_bar.addAction(self.reload_action)
        self.navigation_bar.addAction(self.index_action)
        # 添加URL地址栏
        self.urlbar = QLineEdit()
        # 让地址栏能响应回车按键信号
        self.urlbar.returnPressed.connect(self.navigate_to_url)
        # self.navigation_bar.addSeparator()
        self.navigation_bar.addWidget(self.urlbar)
        # self.navigation_bar.addSeparator()

        # self.navigation_bar.addAction(self.zoom_in_action)
        # self.navigation_bar.addAction(self.zoom_out_action)
        self.navigation_bar.addAction(self.more_action)
        # 让浏览器相应url地址的变化
        webview.urlChanged.connect(self.renew_urlbar)
        webview.loadProgress.connect(self.processLoad)
        webview.loadStarted.connect(self.loadPage)
        webview.loadFinished.connect(self.loadFinish)
        webview.titleChanged.connect(self.renew_title)
        webview.iconChanged.connect(self.renew_icon)
        self.webBind()
        webview.show()
        self.navigation_bar.setIconSize(QSize(20, 20))
        self.urlbar.setFont(QFont('SansSerif', 13))

    def zoom_in_func(self):
        self.webview.setZoomFactor(self.webview.zoomFactor() + 0.1)
        self.sf_label_rate.setText(str(int(self.webview.zoomFactor()*100))+"%")

    def zoom_out_func(self):
        self.webview.setZoomFactor(self.webview.zoomFactor() - 0.1)
        self.sf_label_rate.setText(str(int(self.webview.zoomFactor()*100))+"%")

    def full_screen_func(self):
        self.navigation_bar.setHidden(True)
        self.mainWin.titleBar.setHidden(True)
        self.mainWin.showFullScreen()

    def on_network_call(self, info):
        print(info)
        pass

    def loadPage(self):
        # print("loadPage")
        # print(self.webview.objectName())
        # self.renew_title("空页面")
        index = self.mainWin.tabWidget.currentIndex()
        self.mainWin.tabWidget.setTabIcon(index, QIcon(":icons/earth_128.png"))
        # self.reload_button.setDefaultWidget(self.stop_button_icon)
        self.reload_button.setText(self.stop_icon)
        self.reload_button.setToolTip("停止")

    def processLoad(self, rate):
        self.mainWin.statusBarLabelProgress.setValue(rate)
        self.mainWin.statusBarLabel.setText("网页加载")
        if rate == 0:
            self.mainWin.statusBarLabelProgress.setMaximum(0)
            self.mainWin.statusBarLabelProgress.setMinimum(0)
        else:
            self.mainWin.statusBarLabelProgress.setMaximum(0)
            self.mainWin.statusBarLabelProgress.setMinimum(100)
        if rate == 100:
            self.mainWin.statusBarLabelProgress.setHidden(True)
            self.mainWin.statusBarLabel.setHidden(True)
            self.mainWin.statusBar.setHidden(True)
        else:
            self.mainWin.statusBarLabelProgress.setHidden(False)
            self.mainWin.statusBarLabel.setHidden(False)
            self.mainWin.statusBar.setHidden(False)
        pass

    def loadFinish(self, isEnd):
        if isEnd:
            # print("load finished", isEnd)
            # self.reload_button.setDefaultWidget(self.reload_button_icon)
            self.reload_button.setText(self.reload_icon)
            self.reload_button.setToolTip("刷新")
        else:
            # print("load finished", isEnd)
            # print("load finished",isEnd)
            pass
        # index = self.webview.objectName()
        # title = self.page.title()
        # print("title", title)
        try:
            url = self.page.url().toString()
        except BaseException as base:
            url = self.webview.page().url().toString()
        # self.mainWin.tabWidget.setTabText(int(index), title if title else url)
        self.urlbar.setText(url)

    def webBind(self):
        # print("webBind")
        # self.back_button.disconnect()
        # self.next_button.disconnect()
        # self.stop_button.disconnect()
        # self.reload_button.disconnect()
        # self.add_button.disconnect()
        # self.back_button.triggered.connect(self.webview.back)
        # self.next_button.triggered.connect(self.webview.forward)
        # self.stop_button.triggered.connect(self.webview.stop)
        # self.reload_button.triggered.connect(self.webview.reload)
        # self.add_button.triggered.connect(self.mainWin.newTab)
        self.webview.urlChanged.connect(self.renew_urlbar)
        self.webview.titleChanged.connect(self.renew_title)
        self.webview.iconChanged.connect(self.renew_icon)

    def navigate_to_url(self):
        q = QUrl(self.urlbar.text())
        if q.scheme() == '':
            q.setScheme('http')
        self.webview.setUrl(q)

    def renew_urlbar(self, url):
        # 将当前网页的链接更新到地址栏
        # print("renew_urlbar")
        self.urlbar.setText(url.toString())
        self.urlbar.setCursorPosition(0)
        # print("url", url)f

    def renew_title(self, title):
        # 将当前网页的标题更新到标签栏
        index = self.webview.objectName()
        self.mainWin.tabWidget.setTabToolTip(int(index), title)
        title = " " + title[:11] + ".." if len(title) >= 12 else " " + title
        self.mainWin.tabWidget.setTabText(int(index), title)
        pass

    def renew_icon(self, icon):
        # 将当前网页的图标更新到标签栏
        # print("renew_icon")
        index = self.webview.objectName()
        self.mainWin.tabWidget.setTabIcon(int(index), icon)

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

    # 创建tab
    def create_tab(self, webview):
        # print("create_tab")
        self.tab = QWidget()
        self.mainWin.tabWidget.addTab(self.tab, "新标签页")
        self.mainWin.tabWidget.setCurrentWidget(self.tab)
        index = self.mainWin.tabWidget.currentIndex()
        # self.mainWin.tabWidget.setTabIcon(index, ":icons/logo.png")
        #####
        self.Layout = QVBoxLayout(self.tab)
        self.Layout.setContentsMargins(0, 0, 0, 0)
        self.Layout.addWidget(Browser(self.mainWin, webview=webview))
        webview.setObjectName(str(index))
        self.mainWin.tab_[str(index)] = webview
        self.tab.setObjectName("tab_" + str(index))
Beispiel #21
0
    def _menu(self, event) -> None:
        """Returns a new QMenu for system tray."""
        menu = QMenu()
        menu.setAttribute(Qt.WA_DeleteOnClose)

        menu.addSeparator()

        parser_toggles = set()
        parsers = QMenu("Toggles")
        for parser in self._parsers:
            toggle: QAction = parsers.addAction(parser.name.title())
            toggle.setCheckable(True)
            toggle.setChecked(profile.__dict__[parser.name].toggled)
            parser_toggles.add(toggle)
            parsers.addAction(toggle)

        menu.addMenu(parsers)

        menu.addSeparator()

        profiles = QMenu(profile.name if profile.name else "Profile")

        level_select = QWidgetAction(profiles)
        w = QWidget()
        layout = QHBoxLayout()
        spinbox = QSpinBox()
        spinbox.setMaximum(65)
        spinbox.setMinimum(1)
        spinbox.setMaximumWidth(100)
        spinbox.setValue(profile.spells.level)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(QLabel("Level"), stretch=1)
        layout.addWidget(spinbox, stretch=0)
        w.setLayout(layout)
        level_select.setDefaultWidget(w)
        profiles.addAction(level_select)

        menu.addMenu(profiles)

        menu.addSeparator()
        settings_action = menu.addAction("Settings")

        lock_toggle = menu.addAction(
            "Unlock Windows" if self._locked else "Lock Windows")

        # check online for new version
        new_version_text = ""
        if is_new_version_available(ONLINE_VERSION, CURRENT_VERSION):
            new_version_text = "Update Available {}".format(ONLINE_VERSION)
        else:
            new_version_text = "Version {}".format(CURRENT_VERSION)

        check_version_action = menu.addAction(new_version_text)

        menu.addSeparator()
        quit_action = menu.addAction("Quit")

        action = menu.exec(QCursor.pos())

        # change level if it was changed
        if spinbox.value() != profile.spells.level:
            profile.spells.level = spinbox.value()

        if action == check_version_action:
            webbrowser.open("https://github.com/nomns/nparse/releases")

        elif action == settings_action:
            if not self._settings.isVisible():
                self._settings.set_values()
                self._settings.setWindowTitle(
                    f"Settings (Profile: {profile.name})")
                if self._settings.exec():
                    self._settings.save_settings()
                    # Update required settings
                    for parser in self._parsers:
                        parser.settings_updated()
                    if self._toggled:
                        self._toggle()
                    self._toggle()
                else:
                    self._settings.set_values()  # revert values
            else:
                self._settings.activateWindow()

        elif action == quit_action:
            if self._toggled:
                self._toggle()

            # save parser geometry
            self.save_geometry()
            app_config.save()
            profile.save()
            self._system_tray.setVisible(False)
            self.quit()

        elif action in parser_toggles:
            if not self._locked:
                self.lock_toggle()
            parser = [
                parser for parser in self._parsers
                if parser.name == action.text().lower()
            ][0]
            parser.toggle()

        elif action == lock_toggle:
            self.lock_toggle()
Beispiel #22
0
    def setup_context_menu(self):
        """

        :return:
        """

        self.custMenu = QMenu("Options")
        self.axesMenu = QMenu('Y-Axis')
        self.gridMenu = QMenu('Grid')

        ##### Y-Range Actions
        self.yRange_Widget = QWidget()
        self.yRange_Layout = QVBoxLayout(self.yRange_Widget)
        self.yRange_Layout.setContentsMargins(2, 2, 2, 2)
        self.yRange_Layout.setSpacing(1)

        self.yAutoRangeButton = QPushButton()
        self.yAutoRangeButton.clicked.connect(self.contextMenu_yAutoRangeButton_clicked)
        self.yAutoRangeButton.setText('Use autorange')
        self.yRange_Layout.addWidget(self.yAutoRangeButton)

        ##### Y Line Edits
        # Layout
        self.yRange_EditWidget = QWidget()
        self.yRange_EditLayout = QHBoxLayout(self.yRange_EditWidget)
        self.yRange_EditLayout.setContentsMargins(2, 2, 2, 2)
        self.yRange_EditLayout.setSpacing(1)

        # get old values;
        reg = re.compile(r'(\d+\.\d+)')
        range = reg.findall(self.config['yRange']['value'])
        if len(range) == 2:
            y_min = range[0]
            y_max = range[1]
        else:
            y_min = '0.0'
            y_max = '1.0'

        rx = QRegExp(r'([-]{0,1}\d+\.\d+)')
        validator = QRegExpValidator(rx, self.__plotWidget__)

        # Min
        self.yRange_minEdit = QLineEdit()
        self.yRange_minEdit.setFixedWidth(80)
        self.yRange_minEdit.setText(y_min)
        self.yRange_minEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_minEdit.setValidator(validator)
        # Max
        self.yRange_maxEdit = QLineEdit()
        self.yRange_maxEdit.setFixedWidth(80)
        self.yRange_maxEdit.setText(y_max)
        self.yRange_maxEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_maxEdit.setValidator(validator)
        # addTo Layout
        self.yRange_EditLayout.addWidget(self.yRange_minEdit)
        self.yRange_EditLayout.addWidget(QLabel('<'))
        self.yRange_EditLayout.addWidget(self.yRange_maxEdit)
        self.yRange_Layout.addWidget(self.yRange_EditWidget)

        # build Action
        self.yRange_Action = QWidgetAction(self.__plotWidget__)
        self.yRange_Action.setDefaultWidget(self.yRange_Widget)

        ##### Rolling Plot
        self.rolling_Checkbox = QCheckBox()
        self.rolling_Checkbox.setText('Rolling plot')
        self.rolling_Checkbox.setChecked(self.config['rolling_plot']['value'] == '1')
        self.rolling_Checkbox.stateChanged.connect(self.contextMenu_rolling_toogled)
        self.rolling_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.rolling_Checkbox_Action.setDefaultWidget(self.rolling_Checkbox)
        if self.__stp_active__:
            self.rolling_Checkbox.setDisabled(True)

        # show legend

        self.legend_Checkbox = QCheckBox()
        self.legend_Checkbox.setText('Show legend')
        self.legend_Checkbox.setChecked(self.config['show_legend']['value'] == '1')
        self.legend_Checkbox.stateChanged.connect(self.contextMenu_legend_toogled)
        self.legend_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.legend_Checkbox_Action.setDefaultWidget(self.legend_Checkbox)

        ##### Build axes menu
        #self.axesMenu.addAction(self.xRange_Action)
        self.axesMenu.addSeparator().setText("Y-Range")
        self.axesMenu.addAction(self.yRange_Action)

        # Grid Menu:
        # -----------------------------------------------------------
        # Y-Grid checkbox
        self.xGrid_Checkbox = QCheckBox()
        self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)
        self.xGrid_Checkbox.setText('X-Grid')
        self.xGrid_Action = QWidgetAction(self.__plotWidget__)
        self.xGrid_Action.setDefaultWidget(self.xGrid_Checkbox)
        self.gridMenu.addAction(self.xGrid_Action)
        # Check config for startup  state
        if self.__show_grid_x__:
            self.xGrid_Checkbox.setChecked(True)

        # X-Grid checkbox
        self.yGrid_Checkbox = QCheckBox()
        self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)
        self.yGrid_Checkbox.setText('Y-Grid')
        self.yGrid_Action = QWidgetAction(self.__plotWidget__)
        self.yGrid_Action.setDefaultWidget(self.yGrid_Checkbox)
        self.gridMenu.addAction(self.yGrid_Action)
        # Check config for startup  state
        if self.__show_grid_y__:
            self.yGrid_Checkbox.setChecked(True)

        # add Menus
        self.custMenu.addMenu(self.axesMenu)
        self.custMenu.addMenu(self.gridMenu)
        self.custMenu.addSeparator().setText("Rolling Plot")
        self.custMenu.addAction(self.rolling_Checkbox_Action)
        self.custMenu.addAction(self.legend_Checkbox_Action)
        self.__plotWidget__.getPlotItem().getViewBox().menu.clear()

        if not self.__papi_debug__:
            self.__plotWidget__.getPlotItem().ctrlMenu = [self.pl_create_control_context_menu(), self.custMenu]
Beispiel #23
0
    def __init__(self, parent=None):
        super(MovieWidget, self).__init__(parent)
        mini = True
        self.parent = parent
        self.isVideoAvailable = False
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.videoAvailableChanged.connect(
            self.videoAvailableChanged)

        videoWidget = QVideoWidget(self)
        videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setContextMenuPolicy(Qt.CustomContextMenu)

        # Context Menu
        self.customContextMenuRequested.connect(self.openContextMenu)
        self.contextMenu = QMenu()

        self.openAction = self.contextMenu.addAction("Open file")
        icon = QIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton))
        self.openAction.setIcon(icon)

        self.urlAction = self.contextMenu.addAction("Open stream")
        icon = QIcon(self.style().standardIcon(QStyle.SP_DirLinkIcon))
        self.urlAction.setIcon(icon)

        self.playAction = self.contextMenu.addAction("Play/Pause")
        icon = QIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playAction.setEnabled(False)
        self.playAction.setIcon(icon)

        self.closeAction = self.contextMenu.addAction("Close")
        icon = QIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton))
        self.closeAction.setEnabled(False)
        self.closeAction.setIcon(icon)

        self.posSlider = QSlider(Qt.Horizontal)
        self.posSlider.setRange(0, 0)
        self.posSlider.sliderMoved.connect(self.setPosition)
        self.wac = QWidgetAction(self.contextMenu)
        self.wac.setDefaultWidget(self.posSlider)
        self.posAction = self.contextMenu.addAction(self.wac)

        self.lblFile = QLabel()
        self.wal = QWidgetAction(self.contextMenu)
        self.wal.setDefaultWidget(self.lblFile)
        self.posAction = self.contextMenu.addAction(self.wal)

        # Control box
        self.openButton = QPushButton()
        self.openButton.setIcon(self.style().standardIcon(
            QStyle.SP_DialogOpenButton))
        self.openButton.clicked.connect(self.openFile)

        self.urlButton = QPushButton()
        self.urlButton.setIcon(self.style().standardIcon(
            QStyle.SP_DirLinkIcon))
        self.urlButton.clicked.connect(self.openURL)

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Maximum)

        # Create layouts to place inside widget
        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(self.openButton)
        controlLayout.addWidget(self.urlButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.addWidget(videoWidget)
        if mini != True:
            vLayout.addLayout(controlLayout)
            vLayout.addWidget(self.errorLabel)

        self.setLayout(vLayout)

        # Set widget to contain window contents
        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        self.resize(180, 100)
Beispiel #24
0
    def __evt_yeahdoc_contextMenu(self, p):
        """
        context menu
        """
        item = self.yeahdoclisttree.currentItem()
        if item == None or item.isDisabled():
            pass
        else:
            menu = QMenu()

            # menu top
            action = QWidgetAction(self)
            title = item.text(0)
            if len(title) < 25:
                for i in range(len(title), 25):
                    title = title + "  &nbsp;"
            action.setDefaultWidget(
                QLabel("&nbsp;&nbsp;<img  src='%s'/>  &nbsp;%s" % (getPath("iconDir", "yeahdoc/item.png"), title)))
            menu.addAction(action)

            menu.addSeparator()

            menu.addAction(self.__actions["__yeahdoc_open__"])
            menu.addAction(self.__actions["__yeahdoc_edit__"])

            # change class
            change_class_menu = QMenu()
            entry = YeahdocDatasSupply().bb_read1_simple(item.getMark())
            current_categoryid = entry['categoryid']
            for class_item in YeahdocDatasSupply().bc_list():
                action = QAction(class_item["title"], self, \
                                 triggered=lambda re, item=item, categoryid=str(class_item["id"]): \
                                     self.__evt_change_category(categoryid, item))
                action.setIcon(QIcon(getPath("iconDir", "yeahdoc/flag/%s" % str(class_item["img"]))))
                action.setIconVisibleInMenu(True)
                # mark current class id menu checked
                if class_item['id'] == current_categoryid:
                    action.setCheckable(True)
                    action.setChecked(True)
                    action.setDisabled(True)
                change_class_menu.addAction(action)

            action = QAction(QIcon(getPath("iconDir", "yeahdoc/change.png")),
                             QApplication.translate("YeahdocList", "Change Category"), self)
            action.setIconVisibleInMenu(True)
            action.setMenu(change_class_menu)

            menu.addAction(action)

            menu.addAction(self.__actions["__yeahdoc_star__"])
            menu.addAction(self.__actions["__yeahdoc_rename__"])
            menu.addAction(self.__actions["__yeahdoc_delete__"])

            menu.addSeparator()

            setmode = True if entry['lock'] == 0 else False
            action = QWidgetAction(self)
            widget = QWidget()
            layout = QHBoxLayout()
            layout.setSpacing(0)
            layout.setMargin(0)
            widget.setLayout(layout)
            widgetMore = QWidget()
            widgetMore.setVisible(False)
            layoutMore = QHBoxLayout()
            layoutMore.setSpacing(0)
            layoutMore.setMargin(0)
            widgetMore.setLayout(layoutMore)

            layout.addWidget(QLabel("<img src='%s'/>" % getPath("iconDir", "yeahdoc/password.png")))
            passwordMore = QPushButton(
                QApplication.translate("YeahdocEditor", "Encrypt") if setmode else QApplication.translate(
                    "YeahdocEditor", "Decrypt"))
            passwordMore.setFlat(True)
            layout.addWidget(passwordMore)

            passwordInput = QLineEdit()
            passwordInput.setEchoMode(QLineEdit.Password)
            passwordInput.setMaximumWidth(70)

            layoutMore.addWidget(passwordInput)

            if setmode:
                passwordInputAgain = QLineEdit()
                passwordInputAgain.setEchoMode(QLineEdit.Password)
                passwordInputAgain.setMaximumWidth(70)
                layoutMore.addWidget(QLabel(QApplication.translate("YeahdocEditor", "Re")))
                layoutMore.addWidget(passwordInputAgain)

            passwordSubmit = QPushButton("OK")
            passwordSubmit.setFlat(True)
            layoutMore.addWidget(passwordSubmit)

            layout.addWidget(widgetMore)
            layout.addItem(QSpacerItem(0, 20, QSizePolicy.Expanding, QSizePolicy.Expanding))

            action.setDefaultWidget(widget)
            QObject.connect(passwordSubmit, SIGNAL("clicked ()"),
                            lambda: self.__evt_password(setmode, passwordInput.text(),
                                                        passwordInputAgain.text() if setmode else ""))
            QObject.connect(passwordMore, SIGNAL("clicked ()"),
                            lambda: widgetMore.setVisible(not widgetMore.isVisible()))

            menu.addAction(action)

            # show it.
            menu.exec_(self.mapToGlobal(self.yeahdoclisttree.mapTo(self, p)))
class MainWindow(QtWidgets.QMainWindow):
    save_perspective_action: QAction
    perspective_list_action: QWidgetAction
    perspective_combo_box: QComboBox
    dock_manager: QtAds.CDockManager

    def __init__(self, parent=None):
        super().__init__(parent)
        self.save_perspective_action = None
        self.perspective_list_action = None
        self.perspective_combo_box = None
        self.dock_manager = None

        self.setup_ui()

        self.dock_manager = QtAds.CDockManager(self)
        self.perspective_combo_box.activated[str].connect(
            self.dock_manager.openPerspective)
        self.create_content()
        self.resize(800, 600)
        self.restore_state()
        self.restore_perspectives()

    def setup_ui(self):
        self.setObjectName("MainWindow")
        self.resize(400, 300)
        self.setDockOptions(QtWidgets.QMainWindow.AllowTabbedDocks)
        self.centralWidget = QtWidgets.QWidget(self)
        self.centralWidget.setObjectName("centralWidget")
        self.setCentralWidget(self.centralWidget)
        self.status_bar = QtWidgets.QStatusBar(self)
        self.status_bar.setObjectName("statusBar")
        self.setStatusBar(self.status_bar)
        self.menu_bar = QtWidgets.QMenuBar(self)
        self.menu_bar.setGeometry(QRect(0, 0, 400, 21))
        self.menu_bar.setObjectName("menuBar")
        self.menu_file = QtWidgets.QMenu(self.menu_bar)
        self.menu_file.setObjectName("menuFile")
        self.menu_view = QtWidgets.QMenu(self.menu_bar)
        self.menu_view.setObjectName("menuView")
        self.menu_about = QtWidgets.QMenu(self.menu_bar)
        self.menu_about.setObjectName("menuAbout")
        self.setMenuBar(self.menu_bar)
        self.tool_bar = QtWidgets.QToolBar(self)
        self.tool_bar.setObjectName("toolBar")
        self.addToolBar(Qt.TopToolBarArea, self.tool_bar)
        self.action_exit = QtWidgets.QAction(self)
        self.action_exit.setObjectName("actionExit")
        self.action_save_state = QtWidgets.QAction(self)
        self.action_save_state.setObjectName("actionSaveState")
        self.action_save_state.triggered.connect(self.saveState)

        self.action_restore_state = QtWidgets.QAction(self)
        self.action_restore_state.setObjectName("actionRestoreState")
        self.action_restore_state.triggered.connect(self.restore_state)

        self.menu_file.addAction(self.action_exit)
        self.menu_file.addAction(self.action_save_state)
        self.menu_file.addAction(self.action_restore_state)
        self.menu_bar.addAction(self.menu_file.menuAction())
        self.menu_bar.addAction(self.menu_view.menuAction())
        self.menu_bar.addAction(self.menu_about.menuAction())

        self.setWindowTitle("MainWindow")
        self.menu_file.setTitle("File")
        self.menu_view.setTitle("View")
        self.menu_about.setTitle("About")
        self.tool_bar.setWindowTitle("toolBar")
        self.action_exit.setText("Exit")
        self.action_save_state.setText("Save State")
        self.action_restore_state.setText("Restore State")
        self.create_actions()

    def create_actions(self):
        '''
        Creates the toolbar actions
        '''
        self.tool_bar.addAction(self.action_save_state)
        self.action_save_state.setIcon(self.style().standardIcon(
            QStyle.SP_DialogSaveButton))
        self.tool_bar.addAction(self.action_restore_state)
        self.action_restore_state.setIcon(self.style().standardIcon(
            QStyle.SP_DialogOpenButton))
        self.save_perspective_action = QAction("Save Perspective", self)
        self.save_perspective_action.triggered.connect(self.save_perspective)

        self.perspective_list_action = QWidgetAction(self)
        self.perspective_combo_box = QComboBox(self)
        self.perspective_combo_box.setSizeAdjustPolicy(
            QComboBox.AdjustToContents)
        self.perspective_combo_box.setSizePolicy(QSizePolicy.Preferred,
                                                 QSizePolicy.Preferred)
        self.perspective_list_action.setDefaultWidget(
            self.perspective_combo_box)
        self.tool_bar.addSeparator()
        self.tool_bar.addAction(self.perspective_list_action)
        self.tool_bar.addAction(self.save_perspective_action)

    def create_content(self):
        '''
        Fill the dock manager with dock widgets
        '''
        # Test container docking
        view_menu = self.menu_view
        dock_widget = create_calendar_dock_widget(view_menu)
        dock_widget.setIcon(self.style().standardIcon(
            QStyle.SP_DialogOpenButton))
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
        self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, dock_widget)
        self.dock_manager.addDockWidget(
            QtAds.LeftDockWidgetArea,
            create_long_text_label_dock_widget(view_menu))
        file_system_widget = create_file_system_tree_dock_widget(view_menu)
        tool_bar = file_system_widget.createDefaultToolBar()
        tool_bar.addAction(self.action_save_state)
        tool_bar.addAction(self.action_restore_state)
        self.dock_manager.addDockWidget(QtAds.BottomDockWidgetArea,
                                        file_system_widget)
        file_system_widget = create_file_system_tree_dock_widget(view_menu)
        tool_bar = file_system_widget.createDefaultToolBar()
        tool_bar.addAction(self.action_save_state)
        tool_bar.addAction(self.action_restore_state)
        file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable,
                                      False)
        top_dock_area = self.dock_manager.addDockWidget(
            QtAds.TopDockWidgetArea, file_system_widget)
        dock_widget = create_calendar_dock_widget(view_menu)
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
        dock_widget.setTabToolTip("Tab ToolTip\nHodie est dies magna")
        self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea,
                                        dock_widget, top_dock_area)

        # Test dock area docking
        right_dock_area = self.dock_manager.addDockWidget(
            QtAds.RightDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), top_dock_area)
        self.dock_manager.addDockWidget(
            QtAds.TopDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), right_dock_area)

        bottom_dock_area = self.dock_manager.addDockWidget(
            QtAds.BottomDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), right_dock_area)

        self.dock_manager.addDockWidget(
            QtAds.RightDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), right_dock_area)
        self.dock_manager.addDockWidget(
            QtAds.CenterDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), bottom_dock_area)

    def save_state(self):
        '''
        Saves the dock manager state and the main window geometry
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        settings.setValue("mainWindow/Geometry", self.saveGeometry())
        settings.setValue("mainWindow/State", self.saveState())
        settings.setValue("mainWindow/DockingState",
                          self.dock_manager.saveState())

    def save_perspectives(self):
        '''
        Save the list of perspectives
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        self.dock_manager.savePerspectives(settings)

    def restore_state(self):
        '''
        Restores the dock manager state
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        geom = settings.value("mainWindow/Geometry")
        if geom is not None:
            self.restoreGeometry(geom)

        state = settings.value("mainWindow/State")
        if state is not None:
            self.restoreState(state)

        state = settings.value("mainWindow/DockingState")
        if state is not None:
            self.dock_manager.restore_state(state)

    def restore_perspectives(self):
        '''
        Restore the perspective listo of the dock manager
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        self.dock_manager.loadPerspectives(settings)
        self.perspective_combo_box.clear()
        self.perspective_combo_box.addItems(
            self.dock_manager.perspectiveNames())

    def save_perspective(self):
        perspective_name, ok = QInputDialog.getText(self, 'Save perspective',
                                                    'Enter unique name:')
        if ok and perspective_name:
            self.dock_manager.addPerspective(perspective_name)
            _ = QSignalBlocker(self.perspective_combo_box)
            self.perspective_combo_box.clear()
            self.perspective_combo_box.addItems(
                self.dock_manager.perspectiveNames())
            self.perspective_combo_box.setCurrentText(perspective_name)
            self.save_perspectives()
Beispiel #26
0
    def _initContextMenu(self):
        self._menu = [QMenu("Meter"), QMenu("Grid"), QMenu("Transform")]

        meter_menu = self._menu[0]
        cross_act = QWidgetAction(meter_menu)
        cross_act.setDefaultWidget(self._show_cross_cb)
        meter_menu.addAction(cross_act)

        grid_menu = self._menu[1]
        show_x_act = QWidgetAction(grid_menu)
        show_x_act.setDefaultWidget(self._show_x_grid_cb)
        grid_menu.addAction(show_x_act)
        show_y_act = QWidgetAction(grid_menu)
        show_y_act.setDefaultWidget(self._show_y_grid_cb)
        grid_menu.addAction(show_y_act)
        opacity_act = QWidgetAction(grid_menu)
        widget = QWidget()
        layout = QHBoxLayout()
        layout.addWidget(QLabel("Opacity"))
        layout.addWidget(self._grid_opacity_sld)
        widget.setLayout(layout)
        opacity_act.setDefaultWidget(widget)
        grid_menu.addAction(opacity_act)

        transform_menu = self._menu[2]
        log_x_act = QWidgetAction(transform_menu)
        log_x_act.setDefaultWidget(self._log_x_cb)
        transform_menu.addAction(log_x_act)
        log_y_act = QWidgetAction(transform_menu)
        log_y_act.setDefaultWidget(self._log_y_cb)
        transform_menu.addAction(log_y_act)
Beispiel #27
0
class SystemTray(QSystemTrayIcon):
    def __init__(self, parent=None):
        super(SystemTray, self).__init__(parent)
        self.createActions()
        self.EdgeAction()
        self.UploadAction()
        self.addActions()
        self.setContextMenu(self.menu)

    def showWidget(self):
        if w.isVisible():
            w.hide()
            self.show_action.setIcon(QIcon(QPixmap("./icons/加号.png")))
        else:
            w.showNormal()
            self.show_action.setIcon(QIcon(QPixmap("./icons/减号.png")))

    def exitWidget(self):
        sys.exit(app.exec_())

    def createActions(self):
        self.setIcon(QIcon('./icons/sandbox.png'))
        self.menu = QMenu(QApplication.desktop())
        self.menu.setStyleSheet("QMenu{text-align:center}")
        self.show_action = QWidgetAction(self.menu)
        self.exit_action = QWidgetAction(self.menu)

        self.show_action.triggered.connect(self.showWidget)
        self.exit_action.triggered.connect(self.exitWidget)

        self.show_action.setIcon(QIcon(QPixmap("./icons/减号.png")))
        self.show_action.setIconText("显示主界面")
        self.exit_action.setIcon(QIcon(QPixmap("./icons/关机.png")))
        self.exit_action.setIconText("退出程序")

    def EdgeAction(self):
        edge_widget = QWidget()
        self.edge_action = QWidgetAction(self.menu)
        self.searchLine = QLineEdit()
        self.searchLine.setPlaceholderText('search in sandbox')
        self.searchButton = QPushButton()
        self.searchButton.setIcon(QIcon(QPixmap("./icons/search.png")))
        self.searchButton.setObjectName("searchButton")
        self.searchButton.setIconSize(QSize(18, 18))
        self.searchButton.setStyleSheet("QPushButton{border:2px}")
        self.searchButton.clicked.connect(self.searchInSanbox)
        layout = QGridLayout()
        layout.addWidget(self.searchLine, 1, 1)
        layout.addWidget(self.searchButton, 1, 0)
        edge_widget.setLayout(layout)
        self.edge_action.setDefaultWidget(edge_widget)

    def UploadAction(self):
        upload_widget = QWidget()
        self.upload_action = QWidgetAction(self.menu)
        self.upload_action.setIcon(QIcon(QPixmap("./icons/file.png")))
        self.upload_action.setIconText("加载文件")
        self.upload_action.triggered.connect(self.getfile)
        # self.upload_button = QPushButton("加载文件")
        # self.upload_button.setIcon(QIcon(QPixmap("./icons/file.png")))
        # self.upload_button.setIconSize(QSize(15,15))
        # self.upload_button.setStyleSheet("QPushButton{border:2px}")
        # self.upload_button.clicked.connect(self.getfile)
        # layout = QVBoxLayout()
        # layout.addWidget(self.upload_button)
        # upload_widget.setLayout(layout)
        # self.upload_action.setDefaultWidget(upload_widget)

    def searchInSanbox(self):
        print('hello')
        url = self.searchLine.text()
        if url == '':
            url = 'https://www.baidu.com'
        # self.searchLine.setText(None)
        sendurl(url)

    def getfile(self):
        q_file = QFileDialog()
        q_file.setFileMode(QFileDialog.AnyFile)
        q_file.setFilter(QDir.Files)
        if q_file.exec():
            filenames = q_file.selectedFiles()
            print(filenames[0])
            s = filenames[0]
            sendfile(s)

    def addActions(self):
        self.menu.addAction(self.edge_action)
        self.menu.addAction(self.upload_action)
        self.menu.addAction(self.show_action)
        self.menu.addAction(self.exit_action)
Beispiel #28
0
    def __init__(self, font, parent=None):
        super().__init__(parent)
        auxiliaryWidth = self.fontMetrics().width('0') * 8
        self.leftTextField = MetricsSequenceEdit(font, self)
        self.leftTextField.setMaximumWidth(auxiliaryWidth)
        self.textField = MetricsSequenceComboBox(font, self)
        # XXX: had to use Maximum because Preferred did extend the widget(?)
        self.textField.setSizePolicy(QSizePolicy.Expanding,
                                     QSizePolicy.Maximum)
        self.rightTextField = MetricsSequenceEdit(font, self)
        self.rightTextField.setMaximumWidth(auxiliaryWidth)
        self.leftTextField.textEdited.connect(self.textField.editTextChanged)
        self.rightTextField.textEdited.connect(self.textField.editTextChanged)
        self.textField.editTextChanged.connect(self._textChanged)

        self.comboBox = QComboBox(self)
        self.comboBox.setEditable(True)
        self.comboBox.setCompleter(None)
        self.comboBox.setValidator(QIntValidator(self))
        for p in pointSizes:
            self.comboBox.addItem(str(p))
        self.pointSizeChanged = self.comboBox.currentIndexChanged[str]

        self.configBar = QPushButton(self)
        self.configBar.setFlat(True)
        self.configBar.setIcon(QIcon(":settings.svg"))
        self.configBar.setStyleSheet("padding: 2px 0px; padding-right: 10px")
        self.toolsMenu = QMenu(self)
        self._showKerning = self.toolsMenu.addAction(
            self.tr("Show Kerning"), self._kerningVisibilityChanged)
        self._showKerning.setCheckable(True)
        self._showMetrics = self.toolsMenu.addAction(self.tr("Show Metrics"),
                                                     self._controlsTriggered)
        self._showMetrics.setCheckable(True)
        self.toolsMenu.addSeparator()
        self._verticalFlip = self.toolsMenu.addAction(self.tr("Vertical Flip"),
                                                      self._controlsTriggered)
        self._verticalFlip.setCheckable(True)
        self._wrapLines = self.toolsMenu.addAction(self.tr("Wrap Lines"),
                                                   self._controlsTriggered)
        self._wrapLines.setCheckable(True)
        self.toolsMenu.addSeparator()
        action = self.toolsMenu.addAction(self.tr("Line Height:"))
        action.setEnabled(False)
        lineHeight = QWidgetAction(self.toolsMenu)
        self._lineHeightSlider = slider = QSlider(Qt.Horizontal, self)
        # QSlider works with integers so we'll just divide what comes out of it
        # by 100
        slider.setMinimum(80)
        slider.setMaximum(160)
        slider.setValue(110)
        slider.valueChanged.connect(self._controlsTriggered)
        slider.valueChanged.connect(self._sliderLineHeightChanged)
        lineHeight.setDefaultWidget(slider)
        self.toolsMenu.addAction(lineHeight)
        self.configBar.setMenu(self.toolsMenu)

        self.addWidget(self.leftTextField)
        self.addWidget(self.textField)
        self.addWidget(self.rightTextField)
        self.addWidget(self.comboBox)
        self.addWidget(self.configBar)

        app = QApplication.instance()
        app.dispatcher.addObserver(self, "_currentGlyphChanged",
                                   "currentGlyphChanged")

        self.readSettings()
 def get_widget_action(self, parent):
     wid_action = QWidgetAction(parent)
     wid_action.setDefaultWidget(self)
     return wid_action
Beispiel #30
0
class BeaglesMainWindow(QMainWindow, ActionCallbacks):
    def __init__(self):
        super(BeaglesMainWindow, self).__init__()
        self.io = SharedFlagIO(subprogram=True)

        def createActions(actions: list):
            nonlocal self
            action = partial(newAction, self)
            cmd = 'global {0}; {0} = action("{1}", {2}, {3}, "{4}", "{5}", {6}, {7})'
            for act in actions:
                _str = act
                action_str = getStr(_str)
                shortcut, checkable, enabled = [
                    str(i) for i in self.actionFile[_str]
                ]
                shortcut = '"{}"'.format(
                    shortcut) if shortcut is not None else None
                detail = getStr(_str + "Detail")
                icon = _str
                callback = 'self.' + act
                cmd_string = cmd.format(_str, action_str, callback, shortcut,
                                        icon, detail, checkable, enabled)
                self.io.logger.debug(cmd_string)
                exec(cmd_string)

        with open('beagles/resources/actions/actions.json', 'r') as json_file:
            self.actionFile = json.load(json_file)
        actionList = list(self.actionFile.keys())
        createActions(actionList)
        self.setup()

    def menu(self, title, actions=None):
        menu = self.menuBar().addMenu(title)
        if actions:
            addActions(menu, actions)
        return menu

    def toolbar(self, title, actions=None):
        toolbar = ToolBar(title)
        toolbar.setObjectName(u'%sToolBar' % title)
        toolbar.setMovable(False)
        toolbar.setFixedHeight(32)
        toolbar.setIconSize(QSize(30, 30))
        toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
        if actions:
            addActions(toolbar, actions)
        self.addToolBar(Qt.TopToolBarArea, toolbar)
        return toolbar

    def setup(self):
        self._beginner = True
        self.settings = Settings()
        self.settings.load()
        self.setupZoomWidget()
        self.setupActions()
        self.setupMenus()
        self.setupToolbar()
        self.setupFileDock()
        self.setupLabelDock()
        self.populateMenus()
        self.setupCanvasWidget()
        self.populateModeActions()

    def setupActions(self):
        # Auto saving : Enable auto saving if pressing next
        self.autoSaving = QAction(getStr('autoSaveMode'), self)
        self.autoSaving.setCheckable(True)
        self.autoSaving.setChecked(self.settings.get(SETTING_AUTO_SAVE, False))
        # Sync single class mode from PR#106
        self.singleClassMode = QAction(getStr('singleClsMode'), self)
        self.singleClassMode.setCheckable(True)
        self.singleClassMode.setChecked(
            self.settings.get(SETTING_SINGLE_CLASS, False))
        # Add option to enable/disable labels being displayed at the top of bounding boxes

        self.displayLabelOption = QAction(getStr('displayLabel'), self)
        self.displayLabelOption.setShortcut("Ctrl+Shift+P")
        self.displayLabelOption.setCheckable(True)
        self.displayLabelOption.setChecked(
            self.settings.get(SETTING_PAINT_LABEL, False))
        self.displayLabelOption.triggered.connect(self.togglePaintLabelsOption)

        self.drawSquaresOption = QAction('Draw Squares', self)
        self.drawSquaresOption.setShortcut('Ctrl+Shift+R')
        self.drawSquaresOption.setCheckable(True)
        self.drawSquaresOption.setChecked(
            self.settings.get(SETTING_DRAW_SQUARE, False))
        self.drawSquaresOption.triggered.connect(self.toggleDrawSquare)
        # noinspection PyUnresolvedReferences
        zoomActions = (self.zoomWidget, zoomIn, zoomOut, zoomOrg, setFitWin,
                       setFitWidth)
        # noinspection PyUnresolvedReferences
        self.actions = Struct(
            saveFile=saveFile,
            changeFormat=changeFormat,
            saveAs=saveAs,
            openFile=openFile,
            closeFile=closeFile,
            resetAll=resetAll,
            verifyImg=verifyImg,
            lineColor=boxLineColor,
            create=createShape,
            delBox=delBox,
            editLabel=editLabel,
            copySelectedShape=copySelectedShape,
            trainModel=trainModel,
            visualize=visualize,
            setCreateMode=setCreateMode,
            setEditMode=setEditMode,
            advancedMode=advancedMode,
            shapeLineColor=shapeLineColor,
            shapeFillColor=shapeFillColor,
            zoom=self.zoom,
            zoomIn=zoomIn,
            zoomOut=zoomOut,
            zoomOrg=zoomOrg,
            setFitWin=setFitWin,
            setFitWidth=setFitWidth,
            zoomActions=zoomActions,
            fileMenuActions=(openFile, openDir, impVideo, saveFile, saveAs,
                             commitAnnotatedFrames, trainModel, visualize,
                             closeFile, resetAll, close),
            beginner=(),
            advanced=(),
            editMenu=(editLabel, copySelectedShape, delBox, None, boxLineColor,
                      self.drawSquaresOption),
            beginnerContext=(createShape, editLabel, copySelectedShape,
                             delBox),
            advancedContext=(setCreateMode, setEditMode, editLabel,
                             copySelectedShape, delBox, shapeLineColor,
                             shapeFillColor),
            onLoadActive=(closeFile, createShape, setCreateMode, setEditMode),
            onShapesPresent=(saveAs, hideAll, showAll))

    # noinspection PyUnresolvedReferences
    def populateModeActions(self):
        if self.beginner():
            tool, menu = self.actions.beginner, self.actions.beginnerContext
        else:
            tool, menu = self.actions.advanced, self.actions.advancedContext
        self.tools.clear()
        addActions(self.tools, tool)
        self.canvas.menus[0].clear()
        addActions(self.canvas.menus[0], menu)
        self.menus.edit.clear()
        actions = (self.actions.create,) if self.beginner() \
            else (self.actions.setCreateMode, self.actions.setEditMode,
                  self.actions.verifyImg)
        addActions(self.menus.edit, actions + self.actions.editMenu)

    def setupMenus(self):
        labelMenu = QMenu()
        # noinspection PyUnresolvedReferences
        addActions(labelMenu, (editLabel, delBox))
        self.menus = Struct(file=self.menu('&File'),
                            edit=self.menu('&Edit'),
                            view=self.menu('&View'),
                            machine_learning=self.menu('&Machine Learning'),
                            help=self.menu('&Help'),
                            recentFiles=QMenu('Open &Recent'),
                            labelList=labelMenu)
        # noinspection PyUnresolvedAttribute
        self.menus.file.aboutToShow.connect(self.updateFileMenu)

    def populateMenus(self):
        labels = self.dock.toggleViewAction()
        labels.setText(getStr('showHide'))
        labels.setShortcut('Ctrl+Shift+L')
        # noinspection PyUnresolvedReferences
        addActions(self.menus.file,
                   (openFile, self.menus.recentFiles, openDir, changeSaveDir,
                    impVideo, openAnnotation, saveFile, changeFormat, saveAs,
                    closeFile, resetAll, close))
        # noinspection PyUnresolvedReferences
        addActions(self.menus.help, (showTutorialDialog, showInfo))
        # noinspection PyUnresolvedReferences
        addActions(self.menus.view,
                   (self.autoSaving, self.singleClassMode,
                    self.displayLabelOption, labels, advancedMode, None,
                    prevImg, nextImg, None, hideAll, showAll, None, zoomIn,
                    zoomOut, zoomOrg, None, setFitWin, setFitWidth))
        # noinspection PyUnresolvedReferences
        addActions(self.menus.machine_learning,
                   (commitAnnotatedFrames, trainModel, visualize, None))

    def setupToolbar(self):
        self.tools = self.toolbar('Tools')
        # noinspection PyUnresolvedReferences
        self.actions.beginner = (openFile, openDir, changeSaveDir, saveFile,
                                 None, createShape, copySelectedShape, delBox,
                                 None, prevImg, nextImg, None, zoomIn,
                                 self.zoom, zoomOut, setFitWin, setFitWidth)

        # noinspection PyUnresolvedReferences
        self.actions.advanced = (openFile, saveFile, None, setCreateMode,
                                 setEditMode, verifyImg, None, hideAll,
                                 showAll, None, commitAnnotatedFrames,
                                 trainModel, visualize, impVideo)

    def setupFileDock(self):
        self.fileListWidget = QListWidget()
        self.fileListWidget.itemDoubleClicked.connect(
            self.fileitemDoubleClicked)
        filelistLayout = QVBoxLayout()
        filelistLayout.setContentsMargins(0, 0, 0, 0)
        filelistLayout.addWidget(self.fileListWidget)
        fileListContainer = QWidget()
        fileListContainer.setLayout(filelistLayout)
        self.filedock = QDockWidget(getStr('fileList'), self)
        self.filedock.setObjectName(getStr('files'))
        self.filedock.setWidget(fileListContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.filedock)
        self.filedock.setFeatures(QDockWidget.DockWidgetFloatable)

    def setupLabelDock(self):
        listLayout = QVBoxLayout()
        listLayout.setContentsMargins(0, 0, 0, 0)
        self.editButton = QToolButton()
        self.editButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        # noinspection PyUnresolvedReferences
        self.editButton.setDefaultAction(editLabel)
        # Create a widget for edit and diffc button
        self.difficultButton = QCheckBox(getStr('useDifficult'))
        self.difficultButton.setChecked(False)
        self.difficultButton.stateChanged.connect(self.buttonState)
        self.labelList = QListWidget()
        labelListContainer = QWidget()
        labelListContainer.setLayout(listLayout)
        self.labelList.itemActivated.connect(self.labelSelectionChanged)
        self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged)
        self.labelList.itemDoubleClicked.connect(self.editLabel)
        # Connect to itemChanged to detect checkbox changes.
        self.labelList.itemChanged.connect(self.labelItemChanged)
        listLayout.addWidget(self.labelList)
        self.dock = QDockWidget(getStr('boxLabelText'), self)
        self.dock.setObjectName(getStr('labels'))
        self.dock.setWidget(labelListContainer)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
        self.dockFeatures = \
            QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable
        # noinspection PyTypeChecker
        self.dock.setFeatures(self.dock.features() ^ self.dockFeatures)
        self.useDefaultLabelCheckbox = QCheckBox(getStr('useDefaultLabel'))
        self.useDefaultLabelCheckbox.setChecked(False)
        self.defaultLabelTextLine = QLineEdit()
        useDefaultLabelQHBoxLayout = QHBoxLayout()
        useDefaultLabelQHBoxLayout.addWidget(self.useDefaultLabelCheckbox)
        useDefaultLabelQHBoxLayout.addWidget(self.defaultLabelTextLine)
        useDefaultLabelContainer = QWidget()
        useDefaultLabelContainer.setLayout(useDefaultLabelQHBoxLayout)
        # Add some of widgets to listLayout
        listLayout.addWidget(self.editButton)
        listLayout.addWidget(self.difficultButton)
        listLayout.addWidget(useDefaultLabelContainer)
        self.lastLabel = None

    def setupZoomWidget(self):
        self.zoom = QWidgetAction(self)
        self.zoomWidget = ZoomWidget()
        self.zoom.setDefaultWidget(self.zoomWidget)
        self.zoomWidget.setEnabled(False)

    def setupCanvasWidget(self):
        action = partial(newAction, self)
        # Create and add a widget for showing current label items
        self.canvas = Canvas(parent=self)
        self.canvas.zoomRequest.connect(self.zoomRequest)
        self.canvas.setDrawingShapeToSquare(
            self.settings.get(SETTING_DRAW_SQUARE, False))
        self.canvas.scrollRequest.connect(self.scrollRequest)

        self.canvas.newShape.connect(self.newShape)
        self.canvas.shapeMoved.connect(self.setDirty)
        self.canvas.selectionChanged.connect(self.shapeSelectionChanged)
        self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive)
        # Custom context menu for the canvas widget:
        # noinspection PyUnresolvedReferences
        addActions(self.canvas.menus[0], self.actions.beginnerContext)
        addActions(self.canvas.menus[1],
                   (action('&Copy here', self.copyShape),
                    action('&Move here', self.moveShape)))

    def resetState(self):
        self.itemsToShapes.clear()
        self.shapesToItems.clear()
        self.labelList.clear()
        self.filePath = None
        self.imageData = None
        self.labelFile = None
        self.canvas.resetState()
        self.labelCoordinates.clear()

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Control:
            self.canvas.setDrawingShapeToSquare(False)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Control:
            # Draw rectangle if Ctrl is pressed
            self.canvas.setDrawingShapeToSquare(True)

    def resizeEvent(self, event):
        if self.canvas and not self.image.isNull() \
                and self.zoomMode != self.MANUAL_ZOOM:
            self.adjustScale()
        super(BeaglesMainWindow, self).resizeEvent(event)

    def closeEvent(self, event):
        for handler in self.io.logger.handlers:
            handler.doRollover()
        if not self.mayContinue():
            event.ignore()
        if self.tb_process.pid() > 0:
            self.tb_process.kill()
        settings = self.settings
        # If it loads images from dir, don't load it at the beginning
        if self.dirname is None:
            settings[SETTING_FILENAME] = self.filePath if self.filePath else ''
        else:
            settings[SETTING_FILENAME] = ''
        settings[SETTING_WIN_SIZE] = self.size()
        settings[SETTING_WIN_POSE] = self.pos()
        settings[SETTING_WIN_STATE] = self.saveState()
        settings[SETTING_LINE_COLOR] = self.lineColor
        settings[SETTING_FILL_COLOR] = self.fillColor
        settings[SETTING_RECENT_FILES] = self.recentFiles
        settings[SETTING_ADVANCE_MODE] = not self._beginner

        if self.defaultSaveDir and os.path.exists(self.defaultSaveDir):
            settings[SETTING_SAVE_DIR] = str(self.defaultSaveDir)
        else:
            settings[SETTING_SAVE_DIR] = ''

        if self.lastOpenDir and os.path.exists(self.lastOpenDir):
            settings[SETTING_LAST_OPEN_DIR] = self.lastOpenDir
        else:
            settings[SETTING_LAST_OPEN_DIR] = ''

        settings[SETTING_AUTO_SAVE] = self.autoSaving.isChecked()
        settings[SETTING_SINGLE_CLASS] = self.singleClassMode.isChecked()
        settings[SETTING_PAINT_LABEL] = self.displayLabelOption.isChecked()
        settings[SETTING_DRAW_SQUARE] = self.drawSquaresOption.isChecked()
        settings.save()
Beispiel #31
0
    def makePopupMenu(self):
        index = self.currentIndex()
        sel = self.getSelection()
        clipboard = qApp.clipboard()

        menu = QMenu(self)

        # Get index under cursor
        pos = self.viewport().mapFromGlobal(QCursor.pos())
        mouseIndex = self.indexAt(pos)

        # Get index's title
        if mouseIndex.isValid():
            title = mouseIndex.internalPointer().title()

        elif self.rootIndex().parent().isValid():
            # mouseIndex is the background of an item, so we check the parent
            mouseIndex = self.rootIndex().parent()
            title = mouseIndex.internalPointer().title()

        else:
            title = qApp.translate("outlineBasics", "Root")

        if len(title) > 25:
            title = title[:25] + "…"

        # Open Item action
        self.actOpen = QAction(QIcon.fromTheme("go-right"),
                               qApp.translate("outlineBasics", "Open {}".format(title)),
                               menu)
        self.actOpen.triggered.connect(self.openItem)
        menu.addAction(self.actOpen)

        # Open item(s) in new tab
        if mouseIndex in sel and len(sel) > 1:
            actionTitle = qApp.translate("outlineBasics", "Open {} items in new tabs").format(len(sel))
            self._indexesToOpen = sel
        else:
            actionTitle = qApp.translate("outlineBasics", "Open {} in a new tab").format(title)
            self._indexesToOpen = [mouseIndex]

        self.actNewTab = QAction(QIcon.fromTheme("go-right"), actionTitle, menu)
        self.actNewTab.triggered.connect(self.openItemsInNewTabs)
        menu.addAction(self.actNewTab)

        menu.addSeparator()

        # Add text / folder
        self.actAddFolder = QAction(QIcon.fromTheme("folder-new"),
                                    qApp.translate("outlineBasics", "New &Folder"),
                                    menu)
        self.actAddFolder.triggered.connect(self.addFolder)
        menu.addAction(self.actAddFolder)

        self.actAddText = QAction(QIcon.fromTheme("document-new"),
                                  qApp.translate("outlineBasics", "New &Text"),
                                  menu)
        self.actAddText.triggered.connect(self.addText)
        menu.addAction(self.actAddText)

        menu.addSeparator()

        # Copy, cut, paste, duplicate
        self.actCut = QAction(QIcon.fromTheme("edit-cut"),
                              qApp.translate("outlineBasics", "C&ut"), menu)
        self.actCut.triggered.connect(self.cut)
        menu.addAction(self.actCut)

        self.actCopy = QAction(QIcon.fromTheme("edit-copy"),
                               qApp.translate("outlineBasics", "&Copy"), menu)
        self.actCopy.triggered.connect(self.copy)
        menu.addAction(self.actCopy)

        self.actPaste = QAction(QIcon.fromTheme("edit-paste"),
                                qApp.translate("outlineBasics", "&Paste"), menu)
        self.actPaste.triggered.connect(self.paste)
        menu.addAction(self.actPaste)

        # Rename / duplicate / remove items
        self.actDelete = QAction(QIcon.fromTheme("edit-delete"),
                                 qApp.translate("outlineBasics", "&Delete"),
                                 menu)
        self.actDelete.triggered.connect(self.delete)
        menu.addAction(self.actDelete)

        self.actRename = QAction(QIcon.fromTheme("edit-rename"),
                                 qApp.translate("outlineBasics", "&Rename"),
                                 menu)
        self.actRename.triggered.connect(self.rename)
        menu.addAction(self.actRename)

        menu.addSeparator()

        # POV
        self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu)
        mw = mainWindow()
        a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuPOV)
        a.triggered.connect(lambda: self.setPOV(""))
        self.menuPOV.addAction(a)
        self.menuPOV.addSeparator()

        menus = []
        for i in [qApp.translate("outlineBasics", "Main"),
                  qApp.translate("outlineBasics", "Secondary"),
                  qApp.translate("outlineBasics", "Minor")]:
            m = QMenu(i, self.menuPOV)
            menus.append(m)
            self.menuPOV.addMenu(m)

        mpr = QSignalMapper(self.menuPOV)
        for i in range(mw.mdlCharacter.rowCount()):
            a = QAction(mw.mdlCharacter.icon(i), mw.mdlCharacter.name(i), self.menuPOV)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(mw.mdlCharacter.ID(i)))

            imp = toInt(mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        mpr.mapped.connect(self.setPOV)
        menu.addMenu(self.menuPOV)

        # Status
        self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"), menu)
        # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
        # a.triggered.connect(lambda: self.setStatus(""))
        # self.menuStatus.addAction(a)
        # self.menuStatus.addSeparator()

        mpr = QSignalMapper(self.menuStatus)
        for i in range(mw.mdlStatus.rowCount()):
            a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuStatus.addAction(a)
        mpr.mapped.connect(self.setStatus)
        menu.addMenu(self.menuStatus)

        # Labels
        self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"), menu)
        mpr = QSignalMapper(self.menuLabel)
        for i in range(mw.mdlLabels.rowCount()):
            a = QAction(mw.mdlLabels.item(i, 0).icon(),
                        mw.mdlLabels.item(i, 0).text(),
                        self.menuLabel)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuLabel.addAction(a)
        mpr.mapped.connect(self.setLabel)
        menu.addMenu(self.menuLabel)

        menu.addSeparator()

        # Custom icons
        if self.menuCustomIcons:
            menu.addMenu(self.menuCustomIcons)
        else:
            self.menuCustomIcons = QMenu(qApp.translate("outlineBasics", "Set Custom Icon"), menu)
            a = QAction(qApp.translate("outlineBasics", "Restore to default"), self.menuCustomIcons)
            a.triggered.connect(lambda: self.setCustomIcon(""))
            self.menuCustomIcons.addAction(a)
            self.menuCustomIcons.addSeparator()

            txt = QLineEdit()
            txt.textChanged.connect(self.filterLstIcons)
            txt.setPlaceholderText("Filter icons")
            txt.setStyleSheet("QLineEdit { background: transparent; border: none; }")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(txt)
            self.menuCustomIcons.addAction(act)

            self.lstIcons = QListWidget()
            for i in customIcons():
                item = QListWidgetItem()
                item.setIcon(QIcon.fromTheme(i))
                item.setData(Qt.UserRole, i)
                item.setToolTip(i)
                self.lstIcons.addItem(item)
            self.lstIcons.itemClicked.connect(self.setCustomIconFromItem)
            self.lstIcons.setViewMode(self.lstIcons.IconMode)
            self.lstIcons.setUniformItemSizes(True)
            self.lstIcons.setResizeMode(self.lstIcons.Adjust)
            self.lstIcons.setMovement(self.lstIcons.Static)
            self.lstIcons.setStyleSheet("background: transparent; background: none;")
            self.filterLstIcons("")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(self.lstIcons)
            self.menuCustomIcons.addAction(act)

            menu.addMenu(self.menuCustomIcons)

        # Disabling stuff
        if not clipboard.mimeData().hasFormat("application/xml"):
            self.actPaste.setEnabled(False)

        if len(sel) == 0:
            self.actCopy.setEnabled(False)
            self.actCut.setEnabled(False)
            self.actRename.setEnabled(False)
            self.actDelete.setEnabled(False)
            self.menuPOV.setEnabled(False)
            self.menuStatus.setEnabled(False)
            self.menuLabel.setEnabled(False)
            self.menuCustomIcons.setEnabled(False)

        if len(sel) > 1:
            self.actRename.setEnabled(False)

        return menu
Beispiel #32
0
    def makePopupMenu(self):
        index = self.currentIndex()
        sel = self.getSelection()
        clipboard = qApp.clipboard()

        menu = QMenu(self)

        # Get index under cursor
        pos = self.viewport().mapFromGlobal(QCursor.pos())
        mouseIndex = self.indexAt(pos)

        # Get index's title
        if mouseIndex.isValid():
            title = mouseIndex.internalPointer().title()

        elif self.rootIndex().parent().isValid():
            # mouseIndex is the background of an item, so we check the parent
            mouseIndex = self.rootIndex().parent()
            title = mouseIndex.internalPointer().title()

        else:
            title = qApp.translate("outlineBasics", "Root")

        if len(title) > 25:
            title = title[:25] + "…"

        # Open Item action
        self.actOpen = QAction(
            QIcon.fromTheme("go-right"),
            qApp.translate("outlineBasics", "Open {}".format(title)), menu)
        self.actOpen.triggered.connect(self.openItem)
        menu.addAction(self.actOpen)

        # Open item(s) in new tab
        if mouseIndex in sel and len(sel) > 1:
            actionTitle = qApp.translate("outlineBasics",
                                         "Open {} items in new tabs").format(
                                             len(sel))
            self._indexesToOpen = sel
        else:
            actionTitle = qApp.translate("outlineBasics",
                                         "Open {} in a new tab").format(title)
            self._indexesToOpen = [mouseIndex]

        self.actNewTab = QAction(QIcon.fromTheme("go-right"), actionTitle,
                                 menu)
        self.actNewTab.triggered.connect(self.openItemsInNewTabs)
        menu.addAction(self.actNewTab)

        menu.addSeparator()

        # Add text / folder
        self.actAddFolder = QAction(
            QIcon.fromTheme("folder-new"),
            qApp.translate("outlineBasics", "New &Folder"), menu)
        self.actAddFolder.triggered.connect(self.addFolder)
        menu.addAction(self.actAddFolder)

        self.actAddText = QAction(QIcon.fromTheme("document-new"),
                                  qApp.translate("outlineBasics", "New &Text"),
                                  menu)
        self.actAddText.triggered.connect(self.addText)
        menu.addAction(self.actAddText)

        menu.addSeparator()

        # Copy, cut, paste, duplicate
        self.actCut = QAction(QIcon.fromTheme("edit-cut"),
                              qApp.translate("outlineBasics", "C&ut"), menu)
        self.actCut.triggered.connect(self.cut)
        menu.addAction(self.actCut)

        self.actCopy = QAction(QIcon.fromTheme("edit-copy"),
                               qApp.translate("outlineBasics", "&Copy"), menu)
        self.actCopy.triggered.connect(self.copy)
        menu.addAction(self.actCopy)

        self.actPaste = QAction(QIcon.fromTheme("edit-paste"),
                                qApp.translate("outlineBasics", "&Paste"),
                                menu)
        self.actPaste.triggered.connect(self.paste)
        menu.addAction(self.actPaste)

        # Rename / duplicate / remove items
        self.actDelete = QAction(QIcon.fromTheme("edit-delete"),
                                 qApp.translate("outlineBasics", "&Delete"),
                                 menu)
        self.actDelete.triggered.connect(self.delete)
        menu.addAction(self.actDelete)

        self.actRename = QAction(QIcon.fromTheme("edit-rename"),
                                 qApp.translate("outlineBasics", "&Rename"),
                                 menu)
        self.actRename.triggered.connect(self.rename)
        menu.addAction(self.actRename)

        menu.addSeparator()

        # POV
        self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu)
        mw = mainWindow()
        a = QAction(QIcon.fromTheme("dialog-no"),
                    qApp.translate("outlineBasics", "None"), self.menuPOV)
        a.triggered.connect(lambda: self.setPOV(""))
        self.menuPOV.addAction(a)
        self.menuPOV.addSeparator()

        menus = []
        for i in [
                qApp.translate("outlineBasics", "Main"),
                qApp.translate("outlineBasics", "Secondary"),
                qApp.translate("outlineBasics", "Minor")
        ]:
            m = QMenu(i, self.menuPOV)
            menus.append(m)
            self.menuPOV.addMenu(m)

        mpr = QSignalMapper(self.menuPOV)
        for i in range(mw.mdlCharacter.rowCount()):
            a = QAction(mw.mdlCharacter.icon(i), mw.mdlCharacter.name(i),
                        self.menuPOV)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(mw.mdlCharacter.ID(i)))

            imp = toInt(mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        mpr.mapped.connect(self.setPOV)
        menu.addMenu(self.menuPOV)

        # Status
        self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"),
                                menu)
        # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
        # a.triggered.connect(lambda: self.setStatus(""))
        # self.menuStatus.addAction(a)
        # self.menuStatus.addSeparator()

        mpr = QSignalMapper(self.menuStatus)
        for i in range(mw.mdlStatus.rowCount()):
            a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuStatus.addAction(a)
        mpr.mapped.connect(self.setStatus)
        menu.addMenu(self.menuStatus)

        # Labels
        self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"),
                               menu)
        mpr = QSignalMapper(self.menuLabel)
        for i in range(mw.mdlLabels.rowCount()):
            a = QAction(
                mw.mdlLabels.item(i, 0).icon(),
                mw.mdlLabels.item(i, 0).text(), self.menuLabel)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuLabel.addAction(a)
        mpr.mapped.connect(self.setLabel)
        menu.addMenu(self.menuLabel)

        menu.addSeparator()

        # Custom icons
        if self.menuCustomIcons:
            menu.addMenu(self.menuCustomIcons)
        else:
            self.menuCustomIcons = QMenu(
                qApp.translate("outlineBasics", "Set Custom Icon"), menu)
            a = QAction(qApp.translate("outlineBasics", "Restore to default"),
                        self.menuCustomIcons)
            a.triggered.connect(lambda: self.setCustomIcon(""))
            self.menuCustomIcons.addAction(a)
            self.menuCustomIcons.addSeparator()

            txt = QLineEdit()
            txt.textChanged.connect(self.filterLstIcons)
            txt.setPlaceholderText("Filter icons")
            txt.setStyleSheet("background: transparent; border: none;")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(txt)
            self.menuCustomIcons.addAction(act)

            self.lstIcons = QListWidget()
            for i in customIcons():
                item = QListWidgetItem()
                item.setIcon(QIcon.fromTheme(i))
                item.setData(Qt.UserRole, i)
                item.setToolTip(i)
                self.lstIcons.addItem(item)
            self.lstIcons.itemClicked.connect(self.setCustomIconFromItem)
            self.lstIcons.setViewMode(self.lstIcons.IconMode)
            self.lstIcons.setUniformItemSizes(True)
            self.lstIcons.setResizeMode(self.lstIcons.Adjust)
            self.lstIcons.setMovement(self.lstIcons.Static)
            self.lstIcons.setStyleSheet(
                "background: transparent; background: none;")
            self.filterLstIcons("")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(self.lstIcons)
            self.menuCustomIcons.addAction(act)

            menu.addMenu(self.menuCustomIcons)

        # Disabling stuff
        if not clipboard.mimeData().hasFormat("application/xml"):
            self.actPaste.setEnabled(False)

        if len(sel) == 0:
            self.actCopy.setEnabled(False)
            self.actCut.setEnabled(False)
            self.actRename.setEnabled(False)
            self.actDelete.setEnabled(False)
            self.menuPOV.setEnabled(False)
            self.menuStatus.setEnabled(False)
            self.menuLabel.setEnabled(False)
            self.menuCustomIcons.setEnabled(False)

        if len(sel) > 1:
            self.actRename.setEnabled(False)

        return menu
Beispiel #33
0
class MainWindow(MainWindowUI, MainWindowBase):
    save_perspective_action: QAction
    perspective_list_action: QWidgetAction
    perspective_combo_box: QComboBox
    dock_manager: QtAds.CDockManager

    def __init__(self, parent=None):
        super().__init__(parent)
        self.save_perspective_action = None
        self.perspective_list_action = None
        self.perspective_combo_box = None
        self.dock_manager = None

        self.setupUi(self)
        self.create_actions()

        # uncomment the following line if the tab close button should be
        # a QToolButton instead of a QPushButton
        # QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.configFlags() | QtAds.CDockManager.TabCloseButtonIsToolButton)

        # uncomment the following line if you want to use opaque undocking and
        # opaque splitter resizing
        #QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.DefaultOpaqueConfig);

        # uncomment the following line if you want a fixed tab width that does
        # not change if the visibility of the close button changes
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.RetainTabSizeWhenCloseButtonHidden, True)

        # uncomment the following line if you don't want close button on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHasCloseButton, false);

        # uncomment the following line if you don't want undock button on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHasUndockButton, false);

        # uncomment the following line if you don't want tabs menu button on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHasTabsMenuButton, false);

        # uncomment the following line if you don't want disabled buttons to appear on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHideDisabledButtons, true);

        # uncomment the following line if you want to show tabs menu button on DockArea's title bar only when there are more than one tab and at least of them has elided title
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaDynamicTabsMenuButtonVisibility, true);

        # uncomment the following line if you want floating container to always show application title instead of active dock widget's title
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FloatingContainerHasWidgetTitle, false);

        # uncomment the following line if you want floating container to show active dock widget's icon instead of always showing application icon
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FloatingContainerHasWidgetIcon, true);

        # uncomment the following line if you want a central widget in the main dock container (the dock manager) without a titlebar
        # If you enable this code, you can test it in the demo with the Calendar 0
        # dock widget.
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.HideSingleCentralWidgetTitleBar, true);

        # Now create the dock manager and its content
        self.dock_manager = QtAds.CDockManager(self)

        # Uncomment the following line to have the old style where the dock
        # area close button closes the active tab
        # QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.DockAreaHasCloseButton
        # | QtAds.CDockManager.DockAreaCloseButtonClosesTab)
        self.perspective_combo_box.activated[str].connect(
            self.dock_manager.openPerspective)

        self.create_content()
        # Default window geometry - center on screen
        self.resize(1280, 720)
        self.setGeometry(
            QStyle.alignedRect(
                Qt.LeftToRight, Qt.AlignCenter, self.frameSize(),
                QGuiApplication.primaryScreen().availableGeometry()))

        # self.restore_state()
        self.restore_perspectives()

    def create_content(self):
        # Test container docking
        view_menu = self.menuView
        dock_widget = create_calendar_dock_widget(view_menu)
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
        special_dock_area = self.dock_manager.addDockWidget(
            QtAds.LeftDockWidgetArea, dock_widget)

        # For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified):
        special_dock_area.setAllowedAreas(QtAds.OuterDockAreas)
        # special_dock_area.setAllowedAreas(QtAds.LeftDockWidgetArea | QtAds.RightDockWidgetArea) # just for testing

        self.dock_manager.addDockWidget(
            QtAds.LeftDockWidgetArea,
            create_long_text_label_dock_widget(view_menu))
        file_system_widget = create_file_system_tree_dock_widget(view_menu)
        tool_bar = file_system_widget.createDefaultToolBar()
        tool_bar.addAction(self.actionSaveState)
        tool_bar.addAction(self.actionRestoreState)
        file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable,
                                      False)
        append_feature_string_to_window_title(file_system_widget)
        self.dock_manager.addDockWidget(QtAds.BottomDockWidgetArea,
                                        file_system_widget)

        file_system_widget = create_file_system_tree_dock_widget(view_menu)
        tool_bar = file_system_widget.createDefaultToolBar()
        tool_bar.addAction(self.actionSaveState)
        tool_bar.addAction(self.actionRestoreState)
        file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable,
                                      False)
        file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable,
                                      False)
        append_feature_string_to_window_title(file_system_widget)

        # Test custom factory - we inject a help button into the title bar
        QtAds.CDockComponentsFactory.setFactory(CCustomComponentsFactory())
        top_dock_area = self.dock_manager.addDockWidget(
            QtAds.TopDockWidgetArea, file_system_widget)
        QtAds.CDockComponentsFactory.resetDefaultFactory()

        # We create a calendar widget and clear all flags to prevent the dock area
        # from closing
        dock_widget = create_calendar_dock_widget(view_menu)
        dock_widget.setTabToolTip("Tab ToolTip\nHodie est dies magna")
        dock_area = self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea,
                                                    dock_widget, top_dock_area)

        # Now we add a custom button to the dock area title bar that will create
        # new editor widgets when clicked
        custom_button = QToolButton(dock_area)
        custom_button.setToolTip("Create Editor")
        custom_button.setIcon(svg_icon(":/adsdemo/images/plus.svg"))
        custom_button.setAutoRaise(True)

        title_bar = dock_area.titleBar()
        index = title_bar.indexOf(title_bar.tabBar())
        title_bar.insertWidget(index + 1, custom_button)

        def on_button_clicked():
            dock_widget = create_editor_widget(self.menuView)
            dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose,
                                   True)
            self.dock_manager.addDockWidgetTabToArea(dock_widget, dock_area)
            dock_widget.closeRequested.connect(self.on_editor_close_requested)

        custom_button.clicked.connect(on_button_clicked)

        # Test dock area docking
        right_dock_area = self.dock_manager.addDockWidget(
            QtAds.RightDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), top_dock_area)
        self.dock_manager.addDockWidget(
            QtAds.TopDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), right_dock_area)

        bottom_dock_area = self.dock_manager.addDockWidget(
            QtAds.BottomDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), right_dock_area)

        self.dock_manager.addDockWidget(
            QtAds.CenterDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), right_dock_area)
        self.dock_manager.addDockWidget(
            QtAds.CenterDockWidgetArea,
            create_long_text_label_dock_widget(view_menu), bottom_dock_area)

        action = self.menuTests.addAction("Set {} Floating".format(
            dock_widget.windowTitle()))
        action.triggered.connect(dock_widget.setFloating)
        action = self.menuTests.addAction("Set {} As Current Tab".format(
            dock_widget.windowTitle()))
        action.triggered.connect(dock_widget.setAsCurrentTab)
        action = self.menuTests.addAction("Raise {}".format(
            dock_widget.windowTitle()))
        action.triggered.connect(dock_widget.raise_)

        if ACTIVEX_AVAILABLE:
            flags = self.dock_manager.configFlags()
            if flags & QtAds.CDockManager.OpaqueUndocking:
                self.dock_manager.addDockWidget(
                    QtAds.CenterDockWidgetArea,
                    create_activex_widget(view_menu), right_dock_area)

        for dock_widget in self.dock_manager.dockWidgetsMap().values():
            dock_widget.viewToggled.connect(self.on_view_toggled)
            dock_widget.visibilityChanged.connect(
                self.on_view_visibility_changed)

    def create_actions(self):
        self.toolBar.addAction(self.actionSaveState)
        self.toolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.actionSaveState.setIcon(svg_icon(":/adsdemo/images/save.svg"))
        self.toolBar.addAction(self.actionRestoreState)
        self.actionRestoreState.setIcon(
            svg_icon(":/adsdemo/images/restore.svg"))

        self.save_perspective_action = QAction("Create Perspective", self)
        self.save_perspective_action.setIcon(
            svg_icon(":/adsdemo/images/picture_in_picture.svg"))
        self.save_perspective_action.triggered.connect(self.save_perspective)
        self.perspective_list_action = QWidgetAction(self)
        self.perspective_combo_box = QComboBox(self)
        self.perspective_combo_box.setSizeAdjustPolicy(
            QComboBox.AdjustToContents)
        self.perspective_combo_box.setSizePolicy(QSizePolicy.Preferred,
                                                 QSizePolicy.Preferred)
        self.perspective_list_action.setDefaultWidget(
            self.perspective_combo_box)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.perspective_list_action)
        self.toolBar.addAction(self.save_perspective_action)

        a = self.toolBar.addAction("Create Floating Editor")
        a.setProperty("Floating", True)
        a.setToolTip(
            "Creates floating dynamic dockable editor windows that are deleted on close"
        )
        a.setIcon(svg_icon(":/adsdemo/images/note_add.svg"))
        a.triggered.connect(self.create_editor)
        self.menuTests.addAction(a)

        a = self.toolBar.addAction("Create Docked Editor")
        a.setProperty("Floating", False)
        a.setToolTip(
            "Creates a docked editor windows that are deleted on close")
        a.setIcon(svg_icon(":/adsdemo/images/docked_editor.svg"))
        a.triggered.connect(self.create_editor)
        self.menuTests.addAction(a)

        a = self.toolBar.addAction("Create Floating Table")
        a.setToolTip(
            "Creates floating dynamic dockable table with millions of entries")
        a.setIcon(svg_icon(":/adsdemo/images/grid_on.svg"))
        a.triggered.connect(self.create_table)
        self.menuTests.addAction(a)

        self.menuTests.addSeparator()
        a = self.menuTests.addAction("Show Status Dialog")
        a.triggered.connect(self.show_status_dialog)
        self.menuTests.addSeparator()

    def closeEvent(self, event: QCloseEvent):
        self.save_state()
        super().closeEvent(event)

    def on_actionSaveState_triggered(self, state: bool):
        qDebug("MainWindow::on_action_save_state_triggered")
        self.save_state()

    def on_actionRestoreState_triggered(self, state: bool):
        qDebug("MainWindow::on_action_restore_state_triggered")
        self.restore_state()

    def save_perspective(self):
        perspective_name, ok = QInputDialog.getText(self, "Save perspective",
                                                    "Enter unique name:")

        if ok and perspective_name:
            self.dock_manager.addPerspective(perspective_name)
            _ = QSignalBlocker(self.perspective_combo_box)
            self.perspective_combo_box.clear()
            self.perspective_combo_box.addItems(
                self.dock_manager.perspectiveNames())
            self.perspective_combo_box.setCurrentText(perspective_name)

            self.save_perspectives()

    def on_view_toggled(self, open: bool):
        dock_widget = self.sender()
        if dock_widget is None:
            return

        qDebug("{} view_toggled({})".format(dock_widget.objectName(), open))

    def on_view_visibility_changed(self, visible: bool):
        dock_widget = self.sender()
        if dock_widget is None:
            return

        qDebug("{} visibility_changed({})".format(dock_widget.objectName(),
                                                  visible))

    def create_editor(self):
        sender = self.sender()
        floating = sender.property("Floating")
        print("Floating:", floating)
        dock_widget = create_editor_widget(self.menuView)
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
        dock_widget.closeRequested.connect(self.on_editor_close_requested)

        if floating:
            floating_widget = self.dock_manager.addDockWidgetFloating(
                dock_widget)
            floating_widget.move(QPoint(20, 20))
        else:
            self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea,
                                            dock_widget)

    def on_editor_close_requested(self):
        dock_widget = self.sender()
        result = QMessageBox.question(
            self, "Close Editor",
            "Editor {} contains unsaved changes? Would you like to close it?".
            format(dock_widget.windowTitle()))
        if result == QMessageBox.Yes:
            dock_widget.closeDockWidget()

    def create_table(self):
        dock_widget = create_table_widget(self.menuView)
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
        floating_widget = self.dock_manager.addDockWidgetFloating(dock_widget)
        floating_widget.move(QPoint(40, 40))

    def show_status_dialog(self):
        dialog = CStatusDialog(self.dock_manager)
        dialog.exec_()

    def save_state(self):
        '''
        Saves the dock manager state and the main window geometry
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        settings.setValue("mainWindow/Geometry", self.saveGeometry())
        settings.setValue("mainWindow/State", self.saveState())
        settings.setValue("mainWindow/DockingState",
                          self.dock_manager.saveState())

    def restore_state(self):
        '''
        Restores the dock manager state
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        geom = settings.value("mainWindow/Geometry")
        if geom is not None:
            self.restoreGeometry(geom)

        state = settings.value("mainWindow/State")
        if state is not None:
            self.restoreState(state)

        state = settings.value("mainWindow/DockingState")
        if state is not None:
            self.dock_manager.restore_state(state)

    def save_perspectives(self):
        '''
        Save the list of perspectives
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        self.dock_manager.savePerspectives(settings)

    def restore_perspectives(self):
        '''
        Restore the perspective listo of the dock manager
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        self.dock_manager.loadPerspectives(settings)
        self.perspective_combo_box.clear()
        self.perspective_combo_box.addItems(
            self.dock_manager.perspectiveNames())

    def save_perspective(self):
        perspective_name, ok = QInputDialog.getText(self, 'Save perspective',
                                                    'Enter unique name:')
        if ok and perspective_name:
            self.dock_manager.addPerspective(perspective_name)
            _ = QSignalBlocker(self.perspective_combo_box)
            self.perspective_combo_box.clear()
            self.perspective_combo_box.addItems(
                self.dock_manager.perspectiveNames())
            self.perspective_combo_box.setCurrentText(perspective_name)
            self.save_perspectives()
Beispiel #34
0
    def makePopupMenu(self):
        index = self.currentIndex()
        sel = self.getSelection()
        clipboard = qApp.clipboard()

        menu = QMenu(self)

        # Add / remove items
        self.actOpen = QAction(QIcon.fromTheme("go-right"),
                               qApp.translate("outlineBasics", "Open Item"),
                               menu)
        self.actOpen.triggered.connect(self.openItem)
        menu.addAction(self.actOpen)

        menu.addSeparator()

        # Add / remove items
        self.actAddFolder = QAction(
            QIcon.fromTheme("folder-new"),
            qApp.translate("outlineBasics", "New Folder"), menu)
        self.actAddFolder.triggered.connect(self.addFolder)
        menu.addAction(self.actAddFolder)

        self.actAddText = QAction(QIcon.fromTheme("document-new"),
                                  qApp.translate("outlineBasics", "New Text"),
                                  menu)
        self.actAddText.triggered.connect(self.addText)
        menu.addAction(self.actAddText)

        self.actDelete = QAction(QIcon.fromTheme("edit-delete"),
                                 qApp.translate("outlineBasics", "Delete"),
                                 menu)
        self.actDelete.triggered.connect(self.delete)
        menu.addAction(self.actDelete)

        menu.addSeparator()

        # Copy, cut, paste
        self.actCopy = QAction(QIcon.fromTheme("edit-copy"),
                               qApp.translate("outlineBasics", "Copy"), menu)
        self.actCopy.triggered.connect(self.copy)
        menu.addAction(self.actCopy)

        self.actCut = QAction(QIcon.fromTheme("edit-cut"),
                              qApp.translate("outlineBasics", "Cut"), menu)
        self.actCut.triggered.connect(self.cut)
        menu.addAction(self.actCut)

        self.actPaste = QAction(QIcon.fromTheme("edit-paste"),
                                qApp.translate("outlineBasics", "Paste"), menu)
        self.actPaste.triggered.connect(self.paste)
        menu.addAction(self.actPaste)

        menu.addSeparator()

        # POV
        self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu)
        mw = mainWindow()
        a = QAction(QIcon.fromTheme("dialog-no"),
                    qApp.translate("outlineBasics", "None"), self.menuPOV)
        a.triggered.connect(lambda: self.setPOV(""))
        self.menuPOV.addAction(a)
        self.menuPOV.addSeparator()

        menus = []
        for i in [
                qApp.translate("outlineBasics", "Main"),
                qApp.translate("outlineBasics", "Secondary"),
                qApp.translate("outlineBasics", "Minor")
        ]:
            m = QMenu(i, self.menuPOV)
            menus.append(m)
            self.menuPOV.addMenu(m)

        mpr = QSignalMapper(self.menuPOV)
        for i in range(mw.mdlCharacter.rowCount()):
            a = QAction(mw.mdlCharacter.icon(i), mw.mdlCharacter.name(i),
                        self.menuPOV)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(mw.mdlCharacter.ID(i)))

            imp = toInt(mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        mpr.mapped.connect(self.setPOV)
        menu.addMenu(self.menuPOV)

        # Status
        self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"),
                                menu)
        # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
        # a.triggered.connect(lambda: self.setStatus(""))
        # self.menuStatus.addAction(a)
        # self.menuStatus.addSeparator()

        mpr = QSignalMapper(self.menuStatus)
        for i in range(mw.mdlStatus.rowCount()):
            a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuStatus.addAction(a)
        mpr.mapped.connect(self.setStatus)
        menu.addMenu(self.menuStatus)

        # Labels
        self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"),
                               menu)
        mpr = QSignalMapper(self.menuLabel)
        for i in range(mw.mdlLabels.rowCount()):
            a = QAction(
                mw.mdlLabels.item(i, 0).icon(),
                mw.mdlLabels.item(i, 0).text(), self.menuLabel)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuLabel.addAction(a)
        mpr.mapped.connect(self.setLabel)
        menu.addMenu(self.menuLabel)

        menu.addSeparator()

        # Custom icons
        self.menuCustomIcons = QMenu(
            qApp.translate("outlineBasics", "Set Custom Icon"), menu)
        a = QAction(qApp.translate("outlineBasics", "Restore to default"),
                    self.menuCustomIcons)
        a.triggered.connect(lambda: self.setCustomIcon(""))
        self.menuCustomIcons.addAction(a)
        self.menuCustomIcons.addSeparator()

        txt = QLineEdit()
        txt.textChanged.connect(self.filterLstIcons)
        txt.setPlaceholderText("Filter icons")
        txt.setStyleSheet("background: transparent; border: none;")
        act = QWidgetAction(self.menuCustomIcons)
        act.setDefaultWidget(txt)
        self.menuCustomIcons.addAction(act)

        self.lstIcons = QListWidget()
        for i in customIcons():
            item = QListWidgetItem()
            item.setIcon(QIcon.fromTheme(i))
            item.setData(Qt.UserRole, i)
            item.setToolTip(i)
            self.lstIcons.addItem(item)
        self.lstIcons.itemClicked.connect(self.setCustomIconFromItem)
        self.lstIcons.setViewMode(self.lstIcons.IconMode)
        self.lstIcons.setUniformItemSizes(True)
        self.lstIcons.setResizeMode(self.lstIcons.Adjust)
        self.lstIcons.setMovement(self.lstIcons.Static)
        self.lstIcons.setStyleSheet(
            "background: transparent; background: none;")
        self.filterLstIcons("")
        act = QWidgetAction(self.menuCustomIcons)
        act.setDefaultWidget(self.lstIcons)
        self.menuCustomIcons.addAction(act)

        menu.addMenu(self.menuCustomIcons)

        # Disabling stuff
        if len(sel) > 0 and index.isValid() and not index.internalPointer().isFolder() \
                or not clipboard.mimeData().hasFormat("application/xml"):
            self.actPaste.setEnabled(False)

        if len(sel) > 0 and index.isValid(
        ) and not index.internalPointer().isFolder():
            self.actAddFolder.setEnabled(False)
            self.actAddText.setEnabled(False)

        if len(sel) == 0:
            self.actOpen.setEnabled(False)
            self.actCopy.setEnabled(False)
            self.actCut.setEnabled(False)
            self.actDelete.setEnabled(False)
            self.menuPOV.setEnabled(False)
            self.menuStatus.setEnabled(False)
            self.menuLabel.setEnabled(False)
            self.menuCustomIcons.setEnabled(False)

        return menu
Beispiel #35
0
class StaticPlot(vip_base):
    """
    style_codes:
            0 : QtCore.Qt.SolidLine,
            1 : QtCore.Qt.DashDotDotLine,
            2 : QtCore.Qt.DashDotLine,
            3 : QtCore.Qt.DashLine,
            4 : QtCore.Qt.DotLine

    color_codes:
            0 : (255, 255, 255),
            1 : (255, 0  , 0  ),
            2 : (0  , 255, 0  ),
            3 : (0  , 0  , 255),
            4 : (100, 100, 100)
    """

    def __init__(self):
        super(StaticPlot, self).__init__()
        """
        Function init

        :param config:
        :return:
        """

        self.__colors_selected__ = []
        self.__styles_selected__ = []
        self.__show_grid_x__ = None
        self.__show_grid_y__ = None
        self.__parameters__ = {}
        self.__plotWidget__ = None
        self.__legend__ = None

        self.styles = {
            0: QtCore.Qt.SolidLine,
            1: QtCore.Qt.DashDotDotLine,
            2: QtCore.Qt.DashDotLine,
            3: QtCore.Qt.DashLine,
            4: QtCore.Qt.DotLine
        }

        self.colors = {
            0: (255, 255, 255),
            1: (255, 0, 0  ),
            2: (0, 255, 0  ),
            3: (0, 0, 255),
            4: (100, 100, 100)
        }

    def cb_initialize_plugin(self):
        """
        Function initiate layer 0

        :param config:
        :return:
        """
        self.config = self.pl_get_current_config_ref()
        # ---------------------------
        # Read configuration
        # ---------------------------
        int_re = re.compile(r'(\d+)')

        self.__show_grid_x__ = self.config['x-grid']['value'] == '1'
        self.__show_grid_y__ = self.config['y-grid']['value'] == '1'

        self.__colors_selected__ = int_re.findall(self.config['color']['value'])
        self.__styles_selected__ = int_re.findall(self.config['style']['value'])

        # ----------------------------
        # Set internal variables used for single timestamp plotting (stp)
        # ----------------------------

        self.__plotWidget__ = pg.PlotWidget()

        self.__plotWidget__.setWindowTitle('StaticPlot')

        self.__plotWidget__.showGrid(x=self.__show_grid_x__, y=self.__show_grid_y__)
        self.__plotWidget__.getPlotItem().getViewBox().disableAutoRange()
        self.__plotWidget__.getPlotItem().getViewBox().setYRange(0,6)

        self.pl_set_widget_for_internal_usage(self.__plotWidget__)

        # ---------------------------
        # Create Parameters
        # ---------------------------

        self.__parameters__['x-grid'] = \
            DParameter('x-grid', '[0 1]', Regex='^(1|0){1}$')
        self.__parameters__['y-grid'] = \
            DParameter('y-grid', '[0 1]', Regex='^(1|0){1}$')

        self.__parameters__['color'] = \
            DParameter('color', self.config['color']['value'], Regex='^\[(\s*\d\s*)+\]')
        self.__parameters__['style'] = \
            DParameter('style', self.config['style']['value'], Regex='^\[(\s*\d\s*)+\]')

        self.__parameters__['yRange'] = \
            DParameter('yRange', '[0,1]',  Regex='^\[(\d+\.\d+)\s+(\d+\.\d+)\]$')

        self.pl_send_new_parameter_list(list(self.__parameters__.values()))

        # ---------------------------
        # Create Legend
        # ---------------------------
        if self.config['show_legend']['value']=='1':
            self.__legend__ = pg.LegendItem((100, 40), offset=(40, 1))  # args are (size, offset)
            self.__legend__.setParentItem(self.__plotWidget__.graphicsItem())

        self.setup_context_menu()
        self.__plotWidget__.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.__plotWidget__.customContextMenuRequested.connect(self.showContextMenu)

        self.read_json_data()

        return True

    def cb_pause(self):
        """
        Function pause

        :return:
        """
        pass

    def cb_resume(self):
        """
        Function resume

        :return:
        """
        pass


    def cb_execute(self, Data=None, block_name = None, plugin_uname = None):
        """
        Function cb_execute

        :param **kwargs:
        :param Data:
        :param block_name:
        :return:
        """
        pass

    def cb_set_parameter(self, name, value):
        """
        Function set parameters

        :param name:
        :param value:
        :return:
        """

        if name == 'x-grid':
            self.config['x-grid']['value'] = value
            self.__plotWidget__.showGrid(x=value == '1')
            self.xGrid_Checkbox.setChecked(value=='1')

        if name == 'y-grid':
            self.config['y-grid']['value'] = value
            self.__plotWidget__.showGrid(y=value == '1')
            self.yGrid_Checkbox.setChecked(value=='1')

        if name == 'color':
            self.clear()
            self.config['color']['value'] = value
            int_re = re.compile(r'(\d+)')
            self.__colors_selected__ = int_re.findall(self.config['color']['value'])

        if name == 'style':
            self.clear()
            self.config['style']['value'] = value
            int_re = re.compile(r'(\d+)')
            self.__styles_selected__ = int_re.findall(self.config['style']['value'])

        if name == 'yRange':
            self.use_range_for_y(value)

        if name == 'xRange':
            self.use_range_for_x(value)

    def read_json_data(self):

        json_str = self.config['json_data']['value']
        axis_id  = self.config['axis_identifier']['value']
        data = json.loads(json_str)


        self.plot_data(data, axis_id)

    def plot_data(self, data, axis_id):
        """
        Function update_plot_single_timestamp

        :return:
        """

        self.clear()

        tdata = data[axis_id]

        x_min = min(tdata)
        x_max = max(tdata)

        y_min = None
        y_max = None

        counter = 0

        for signal_name in data:
            if signal_name != axis_id:
                signal_data = data[signal_name]

                if y_max is not None:
                    y_max = max(max(signal_data), y_max)
                else:
                    y_max = max(signal_data)

                if y_min is not None:
                    y_min = min(min(signal_data), y_min)
                else:
                    y_min = min(signal_data)

                pen = self.get_pen(counter)

                graphic = GraphicItem(np.array(tdata), np.array(signal_data), 0, pen=pen)

                self.__plotWidget__.addItem(graphic)

                if self.__legend__ is not None:
                    data_item = pg.PlotDataItem()
                    data_item.setPen(pen)

                    self.__legend__.addItem(data_item, signal_name)

                counter += 1

        self.use_range_for_x("[{:2.2f} {:2.2f}]".format(x_min, x_max))
        self.use_range_for_y("[{:2.2f} {:2.2f}]".format(y_min, y_max))

#        self.__plotWidget__.getPlotItem().getViewBox().setXRange(x_min, x_max)

    def cb_plugin_meta_updated(self):
        """
        This function is called whenever meta information are changed.
        This enables the plot to handle more than one input for plotting.

        :return:
        """

        pass

    def get_pen(self, index):
        """
        Function get pen

        :param index:
        :return:
        """
        index = int(index)

        style_index = index % len(self.__styles_selected__)
        style_code = int(self.__styles_selected__[style_index])

        color_index = index % len(self.__colors_selected__)
        color_code = int(self.__colors_selected__[color_index])

        if style_code in self.styles:
            style = self.styles[style_code]
        else:
            style = self.styles[0]

        if color_code in self.colors:
            color = self.colors[color_code]
        else:
            color = self.colors[0]

        return pg.mkPen(color=color, style=style)

    def use_range_for_x(self, value):
        """

        :param value:
        :return:
        """
        reg = re.compile(r'(\d+\.\d+)')
        range = reg.findall(value)

        if len(range) == 2:
            self.__plotWidget__.getPlotItem().getViewBox().setXRange(float(range[0]),float(range[1]))

    def use_range_for_y(self, value):
        """

        :param value:
        :return:
        """
        reg = re.compile(r'([-]{0,1}\d+\.\d+)')
        range = reg.findall(value)

        if len(range) == 2:
            self.__plotWidget__.getPlotItem().getViewBox().setYRange(float(range[0]), float(range[1]))

    def setup_context_menu(self):
        """

        :return:
        """

        self.custMenu = QMenu("Options")
        self.gridMenu = QMenu('Grid')


        # Grid Menu:
        # -----------------------------------------------------------
        # Y-Grid checkbox
        self.xGrid_Checkbox = QCheckBox()
        self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)
        self.xGrid_Checkbox.setText('X-Grid')
        self.xGrid_Action = QWidgetAction(self.__plotWidget__)
        self.xGrid_Action.setDefaultWidget(self.xGrid_Checkbox)
        self.gridMenu.addAction(self.xGrid_Action)
        # Check config for startup  state
        if self.__show_grid_x__:
            self.xGrid_Checkbox.setChecked(True)

        # X-Grid checkbox
        self.yGrid_Checkbox = QCheckBox()
        self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)
        self.yGrid_Checkbox.setText('Y-Grid')
        self.yGrid_Action = QWidgetAction(self.__plotWidget__)
        self.yGrid_Action.setDefaultWidget(self.yGrid_Checkbox)
        self.gridMenu.addAction(self.yGrid_Action)
        # Check config for startup  state
        if self.__show_grid_y__:
            self.yGrid_Checkbox.setChecked(True)

        # add Menus
        self.custMenu.addMenu(self.gridMenu)

        self.__plotWidget__.getPlotItem().getViewBox().menu.clear()

        self.__plotWidget__.getPlotItem().ctrlMenu = [self.pl_create_control_context_menu(), self.custMenu]

    def showContextMenu(self):
        self.setup_context_menu()

    def contextMenu_xGrid_toogle(self):
        if self.xGrid_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'x-grid', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'x-grid', '0')

    def contextMenu_yGrid_toogle(self):
        if self.yGrid_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'y-grid', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'y-grid', '0')

    def contextMenu_yRange_toogle(self):
        mi = self.yRange_minEdit.text()
        ma = self.yRange_maxEdit.text()
        if float(mi) < float(ma):
            self.control_api.do_set_parameter(self.__id__, 'yRange', '[' + float(mi) + ' ' + float(ma) + ']')


    def cb_quit(self):
        """
        Function quit plugin

        :return:
        """
        print('StaticPlot: will quit')

    def cb_get_plugin_configuration(self):
        """
        Function get plugin configuration

        :return {}:
        """
        config = {
            'json_data' : {
                'value' : '{"v1": [5, 6, 7, 8, 9 ], "v2": [ 0, 1, 2, 3, 4 ], '
                          '"v3": [ -5, -6, -7, -8, -9 ], "v4": [ 0, -1, -2, -3, -4 ], '
                          '"t": [ 0, 1, 2, 3, 4 ]}',
                'tooltip' : 'Used as data source. Format: { "time" : [...], "y1" : [...], "y2" : [...]}'
            },
            'axis_identifier' : {
                'value' :  't',
                'tooltip' : 'Used to specify the identifier for the X-Axis e.g. time in json_data'
            },
            'show_legend' : {
                'value' : pc.REGEX_BOOL_BIN,
                'type'  : pc.CFG_TYPE_BOOL
            },
            'x-grid': {
                'value': "0",
                'regex': pc.REGEX_BOOL_BIN,
                'type': pc.CFG_TYPE_BOOL,
                'display_text': 'Grid-X'
            }, 'y-grid': {
                'value': "0",
                'regex': pc.REGEX_BOOL_BIN,
                'type': pc.CFG_TYPE_BOOL,
                'display_text': 'Grid-Y'
            }, 'color': {
                'value': "[0 1 2 3 4]",
                'regex': '^\[(\s*\d\s*)+\]',
                'advanced': '1',
                'display_text': 'Color'
            }, 'style': {
                'value': "[0 0 0 0 0]",
                'regex': '^\[(\s*\d\s*)+\]',
                'advanced': '1',
                'display_text': 'Style'
            }
        }
        # http://www.regexr.com/
        return config

    def clear(self):
        """

        :return:
        """
        self.__plotWidget__.clear()
Beispiel #36
0
    def init_items(self):
        self.toolbar.setObjectName("main_toolbar")
        self.main_window.addToolBar(Qt.TopToolBarArea, self.toolbar)
        self.toolbar.setMovable(False)

        steps_menu = QMenu()
        for step in AVAILABLE_STEPS:
            s_action = QAction(step, self.main_window)
            s_action.triggered.connect(
                partial(
                    self.main_window.default_page_controller.
                    trigger_add_step_command,
                    step,
                ))
            steps_menu.addAction(s_action)

        toolbar_new_step_action = QAction(QIcon(":/images/plus-48.png"),
                                          "New Step", self.main_window)
        toolbar_new_step_action.setMenu(steps_menu)
        self.toolbar.addAction(toolbar_new_step_action)

        self.toolbar.addSeparator()

        toolbar_environment_action = QAction(
            QIcon(":/images/environment-48.png"),
            "Configure Environments",
            self.main_window,
        )
        toolbar_environment_action.triggered.connect(
            self.main_window.environment_view.show_dialog)
        self.toolbar.addAction(toolbar_environment_action)

        tool_bar_envs_list = QComboBox(self.main_window)
        tool_bar_envs_list.setSizePolicy(QSizePolicy.MinimumExpanding,
                                         QSizePolicy.MinimumExpanding)
        tool_bar_envs_list.setDuplicatesEnabled(False)
        tool_bar_envs_list.currentTextChanged.connect(
            self.main_window.environment_list_view.
            on_toolbar_selected_environment_changed)
        tool_bar_envs_list_action = QWidgetAction(self.main_window)
        tool_bar_envs_list_action.setText("Environmnents")
        tool_bar_envs_list_action.setDefaultWidget(tool_bar_envs_list)
        self.toolbar.addAction(tool_bar_envs_list_action)

        self.toolbar.addSeparator()

        spacer = QWidget(self.main_window)
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.toolbar.addWidget(spacer)

        toolbar_configure_action = QAction(QIcon(":/images/configure-48.png"),
                                           "Settings", self.main_window)
        toolbar_configure_action.triggered.connect(
            self.main_window.config_view.show_dialog)
        self.toolbar.addAction(toolbar_configure_action)

        toolbar_quit_action = QAction(QIcon(":/images/quit-48.png"), "Quit",
                                      self.main_window)
        toolbar_quit_action.triggered.connect(self.trigger_quit_application)
        self.toolbar.addAction(toolbar_quit_action)
Beispiel #37
0
class Plot(vip_base):
    """
    style_codes:
            0 : QtCore.Qt.SolidLine,
            1 : QtCore.Qt.DashDotDotLine,
            2 : QtCore.Qt.DashDotLine,
            3 : QtCore.Qt.DashLine,
            4 : QtCore.Qt.DotLine

    color_codes:
            0 : (255, 255, 255),
            1 : (255, 0  , 0  ),
            2 : (0  , 255, 0  ),
            3 : (0  , 0  , 255),
            4 : (100, 100, 100)
    """

    def __init__(self, debug=False):
        super(Plot, self).__init__()
        """
        Function init

        :param config:
        :return:
        """

        self.signals = {}

        self.__papi_debug__ = debug
        self.__buffer_size__ = None
        self.__downsampling_rate__ = 1
        self.__tbuffer__ = []

        self.__signals_have_same_length = True

        self.__append_at__ = 1
        self.__new_added_data__ = 0
        self.__input_size__ = 0
        self.__rolling_plot__ = False
        self.__colors_selected__ = []
        self.__styles_selected__ = []
        self.__show_grid_x__ = None
        self.__show_grid_y__ = None
        self.__parameters__ = {}
        self.__update_intervall__ = None
        self.__last_time__ = None
        self.__last_plot_time__ = None
        self.__plotWidget__ = None
        self.__legend__ = None

        self.__stp_min_x = None
        self.__stp_max_x = None

        self.__stp_min_y = None
        self.__stp_max_y = None
        self.__stp_active__ = None

        self.__downsampling_rate_start__ = None;
        self.__downsampling_rate__ = None

        self.styles = {
            0: QtCore.Qt.SolidLine,
            1: QtCore.Qt.DashDotDotLine,
            2: QtCore.Qt.DashDotLine,
            3: QtCore.Qt.DashLine,
            4: QtCore.Qt.DotLine
        }

        self.colors = {
            0: (255, 255, 255),
            1: (255, 0, 0  ),
            2: (0, 255, 0  ),
            3: (0, 0, 255),
            4: (100, 100, 100)
        }

    def cb_initialize_plugin(self):
        """
        Function initiate layer 0

        :param config:
        :return:
        """
        self.config = self.pl_get_current_config_ref()
        # ---------------------------
        # Read configuration
        # ---------------------------
        int_re = re.compile(r'(\d+)')
        self.__show_legend__ = self.config['show_legend']['value'] == '1'
        self.__show_grid_x__ = self.config['x-grid']['value'] == '1'
        self.__show_grid_y__ = self.config['y-grid']['value'] == '1'
        self.__rolling_plot__ = self.config['rolling_plot']['value'] == '1'

        self.__colors_selected__ = int_re.findall(self.config['color']['value'])
        self.__styles_selected__ = int_re.findall(self.config['style']['value'])

        self.__buffer_size__ = int(int_re.findall(self.config['buffersize']['value'])[0])

        self.__downsampling_rate__ = int(int_re.findall(self.config['downsampling_rate']['value'])[0])
        self.__downsampling_rate_start__ = 0

        # ----------------------------
        # Set internal variables
        # ----------------------------

        self.__tbuffer__ = collections.deque([0.0] * 0, self.__buffer_size__)

        # ----------------------------
        # Set internal variables used for single timestamp plotting (stp)
        # ----------------------------

        self.__stp_min_x = 0
        self.__stp_max_x = 0

        self.__stp_min_y = 0
        self.__stp_max_y = 1

        self.__stp_active__ = False


        # --------------------------------
        # Create Layout and labels
        # --------------------------------

        self.central_widget = QWidget()
        self.central_widget.setContentsMargins(0,0,0,0)

        self.label_widget = QWidget()
        self.label_widget.setContentsMargins(0,0,0,0)

        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setContentsMargins(0,0,0,0)
        self.verticalLayout.setSpacing(0)

        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setContentsMargins(0,0,0,0)
        self.horizontalLayout.setSpacing(0)

        self.space_label = QLabel()
        self.space_label.setMargin(0)
        self.space_label.setAlignment(QtCore.Qt.AlignJustify)
        self.space_label.setStyleSheet("QLabel { background-color : black; color : grey;"
                                      "border : 0px solid black ; border-bottom-width : 5px }")

        self.time_label = QLabel()
        self.time_label.setMargin(0)
        self.time_label.setAlignment(QtCore.Qt.AlignJustify)
        self.time_label.setStyleSheet("QLabel { background-color : black; color : grey;"
                                      "border : 0px solid black ; border-bottom-width : 5px }")
        self.time_label.setMaximumWidth(55)


        self.unit_label = QLabel()
        self.unit_label.setMargin(0)
        self.unit_label.setAlignment(QtCore.Qt.AlignLeft)
        self.unit_label.setStyleSheet("QLabel { background-color : black; color : grey;"
                                      "border : 0px solid black ; border-bottom-width : 5px }")

        self.unit_label.setText('[s]')

        self.central_widget.setLayout(self.verticalLayout)
        self.label_widget.setLayout(self.horizontalLayout)

        # --------------------------------
        # Create PlotWidget
        # --------------------------------

        self.__plotWidget__ = PlotWidget()
        self.__plotWidget__.yRangeChanged.connect(self.plot_yrange_changed)
        self.__plotWidget__.setWindowTitle('PlotPerformanceTitle')

        self.__plotWidget__.showGrid(x=self.__show_grid_x__, y=self.__show_grid_y__)
        self.__plotWidget__.getPlotItem().getViewBox().disableAutoRange()
        self.__plotWidget__.getPlotItem().getViewBox().setYRange(0,6)

        self.__plotWidget__.getPlotItem().setDownsampling(auto=True)

        # ------------------------------
        # Add Widget to Layout
        # ------------------------------
        self.horizontalLayout.addWidget(self.space_label)
        self.horizontalLayout.addWidget(self.time_label)
        self.horizontalLayout.addWidget(self.unit_label)

        self.verticalLayout.addWidget(self.__plotWidget__)
        self.verticalLayout.addWidget(self.label_widget)


        if not self.__papi_debug__:
#            self.pl_set_widget_for_internal_usage(self.__plotWidget__)
            self.pl_set_widget_for_internal_usage(self.central_widget)

        self.__plotWidget__.getPlotItem().getViewBox().enableAutoRange(axis=pg.ViewBox.YAxis, enable=False)
        self.__plotWidget__.getPlotItem().getViewBox().enableAutoRange(axis=pg.ViewBox.XAxis, enable=False)

        self.__plotWidget__.getPlotItem().getViewBox().setMouseEnabled(x=False, y=True)

        # ---------------------------
        # Create Parameters
        # ---------------------------

        self.__parameters__['x-grid'] = \
            DParameter('x-grid', self.config['x-grid']['value'], Regex='^(1|0){1}$')
        self.__parameters__['y-grid'] = \
            DParameter('y-grid', self.config['y-grid']['value'], Regex='^(1|0){1}$')

        self.__parameters__['color'] = \
            DParameter('color', self.config['color']['value'], Regex='^\[(\s*\d\s*)+\]')
        self.__parameters__['style'] = \
            DParameter('style', self.config['style']['value'], Regex='^\[(\s*\d\s*)+\]')
        self.__parameters__['rolling'] = \
            DParameter('rolling', self.config['rolling_plot']['value'], Regex='^(1|0){1}')

        self.__parameters__['downsampling_rate'] = \
            DParameter('downsampling_rate', self.__downsampling_rate__, Regex='^\d+$')
        self.__parameters__['buffersize'] = \
            DParameter('buffersize', self.__buffer_size__, Regex='^\d+$')

        self.__parameters__['yRange'] = \
            DParameter('yRange', self.config['yRange']['value'],  Regex='^\[(\d+\.\d+)\s+(\d+\.\d+)\]$')

        self.__parameters__['show_legend'] = \
            DParameter('show_legend', self.config['show_legend']['value'],  Regex=pc.REGEX_BOOL_BIN)

        if not self.__papi_debug__:
            self.pl_send_new_parameter_list(list(self.__parameters__.values()))

        # ---------------------------
        # Create Legend
        # ---------------------------

        if self.__show_legend__:
            self.__legend__ = self.__plotWidget__.getPlotItem().addLegend()
        else:
            self.__legend__ = None


        self.__last_time__ = current_milli_time()

        self.__update_intervall__ = 20  # in milliseconds
        self.__last_plot_time__   = 0

        self.setup_context_menu()
        self.__plotWidget__.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.__plotWidget__.customContextMenuRequested.connect(self.showContextMenu)

        self.use_range_for_y(self.config['yRange']['value'])

        # ----------------------------
        # Initiate for default plotting
        # ----------------------------

        self.initiate_update_plot()
        return True

    def cb_pause(self):
        """
        Function pause

        :return:
        """
        self.__plotWidget__.getPlotItem().getViewBox().setMouseEnabled(x=True, y=True)

    def cb_resume(self):
        """
        Function resume

        :return:
        """
        self.__plotWidget__.getPlotItem().getViewBox().setMouseEnabled(x=False, y=True)

    def cb_execute(self, Data=None, block_name = None, plugin_uname = None):
        """
        Function cb_execute

        :param Data:
        :param block_name:
        :return:
        """

        t = Data[CORE_TIME_SIGNAL]

        self.__input_size__ = len(t)

        self.__signals_have_same_length = True

        now = pg.ptime.time()

        for key in Data:
            if key != CORE_TIME_SIGNAL:
                y = Data[key]
                if key in self.signals:
                    if self.__downsampling_rate_start__ < len(y):
                        ds_y = y[self.__downsampling_rate_start__::self.__downsampling_rate__]

                        self.signals[key].add_data(ds_y)

                        self.__signals_have_same_length &= (len(y) == len(t))

        if self.__downsampling_rate_start__ >= len(t):
            self.__downsampling_rate_start__ -= len(t)
        else:
            ds_t = t[self.__downsampling_rate_start__::self.__downsampling_rate__]
            self.__downsampling_rate_start__ += self.__downsampling_rate__ - len(ds_t)
            self.__tbuffer__.extend(ds_t)

        self.__new_added_data__ += len(t)

        self.rolling_Checkbox.setDisabled(self.__stp_active__)

        if self.__input_size__ > 1 or self.__signals_have_same_length:

            if self.__stp_active__:
                self.initiate_update_plot()

            if current_milli_time() - self.__last_time__ > self.__update_intervall__ - self.__last_plot_time__:
                self.__last_time__ = current_milli_time()
                self.update_plot()
                self.__last_time__ = current_milli_time()
                self.__new_added_data__ = 0
        else:

            if not self.__stp_active__ :
                self.initiate_update_plot_single_timestamp()

            if current_milli_time() - self.__last_time__ > self.__update_intervall__ - self.__last_plot_time__:
                self.__last_time__ = current_milli_time()

                self.update_plot_single_timestamp(Data)

                self.__last_time__ = current_milli_time()
                self.__new_added_data__ = 0

        # print("Plot time: %0.5f sec" % (self.__last_plot_time__) )

    def cb_set_parameter(self, name, value):
        """
        Function set parameters

        :param name:
        :param value:
        :return:
        """
        if name == 'x-grid':
            self.config['x-grid']['value'] = value
            self.__plotWidget__.showGrid(x=value == '1')
            self.xGrid_Checkbox.stateChanged.disconnect()
            self.xGrid_Checkbox.setChecked(value=='1')
            self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)

        if name == 'y-grid':
            self.config['y-grid']['value'] = value
            self.__plotWidget__.showGrid(y=value == '1')
            self.yGrid_Checkbox.stateChanged.disconnect()
            self.yGrid_Checkbox.setChecked(value=='1')
            self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)

        if name == 'downsampling_rate':
            self.config['downsampling_rate']['value'] = value
            self.__downsampling_rate__ = int(value)
            self.__new_added_data__ = 0
            self.update_downsampling_rate()

        if name == 'rolling':
            self.clear()
            self.config['rolling_plot']['value'] = value
            self.update_rolling_plot()

        if name == 'color':
            self.clear()
            self.config['color']['value'] = value
            int_re = re.compile(r'(\d+)')
            self.__colors_selected__ = int_re.findall(self.config['color']['value'])
            self.update_pens()
            self.update_legend()

        if name == 'style':
            self.clear()
            self.config['style']['value'] = value
            int_re = re.compile(r'(\d+)')
            self.__styles_selected__ = int_re.findall(self.config['style']['value'])
            self.update_pens()
            self.update_legend()

        if name == 'show_legend':
            self.config['show_legend']['value'] = value
            if value == '0':
                if self.__legend__ is not None:
                    self.__legend__.scene().removeItem(self.__legend__)
                    del self.__legend__
                    self.__legend__ = None
            if value == '1':
                self.update_legend()

        if name == 'buffersize':
            self.config['buffersize']['value'] = value
            self.update_buffer_size(value)

        if name == 'yRange':
            self.config['yRange']['value'] = value
            self.use_range_for_y(value)

    def update_pens(self):
        """
        Function update pens

        :return:
        """

        for signal_name in self.signals.keys():
            signal_id = self.signals[signal_name].id
            new_pen = self.get_pen(signal_id)
            other_pen = self.get_pen(signal_id)

            o_color = other_pen.color()
            o_color.setAlpha(100)
            other_pen.setColor(o_color)

            self.signals[signal_name].pen = new_pen
            self.signals[signal_name].other_pen = other_pen

    def update_plot(self):
        """
        Function update_plot

        :return:
        """

        if len(self.__tbuffer__) == 0:
            return

        if not self.__rolling_plot__:
            tdata = list(self.__tbuffer__)

        if self.__rolling_plot__:
            tdata = list(range(0, len(self.__tbuffer__)))
            self.__append_at__ += self.signals[list(self.signals.keys())[0]].get_new_added_since_last_drawing()
            self.__append_at__ %= len(tdata)
            tdata = np.roll(tdata, -int(self.__append_at__))

        now = pg.ptime.time()

        for signal_name in self.signals:

            # get all no more needed graphic items
            graphics = self.signals[signal_name].get_old_graphics()
            for graphic in graphics:
                self.__plotWidget__.removeItem(graphic)

            # Create new new graphic items
            self.signals[signal_name].create_graphics(tdata)

            # Get new created graphic item and paint them
            graphics = self.signals[signal_name].get_graphics()
            for graphic in graphics:
                self.__plotWidget__.addItem(graphic)

        self.__last_plot_time__ = pg.ptime.time()-now

        if self.__rolling_plot__:
            self.__plotWidget__.getPlotItem().getViewBox().setXRange(0, len(tdata)-1)
            self.time_label.setNum(self.__tbuffer__[-1])
        else:
            self.__plotWidget__.getPlotItem().getViewBox().setXRange(tdata[0], tdata[-1])

        # if self.__papi_debug__:
        #     print("Plot time: %0.5f sec" % (self.__last_plot_time__) )

    def initiate_update_plot(self):
        """
        To all needed changes to use default plotting

        :return:
        """
        self.__stp_active__ = False

        if self.__rolling_plot__:
            self.time_label.setHidden(False)
        else:
            self.time_label.setHidden(True)

        pass

    def initiate_update_plot_single_timestamp(self):
        """
        To all needed changes to use single timestamp plotting

        :return:
        """

        self.__stp_active__ = True

        self.time_label.setHidden(False)

    def update_plot_single_timestamp(self, data):
        """
        Function update_plot_single_timestamp

        :return:
        """

        self.__plotWidget__.clear()

        cur_max_y = 0
        cur_min_y = 1000

        for signal_name in data:
            if signal_name != CORE_TIME_SIGNAL:
                signal_data = data[signal_name]
                if signal_name in self.signals:

                    tdata = np.linspace(1, len(signal_data), len(signal_data))

                    plot_item = self.signals[signal_name]

                    if len(tdata) == 1:
                        graphic = GraphicItem(np.array([self.__stp_min_x, self.__stp_max_x]), np.array([signal_data[0], signal_data[0]]), 0, pen=plot_item.pen)
                    else:
                        graphic = GraphicItem(np.array(tdata), np.array(signal_data), 0, pen=plot_item.pen)

                    self.__plotWidget__.addItem(graphic)

                    self.__stp_max_x = max(self.__stp_max_x, max(tdata))
                    self.__stp_min_x = min(self.__stp_min_x, min(tdata))

                    cur_max_y = max(cur_max_y, max(signal_data))
                    cur_min_y = min(cur_min_y, min(signal_data))

        self.__stp_max_y = cur_max_y
        self.__stp_min_y = cur_min_y

        self.__plotWidget__.getPlotItem().getViewBox().setXRange(self.__stp_min_x, self.__stp_max_x)

        self.time_label.setNum(data[CORE_TIME_SIGNAL][0])

    def update_buffer_size(self, new_size):
        """
        Function set buffer size

        :param new_size:
        :return:
        """

        self.__buffer_size__ = int(new_size)

        start_size = len(self.__tbuffer__)

        for signal_name in self.signals:
            self.__tbuffer__ = collections.deque([0.0] * start_size, self.__buffer_size__)  # COLLECTION

            plot_item = self.signals[signal_name]
            plot_item.max_elements = self.__buffer_size__
            plot_item.clear()
            self.__plotWidget__.clear()

        self.update_rolling_plot()

        self.__new_added_data__ = 0

    def cb_plugin_meta_updated(self):
        """
        This function is called whenever meta information are changed.
        This enables the plot to handle more than one input for plotting.

        :return:
        """
        dp_info = self.pl_get_dplugin_info()
        subscriptions = dp_info.get_subscribtions()
        changes = False
        current_signals = {}
        index = 0

        for dpluginsub_id in subscriptions:
            for dblock_name in subscriptions[dpluginsub_id]:

                # get subscription for dblock
                subscription = subscriptions[dpluginsub_id][dblock_name]

                for signal_name in subscription.get_signals():

                    if signal_name != pc.CORE_TIME_SIGNAL:

                        signal = subscription.get_dblock().get_signal_by_uname(signal_name)
                        current_signals[signal_name] = {}
                        current_signals[signal_name]['signal'] = signal
                        current_signals[signal_name]['index'] = index
                        index += 1

        # ----------------------------
        # Add new subscribed signals
        # ----------------------------
        for signal_name in sorted(current_signals.keys()):
            if signal_name != CORE_TIME_SIGNAL:
                if signal_name not in self.signals:
                    signal = current_signals[signal_name]['signal']
                    self.add_plot_item(signal, current_signals[signal_name]['index'])
                    changes = True

        # -------------------------------
        # Remove unsubscribed signals
        # -------------------------------
        for signal_name in self.signals.copy():
            if signal_name not in current_signals:
                if self.__legend__ is not None:
                    self.remove_plot_item(signal_name)
                changes = True

        if changes:
            self.update_pens()
            self.update_signals()
            self.update_legend()
            self.update_rolling_plot()
            self.update_downsampling_rate()
        else:
            self.update_signals()
            #self.update_legend()

    def add_plot_item(self, signal, signal_id):
        """
        Create a new plot item object for a given signal and internal id

        :param signal: DSignal object
        :param signal_id: plot internal signal id
        :return:
        """

        signal_name = signal.uname

        if signal_name not in self.signals:
            self.signals[signal_name] = {}

            plot_item = PlotItem(signal, signal_id, self.__buffer_size__)
            plot_item.set_downsampling_rate(self.__downsampling_rate__)

            self.signals[signal_name] = plot_item

    def remove_plot_item(self, signal_name):
        """
        Remove the plot item object for a given signal_name.

        :param signal_name:
        :return:
        """

        if signal_name in self.signals:
            plot_item = self.signals[signal_name]

            # Remove all graphic objects

            for graphic in plot_item.graphics:
                self.__plotWidget__.removeItem(graphic)

            # Remove from Legend
            self.__legend__.removeItem(plot_item.signal_name)
            del self.signals[signal_name]

    def get_pen(self, index):
        """
        Function get pen

        :param index:
        :return:
        """
        index = int(index)

        style_index = index % len(self.__styles_selected__)
        style_code = int(self.__styles_selected__[style_index])

        color_index = index % len(self.__colors_selected__)
        color_code = int(self.__colors_selected__[color_index])

        if style_code in self.styles:
            style = self.styles[style_code]
        else:
            style = self.styles[0]

        if color_code in self.colors:
            color = self.colors[color_code]
        else:
            color = self.colors[0]

        return pg.mkPen(color=color, style=style)

    def update_rolling_plot(self):
        """
        Used to update the rolling plot by resolving all dependencies.
        The configuration for the rolling plot depends on the current value in self.config['rolling_plot']['value']

        :return:
        """

        value = self.config['rolling_plot']['value']

        self.__rolling_plot__ = int(float(self.config['rolling_plot']['value'])) == int('1')

        self.rolling_Checkbox.stateChanged.disconnect()
        self.rolling_Checkbox.setChecked(value == '1')
        self.rolling_Checkbox.stateChanged.connect(self.contextMenu_rolling_toogled)

        self.clear()


        for signal_name in self.signals:
            self.signals[signal_name].rolling_plot = self.__rolling_plot__

        self.initiate_update_plot()

    def use_range_for_x(self, value):
        """

        :param value:
        :return:
        """
        reg = re.compile(r'(\d+\.\d+)')
        range = reg.findall(value)
        if len(range) == 2:
            #self.xRange_minEdit.setText(range[0])
            #self.xRange_maxEdit.setText(range[1])
            self.__plotWidget__.getPlotItem().getViewBox().setXRange(float(range[0]),float(range[1]))

    def use_range_for_y(self, value):
        """

        :param value:
        :return:
        """
        reg = re.compile(r'([-]{0,1}\d+\.\d+)')
        range = reg.findall(value)



        if len(range) == 2:

            self.yRange_minEdit.setText(range[0])
            self.yRange_maxEdit.setText(range[1])
            self.__plotWidget__.getPlotItem().getViewBox().setYRange(float(range[0]), float(range[1]))

    def setup_context_menu(self):
        """

        :return:
        """

        self.custMenu = QMenu("Options")
        self.axesMenu = QMenu('Y-Axis')
        self.gridMenu = QMenu('Grid')

        ##### Y-Range Actions
        self.yRange_Widget = QWidget()
        self.yRange_Layout = QVBoxLayout(self.yRange_Widget)
        self.yRange_Layout.setContentsMargins(2, 2, 2, 2)
        self.yRange_Layout.setSpacing(1)

        self.yAutoRangeButton = QPushButton()
        self.yAutoRangeButton.clicked.connect(self.contextMenu_yAutoRangeButton_clicked)
        self.yAutoRangeButton.setText('Use autorange')
        self.yRange_Layout.addWidget(self.yAutoRangeButton)

        ##### Y Line Edits
        # Layout
        self.yRange_EditWidget = QWidget()
        self.yRange_EditLayout = QHBoxLayout(self.yRange_EditWidget)
        self.yRange_EditLayout.setContentsMargins(2, 2, 2, 2)
        self.yRange_EditLayout.setSpacing(1)

        # get old values;
        reg = re.compile(r'(\d+\.\d+)')
        range = reg.findall(self.config['yRange']['value'])
        if len(range) == 2:
            y_min = range[0]
            y_max = range[1]
        else:
            y_min = '0.0'
            y_max = '1.0'

        rx = QRegExp(r'([-]{0,1}\d+\.\d+)')
        validator = QRegExpValidator(rx, self.__plotWidget__)

        # Min
        self.yRange_minEdit = QLineEdit()
        self.yRange_minEdit.setFixedWidth(80)
        self.yRange_minEdit.setText(y_min)
        self.yRange_minEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_minEdit.setValidator(validator)
        # Max
        self.yRange_maxEdit = QLineEdit()
        self.yRange_maxEdit.setFixedWidth(80)
        self.yRange_maxEdit.setText(y_max)
        self.yRange_maxEdit.editingFinished.connect(self.contextMenu_yRange_toogle)
        self.yRange_maxEdit.setValidator(validator)
        # addTo Layout
        self.yRange_EditLayout.addWidget(self.yRange_minEdit)
        self.yRange_EditLayout.addWidget(QLabel('<'))
        self.yRange_EditLayout.addWidget(self.yRange_maxEdit)
        self.yRange_Layout.addWidget(self.yRange_EditWidget)

        # build Action
        self.yRange_Action = QWidgetAction(self.__plotWidget__)
        self.yRange_Action.setDefaultWidget(self.yRange_Widget)

        ##### Rolling Plot
        self.rolling_Checkbox = QCheckBox()
        self.rolling_Checkbox.setText('Rolling plot')
        self.rolling_Checkbox.setChecked(self.config['rolling_plot']['value'] == '1')
        self.rolling_Checkbox.stateChanged.connect(self.contextMenu_rolling_toogled)
        self.rolling_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.rolling_Checkbox_Action.setDefaultWidget(self.rolling_Checkbox)
        if self.__stp_active__:
            self.rolling_Checkbox.setDisabled(True)

        # show legend

        self.legend_Checkbox = QCheckBox()
        self.legend_Checkbox.setText('Show legend')
        self.legend_Checkbox.setChecked(self.config['show_legend']['value'] == '1')
        self.legend_Checkbox.stateChanged.connect(self.contextMenu_legend_toogled)
        self.legend_Checkbox_Action = QWidgetAction(self.__plotWidget__)
        self.legend_Checkbox_Action.setDefaultWidget(self.legend_Checkbox)

        ##### Build axes menu
        #self.axesMenu.addAction(self.xRange_Action)
        self.axesMenu.addSeparator().setText("Y-Range")
        self.axesMenu.addAction(self.yRange_Action)

        # Grid Menu:
        # -----------------------------------------------------------
        # Y-Grid checkbox
        self.xGrid_Checkbox = QCheckBox()
        self.xGrid_Checkbox.stateChanged.connect(self.contextMenu_xGrid_toogle)
        self.xGrid_Checkbox.setText('X-Grid')
        self.xGrid_Action = QWidgetAction(self.__plotWidget__)
        self.xGrid_Action.setDefaultWidget(self.xGrid_Checkbox)
        self.gridMenu.addAction(self.xGrid_Action)
        # Check config for startup  state
        if self.__show_grid_x__:
            self.xGrid_Checkbox.setChecked(True)

        # X-Grid checkbox
        self.yGrid_Checkbox = QCheckBox()
        self.yGrid_Checkbox.stateChanged.connect(self.contextMenu_yGrid_toogle)
        self.yGrid_Checkbox.setText('Y-Grid')
        self.yGrid_Action = QWidgetAction(self.__plotWidget__)
        self.yGrid_Action.setDefaultWidget(self.yGrid_Checkbox)
        self.gridMenu.addAction(self.yGrid_Action)
        # Check config for startup  state
        if self.__show_grid_y__:
            self.yGrid_Checkbox.setChecked(True)

        # add Menus
        self.custMenu.addMenu(self.axesMenu)
        self.custMenu.addMenu(self.gridMenu)
        self.custMenu.addSeparator().setText("Rolling Plot")
        self.custMenu.addAction(self.rolling_Checkbox_Action)
        self.custMenu.addAction(self.legend_Checkbox_Action)
        self.__plotWidget__.getPlotItem().getViewBox().menu.clear()

        if not self.__papi_debug__:
            self.__plotWidget__.getPlotItem().ctrlMenu = [self.pl_create_control_context_menu(), self.custMenu]

    def showContextMenu(self):
        self.setup_context_menu()


    def contextMenu_yAutoRangeButton_clicked(self):
        mi = None
        ma = None

        if self.__stp_active__:
            mi = self.__stp_min_y
            ma = self.__stp_max_y
        else:
            for sig in self.signals:
                graphics = self.signals[sig].graphics
                buf = []
                for graphic in graphics:
                    buf.extend(graphic.y)

                ma_buf = max(buf)
                mi_buf = min(buf)
                if ma is not None:
                    if ma_buf > ma:
                        ma = ma_buf
                else:
                    ma = ma_buf

                if mi is not None:
                    if mi_buf < mi:
                        mi = mi_buf
                else:
                    mi = mi_buf

        ma = str(float(ma))
        mi = str(float(mi))

        self.yRange_maxEdit.setText(ma)
        self.yRange_minEdit.setText(mi)
        self.control_api.do_set_parameter(self.__id__, 'yRange', '[' +mi + ' ' + ma + ']')

    def contextMenu_rolling_toogled(self):
        if self.rolling_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'rolling', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'rolling', '0')

    def contextMenu_legend_toogled(self):
        if self.legend_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'show_legend', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'show_legend', '0')

    def contextMenu_xGrid_toogle(self):
        if self.xGrid_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'x-grid', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'x-grid', '0')

    def contextMenu_yGrid_toogle(self):
        if self.yGrid_Checkbox.isChecked():
            self.control_api.do_set_parameter(self.__id__, 'y-grid', '1')
        else:
            self.control_api.do_set_parameter(self.__id__, 'y-grid', '0')

    def contextMenu_yRange_toogle(self):
        mi = self.yRange_minEdit.text()
        ma = self.yRange_maxEdit.text()
        if float(mi) < float(ma):
            self.control_api.do_set_parameter(self.__id__, 'yRange', '[' + mi + ' ' + ma + ']')

    def update_signals(self):
        """
        Used to update the signals as they are described in self.dplugin_info

        :return:
        """
        dp_info = self.pl_get_dplugin_info()
        subscriptions = dp_info.get_subscribtions()

        for dpluginsub_id in subscriptions:
            for dblock_name in subscriptions[dpluginsub_id]:

                # get subscription for dblock
                subscription = subscriptions[dpluginsub_id][dblock_name]

                for signal_name in subscription.get_signals():
                    if signal_name != CORE_TIME_SIGNAL:
                        signal = subscription.get_dblock().get_signal_by_uname(signal_name)

                        self.signals[signal_name].update_signal(signal)

    def update_legend(self):
        """
        Used to update the legend.

        :return:
        """

        if not self.__show_legend__:
            return

        if self.__legend__ is not None:
            self.__legend__.scene().removeItem(self.__legend__)
            del self.__legend__
            self.__legend__ = None

        self.__legend__ = self.__plotWidget__.getPlotItem().addLegend()

        if not self.__papi_debug__:
            self.update_signals()

        for signal_name in sorted(self.signals.keys()):

            graphic = self.signals[signal_name].get_legend_item()

            if graphic is not None:
                signal = self.signals[signal_name].signal
                legend_name = signal.dname

                self.__legend__.addItem(graphic, legend_name)

    def update_downsampling_rate(self):
        """
        Used to update the downsampling rate by resolving all dependencies.
        The new downsampling rate is taken by using the private attribute __downsampling_rate__.

        :return:
        """
        rate = self.__downsampling_rate__

        self.__downsampling_rate_start__ = 0
        self.__downsampling_rate__ = rate

        for signal_name in self.signals:
            self.signals[signal_name].set_downsampling_rate(rate)

    def plot_yrange_changed(self):

        viewbox = self.__plotWidget__.getPlotItem().getViewBox()
        [xRange, yRange] = viewbox.viewRange()
        self.control_api.do_update_parameter(self.__id__, 'yRange', '[' + str(yRange[0]) + ' ' + str(yRange[1]) + ']')

        self.config['yRange']['value'] = '[' + str(yRange[0]) + ' ' + str(yRange[1]) + ']'

    def cb_quit(self):
        """
        Function quit plugin

        :return:
        """
        print('PlotPerformance: will quit')

    def debug_papi(self):
        config = self.get_cb_plugin_configuration()

        config['yRange'] =  {
            'value': '[0.0 50.0]',
            'regex': '(\d+\.\d+)',
            'advanced': '1',
            'display_text': 'y: range'
        }
        config['buffersize'] =  {
            'value': '1000',
            'regex': '(\d+\.\d+)',
            'advanced': '1',
            'display_text': 'y: range'
        }
        config['downsampling_rate'] =  {
            'value': '10',
            'regex': '(\d+\.\d+)',
            'advanced': '1',
            'display_text': 'y: range'
        }

        self.config = config
        self.__id__ = 0
        self.cb_initialize_plugin(config)

        signal_1 = DSignal('signal_1')
        signal_2 = DSignal('signal_2')
        signal_3 = DSignal('signal_3')
        signal_4 = DSignal('signal_4')
        signal_5 = DSignal('signal_5')

        self.add_plot_item(signal_1, 1)
        self.add_plot_item(signal_2, 2)
        self.add_plot_item(signal_3, 3)
        self.add_plot_item(signal_4, 4)
        self.add_plot_item(signal_5, 5)

        self.update_pens()
        self.update_legend()

        pass

    def cb_get_plugin_configuration(self):
        """
        Function get plugin configuration

        :return {}:
        """
        config = {
        'x-grid': {
            'value': "0",
            'regex': '^(1|0)$',
            'type': 'bool',
            'display_text': 'Grid-X'
        }, 'y-grid': {
            'value': "0",
            'regex': '^(1|0)$',
            'type': 'bool',
            'display_text': 'Grid-Y'
        }, 'color': {
            'value': "[0 1 2 3 4]",
            'regex': '^\[(\s*\d\s*)+\]',
            'advanced': '1',
            'display_text': 'Color'
        }, 'style': {
            'value': "[0 0 0 0 0]",
            'regex': '^\[(\s*\d\s*)+\]',
            'advanced': '1',
            'display_text': 'Style'
        }, 'buffersize': {
            'value': "100",
            'regex': '^(\d+)$',
            'advanced': '1',
            'display_text': 'Buffersize'
        }, 'downsampling_rate': {
            'value': "1",
            'regex': '(\d+)'
        }, 'rolling_plot': {
            'value': '0',
            'regex': '^(1|0)$',
            'type': 'bool',
            'display_text': 'Rolling Plot'
        }, 'yRange': {
            'value': '[0.0 1.0]',
            'regex': '^\[(\d+\.\d+)\s+(\d+\.\d+)\]$',
            'advanced': '1',
            'display_text': 'y: range'
        },  'show_legend' : {
            'value' : '1',
            'regex' : pc.REGEX_BOOL_BIN,
            'display_text' : 'Enable/Disable legend',
            'type' : pc.CFG_TYPE_BOOL
        }
        }
        # http://www.regexr.com/
        return config

    def clear(self):
        """

        :return:
        """
        self.__plotWidget__.clear()
        self.__tbuffer__.clear()

        for signal_name in self.signals:
            self.signals[signal_name].clear()
Beispiel #38
0
 def UploadAction(self):
     upload_widget = QWidget()
     self.upload_action = QWidgetAction(self.menu)
     self.upload_action.setIcon(QIcon(QPixmap("./icons/file.png")))
     self.upload_action.setIconText("加载文件")
     self.upload_action.triggered.connect(self.getfile)
Beispiel #39
0
class SegyViewWidget(QWidget):
    def __init__(self,
                 filename,
                 show_toolbar=True,
                 color_maps=None,
                 width=11.7,
                 height=8.3,
                 dpi=100,
                 segyioargs={},
                 parent=None):
        QWidget.__init__(self, parent)

        inline = SliceModel("Inline", SD.inline, SD.crossline, SD.depth)
        xline = SliceModel("Crossline", SD.crossline, SD.inline, SD.depth)
        depth = SliceModel("Depth", SD.depth, SD.inline, SD.crossline)

        slice_models = [inline, xline, depth]
        slice_data_source = SliceDataSource(filename, **segyioargs)
        self._slice_data_source = slice_data_source

        self._context = SliceViewContext(slice_models, slice_data_source)
        self._context.show_indicators(True)

        self._slice_view_widget = SliceViewWidget(self._context, width, height,
                                                  dpi, self)

        layout = QVBoxLayout()

        self._settings_window = SettingsWindow(self._context, self)
        self._help_window = HelpWindow(self)

        self._toolbar = self._create_toolbar(color_maps)
        self._toolbar.setVisible(show_toolbar)
        layout.addWidget(self._toolbar)
        layout.addWidget(self._slice_view_widget)

        self.setLayout(layout)

    @property
    def context(self):
        """ :rtype: SliceViewContext"""
        return self._context

    @property
    def slice_data_source(self):
        """ :rtype: SliceDataSource"""
        return self._slice_data_source

    @property
    def toolbar(self):
        """ :rtype: QToolBar """
        return self._toolbar

    @property
    def slice_view_widget(self):
        """ :rtype: SliceViewWidget """
        return self._slice_view_widget

    @property
    def settings_window(self):
        """ :rtype: QWidget """
        return self._settings_window

    @property
    def help_window(self):
        """ :rtype: QWidget """
        return self._help_window

    # custom signal slots are required to be manually disconnected
    # https://stackoverflow.com/questions/15600014/pyqt-disconnect-slots-new-style
#    def __del__(self):
#        self._layout_combo.layout_changed.disconnect(self._slice_view_widget.set_plot_layout)

    def _create_toolbar(self, color_maps):
        toolbar = QToolBar()
        toolbar.setFloatable(False)
        toolbar.setMovable(False)

        self._layout_combo = LayoutCombo()
        self._layout_combo_action = QWidgetAction(self._layout_combo)
        self._layout_combo_action.setDefaultWidget(self._layout_combo)
        toolbar.addAction(self._layout_combo_action)
        self._layout_combo.layout_changed.connect(
            self._slice_view_widget.set_plot_layout)

        # self._colormap_combo = ColormapCombo(['seismic', 'spectral', 'RdGy', 'hot', 'jet', 'gray'])
        self._colormap_combo = ColormapCombo(color_maps)
        self._colormap_combo.currentIndexChanged[int].connect(
            self._colormap_changed)
        toolbar.addWidget(self._colormap_combo)

        self._save_button = QToolButton()
        self._save_button.setToolTip("Save as image")
        self._save_button.setIcon(resource_icon("table_export.png"))
        self._save_button.clicked.connect(self._save_figure)
        toolbar.addWidget(self._save_button)

        self._settings_button = QToolButton()
        self._settings_button.setToolTip("Toggle settings visibility")
        self._settings_button.setIcon(resource_icon("cog.png"))
        self._settings_button.setCheckable(True)
        self._settings_button.toggled.connect(self._show_settings)
        toolbar.addWidget(self._settings_button)

        self._help_button = QToolButton()
        self._help_button.setToolTip("View help")
        self._help_button.setIcon(resource_icon("help.png"))
        self._help_button.setCheckable(True)
        self._help_button.toggled.connect(self._show_help)
        toolbar.addWidget(self._help_button)

        def toggle_on_close(event):
            self._settings_button.setChecked(False)
            event.accept()

        def toggle_on_close_help(event):
            self._help_button.setChecked(False)
            event.accept()

        self._settings_window.closeEvent = toggle_on_close
        self._help_window.closeEvent = toggle_on_close_help

        self._colormap_combo.setCurrentIndex(45)
        self.set_default_layout()

        return toolbar

    def _colormap_changed(self, index):
        colormap = str(self._colormap_combo.itemText(index))
        self._context.set_colormap(colormap)

    def _interpolation_changed(self, index):
        interpolation_name = str(self._interpolation_combo.itemText(index))
        self._context.set_interpolation(interpolation_name)

    def _save_figure(self):
        formats = "Portable Network Graphic (*.png);;Adobe Acrobat (*.pdf);;Scalable Vector Graphics (*.svg)"
        output_file = QFileDialog.getSaveFileName(self, "Save as image",
                                                  "untitled.png", formats)

        output_file = str(output_file).strip()

        if len(output_file) == 0:
            return

        image_size = self._context.image_size
        if not image_size:
            fig = self._slice_view_widget
        else:
            w, h, dpi = image_size
            fig = SliceViewWidget(self._context, width=w, height=h, dpi=dpi)
            fig.set_plot_layout(
                self._slice_view_widget.layout_figure().current_layout())

        fig.layout_figure().savefig(output_file)

    def set_source_filename(self, filename):
        self._slice_data_source.set_source_filename(filename)

    def set_default_layout(self):
        # default slice view layout depends on the file size
        if self._slice_data_source.file_size < 8 * 10**8:
            self._layout_combo.setCurrentIndex(
                self._layout_combo.DEFAULT_SMALL_FILE_LAYOUT)
        else:
            self._layout_combo.setCurrentIndex(
                self._layout_combo.DEFAULT_LARGE_FILE_LAYOUT)

    def as_depth(self):
        self._context.samples_unit = 'Depth (m)'

    def _show_settings(self, toggled):
        self._settings_window.setVisible(toggled)
        if self._settings_window.isMinimized():
            self._settings_window.showNormal()

    def _show_help(self, toggled):
        self._help_window.setVisible(toggled)
        if self._help_window.isMinimized():
            self._help_window.showNormal()

    def show_toolbar(self,
                     toolbar,
                     layout_combo=True,
                     colormap=True,
                     save=True,
                     settings=True):
        self._toolbar.setVisible(toolbar)
        self._colormap_combo.setDisabled(not colormap)
        self._save_button.setDisabled(not save)
        self._settings_button.setDisabled(not settings)
        self._layout_combo_action.setVisible(layout_combo)
class MainWindow(MainWindowUI, MainWindowBase):
    save_perspective_action: QAction
    perspective_list_action: QWidgetAction
    perspective_combo_box: QComboBox
    dock_manager: QtAds.CDockManager

    def __init__(self, parent=None):
        super().__init__(parent)
        self.save_perspective_action = None
        self.perspective_list_action = None
        self.perspective_combo_box = None
        self.dock_manager = None

        self.setupUi(self)
        self.create_actions()

        # uncomment the following line if the tab close button should be
        # a QToolButton instead of a QPushButton
        # QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.configFlags() | QtAds.CDockManager.TabCloseButtonIsToolButton)

        # uncomment the following line if you want to use opaque undocking and
        # opaque splitter resizing
        #QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.DefaultOpaqueConfig)

        # uncomment the following line if you want a fixed tab width that does
        # not change if the visibility of the close button changes
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.RetainTabSizeWhenCloseButtonHidden, True)

        # uncomment the following line if you don't want close button on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHasCloseButton, False)

        # uncomment the following line if you don't want undock button on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHasUndockButton, False)

        # uncomment the following line if you don't want tabs menu button on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHasTabsMenuButton, False)

        # uncomment the following line if you don't want disabled buttons to appear on DockArea's title bar
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaHideDisabledButtons, True)

        # uncomment the following line if you want to show tabs menu button on DockArea's title bar only when there are more than one tab and at least of them has elided title
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.DockAreaDynamicTabsMenuButtonVisibility, True)

        # uncomment the following line if you want floating container to always show application title instead of active dock widget's title
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FloatingContainerHasWidgetTitle, False)

        # uncomment the following line if you want floating container to show active dock widget's icon instead of always showing application icon
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FloatingContainerHasWidgetIcon, True)

        # uncomment the following line if you want a central widget in the main dock container (the dock manager) without a titlebar
        # If you enable this code, you can test it in the demo with the Calendar 0
        # dock widget.
        #QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.HideSingleCentralWidgetTitleBar, True)

        # uncomment the following line to enable focus highlighting of the dock
        # widget that has the focus
        QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FocusHighlighting,
                                         True)

        # uncomment if you would like to enable an equal distribution of the
        # available size of a splitter to all contained dock widgets
        # QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.EqualSplitOnInsertion, True)

        # Now create the dock manager and its content
        self.dock_manager = QtAds.CDockManager(self)

        # Uncomment the following line to have the old style where the dock
        # area close button closes the active tab
        # QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.DockAreaHasCloseButton
        # | QtAds.CDockManager.DockAreaCloseButtonClosesTab)
        self.perspective_combo_box.activated[str].connect(
            self.dock_manager.openPerspective)

        self.create_content()
        # Default window geometry - center on screen
        self.resize(1280, 720)
        self.setGeometry(
            QStyle.alignedRect(
                Qt.LeftToRight, Qt.AlignCenter, self.frameSize(),
                QGuiApplication.primaryScreen().availableGeometry()))

        # self.restore_state()
        self.restore_perspectives()

    def create_content(self):
        # Test container docking
        dock_widget = self.create_calendar_dock_widget()
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
        special_dock_area = self.dock_manager.addDockWidget(
            QtAds.LeftDockWidgetArea, dock_widget)

        # For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified):
        special_dock_area.setAllowedAreas(QtAds.OuterDockAreas)
        # special_dock_area.setAllowedAreas(QtAds.LeftDockWidgetArea | QtAds.RightDockWidgetArea) # just for testing

        dock_widget = self.create_long_text_label_dock_widget()
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetFocusable, False)
        self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, dock_widget)
        file_system_widget = self.create_file_system_tree_dock_widget()
        tool_bar = file_system_widget.createDefaultToolBar()
        tool_bar.addAction(self.actionSaveState)
        tool_bar.addAction(self.actionRestoreState)
        file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable,
                                      False)
        append_feature_string_to_window_title(file_system_widget)
        self.dock_manager.addDockWidget(QtAds.BottomDockWidgetArea,
                                        file_system_widget)

        file_system_widget = self.create_file_system_tree_dock_widget()
        file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable,
                                      False)
        file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable,
                                      False)
        append_feature_string_to_window_title(file_system_widget)

        # Test custom factory - we inject a help button into the title bar
        QtAds.CDockComponentsFactory.setFactory(CCustomComponentsFactory())
        top_dock_area = self.dock_manager.addDockWidget(
            QtAds.TopDockWidgetArea, file_system_widget)
        QtAds.CDockComponentsFactory.resetDefaultFactory()

        # We create a calendar widget and clear all flags to prevent the dock area
        # from closing
        dock_widget = self.create_calendar_dock_widget()
        dock_widget.setTabToolTip("Tab ToolTip\nHodie est dies magna")
        dock_area = self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea,
                                                    dock_widget, top_dock_area)

        # Now we add a custom button to the dock area title bar that will create
        # new editor widgets when clicked
        custom_button = QToolButton(dock_area)
        custom_button.setToolTip("Create Editor")
        custom_button.setIcon(svg_icon(":/adsdemo/images/plus.svg"))
        custom_button.setAutoRaise(True)

        title_bar = dock_area.titleBar()
        index = title_bar.indexOf(title_bar.tabBar())
        title_bar.insertWidget(index + 1, custom_button)

        def on_button_clicked():
            dock_widget = self.create_editor_widget()
            dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose,
                                   True)
            self.dock_manager.addDockWidgetTabToArea(dock_widget, dock_area)
            dock_widget.closeRequested.connect(self.on_editor_close_requested)

        custom_button.clicked.connect(on_button_clicked)

        # Test dock area docking
        right_dock_area = self.dock_manager.addDockWidget(
            QtAds.RightDockWidgetArea,
            self.create_long_text_label_dock_widget(), top_dock_area)
        self.dock_manager.addDockWidget(
            QtAds.TopDockWidgetArea, self.create_long_text_label_dock_widget(),
            right_dock_area)

        bottom_dock_area = self.dock_manager.addDockWidget(
            QtAds.BottomDockWidgetArea,
            self.create_long_text_label_dock_widget(), right_dock_area)

        self.dock_manager.addDockWidget(
            QtAds.CenterDockWidgetArea,
            self.create_long_text_label_dock_widget(), right_dock_area)
        self.dock_manager.addDockWidget(
            QtAds.CenterDockWidgetArea,
            self.create_long_text_label_dock_widget(), bottom_dock_area)

        action = self.menuTests.addAction("Set {} Floating".format(
            dock_widget.windowTitle()))
        action.triggered.connect(dock_widget.setFloating)
        action = self.menuTests.addAction("Set {} As Current Tab".format(
            dock_widget.windowTitle()))
        action.triggered.connect(dock_widget.setAsCurrentTab)
        action = self.menuTests.addAction("Raise {}".format(
            dock_widget.windowTitle()))
        action.triggered.connect(dock_widget.raise_)

        if ACTIVEX_AVAILABLE:
            flags = self.dock_manager.configFlags()
            if flags & QtAds.CDockManager.OpaqueUndocking:
                self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea,
                                                self.create_activex_widget(),
                                                right_dock_area)

        for dock_widget in self.dock_manager.dockWidgetsMap().values():
            dock_widget.viewToggled.connect(self.on_view_toggled)
            dock_widget.visibilityChanged.connect(
                self.on_view_visibility_changed)

    def create_actions(self):
        self.toolBar.addAction(self.actionSaveState)
        self.toolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.actionSaveState.setIcon(svg_icon(":/adsdemo/images/save.svg"))
        self.toolBar.addAction(self.actionRestoreState)
        self.actionRestoreState.setIcon(
            svg_icon(":/adsdemo/images/restore.svg"))

        self.save_perspective_action = QAction("Create Perspective", self)
        self.save_perspective_action.setIcon(
            svg_icon(":/adsdemo/images/picture_in_picture.svg"))
        self.save_perspective_action.triggered.connect(self.save_perspective)
        self.perspective_list_action = QWidgetAction(self)
        self.perspective_combo_box = QComboBox(self)
        self.perspective_combo_box.setSizeAdjustPolicy(
            QComboBox.AdjustToContents)
        self.perspective_combo_box.setSizePolicy(QSizePolicy.Preferred,
                                                 QSizePolicy.Preferred)
        self.perspective_list_action.setDefaultWidget(
            self.perspective_combo_box)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.perspective_list_action)
        self.toolBar.addAction(self.save_perspective_action)

        a = self.toolBar.addAction("Create Floating Editor")
        a.setProperty("Floating", True)
        a.setToolTip(
            "Creates floating dynamic dockable editor windows that are deleted on close"
        )
        a.setIcon(svg_icon(":/adsdemo/images/note_add.svg"))
        a.triggered.connect(self.create_editor)
        self.menuTests.addAction(a)

        a = self.toolBar.addAction("Create Docked Editor")
        a.setProperty("Floating", False)
        a.setToolTip(
            "Creates a docked editor windows that are deleted on close")
        a.setIcon(svg_icon(":/adsdemo/images/docked_editor.svg"))
        a.triggered.connect(self.create_editor)
        self.menuTests.addAction(a)

        a = self.toolBar.addAction("Create Floating Table")
        a.setToolTip(
            "Creates floating dynamic dockable table with millions of entries")
        a.setIcon(svg_icon(":/adsdemo/images/grid_on.svg"))
        a.triggered.connect(self.create_table)
        self.menuTests.addAction(a)

        self.menuTests.addSeparator()
        a = self.menuTests.addAction("Show Status Dialog")
        a.triggered.connect(self.show_status_dialog)
        self.menuTests.addSeparator()

    def closeEvent(self, event: QCloseEvent):
        self.save_state()
        super().closeEvent(event)

    def on_actionSaveState_triggered(self, state: bool):
        qDebug("MainWindow::on_action_save_state_triggered")
        self.save_state()

    def on_actionRestoreState_triggered(self, state: bool):
        qDebug("MainWindow::on_action_restore_state_triggered")
        self.restore_state()

    def save_perspective(self):
        perspective_name, ok = QInputDialog.getText(self, "Save perspective",
                                                    "Enter unique name:")

        if ok and perspective_name:
            self.dock_manager.addPerspective(perspective_name)
            _ = QSignalBlocker(self.perspective_combo_box)
            self.perspective_combo_box.clear()
            self.perspective_combo_box.addItems(
                self.dock_manager.perspectiveNames())
            self.perspective_combo_box.setCurrentText(perspective_name)

            self.save_perspectives()

    def on_view_toggled(self, open: bool):
        dock_widget = self.sender()
        if dock_widget is None:
            return

        qDebug("{} view_toggled({})".format(dock_widget.objectName(), open))

    def on_view_visibility_changed(self, visible: bool):
        dock_widget = self.sender()
        if dock_widget is None:
            return

        # qDebug("{} visibility_changed({})".format(dock_widget.objectName(), visible))

    def create_editor(self):
        sender = self.sender()
        floating = sender.property("Floating")
        print("Floating:", floating)
        dock_widget = self.create_editor_widget()
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
        dock_widget.closeRequested.connect(self.on_editor_close_requested)

        if floating:
            floating_widget = self.dock_manager.addDockWidgetFloating(
                dock_widget)
            floating_widget.move(QPoint(20, 20))
        else:
            self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea,
                                            dock_widget)

    def on_editor_close_requested(self):
        dock_widget = self.sender()
        result = QMessageBox.question(
            self, "Close Editor",
            "Editor {} contains unsaved changes? Would you like to close it?".
            format(dock_widget.windowTitle()))
        if result == QMessageBox.Yes:
            dock_widget.closeDockWidget()

    def create_table(self):
        dock_widget = self.create_table_widget()
        dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
        floating_widget = self.dock_manager.addDockWidgetFloating(dock_widget)
        floating_widget.move(QPoint(40, 40))

    def show_status_dialog(self):
        dialog = CStatusDialog(self.dock_manager)
        dialog.exec_()

    def save_state(self):
        '''
        Saves the dock manager state and the main window geometry
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        settings.setValue("mainWindow/Geometry", self.saveGeometry())
        settings.setValue("mainWindow/State", self.saveState())
        settings.setValue("mainWindow/DockingState",
                          self.dock_manager.saveState())

    def restore_state(self):
        '''
        Restores the dock manager state
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        geom = settings.value("mainWindow/Geometry")
        if geom is not None:
            self.restoreGeometry(geom)

        state = settings.value("mainWindow/State")
        if state is not None:
            self.restoreState(state)

        state = settings.value("mainWindow/DockingState")
        if state is not None:
            self.dock_manager.restore_state(state)

    def save_perspectives(self):
        '''
        Save the list of perspectives
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        self.dock_manager.savePerspectives(settings)

    def restore_perspectives(self):
        '''
        Restore the perspective listo of the dock manager
        '''
        settings = QSettings("Settings.ini", QSettings.IniFormat)
        self.dock_manager.loadPerspectives(settings)
        self.perspective_combo_box.clear()
        self.perspective_combo_box.addItems(
            self.dock_manager.perspectiveNames())

    def save_perspective(self):
        perspective_name, ok = QInputDialog.getText(self, 'Save perspective',
                                                    'Enter unique name:')
        if ok and perspective_name:
            self.dock_manager.addPerspective(perspective_name)
            _ = QSignalBlocker(self.perspective_combo_box)
            self.perspective_combo_box.clear()
            self.perspective_combo_box.addItems(
                self.dock_manager.perspectiveNames())
            self.perspective_combo_box.setCurrentText(perspective_name)
            self.save_perspectives()

    def create_long_text_label_dock_widget(self) -> QtAds.CDockWidget:
        label = QLabel()
        label.setWordWrap(True)
        label.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        label.setText('''Label {} {} - Lorem ipsum dolor sit amet, consectetuer
    adipiscing elit.  Aenean commodo ligula eget dolor. Aenean massa. Cum
    sociis natoque penatibus et magnis dis parturient montes, nascetur
    ridiculus mus.  Donec quam felis, ultricies nec, pellentesque eu, pretium
    quis, sem.  Nulla consequat massa quis enim. Donec pede justo, fringilla
    vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut,
    imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis
    pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi.
    Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu,
    consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra
    quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet.
        '''.format(_State.label_count,
                   datetime.datetime.now().strftime("%H:%M:%S:%f")))
        dock_widget = QtAds.CDockWidget("Label {}".format(_State.label_count))
        _State.label_count += 1
        dock_widget.setWidget(label)

        self.menuView.addAction(dock_widget.toggleViewAction())
        return dock_widget

    def create_calendar_dock_widget(self) -> QtAds.CDockWidget:
        widget = QCalendarWidget()

        dock_widget = QtAds.CDockWidget("Calendar {}".format(
            _State.calendar_count))
        _State.calendar_count += 1
        # The following lines are for testing the setWidget() and takeWidget()
        # functionality
        dock_widget.setWidget(widget)
        dock_widget.setWidget(
            widget
        )  # what happens if we set a widget if a widget is already set
        dock_widget.takeWidget()  # we remove the widget
        dock_widget.setWidget(
            widget)  # and set the widget again - there should be no error
        dock_widget.setToggleViewActionMode(QtAds.CDockWidget.ActionModeShow)
        dock_widget.setIcon(svg_icon(":/adsdemo/images/date_range.svg"))
        self.menuView.addAction(dock_widget.toggleViewAction())
        return dock_widget

    def create_file_system_tree_dock_widget(self) -> QtAds.CDockWidget:
        widget = QTreeView()
        widget.setFrameShape(QFrame.NoFrame)

        m = QFileSystemModel(widget)
        m.setRootPath(QDir.currentPath())
        widget.setModel(m)

        dock_widget = QtAds.CDockWidget("Filesystem {}".format(
            _State.file_system_count))
        _State.file_system_count += 1
        dock_widget.setWidget(widget)
        self.menuView.addAction(dock_widget.toggleViewAction())
        return dock_widget

    def create_editor_widget(self) -> QtAds.CDockWidget:
        widget = QPlainTextEdit()
        widget.setPlaceholderText(
            "This is an editor. If you close the editor, it will be "
            "deleted. Enter your text here.")
        widget.setStyleSheet("border: none")
        dock_widget = QtAds.CDockWidget("Editor {}".format(
            _State.editor_count))
        _State.editor_count += 1
        dock_widget.setWidget(widget)
        dock_widget.setIcon(svg_icon(":/adsdemo/images/edit.svg"))
        dock_widget.setFeature(QtAds.CDockWidget.CustomCloseHandling, True)
        self.menuView.addAction(dock_widget.toggleViewAction())

        options_menu = QMenu(dock_widget)
        options_menu.setTitle("Options")
        options_menu.setToolTip(options_menu.title())
        options_menu.setIcon(
            svg_icon(":/adsdemo/images/custom-menu-button.svg"))
        menu_action = options_menu.menuAction()
        # The object name of the action will be set for the QToolButton that
        # is created in the dock area title bar. You can use this name for CSS
        # styling
        menu_action.setObjectName("options_menu")
        dock_widget.setTitleBarActions([options_menu.menuAction()])
        a = options_menu.addAction("Clear Editor")
        a.triggered.connect(widget.clear)

        return dock_widget

    def create_table_widget(self) -> QtAds.CDockWidget:
        widget = CMinSizeTableWidget()
        dock_widget = QtAds.CDockWidget("Table {}".format(_State.table_count))
        _State.table_count += 1
        COLCOUNT = 5
        ROWCOUNT = 30
        widget.setColumnCount(COLCOUNT)
        widget.setRowCount(ROWCOUNT)
        for col in range(ROWCOUNT):
            widget.setHorizontalHeaderItem(
                col, QTableWidgetItem("Col {}".format(col + 1)))
            for row in range(ROWCOUNT):
                widget.setItem(
                    row, col,
                    QTableWidgetItem("T {:}-{:}".format(row + 1, col + 1)))

        dock_widget.setWidget(widget)
        dock_widget.setIcon(svg_icon(":/adsdemo/images/grid_on.svg"))
        dock_widget.setMinimumSizeHintMode(
            QtAds.CDockWidget.MinimumSizeHintFromContent)
        toolbar = dock_widget.createDefaultToolBar()
        action = toolbar.addAction(svg_icon(":/adsdemo/images/fullscreen.svg"),
                                   "Toggle Fullscreen")

        def on_toggle_fullscreen():
            if dock_widget.isFullScreen():
                dock_widget.showNormal()
            else:
                dock_widget.showFullScreen()

        action.triggered.connect(on_toggle_fullscreen)
        self.menuView.addAction(dock_widget.toggleViewAction())
        return dock_widget

    def create_activex_widget(self,
                              parent: QWidget = None) -> QtAds.CDockWidget:
        widget = QAxWidget("{6bf52a52-394a-11d3-b153-00c04f79faa6}", parent)
        dock_widget = QtAds.CDockWidget("Active X {}".format(
            _State.activex_count))
        _State.activex_count += 1
        dock_widget.setWidget(widget)
        self.menuView.addAction(dock_widget.toggleViewAction())
        return dock_widget
Beispiel #41
0
 def __init__(self, widget, parent=None):
     QWidgetAction.__init__(self, parent)
     self.widget = widget
     self.setDefaultWidget(self.widget)
     widget.setMyAction(self)  # Let widget know about action.