예제 #1
0
    def initUI(self):
        QToolTip.setFont(QFont('SansSerif', 10))
        self.setToolTip('This is a <b>QWidget</b> widget.')
        #quitBtn = QPushButton('Quit', self)
        #quitBtn.clicked.connect(self.quitBtnEvent())
        #quitBtn.clicked.connect(QCoreApplication.instance().quit)
        #quitBtn.setToolTip('This is a <b>QPushButton</b> widget.')
        #quitBtn.resize(quitBtn.sizeHint())

        exitAction = QAction(QIcon('application-exit-4.png'), '&Exit', self)
        exitAction.setShortcut('Alt+F4')
        exitAction.setStatusTip('Exit Application')
        exitAction.triggered.connect(qApp.quit)

        menuBar = QMenuBar()
        fileMenu = menuBar.addMenu('&File')
        fileMenu.addAction(exitAction)
        fileMenu.resize(fileMenu.sizeHint())

        toolBar = QToolBar(self)
        toolBar.addAction(exitAction)
        #toolBar.resize(toolBar.sizeHint())
        toolBar.setFixedHeight(60)

        hozLine = QFrame()
        hozLine.setFrameStyle(QFrame.HLine)
        #hozLine.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Expanding)

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

        grid = QGridLayout()
        lbl_1 = QLabel('1,1')
        lbl_2 = QLabel('1,2')
        lbl_3 = QLabel('2,1')
        lbl_4 = QLabel('2,2')
        grid.addWidget(lbl_1, 1, 1)
        grid.addWidget(lbl_2, 1, 2)
        grid.addWidget(lbl_3, 2, 1)
        grid.addWidget(lbl_4, 2, 2)

        vbox = QVBoxLayout()
        vbox.addWidget(menuBar)
        vbox.addWidget(hozLine)
        vbox.addWidget(toolBar)
        # vbox.addWidget(hozLine)
        vbox.addLayout(grid)
        vbox.addStretch(1)
        vbox.addWidget(statusBar)

        self.setLayout(vbox)

        self.setGeometry(300, 300, 500, 500)
        self.setWindowTitle('Photos')
        self.setWindowIcon(QIcon('camera-photo-5.png'))
        self.center()
        self.show()
예제 #2
0
class ControlPanelWindow(QDialog):
    def __init__(self, parent, cli_iface, iface_name):
        super(ControlPanelWindow, self).__init__(parent)
        self.setWindowTitle('SLCAN Adapter Control Panel')
        self.setAttribute(Qt.WA_DeleteOnClose)              # This is required to stop background timers!

        self._cli_iface = cli_iface
        self._iface_name = iface_name

        self._state_widget = StateWidget(self, self._cli_iface)
        self._config_widget = ConfigWidget(self, self._cli_iface)
        self._cli_widget = CLIWidget(self, self._cli_iface)

        self._tab_widget = QTabWidget(self)
        self._tab_widget.addTab(self._state_widget, get_icon('dashboard'), 'Adapter State')
        self._tab_widget.addTab(self._config_widget, get_icon('wrench'), 'Configuration')
        self._tab_widget.addTab(self._cli_widget, get_icon('terminal'), 'Command Line')

        self._status_bar = QStatusBar(self)
        self._status_bar.setSizeGripEnabled(False)

        iface_name_label = QLabel(iface_name.split('/')[-1], self)
        iface_name_label.setFont(get_monospace_font())

        layout = QVBoxLayout(self)
        layout.addWidget(iface_name_label)
        layout.addWidget(self._tab_widget)
        layout.addWidget(self._status_bar)

        left, top, right, bottom = layout.getContentsMargins()
        bottom = 0
        layout.setContentsMargins(left, top, right, bottom)

        self.setLayout(layout)
        self.resize(400, 400)

    def closeEvent(self, close_event):
        if self._config_widget.have_unsaved_changes:
            if request_confirmation('Save changes?',
                                    'You made changes to the adapter configuration that were not saved. '
                                    'Do you want to go back and save them?',
                                    parent=self):
                close_event.ignore()
                self._tab_widget.setCurrentWidget(self._config_widget)
                return

        super(ControlPanelWindow, self).closeEvent(close_event)

    def show_message(self, text, *fmt, duration=0):
        self._status_bar.showMessage(text % fmt, duration * 1000)
예제 #3
0
class Tab(QWidget):
    def __init__(self, parent, configuration):
        QWidget.__init__(self, parent)
        self._configuration = configuration

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        main_widget = QWidget(self)
        self._layout_main = QVBoxLayout()
        self._layout_main.setContentsMargins(0, 0, 0, 0)
        self._layout_main.setSpacing(6)
        main_widget.setLayout(self._layout_main)
        layout.addWidget(main_widget)
        self._status_bar = QStatusBar()
        layout.addWidget(self._status_bar)
        self.setLayout(layout)

    def _add_widget(self, widget):
        self._layout_main.addWidget(widget)

    def set_error_message(self, msg):
        self._status_bar.showMessage(msg)
예제 #4
0
class NodePropertiesWindow(QDialog):
    def __init__(
        self, parent, node, target_node_id, file_server_widget, node_monitor, dynamic_node_id_allocator_widget
    ):
        super(NodePropertiesWindow, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)  # This is required to stop background timers!
        self.setWindowTitle("Node Properties [%d]" % target_node_id)
        self.setMinimumWidth(640)

        self._target_node_id = target_node_id
        self._node = node
        self._file_server_widget = file_server_widget

        self._info_box = InfoBox(self, target_node_id, node_monitor)
        self._controls = Controls(self, node, target_node_id, file_server_widget, dynamic_node_id_allocator_widget)
        self._config_params = ConfigParams(self, node, target_node_id)

        self._status_bar = QStatusBar(self)
        self._status_bar.setSizeGripEnabled(False)

        layout = QVBoxLayout(self)
        layout.addWidget(self._info_box)
        layout.addWidget(self._controls)
        layout.addWidget(self._config_params)
        layout.addWidget(self._status_bar)

        left, top, right, bottom = layout.getContentsMargins()
        bottom = 0
        layout.setContentsMargins(left, top, right, bottom)

        self.setLayout(layout)

    def show_message(self, text, *fmt, duration=0):
        self._status_bar.showMessage(text % fmt, duration * 1000)

    @property
    def target_node_id(self):
        return self._target_node_id
예제 #5
0
class EEGStudio(QMainWindow):
	"""docstring for EEGStudio"""
	def __init__(self):
		super(EEGStudio, self).__init__()
		self.setWindowTitle('EEG Studio v1.0')
		self.setContentsMargins(10, 10, 10, 10)
		# Variables
		self.D = None
		self.X = None
		self.fs = 0
		self.label = list()
		self.markPos = list()
		self.markItem = list()
		self.maxDuration = 0
		# Main widgets
		self.fileDialog = FilePathDialog('EEG file:', 'Open file', 'EEG files (*.csv)')
		self.videoDialog = FilePathDialog('Video file:', 'Open video', 'Video files (*.mp4)')
		self.channelPanel = CheckBoxPanel(title='Channels')
		self.filteringForm = FilteringForm(title='Filtering')
		# Video player
		self.player = VideoPlayer()
		self.player.setSize(640, 480)
		self.player.error.connect(self.mediaError)
		self.player.stateChanged.connect(self.stateChanged)
		self.player.positionChanged.connect(self.positionChanged)
		self.player.durationChanged.connect(self.durationChanged)
		self.player.mediaStatusChanged.connect(self.mediaStatusChanged)
		self.player.videoAvailableChanged.connect(self.videoAvailableChanged)
		# Threads
		self.eegViewer = EEGViewer(mode='single')
		# EditLines
		self.timeEdit = QLineEdit('--:--:--')
		self.timeEdit.setAlignment(Qt.AlignCenter)
		self.indexEdit = QLineEdit('')
		self.indexEdit.setAlignment(Qt.AlignCenter)
		# Buttons
		self.icon = QWidget().style()
		self.loadButton = QPushButton('Load')
		self.loadButton.setIcon(self.icon.standardIcon(QStyle.SP_BrowserReload))
		self.loadButton.clicked.connect(self.loadFiles)
		self.saveButton = QPushButton('Save')
		self.saveButton.setIcon(self.icon.standardIcon(QStyle.SP_DialogSaveButton))
		self.saveButton.setEnabled(False)
		self.saveButton.clicked.connect(self.saveLabels)
		self.addButton = QPushButton('Add')
		self.addButton.setEnabled(False)
		self.addButton.clicked.connect(lambda: self.addLabel(None))
		self.applyButton = QPushButton('Apply')
		self.applyButton.setIcon(self.icon.standardIcon(QStyle.SP_DialogApplyButton))
		self.applyButton.setEnabled(False)
		self.applyButton.clicked.connect(self.applyParameters)
		self.playButton = QPushButton()
		self.playButton.setIcon(self.icon.standardIcon(QStyle.SP_MediaPlay))
		self.playButton.clicked.connect(self.play)
		self.playButton.setEnabled(False)
		self.stopButton = QPushButton()
		self.stopButton.setIcon(self.icon.standardIcon(QStyle.SP_MediaStop))
		self.stopButton.clicked.connect(self.stop)
		self.stopButton.setEnabled(False)
		self.syncButton = QPushButton('Sync')
		self.syncButton.setEnabled(False)
		self.syncButton.clicked.connect(self.syncTime)
		# Slider
		self.positionSlider = QSlider(Qt.Horizontal)
		self.positionSlider.setRange(0, 1)
		self.positionSlider.setTickPosition(2)
		self.positionSlider.setTickInterval(60000)
		self.positionSlider.sliderMoved.connect(self.setPosition)
		# GroupBoxes
		syncGBox = QGroupBox('Synchronization')
		syncGBox.setAlignment(Qt.AlignCenter)
		labelingGBox = QGroupBox('Labeling')
		labelingGBox.setAlignment(Qt.AlignCenter)
		# Layouts
		sourceLayout = QGridLayout()
		sourceLayout.setColumnStretch(0, 14)
		sourceLayout.setColumnStretch(1, 1)
		sourceLayout.setVerticalSpacing(0)
		sourceLayout.addWidget(self.fileDialog, 0, 0)
		sourceLayout.addWidget(self.videoDialog, 1, 0)
		sourceLayout.addWidget(self.loadButton, 0, 1, 2, 1)

		paramsLayout = QHBoxLayout()
		paramsLayout.addWidget(self.filteringForm, 7)
		paramsLayout.addWidget(self.applyButton,1)

		syncLayout = QGridLayout()
		syncLayout.addWidget(self.timeEdit)
		syncLayout.addWidget(self.syncButton)
		syncGBox.setLayout(syncLayout)

		labelingLayout = QGridLayout()
		labelingLayout.addWidget(QLabel('Index:'), 0, 0, alignment=Qt.AlignRight)
		labelingLayout.addWidget(self.indexEdit, 0, 1)
		labelingLayout.addWidget(self.addButton, 0, 2)
		labelingLayout.addWidget(self.saveButton, 1, 0, 1, 3)
		labelingGBox.setLayout(labelingLayout)

		controlLayout = QHBoxLayout()
		controlLayout.addWidget(self.playButton, 1)
		controlLayout.addWidget(self.stopButton, 1)
		controlLayout.addWidget(self.positionSlider, 15)
		controlLayout.addWidget(syncGBox, 1)

		mainLayout = QVBoxLayout()
		mainLayout.addLayout(sourceLayout, 1)
		mainLayout.addStretch(1)
		mainLayout.addWidget(self.channelPanel, 1)
		mainLayout.addStretch(1)
		mainLayout.addLayout(paramsLayout, 1)
		mainLayout.addStretch(1)
		mainLayout.addWidget(labelingGBox, 1, alignment=Qt.AlignCenter)
		mainLayout.addStretch(1)
		mainLayout.addLayout(controlLayout, 1)
		# Main widget
		mainWidget = QWidget()
		mainWidget.setLayout(mainLayout)
		self.setCentralWidget(mainWidget)
		# Status bar
		self.statusBar = QStatusBar()
		self.setStatusBar(self.statusBar)
		self.statusBar.showMessage('¡System ready!')

	def loadFiles(self):
		try:
			path = self.fileDialog.getFullPath()
			self.D = pd.read_csv(path)
			self.statusBar.showMessage('EEG file was successfully loaded!')
			self.positionSlider.setRange(0, self.D.index.size)
			self.createChannelWidgets()
			self.eegViewer.show()
			path = self.videoDialog.getFullPath()
			self.player.loadMedia(path)
			self.applyButton.setEnabled(True)
		except FileNotFoundError:
			self.statusBar.showMessage('EEG file not found!')

	def mediaError(self):
		self.statusBar.showMessage('Error: {}'.format(self.player.errorString()))

	def setPosition(self, position):
		if self.player.isVideoAvailable():
			self.player.setPosition(position)
			self.syncTime()

	def durationChanged(self, duration):
		self.maxDuration = duration
		self.positionSlider.setRange(0, duration)
		self.timeEdit.setText('00:00:00')

	def positionChanged(self, position):
		self.positionSlider.setValue(position)
		seconds = round(position / 1000)
		time_str = str(timedelta(seconds=seconds))
		self.timeEdit.setText(time_str)

	def stateChanged(self, state):
		if state == VideoPlayer.PlayingState:
			self.playButton.setIcon(self.icon.standardIcon(QStyle.SP_MediaPause))
			self.statusBar.showMessage('Running...')
		else:
			self.playButton.setIcon(self.icon.standardIcon(QStyle.SP_MediaPlay))
			self.statusBar.showMessage('Paused!')
			
	def mediaStatusChanged(self, status):
		if status == self.player.LoadingMedia:
			self.statusBar.showMessage('Loading video...')
		elif status == self.player.LoadedMedia:
			self.player.stop()
			self.syncButton.setEnabled(True)
			self.statusBar.showMessage('Video was successfully loaded!')

	def videoAvailableChanged(self, videoAvailable):
		if videoAvailable == True:
			self.player.show()
		else:
			self.player.hide()

	def createChannelWidgets(self):
		columns = self.D.columns
		self.channelPanel.setOptions(columns)

	def applyParameters(self):
		self.X = self.D.copy()
		param = self.filteringForm.getValues()
		channel = self.channelPanel.getChecked()
		if len(channel) == 0:
			self.statusBar.showMessage('You must select at least one channel')
			return
		color = self.channelPanel.getColors()
		numCh = param['n_channels']
		self.fs = param['fs']
		notch(self.X, self.fs, param['notch'], numCh)
		bandpass(self.X, self.fs, param['low'], param['high'], param['order'], numCh)
		self.X[self.X.columns[:numCh]] = MinMaxScaler().fit_transform(self.X[self.X.columns[:numCh]])
		self.label = np.zeros((self.X.index.size,), dtype=int)
		if 'Label' in self.X.columns:
			self.label = self.X['Label'].to_numpy(copy=True)
		self.eegViewer.configure(channel, color, self.fs * 1.2, self.fs)
		self.eegViewer.plotData(self.X)
		self.eegViewer.setPosition(0)
		self.markPos.clear()
		self.markItem.clear()
		marks = np.where(self.label == 1)[0]
		for index in marks:
			self.addLabel(index)
		self.addButton.setEnabled(True)
		self.playButton.setEnabled(True)
		self.playButton.setFocus()
		self.stopButton.setEnabled(True)
		self.saveButton.setEnabled(True)
		self.applyButton.setEnabled(False)

	def play(self):
		if self.player.isVideoAvailable():
			self.player.toggle()
		if self.eegViewer.getState() == EEGViewer.StoppedState:
			self.eegViewer.play()
		else:
			self.eegViewer.toggle()
		self.syncTime()
		self.playButton.setFocus()

	def stop(self):
		if self.player.isVideoAvailable():
			self.player.stop()
		self.eegViewer.stop()
		self.playButton.setFocus()
		self.applyButton.setEnabled(True)

	def timeToSeconds(self):
		time_str = self.timeEdit.text()
		time_obj = pd.to_timedelta(time_str)
		seconds = int(time_obj.total_seconds())
		return seconds

	def syncTime(self):
		seconds = self.timeToSeconds()
		position_vid = seconds * 1000
		position_eeg = seconds * self.fs
		if position_vid <= self.maxDuration:
			self.player.setPosition(position_vid)
		self.eegViewer.setPosition(position_eeg)
		self.playButton.setFocus()

	def addLabel(self, index=None):
		position = int(self.indexEdit.text().strip()) if index is None else index
		if position < 0 or position > self.D.index.size:
			self.statusBar.showMessage('Index {} does not exist!'.format(position))
		else:
			mark = self.eegViewer.addMark(position)
			mark.sigPositionChangeFinished.connect(self.markMoved)
			self.markPos.append(position)
			self.markItem.append(mark)
			self.label[position] = 1
			self.indexEdit.setText('')
			self.playButton.setFocus()

	def markMoved(self):
		markPos = np.array(self.markPos, dtype=int)
		linePos = np.array([line.getXPos() for line in self.markItem], dtype=int)
		moved = np.where(markPos != linePos)[0]
		old_index = markPos[moved]
		self.label[old_index] = 0
		new_index = linePos[moved]
		self.label[new_index] = 1
		self.markPos = linePos.tolist()
		self.statusBar.showMessage(f'Label moved from {old_index} to {new_index}')

	def saveLabels(self):
		self.D['Label'] = self.label
		path = self.fileDialog.getFullPath()
		path = path.split('.')[0]
		path += '_Label.csv'
		self.D.to_csv(path, index=False)
		self.statusBar.showMessage('Labeled EEG file saved as {}'.format(path))
예제 #6
0
class AppWindow(QMainWindow):
    onRestart = pyqtSignal(name='onRestart')

    def __init__(self, dwarf_args, flags=None):
        super(AppWindow, self).__init__(flags)

        self.dwarf_args = dwarf_args

        self.session_manager = SessionManager(self)
        self.session_manager.sessionCreated.connect(self.session_created)
        self.session_manager.sessionStopped.connect(self.session_stopped)
        self.session_manager.sessionClosed.connect(self.session_closed)

        self._tab_order = [
            'memory', 'modules', 'ranges', 'jvm-inspector', 'jvm-debugger'
        ]

        self.menu = self.menuBar()
        self._is_newer_dwarf = False
        self.view_menu = None

        #dockwidgets
        self.watchers_dwidget = None
        self.hooks_dwiget = None
        self.bookmarks_dwiget = None
        self.registers_dock = None
        self.console_dock = None
        self.backtrace_dock = None
        self.threads_dock = None
        #panels
        self.asm_panel = None
        self.console_panel = None
        self.context_panel = None
        self.backtrace_panel = None
        self.contexts_list_panel = None
        self.data_panel = None
        self.emulator_panel = None
        self.ftrace_panel = None
        self.hooks_panel = None
        self.bookmarks_panel = None
        self.smali_panel = None
        self.java_inspector_panel = None
        self.java_explorer_panel = None
        self.java_trace_panel = None
        self.memory_panel = None
        self.modules_panel = None
        self.ranges_panel = None
        self.search_panel = None
        self.trace_panel = None
        self.watchers_panel = None
        self.welcome_window = None

        self._ui_elems = []

        self.setWindowTitle(
            'Dwarf - A debugger for reverse engineers, crackers and security analyst'
        )

        # load external assets
        _app = QApplication.instance()

        self.remove_tmp_dir()

        # themes
        self.prefs = Prefs()
        self.set_theme(self.prefs.get('dwarf_ui_theme', 'black'))

        # load font
        if os.path.exists(utils.resource_path('assets/Anton.ttf')):
            QFontDatabase.addApplicationFont(
                utils.resource_path('assets/Anton.ttf'))
        if os.path.exists(utils.resource_path('assets/OpenSans-Regular.ttf')):
            QFontDatabase.addApplicationFont(
                utils.resource_path('assets/OpenSans-Regular.ttf'))
            font = QFont("OpenSans", 9, QFont.Normal)
            # TODO: add settingsdlg
            font_size = self.prefs.get('dwarf_ui_font_size', 12)
            font.setPixelSize(font_size)
            _app.setFont(font)
            if os.path.exists(utils.resource_path('assets/OpenSans-Bold.ttf')):
                QFontDatabase.addApplicationFont(
                    utils.resource_path('assets/OpenSans-Bold.ttf'))

        # mainwindow statusbar
        self.progressbar = QProgressBar()
        self.progressbar.setRange(0, 0)
        self.progressbar.setVisible(False)
        self.progressbar.setFixedHeight(15)
        self.progressbar.setFixedWidth(100)
        self.progressbar.setTextVisible(False)
        self.progressbar.setValue(30)
        self.statusbar = QStatusBar(self)
        self.statusbar.setAutoFillBackground(False)
        self.statusbar.addPermanentWidget(self.progressbar)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        self.main_tabs = QTabWidget(self)
        self.main_tabs.setMovable(False)
        self.main_tabs.setTabsClosable(True)
        self.main_tabs.setAutoFillBackground(True)
        self.main_tabs.tabCloseRequested.connect(self._on_close_tab)
        self.setCentralWidget(self.main_tabs)

        if self.dwarf_args.package is None:
            self.welcome_window = WelcomeDialog(self)
            self.welcome_window.setModal(True)
            self.welcome_window.onIsNewerVersion.connect(
                self._enable_update_menu)
            self.welcome_window.onUpdateComplete.connect(
                self._on_dwarf_updated)
            self.welcome_window.setWindowTitle(
                'Welcome to Dwarf - A debugger for reverse engineers, crackers and security analyst'
            )
            self.welcome_window.onSessionSelected.connect(self._start_session)
            self.welcome_window.onSessionRestore.connect(self._restore_session)
            # wait for welcome screen
            self.hide()
            self.welcome_window.show()
        else:
            if dwarf_args.package is not None:
                if dwarf_args.type is None:
                    # no device given check if package is local path
                    if os.path.exists(dwarf_args.package):
                        print('* Starting new LocalSession')
                        self._start_session('local')
                    else:
                        print('use -t to set sessiontype')
                        exit(0)
                else:
                    print('* Starting new Session')
                    self._start_session(dwarf_args.type)

    def _setup_main_menu(self):
        self.menu = self.menuBar()
        dwarf_menu = QMenu('Dwarf', self)
        theme = QMenu('Theme', dwarf_menu)
        theme.addAction('Black')
        theme.addAction('Dark')
        theme.addAction('Light')
        theme.triggered.connect(self._set_theme)
        dwarf_menu.addMenu(theme)
        dwarf_menu.addSeparator()
        if self._is_newer_dwarf:
            dwarf_menu.addAction('Update', self._update_dwarf)
        dwarf_menu.addAction('Close', self.session_manager.session.stop)
        self.menu.addMenu(dwarf_menu)

        session = self.session_manager.session
        if session is not None:
            session_menu = session.main_menu
            if isinstance(session_menu, list):
                for menu in session_menu:
                    self.menu.addMenu(menu)
            else:
                self.menu.addMenu(session_menu)

        self.view_menu = QMenu('View', self)
        subview_menu = QMenu('Subview', self.view_menu)
        subview_menu.addAction('Search',
                               lambda: self.show_main_tab('search'),
                               shortcut=QKeySequence(Qt.CTRL + Qt.Key_F3))
        subview_menu.addAction('Emulator',
                               lambda: self.show_main_tab('emulator'),
                               shortcut=QKeySequence(Qt.CTRL + Qt.Key_F2))
        subview_menu.addAction('Disassembly',
                               lambda: self.show_main_tab('disassembly'),
                               shortcut=QKeySequence(Qt.CTRL + Qt.Key_F5))
        self.view_menu.addMenu(subview_menu)
        self.view_menu.addSeparator()
        self.menu.addMenu(self.view_menu)

        if self.dwarf_args.debug_script:
            debug_menu = QMenu('Debug', self)
            debug_menu.addAction('Reload core', self._menu_reload_core)
            debug_menu.addAction('Debug dwarf js core',
                                 self._menu_debug_dwarf_js)
            self.menu.addMenu(debug_menu)

        about_menu = QMenu('About', self)
        about_menu.addAction('Dwarf on GitHub', self._menu_github)
        about_menu.addAction('Documention', self._menu_documentation)
        about_menu.addAction('Api', self._menu_api)
        about_menu.addAction('Slack', self._menu_slack)
        about_menu.addSeparator()
        about_menu.addAction('Info', self._show_about_dlg)
        self.menu.addMenu(about_menu)

    def _enable_update_menu(self):
        self._is_newer_dwarf = True

    def _update_dwarf(self):
        if self.welcome_window:
            self.welcome_window._update_dwarf()

    def _on_close_tab(self, index):
        tab_text = self.main_tabs.tabText(index)
        if tab_text:
            if tab_text.lower() in self.session_manager.session.non_closable:
                return
            try:
                self._ui_elems.remove(tab_text.lower())
            except ValueError:  # recheck ValueError: list.remove(x): x not in list
                pass
            self.main_tabs.removeTab(index)

    def _handle_tab_change(self):
        for index in range(self.main_tabs.count()):
            tab_name = self.main_tabs.tabText(index).lower().replace(' ', '-')
            if tab_name in self.session_manager.session.non_closable:
                self.main_tabs.tabBar().setTabButton(index, QTabBar.RightSide,
                                                     None)

                if tab_name in self._tab_order:
                    should_index = self._tab_order.index(tab_name)
                    if index != should_index:
                        self.main_tabs.tabBar().moveTab(index, should_index)

    def _on_dwarf_updated(self):
        self.onRestart.emit()

    def remove_tmp_dir(self):
        if os.path.exists('.tmp'):
            shutil.rmtree('.tmp', ignore_errors=True)

    def _set_theme(self, qaction):
        if qaction:
            self.set_theme(qaction.text())

    def _menu_reload_core(self):
        self.dwarf.load_script()

    def _menu_debug_dwarf_js(self):
        you_know_what_to_do = json.loads(
            self.dwarf._script.exports.debugdwarfjs())
        return you_know_what_to_do

    def show_main_tab(self, name):
        # elem doesnt exists? create it
        if name not in self._ui_elems:
            self._create_ui_elem(name)

        index = 0
        name = name.join(name.split()).lower()
        if name == 'memory':
            index = self.main_tabs.indexOf(self.memory_panel)
        elif name == 'ranges':
            index = self.main_tabs.indexOf(self.ranges_panel)
        elif name == 'search':
            index = self.main_tabs.indexOf(self.search_panel)
        elif name == 'modules':
            index = self.main_tabs.indexOf(self.modules_panel)
        elif name == 'disassembly':
            index = self.main_tabs.indexOf(self.asm_panel)
        elif name == 'trace':
            index = self.main_tabs.indexOf(self.trace_panel)
        elif name == 'data':
            index = self.main_tabs.indexOf(self.data_panel)
        elif name == 'emulator':
            index = self.main_tabs.indexOf(self.emulator_panel)
        elif name == 'java-trace':
            index = self.main_tabs.indexOf(self.java_trace_panel)
        elif name == 'jvm-inspector':
            index = self.main_tabs.indexOf(self.java_inspector_panel)
        elif name == 'jvm-debugger':
            index = self.main_tabs.indexOf(self.java_explorer_panel)
        elif name == 'smali':
            index = self.main_tabs.indexOf(self.smali_panel)

        self.main_tabs.setCurrentIndex(index)

    def jump_to_address(self, ptr, show_panel=True):
        if self.memory_panel is not None:
            if show_panel:
                self.show_main_tab('memory')
            self.memory_panel.read_memory(ptr)

    @pyqtSlot(name='mainMenuGitHub')
    def _menu_github(self):
        QDesktopServices.openUrl(QUrl('https://github.com/iGio90/Dwarf'))

    @pyqtSlot(name='mainMenuDocumentation')
    def _menu_api(self):
        QDesktopServices.openUrl(QUrl('https://igio90.github.io/Dwarf/'))

    @pyqtSlot(name='mainMenuApi')
    def _menu_documentation(self):
        QDesktopServices.openUrl(QUrl('https://igio90.github.io/Dwarf/api'))

    @pyqtSlot(name='mainMenuSlack')
    def _menu_slack(self):
        QDesktopServices.openUrl(
            QUrl('https://join.slack.com/t/resecret/shared_invite'
                 '/enQtMzc1NTg4MzE3NjA1LTlkNzYxNTIwYTc2ZTYyOWY1MT'
                 'Q1NzBiN2ZhYjQwYmY0ZmRhODQ0NDE3NmRmZjFiMmE1MDYwN'
                 'WJlNDVjZDcwNGE'))

    def _show_about_dlg(self):
        about_dlg = AboutDialog(self)
        about_dlg.show()

    def _create_ui_elem(self, elem):
        if not isinstance(elem, str):
            return

        if elem not in self._ui_elems:
            self._ui_elems.append(elem)

        if elem == 'watchers':
            from ui.panel_watchers import WatchersPanel
            self.watchers_dwidget = QDockWidget('Watchers', self)
            self.watchers_panel = WatchersPanel(self)
            # dont respond to dblclick mem cant be shown
            # self.watchers_panel.onItemDoubleClicked.connect(
            #    self._on_watcher_clicked)
            self.watchers_panel.onItemRemoved.connect(
                self._on_watcher_removeditem)
            self.watchers_panel.onItemAdded.connect(self._on_watcher_added)
            self.watchers_dwidget.setWidget(self.watchers_panel)
            self.watchers_dwidget.setObjectName('WatchersPanel')
            self.addDockWidget(Qt.LeftDockWidgetArea, self.watchers_dwidget)
            self.view_menu.addAction(self.watchers_dwidget.toggleViewAction())
        elif elem == 'hooks':
            from ui.panel_hooks import HooksPanel
            self.hooks_dwiget = QDockWidget('Breakpoints', self)
            self.hooks_panel = HooksPanel(self)
            self.hooks_panel.onShowMemoryRequest.connect(
                self._on_watcher_clicked)
            self.hooks_panel.onHookRemoved.connect(self._on_hook_removed)
            self.hooks_dwiget.setWidget(self.hooks_panel)
            self.hooks_dwiget.setObjectName('HooksPanel')
            self.addDockWidget(Qt.LeftDockWidgetArea, self.hooks_dwiget)
            self.view_menu.addAction(self.hooks_dwiget.toggleViewAction())
        elif elem == 'bookmarks':
            from ui.panel_bookmarks import BookmarksPanel
            self.bookmarks_dwiget = QDockWidget('Boomarks', self)
            self.bookmarks_panel = BookmarksPanel(self)
            self.bookmarks_panel.onShowMemoryRequest.connect(
                self._on_watcher_clicked)
            self.bookmarks_dwiget.setWidget(self.bookmarks_panel)
            self.bookmarks_dwiget.setObjectName('BookmarksPanel')
            self.addDockWidget(Qt.LeftDockWidgetArea, self.bookmarks_dwiget)
            self.view_menu.addAction(self.bookmarks_dwiget.toggleViewAction())
        elif elem == 'registers':
            from ui.panel_context import ContextPanel
            self.registers_dock = QDockWidget('Context', self)
            self.context_panel = ContextPanel(self)
            self.registers_dock.setWidget(self.context_panel)
            self.registers_dock.setObjectName('ContextsPanel')
            self.addDockWidget(Qt.RightDockWidgetArea, self.registers_dock)
            self.view_menu.addAction(self.registers_dock.toggleViewAction())
        elif elem == 'memory':
            from ui.panel_memory import MemoryPanel
            self.memory_panel = MemoryPanel(self)
            self.memory_panel.onShowDisassembly.connect(
                self._disassemble_range)
            self.memory_panel.dataChanged.connect(self._on_memory_modified)
            self.memory_panel.statusChanged.connect(self.set_status_text)
            self.main_tabs.addTab(self.memory_panel, 'Memory')
        elif elem == 'jvm-debugger':
            from ui.panel_java_explorer import JavaExplorerPanel
            self.java_explorer_panel = JavaExplorerPanel(self)
            self.main_tabs.addTab(self.java_explorer_panel, 'JVM debugger')
            self.main_tabs.tabBar().moveTab(
                self.main_tabs.indexOf(self.java_explorer_panel), 1)
        elif elem == 'jvm-inspector':
            from ui.panel_java_inspector import JavaInspector
            self.java_inspector_panel = JavaInspector(self)
            self.main_tabs.addTab(self.java_inspector_panel, 'JVM inspector')
        elif elem == 'console':
            from ui.panel_console import ConsolePanel
            self.console_dock = QDockWidget('Console', self)
            self.console_panel = ConsolePanel(self)
            self.dwarf.onLogToConsole.connect(self._log_js_output)
            self.console_dock.setWidget(self.console_panel)
            self.console_dock.setObjectName('ConsolePanel')
            self.addDockWidget(Qt.BottomDockWidgetArea, self.console_dock)
            self.view_menu.addAction(self.console_dock.toggleViewAction())
        elif elem == 'backtrace':
            from ui.panel_backtrace import BacktracePanel
            self.backtrace_dock = QDockWidget('Backtrace', self)
            self.backtrace_panel = BacktracePanel(self)
            self.backtrace_dock.setWidget(self.backtrace_panel)
            self.backtrace_dock.setObjectName('BacktracePanel')
            self.backtrace_panel.onShowMemoryRequest.connect(
                self._on_watcher_clicked)
            self.addDockWidget(Qt.RightDockWidgetArea, self.backtrace_dock)
            self.view_menu.addAction(self.backtrace_dock.toggleViewAction())
        elif elem == 'threads':
            from ui.panel_contexts_list import ContextsListPanel
            self.threads_dock = QDockWidget('Threads', self)
            self.contexts_list_panel = ContextsListPanel(self)
            self.dwarf.onThreadResumed.connect(
                self.contexts_list_panel.resume_tid)
            self.contexts_list_panel.onItemDoubleClicked.connect(
                self._manually_apply_context)
            self.threads_dock.setWidget(self.contexts_list_panel)
            self.threads_dock.setObjectName('ThreadPanel')
            self.addDockWidget(Qt.RightDockWidgetArea, self.threads_dock)
            self.view_menu.addAction(self.threads_dock.toggleViewAction())
        elif elem == 'modules':
            from ui.panel_modules import ModulesPanel
            self.modules_panel = ModulesPanel(self)
            self.modules_panel.onModuleSelected.connect(
                self._on_module_dblclicked)
            self.modules_panel.onModuleFuncSelected.connect(
                self._on_modulefunc_dblclicked)
            self.modules_panel.onAddHook.connect(self._on_addmodule_hook)
            self.modules_panel.onDumpBinary.connect(self._on_dumpmodule)
            self.main_tabs.addTab(self.modules_panel, 'Modules')
        elif elem == 'ranges':
            from ui.panel_ranges import RangesPanel
            self.ranges_panel = RangesPanel(self)
            self.ranges_panel.onItemDoubleClicked.connect(
                self._range_dblclicked)
            self.ranges_panel.onDumpBinary.connect(self._on_dumpmodule)
            # connect to watcherpanel func
            self.ranges_panel.onAddWatcher.connect(
                self.watchers_panel.do_addwatcher_dlg)
            self.main_tabs.addTab(self.ranges_panel, 'Ranges')
        elif elem == 'search':
            from ui.panel_search import SearchPanel
            self.search_panel = SearchPanel(self)
            self.search_panel.onShowMemoryRequest.connect(
                self._on_watcher_clicked)
            self.main_tabs.addTab(self.search_panel, 'Search')
        elif elem == 'data':
            from ui.panel_data import DataPanel
            self.data_panel = DataPanel(self)
            self.main_tabs.addTab(self.data_panel, 'Data')
        elif elem == 'trace':
            from ui.panel_trace import TracePanel
            self.trace_panel = TracePanel(self)
            self.main_tabs.addTab(self.trace_panel, 'Trace')
        elif elem == 'disassembly':
            from ui.widgets.disasm_view import DisassemblyView
            self.asm_panel = DisassemblyView(self)
            self.asm_panel.onShowMemoryRequest.connect(self._on_disasm_showmem)
            self.main_tabs.addTab(self.asm_panel, 'Disassembly')
        elif elem == 'emulator':
            from ui.panel_emulator import EmulatorPanel
            self.emulator_panel = EmulatorPanel(self)
            self.main_tabs.addTab(self.emulator_panel, 'Emulator')
        elif elem == 'java-trace':
            from ui.panel_java_trace import JavaTracePanel
            self.java_trace_panel = JavaTracePanel(self)
            self.main_tabs.addTab(self.java_trace_panel, 'JVM tracer')
        elif elem == 'smali':
            from ui.panel_smali import SmaliPanel
            self.smali_panel = SmaliPanel()
            self.main_tabs.addTab(self.smali_panel, 'Smali')
        else:
            print('no handler for elem: ' + elem)

        # make tabs unclosable and sort
        self._handle_tab_change()

        # TODO: remove add @2x
        for item in self.findChildren(QDockWidget):
            if item:
                if 'darwin' in sys.platform:
                    item.setStyleSheet(
                        'QDockWidget::title { padding-left:-30px; }')

    def set_theme(self, theme):
        if theme:
            theme = theme.replace(os.pardir, '').replace('.', '')
            theme = theme.join(theme.split()).lower()
            theme_style = 'assets/' + theme + '_style.qss'
            if not os.path.exists(utils.resource_path(theme_style)):
                return

            self.prefs.put('dwarf_ui_theme', theme)

            try:
                _app = QApplication.instance()
                with open(theme_style) as stylesheet:
                    _app.setStyleSheet(_app.styleSheet() + '\n' +
                                       stylesheet.read())
            except Exception as e:
                pass
                # err = self.dwarf.spawn(dwarf_args.package, dwarf_args.script)

    def set_status_text(self, txt):
        self.statusbar.showMessage(txt)

    # ************************************************************************
    # **************************** Properties ********************************
    # ************************************************************************
    @property
    def disassembly(self):
        return self.asm_panel

    @property
    def backtrace(self):
        return self.backtrace_panel

    @property
    def console(self):
        return self.console_panel

    @property
    def context(self):
        return self.context_panel

    @property
    def threads(self):
        return self.contexts_list_panel

    @property
    def emulator(self):
        return self.emulator_panel

    @property
    def ftrace(self):
        return self.ftrace_panel

    @property
    def hooks(self):
        return self.hooks_panel

    @property
    def java_inspector(self):
        return self.java_inspector_panel

    @property
    def java_explorer(self):
        return self.java_explorer_panel

    @property
    def memory(self):
        return self.memory_panel

    @property
    def modules(self):
        return self.memory_panel

    @property
    def ranges(self):
        return self.ranges_panel

    @property
    def trace(self):
        return self.trace_panel

    @property
    def watchers(self):
        return self.watchers_panel

    @property
    def dwarf(self):
        if self.session_manager.session is not None:
            return self.session_manager.session.dwarf
        else:
            return None

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    # session handlers
    def _start_session(self, session_type, session_data=None):
        if self.welcome_window is not None:
            self.welcome_window.close()
        self.session_manager.create_session(session_type,
                                            session_data=session_data)

    def _restore_session(self, session_data):
        if 'session' in session_data:
            session_type = session_data['session']
            self._start_session(session_type, session_data=session_data)

    def session_created(self):
        # session init done create ui for it
        session = self.session_manager.session
        self._setup_main_menu()
        for ui_elem in session.session_ui_sections:
            ui_elem = ui_elem.join(ui_elem.split()).lower()
            self._create_ui_elem(ui_elem)

        self.dwarf.onAttached.connect(self._on_attached)
        self.dwarf.onScriptLoaded.connect(self._on_script_loaded)

        # hookup
        self.dwarf.onSetRanges.connect(self._on_setranges)
        self.dwarf.onSetModules.connect(self._on_setmodules)

        self.dwarf.onAddNativeHook.connect(self._on_add_hook)
        self.dwarf.onApplyContext.connect(self._apply_context)
        self.dwarf.onThreadResumed.connect(self.on_tid_resumed)

        self.dwarf.onTraceData.connect(self._on_tracer_data)
        self.dwarf.onSetData.connect(self._on_set_data)

        self.session_manager.start_session(self.dwarf_args)
        q_settings = QSettings("dwarf_window_pos.ini", QSettings.IniFormat)
        ui_state = q_settings.value('dwarf_ui_state')
        if ui_state:
            self.restoreGeometry(ui_state)
        window_state = q_settings.value('dwarf_ui_window', self.saveState())
        if window_state:
            self.restoreState(window_state)

        self.showMaximized()

    def session_stopped(self):
        self.remove_tmp_dir()
        self.menu.clear()

        self.main_tabs.clear()

        # actually we need to kill this. needs a refactor
        if self.java_trace_panel is not None:
            self.java_trace_panel = None

        for elem in self._ui_elems:
            if elem == 'watchers':
                self.watchers_panel.clear_list()
                self.watchers_panel.close()
                self.watchers_panel = None
                self.removeDockWidget(self.watchers_dwidget)
                self.watchers_dwidget = None
            elif elem == 'hooks':
                self.hooks_panel.close()
                self.hooks_panel = None
                self.removeDockWidget(self.hooks_dwiget)
                self.hooks_dwiget = None
            elif elem == 'registers':
                self.context_panel.close()
                self.context_panel = None
                self.removeDockWidget(self.registers_dock)
                self.registers_dock = None
            elif elem == 'memory':
                self.memory_panel.close()
                self.memory_panel = None
                self.main_tabs.removeTab(0)
                # self.main_tabs
            elif elem == 'jvm-debugger':
                self.java_explorer_panel.close()
                self.java_explorer_panel = None
                self.removeDockWidget(self.watchers_dwidget)
            elif elem == 'console':
                self.console_panel.close()
                self.console_panel = None
                self.removeDockWidget(self.console_dock)
                self.console_dock = None
            elif elem == 'backtrace':
                self.backtrace_panel.close()
                self.backtrace_panel = None
                self.removeDockWidget(self.backtrace_dock)
            elif elem == 'threads':
                self.contexts_list_panel.close()
                self.contexts_list_panel = None
                self.removeDockWidget(self.threads_dock)
                self.threads_dock = None
            elif elem == 'bookmarks':
                self.bookmarks_panel.close()
                self.bookmarks_panel = None
                self.removeDockWidget(self.bookmarks_dwiget)
                self.bookmarks_dwiget = None

    def session_closed(self):
        self._ui_elems = []
        self.hide()
        if self.welcome_window is not None:
            self.welcome_window.exec()

        # close if it was a commandline session
        if self.welcome_window is None:
            if self.dwarf_args.package:
                self.close()

    # ui handler
    def closeEvent(self, event):
        """ Window closed
            save stuff or whatever at exit

            detaches dwarf
        """
        # save windowstuff
        q_settings = QSettings("dwarf_window_pos.ini", QSettings.IniFormat)
        q_settings.setValue('dwarf_ui_state', self.saveGeometry())
        q_settings.setValue('dwarf_ui_window', self.saveState())

        if self.dwarf:
            self.dwarf.detach()
        super().closeEvent(event)

    def _on_watcher_clicked(self, ptr):
        """ Address in Watcher/Hookpanel was clicked
            show Memory
        """
        if '.' in ptr:  # java_hook
            file_path = ptr.replace('.', os.path.sep)
            if os.path.exists('.tmp/smali/' + file_path + '.smali'):
                if self.smali_panel is None:
                    self._create_ui_elem('smali')
                self.smali_panel.set_file('.tmp/smali/' + file_path + '.smali')
                self.show_main_tab('smali')
        else:
            self.memory_panel.read_memory(ptr=ptr)
            self.show_main_tab('memory')

    def _on_disasm_showmem(self, ptr, length):
        """ Address in Disasm was clicked
            adds temphighlight for bytes from current instruction
        """
        self.memory_panel.read_memory(ptr)
        self.memory_panel.add_highlight(
            HighLight('attention', utils.parse_ptr(ptr), length))
        self.show_main_tab('memory')

    def _on_watcher_added(self, ptr):
        """ Watcher Entry was added
        """
        try:
            # set highlight
            self.memory_panel.add_highlight(
                HighLight('watcher', ptr, self.dwarf.pointer_size))
        except HighlightExistsError:
            pass

    def _on_watcher_removeditem(self, ptr):
        """ Watcher Entry was removed
            remove highlight too
        """
        self.memory_panel.remove_highlight(ptr)

    def _on_module_dblclicked(self, data):
        """ Module in ModulePanel was doubleclicked
        """
        addr, size = data
        addr = utils.parse_ptr(addr)
        size = int(size, 10)
        self.memory_panel.read_memory(ptr=addr, length=size)
        self.show_main_tab('Memory')

    def _on_modulefunc_dblclicked(self, ptr):
        """ Function in ModulePanel was doubleclicked
        """
        ptr = utils.parse_ptr(ptr)
        self.memory_panel.read_memory(ptr=ptr)
        self.show_main_tab('Memory')

    def _on_dumpmodule(self, data):
        """ DumpBinary MenuItem in ModulePanel was selected
        """
        ptr, size = data
        ptr = utils.parse_ptr(ptr)
        size = int(size, 10)
        self.dwarf.dump_memory(ptr=ptr, length=size)

    def _disassemble_range(self, mem_range):
        """ Disassemble MenuItem in Hexview was selected
        """
        if mem_range:
            if self.asm_panel is None:
                self._create_ui_elem('disassembly')

            if mem_range:
                self.asm_panel.disassemble(mem_range)
                self.show_main_tab('disassembly')

    def _range_dblclicked(self, ptr):
        """ Range in RangesPanel was doubleclicked
        """
        ptr = utils.parse_ptr(ptr)
        self.memory_panel.read_memory(ptr=ptr)
        self.show_main_tab('Memory')

    # dwarf handlers
    def _log_js_output(self, output):
        if self.console_panel is not None:
            self.console_panel.get_js_console().log(output)

    def _on_setranges(self, ranges):
        """ Dwarf wants to set Ranges
            only hooked up to switch tab or create ui
            its connected in panel after creation
        """
        if self.ranges_panel is None:
            self.show_main_tab('ranges')
            # forward only now to panel it connects after creation
            self.ranges_panel.set_ranges(ranges)

    def _on_setmodules(self, modules):
        """ Dwarf wants to set Modules
            only hooked up to switch tab or create ui
            its connected in panel after creation
        """
        if self.modules_panel is None:
            self._create_ui_elem('modules')
            self.modules_panel.set_modules(modules)

        if self.modules_panel is not None:
            self.show_main_tab('modules')

    def _manually_apply_context(self, context):
        """
        perform additional operation if the context has been manually applied from the context list
        """
        self._apply_context(context, manual=True)

    def _apply_context(self, context, manual=False):
        # update current context tid
        # this should be on top as any further api from js needs to be executed on that thread
        is_initial_hook = context['reason'] >= 0
        if manual or (self.dwarf.context_tid and not is_initial_hook):
            self.dwarf.context_tid = context['tid']

        if 'context' in context:
            if not manual:
                self.threads.add_context(context)

            is_java = context['is_java']
            if is_java:
                if self.java_explorer_panel is None:
                    self._create_ui_elem('jvm-debugger')
                self.context_panel.set_context(context['ptr'], 1,
                                               context['context'])
                self.java_explorer_panel._set_handle_arg(-1)
                self.show_main_tab('jvm-debugger')
            else:
                self.context_panel.set_context(context['ptr'], 0,
                                               context['context'])

                if 'pc' in context['context']:
                    if not 'disassembly' in self._ui_elems:
                        from lib.range import Range
                        _range = Range(Range.SOURCE_TARGET, self.dwarf)
                        _range.init_with_address(
                            int(context['context']['pc']['value'], 16))

                        self._disassemble_range(_range)

        if 'backtrace' in context:
            self.backtrace_panel.set_backtrace(context['backtrace'])

    def _on_add_hook(self, hook):
        try:
            # set highlight
            ptr = hook.get_ptr()
            ptr = utils.parse_ptr(ptr)
            self.memory_panel.add_highlight(
                HighLight('hook', ptr, self.dwarf.pointer_size))
        except HighlightExistsError:
            pass

    def _on_hook_removed(self, ptr):
        ptr = utils.parse_ptr(ptr)
        self.memory_panel.remove_highlight(ptr)

    def _on_addmodule_hook(self, data):
        ptr, name = data
        self.dwarf.hook_native(ptr, own_input=name)

    def on_tid_resumed(self, tid):
        if self.dwarf:
            if self.dwarf.context_tid == tid:
                # clear backtrace
                if 'backtrace' in self._ui_elems:
                    if self.backtrace_panel is not None:
                        self.backtrace_panel.clear()

                # remove thread
                if 'threads' in self._ui_elems:
                    if self.contexts_list_panel is not None:
                        self.contexts_list_panel.resume_tid(tid)

                # clear registers
                if 'registers' in self._ui_elems:
                    if self.context_panel is not None:
                        self.context_panel.clear()

                # clear jvm explorer
                if 'jvm-debugger' in self._ui_elems:
                    if self.java_explorer_panel is not None:
                        self.java_explorer_panel.clear_panel()

                # invalidate dwarf context tid
                self.dwarf.context_tid = 0

    def _on_tracer_data(self, data):
        if not data:
            return

        if self.trace_panel is None:
            self._create_ui_elem('trace')

        if self.trace_panel is not None:
            self.show_main_tab('Trace')
            self.trace_panel.start()

            trace_events_parts = data[1].split(',')
            while trace_events_parts:
                trace_event = TraceEvent(trace_events_parts.pop(0),
                                         trace_events_parts.pop(0),
                                         trace_events_parts.pop(0),
                                         trace_events_parts.pop(0))
                self.trace_panel.event_queue.append(trace_event)

    def _on_set_data(self, data):
        if not isinstance(data, list):
            return

        if self.data_panel is None:
            self._create_ui_elem('data')

        if self.data_panel is not None:
            self.show_main_tab('Data')
            self.data_panel.append_data(data[0], data[1], data[2])

    def show_progress(self, text):
        self.progressbar.setVisible(True)
        self.set_status_text(text)

    def hide_progress(self):
        self.progressbar.setVisible(False)
        self.set_status_text('')

    def _on_attached(self, data):
        self.setWindowTitle('Dwarf - Attached to %s (%s)' % (data[1], data[0]))

    def _on_script_loaded(self):
        # restore the loaded session if any
        self.session_manager.restore_session()

    def _on_memory_modified(self, pos, length):
        data_pos = self.memory_panel.base + pos
        data = self.memory_panel.data[pos:pos + length]
        data = [data[0]]  # todo: strange js part

        if self.dwarf.dwarf_api('writeBytes', [data_pos, data]):
            pass
        else:
            utils.show_message_box('Failed to write Memory')

    def on_add_bookmark(self, ptr):
        """
        provide ptr as int
        """
        if self.bookmarks_panel is not None:
            self.bookmarks_panel._create_bookmark(ptr=hex(ptr))
예제 #7
0
class NoteMain(QMainWindow):
    def __init__(self, parent=None):
        super(NoteMain, self).__init__(parent)
        self.setWindowTitle("CSDN 同步笔记(author:rechard)")
        #os.path.dirname(os.path.realpath(__file__) 获取到当前文件的路径
        #self.setWindowIcon(QtGui.QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "icon.png" )))
        self.setWindowIcon(QIcon("./images/icon.png"))
        self.blogCache = BlogCache()
        self.browser = BrowserWidget()
        self.browser.cookieAdd.connect(self.on_browser_cookieAdd)
        self.split = QSplitter()
        self.articleList = ArticleList()
        self.articleList.itemClicked.connect(self.articleItemClick)
        self.initCategory()
        self.split.addWidget(self.articleList)
        self.split.addWidget(self.browser)
        self.toolbar = MDToolBarWidget(self.browser)
        self.split.addWidget(self.toolbar)
        self.split.setSizes([0, 0, 900, 0])
        self.setCentralWidget(self.split)
        self.showMaximized()
        #self.setGeometry(200, 200, 800, 500)
        self.cookies = {}  # 存放domain的key-value
        self.loginDone = False
        #self.loginSuccessInit()

    #点击article list里的选项
    def articleItemClick(self, clickItem: ArticleItem):
        self.showArticleInLeftFrame(clickItem.getBlog())

    def on_browser_cookieAdd(self, cookie):  # 处理cookie添加的事件
        name = cookie.name().data().decode('utf-8')  # 先获取cookie的名字,再把编码处理一下
        value = cookie.value().data().decode('utf-8')  # 先获取cookie值,再把编码处理一下
        self.cookies[name] = value
        if self.cookies.get('UserToken') and not self.loginDone:
            self.loginSuccessInit()

    def onLoadFinished(self, finished):
        if finished and self.cookies.get('UserToken') and not self.loginDone:
            self.loginSuccessInit()

    def loginSuccessInit(self):
        self.initMenu()
        self.loadAllBlogsCategories()
        self.loadAllDraftBlogCategories()
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.loginDone = True
        self.browser.setHtml('welcome!')
        self.split.setSizes([250, 250, 900, 50])

    # 显示文章到左边的显示框里
    def showArticleInLeftFrame(self, blog: Blog = None):
        if blog != None:
            self.browser.setBlog(blog)
            self.browser.setTitle(blog.title)
            if blog.url == 'draft':
                self.showHtml(blog)
            else:
                self.backend = LoadArticleThread(blog,
                                                 CSDNService(self.cookies))
                self.backend.trigger.connect(self.showHtml)
                self.backend.start()

    def showHtml(self, data: Blog):
        searchTxt = self.searchTxt.text()
        html = data.content
        if len(searchTxt.strip()) > 0:
            html = html.replace(
                searchTxt, '<font style=\'background-color:yellow\'>' +
                searchTxt + '</font>')
        self.browser.setHtml(html)
        self.browser.setMD(data.mdText)

    # 加载loading 条
    def startloading(self):
        self.imageLabel = QLabel()
        self.movie = QMovie("./images/loading.gif")
        self.imageLabel.setMovie(self.movie)
        self.movie.start()
        self.setCentralWidget(self.imageLabel)

    def stopLoading(self):
        self.setCentralWidget(self.browser)

    def initMenu(self):
        tb: QToolBar = self.addToolBar("toolbar")
        add = QAction(QIcon('./images/add.png'), '&新建草稿', self)
        add.setStatusTip('新建文章')
        tb.addAction(add)

        refreshAct = QAction(QIcon('./images/refresh.png'), '&同步文章', self)
        refreshAct.setShortcut('Ctrl+R')
        refreshAct.setStatusTip('从csdn同步文章...')
        tb.addAction(refreshAct)

        personal = QAction(QIcon('./images/personal.png'), '&个人信息', self)
        personal.setStatusTip('个人信息')
        tb.addAction(personal)

        help = QAction(QIcon('./images/help.png'), '&帮助', self)
        help.setStatusTip('帮助说明')
        tb.addAction(help)

        tb.actionTriggered[QAction].connect(self.windowaction)
        tb.setFloatable(False)
        logging.info("menu ini success")

    def windowaction(self, q):
        if q.text() == "&新建草稿":
            self.createDraft()
        elif q.text() == "&同步文章":
            self.reloadArticles()
        elif q.text() == "&个人信息":
            QMessageBox.about(self, "个人信息", "用户名:%s" % self.cookies['UN'])
        elif q.text() == "&帮助":
            QMessageBox.about(
                self, "帮助说明", '''
             同步csdn文章的一个笔记工具,模仿有道笔记的界面,使用到了python,pyqt5, sqllite等
            ''')

    def createDraft(self):
        blog = Blog()
        blog.title = '无标题笔记'
        blog.category = 'draft'
        blog.categoryUrl = 'none'
        blog.content = ''
        blog.mdText = ''
        blog.url = 'draft'
        c = TreeWidgetItem(blog=blog)
        c.setText(0, blog.title)
        c.setIcon(0, QIcon("./images/draft.png"))
        self.draftArticles.addChild(c)
        # todo: how to focus on new created item
        BlogCache().saveArticlies([blog])
        item = ListWidgetItem(blog=blog)
        item.setSizeHint(QSize(100, 80))
        item.setIcon(QIcon("./images/draft.png"))
        item.setText(blog.title)
        self.articleList.addItem(item)

    def reloadArticles(self):
        service = CSDNService(self.cookies)
        #self.reloadPublish=ReloadBlogThread(url='https://blog.csdn.net/guo_xl',service=service,parent=self)
        self.reloadPublish = ReloadBlogThread(url='https://blog.csdn.net/' +
                                              self.cookies['UN'],
                                              service=service,
                                              parent=self)
        self.reloadPublish.start()
        self.reloadPublish.trigger.connect(self.handleReloadMessage)
        self.reloadDraft = ReloadDraftBlogThread(service=service)
        self.reloadDraft.start()
        self.reloadDraft.trigger.connect(self.handleDraftReloadMessage)
        self.statusBar.showMessage("博客加载中...")
        MessageTip("开始同步").show()

    #返回的data是个[],里面装了Blog对象
    def handleDraftReloadMessage(self, data):
        if isinstance(data, str):
            self.statusBar.showMessage(data)
            if data == "加载完毕":
                self.loadAllDraftBlogCategories()
        elif isinstance(data, List):
            self.draftArticles.takeChildren()
            for blog in data:
                c = TreeWidgetItem(blog=blog)
                c.setText(0, blog.title)
                c.setIcon(0, QIcon("./images/draft.png"))
                self.draftArticles.addChild(c)
        elif isinstance(data, Blog):
            self.blogCache.saveArticlies([data])

    def handleReloadMessage(self, data):
        if isinstance(data, str):
            self.statusBar.showMessage(data)
            if data == "加载完毕":
                self.loadAllBlogsCategories()
        elif isinstance(data, dict):
            list = data["data"]
            type = data["type"]
            if type == BlogLoadType.categories:
                self.handleDisplayCategories(list)
            elif type == BlogLoadType.subCategories:
                categoryName = data["categoryName"]
                logging.info("处理%s" % categoryName)
                #找到categoryName对应的menu item
                #坑爹,不要用publishArticlesCategory.takeChildren()移除所有的item
                count = self.publishArticlesCategory.childCount()
                i = 0
                while i < count:
                    c = self.publishArticlesCategory.child(i)
                    i += 1
                    if categoryName == c.text(0):
                        self.handleDisplaySubCategories(list, c)
                        logging.info("处理完%s" % categoryName)
                        return
        elif isinstance(data, Blog):
            self.blogCache.saveArticlies([data])

    #记载草稿
    def loadAllDraftBlogCategories(self):
        data = self.blogCache.searchAllDraft()
        self.draftArticles.takeChildren()
        for blog in data:
            c = TreeWidgetItem(blog=blog)
            c.setText(0, blog.title)
            c.setIcon(0, QIcon("./images/draft.png"))
            self.draftArticles.addChild(c)
            item = ListWidgetItem(blog=blog)
            item.setSizeHint(QSize(100, 80))
            item.setIcon(QIcon("./images/draft.png"))
            item.setText(blog.title)
            self.articleList.addItem(item)

    #加载blog's all categories
    def loadAllBlogsCategories(self):
        # 注意这里写法
        # 这样是错误的,为什么?
        # backend=BackendThread()
        # backend.start()
        # backend.articleCategory.connect(self.handleDisplay)
        data = self.blogCache.searchAllPublished()
        publicCategory = self.publishArticlesCategory
        publicCategory.takeChildren()
        for k, v in data.items():
            child = QTreeWidgetItem()
            child.setText(0, v.get("category"))  # title
            child.setText(1, v.get("categoryUrl"))  # url
            child.setText(2, 'category')
            child.setIcon(0, QIcon("./images/folder_close.png"))
            publicCategory.addChild(child)
            for blog in v.get("blogs"):
                c = TreeWidgetItem(blog=blog)
                c.setText(0, blog.title)
                c.setIcon(0, QIcon("./images/blog_normal.png"))
                child.addChild(c)
                item = ListWidgetItem(blog=blog)
                item.setSizeHint(QSize(100, 80))
                item.setIcon(QIcon("./images/blog_normal.png"))
                item.setText(blog.title)
                self.articleList.addItem(item)
        self.publishArticlesCategory.setDisabled(False)

    def handleDisplayCategories(self, data):
        publicCategory = self.publishArticlesCategory
        for item in data:
            if self.findCategoryByUrl(item["url"], publicCategory) == None:
                child = QTreeWidgetItem()
                child.setText(0, item["title"])  # title
                child.setText(1, item["url"])  # url
                child.setText(2, 'category')
                child.setIcon(0, QIcon("./images/folder_close.png"))
                publicCategory.addChild(child)

    def findCategoryByUrl(self, url, widget):
        total = widget.childCount()
        i = 0
        while i < total:
            if widget.child(i).text(1) == url:
                return widget.child(i)
            i = i + 1
        return None

    def initCategory(self):
        self.container = QWidget(self)
        layout = QVBoxLayout(self.container)
        self.tree = QTreeWidget()
        # 设置列数
        self.tree.setColumnCount(3)
        self.tree.setColumnHidden(1, True)
        self.tree.setColumnHidden(2, True)
        # 设置头的标题
        self.tree.setHeaderLabels(['title', 'url', 'category'])
        self.tree.setHeaderHidden(True)
        # 设置列宽
        self.tree.setColumnWidth(0, 320)
        self.searchTxt = QLineEdit()
        self.searchTxt.setPlaceholderText("关键字查询")
        self.searchTxt.textChanged.connect(self.search)
        layout.addWidget(self.searchTxt)
        layout.addWidget(self.tree)
        self.initPublishArticle()
        self.initDraftArticle()
        self.tree.itemClicked.connect(self.onClicked)
        self.tree.itemCollapsed.connect(self.onCollapsed)
        self.tree.itemExpanded.connect(self.onExpended)
        self.split.addWidget(self.container)

        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.onCustomContextMenu)

    def onCustomContextMenu(self, point):
        i = self.tree.indexAt(point)
        menu = QMenu()
        upload = QAction("上传到CSDN", self)
        menu.addAction(upload)
        t = time.time()
        k = menu.exec_(self.tree.mapToGlobal(point))
        #If the menu hasn't been open for more than 0.6s,
        #assume user did not have time to properly react to it opening
        if time.time() - t < 0.6:
            return
        if k == upload:
            msg = QMessageBox()
            msg.setText("同步到csdn")
            msg.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
            r = msg.exec_()
            if r == QMessageBox.Yes:
                MessageTip("开始同步到csdn").show()
                item = self.tree.currentItem()
                ut = UpdateThread(item.getBlog(), CSDNService(self.cookies))
                ut.update_proess_signal.connect(self.onUploaded)
                ut.start()

    def onUploaded(self, code: int):
        if (code == 200):
            win = MessageTip("发布到csdn成功")
            win.show()

    def onCollapsed(self, index: QModelIndex):
        index.setIcon(0, QIcon("./images/folder_open.png")
                      ) if index.isExpanded() else index.setIcon(
                          0, QIcon("./images/folder_close.png"))

    def onExpended(self, index: QModelIndex):
        index.setIcon(0, QIcon("./images/folder_open.png")
                      ) if index.isExpanded() else index.setIcon(
                          0, QIcon("./images/folder_close.png"))

    def search(self, data):
        result = self.blogCache.fuzzySearch(data)
        #public:QTreeWidgetItem=self.publishArticlesCategory # public
        # total=public.childCount()
        # i=0
        # while i<total:
        #   c=public.child(i)
        #   ctotal=c.childCount()
        #   j=0
        #   while j<ctotal:
        #       if len(data)>0 and (not result or c.child(j).text(0) not in result):
        #           c.child(j).setHidden(True)
        #       else:
        #           c.child(j).setHidden(False)
        #       j=j+1
        #   i=i+1
        i = 0
        articleList: QListWidget = self.articleList
        total = articleList.count()
        while i < total:
            if len(data) > 0 and (not result
                                  or articleList.item(i).text() not in result):
                articleList.item(i).setHidden(True)
            else:
                articleList.item(i).setHidden(False)
            i = i + 1

    def onClicked(self):
        try:
            item = self.tree.currentItem()
            if item != None:
                #None是root节点
                if isinstance(item, TreeWidgetItem):
                    self.showArticleInLeftFrame(item.getBlog())
        except Exception as ex:
            logging.exception(ex)

    #加载category下的子category
    # def loadSubCategories(self, item:QTreeWidgetItem):
    #     list=item.takeChildren()
    #     list.clear()
    #     #改成异步加载
    #     logging.info("loading sub category start")
    #     self.backend=BackendThread(url=item.text(1),type=BlogLoadType.subCategories)
    #     self.backend.trigger.connect(lambda data:self.handleDisplaySubCategories(data, item))
    #     self.backend.start()

    def handleDisplaySubCategories(self, articles, item):
        logging.info("loading %s subcategory" % item.text(0))
        for i in articles:
            if self.findCategoryByUrl(i["url"], item) == None:
                c = QTreeWidgetItem()
                c.setText(0, i['title'])  # title
                c.setText(1, i['url'])  # url
                c.setText(2, 'article')
                c.setText(3, i['updateTime'])
                item.addChild(c)

    def initDraftArticle(self):
        self.draftArticles = QTreeWidgetItem(self.tree)
        self.draftArticles.setText(0, '草稿箱')
        self.draftArticles.setIcon(0, QIcon("./images/folder_close.png"))
        self.tree.addTopLevelItem(self.draftArticles)

    def initPublishArticle(self):
        self.publishArticlesCategory = QTreeWidgetItem(self.tree)
        self.publishArticlesCategory.setText(0, '公开文章')
        self.publishArticlesCategory.setIcon(
            0, QIcon("./images/folder_close.png"))
        self.publishArticlesCategory.setDisabled(True)
        # self.label =  QLabel('', self)
        # self.movie =  QMovie("./images/loading.gif")
        # self.label.setMovie(self.movie)
        # self.movie.start()

        ### 设置节点的背景颜色
        #brush_red = QBrush(Qt.red)
        #self.publishArticles.setBackground(0, brush_red)
        #brush_green = QBrush(Qt.green)
        #self.publishArticlesCategories.setBackground(1, brush_green)
        self.tree.addTopLevelItem(self.publishArticlesCategory)
        #异步加载文章
        #self.statusBar.showMessage("博客加载中...")

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
예제 #8
0
class EEGRecorder(QMainWindow):
    """docstring for EEGRecorder"""
    def __init__(self):
        super(EEGRecorder, self).__init__()
        self.setWindowTitle('EEG Recorder v2.0')
        self.setWindowIcon(QIcon('./icons/record.png'))
        self.resize(480, 640)
        self.setContentsMargins(10, 10, 10, 10)
        # Main widgets
        self.videoDialog = FilePathDialog('Video file:', 'Open video',
                                          'Video files (*.mp4)')
        self.connectionForm = LSLForm('Lab Streaming Layer')
        self.personalForm = PersonalInformationForm('Personal Information')
        # Video player
        self.player = VideoPlayer()
        self.player.setSize(640, 480)
        self.player.error.connect(self.mediaError)
        self.player.mediaStatusChanged.connect(self.mediaStatusChanged)
        # Threads
        self.lsl = LSLClient()
        self.camera = OCVWebcam()
        # Buttons
        self.loadButton = QPushButton('Load')
        self.loadButton.clicked.connect(self.loadVideo)
        self.startButton = QPushButton('Start')
        self.startButton.setEnabled(False)
        self.startButton.clicked.connect(self.startRecording)
        self.pauseResumeButton = QPushButton('Pause')
        self.pauseResumeButton.setEnabled(False)
        self.pauseResumeButton.clicked.connect(self.pauseAndResume)
        self.stopSaveButton = QPushButton('Stop && Save')
        self.stopSaveButton.setEnabled(False)
        self.stopSaveButton.clicked.connect(self.stopAndSave)
        # Layouts
        buttonLayout = QHBoxLayout()
        buttonLayout.addWidget(self.startButton)
        buttonLayout.addWidget(self.pauseResumeButton)
        buttonLayout.addWidget(self.stopSaveButton)
        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.videoDialog, 1)
        mainLayout.addStretch(1)
        mainLayout.addWidget(self.loadButton)
        mainLayout.addStretch(1)
        mainLayout.addWidget(self.connectionForm, 1)
        mainLayout.addStretch(1)
        mainLayout.addWidget(self.personalForm, 1)
        mainLayout.addStretch(1)
        mainLayout.addLayout(buttonLayout, 1)
        # Main widget
        mainWidget = QWidget()
        mainWidget.setLayout(mainLayout)
        self.setCentralWidget(mainWidget)
        # Status bar
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage('¡System ready!')

    def loadVideo(self):
        path = self.videoDialog.getFullPath()
        self.player.loadMedia(path)
        self.camera.setSource(0, width=640, height=480)
        self.startButton.setEnabled(True)

    def mediaError(self):
        self.statusBar.showMessage('Error: {}'.format(
            self.player.errorString()))

    def mediaStatusChanged(self, status):
        if status == self.player.LoadingMedia:
            self.statusBar.showMessage('Loading video...')
        elif status == self.player.LoadedMedia:
            self.player.show()
            self.statusBar.showMessage('Video was successfully loaded!')
        elif status == self.player.EndOfMedia:
            self.stopAndSave()

    def startRecording(self):
        server = self.connectionForm.getValues()['server']
        if server == '':
            self.statusBar.showMessage('¡LSL server not specified!')
            return
        self.lsl.setStream('name', server)
        self.camera.record('video.hdf5')
        self.lsl.record()
        if self.player.isVideoAvailable():
            self.player.play()
        self.statusBar.showMessage('Recording...')
        self.pauseResumeButton.setEnabled(True)
        self.stopSaveButton.setEnabled(True)
        self.startButton.setEnabled(False)
        self.loadButton.setEnabled(False)

    def pauseAndResume(self):
        self.lsl.toggle()
        self.camera.toggle()
        if self.player.isVideoAvailable():
            self.player.toggle()
        if self.lsl.getState() == LSLClient.PausedState:
            self.pauseResumeButton.setText('Resume')
            self.statusBar.showMessage('Paused!')
        else:
            self.pauseResumeButton.setText('Pause')
            self.statusBar.showMessage('Recording...')

    def stopAndSave(self):
        self.lsl.stop()
        self.camera.stop()
        self.statusBar.showMessage('Stopping LSL thread...')
        while not self.lsl.isFinished():
            pass
        self.statusBar.showMessage('LSL thread finished!')
        if self.player.isVideoAvailable():
            self.player.stop()
            self.player.hide()
        path = QFileDialog.getExistingDirectory(self, 'Select folder',
                                                QDir.homePath(),
                                                QFileDialog.ShowDirsOnly)
        if path != '':
            path += '/'
            self.saveDataAndVideo(path)
        else:
            self.statusBar.showMessage('Files were not saved... data is lost!')
        self.pauseResumeButton.setEnabled(False)
        self.stopSaveButton.setEnabled(False)
        self.startButton.setEnabled(False)
        self.loadButton.setEnabled(True)

    def getFilenames(self, path):
        # File counter
        i = 1
        # Get personal information
        subject = self.personalForm.getValues()
        # Create the file base name
        basename = '{}-{}-{}-{}'.format(subject['name'], subject['last'],
                                        subject['age'], subject['sex'])
        # Get current date
        date = datetime.today().strftime('%Y-%m-%d')
        # Add elapsed time and date
        basename += '_{}'.format(date)
        # Add file extension
        filename = basename + '_{}.csv'.format(i)
        # Complete the full path
        dataFullPath = path + filename
        # Evaluate if the file name is already used
        while QFile(dataFullPath).exists():
            i += 1
            filename = basename + '_{}.csv'.format(i)
            dataFullPath = path + filename
        # Create a new full path to store the video file
        filename = basename + '_{}.hdf5'.format(i)
        videoFullPath = path + filename
        # Return data and video full paths
        return (dataFullPath, videoFullPath)

    def saveDataAndVideo(self, path):
        # Get valid file names
        dataFullPath, videoFullPath = self.getFilenames(path)
        # Get the EEG data
        D = self.lsl.getData()
        # Get the EEG channels
        channels = self.connectionForm.getValues()['channels'].strip()
        channels = channels.split(',') if channels != '' else range(
            1,
            len(D[0]) + 1)
        # Create a new DataFrame
        file = pd.DataFrame(D, columns=channels)
        # Export DataFrame to CSV
        file.to_csv(dataFullPath, index=False)
        self.statusBar.showMessage('EEG file saved as {}'.format(dataFullPath))
        # Rename video file
        file = QFile('video.hdf5')
        file.rename(videoFullPath)
        self.statusBar.showMessage(
            'Video file saved as {}'.format(videoFullPath))
예제 #9
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(533, 388)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.mainGridLayout = QGridLayout()
        self.mainGridLayout.setObjectName(_fromUtf8("mainGridLayout"))
        self.z_Spin = QSpinBox(self.centralwidget)
        self.z_Spin.setMinimum(1)
        self.z_Spin.setObjectName(_fromUtf8("z_Spin"))
        self.mainGridLayout.addWidget(self.z_Spin, 2, 0, 1, 2)
        self.time_Spin = QSpinBox(self.centralwidget)
        self.time_Spin.setMinimum(1)
        self.time_Spin.setObjectName(_fromUtf8("time_Spin"))
        self.mainGridLayout.addWidget(self.time_Spin, 2, 2, 1, 1)
        self.openFile_Button = QPushButton(self.centralwidget)
        self.openFile_Button.setObjectName(_fromUtf8("openFile_Button"))
        self.mainGridLayout.addWidget(self.openFile_Button, 0, 0, 1, 1)
        self.DIC_Spin = QSpinBox(self.centralwidget)
        self.DIC_Spin.setMinimum(1)
        self.DIC_Spin.setObjectName(_fromUtf8("DIC_Spin"))
        self.mainGridLayout.addWidget(self.DIC_Spin, 2, 4, 1, 1)
        self.Z_Label = QLabel(self.centralwidget)
        self.Z_Label.setObjectName(_fromUtf8("Z_Label"))
        self.mainGridLayout.addWidget(self.Z_Label, 1, 0, 1, 2)
        self.correctAtt_Check = QCheckBox(self.centralwidget)
        self.correctAtt_Check.setObjectName(_fromUtf8("correctAtt_Check"))
        self.mainGridLayout.addWidget(self.correctAtt_Check, 3, 4, 1, 1)
        self.Ch_label = QLabel(self.centralwidget)
        self.Ch_label.setObjectName(_fromUtf8("Ch_label"))
        self.mainGridLayout.addWidget(self.Ch_label, 1, 3, 1, 1)
        self.Bkgd_horizontalLayout = QHBoxLayout()
        self.Bkgd_horizontalLayout.setObjectName(
            _fromUtf8("Bkgd_horizontalLayout"))
        self.removeBG_Check = QCheckBox(self.centralwidget)
        self.removeBG_Check.setObjectName(_fromUtf8("removeBG_Check"))
        self.Bkgd_horizontalLayout.addWidget(self.removeBG_Check)
        self.customize_Check = QCheckBox(self.centralwidget)
        self.customize_Check.setObjectName(_fromUtf8("customize_Check"))
        self.Bkgd_horizontalLayout.addWidget(self.customize_Check)
        self.mainGridLayout.addLayout(self.Bkgd_horizontalLayout, 3, 2, 1, 2)
        self.comboBox = QComboBox(self.centralwidget)
        self.comboBox.setObjectName(_fromUtf8("comboBox"))
        self.comboBox.addItem(_fromUtf8(""))
        self.comboBox.addItem(_fromUtf8(""))
        self.mainGridLayout.addWidget(self.comboBox, 4, 0, 3, 2)
        self.fileName_Line = QLineEdit(self.centralwidget)
        self.fileName_Line.setObjectName(_fromUtf8("fileName_Line"))
        self.mainGridLayout.addWidget(self.fileName_Line, 0, 1, 1, 4)
        self.correctDrift_Check = QCheckBox(self.centralwidget)
        self.correctDrift_Check.setObjectName(_fromUtf8("correctDrift_Check"))
        self.mainGridLayout.addWidget(self.correctDrift_Check, 3, 0, 1, 2)
        self.T_Label = QLabel(self.centralwidget)
        self.T_Label.setObjectName(_fromUtf8("T_Label"))
        self.mainGridLayout.addWidget(self.T_Label, 1, 2, 1, 1)
        self.DIC_label = QLabel(self.centralwidget)
        self.DIC_label.setObjectName(_fromUtf8("DIC_label"))
        self.mainGridLayout.addWidget(self.DIC_label, 1, 4, 1, 1)
        self.channel_Spin = QSpinBox(self.centralwidget)
        self.channel_Spin.setMinimum(1)
        self.channel_Spin.setMaximum(5)
        self.channel_Spin.setObjectName(_fromUtf8("channel_Spin"))
        self.mainGridLayout.addWidget(self.channel_Spin, 2, 3, 1, 1)
        self.run_Button = QPushButton(self.centralwidget)
        self.run_Button.setObjectName(_fromUtf8("run_Button"))
        self.mainGridLayout.addWidget(self.run_Button, 9, 0, 1, 1)
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.resolution_Spin = QDoubleSpinBox(self.centralwidget)
        self.resolution_Spin.setSingleStep(0.01)
        self.resolution_Spin.setProperty("value", 0.21)
        self.resolution_Spin.setObjectName(_fromUtf8("resolution_Spin"))
        self.horizontalLayout.addWidget(self.resolution_Spin)
        self.resolution_Label = QLabel(self.centralwidget)
        self.resolution_Label.setObjectName(_fromUtf8("resolution_Label"))
        self.horizontalLayout.addWidget(self.resolution_Label)
        self.mainGridLayout.addLayout(self.horizontalLayout, 7, 0, 2, 2)
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.correctAtt_Spin = QDoubleSpinBox(self.centralwidget)
        self.correctAtt_Spin.setMaximum(1.0)
        self.correctAtt_Spin.setMinimum(0.01)
        self.correctAtt_Spin.setValue(0.1)
        self.correctAtt_Spin.setSingleStep(0.01)
        self.correctAtt_Spin.setObjectName(_fromUtf8("correctAtt_Spin"))
        self.verticalLayout.addWidget(self.correctAtt_Spin)
        spacerItem = QSpacerItem(88, 37, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem)
        self.mainGridLayout.addLayout(self.verticalLayout, 4, 4, 5, 1)
        self.featureSize_verticalLayout = QVBoxLayout()
        self.featureSize_verticalLayout.setObjectName(
            _fromUtf8("featureSize_verticalLayout"))
        self.horizontalLayout_1 = QHBoxLayout()
        self.horizontalLayout_1.setObjectName(_fromUtf8("horizontalLayout_1"))
        self.featureSize1_Label = QLabel(self.centralwidget)
        self.featureSize1_Label.setEnabled(True)
        self.featureSize1_Label.setObjectName(_fromUtf8("featureSize1_Label"))
        self.horizontalLayout_1.addWidget(self.featureSize1_Label)
        self.featureSize1_Spin = oddSpinBox(self.centralwidget)
        self.featureSize1_Spin.setEnabled(True)
        self.featureSize1_Spin.setMaximum(999)
        self.featureSize1_Spin.setSingleStep(2)
        self.featureSize1_Spin.setObjectName(_fromUtf8("featureSize1_Spin"))
        self.horizontalLayout_1.addWidget(self.featureSize1_Spin)
        self.featureSize_verticalLayout.addLayout(self.horizontalLayout_1)
        self.horizontalLayout_2 = QHBoxLayout()
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
        self.featureSize2_Label = QLabel(self.centralwidget)
        self.featureSize2_Label.setEnabled(True)
        self.featureSize2_Label.setObjectName(_fromUtf8("featureSize2_Label"))
        self.horizontalLayout_2.addWidget(self.featureSize2_Label)
        self.featureSize2_Spin = oddSpinBox(self.centralwidget)
        self.featureSize2_Spin.setEnabled(True)
        self.featureSize2_Spin.setMaximum(999)
        self.featureSize2_Spin.setSingleStep(2)
        self.featureSize2_Spin.setObjectName(_fromUtf8("featureSize2_Spin"))
        self.horizontalLayout_2.addWidget(self.featureSize2_Spin)
        self.featureSize_verticalLayout.addLayout(self.horizontalLayout_2)
        self.horizontalLayout_3 = QHBoxLayout()
        self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
        self.featureSize3_Label = QLabel(self.centralwidget)
        self.featureSize3_Label.setEnabled(True)
        self.featureSize3_Label.setObjectName(_fromUtf8("featureSize3_Label"))
        self.horizontalLayout_3.addWidget(self.featureSize3_Label)
        self.featureSize3_Spin = oddSpinBox(self.centralwidget)
        self.featureSize3_Spin.setEnabled(True)
        self.featureSize3_Spin.setMaximum(999)
        self.featureSize3_Spin.setSingleStep(2)
        self.featureSize3_Spin.setObjectName(_fromUtf8("featureSize3_Spin"))
        self.horizontalLayout_3.addWidget(self.featureSize3_Spin)
        self.featureSize_verticalLayout.addLayout(self.horizontalLayout_3)
        self.horizontalLayout_5 = QHBoxLayout()
        self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5"))
        self.featureSize4_Label = QLabel(self.centralwidget)
        self.featureSize4_Label.setEnabled(True)
        self.featureSize4_Label.setObjectName(_fromUtf8("featureSize4_Label"))
        self.horizontalLayout_5.addWidget(self.featureSize4_Label)
        self.featureSize4_Spin = oddSpinBox(self.centralwidget)
        self.featureSize4_Spin.setEnabled(True)
        self.featureSize4_Spin.setMaximum(999)
        self.featureSize4_Spin.setSingleStep(2)
        self.featureSize4_Spin.setObjectName(_fromUtf8("featureSize4_Spin"))
        self.horizontalLayout_5.addWidget(self.featureSize4_Spin)
        self.featureSize_verticalLayout.addLayout(self.horizontalLayout_5)
        self.horizontalLayout_8 = QHBoxLayout()
        self.horizontalLayout_8.setObjectName(_fromUtf8("horizontalLayout_8"))
        self.featureSize5_Label = QLabel(self.centralwidget)
        self.featureSize5_Label.setEnabled(True)
        self.featureSize5_Label.setObjectName(_fromUtf8("featureSize5_Label"))
        self.horizontalLayout_8.addWidget(self.featureSize5_Label)
        self.featureSize5_Spin = oddSpinBox(self.centralwidget)
        self.featureSize5_Spin.setEnabled(True)
        self.featureSize5_Spin.setMaximum(999)
        self.featureSize5_Spin.setSingleStep(2)
        self.featureSize5_Spin.setObjectName(_fromUtf8("featureSize5_Spin"))
        self.horizontalLayout_8.addWidget(self.featureSize5_Spin)
        self.featureSize_verticalLayout.addLayout(self.horizontalLayout_8)
        spacerItem1 = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.featureSize_verticalLayout.addItem(spacerItem1)
        self.mainGridLayout.addLayout(self.featureSize_verticalLayout, 4, 2, 5,
                                      2)
        self.gridLayout.addLayout(self.mainGridLayout, 0, 0, 1, 1)
        self.resolution_Label.raise_()
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusBar = QStatusBar(MainWindow)
        self.statusBar.setObjectName(_fromUtf8("statusBar"))
        MainWindow.setStatusBar(self.statusBar)

        self.featureSpins = [
            self.featureSize1_Spin, self.featureSize2_Spin,
            self.featureSize3_Spin, self.featureSize4_Spin,
            self.featureSize5_Spin
        ]
        self.featureLabels = [
            self.featureSize1_Label, self.featureSize2_Label,
            self.featureSize3_Label, self.featureSize4_Label,
            self.featureSize5_Label
        ]
        self.defaultFeatureValue = 301
        self.initialSetup()

        self.retranslateUi(MainWindow)
        self.connectUI()
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.openFile_Button.setText(_translate("MainWindow", "Open", None))
        self.Z_Label.setText(_translate("MainWindow", "Z", None))
        self.correctAtt_Check.setText(
            _translate("MainWindow", "Correct Attenuation", None))
        self.Ch_label.setText(_translate("MainWindow", "C", None))
        self.removeBG_Check.setText(
            _translate("MainWindow", "Remove Bkgd", None))
        self.customize_Check.setText(
            _translate("MainWindow", "Customize", None))
        self.comboBox.setItemText(0, _translate("MainWindow", "czt", None))
        self.comboBox.setItemText(1, _translate("MainWindow", "zct", None))
        self.correctDrift_Check.setText(
            _translate("MainWindow", "Correct Drift", None))
        self.T_Label.setText(_translate("MainWindow", "T", None))
        self.DIC_label.setText(_translate("MainWindow", "DIC", None))
        self.run_Button.setText(_translate("MainWindow", "Run", None))
        self.resolution_Label.setText(_translate("MainWindow", "um/pix", None))
        self.featureSize1_Label.setText(
            _translate("MainWindow", "Feature Size Ch X", None))
        self.featureSize2_Label.setText(
            _translate("MainWindow", "Feature Size Ch 2", None))
        self.featureSize3_Label.setText(
            _translate("MainWindow", "Feature Size Ch 3", None))
        self.featureSize4_Label.setText(
            _translate("MainWindow", "Feature Size Ch 4", None))
        self.featureSize5_Label.setText(
            _translate("MainWindow", "Feature Size Ch 5", None))

    def initialSetup(self):
        for feature in self.featureSpins:
            feature.setValue(self.defaultFeatureValue)
        self.noBckgdChecked()
        self.correctAttClicked(False)
        self.run_Button.setEnabled(False)

        self.z_Spin.setValue(18)
        self.time_Spin.setValue(4)
        self.channel_Spin.setValue(3)
        self.DIC_Spin.setValue(3)
        self.fileName_Line.setText(
            '/home/renat/Documents/work/development/example/W9F004T0001Z01C1.tif'
        )

        # #         self.z_Spin.setValue(1)
        # #         self.time_Spin.setValue(17)
        # #         self.channel_Spin.setValue(3)
        # #         self.DIC_Spin.setValue(1)
        # #         self.fileName_Line.setText('/home/renat/Documents/work/development/test/TESTME_BGLI141_1B_t2.tif')
        #
        # #         self.z_Spin.setValue(5)
        # #         self.time_Spin.setValue(7)
        # #         self.channel_Spin.setValue(3)
        # #         self.DIC_Spin.setValue(3)
        # #         self.fileName_Line.setText('/home/renat/Documents/work/development/test/OD3465-0002.tif_Files/OD3465-0002_z0t0c0.tif')
        self.run_Button.setEnabled(True)

    #
    # #         self.z_Spin.setValue(5)
    # #         self.time_Spin.setValue(7)
    # #         self.channel_Spin.setValue(3)
    # #         self.DIC_Spin.setValue(3)
    # #         self.fileName_Line.setText('/home/renat/Documents/work/development/test/OD3465-0003_2x2.tif_Files/OD3465-0003_2x2_z0t0c0.tif')
    # #         self.resolution_Spin.setValue(0.42)
    # #         self.run_Button.setEnabled(True)0

    def connectUI(self):
        self.openFile_Button.clicked.connect(self.openFile)
        self.run_Button.clicked.connect(self.run)
        self.correctAtt_Check.toggled.connect(self.correctAttClicked)

        self.channel_Spin.valueChanged.connect(self.channelNumChanged)
        self.DIC_Spin.valueChanged.connect(self.DIC_changed)
        self.removeBG_Check.toggled.connect(self.removeBGClicked)
        self.customize_Check.toggled.connect(self.customBGClicked)

    #         for i in range(len(self.featureSpins)):
    #             self.featureSpins[i].valueChanged.connect(self.checkOdd)

    def openFile(self):
        fileFilter = "TIF (*.tif)"
        fileName = QFileDialog.getOpenFileName(
            self.centralwidget, 'Open File',
            '/home/renat/Documents/work/development/Well005/', fileFilter)
        self.fileName_Line.setText(_translate("MainWindow", fileName[0], None))
        self.run_Button.setEnabled(True)

    def correctAttClicked(self, state):
        self.correctAtt_Spin.setEnabled(state)
        self.correctAtt_Spin.setVisible(state)
        if state:
            self.removeBG_Check.setChecked(True)

    def removeBGClicked(self, state):
        if state:
            self.customize_Check.setVisible(True)
            self.customize_Check.setEnabled(True)
            if self.channel_Spin.value() > 1: self.showFeatureSize(0, True)
        else:
            self.noBckgdChecked()

    def customBGClicked(self, state):
        nCh = self.channel_Spin.value()
        if state:
            self.showFeatureSize(0, False)
            self.featureSize1_Label.setText("Feature Size Ch 1")
            for i in range(nCh):
                if i != self.DIC_Spin.value() - 1:
                    self.showFeatureSize(i, True)
        else:
            self.hideAllFeatures()
            self.featureSize1_Label.setText("Feature Size Ch X")
            if self.channel_Spin.value() > 1: self.showFeatureSize(0, True)

    def channelNumChanged(self, nCh):
        self.DIC_Spin.setMaximum(nCh)
        if self.customize_Check.isChecked():
            self.customBGClicked(False)
            self.customBGClicked(True)

    def DIC_changed(self):
        if self.customize_Check.isChecked():
            self.customBGClicked(False)
            self.customBGClicked(True)

    def hideAllFeatures(self):
        for i in range(len(self.featureLabels)):
            self.showFeatureSize(i, False)

    def noBckgdChecked(self):
        self.correctAtt_Check.setChecked(False)
        self.hideAllFeatures()
        self.customize_Check.setChecked(False)
        self.customize_Check.setEnabled(False)
        self.customize_Check.setVisible(False)

    def showFeatureSize(self, ch, bool):
        self.featureSpins[ch].setEnabled(bool)
        self.featureSpins[ch].setVisible(bool)
        self.featureLabels[ch].setVisible(bool)

    def checkOdd(self, val):
        if val % 2 == 0:
            self.centralwidget.sender().setValue(val + 1)

    def run(self):
        self.statusBar.showMessage('Running...')
        QApplication.processEvents()
        if self.customize_Check.isChecked():
            featureList = []
            for f in self.featureSpins:
                featureList.append(f.value())
        else:
            featureList = [
                self.featureSize1_Spin.value()
                for i in range(self.channel_Spin.value())
            ]
        featureList[self.DIC_Spin.value() - 1] = None
        self.statusBar.showMessage('Loading images...')
        imgs = self.openImage()
        self.statusBar.showMessage('Cropping...')
        try:
            allEmbs = cropAPI.cropEmbs(imgs, self.DIC_Spin.value() - 1, self.correctDrift_Check.isChecked(), \
                                       self.correctAtt_Check.isChecked(), self.correctAtt_Spin.value(),
                                       self.removeBG_Check.isChecked(), featureList, self.resolution_Spin.value())
            self.save(allEmbs)
        except Exception as err:
            QMessageBox.warning(self.centralwidget, 'Error',
                                traceback.format_exc())
            self.statusBar.showMessage('Error: ' + str(err))

    def openImage(self):
        path, nZ, nT, nCh, order = str(self.fileName_Line.text()), self.z_Spin.value(), self.time_Spin.value(), \
                                   self.channel_Spin.value(), str(self.comboBox.currentText())
        if os.path.isfile(path):
            ims = myFunc.loadImTif(path)
            if len(ims.shape) == 2:
                path = '/'.join(path.split('/')[:-1]) + '/'
                ims = myFunc.loadImFolder(path)
        elif os.path.isdir(path):
            ims = myFunc.loadImFolder(path)
        else:
            raise ('Error: wrong path {0}'.format(path))
        if len(ims.shape) > 3:
            ims = np.reshape(ims, (-1, ims.shape[-2], ims.shape[-1]))
        if np.array(ims).size == nZ * nT * nCh * ims[0].size:
            if order == 'czt':
                ims = np.reshape(ims, (nT, nZ, nCh, ims[0].shape[0],
                                       ims[0].shape[1])).astype(np.float)
            else:
                ims = np.reshape(ims, (nT, nCh, nZ, ims[0].shape[0],
                                       ims[0].shape[1])).astype(np.float)
                ims = np.swapaxes(ims, 1, 2)
        else:
            self.statusBar.showMessage(
                'Error: number of images (or sizes) does not correspond to z={0}, t={1}, ch={2}'
                .format(nZ, nT, nCh))
            raise Exception(
                'Error: number of images (or sizes) does not correspond to z={0}, t={1}, ch={2}'
                .format(nZ, nT, nCh))
        return ims

    def save(self, allEmbs):
        path = '/'.join(str(self.fileName_Line.text()).split('/')[:-1]) + '/'
        if not os.path.exists(path + 'crop/'): myFunc.mkdir_p(path + 'crop/')
        for i in range(len(allEmbs)):
            self.statusBar.showMessage('saving Embryo {}'.format(i + 1))
            myFunc.saveImagesMulti(allEmbs[i].astype(np.uint16),
                                   path + 'crop/Emb{0:02}.tif'.format(i))
        self.statusBar.showMessage('embryos saved')
예제 #10
0
파일: gps.py 프로젝트: strnk/skippycopter
class GPSWindow(QDialog):
    satellites = 0      # Satellites in view
    hdop = 40           # Horizontal dilution of position

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

    def setupUi(self):
        self.setObjectName("GPSWindow")
        self.setModal(True)

        top = QHBoxLayout(self)
        ll = QVBoxLayout()
        self.web = QWebView()
        ll.addWidget(self.web)

        self.statusBar = QStatusBar(self)
        ll.addWidget(self.statusBar)

        top.addLayout(ll)

        self.resize(640, 480)

        self.statusBar.showMessage("No fix")
        self.web.setHtml('''<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Circles</title>
    <style>
      html, body, #map-canvas {
        height: 100%;
        margin: 0;
        padding: 0;
      }

    </style>
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
    <script>
var map;
var quadcircle;

function updatePosition(lat, lng, err){
    quadCircle.setMap(map);
    quadCircle.setCenter(new google.maps.LatLng(lat, lng));
    quadCircle.setRadius(err);
}

function hidePosition(){
    quadCircle.setMap(null);
}

function moveToLocation(lat, lng){
    var center = new google.maps.LatLng(lat, lng);
    map.panTo(center);
}

function initialize() {
    // Create the map.
    map = new google.maps.Map(document.getElementById('map-canvas'), {
        zoom: 4,
        center: new google.maps.LatLng(0, 0),
        mapTypeId: google.maps.MapTypeId.TERRAIN
    });

    // Representation of the quadricopter on map
    quadCircle = new google.maps.Circle({
        strokeColor: '#FF0000',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#FF0000',
        fillOpacity: 0.35,
        map: null
    });
    hidePosition();
}

google.maps.event.addDomListener(window, 'load', initialize);

    </script>
  </head>
  <body>
    <div id="map-canvas"></div>
  </body>
</html>''')

    def parseNMEA(self, nmeaMessage):
        fields = nmeaMessage.split(',')

        # Recommended Minimum
        if fields[0] == '$GPRMC':
            if fields[3] != '' and fields[5] != '':
                lat = float(fields[3]) * (1.0 if fields[4] == 'N' else -1.0)
                lon = float(fields[5]) * (1.0 if fields[4] == 'E' else -1.0)

                lat = int(lat/100) + (lat - (int(lat/100) * 100)) / 60
                lon = int(lon/100) + (lon - (int(lon/100) * 100)) / 60

                self.web.page().mainFrame().evaluateJavaScript('moveToLocation(%f, %f)' % (lat, lon))
                self.web.page().mainFrame().evaluateJavaScript('updatePosition(%f, %f, %d)' % (lat, lon, self.hdop * 2.5))

                self.statusBar.showMessage("Fix, %d satellites in view" % (self.satellites))
            else:
                self.statusBar.showMessage("No fix, %d satellites in view" % (self.satellites))
                self.web.page().mainFrame().evaluateJavaScript('hidePosition()')
        elif fields[0] == '$GPGSV':
            self.satellites = int(fields[3])
        elif fields[0] == '$GPGSA':
            self.hdop = float(fields[16])

    def newData(self, string):
        data = string.rstrip('\r\n').split()

        if data[0] != 'GPS':
            return

        self.parseNMEA(' '.join(data[1:]))

    def newMessage(self, message, data):
        if message == 'GPS':
            self.parseNMEA(data)
예제 #11
0
class MainWindow_Ui(QMainWindow):
    def __init__(self, persepolis_setting):
        super().__init__()
        # MainWindow
        self.persepolis_setting = persepolis_setting

        # add support for other languages
        locale = str(self.persepolis_setting.value('settings/locale'))
        QLocale.setDefault(QLocale(locale))
        self.translator = QTranslator()
        if self.translator.load(':/translations/locales/ui_' + locale, 'ts'):
            QCoreApplication.installTranslator(self.translator)


        # set ui direction
        ui_direction = self.persepolis_setting.value('ui_direction')

        if ui_direction == 'rtl':
            self.setLayoutDirection(Qt.RightToLeft)
        
        elif ui_direction in 'ltr':
            self.setLayoutDirection(Qt.LeftToRight)



        icons = ':/' + \
            str(self.persepolis_setting.value('settings/icons')) + '/'

        self.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager"))
        self.setWindowIcon(QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg')))

        self.centralwidget = QWidget(self)
        self.verticalLayout = QVBoxLayout(self.centralwidget)
        # enable drag and drop
        self.setAcceptDrops(True)
# frame
        self.frame = QFrame(self.centralwidget)

# download_table_horizontalLayout
        download_table_horizontalLayout = QHBoxLayout()
        tabels_splitter = QSplitter(Qt.Horizontal)
# category_tree
        self.category_tree_qwidget = QWidget(self)
        category_tree_verticalLayout = QVBoxLayout()
        self.category_tree = CategoryTreeView(self)
        category_tree_verticalLayout.addWidget(self.category_tree)

        self.category_tree_model = QStandardItemModel()
        self.category_tree.setModel(self.category_tree_model)
        category_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'Category')]

        self.category_tree_model.setHorizontalHeaderLabels(
            category_table_header)
        self.category_tree.header().setStretchLastSection(True)

        self.category_tree.header().setDefaultAlignment(Qt.AlignCenter)
        
# queue_panel
        self.queue_panel_widget = QWidget(self)

        queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget)
# queue_panel_show_button
        self.queue_panel_show_button = QPushButton(self)

        queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button)
# queue_panel_widget_frame
        self.queue_panel_widget_frame = QFrame(self)
        self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel)
        self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised)

        queue_panel_verticalLayout_main.addWidget(
            self.queue_panel_widget_frame)

        queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame)
        queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1)

# start_end_frame
        self.start_end_frame = QFrame(self)

# start time
        start_verticalLayout = QVBoxLayout(self.start_end_frame)
        self.start_checkBox = QCheckBox(self)
        start_verticalLayout.addWidget(self.start_checkBox)

        self.start_frame = QFrame(self)
        self.start_frame.setFrameShape(QFrame.StyledPanel)
        self.start_frame.setFrameShadow(QFrame.Raised)

        start_frame_verticalLayout = QVBoxLayout(self.start_frame)

        self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame)
        self.start_time_qDataTimeEdit.setDisplayFormat('H:mm')
        start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit)
  
        start_verticalLayout.addWidget(self.start_frame)
# end time

        self.end_checkBox = QCheckBox(self)
        start_verticalLayout.addWidget(self.end_checkBox)

        self.end_frame = QFrame(self)
        self.end_frame.setFrameShape(QFrame.StyledPanel)
        self.end_frame.setFrameShadow(QFrame.Raised)

        end_frame_verticalLayout = QVBoxLayout(self.end_frame)

        self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame)
        self.end_time_qDateTimeEdit.setDisplayFormat('H:mm')
        end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit)
 
        start_verticalLayout.addWidget(self.end_frame)

        self.reverse_checkBox = QCheckBox(self)
        start_verticalLayout.addWidget(self.reverse_checkBox)

        queue_panel_verticalLayout.addWidget(self.start_end_frame)

# limit_after_frame
        self.limit_after_frame = QFrame(self)
# limit_checkBox
        limit_verticalLayout = QVBoxLayout(self.limit_after_frame)
        self.limit_checkBox = QCheckBox(self)
        limit_verticalLayout.addWidget(self.limit_checkBox)
# limit_frame
        self.limit_frame = QFrame(self)
        self.limit_frame.setFrameShape(QFrame.StyledPanel)
        self.limit_frame.setFrameShadow(QFrame.Raised)
        limit_verticalLayout.addWidget(self.limit_frame)

        limit_frame_verticalLayout = QVBoxLayout(self.limit_frame)
# limit_spinBox
        limit_frame_horizontalLayout = QHBoxLayout()
        self.limit_spinBox = QDoubleSpinBox(self)
        self.limit_spinBox.setMinimum(1)
        self.limit_spinBox.setMaximum(1023)
        limit_frame_horizontalLayout.addWidget(self.limit_spinBox)
# limit_comboBox
        self.limit_comboBox = QComboBox(self)
        self.limit_comboBox.addItem("")
        self.limit_comboBox.addItem("")
        limit_frame_horizontalLayout.addWidget(self.limit_comboBox)
        limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout)
# limit_pushButton
        self.limit_pushButton = QPushButton(self)
        limit_frame_verticalLayout.addWidget(self.limit_pushButton)

# after_checkBox
        self.after_checkBox = QtWidgets.QCheckBox(self)
        limit_verticalLayout.addWidget(self.after_checkBox)
# after_frame
        self.after_frame = QtWidgets.QFrame(self)
        self.after_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.after_frame.setFrameShadow(QtWidgets.QFrame.Raised)
        limit_verticalLayout.addWidget(self.after_frame)

        after_frame_verticalLayout = QVBoxLayout(self.after_frame)
# after_comboBox
        self.after_comboBox = QComboBox(self)
        self.after_comboBox.addItem("")

        after_frame_verticalLayout.addWidget(self.after_comboBox)
# after_pushButton
        self.after_pushButton = QPushButton(self)
        after_frame_verticalLayout.addWidget(self.after_pushButton)

        queue_panel_verticalLayout.addWidget(self.limit_after_frame)
        category_tree_verticalLayout.addWidget(self.queue_panel_widget)

# keep_awake_checkBox
        self.keep_awake_checkBox = QCheckBox(self)
        queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox)

        self.category_tree_qwidget.setLayout(category_tree_verticalLayout)
        tabels_splitter.addWidget(self.category_tree_qwidget)

# download table widget
        self.download_table_content_widget = QWidget(self)
        download_table_content_widget_verticalLayout = QVBoxLayout(
            self.download_table_content_widget)

        self.download_table = DownloadTableWidget(self)
        download_table_content_widget_verticalLayout.addWidget(
            self.download_table)
        tabels_splitter.addWidget(self.download_table_content_widget)

        self.download_table.setColumnCount(13)
        self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.download_table.verticalHeader().hide()

# hide gid and download dictioanry section
        self.download_table.setColumnHidden(8, True)
        self.download_table.setColumnHidden(9, True)

        download_table_header = [QCoreApplication.translate("mainwindow_ui_tr", 'File Name'), QCoreApplication.translate("mainwindow_ui_tr",'Status'), QCoreApplication.translate("mainwindow_ui_tr", 'Size'), QCoreApplication.translate("mainwindow_ui_tr", 'Downloaded'), QCoreApplication.translate("mainwindow_ui_tr", 'Percentage'), QCoreApplication.translate("mainwindow_ui_tr", 'Connections'),
                                 QCoreApplication.translate("mainwindow_ui_tr", 'Transfer rate'), QCoreApplication.translate("mainwindow_ui_tr",'Estimated time left'), 'Gid', QCoreApplication.translate("mainwindow_ui_tr",'Link'), QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), QCoreApplication.translate("mainwindow_ui_tr", 'Last try date'), QCoreApplication.translate("mainwindow_ui_tr",'Category')]

        self.download_table.setHorizontalHeaderLabels(download_table_header)

# fixing the size of download_table when window is Maximized!
        self.download_table.horizontalHeader().setSectionResizeMode(0)
        self.download_table.horizontalHeader().setStretchLastSection(True)

        tabels_splitter.setStretchFactor(0, 3) # category_tree width
        tabels_splitter.setStretchFactor(1, 10)  # ratio of tables's width
        download_table_horizontalLayout.addWidget(tabels_splitter)
        self.frame.setLayout(download_table_horizontalLayout)
        self.verticalLayout.addWidget(self.frame)
        self.setCentralWidget(self.centralwidget)

# menubar
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QRect(0, 0, 600, 24))
        self.setMenuBar(self.menubar)
        fileMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&File'))
        editMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Edit'))
        viewMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&View'))
        downloadMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Download'))
        queueMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Queue'))
        videoFinderMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'V&ideo Finder'))
        helpMenu = self.menubar.addMenu(QCoreApplication.translate("mainwindow_ui_tr", '&Help'))


# viewMenu submenus
        sortMenu = viewMenu.addMenu(QCoreApplication.translate("mainwindow_ui_tr", 'Sort by'))
# statusbar
        self.statusbar = QStatusBar(self)
        self.setStatusBar(self.statusbar)
        self.statusbar.showMessage(QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager"))
# toolBar
        self.toolBar2 = QToolBar(self)
        self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar2)
        self.toolBar2.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Menu'))
        self.toolBar2.setFloatable(False)
        self.toolBar2.setMovable(False)

        self.toolBar = QToolBar(self)
        self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.toolBar.setWindowTitle(QCoreApplication.translate("mainwindow_ui_tr", 'Toolbar'))
        self.toolBar.setFloatable(False)
        self.toolBar.setMovable(False)


#toolBar and menubar and actions
        self.videoFinderAddLinkAction = QAction(QIcon(icons + 'video_finder'), QCoreApplication.translate("mainwindow_ui_tr", 'Find Video Links'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Download video or audio from Youtube, Vimeo, etc...'),
                                            triggered=self.showVideoFinderAddLinkWindow)

        QShortcut(QKeySequence('Ctrl+I'), self, self.showVideoFinderAddLinkWindow)

        videoFinderMenu.addAction(self.videoFinderAddLinkAction)

        self.stopAllAction = QAction(QIcon(icons + 'stop_all'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop all active downloads'),
                                     self, statusTip='Stop all active downloads', triggered=self.stopAllDownloads)
        downloadMenu.addAction(self.stopAllAction)

        self.sort_file_name_Action = QAction(
            QCoreApplication.translate("mainwindow_ui_tr", 'File name'), self, triggered=self.sortByName)
        sortMenu.addAction(self.sort_file_name_Action)

        self.sort_file_size_Action = QAction(
            QCoreApplication.translate("mainwindow_ui_tr", 'File size'), self, triggered=self.sortBySize)
        sortMenu.addAction(self.sort_file_size_Action)

        self.sort_first_try_date_Action = QAction(
            QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), self, triggered=self.sortByFirstTry)
        sortMenu.addAction(self.sort_first_try_date_Action)

        self.sort_last_try_date_Action = QAction(
            QCoreApplication.translate("mainwindow_ui_tr", 'Last try date'), self, triggered=self.sortByLastTry)
        sortMenu.addAction(self.sort_last_try_date_Action)

        self.sort_download_status_Action = QAction(
            QCoreApplication.translate("mainwindow_ui_tr", 'Download status'), self, triggered=self.sortByStatus)
        sortMenu.addAction(self.sort_download_status_Action)

        self.trayAction = QAction(QCoreApplication.translate("mainwindow_ui_tr", 'Show system tray icon'), self,
                                  statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Show/Hide system tray icon"), triggered=self.showTray)
        self.trayAction.setCheckable(True)
        viewMenu.addAction(self.trayAction)

        self.showMenuBarAction = QAction(
            QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), triggered=self.showMenuBar)
        self.showMenuBarAction.setCheckable(True)
        viewMenu.addAction(self.showMenuBarAction)

        self.showSidePanelAction = QAction(
            QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), triggered=self.showSidePanel)
        self.showSidePanelAction.setCheckable(True)
        viewMenu.addAction(self.showSidePanelAction)

        self.minimizeAction = QAction(QIcon(icons + 'minimize'), QCoreApplication.translate("mainwindow_ui_tr", 'Minimize to system tray'), self,
                                      statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Minimize to system tray"), triggered=self.minMaxTray)
        QShortcut(QKeySequence('Ctrl+W'), self, self.minMaxTray)

        viewMenu.addAction(self.minimizeAction)

        self.addlinkAction = QAction(QIcon(icons + 'add'), QCoreApplication.translate("mainwindow_ui_tr", 'Add New Download Link'), self,
                                     statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Add New Download Link"), triggered=self.addLinkButtonPressed)
        QShortcut(QKeySequence('Ctrl+N'), self, self.addLinkButtonPressed)
        fileMenu.addAction(self.addlinkAction)

        self.addtextfileAction = QAction(QIcon(icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Import links from text file'), self,
                                         statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create a Text file and put links in it.line by line!'), triggered=self.importText)
        fileMenu.addAction(self.addtextfileAction)

        self.resumeAction = QAction(QIcon(icons + 'play'), QCoreApplication.translate("mainwindow_ui_tr", 'Resume Download'), self,
                                    statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Resume Download"), triggered=self.resumeButtonPressed)
        QShortcut(QKeySequence('Ctrl+R'), self, self.resumeButtonPressed)
        downloadMenu.addAction(self.resumeAction)

        self.pauseAction = QAction(QIcon(icons + 'pause'), QCoreApplication.translate("mainwindow_ui_tr", 'Pause Download'), self,
                                   statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Pause Download"), triggered=self.pauseButtonPressed)
        QShortcut(QKeySequence('Ctrl+C'), self, self.pauseButtonPressed)
        downloadMenu.addAction(self.pauseAction)

        self.stopAction = QAction(QIcon(icons + 'stop'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop Download'), self,
                                  statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Stop/Cancel Download"), triggered=self.stopButtonPressed)
        QShortcut(QKeySequence('Ctrl+S'), self, self.stopButtonPressed)
        downloadMenu.addAction(self.stopAction)

        self.propertiesAction = QAction(QIcon(icons + 'setting'), QCoreApplication.translate("mainwindow_ui_tr", 'Properties'), self,
                                        statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Properties"), triggered=self.propertiesButtonPressed)
        QShortcut(QKeySequence('Ctrl+P'), self, self.propertiesButtonPressed)
        downloadMenu.addAction(self.propertiesAction)

        self.progressAction = QAction(QIcon(icons + 'window'), QCoreApplication.translate("mainwindow_ui_tr", 'Progress'), self,
                                      statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Progress"), triggered=self.progressButtonPressed)
        QShortcut(QKeySequence('Ctrl+Z'), self, self.progressButtonPressed)
        downloadMenu.addAction(self.progressAction)

        self.openFileAction = QAction(QIcon(
            icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), triggered=self.openFile)
        fileMenu.addAction(self.openFileAction)

        self.openDownloadFolderAction = QAction(QIcon(
            icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), triggered=self.openDownloadFolder)
        fileMenu.addAction(self.openDownloadFolderAction)

        self.openDefaultDownloadFolderAction = QAction(QIcon(
            icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open default download folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open default download folder'), triggered=self.openDefaultDownloadFolder)
        fileMenu.addAction(self.openDefaultDownloadFolderAction)

        self.exitAction = QAction(QIcon(icons + 'exit'), QCoreApplication.translate("mainwindow_ui_tr", 'Exit'), self,
                                  statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Exit"), triggered=self.closeEvent)
        QShortcut(QKeySequence('Ctrl+Q'), self, self.closeEvent)
        fileMenu.addAction(self.exitAction)

        self.clearAction = QAction(QIcon(icons + 'multi_remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Clear download list'),
                                         self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Clear all items in download list'), triggered=self.clearDownloadList)
        editMenu.addAction(self.clearAction)

        self.removeSelectedAction = QAction(QIcon(icons + 'remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove selected downloads from list'),
                                            self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove selected downloads form list'), triggered=self.removeSelected)
        editMenu.addAction(self.removeSelectedAction)
        self.removeSelectedAction.setEnabled(False)

        self.deleteSelectedAction = QAction(QIcon(icons + 'trash'), QCoreApplication.translate("mainwindow_ui_tr", 'Delete selected download files'),
                                            self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Delete selected download files'), triggered=self.deleteSelected)
        editMenu.addAction(self.deleteSelectedAction)
        self.deleteSelectedAction.setEnabled(False)

        self.createQueueAction = QAction(QIcon(icons + 'add_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Create new queue'),
                                         self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create new download queue'), triggered=self.createQueue)
        queueMenu.addAction(self.createQueueAction)

        self.removeQueueAction = QAction(QIcon(icons + 'remove_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'),
                                         self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), triggered=self.removeQueue)
        queueMenu.addAction(self.removeQueueAction)

        self.startQueueAction = QAction(QIcon(
            icons + 'start_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), triggered=self.startQueue)
        queueMenu.addAction(self.startQueueAction)

        self.stopQueueAction = QAction(QIcon(
            icons + 'stop_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), triggered=self.stopQueue)
        queueMenu.addAction(self.stopQueueAction)

        self.moveUpSelectedAction = QAction(QIcon(icons + 'multi_up'), QCoreApplication.translate("mainwindow_ui_tr", 'Move up selected items'), self,
                                            statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items up by one row'), triggered=self.moveUpSelected)
        queueMenu.addAction(self.moveUpSelectedAction)

        self.moveDownSelectedAction = QAction(QIcon(icons + 'multi_down'), QCoreApplication.translate("mainwindow_ui_tr", 'Move down selected items'),
                                              self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Move currently selected items down by one row'), triggered=self.moveDownSelected)
        queueMenu.addAction(self.moveDownSelectedAction)

        self.preferencesAction = QAction(QIcon(icons + 'preferences'), QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'),
                                         self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), triggered=self.openPreferences, menuRole=5)
        editMenu.addAction(self.preferencesAction)

        self.aboutAction = QAction(QIcon(
            icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'About'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'About'), triggered=self.openAbout, menuRole=4)
        helpMenu.addAction(self.aboutAction)

        self.issueAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'),
                                   self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), triggered=self.reportIssue)
        helpMenu.addAction(self.issueAction)

        self.updateAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer version'),
                                    self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer release'), triggered=self.newUpdate)
        helpMenu.addAction(self.updateAction)

        self.logAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Show log file'),
                                   self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.showLog)
        helpMenu.addAction(self.logAction)

        self.helpAction = QAction(QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Help'),
                                   self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.persepolisHelp)
        helpMenu.addAction(self.helpAction)

        self.qmenu = MenuWidget(self)

        self.toolBar2.addWidget(self.qmenu)

# labels
        self.queue_panel_show_button.setText(QCoreApplication.translate("mainwindow_ui_tr", "Hide options"))
        self.start_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Start Time"))

        self.end_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "End Time"))

        self.reverse_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Download bottom of\n the list first"))

        self.limit_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Limit Speed"))
        self.limit_comboBox.setItemText(0, "KiB/s")
        self.limit_comboBox.setItemText(1, "MiB/s")
        self.limit_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Apply"))

        self.after_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "After download"))
        self.after_comboBox.setItemText(0, QCoreApplication.translate("mainwindow_ui_tr", "Shut Down"))

        self.keep_awake_checkBox.setText(QCoreApplication.translate("mainwindow_ui_tr", "Keep system awake!"))
        self.keep_awake_checkBox.setToolTip(
            QCoreApplication.translate("mainwindow_ui_tr", "<html><head/><body><p>This option is preventing system from going to sleep.\
            This is necessary if your power manager is suspending system automatically. </p></body></html>"))
 
        self.after_pushButton.setText(QCoreApplication.translate("mainwindow_ui_tr", "Apply"))

    def changeIcon(self, icons):
        icons = ':/' + str(icons) + '/'

        action_icon_dict = {self.stopAllAction: 'stop_all', self.minimizeAction: 'minimize', self.addlinkAction: 'add', self.addtextfileAction: 'file', self.resumeAction: 'play', self.pauseAction: 'pause', self.stopAction: 'stop', self.propertiesAction: 'setting', self.progressAction: 'window', self.openFileAction: 'file', self.openDownloadFolderAction: 'folder', self.openDefaultDownloadFolderAction: 'folder', self.exitAction: 'exit',
                self.removeSelectedAction: 'multi_remove', self.deleteSelectedAction: 'multi_trash', self.createQueueAction: 'add_queue', self.removeQueueAction: 'remove_queue', self.startQueueAction: 'start_queue', self.stopQueueAction: 'stop_queue', self.preferencesAction: 'preferences', self.aboutAction: 'about', self.issueAction: 'about', self.updateAction: 'about', self.videoFinderAddLinkAction: 'video_finder', self.qmenu: 'menu'}
        for key in action_icon_dict.keys():
            key.setIcon(QIcon(icons + str(action_icon_dict[key])))
예제 #12
0
class MainWindowUi(QMainWindow):
    """This class manages the system tray icon of the main program, post-login.
    """

    vpn_connect_section = QVBoxLayout()

    def __init__(self):
        super(QMainWindow, self).__init__()
        # Using a StackedWidget to be able to replace login window
        # https://stackoverflow.com/questions/13550076
        self.cw = QStackedWidget()
        self.setCentralWidget(self.cw)
        # Set minimum width of Main Window to 500 pixels
        self.cw.setMinimumWidth(500)
        self.setWindowTitle('MerLink - VPN Client for Meraki firewalls')
        self.link_style = "font-family: verdana, sans-serif; font-style:" \
                          " normal; font-size: 13px; color: #1795E6;"

        # Required for Login. Elements should be object variables if they
        # Could be called by other modules
        self.username_textfield = QLineEdit()
        self.password_textfield = QLineEdit()
        self.guest_user_chkbox = QCheckBox("Use guest account instead")
        self.password_textfield.setEchoMode(QLineEdit.Password)
        self.org_dropdown = QComboBox()
        self.create_vpn_btn = QPushButton("Create VPN Interface")

        self.create_vpn_tabs = QTabWidget()
        self.tab_dashboard = QWidget()
        self.tab_manual = QWidget()
        self.vpn_opts_layout = QVBoxLayout()

    def setup_pyqt_slots(self):
        """Initiate all of the triggers and connects."""

    def setup_window(self):
        """Setup various sections that will be combined."""
        self.create_vpn_tabs.addTab(self.tab_dashboard, "Dashboard Setup")
        self.create_vpn_tabs.addTab(self.tab_manual, "Manual Setup")

        self.vpn_opts_setup()
        self.setup_manual_tab()
        self.setup_dashboard_tab()
        self.vpn_connect_setup()

        self.decorate_sections()
        self.combine_sections_dashboard()

        # Set the layout once we are done adding elements
        self.main_window_set_admin_layout()

    def setup_dashboard_tab(self):
        """Provide input fields for dashboard-gathered data."""
        self.tab_dashboard.layout = QVBoxLayout(self)

        # Guest users should manually enter their information
        # Only difference between Guest and Dashboard for UI should be that
        # Email/pass is prepopulated for dashboard admins (inactivated)
        email_pass_layout = QVBoxLayout()
        username_label = QLabel("Email")
        password_label = QLabel("Password")
        self.disable_email_pass(True)
        self.add_all_to_layout(
            email_pass_layout,
            [
                username_label,
                self.username_textfield,
                password_label,
                self.password_textfield
            ]
        )
        self.tab_dashboard.layout.addWidget(self.guest_user_chkbox)
        self.tab_dashboard.layout.addLayout(email_pass_layout)
        self.tab_dashboard.layout.addLayout(self.vpn_opts_layout)
        self.tab_dashboard.setLayout(self.tab_dashboard.layout)

    def disable_email_pass(self, change_to_disabled):
        """Disable username/password if user should not edit them."""
        disable_lineedit(self.username_textfield, change_to_disabled)
        disable_lineedit(self.password_textfield, change_to_disabled)

    def vpn_opts_setup(self):
        """Set up the vpn vars UI region."""
        # Create org and network dropdowns so the user can select the firewall
        # they would like to connect to.
        org_dropdown = QComboBox()
        org_dropdown.addItem('-- Select an Organization --')
        network_dropdown = QComboBox()
        network_dropdown.setEnabled(False)

        # Allow the user to change the VPN name
        vpn_name_layout = QHBoxLayout()
        vpn_name_label = QLabel("VPN Name:")
        vpn_name_textfield = QLineEdit()
        vpn_name_layout.addWidget(vpn_name_label)
        vpn_name_layout.addWidget(vpn_name_textfield)

        # Ask the user for int/str values if they want to enter them
        idle_disconnect_layout = QHBoxLayout()
        idle_disconnect_chkbox = QCheckBox("Idle disconnect seconds?")
        idle_disconnect_spinbox = QSpinBox()
        idle_disconnect_spinbox.setValue(0)
        # Negative seconds aren't useful here
        idle_disconnect_spinbox.setMinimum(0)
        idle_disconnect_layout.addWidget(
            idle_disconnect_chkbox)
        idle_disconnect_layout.addWidget(
            idle_disconnect_spinbox)

        dns_suffix_layout = QHBoxLayout()
        dns_suffix_chkbox = QCheckBox("DNS Suffix?")
        dns_suffix_txtbox = QLineEdit('-')
        dns_suffix_layout.addWidget(dns_suffix_chkbox)
        dns_suffix_layout.addWidget(dns_suffix_txtbox)

        # Boolean asks of the user
        split_tunneled_chkbox = QCheckBox("Split-Tunnel?")
        remember_credential_chkbox = QCheckBox("Remember Credentials?")
        use_winlogon_chkbox = QCheckBox("Use Windows Logon Credentials?")

        self.add_all_to_layout(
            self.vpn_opts_layout,
            [
                org_dropdown,
                network_dropdown,
                vpn_name_layout,
                # Add layouts for specialized params
                idle_disconnect_layout,
                dns_suffix_layout,
                # Add checkboxes
                split_tunneled_chkbox,
                remember_credential_chkbox,
                use_winlogon_chkbox,
                # Ensure that button is at bottom of pane by adding space
                QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
            ]
        )

    def setup_manual_tab(self):
        """Gray out options and provide input fields to manually enter data."""
        self.tab_manual.layout = QVBoxLayout(self)
        # User should be able to change email/pass as it's required
        self.disable_email_pass(False)
        username_textfield = QLineEdit()
        password_textfield = QLineEdit()
        password_textfield.setEchoMode(QLineEdit.Password)
        username_label = QLabel("Email")
        password_label = QLabel("Password")
        vpn_name_label = QLabel("VPN Name")
        vpn_name_textfield = QLineEdit()
        server_name_label = QLabel("Server name/IP")
        server_name_textfield = QLineEdit()
        shared_secret_label = QLabel("Shared Secret")
        shared_secret_textfield = QLineEdit()
        shared_secret_textfield.setEchoMode(QLineEdit.Password)
        self.add_all_to_layout(
            self.tab_manual.layout,
            [
                username_label,
                username_textfield,
                password_label,
                password_textfield,
                vpn_name_label,
                vpn_name_textfield,
                server_name_label,
                server_name_textfield,
                shared_secret_label,
                shared_secret_textfield,
                QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
            ]
        )
        self.tab_manual.setLayout(self.tab_manual.layout)

    def vpn_connect_setup(self):
        """Setup the GUI componentst of the right pane."""
        vpn_list = QListWidget()
        ipsum_vpn_interfaces = ['eth', 'wifi']
        vpn_list.addItems(ipsum_vpn_interfaces)

        check_for_probs_cb = QCheckBox(
            "Check for issues before connecting (recommended)")
        check_for_probs_cb.setChecked(True)
        probs_list = QListWidget()
        problems = ["Forget the milk", "My hovercraft is full of eels"]
        probs_list.addItems(problems)
        connect_vpn_btn = QPushButton("Connect")

        self.add_all_to_layout(
            self.vpn_connect_section,
            [
                vpn_list,
                check_for_probs_cb,
                probs_list,
                connect_vpn_btn
            ]
        )

    def decorate_sections(self):
        """Add a box around each section for readability."""
        # Set GroupBox CSS manually because otherwise margins are huge
        self.setStyleSheet(".QGroupBox {  border: 1px solid #ccc;}")

    def combine_sections_dashboard(self):
        """Combine left and right panes into a final layout."""
         # Create a horizontal line above the status bar to highlight it
        self.hline = QFrame()
        self.hline.setFrameShape(QFrame.HLine)
        self.hline.setFrameShadow(QFrame.Sunken)

        self.vline = QFrame()
        self.vline.setFrameShape(QFrame.VLine)
        self.vline.setFrameShadow(QFrame.Sunken)
        # Status bar be at bottom and inform user of what the program is doing.
        self.status = QStatusBar()
        self.status.showMessage("Status: -")
        self.status.setStyleSheet("Background:#fff")

        main_widget = QWidget()
        main_layout = QVBoxLayout(main_widget)

        left_pane = QVBoxLayout()
        left_pane.addWidget(self.create_vpn_tabs)
        left_pane.addWidget(self.create_vpn_btn)

        two_pane_layout = QHBoxLayout()
        two_pane_layout.addLayout(left_pane)
        two_pane_layout.addWidget(self.vline)
        two_pane_layout.addLayout(self.vpn_connect_section)

        main_layout.addLayout(two_pane_layout)
        main_layout.addWidget(self.hline)
        main_layout.addWidget(self.status)

        self.cw.addWidget(main_widget)

    def main_window_set_admin_layout(self):
        """Set the dashboard user layout.
    
        Hides guest user layout as we will only be connecting with one user.
        The user will see the username/obfuscated password they entered.
        """
        self.username_textfield.setText(
            self.login_dict['username'])
        self.username_textfield.setReadOnly(True)
        self.password_textfield.setText(
            self.login_dict['password'])
        self.password_textfield.setReadOnly(True)

    def main_window_set_guest_layout(self):
        """Set the guest user layout.
    
        Hides dashboard user layout as we will only be connecting with one user.
        The user will see blank user/pass text fields where they can enter
        information for a guest user.
        """
        self.radio_username_textfield.clear()
        self.radio_username_textfield.setReadOnly(False)
        self.radio_password_textfield.clear()
        self.radio_password_textfield.setReadOnly(False)

    @staticmethod
    def add_all_to_layout(layout, element_list):
        """Add all of the elements to the layout."""
        for elem in element_list:
            if isinstance(elem, QWidget):
                layout.addWidget(elem)
            elif is_layout(elem):
                layout.addLayout(elem)
            elif isinstance(elem, QSpacerItem):
                layout.addItem(elem)
            else:
                print("ERROR: Trying to add illegal element to UI!")
                exit(1)
예제 #13
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'IT567 Port Scanner'
        self.left = 10
        self.top = 10
        self.width = 400
        self.height = 400
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        self.host_label = QLabel("IPs:", self)
        self.host_label.move(20, 14)

        self.host_text = QLineEdit(self)
        self.host_text.move(80, 20)
        self.host_text.resize(140, 20)

        self.port_label = QLabel("Ports:", self)
        self.port_label.move(20, 44)

        self.port_text = QLineEdit(self)
        self.port_text.move(80, 50)
        self.port_text.resize(140, 20)

        self.tcp_button = QRadioButton("TCP", self)
        self.tcp_button.move(20, 80)
        self.tcp_button.setChecked(True)

        self.udp_button = QRadioButton("UDP", self)
        self.udp_button.move(80, 80)

        # Create a button in the window
        self.button = QPushButton('Scan', self)
        self.button.move(20, 120)
        self.button.setAutoDefault(True)

        self.output = QTextEdit(self)
        self.output.setReadOnly(True)
        self.output.move(20, 160)
        self.output.resize(360, 210)

        # connect button to function on_click
        self.button.clicked.connect(self.on_click)
        self.button.pressed.connect(self.on_pressed)
        self.show()

    @pyqtSlot()
    def on_pressed(self):
        self.button.setEnabled(False)
        self.output.clear()

    @pyqtSlot()
    def on_click(self):
        if not self.host_text.text():
            self.statusBar.showMessage("No hosts specified")
            self.button.setEnabled(True)
            return

        if not self.port_text.text():
            self.statusBar.showMessage("No ports specified")
            self.button.setEnabled(True)
            return

        try:
            hosts = host_list(self.host_text.text())
            ports = port_list(self.port_text.text())
        except ValueError as e:
            self.statusBar.showMessage(str(e))
            self.button.setEnabled(True)
            return

        self.statusBar.showMessage("Scanning...")
        for host in hosts:
            udp = self.udp_button.isChecked()
            protocol = "UDP" if udp else "TCP"
            self.output.append("Host {} ({}):".format(host, protocol))
            try:
                for port in scan_host(host, ports, udp=udp):
                    self.output.append(str(port))
            except socket.error as e:
                self.output.append(str(e))

            self.output.append("")

        self.statusBar.clearMessage()
        self.output.append("Done")
        self.button.setEnabled(True)
예제 #14
0
class VideoPlayer(QWidget):
    def __init__(self, name, file_path, parent=None):
        super(VideoPlayer, self).__init__(parent)

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

        # Contains full path
        self.fileName = file_path

        self.res = 'answer not yet'

        btnSize = QSize(16, 16)
        videoWidget = QVideoWidget()

        #nameLabel = QLabel("")
        #nameLabel.setText("Name of the person")

        openButton = QPushButton("Open Video")
        openButton.setToolTip("Open Video File")
        openButton.setStatusTip("Open Video File")
        openButton.setFixedHeight(24)
        openButton.setIconSize(btnSize)
        openButton.setFont(QFont("Noto Sans", 8))
        openButton.setIcon(
            QIcon.fromTheme("document-open", QIcon("D:/_Qt/img/open.png")))
        # openButton.clicked.connect(self.abrir)

        self.result = QPushButton("Result")
        self.result.setGeometry(QtCore.QRect(500, 400, 141, 51))
        self.result.setObjectName("result")
        self.result.setEnabled(False)

        self.result.clicked.connect(self.result_window)
        """
        result window event

        """

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedHeight(24)
        self.playButton.setIconSize(btnSize)
        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.statusBar = QStatusBar()
        self.statusBar.setFont(QFont("Noto Sans", 7))
        self.statusBar.setFixedHeight(50)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        #controlLayout.addWidget(openButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.result)

        layout = QVBoxLayout()
        layout.addWidget(videoWidget)
        layout.addLayout(controlLayout)
        layout.addWidget(self.statusBar)

        self.mediaPlayer.setMedia(
            QMediaContent(QUrl.fromLocalFile(self.fileName)))
        self.playButton.setEnabled(True)
        #self.statusBar.showMessage(fileName)
        self.play()

        self.setLayout(layout)

        f = "Hello, " + name
        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.statusBar.showMessage(f)

    def enable_result(self, res):
        self.res = res
        self.result.setEnabled(True)
        print('VideoPlayer, result is enabled')
        pass

    def abrir(self):
        # fileName, _ = QFileDialog.getOpenFileName(self, "Selecciona los mediose",
        #         ".", "Video Files (*.mp4 *.flv *.ts *.mts *.avi)")

        # if fileName != '':
        self.mediaPlayer.setMedia(
            QMediaContent(QUrl.fromLocalFile(self.fileName)))
        self.playButton.setEnabled(True)
        #self.statusBar.showMessage(fileName)
        self.play()

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

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

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

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

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

    def handleError(self):
        self.playButton.setEnabled(False)
        self.statusBar.showMessage("Error: " + self.mediaPlayer.errorString())

    def result_window(self):
        print("answer: ", self.res)
예제 #15
0
class VideoPlayer(QWidget):
    def __init__(self, parent=None):
        super(VideoPlayer, self).__init__(parent)

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

        btnSize = QSize(16, 16)
        videoWidget = QVideoWidget()

        openButton = QPushButton("Open Video")
        openButton.setToolTip("Open Video File")
        openButton.setStatusTip("Open Video File")
        openButton.setFixedHeight(24)
        openButton.setIconSize(btnSize)
        openButton.setFont(QFont("Noto Sans", 8))
        openButton.setIcon(
            QIcon.fromTheme("document-open", QIcon("D:/_Qt/img/open.png")))
        openButton.clicked.connect(self.abrir)

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedHeight(24)
        self.playButton.setIconSize(btnSize)
        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.statusBar = QStatusBar()
        self.statusBar.setFont(QFont("Noto Sans", 7))
        self.statusBar.setFixedHeight(14)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(openButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)

        layout = QVBoxLayout()
        layout.addWidget(videoWidget)
        layout.addLayout(controlLayout)
        layout.addWidget(self.statusBar)

        self.setLayout(layout)

        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.statusBar.showMessage("Ready")

    def abrir(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, "Selecciona los mediose", ".",
            "Video Files (*.mp4 *.flv *.ts *.mts *.avi)")

        if fileName != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(fileName)))
            self.playButton.setEnabled(True)
            self.statusBar.showMessage(fileName)
            self.play()

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

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

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

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

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

    def handleError(self):
        self.playButton.setEnabled(False)
        self.statusBar.showMessage("Error: " + self.mediaPlayer.errorString())
예제 #16
0
class Config(QWidget):
    def __init__(self):
        super(Config, self).__init__()
        config_group = QtWidgets.QGroupBox(u"参数配置")
        lineconfig_group = QtWidgets.QGroupBox(u"线条风格配置")
        axisconfig_group = QtWidgets.QGroupBox(u"坐标轴风格配置")
        lineshow_group = QtWidgets.QGroupBox(u"线条风格预览")
        result_group = QtWidgets.QGroupBox(u"结果展示")

        # 当前绘图结果
        self.fig = None

        # 当前绘图总数据保存
        # 坐标轴信息
        self.min_x = 0.
        self.max_x = 1.
        self.min_y = 0.
        self.max_y = 1.
        self.x_text = u'The number of retrived samples'
        self.y_text = u'precision @ 256 bins'
        self.x_tick_list = [0., 0.5, 1.]
        self.x_label_list = ['0', '0.5', '1.0']
        self.y_tick_list = [0., 0.5, 1.]
        self.y_label_list = ['0', '0.5', '1.0']
        # 已有曲线信息
        self.formula_list = []
        self.ls_list = []
        self.lc_list = []
        self.lt_list = []
        self.mark_list = []
        self.mark_density_list = []

        # 当前绘图曲线元数据保存
        self.ls = '-'
        self.mark = 'o'
        self.formula = 'y=x**2'
        self.lc = '#00ff00'
        self.lt = 'Our Method'
        self.md = 5

        # 状态栏
        self.statusBar = QStatusBar()
        self.statusBar.setFont(QFont(u'华文楷体', 10))
        self.statusBar.showMessage(u"准备就绪")

        # 编辑公式
        self.math = QLineEdit()
        self.math.setPlaceholderText(u'y=x**2')
        self.math.setClearButtonEnabled(True)

        # 线条风格
        self.linestyle = QComboBox()
        self.line_list = ["-", "--", "-.", ":"]
        for each in self.line_list:
            self.linestyle.addItem(each)

        # 标记风格
        self.markerstyle = QComboBox()
        self.marker_list = [
            ".", ",", "o", "v", "^", "<", ">", "1", "2", "3", "4"
            "s", "p", "*", "h", "H", "+", "x", "D", "d", "|", "_"
        ]
        for each in self.marker_list:
            self.markerstyle.addItem(each)

        # 设置线条标签名称
        self.label = QLineEdit()
        self.label.setPlaceholderText(u'Our Method')
        self.label.setClearButtonEnabled(True)

        # 设置线条颜色
        self.lineColor = QPushButton('更改线条颜色')
        self.lineColor.setToolTip("点击此按钮将更改线条颜色!")
        self.lineColor.setStatusTip("点击此按钮将更改线条颜色!")
        self.lineColor.clicked.connect(self.changeColor)
        self.lineColor.resize(self.lineColor.sizeHint())
        self.lineColor.installEventFilter(self)

        # 设置标记密集程度
        self.markDensity = QSlider(Qt.Horizontal)
        self.markDensity.setMinimum(1)
        self.markDensity.setMaximum(50)
        self.markDensity.setValue(5)
        self.markDensity.installEventFilter(self)

        # 横坐标轴范围
        self.x_scale = QLineEdit()
        self.x_scale.setPlaceholderText(u'0,1')
        self.x_scale.setClearButtonEnabled(True)

        # 纵坐标轴范围
        self.y_scale = QLineEdit()
        self.y_scale.setPlaceholderText(u'0,1')
        self.y_scale.setClearButtonEnabled(True)

        # 横坐标轴标签名称
        self.x_label = QLineEdit()
        self.x_label.setPlaceholderText(u'The number of retrived samples')
        self.x_label.setClearButtonEnabled(True)

        # 纵坐标轴标签名称
        self.y_label = QLineEdit()
        self.y_label.setPlaceholderText(u'precision @ 256 bins')
        self.y_label.setClearButtonEnabled(True)

        # 横坐标刻度数量
        self.x_ticks = QLineEdit()
        self.x_ticks.setPlaceholderText(u'100')
        self.x_ticks.setClearButtonEnabled(True)

        # 纵坐标刻度数量
        self.y_ticks = QLineEdit()
        self.y_ticks.setPlaceholderText(u'100')
        self.y_ticks.setClearButtonEnabled(True)

        # 线条风格预览按钮
        self.lineview = QPushButton(u'预览')
        self.lineview.setToolTip("线条预览!")
        self.lineview.setStatusTip("线条预览!")
        self.lineview.clicked.connect(self.showLine)
        self.lineview.installEventFilter(self)

        # 布局设置
        main_layout = QVBoxLayout()

        # 参数外层布局
        config_outer_layout = QVBoxLayout()

        # 参数内层布局配置
        config_inner_layout = QHBoxLayout()
        config_inner_layout.addWidget(lineconfig_group)
        config_inner_layout.setStretchFactor(lineconfig_group, 1)
        config_inner_layout.addWidget(axisconfig_group)
        config_inner_layout.setStretchFactor(axisconfig_group, 1)
        config_inner_layout.addWidget(lineshow_group)
        config_inner_layout.setStretchFactor(lineshow_group, 1)

        # 线条布局
        line_layout = QFormLayout()
        line_layout.addRow(u'编辑公式', self.math)
        line_layout.addRow(u'线条风格', self.linestyle)
        line_layout.addRow(u'标记风格', self.markerstyle)
        line_layout.addRow(u'标签名称', self.label)
        line_layout.addRow(u'颜色配置', self.lineColor)
        line_layout.addRow(u'标记密度', self.markDensity)
        lineconfig_group.setLayout(line_layout)

        # 坐标轴布局
        tick_layout = QFormLayout()
        tick_layout.addRow(u'横坐标轴范围', self.x_scale)
        tick_layout.addRow(u'纵坐标轴范围', self.y_scale)
        tick_layout.addRow(u'横坐标轴标签名称', self.x_label)
        tick_layout.addRow(u'纵坐标轴标签名称', self.y_label)
        tick_layout.addRow(u'横坐标刻度数量', self.x_ticks)
        tick_layout.addRow(u'纵坐标刻度数量', self.y_ticks)
        axisconfig_group.setLayout(tick_layout)

        # 预览布局
        view = QVBoxLayout()

        # 预览显示
        self.view_face = QMainWindow()
        view.addWidget(self.view_face)
        # 预览按钮
        view.addWidget(self.lineview)
        lineshow_group.setLayout(view)

        # 中层按钮定义
        # 按钮一:显示最终结果
        # 按钮二:添加新的线条
        # 按钮三:删除最近一条线条
        # 按钮四:保存图像
        self.showresult = QPushButton(u'刷新视图')
        self.showresult.setToolTip(u'刷新视图!')
        self.showresult.clicked.connect(self.resultShow)
        self.showresult.installEventFilter(self)

        self.addline = QPushButton(u'新增线条')
        self.addline.setToolTip(u'新增一条曲线!')
        self.addline.clicked.connect(self.addLine)
        self.addline.installEventFilter(self)

        self.removeline = QPushButton(u'删除线条')
        self.removeline.setToolTip(u'删除最近一条曲线!')
        self.removeline.clicked.connect(self.removeLine)
        self.removeline.installEventFilter(self)

        self.savefig = QPushButton(u'保存结果')
        self.savefig.setToolTip(u'将当前结果保存为高清图片!')
        self.savefig.clicked.connect(self.saveFig)
        self.savefig.installEventFilter(self)

        # 中层按钮布局
        center_layout = QHBoxLayout()
        center_layout.addWidget(self.showresult)
        center_layout.addWidget(self.addline)
        center_layout.addWidget(self.removeline)
        center_layout.addWidget(self.savefig)

        # 第三层按钮定义
        file_layout = QHBoxLayout()
        left_layout = QHBoxLayout()
        leftl_layout = QFormLayout()
        self.x_file_path = QLineEdit()
        self.x_file_path.setFixedHeight(20)
        leftl_layout.addRow(u"X轴:", self.x_file_path)
        leftr_layout = QVBoxLayout()
        x_file_option = QPushButton("选择")
        x_file_option.setFixedWidth(35)
        x_file_option.setFixedHeight(20)
        x_file_option.clicked.connect(self.xFile)
        leftr_layout.addWidget(x_file_option)
        left_layout.addLayout(leftl_layout)
        left_layout.addLayout(leftr_layout)

        right_layout = QHBoxLayout()
        rightl_layout = QFormLayout()
        self.y_file_path = QLineEdit()
        self.y_file_path.setFixedHeight(20)
        rightl_layout.addRow(u"Y轴:", self.y_file_path)
        rightr_layout = QVBoxLayout()
        y_file_option = QPushButton("选择")
        y_file_option.setFixedWidth(35)
        y_file_option.setFixedHeight(20)
        y_file_option.clicked.connect(self.yFile)
        rightr_layout.addWidget(y_file_option)
        right_layout.addLayout(rightl_layout)
        right_layout.addLayout(rightr_layout)

        self.selection = QCheckBox(u"自适应")

        okbt = QPushButton(u"确定")
        okbt.clicked.connect(self.xyPlot)

        file_layout.addLayout(left_layout)
        file_layout.addLayout(right_layout)
        file_layout.addWidget(self.selection)
        file_layout.addWidget(okbt)

        # 设置布局中控件的间距
        left_layout.setSpacing(3)
        right_layout.setSpacing(3)
        file_layout.setSpacing(20)

        # 下层状态栏
        bottom_layout = QVBoxLayout()
        bottom_layout.addWidget(self.statusBar)

        config_outer_layout.addItem(config_inner_layout)
        config_outer_layout.addItem(center_layout)
        config_outer_layout.addItem(file_layout)
        config_outer_layout.addItem(bottom_layout)

        config_group.setLayout(config_outer_layout)

        # 结果展示栏,设置为mainWindow
        result = QVBoxLayout()
        self.result = QMainWindow()
        result.addWidget(self.result)
        result_group.setLayout(result)

        main_layout.addWidget(config_group)
        main_layout.setStretchFactor(config_group, 1)
        main_layout.addWidget(result_group)
        main_layout.setStretchFactor(result_group, 2)
        self.setLayout(main_layout)

        cp = QDesktopWidget().availableGeometry().center()
        window_width = int(cp.x() * 2 * 0.7)
        window_height = int(cp.y() * 2 * 0.7)
        self.setGeometry(cp.x() - window_width // 2,
                         cp.y() - window_height // 2, window_width,
                         window_height)

    def changeColor(self):
        col = QColorDialog.getColor()
        if col.isValid():
            self.lc = col.name()
            self.showLine()

    def showLine(self):
        # self.view_face.setFixedWidth(230)
        # self.view_face.setSizePolicy(self.view_face.sizeHint())
        # 获取参数
        try:
            x_scale_text = self.x_scale.text()
            if x_scale_text == "":
                x_scale_text = self.x_scale.placeholderText()
            self.min_x, self.max_x = [
                float(k.strip()) for k in x_scale_text.strip().split(',')
            ]
        except Exception as ex:
            pass

        self.formula = self.math.text()
        if self.formula == "":
            self.formula = self.math.placeholderText()
        self.ls = self.linestyle.currentText()
        self.mark = self.markerstyle.currentText()
        self.lt = self.label.text()
        if self.lt == "":
            self.lt = self.label.placeholderText()
        self.md = self.markDensity.value()

        x0 = np.linspace(self.min_x, self.max_x, 100)
        try:
            formula_str = self.formula.split('=')[1]
            y0 = [eval(formula_str) for x in x0]
        except Exception as ex:
            return
        plt.cla()
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        ax.set_xlim(self.min_x, self.max_x)
        ax.plot(x0,
                y0,
                color=self.lc,
                ls=self.ls,
                marker=self.mark,
                label=self.lt,
                markevery=self.md)
        plt.subplots_adjust(left=0.17,
                            bottom=0.17,
                            right=0.9,
                            top=0.9,
                            hspace=0.1,
                            wspace=0.3)
        ax.legend(loc='best')
        self.fig = fig
        canvas = FigureCanvas(fig)
        self.view_face.setCentralWidget(canvas)

    def resultShow(self):
        try:
            x_scale_text = self.x_scale.text()
            if x_scale_text == "":
                x_scale_text = self.x_scale.placeholderText()
            self.min_x, self.max_x = [
                float(k.strip()) for k in x_scale_text.strip().split(',')
            ]
        except Exception as ex:
            pass

        try:
            y_scale_text = self.y_scale.text()
            if y_scale_text == "":
                y_scale_text = self.y_scale.placeholderText()
            self.min_y, self.max_y = [
                float(k.strip()) for k in y_scale_text.strip().split(',')
            ]
        except Exception as ex:
            pass

        self.x_text = self.x_label.text()
        if self.x_text == "":
            self.x_text = self.x_label.placeholderText()
        self.y_text = self.y_label.text()
        if self.y_text == "":
            self.y_text = self.y_label.placeholderText()

        try:
            x_tick_str = self.x_ticks.text()
            if x_tick_str == "":
                x_tick_str = self.x_ticks.placeholderText()
            self.x_tick_list = np.linspace(self.min_x, self.max_x,
                                           int(x_tick_str.strip()))
            self.x_label_list = self.x_tick_list
        except Exception as ex:
            pass

        try:
            y_tick_str = self.y_ticks.text()
            if y_tick_str == "":
                y_tick_str = self.y_ticks.placeholderText()
            self.y_tick_list = np.linspace(self.min_y, self.max_y,
                                           int(y_tick_str.strip()))
            self.y_label_list = self.y_tick_list
        except Exception as ex:
            pass

        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        for index in range(len(self.formula_list)):
            x0 = np.linspace(self.min_x, self.max_x, 100)
            y0 = [eval(self.formula_list[index].split('=')[1]) for x in x0]
            ax.plot(x0,
                    y0,
                    color=self.lc_list[index],
                    ls=self.ls_list[index],
                    marker=self.mark_list[index],
                    markevery=self.mark_density_list[index],
                    label=self.lt_list[index])
        ax.legend(loc='best')
        ax.set_xticks(self.x_tick_list)
        ax.set_xticklabels(self.x_label_list)
        ax.set_yticks(self.y_tick_list)
        ax.set_yticklabels(self.y_label_list)
        ax.set_xlabel(self.x_text)
        ax.set_ylabel(self.y_text)
        ax.set_xlim(self.min_x, self.max_x)
        ax.set_ylim(self.min_y, self.max_y)
        self.fig = fig
        canvas = FigureCanvas(fig)
        self.result.setCentralWidget(canvas)

    def addLine(self):
        try:
            x = 1
            math_txt = self.math.text()
            if math_txt == "":
                math_txt = self.math.placeholderText()
            temp = eval(math_txt.split('=')[1])
            self.formula_list.append(math_txt)
            self.ls_list.append(self.linestyle.currentText())
            self.mark_list.append(self.markerstyle.currentText())
            label_txt = self.label.text()
            if label_txt == "":
                label_txt = self.label.placeholderText()
            self.lt_list.append(label_txt)
            self.lc_list.append(self.lc)
            self.mark_density_list.append(self.md)
            self.resultShow()
        except Exception as ex:
            pass

    def removeLine(self):
        try:
            assert (len(self.formula_list) != 0)
            self.formula_list.pop()
            self.ls_list.pop()
            self.mark_list.pop()
            self.lt_list.pop()
            self.lc_list.pop()
            self.mark_density_list.pop()
            self.resultShow()
        except Exception as ex:
            pass

    def xFile(self):
        filename, filetype = QFileDialog.getOpenFileName(self, "选取文件", "./",\
         "Text Files (*.txt);;Python Files (*.npy)")
        if filename != "":
            self.x_file_path.setText(filename)

    def yFile(self):
        filename, filetype = QFileDialog.getOpenFileName(self, "选取文件", "./",\
         "Text Files (*.txt);;Python Files (*.npy)")
        if filename != "":
            self.y_file_path.setText(filename)

    def xyPlot(self):
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        xfile = self.x_file_path.text()
        yfile = self.y_file_path.text()
        x_arr = None
        y_arr = None
        if xfile and yfile:
            if not os.path.exists(xfile) or not os.path.exists(yfile):
                return
            xtype = os.path.splitext(xfile)[1]
            ytype = os.path.splitext(yfile)[1]
            if xtype != ytype:
                return
            if xtype.lower() == '.txt':
                try:
                    with open(xfile) as fp:
                        xdata = [[each.strip() for each in line.split(',')]
                                 for line in fp.readlines()]
                    with open(yfile) as fp:
                        ydata = [[each.strip() for each in line.split(',')]
                                 for line in fp.readlines()]
                    x_arr = np.array(xdata, dtype=np.float)
                    y_arr = np.array(ydata, dtype=np.float)
                    if x_arr.shape != y_arr.shape:
                        return
                except Exception as ex:
                    pass
            elif xtype.lower() == '.npy':
                try:
                    x_arr = np.load(xfile)
                    y_arr = np.load(yfile)
                    if x_arr.shape != y_arr.shape:
                        return
                except Exception as ex:
                    pass

            if self.selection.checkState():
                rd = np.random.RandomState(1234)
                color_list = rd.rand(x_arr.shape[0], 3)
                for index in range(x_arr.shape[0]):
                    ax.plot(x_arr[index], y_arr[index], color=color_list[index],\
                     ls=rd.choice(self.line_list), marker=rd.choice(self.marker_list))
                self.fig = fig
                canvas = FigureCanvas(fig)
                self.result.setCentralWidget(canvas)
        else:
            pass

    def saveFig(self):
        dialog = QFileDialog()
        filename, filetype = dialog.getSaveFileName(self, "图像保存", "./result.png"\
                        ,"All Files (*);;JPEG Files (*.jpg);;PNG Files (*.png);;SVG Files (*.svg)")
        self.fig.set_size_inches(8, 6)
        if filename != "" and self.fig:
            plt.savefig(filename, dpi=80)
            self.resultShow()

    def eventFilter(self, obj, event):
        if event.type() == QEvent.HoverEnter:
            if obj == self.lineColor:
                self.statusBar.showMessage(u"点击此按钮将更改线条颜色!")
                return False
            elif obj == self.markDensity:
                value = self.markDensity.value()
                self.statusBar.showMessage(str(value))
                return False
            elif obj == self.lineview:
                self.statusBar.showMessage(u"线条预览!")
                return False
            elif obj == self.showresult:
                self.statusBar.showMessage(u"刷新当前视图,重新显示图片!")
                return False
            elif obj == self.addline:
                self.statusBar.showMessage(u'新增一条曲线!')
                return False
            elif obj == self.removeline:
                self.statusBar.showMessage(u'删去最近的一条曲线!')
                return False
            elif obj == self.savefig:
                self.statusBar.showMessage(u'将当前结果保存为高清图片!')
                return False
        elif event.type() == 2 or event.type() == 129:
            if obj == self.markDensity:
                value = self.markDensity.value()
                self.statusBar.showMessage(str(value))
                self.showLine()
                return False
            else:
                return False
        else:
            return False
예제 #17
0
class MainWindow(QMainWindow):
    # pylint: disable=too-many-instance-attributes
    # pylint: disable=too-many-statements
    def __init__(self, app, mapLayers, mapLayersCategory):
        QMainWindow.__init__(self)
        self.app = app

        self.mapLayers = mapLayers
        self.mapLayersCategory = mapLayersCategory

        self.resize(shared.windowWidth, shared.windowHeight)
        self.setWindowTitle(shared.progName + ": " + shared.progVer)

        # Set up the map canvas
        self.canvas = QgsMapCanvas()
        self.setCentralWidget(self.canvas)

        self.canvas.setCanvasColor(Qt.white)
        self.canvas.enableAntiAliasing(True)

        self.canvas.setCachingEnabled(True)
        #self.canvas.setMapUpdateInterval(1000)
        self.canvas.setParallelRenderingEnabled(True)
        self.canvas.enableMapTileRendering(True)

        self.canvas.setLayers(self.mapLayers)
        self.canvas.setExtent(shared.extentRect)
        self.canvas.setMagnificationFactor(shared.windowMagnification)

        #mapSet = self.canvas.mapSettings()
        #print(mapSet.flags())

        # Create some actions
        #self.actionExit = QAction(QIcon('exit.png'), '&Exit', self)
        self.actionExit = QAction("&Exit", self)
        self.actionExit.setShortcut("Ctrl+Q")
        self.actionExit.setStatusTip("Exit " + shared.progName)

        self.actionZoomIn = QAction("Zoom in", self)
        self.actionZoomIn.setCheckable(True)
        #self.actionExit.setShortcut("Ctrl++")
        self.actionZoomIn.setStatusTip("Show more detail")

        self.actionZoomOut = QAction("Zoom out", self)
        self.actionZoomOut.setCheckable(True)
        #self.actionExit.setShortcut("Ctrl+-")
        self.actionZoomOut.setStatusTip("Show less detail")

        self.actionPan = QAction("Pan", self)
        self.actionPan.setCheckable(True)
        self.actionPan.setStatusTip("Move the map laterally")

        self.actionChangeBackground = QAction("Change background", self)
        self.actionChangeBackground.setStatusTip(
            "Change the raster background")
        if not shared.haveRasterBackground:
            self.actionChangeBackground.setEnabled(False)

        self.actionCoords = QAction("Show coordinates", self)
        self.actionCoords.setCheckable(True)
        self.actionCoords.setStatusTip("Click to show coordinates")

        self.actionRun = QAction("Simulate", self)
        self.actionRun.setStatusTip("Route flow")

        # Connect the actions
        self.actionExit.triggered.connect(app.quit)
        self.actionZoomIn.triggered.connect(self.zoomIn)
        self.actionZoomOut.triggered.connect(self.zoomOut)
        self.actionPan.triggered.connect(self.pan)
        self.actionChangeBackground.triggered.connect(self.changeBackground)
        self.actionCoords.triggered.connect(self.showCoords)
        self.actionRun.triggered.connect(self.doRun)

        # Create a menu bar and add menus
        self.menubar = self.menuBar()

        self.fileMenu = self.menubar.addMenu("&File")
        self.fileMenu.addAction(self.actionExit)

        self.editMenu = self.menubar.addMenu("&Edit")
        #self.editMenu.addAction(self.actionExit)

        self.viewMenu = self.menubar.addMenu("&View")
        self.viewMenu.addAction(self.actionZoomIn)
        self.viewMenu.addAction(self.actionZoomOut)
        self.viewMenu.addAction(self.actionPan)
        self.viewMenu.addAction(self.actionChangeBackground)
        self.viewMenu.addAction(self.actionCoords)

        self.runMenu = self.menubar.addMenu("&Run")
        self.runMenu.addAction(self.actionRun)

        # Create a tool bar and add some actions
        self.toolbar = self.addToolBar("Default")
        self.toolbar.setFloatable(True)

        self.toolbar.addAction(self.actionRun)
        self.toolbar.addAction(self.actionZoomIn)
        self.toolbar.addAction(self.actionZoomOut)
        self.toolbar.addAction(self.actionPan)
        self.toolbar.addAction(self.actionCoords)

        # Create some map tools
        self.toolPan = QgsMapToolPan(self.canvas)
        self.toolPan.setAction(self.actionPan)
        self.toolZoomIn = QgsMapToolZoom(self.canvas, False)  # False = in
        self.toolZoomIn.setAction(self.actionZoomIn)
        self.toolZoomOut = QgsMapToolZoom(self.canvas, True)  # True = out
        self.toolZoomOut.setAction(self.actionZoomOut)
        self.toolCoords = PointTool(self.canvas)
        self.toolCoords.setAction(self.actionCoords)

        # Put into panning mode
        self.pan()

        # Add a status bar
        self.statusBar = QStatusBar(self.canvas)
        self.setStatusBar(self.statusBar)

        # And put a progress indicator on the status bar
        self.statusBar.progress = QProgressBar(self)
        self.statusBar.progress.setRange(0, 100)
        self.statusBar.progress.setMaximumWidth(500)
        self.statusBar.progress.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.statusBar.addPermanentWidget(self.statusBar.progress)

        self.myThread = None

        return
#======================================================================================================================

#======================================================================================================================

    def doRun(self):
        # Delete all output features (in case we have some from a previous run)
        listIDs = [
            feat.id() for feat in shared.outFlowMarkerPointLayer.getFeatures()
        ]
        prov = shared.outFlowMarkerPointLayer.dataProvider()
        prov.deleteFeatures([featID for featID in listIDs])
        shared.outFlowMarkerPointLayer.updateExtents()
        shared.outFlowMarkerPointLayer.triggerRepaint()

        listIDs = [feat.id() for feat in shared.outFlowLineLayer.getFeatures()]
        prov = shared.outFlowLineLayer.dataProvider()
        prov.deleteFeatures([featID for featID in listIDs])
        shared.outFlowLineLayer.updateExtents()
        shared.outFlowLineLayer.triggerRepaint()

        self.canvas.repaint()
        self.statusBar.progress.setValue(0)
        self.actionRun.setEnabled(False)

        # All is now ready, so run the simulation as a separate thread
        self.myThread = SimulationThread(self.app, self)

        self.myThread.refresh.connect(self.doRefresh)
        self.myThread.runDone.connect(self.runDone)

        self.canvas.freeze(True)
        #self.canvas.refreshAllLayers()
        #self.app.processEvents()

        self.myThread.start()

        print("\nThread started")

        return
#======================================================================================================================

#======================================================================================================================

    def doRefresh(self):
        self.canvas.freeze(False)

        if not self.canvas.isDrawing():
            shared.outFlowMarkerPointLayer.triggerRepaint()
            shared.outFlowLineLayer.triggerRepaint()
            self.canvas.repaint()

        self.canvas.freeze(True)

        if not isinstance(shared.flowStartPoints, int):
            doneSoFar = (float(shared.thisStartPoint) /
                         float(len(shared.flowStartPoints) + 1)) * 100.0
            #shared.fpOut.write(doneSoFar)
            self.statusBar.progress.setValue(doneSoFar)

        return
#======================================================================================================================

#======================================================================================================================

    def zoomIn(self):
        self.canvas.freeze(False)
        self.canvas.setMapTool(self.toolZoomIn)
        return
#======================================================================================================================

#======================================================================================================================

    def zoomOut(self):
        self.canvas.freeze(False)
        self.canvas.setMapTool(self.toolZoomOut)
        return
#======================================================================================================================

#======================================================================================================================

    def pan(self):
        self.canvas.freeze(False)
        self.canvas.setMapTool(self.toolPan)
        return
#======================================================================================================================

#======================================================================================================================

    def showCoords(self):
        self.canvas.setMapTool(self.toolCoords)

        return
#======================================================================================================================

#======================================================================================================================

    def close(self):
        if self.myThread:
            self.myThread.quit()
            self.myThread = None

        return
#======================================================================================================================

#======================================================================================================================

    def runDone(self):
        self.canvas.freeze(False)
        shared.outFlowMarkerPointLayer.triggerRepaint()
        shared.outFlowLineLayer.triggerRepaint()
        self.canvas.repaint()

        print("Thread done")

        self.myThread.quit()
        #self.myThread = None

        self.statusBar.progress.setValue(100)

        #QMessageBox.information(self, "End of run", shared.progName + ": flow routed")
        self.statusBar.showMessage("End of run: flow routed",
                                   shared.defaultMessageDisplayTime)

        # To prevent subsequent re-runs
        #      self.actionRun.setEnabled(False)

        return
#======================================================================================================================

#======================================================================================================================

    def changeBackground(self):
        for n in range(len(shared.rasterInputLayersCategory)):
            if shared.rasterInputLayersCategory[n] == INPUT_RASTER_BACKGROUND:
                oldOpacity = shared.rasterInputLayers[n].renderer().opacity()
                if oldOpacity == 0:
                    newOpacity = shared.rasterFileOpacity[n]
                else:
                    newOpacity = 0

                shared.rasterInputLayers[n].renderer().setOpacity(newOpacity)

                #layerID = shared.rasterInputLayers[n].id()
                #layerTreeNode = QgsProject.instance().layerTreeRoot().findLayer(layerID)

                #print(layerTreeNode.dump())

                #layerTreeNode.setItemVisibilityChecked(not layerTreeNode.itemVisibilityChecked())

                #print(layerTreeNode.dump())
                #print("*****************")

        #for n in range(len(self.mapLayers)):
        #if self.mapLayersCategory[n] == INPUT_RASTER_BACKGROUND:
        #self.mapLayers[n].setVisible(not self.mapLayers[n].isVisible())

        #self.canvas.setLayers(self.mapLayers)
        self.doRefresh()

        return
예제 #18
0
 def _updateStatusBar(self):
     status = QStatusBar()
     status.showMessage('Josias')
     self.setStatusBar(status)
예제 #19
0
파일: test.py 프로젝트: rcmhunt71/InstaGrab
 def _createStatusBar(self):
     status = QStatusBar()
     status.showMessage("I'm the status bar")
     self.setStatusBar(status)
예제 #20
0
class MyWidget(QWidget):
    
    def __init__(self, fig, ax, df, title, parent=None):
        super(MyWidget, self).__init__(parent)
        #super().__init__()
        self.legend = []
        self.ax = ax
        self.df = df
        
        # Graph
        ctrl_sys = ControlSys(fig, ax)
        self.cg = CGraph(fig, ax, ctrl_sys, df, title)

        self.setWindowTitle(title)
        self.setGeometry(5,30,400,680)
        
        # Vbox
        self.topLayout = QVBoxLayout(self)

        # grid
        # message -> QLayout: Attempting to add QLayout "" to MyWidget "", which already has a layout
        self.grid=QGridLayout()

        # Line
        #self.grid.addWidget(self.Line,0,0)

        #combo box
        self.combo_L = QComboBox(self)
        self.combo_R = QComboBox(self)
        self.combo_I = QComboBox(self)
        for hd in df.columns.values:
            header = hd #str(unicode(hd)) #unicode(hd, 'cp949') # Korean character
            self.combo_L.addItem(header)
            self.combo_R.addItem(header)
            self.combo_I.addItem(header)
        
        # Check Box
        self.grid.addWidget(self.combo_L,0,0)
        self.cb_L = QCheckBox("L cursor", self)
        self.grid.addWidget(self.cb_L, 0, 1)

        self.grid.addWidget(self.combo_R,1,0)
        self.cb_R = QCheckBox("R cursor", self)
        self.grid.addWidget(self.cb_R, 1, 1)
      
        self.grid.addWidget(self.combo_I,2,0)
        self.cb_I = QCheckBox("Select X-axis", self)
        self.grid.addWidget(self.cb_I, 2, 1)

        # Push Button
        self.all_Visible=QPushButton('Show All', self)
        self.all_Visible.clicked.connect(self.AllVisible)
        self.all_Hide=QPushButton('Hide All', self)
        self.all_Hide.clicked.connect(self.AllHide)
        self.grid.addWidget(self.all_Visible,4,0)
        self.grid.addWidget(self.all_Hide,5,0)

        # Check Box
        self.cb_TS = QCheckBox("X-axis is TimeStamp", self)
        self.grid.addWidget(self.cb_TS, 4, 1)
        self.cb_scale = QCheckBox("Auto Fit Height", self)
        self.cb_scale.setCheckState(2)
        self.grid.addWidget(self.cb_scale, 5, 1)
        self.b_autoscale = True

        self.topLayout.addLayout(self.grid)
       
        # Scrollable Check Box
        self.scrollArea = QScrollArea(self)
        self.scrollArea.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QWidget(self.scrollArea)
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(5,30,400,680))
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.topLayout.addWidget(self.scrollArea)

        self.gridScroll = QGridLayout(self.scrollAreaWidgetContents)
        self.cb = []
        i = 0   # layout index
        for header in [column for column in df]:
            c = QCheckBox(header, self)                            
            c.stateChanged.connect(self.ToggleVisibility)
            col_number = 2 # how many columns 
            j = (i-2) // col_number + 2
            k = (i-2) % col_number
            self.gridScroll.addWidget(c, j, k)
            i += 1
            self.cb.append(c)            
        
        # Status bar
        self.StatusBar = QStatusBar(self)
        self.topLayout.addWidget(self.StatusBar)
        self.StatusBar.showMessage("Happy Day  ")

        self.setLayout(self.topLayout)
        #self.Line,QtCore.SLOT('setText(QString)'))
        
        self.combo_L.activated.connect(lambda: self.select_cursor_data(1))
        self.combo_R.activated.connect(lambda: self.select_cursor_data(2))
        self.combo_I.activated.connect(self.select_index)
        self.cb_L.stateChanged.connect(self.cursor_on)
        self.cb_R.stateChanged.connect(self.cursor_on)
        self.cb_I.stateChanged.connect(self.index_on)
        self.cb_TS.stateChanged.connect(self.timestamp_on)
        self.cb_scale.stateChanged.connect(self.ToggelAutoScale)
    
    def index_on(self):
        if self.cb_I.isChecked():
            idx = self.combo_I.currentText()
            self.cg.select_index(idx)
        else:
            self.cg.select_index(None)
            
    def select_index(self):
        self.cb_I.setCheckState(2)
        idx = self.combo_I.currentText()
        self.cg.select_index(idx)

    def timestamp_on(self):
        if self.cb_TS.isChecked():
            idx = self.combo_I.currentText()
            self.cg.set_timestamp(idx)
        else:
            self.cg.set_timestamp(None)
                        
    def closeEvent(self, event):
        print ("Closing GUI")
        sys.exit()

    def AllVisible(self):
        i = 0
        for each in self.cb:
            each.setCheckState(2)
            self.cg.set_visible(i, True)
            i += 1
        self.UpdateDraw()
        
    def AllHide(self):
        i = 0
        for each in self.cb:
            each.setCheckState(0)
            self.cg.set_visible(i, False)
            i += 1
        self.UpdateDraw()
        
    def ToggleVisibility(self):
        i = 0
        for each in self.cb:
            if each.isChecked():	#checked
                self.cg.set_visible(i, True)
            else:
                self.cg.set_visible(i, False)            
            i += 1
        self.UpdateDraw()
        
    def UpdateDraw(self):
        if self.b_autoscale:
            self.cg.autoscale_y()
        self.cg.update_draw()             
    
    def GetAddr(self):
        return self.addr

    def ToggelAutoScale(self):
        self.b_autoscale ^= True
        if self.b_autoscale:
            self.cg.autoscale_y()
            self.cg.update_draw()             

    def cursor_on(self):
        if self.cb_L.isChecked():
            self.cg.cursor_on(1, True)
        else:
            self.cg.cursor_on(1, False)
        if self.cb_R.isChecked():
            self.cg.cursor_on(2, True)
        else:
            self.cg.cursor_on(2, False)
    
    def select_cursor_data(self, btn):
        if btn == 1: #Left
            header = self.combo_L.currentText()
            self.cb_L.setCheckState(2)
        else:
            header = self.combo_R.currentText()
            self.cb_R.setCheckState(2)
        self.cg.select_cursor_data(btn, header)
        # check box check
        clist = list(self.df.columns.values) # make headers to list
        i = clist.index(header) #find index of the header
        self.cb[i].setCheckState(2) #check checkbox
        self.cg.set_visible(i, True) #make visiabel
예제 #21
0
파일: gui.py 프로젝트: FZUG/repo-checker
class MainWindow(QMainWindow):
    tableContents = []
    tableColumnCount = 8
    tableRowCount = 10
    workerCount = config['worker_num']  # 线程数
    workers = []  # 保存线程对象
    q = Queue()
    wtime = [0, 0]
    bgColor = QColor(180, 200, 230, 40)
    progressVal = 0
    taskVal = 0

    def __init__(self):
        super(MainWindow, self).__init__()
        self.description = self.tr("""<b>Checker</b><br /><br />
            Version: %s<br />
            %s<br /><br />
            Project: <a href=\"%s\">1dot75cm/repo-checker</a><br />
            License: %s<br />
            Author: <a href=\"mailto:%s\">%s</a>""") % (__version__,
            __descript__, __url__, __license__, __email__, __author__)
        self.tableHeaders = [self.tr("Name"), self.tr("URL"), self.tr("Branch"),
                             self.tr("RPM date [commit]"), self.tr("Release date [commit]"),
                             self.tr("Latest date [commit]"), self.tr("Status"), self.tr("Comment")]
        self.setupUi(self)

    def setupUi(self, MainWindow):
        """初始化主窗口"""
        MainWindow.setObjectName("MainWindow")
        MainWindow.setMinimumSize(QSize(910, 450))
        MainWindow.setWindowTitle(self.tr("Checker"))
        MainWindow.setAnimated(True)

        self.centralwidget = QWidget(MainWindow)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.centralwidget.setSizePolicy(sizePolicy)

        self.verticalLayout = QVBoxLayout(self.centralwidget)
        self.verticalLayout.setContentsMargins(5, 5, 5, 5)

        self.tableWidget = QTableWidget(self.centralwidget)
        self.setupTable()
        self.verticalLayout.addWidget(self.tableWidget)

        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setContentsMargins(5, 5, 5, 5)

        self.addButton = QPushButton(self.centralwidget)
        self.addButton.setFixedSize(QSize(25, 25))
        self.addButton.setText("+")
        self.horizontalLayout.addWidget(self.addButton)

        self.delButton = QPushButton(self.centralwidget)
        self.delButton.setFixedSize(QSize(25, 25))
        self.delButton.setText("-")
        self.horizontalLayout.addWidget(self.delButton)

        self.upButton = QPushButton(self.centralwidget)
        self.upButton.setFixedSize(QSize(25, 25))
        self.upButton.setText("↑")
        self.upButton.setObjectName("up")
        self.horizontalLayout.addWidget(self.upButton)

        self.downButton = QPushButton(self.centralwidget)
        self.downButton.setFixedSize(QSize(25, 25))
        self.downButton.setText("↓")
        self.horizontalLayout.addWidget(self.downButton)

        spacerItem = QSpacerItem(40, 20, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)

        self.progressBar = QProgressBar(self.centralwidget)
        self.progressBar.hide()
        self.horizontalLayout.addWidget(self.progressBar)

        self.label = QLabel(self.centralwidget)
        self.horizontalLayout.addWidget(self.label)

        spacerItem = QSpacerItem(40, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)

        self.checkButton = QPushButton(self.centralwidget)
        self.checkButton.setText(self.tr("Check"))
        self.horizontalLayout.addWidget(self.checkButton)

        self.updateButton = QPushButton(self.centralwidget)
        self.updateButton.setText(self.tr("Update item"))
        self.horizontalLayout.addWidget(self.updateButton)

        self.editRuleButton = QPushButton(self.centralwidget)
        self.editRuleButton.setText(self.tr("Edit rule"))
        self.horizontalLayout.addWidget(self.editRuleButton)

        self.verticalLayout.addLayout(self.horizontalLayout)
        MainWindow.setCentralWidget(self.centralwidget)

        # 菜单
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setGeometry(QRect(0, 0, 780, 34))
        MainWindow.setMenuBar(self.menubar)

        self.fileMenu = QMenu(self.menubar)
        self.fileMenu.setTitle(self.tr("File"))
        self.menubar.addAction(self.fileMenu.menuAction())

        self.toolMenu = QMenu(self.menubar)
        self.toolMenu.setTitle(self.tr("Tool"))
        self.menubar.addAction(self.toolMenu.menuAction())

        self.helpMenu = QMenu(self.menubar)
        self.helpMenu.setTitle(self.tr("Help"))
        self.menubar.addAction(self.helpMenu.menuAction())

        self.statusbar = QStatusBar(MainWindow)
        MainWindow.setStatusBar(self.statusbar)

        # 菜单项
        self.aboutAction = QAction(MainWindow)
        self.aboutAction.setText(self.tr("About"))
        self.aboutAction.setObjectName("about")
        self.aboutQtAction = QAction(MainWindow)
        self.aboutQtAction.setText(self.tr("About Qt"))
        self.aboutQtAction.setObjectName("about_qt")
        self.openAction = QAction(MainWindow)
        self.openAction.setText(self.tr("&Open"))
        self.openAction.setShortcut('Ctrl+O')
        self.openAction.setStatusTip(self.tr('Open a file'))
        self.openAction.setObjectName("open")
        self.openUrlAction = QAction(MainWindow)
        self.openUrlAction.setText(self.tr("Open &url"))
        self.openUrlAction.setShortcut('Ctrl+U')
        self.openUrlAction.setStatusTip(self.tr('Open a file with url'))
        self.saveAction = QAction(MainWindow)
        self.saveAction.setText(self.tr("&Save"))
        self.saveAction.setShortcut('Ctrl+S')
        self.saveAction.setStatusTip(self.tr('Save a file'))
        self.saveAction.setObjectName("save")
        self.saveAsAction = QAction(MainWindow)
        self.saveAsAction.setText(self.tr("Save As"))
        self.saveAsAction.setObjectName("save_as")
        self.closeAction = QAction(MainWindow)
        self.closeAction.setText(self.tr("&Close"))
        self.closeAction.setShortcut('Ctrl+W')
        self.closeAction.setStatusTip(self.tr('Close current page'))
        self.exitAction = QAction(MainWindow)
        self.exitAction.setText(self.tr("&Exit"))
        self.exitAction.setShortcut('Ctrl+Q')
        self.exitAction.setStatusTip(self.tr('Exit application'))
        self.settingAction = QAction(MainWindow)
        self.settingAction.setText(self.tr("&Settings"))
        self.settingAction.setShortcut('Ctrl+P')
        self.settingAction.setStatusTip(self.tr('Open settings dialog'))

        self.helpMenu.addAction(self.aboutAction)
        self.helpMenu.addAction(self.aboutQtAction)
        self.toolMenu.addAction(self.settingAction)
        self.fileMenu.addAction(self.openAction)
        self.fileMenu.addAction(self.openUrlAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.saveAction)
        self.fileMenu.addAction(self.saveAsAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.closeAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAction)

        # Signal & Slot
        self.addButton.clicked.connect(self.addRowSlot)
        self.delButton.clicked.connect(self.delRowSlot)
        self.upButton.clicked.connect(self.moveRowSlot)
        self.downButton.clicked.connect(self.moveRowSlot)
        self.checkButton.clicked.connect(self.checkUpdateSlot)
        self.updateButton.clicked.connect(self.updateTableItemSlot)
        self.editRuleButton.clicked.connect(self.editTableItemRuleSlot)
        self.settingAction.triggered.connect(self.showSettingDialogSlot)
        self.aboutAction.triggered.connect(self.showAboutDialogSlot)
        self.aboutQtAction.triggered.connect(self.showAboutDialogSlot)
        self.openAction.triggered.connect(self.showFileDialogSlot)
        self.openUrlAction.triggered.connect(self.showOpenUrlDialogSlot)
        self.saveAction.triggered.connect(self.showFileDialogSlot)
        self.saveAsAction.triggered.connect(self.showFileDialogSlot)
        self.closeAction.triggered.connect(self.tableWidget.clearContents)
        self.exitAction.triggered.connect(self.close)
        self.tableWidget.itemChanged.connect(self.itemChangedSlot)
        self.tableWidget.itemClicked.connect(self.itemClickedForOpenUrlSlot)

    def closeEvent(self, event):
        """关闭应用提示"""
        reply = QMessageBox.question(self, self.tr('Message'),
            self.tr("Are you sure to quit?"), QMessageBox.Yes |
            QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()  # 接受关闭事件
        else:
            event.ignore()  # 拒绝关闭事件

    def itemClickedForOpenUrlSlot(self, item):
        """Ctrl+left 打开链接"""
        # http://stackoverflow.com/questions/3100090/
        if item.column() == 1 and item.text() and \
                qApp.keyboardModifiers() == Qt.ControlModifier:
            QDesktopServices.openUrl(QUrl(item.text()))  # open url

    def itemChangedSlot(self, item):  # QTableWidgetItem
        """捕获itemChanged信号, 修改表项"""
        try:
            self.tableContents[item.row()].load(item.column(), item.text())
        except IndexError:
            pass

    def moveRowSlot(self):
        """移动行"""
        try:
            sourceRow = self.tableWidget.currentRow()
            destRow = sourceRow-1 if self.sender().objectName() == "up" else sourceRow+1
            if sourceRow != -1:
                sourceItems = self.getRow(sourceRow)
                destItems = self.getRow(destRow)
                self.setRow(destRow, sourceItems)
                self.setRow(sourceRow, destItems)
                self.tableWidget.selectRow(destRow)  # 修改焦点
                log.debug(self.tableContents)
        except AttributeError:
            if self.sender().objectName() == "up":
                QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is to top."))
            else:
                QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is to bottom."))

    def getRow(self, rowIndex):
        """获取行"""
        rowItems = []
        for i in range(7):
            item = self.tableWidget.item(rowIndex, i)
            rowItems.append(item.text())
        rowItems.append(self.tableContents[rowIndex].get_rules(ui=True))
        return rowItems

    def setRow(self, rowIndex, rowItems):
        """设置行"""
        for n, i in enumerate(rowItems):
            if n == len(rowItems) - 1:
                self.tableContents[rowIndex].set_rules(i)
            else:
                item = self.tableWidget.item(rowIndex, n)
                item.setText(i)

    def addRowSlot(self):
        """添加行"""
        rowIndex = self.tableWidget.rowCount()
        self.tableWidget.setRowCount(rowIndex + 1)
        self.tableContents.append(Checker())
        self.updateTableSlot(0)  # 更新列表控件
        log.debug(self.tableContents)

    def delRowSlot(self):
        """删除行"""
        # 焦点默认在第一行,要设置setFocusPolicy(Qt.NoFocus)
        rowIndex = self.tableWidget.currentRow()
        if rowIndex != -1:
            self.tableWidget.removeRow(rowIndex)
            self.tableContents.remove(self.tableContents[rowIndex])
            log.debug(self.tableContents)
        else:
            QMessageBox.warning(self, self.tr("Warning"), self.tr("Please select a row."))

    def loadData(self, data):
        """载入数据"""
        self.tableContents = []  # list.clear() Python 3
        for i in data:
            self.tableContents.append(Checker(i))

    def checkUpdateSlot(self):
        """执行更新检查"""
        self.wtime[0] = int(time.time())  # 计时
        self.statusbar.showMessage(self.tr("checking..."))
        self.progressBar.setValue(0)
        self.progressBar.show()
        self.progressVal = 0
        self.taskVal = 0

        for t in range(self.workerCount):
            t = WorkThread(self.q)  # 耗时任务需要用线程执行,再刷新进度条
            t.triggered.connect(self.updateTableSlot)
            self.workers.append(t)
            t.start()  # 执行工作线程

        # 填充队列
        for item in self.tableContents:
            self.q.put(item)

    def updateTableSlot(self, val):
        """线程通过该槽,刷新进度条,表格内容"""
        if val:
            self.taskVal += val
            self.progressVal = self.taskVal / len(self.tableContents) * 100
            self.progressBar.setValue(self.progressVal)
            self.label.setText("%s/%s" % (self.taskVal, len(self.tableContents)))
        self.tableWidget.setRowCount(len(self.tableContents))  # 行数

        for n, i in enumerate(self.tableContents):
            items = i.dump()
            for j in range(self.tableWidget.columnCount()):
                item = QTableWidgetItem(items[j])
                if j in [0, 1]:
                    item.setToolTip(item.text())
                self.tableWidget.setItem(n, j, item)
            self.setStatusColor(n)

        self.setBackgroundColor(self.bgColor)

        if self.progressVal == 100:
            self.wtime[1] = int(time.time())
            self.statusbar.showMessage(self.tr(
                "finished (work time %ds)") % (self.wtime[1] - self.wtime[0]))

    def updateTableItemSlot(self):
        """更新指定的 RPM 日期为 Release 日期"""
        rowIndex = self.tableWidget.currentRow()
        if rowIndex != -1:
            try:
                item = self.tableWidget.item(rowIndex, 4)
                self.tableWidget.item(rowIndex, 3).setText(item.text())
                self.tableContents[rowIndex].load_meta(item.text())
            except (IndexError, AttributeError):
                QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is empty."))
        else:
            QMessageBox.warning(self, self.tr("Warning"), self.tr("Please select a row."))

    def editTableItemRuleSlot(self):
        """编辑列表项规则"""
        rowIndex = self.tableWidget.currentRow()
        if rowIndex != -1:
            try:
                # 父控件, 标题, 标签提示, 默认值, window flags
                rules, ok = QInputDialog.getMultiLineText(self, self.tr("Edit rule"),
                    self.tr("XPath rule(format: \"[(time, commit), (time, commit)]\"):"),
                    re.sub("\),|],|',", lambda x: "%s\n" % x.group(),
                        str(self.tableContents[rowIndex].get_rules(ui=True)) ))

                if ok:
                    self.tableContents[rowIndex].set_rules(rules)
            except (IndexError, UnboundLocalError):
                QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is empty."))
        else:
            QMessageBox.warning(self, self.tr("Warning"), self.tr("Please select a row."))

    def showSettingDialogSlot(self):
        """显示设置对话框"""
        settingDialog = SettingDialog()
        settingDialog.exec_()

    def showAboutDialogSlot(self):
        """显示关于对话框"""
        if self.sender().objectName() == "about":
            QMessageBox.about(self, self.tr("Checker"), self.description)
        else:
            QMessageBox.aboutQt(self, self.tr("Checker"))

    def showOpenUrlDialogSlot(self):
        """通过 Url 打开文件"""
        url, _ = QInputDialog.getText(self, self.tr("Open url"),
                     self.tr("Enter url:"), QLineEdit.Normal, "")
        try:
            resp = backend.get(url)
            self.loadData(resp.json())
            self.updateTableSlot(0)  # 更新列表控件
            self.statusbar.showMessage(self.tr("open url successfully"))
        except Exception as e:
            QMessageBox.warning(self, self.tr("Error"),
                                self.tr("Open url failed. See below:\n%s") % e)
            self.statusbar.showMessage(self.tr("open url failed"))

    def loadCsvFile(self, fname):
        """load csv file (old format)"""
        _data = []
        with open(fname, 'r') as fp:
            content = csv.reader(fp)
            for row in content:
                if len(row) and row[0][0] != "#":
                    _data.append(row)
            self.loadData(_data)

    def showFileDialogSlot(self):
        """打开/保存数据至文件"""
        if self.sender().objectName() == "open":
            fname = QFileDialog.getOpenFileName(self, self.tr("Open file"), os.getcwd())
            fname = fname[0] if isinstance(fname, tuple) else fname  # qt5 tuple, qt4 str

            if fname:
                try:
                    with open(fname, 'r') as fp:
                        self.loadData(json.load(fp))
                except AttributeError as e:
                    QMessageBox.warning(self, self.tr("Error"),
                        self.tr("Open file failed. See below:\n%s") % e)
                except:  # json.decoder.JSONDecodeError Python 3
                    try:  # load csv file (old format)
                        self.loadCsvFile(fname)
                    except Exception as e:
                        QMessageBox.warning(self, self.tr("Error"),
                            self.tr("The file does not contain JSON or CSV. See below:\n%s") % e)

                self.updateTableSlot(0)  # 更新列表控件
                self.statusbar.showMessage(self.tr("open file successfully"))

        elif self.sender().objectName() in ["save", "save_as"]:
            fname = QFileDialog.getSaveFileName(self, self.tr("Save file"), os.getcwd())
            fname = fname[0] if isinstance(fname, tuple) else fname  # qt5 tuple, qt4 str

            if fname:
                try:
                    with open(fname, 'w') as fp:
                        json.dump([i.dump(mode="raw") for i in self.tableContents],
                                  fp, ensure_ascii=False)
                    self.statusbar.showMessage(self.tr("saved successfully"))
                except AttributeError as e:
                    QMessageBox.warning(self, self.tr("Error"),
                        self.tr("Save file failed. See below:\n%s") % e)

    def setBackgroundColor(self, color):
        """修改背景色"""
        for i in range(self.tableWidget.rowCount()):
            if i % 2 != 0:
                for j in range(self.tableWidget.columnCount()):
                    item = self.tableWidget.item(i, j)
                    if item:
                        item.setBackground(color)

    def setStatusColor(self, rowIndex):
        """修改状态文字颜色"""
        item = self.tableWidget.item(rowIndex, 6)
        if item.text() == "normal":
            item.setForeground(Qt.darkGreen)
        elif item.text() == "update":
            item.setForeground(Qt.darkRed)
        elif item.text() == "error":
            item.setForeground(Qt.darkYellow)
        elif item.text() == "none":
            item.setForeground(Qt.gray)

    def setupTable(self):
        """初始化列表"""
        self.tableWidget.setFocusPolicy(Qt.NoFocus)  # 无焦点
        self.tableWidget.setGridStyle(Qt.DashDotLine)  # 线类型
        self.tableWidget.setWordWrap(True)
        self.tableWidget.setCornerButtonEnabled(True)
        self.tableWidget.horizontalHeader().setVisible(True)  # 显示表头
        #self.tableWidget.horizontalHeader().setSortIndicatorShown(True)  # 排序指示器
        self.tableWidget.horizontalHeader().setStretchLastSection(True)  # 扩展最后一列

        self.tableWidget.setColumnCount(self.tableColumnCount)  # 列数
        self.tableWidget.setRowCount(self.tableRowCount)  # 行数

        # 行头
        for i in range(self.tableRowCount):
            item = QTableWidgetItem("%s" % (i+1))
            self.tableWidget.setVerticalHeaderItem(i, item)  # 行号

        # 列头
        for i in range(self.tableColumnCount):
            item = QTableWidgetItem(self.tableHeaders[i])  # QIcon, str
            self.tableWidget.setHorizontalHeaderItem(i, item)  # 初始化表头

        for i in [3, 4, 5]:
            self.tableWidget.resizeColumnToContents(i)  # 根据内容调整列宽

        # 初始化项目
        for i in range(self.tableRowCount):
            self.tableContents.append(Checker())
            for j in range(self.tableColumnCount):
                item = QTableWidgetItem()
                self.tableWidget.setItem(i, j, item)

        self.setBackgroundColor(self.bgColor)
예제 #22
0
class Player(QWidget):

    fullScreenChanged = pyqtSignal(bool)

    def __init__(self, playlist, parent=None):
        super(Player, self).__init__(parent)
        self.setStyleSheet(stylesheet(self))
        self.colorDialog = None
        self.trackInfo = ""
        self.statusInfo = ""
        self.duration = 0

        self.url = ""
        self. settings = QSettings("QAudioPlayer", "QAudioPlayer")

        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.player.setPlaylist(self.playlist)

        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.metaDataChanged.connect(self.metaDataChanged)
        self.playlist.currentIndexChanged.connect(self.playlistPositionChanged)
        self.player.mediaStatusChanged.connect(self.statusChanged)
        self.player.bufferStatusChanged.connect(self.bufferingProgress)
        self.player.error.connect(self.displayErrorMessage)

        self.playlistModel = PlaylistModel()
        self.playlistModel.setPlaylist(self.playlist)

        self.playlistView = QListView()
#        self.playlistView.setSpacing(1)
        self.playlistView.setStyleSheet(stylesheet(self))
        self.playlistView.setModel(self.playlistModel)
        self.playlistView.setCurrentIndex(
                self.playlistModel.index(self.playlist.currentIndex(), 0))

        self.playlistView.activated.connect(self.jump)

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.player.duration() / 1000)
        self.slider.setStyleSheet(stylesheet(self))

        self.labelDuration = QLabel()
        self.slider.sliderMoved.connect(self.seek)

        openButton = QPushButton("Open", clicked=self.open)
        openButton.setIcon(openButton.style().standardIcon(QStyle.SP_DialogOpenButton))

        clearButton = QPushButton("", clicked=self.clearList)
        clearButton.setFixedWidth(36)
        clearButton.setIcon(QIcon.fromTheme("edit-delete"))
        clearButton.setToolTip("clear List")

        controls = PlayerControls()
        controls.setState(self.player.state())
        controls.setVolume(self.player.volume())
        controls.setMuted(controls.isMuted())

        controls.play.connect(self.player.play)
        controls.pause.connect(self.player.pause)
        controls.stop.connect(self.player.stop)
        controls.next.connect(self.playlist.next)
        controls.previous.connect(self.previousClicked)
        controls.changeVolume.connect(self.player.setVolume)
        controls.changeMuting.connect(self.player.setMuted)
        controls.changeRate.connect(self.player.setPlaybackRate)

        self.player.stateChanged.connect(controls.setState)
        self.player.volumeChanged.connect(controls.setVolume)
        self.player.mutedChanged.connect(controls.setMuted)

        displayLayout = QHBoxLayout()
        displayLayout.addWidget(self.playlistView)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(openButton)
        controlLayout.addWidget(clearButton)
#        controlLayout.addStretch(1)
        controlLayout.addWidget(controls)
#        controlLayout.addStretch(1)

        layout = QVBoxLayout()
        layout.addLayout(displayLayout)
        hLayout = QHBoxLayout()
        hLayout.addWidget(self.slider)
        hLayout.addWidget(self.labelDuration)
        layout.addLayout(hLayout)
        layout.addLayout(controlLayout)

        self.statusBar = QStatusBar()
        vlayout = QVBoxLayout()
        vlayout.addWidget(self.statusBar)
        layout.addLayout(vlayout)
        self.statusBar.showMessage("Welcome")
        self.setWindowTitle("QAudioPlayer")
        self.setMinimumSize(300, 200)
#        self.setBackgroundRole(QPalette.Window)
        self.setContentsMargins(0,0,0,0)
        self.setLayout(layout)
        self.readSettings()

        if not self.player.isAvailable():
            QMessageBox.warning(self, "Service not available",
                    "The QMediaPlayer object does not have a valid service.\n"
                    "Please check the media service plugins are installed.")

            controls.setEnabled(False)
            self.playlistView.setEnabled(False)
            openButton.setEnabled(False)
            self.colorButton.setEnabled(False)
            self.fullScreenButton.setEnabled(False)

        self.metaDataChanged()

        self.addToPlaylist(playlist)

    def readSettings(self):
        if self.settings.contains("url"):
            self.url = self.settings.value("url")
            self.addToPlaylist(self.url)

    def writeSettings(self):
        self.settings.setValue("url", self.url)

    def closeEvent(self, event):
        print("writing settings")
        self.writeSettings()
        print("goodbye ...")
        event.accept()

    def open(self):
        fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files", "/home", "Audio Files *.mp3 *.m4a *.ogg *.wav *.m3u")
        if fileNames:
            self.url = fileNames
            self.addToPlaylist(fileNames)
            print("added Files to playlist")

    def openOnStart(self, name):
        fileInfo = QFileInfo(name)
        if fileInfo.exists():
            url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
            if fileInfo.suffix().lower() == 'm3u':
                self.playlist.load(url)
            else:
                self.playlist.addMedia(QMediaContent(url))
        else:
            url = QUrl(name)
            if url.isValid():
                self.playlist.addMedia(QMediaContent(url))
        print("added Files to playlist")

    def clearList(self):
        self.playlist.clear()

    def addToPlaylist(self, fileNames):
        for name in fileNames:
            fileInfo = QFileInfo(name)
            if fileInfo.exists():
                url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
                if fileInfo.suffix().lower() == 'm3u':
                    self.playlist.load(url)
                else:
                    self.playlist.addMedia(QMediaContent(url))
            else:
                url = QUrl(name)
                if url.isValid():
                    self.playlist.addMedia(QMediaContent(url))

    def durationChanged(self, duration):
        duration /= 1000

        self.duration = duration
        self.slider.setMaximum(duration)

    def positionChanged(self, progress):
        progress /= 1000

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

        self.updateDurationInfo(progress)

    def metaDataChanged(self):
        if self.player.isMetaDataAvailable():
            self.setTrackInfo("%s - %s" % (
                    self.player.metaData(QMediaMetaData.AlbumArtist),
                    self.player.metaData(QMediaMetaData.Title)))

    def previousClicked(self):
        # Go to the previous track if we are within the first 5 seconds of
        # playback.  Otherwise, seek to the beginning.
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def jump(self, index):
        if index.isValid():
            self.playlist.setCurrentIndex(index.row())
            self.player.play()

    def playlistPositionChanged(self, position):
        self.playlistView.setCurrentIndex(
                self.playlistModel.index(position, 0))

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)

    def statusChanged(self, status):
        self.handleCursor(status)

        if status == QMediaPlayer.LoadingMedia:
            self.setStatusInfo("Loading...")
        elif status == QMediaPlayer.StalledMedia:
            self.setStatusInfo("Media Stalled")
        elif status == QMediaPlayer.EndOfMedia:
            QApplication.alert(self)
        elif status == QMediaPlayer.InvalidMedia:
            self.displayErrorMessage()
        else:
            self.setStatusInfo("")

    def handleCursor(self, status):
        if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia):
            self.setCursor(Qt.BusyCursor)
        else:
            self.unsetCursor()

    def bufferingProgress(self, progress):
        self.setStatusInfo("Buffering %d%" % progress)

    def setTrackInfo(self, info):
        self.trackInfo = info

        if self.statusInfo != "":
             self.statusBar.showMessage("%s | %s" % (self.trackInfo, self.statusInfo))
        else:
            self.statusBar.showMessage(self.trackInfo)

    def setStatusInfo(self, info):
        self.statusInfo = info

        if self.statusInfo != "":
            self.statusBar.showMessage("%s | %s" % (self.trackInfo, self.statusInfo))
        else:
            self.statusBar.showMessage(self.trackInfo)

    def displayErrorMessage(self):
        self.setStatusInfo(self.player.errorString())

    def updateDurationInfo(self, currentInfo):
        duration = self.duration
        if currentInfo or duration:
            currentTime = QTime((currentInfo/3600)%60, (currentInfo/60)%60,
                    currentInfo%60, (currentInfo*1000)%1000)
            totalTime = QTime((duration/3600)%60, (duration/60)%60,
                    duration%60, (duration*1000)%1000);

            format = 'hh:mm:ss' if duration > 3600 else 'mm:ss'
            tStr = currentTime.toString(format) + " / " + totalTime.toString(format)
        else:
            tStr = ""

        self.labelDuration.setText(tStr)
예제 #23
0
class Window(QMainWindow):
    """
    Represents the application's main window that will contain the UI widgets.
    All interactions with the UI go through the object created by this class.
    """

    icon = 'icon.png'

    def __init__(self):
        """
        Create the default start state. The window contains a root widget into
        which is placed:

        * A status bar widget at the top, containing curent user / status
          information.
        * A main-view widget, itself containing a list view for sources and a
          place for details / message contents / forms.
        """
        super().__init__()
        self.setWindowTitle(_("SecureDrop Client {}").format(__version__))
        self.setWindowIcon(load_icon(self.icon))
        self.widget = QWidget()
        widget_layout = QVBoxLayout()
        self.widget.setLayout(widget_layout)
        self.tool_bar = ToolBar(self.widget)
        self.main_view = MainView(self.widget)
        self.main_view.source_list.itemSelectionChanged.\
            connect(self.on_source_changed)
        widget_layout.addWidget(self.tool_bar, 1)
        widget_layout.addWidget(self.main_view, 6)
        self.setCentralWidget(self.widget)
        self.current_source = None  # Tracks which source is shown
        self.show()
        self.autosize_window()

    def setup(self, controller):
        """
        Create references to the controller logic and instantiate the various
        views used in the UI.
        """
        self.controller = controller  # Reference the Client logic instance.
        self.tool_bar.setup(self, controller)
        self.status_bar = QStatusBar(self)
        self.setStatusBar(self.status_bar)
        self.set_status('Started SecureDrop Client. Please sign in.', 20000)
        self.login_dialog = LoginDialog(self)
        self.main_view.setup(self.controller)

    def autosize_window(self):
        """
        Ensure the application window takes up 100% of the available screen
        (i.e. the whole of the virtualised desktop in Qubes dom)
        """
        screen = QDesktopWidget().screenGeometry()
        self.resize(screen.width(), screen.height())

    def show_login(self):
        """
        Show the login form.
        """
        self.login_dialog = LoginDialog(self)
        self.login_dialog.setup(self.controller)
        self.login_dialog.reset()
        self.login_dialog.exec()

    def show_login_error(self, error):
        """
        Display an error in the login dialog.
        """
        if self.login_dialog and error:
            self.login_dialog.error(error)

    def hide_login(self):
        """
        Kill the login dialog.
        """
        self.login_dialog.accept()
        self.login_dialog = None

    def update_error_status(self, error=None):
        """
        Show an error message on the sidebar.
        """
        self.main_view.update_error_status(error)

    def show_sources(self, sources):
        """
        Update the left hand sources list in the UI with the passed in list of
        sources.
        """
        self.main_view.source_list.update(sources)

    def show_sync(self, updated_on):
        """
        Display a message indicating the data-sync state.
        """
        if updated_on:
            self.main_view.status.setText('Last Sync: ' +
                                          updated_on.humanize())
        else:
            self.main_view.status.setText(_('Waiting to Synchronize'))

    def set_logged_in_as(self, username):
        """
        Update the UI to show user logged in with username.
        """
        self.tool_bar.set_logged_in_as(username)

    def logout(self):
        """
        Update the UI to show the user is logged out.
        """
        self.tool_bar.set_logged_out()

    def on_source_changed(self):
        """
        React to when the selected source has changed.
        """
        source_item = self.main_view.source_list.currentItem()
        source_widget = self.main_view.source_list.itemWidget(source_item)
        if source_widget:
            self.current_source = source_widget.source
            self.show_conversation_for(self.current_source)

    def show_conversation_for(self, source):
        """
        Show conversation of messages and replies between a source and
        journalists.
        """
        conversation = ConversationView(self)
        conversation.setup(self.controller)
        conversation.add_message('Source name: {}'.format(
            source.journalist_designation))

        # Display each conversation item in the source collection.
        for conversation_item in source.collection:
            if conversation_item.filename.endswith('msg.gpg'):
                # TODO: Decrypt and display the message
                pass
            elif conversation_item.filename.endswith('reply.gpg'):
                # TODO: Decrypt and display the reply
                pass
            else:
                conversation.add_file(source, conversation_item)

        conversation.add_message('Hello, hello, is this thing switched on?')
        conversation.add_reply('Yes, I can hear you loud and clear!')
        conversation.add_reply('How can I help?')
        conversation.add_message('I have top secret documents relating to '
                                 'a massive technical scandal at the heart '
                                 ' of the Freedom of the Press Foundation. '
                                 'In a shocking turn of events, it appears '
                                 'they give away all their software for FREE.')
        conversation.add_message("Hello: I’m a nurse at one of the trauma "
                                 "centers in town. We've had many patients in "
                                 "the last several months, all with "
                                 "similar/mysterious respiratory issues. My "
                                 "staff has noticed that most live down-wind "
                                 "from the Dole fields West of 696. Some of "
                                 "the patients say they have complained to "
                                 "local authorities about sewage smells. One "
                                 "said she's spotted a truck spraying a "
                                 "sludge of some kind, on the fields at "
                                 "night. I'm attaching a video from the "
                                 "patient who taped the trucks, and a PDF of "
                                 "redacted police reports that other patients "
                                 "shared. I don’t know if there's much you "
                                 "can do, but if there is I would be happy "
                                 "to help.")
        conversation.add_message("I work at the City Water Department, and a "
                                 "man named Reggie Esters is one of our board "
                                 "directors. I believe Reggie is related to "
                                 "Rep Monica Conyers. He's literally never "
                                 "here, and the resume on file for him makes "
                                 "no sense. I have a hunch he is not in his "
                                 "job legitimately, and think you should look "
                                 "into this. Also: someone I work with heard "
                                 "him on the phone once, talking about his "
                                 "'time' at Jackson—that contradicts his "
                                 "resume. It really seems fishy.")
        conversation.add_reply("THIS IS IT THIS IS THE TAPE EVERYONE'S "
                               "LOOKING FOR!!!")
        conversation.add_reply("Hello: I read your story on Sally Dale, and "
                               "her lawsuit against the St. Joseph's "
                               "Orphanage. My great-aunt was one of the nuns "
                               "there. She is willing to be interviewed, but "
                               "does not want her name, location, or any "
                               "identity details released. She feels "
                               "horrible. She wants the children who survived "
                               "to find peace. Thanks.")
        self.main_view.update_view(conversation)

    def set_status(self, message, duration=5000):
        """
        Display a status message to the user. Optionally, supply a duration
        (in milliseconds), the default value being a duration of 5 seconds.
        """
        self.status_bar.showMessage(message, duration)
예제 #24
0
class MainApp(QWidget):
    def __init__(self, parent=None):
        logging.debug("MainApp:init() instantiated")
        super().__init__()
        self.baseWidgets = {}
        self.vmWidgets = {}
        self.materialWidgets = {}
        self.cf = SystemConfigIO()
        self.ec = ExperimentConfigIO.getInstance()
        self.statusBar = QStatusBar()

        self.setMinimumSize(670, 565)
        quit = QAction("Quit", self)
        quit.triggered.connect(self.closeEvent)
        self.setWindowTitle("ARL South RES v0.1")

        self.tabWidget = QtWidgets.QTabWidget()
        self.tabWidget.setGeometry(QtCore.QRect(0, 15, 668, 565))
        self.tabWidget.setObjectName("tabWidget")

        # Configuration Window (windowBox) contains:
        ## windowBoxHLayout contains:
        ###experimentTree (Left)
        ###basedataStackedWidget (Right)
        self.windowWidget = QtWidgets.QWidget()
        self.windowWidget.setObjectName("windowWidget")
        self.windowBoxHLayout = QtWidgets.QHBoxLayout()
        #self.windowBoxHLayout.setContentsMargins(0, 0, 0, 0)
        self.windowBoxHLayout.setObjectName("windowBoxHLayout")
        self.windowWidget.setLayout(self.windowBoxHLayout)

        self.experimentTree = QtWidgets.QTreeWidget()
        self.experimentTree.itemSelectionChanged.connect(self.onItemSelected)
        self.experimentTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.experimentTree.customContextMenuRequested.connect(
            self.showContextMenu)
        self.experimentTree.setEnabled(True)
        self.experimentTree.setMinimumSize(200, 521)
        self.experimentTree.setMaximumWidth(350)
        self.experimentTree.setObjectName("experimentTree")
        self.experimentTree.headerItem().setText(0, "Experiments")
        self.experimentTree.setSortingEnabled(False)
        self.windowBoxHLayout.addWidget(self.experimentTree)

        self.basedataStackedWidget = QStackedWidget()
        self.basedataStackedWidget.setObjectName("basedataStackedWidget")
        self.basedataStackedWidget.setEnabled(False)
        self.windowBoxHLayout.addWidget(self.basedataStackedWidget)
        self.tabWidget.addTab(self.windowWidget, "Configuration")

        # VBox Actions Tab
        self.experimentActionsWidget = ExperimentActionsWidget(
            statusBar=self.statusBar)
        self.experimentActionsWidget.setObjectName("experimentActionsWidget")
        self.tabWidget.addTab(self.experimentActionsWidget,
                              "Experiment Actions")

        # Remote Connections Tab
        self.connectionWidget = ConnectionWidget(statusBar=self.statusBar)
        self.connectionWidget.setObjectName("connectionsWidget")
        self.tabWidget.addTab(self.connectionWidget, "Remote Connections")

        #Create the bottom layout so that we can access the status bar
        self.bottomLayout = QHBoxLayout()
        self.statusBar.showMessage("Loading GUI...")
        self.bottomLayout.addWidget(self.statusBar)
        self.saveButton = QtWidgets.QPushButton("Save Current")
        self.saveButton.clicked.connect(self.saveExperimentButton)
        self.saveButton.setEnabled(False)
        self.bottomLayout.addWidget(self.saveButton)

        self.populateUi()
        self.setupContextMenus()

        self.initMenu()
        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.mainMenu)
        self.mainLayout.addWidget(self.tabWidget)
        self.mainLayout.addLayout(self.bottomLayout)

        self.setLayout(self.mainLayout)
        #self.setCentralWidget(self.outerBox)
        self.tabWidget.setCurrentIndex(0)

        #self.statusBar.showMessage("Finished Loading GUI Components")

        # Plugin Section
        self.tabWidget.addTab(CTFi2GUI(), "CTFi2")

    def readSystemConfig(self):
        logging.debug("MainApp:readSystemConfig() instantiated")
        self.vboxPath = self.cf.getConfig()['VBOX']['VMANAGE_PATH']
        self.experimentPath = self.cf.getConfig(
        )['EXPERIMENTS']['EXPERIMENTS_PATH']
        self.statusBar.showMessage("Finished reading system config")

    def setupContextMenus(self):
        logging.debug("MainApp:setupContextMenus() instantiated")
        # Context menu for blank space
        self.blankTreeContextMenu = QtWidgets.QMenu()
        self.addExperiment = self.blankTreeContextMenu.addAction(
            "New Experiment")
        self.addExperiment.triggered.connect(self.addExperimentActionEvent)
        self.importExperiment = self.blankTreeContextMenu.addAction(
            "Import Experiment from RES archive")
        self.importExperiment.triggered.connect(self.importActionEvent)

        # Experiment context menu
        self.experimentContextMenu = QtWidgets.QMenu()
        self.addVMContextSubMenu = QtWidgets.QMenu()
        self.experimentContextMenu.addMenu(self.addVMContextSubMenu)
        self.addVMContextSubMenu.setTitle("Add")
        self.addVM = self.addVMContextSubMenu.addAction("Virtual Machines")
        self.addVM.triggered.connect(self.addVMActionEvent)
        self.addMaterial = self.addVMContextSubMenu.addAction("Material Files")
        self.addMaterial.triggered.connect(self.addMaterialActionEvent)

        # Add line separator here
        self.removeExperiment = self.experimentContextMenu.addAction(
            "Remove Experiment")
        self.removeExperiment.triggered.connect(
            self.removeExperimentItemActionEvent)
        self.exportExperiment = self.experimentContextMenu.addAction(
            "Export Experiment")
        self.exportExperiment.triggered.connect(self.exportActionEvent)

        # VM/Material context menu
        self.itemContextMenu = QtWidgets.QMenu()
        self.removeItem = self.itemContextMenu.addAction(
            "Remove Experiment Item")
        self.removeItem.triggered.connect(self.removeExperimentItemActionEvent)

    def populateUi(self):
        logging.debug("MainApp:populateUi() instantiated")
        self.statusBar.showMessage("Populating UI")
        self.readSystemConfig()
        #####Create the following based on the config file
        result = self.ec.getExperimentXMLFilenames()
        if result == None:
            return
        [xmlExperimentFilenames, xmlExperimentNames] = result
        if xmlExperimentFilenames == [] or xmlExperimentNames == []:
            self.statusBar.showMessage("No configs found")
            return

        #For all experiment files found
        for configname in xmlExperimentNames:
            ####Read Experiment Config Data and Populate Tree
            self.loadConfigname(configname)
        self.statusBar.showMessage(
            "Completed populating the User Interface from " +
            str(len(xmlExperimentNames)) + " config files read", 6000)

    ###############################

    def loadConfigname(self, configname):
        logging.debug("MainApp(): loadConfigname instantiated")
        logging.info("Reading XML data for " + str(configname))
        jsondata = self.ec.getExperimentXMLFileData(configname)
        self.statusBar.showMessage("Finished reading experiment config")

        ##########testbed-setup data######
        if jsondata == None:
            jsondata = {}
        if "xml" not in jsondata or jsondata["xml"] == None or str(
                jsondata["xml"]).strip() == "":
            jsondata["xml"] = {}
        if "testbed-setup" not in jsondata["xml"]:
            jsondata["xml"]["testbed-setup"] = {}
        if "vm-set" not in jsondata["xml"]["testbed-setup"]:
            jsondata["xml"]["testbed-setup"]["vm-set"] = {}
        #Temporary fix for older xml/json files.
        if "users-filename" not in jsondata["xml"]["testbed-setup"]["vm-set"]:
            jsondata["xml"]["testbed-setup"]["vm-set"]["users-filename"] = ""
        if "rdp-broker-ip" not in jsondata["xml"]["testbed-setup"]["vm-set"]:
            jsondata["xml"]["testbed-setup"]["vm-set"]["rdp-broker-ip"] = ""
        if "chat-server-ip" not in jsondata["xml"]["testbed-setup"]["vm-set"]:
            jsondata["xml"]["testbed-setup"]["vm-set"]["chat-server-ip"] = ""

        configTreeWidgetItem = QtWidgets.QTreeWidgetItem(self.experimentTree)
        configTreeWidgetItem.setText(0, configname)
        self.experimentActionsWidget.addExperimentItem(
            configname, config_jsondata=jsondata)
        self.connectionWidget.addExperimentItem(configname,
                                                config_jsondata=jsondata)
        basejsondata = jsondata["xml"]
        # Base Config Widget
        self.baseWidget = BaseWidget(self, configname, configname,
                                     basejsondata)
        self.baseWidgets[configname] = {
            "BaseWidget": {},
            "VMWidgets": {},
            "MaterialWidgets": {}
        }
        self.baseWidgets[configname]["BaseWidget"] = self.baseWidget
        self.basedataStackedWidget.addWidget(self.baseWidget)

        ##########vm data######
        if "vm" in jsondata["xml"]["testbed-setup"]["vm-set"]:
            vmsjsondata = jsondata["xml"]["testbed-setup"]["vm-set"]["vm"]
            if isinstance(vmsjsondata, list):
                for vm in vmsjsondata:
                    vm_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem)
                    vmlabel = "V: " + vm["name"]
                    vm_item.setText(0, vmlabel)
                    # VM Config Widget
                    vmWidget = VMWidget(None, configname, vm["name"], vm)
                    self.baseWidgets[configname]["VMWidgets"][
                        vmlabel] = vmWidget
                    self.basedataStackedWidget.addWidget(vmWidget)
            else:
                vm_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem)
                vmlabel = "V: " + vmsjsondata["name"]
                vm_item.setText(0, vmlabel)
                # VM Config Widget
                vmWidget = VMWidget(None, configname, vmsjsondata["name"],
                                    vmsjsondata)
                self.baseWidgets[configname]["VMWidgets"][vmlabel] = vmWidget
                self.basedataStackedWidget.addWidget(vmWidget)

    ##########material data######
        if "material" in jsondata["xml"]["testbed-setup"]["vm-set"]:
            materialsjsondata = jsondata["xml"]["testbed-setup"]["vm-set"][
                "material"]
            if isinstance(materialsjsondata, list):
                for material in materialsjsondata:
                    material_item = QtWidgets.QTreeWidgetItem(
                        configTreeWidgetItem)
                    materiallabel = "M: " + material["name"]
                    material_item.setText(0, materiallabel)
                    # Material Config Widget
                    materialWidget = MaterialWidget(None, configname,
                                                    material["name"], material)
                    self.baseWidgets[configname]["MaterialWidgets"][
                        materiallabel] = materialWidget
                    self.basedataStackedWidget.addWidget(materialWidget)
            else:
                material_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem)
                materiallabel = "M: " + materialsjsondata["name"]
                material_item.setText(0, materiallabel)
                # Material Config Widget
                materialWidget = MaterialWidget(None, configname,
                                                materialsjsondata["name"],
                                                materialsjsondata)
                self.baseWidgets[configname]["MaterialWidgets"][
                    materiallabel] = materialWidget
                self.basedataStackedWidget.addWidget(materialWidget)
        logging.debug("MainApp(): Finished loading configname: " +
                      str(configname))

    def onItemSelected(self):
        logging.debug("MainApp:onItemSelected instantiated")
        # Get the selected item
        selectedItem = self.experimentTree.currentItem()
        if selectedItem == None:
            logging.debug("MainApp:onItemSelected no configurations left")
            self.statusBar.showMessage(
                "No configuration items selected or available.")
            return
        self.basedataStackedWidget.setEnabled(True)
        # Now enable the save button
        self.saveButton.setEnabled(True)
        self.saveExperimentMenuButton.setEnabled(True)
        #Check if it's the case that an experiment name was selected
        parentSelectedItem = selectedItem.parent()
        if (parentSelectedItem == None):
            #A base widget was selected
            self.basedataStackedWidget.setCurrentWidget(
                self.baseWidgets[selectedItem.text(0)]["BaseWidget"])
        else:
            #Check if it's the case that a VM Name was selected
            if (selectedItem.text(0)[0] == "V"):
                logging.debug("Setting right widget: " +
                              str(self.baseWidgets[parentSelectedItem.text(0)]
                                  ["VMWidgets"][selectedItem.text(0)]))
                self.basedataStackedWidget.setCurrentWidget(
                    self.baseWidgets[parentSelectedItem.text(0)]["VMWidgets"][
                        selectedItem.text(0)])
            #Check if it's the case that a Material Name was selected
            elif (selectedItem.text(0)[0] == "M"):
                logging.debug("Setting right widget: " +
                              str(self.baseWidgets[parentSelectedItem.text(0)]
                                  ["MaterialWidgets"][selectedItem.text(0)]))
                self.basedataStackedWidget.setCurrentWidget(
                    self.baseWidgets[parentSelectedItem.text(
                        0)]["MaterialWidgets"][selectedItem.text(0)])

    def showContextMenu(self, position):
        logging.debug("MainApp:showContextMenu() instantiated: " +
                      str(position))
        if (self.experimentTree.itemAt(position) == None):
            self.blankTreeContextMenu.popup(
                self.experimentTree.mapToGlobal(position))
        elif (self.experimentTree.itemAt(position).parent() == None):
            self.experimentContextMenu.popup(
                self.experimentTree.mapToGlobal(position))
        else:
            self.itemContextMenu.popup(
                self.experimentTree.mapToGlobal(position))

    def addExperimentActionEvent(self):
        logging.debug("MainApp:addExperimentActionEvent() instantiated")
        configname = ExperimentAddDialog().experimentAddDialog(
            self, self.baseWidgets.keys())

        if configname != None:
            logging.debug(
                "configureVM(): OK pressed and valid configname entered: " +
                str(configname))
        else:
            logging.debug("configureVM(): Cancel pressed or no VM selected")
            return

        ##Now add the item to the tree widget and create the baseWidget
        configTreeWidgetItem = QtWidgets.QTreeWidgetItem(self.experimentTree)
        configTreeWidgetItem.setText(0, configname)
        self.experimentActionsWidget.addExperimentItem(configname)
        self.connectionWidget.addExperimentItem(configname)
        # Base Config Widget
        self.baseWidget = BaseWidget(self, configname, configname)
        self.baseWidgets[configname] = {
            "BaseWidget": {},
            "VMWidgets": {},
            "MaterialWidgets": {}
        }
        self.baseWidgets[configname]["BaseWidget"] = self.baseWidget
        self.basedataStackedWidget.addWidget(self.baseWidget)
        self.statusBar.showMessage("Added new experiment: " + str(configname))

    def importActionEvent(self):
        logging.debug("MainApp:importActionEvent() instantiated")
        #Check if it's the case that an experiment name was selected
        confignamesChosen = PackageImportDialog().packageImportDialog(
            self, self.baseWidgets.keys())
        if confignamesChosen == []:
            logging.debug(
                "importActionEvent(): Canceled or a file could not be imported. make sure file exists."
            )
            return
        #for fileChosen in filesChosen:
        logging.debug(
            "MainApp: importActionEvent(): Files choosen (getting only first): "
            + confignamesChosen)
        firstConfignameChosen = confignamesChosen
        self.loadConfigname(firstConfignameChosen)
        #Add the items to the tree
        self.statusBar.showMessage("Imported " + firstConfignameChosen)

    def addVMActionEvent(self):
        logging.debug("MainApp:addVMActionEvent() instantiated")
        selectedItem = self.experimentTree.currentItem()
        if selectedItem == None:
            logging.debug("MainApp:addVMActionEvent no configurations left")
            self.statusBar.showMessage(
                "Could not add VM. No configuration items selected or available."
            )
            return
        selectedItemName = selectedItem.text(0)
        #Now allow the user to choose the VM:
        (response, vmsChosen) = VMRetrieveDialog(self).exec_()

        if response == QMessageBox.Ok and vmsChosen != None:
            logging.debug("configureVM(): OK pressed and VMs selected " +
                          str(vmsChosen))
        else:
            logging.debug("configureVM(): Cancel pressed or no VM selected")
            return

        if vmsChosen == []:
            logging.debug(
                "configureVM(): Canceled or a file could not be added. Try again later or check permissions"
            )
            return

        for vmChosen in vmsChosen:
            logging.debug("MainApp: addVMActionEvent(): File choosen: " +
                          str(vmChosen))
            #Add the item to the tree
            vmItem = QtWidgets.QTreeWidgetItem(selectedItem)
            vmlabel = "V: " + vmChosen
            vmItem.setText(0, vmlabel)
            # VM Config Widget
            #Now add the item to the stack and list of baseWidgets
            vmjsondata = {"name": vmChosen}
            vmWidget = VMWidget(self, selectedItemName, vmChosen, vmjsondata)
            self.baseWidgets[selectedItemName]["VMWidgets"][vmlabel] = vmWidget
            self.basedataStackedWidget.addWidget(vmWidget)
        #Now add data to the experimentActionWidget associated with the current config
        #Check if it's the case that an experiment name was selected
        parentSelectedItem = selectedItem.parent()
        if parentSelectedItem != None:
            selectedItem = parentSelectedItem
        configname = selectedItem.text(0)
        config_jsondata = self.getWritableData(configname)
        self.experimentActionsWidget.resetExperiment(
            configname, config_jsondata=config_jsondata)
        self.connectionWidget.resetExperiment(configname,
                                              config_jsondata=config_jsondata)
        self.statusBar.showMessage("Added " + str(len(vmsChosen)) +
                                   " VM files to experiment: " +
                                   str(selectedItemName))

    def startHypervisorActionEvent(self):
        logging.debug("MainApp:startHypervisorActionEvent() instantiated")
        logging.debug(
            "MainApp:startHypervisorActionEvent no configurations left")

        # Try to open the hypervisor and check if it worked or not
        result = HypervisorOpenDialog().hypervisorOpenDialog(self)
        if result != "success":
            logging.debug(
                "startHypervisorActionEvent(): Could not start the hypervisor")
            self.statusBar.showMessage("Hypervisor could not be started.")
            return

        self.statusBar.showMessage("Started hypervisor.")

    def addMaterialActionEvent(self):
        logging.debug("MainApp:addMaterialActionEvent() instantiated")
        selectedItem = self.experimentTree.currentItem()
        if selectedItem == None:
            logging.debug(
                "MainApp:addMaterialActionEvent no configurations left")
            self.statusBar.showMessage(
                "Could not add item. No configuration items selected or available."
            )
            return

        selectedItemName = selectedItem.text(0)
        #Check if it's the case that an experiment name was selected
        filesChosen = MaterialAddFileDialog().materialAddFileDialog(
            selectedItemName)
        if filesChosen == []:
            logging.debug(
                "addMaterialActionEvent(): Canceled or a file could not be added. Try again later or check permissions"
            )
            return
        for fileChosen in filesChosen:
            fileChosen = os.path.basename(fileChosen)
            logging.debug("MainApp: addMaterialActionEvent(): File choosen: " +
                          fileChosen)
            #Add the item to the tree
            material_item = QtWidgets.QTreeWidgetItem(selectedItem)
            materiallabel = "M: " + fileChosen
            material_item.setText(0, materiallabel)
            # Material Config Widget
            #Now add the item to the stack and list of baseWidgets
            materialsjsondata = {"name": fileChosen}
            materialWidget = MaterialWidget(self, selectedItemName, fileChosen,
                                            materialsjsondata)
            self.baseWidgets[selectedItem.text(
                0)]["MaterialWidgets"][materiallabel] = materialWidget
            self.basedataStackedWidget.addWidget(materialWidget)
        self.statusBar.showMessage("Added " + str(len(filesChosen)) +
                                   " material files to experiment: " +
                                   str(selectedItemName))

    def removeExperimentItemActionEvent(self):
        logging.debug("MainApp:removeExperimentItemActionEvent() instantiated")
        selectedItem = self.experimentTree.currentItem()
        if selectedItem == None:
            logging.debug("MainApp:onItemSelected no configurations left")
            self.statusBar.showMessage(
                "Could not remove. No configuration items selected or available."
            )
            return

        selectedItemName = selectedItem.text(0)
        #Check if it's the case that an experiment name was selected
        parentSelectedItem = selectedItem.parent()
        if (parentSelectedItem == None):
            #A base widget was selected
            successfilenames = ExperimentRemoveFileDialog(
            ).experimentRemoveFileDialog(selectedItemName)
            if successfilenames == [] or successfilenames == "":
                logging.debug(
                    "removeExperimentItemActionEvent(): Canceled or a file could not be removed. Try again later or check permissions"
                )
                return

            self.experimentTree.invisibleRootItem().removeChild(selectedItem)
            self.basedataStackedWidget.removeWidget(
                self.baseWidgets[selectedItemName]["BaseWidget"])
            del self.baseWidgets[selectedItemName]
            self.experimentActionsWidget.removeExperimentItem(selectedItemName)
            self.experimentActionsWidget.removeExperimentItem(selectedItemName)
            self.statusBar.showMessage("Removed experiment: " +
                                       str(selectedItemName))
        else:
            #Check if it's the case that a VM Name was selected
            if (selectedItem.text(0)[0] == "V"):
                parentSelectedItem.removeChild(selectedItem)
                configname = parentSelectedItem.text(0)
                self.basedataStackedWidget.removeWidget(
                    self.baseWidgets[configname]["VMWidgets"][
                        selectedItem.text(0)])
                del self.baseWidgets[configname]["VMWidgets"][
                    selectedItem.text(0)]
                self.statusBar.showMessage("Removed VM: " +
                                           str(selectedItemName) +
                                           " from experiment: " +
                                           str(parentSelectedItem.text(0)))
                #Also remove from the experiment action widget:
                config_jsondata = self.getWritableData(configname)
                self.experimentActionsWidget.resetExperiment(
                    configname, config_jsondata=config_jsondata)
                self.connectionWidget.resetExperiment(
                    configname, config_jsondata=config_jsondata)

            #Check if it's the case that a Material Name was selected
            elif (selectedItem.text(0)[0] == "M"):
                materialName = selectedItemName.split("M: ")[1]
                successfilenames = MaterialRemoveFileDialog(
                ).materialRemoveFileDialog(parentSelectedItem.text(0),
                                           materialName)
                if successfilenames == []:
                    logging.debug(
                        "Canceled or a file could not be removed. Try again later or check permissions"
                    )
                    return
                parentSelectedItem.removeChild(selectedItem)
                self.basedataStackedWidget.removeWidget(
                    self.baseWidgets[parentSelectedItem.text(
                        0)]["MaterialWidgets"][selectedItem.text(0)])
                del self.baseWidgets[parentSelectedItem.text(
                    0)]["MaterialWidgets"][selectedItem.text(0)]
                self.statusBar.showMessage("Removed Material: " +
                                           str(materialName) +
                                           " from experiment: " +
                                           str(parentSelectedItem.text(0)))

    def exportActionEvent(self):
        logging.debug("MainApp:exportActionEvent() instantiated")
        #Check if it's the case that an experiment name was selected
        selectedItem = self.experimentTree.currentItem()
        if selectedItem == None:
            logging.debug("MainApp:exportActionEvent no configurations left")
            self.statusBar.showMessage(
                "Could not export experiment. No configuration items selected or available."
            )
            return
        selectedItemName = selectedItem.text(0)

        folderChosen = PackageExportDialog().packageExportDialog(
            self, selectedItemName)
        if folderChosen == []:
            logging.debug(
                "exportActionEvent(): Canceled or the experiment could not be exported. Check folder permissions."
            )
            return
        folderChosen = os.path.basename(folderChosen[0])

        logging.debug("MainApp: exportActionEvent(): File choosen: " +
                      folderChosen)
        #Add the items to the tree

        self.statusBar.showMessage("Exported to " + folderChosen)

    def editPathActionEvent(self):
        logging.debug("MainApp:editPathActionEvent() instantiated")
        result = ConfigurationDialog(self).exec_()

    def closeEvent(self, event):
        logging.debug("MainApp:closeEvent(): instantiated")
        logging.debug("closeEvent(): returning accept")
        event.accept()
        qApp.quit()
        return

    def initMenu(self):

        self.mainMenu = QMenuBar()
        self.fileMenu = self.mainMenu.addMenu("File")
        self.editMenu = self.mainMenu.addMenu("Edit")
        self.hypervisorMenu = self.mainMenu.addMenu("Hypervisor")

        self.newExperimentMenuButton = QAction(QIcon(), "New Experiment", self)
        self.newExperimentMenuButton.setShortcut("Ctrl+N")
        self.newExperimentMenuButton.setStatusTip("Create New Experiment")
        self.newExperimentMenuButton.triggered.connect(
            self.addExperimentActionEvent)
        self.fileMenu.addAction(self.newExperimentMenuButton)

        self.importExperimentMenuButton = QAction(QIcon(), "Import Experiment",
                                                  self)
        self.importExperimentMenuButton.setShortcut("Ctrl+I")
        self.importExperimentMenuButton.setStatusTip(
            "Import Experiment from RES File")
        self.importExperimentMenuButton.triggered.connect(
            self.importActionEvent)
        self.fileMenu.addAction(self.importExperimentMenuButton)

        self.saveExperimentMenuButton = QAction(QIcon(), "Save Experiment",
                                                self)
        self.saveExperimentMenuButton.setShortcut("Ctrl+I")
        self.saveExperimentMenuButton.setStatusTip(
            "Save currently selected experiment")
        self.saveExperimentMenuButton.triggered.connect(
            self.saveExperimentButton)
        self.saveExperimentMenuButton.setEnabled(False)
        self.fileMenu.addAction(self.saveExperimentMenuButton)

        self.exitMenuButton = QAction(QIcon("exit24.png"), "Exit", self)
        self.exitMenuButton.setShortcut("Ctrl+Q")
        self.exitMenuButton.setStatusTip("Exit application")
        self.exitMenuButton.triggered.connect(self.close)
        self.fileMenu.addAction(self.exitMenuButton)

        self.pathMenuButton = QAction(QIcon(), "Edit Paths", self)
        self.pathMenuButton.setShortcut("Ctrl+E")
        self.pathMenuButton.setStatusTip("Edit Paths")
        self.pathMenuButton.triggered.connect(self.editPathActionEvent)
        self.editMenu.addAction(self.pathMenuButton)

        self.startHypervisorMenuButton = QAction(QIcon(),
                                                 "Instantiate Hypervisor",
                                                 self)
        self.startHypervisorMenuButton.setShortcut("Ctrl+O")
        self.startHypervisorMenuButton.setStatusTip(
            "Start the hypervisor that is currently configured")
        self.startHypervisorMenuButton.triggered.connect(
            self.startHypervisorActionEvent)
        self.hypervisorMenu.addAction(self.startHypervisorMenuButton)

    def getWritableData(self, configname):
        logging.debug("MainApp: getWritableData() instantiated")
        jsondata = {}
        jsondata["xml"] = {}
        #get baseWidget data
        baseWidget = self.baseWidgets[configname]["BaseWidget"]
        ###TODO: make this work for multiple experiments (current testing assumes only one)
        if isinstance(baseWidget, BaseWidget):
            jsondata["xml"] = baseWidget.getWritableData()
        ###Setup the dictionary
        if "testbed-setup" not in jsondata["xml"]:
            jsondata["xml"]["testbed-setup"] = {}
        if "vm-set" not in jsondata["xml"]["testbed-setup"]:
            jsondata["xml"]["testbed-setup"]["vm-set"] = {}
        if "vm" not in jsondata["xml"]["testbed-setup"]["vm-set"]:
            jsondata["xml"]["testbed-setup"]["vm-set"]["vm"] = []
        if "material" not in jsondata["xml"]["testbed-setup"]["vm-set"]:
            jsondata["xml"]["testbed-setup"]["vm-set"]["material"] = []

        for vmData in self.baseWidgets[configname]["VMWidgets"].values():
            jsondata["xml"]["testbed-setup"]["vm-set"]["vm"].append(
                vmData.getWritableData())
        for materialData in self.baseWidgets[configname][
                "MaterialWidgets"].values():
            jsondata["xml"]["testbed-setup"]["vm-set"]["material"].append(
                materialData.getWritableData())
        return jsondata

    def saveExperimentButton(self):
        logging.debug("MainApp: saveExperiment() instantiated")
        self.saveExperiment()

    def saveExperiment(self, configname=None):
        logging.debug("MainApp: saveExperiment() instantiated")
        selectedItem = self.experimentTree.currentItem()
        if selectedItem == None:
            logging.debug("MainApp:onItemSelected no configurations left")
            self.statusBar.showMessage(
                "Could not save. No configuration items selected or available."
            )
            return
        #Check if it's the case that an experiment name was selected
        parentSelectedItem = selectedItem.parent()
        if parentSelectedItem != None:
            selectedItem = parentSelectedItem
        configname = selectedItem.text(0)
        jsondata = self.getWritableData(configname)

        self.ec.writeExperimentXMLFileData(jsondata, configname)
        self.ec.writeExperimentJSONFileData(jsondata, configname)
        self.ec.getExperimentVMRolledOut(configname,
                                         jsondata,
                                         force_refresh=True)
        res = self.ec.getExperimentServerInfo(configname)
        #Now reset the experimentActions view
        self.experimentActionsWidget.resetExperiment(configname, jsondata)
        self.connectionWidget.resetExperiment(configname, jsondata)
        self.statusBar.showMessage(
            "Succesfully saved experiment file for " + str(configname), 2000)
예제 #25
0
class MainWindow(QMainWindow, metaclass=QSingleton):

    new_session = pyqtSignal()
    save_session = pyqtSignal(str)
    open_session = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.setMinimumSize(500, 400)

        self._cue_add_menu = {}
        self.layout = None

        # Status Bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)
        MainActionsHandler().action_done.connect(self._action_done)
        MainActionsHandler().action_undone.connect(self._action_undone)
        MainActionsHandler().action_redone.connect(self._action_redone)

        # Menubar
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 0, 25))
        self.menubar.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)

        self.menuFile = QMenu(self.menubar)
        self.menuEdit = QMenu(self.menubar)
        self.menuLayout = QMenu(self.menubar)
        self.menuTools = QMenu(self.menubar)
        self.menuAbout = QMenu(self.menubar)

        self.menubar.addMenu(self.menuFile)
        self.menubar.addMenu(self.menuEdit)
        self.menubar.addMenu(self.menuLayout)
        self.menubar.addMenu(self.menuTools)
        self.menubar.addMenu(self.menuAbout)

        self.setMenuBar(self.menubar)

        # menuFile
        self.newSessionAction = QAction(self)
        self.newSessionAction.triggered.connect(self._new_session)
        self.openSessionAction = QAction(self)
        self.openSessionAction.triggered.connect(self._load_from_file)
        self.saveSessionAction = QAction(self)
        self.saveSessionAction.triggered.connect(self._save)
        self.saveSessionWithName = QAction(self)
        self.saveSessionWithName.triggered.connect(self._save_with_name)
        self.editPreferences = QAction(self)
        self.editPreferences.triggered.connect(self._show_preferences)
        self.fullScreenAction = QAction(self)
        self.fullScreenAction.triggered.connect(self._fullscreen)
        self.fullScreenAction.setCheckable(True)
        self.exitAction = QAction(self)
        self.exitAction.triggered.connect(self._exit)

        self.menuFile.addAction(self.newSessionAction)
        self.menuFile.addAction(self.openSessionAction)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.saveSessionAction)
        self.menuFile.addAction(self.saveSessionWithName)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.editPreferences)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.fullScreenAction)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.exitAction)

        # menuEdit
        self.actionUndo = QAction(self)
        self.actionUndo.triggered.connect(MainActionsHandler().undo_action)
        self.actionRedo = QAction(self)
        self.actionRedo.triggered.connect(MainActionsHandler().redo_action)
        self.multiEdit = QAction(self)
        self.selectAll = QAction(self)
        self.deselectAll = QAction(self)
        self.invertSelection = QAction(self)

        self.cueSeparator = self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.actionUndo)
        self.menuEdit.addAction(self.actionRedo)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.selectAll)
        self.menuEdit.addAction(self.deselectAll)
        self.menuEdit.addAction(self.invertSelection)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.multiEdit)

        # menuAbout
        self.actionAbout = QAction(self)
        self.actionAbout.triggered.connect(about.About(self).show)

        self.actionAbout_Qt = QAction(self)
        self.actionAbout_Qt.triggered.connect(qApp.aboutQt)

        self.menuAbout.addAction(self.actionAbout)
        self.menuAbout.addSeparator()
        self.menuAbout.addAction(self.actionAbout_Qt)

        # Set component text
        self.retranslateUi()
        # The save file name
        self.filename = ''

    def retranslateUi(self):
        self.setWindowTitle('Linux Show Player')
        # menuFile
        self.menuFile.setTitle("&File")
        self.newSessionAction.setText("New session")
        self.newSessionAction.setShortcut("CTRL+N")
        self.openSessionAction.setText("Open")
        self.openSessionAction.setShortcut("CTRL+O")
        self.saveSessionAction.setText("Save session")
        self.saveSessionAction.setShortcut("CTRL+S")
        self.editPreferences.setText("Preferences")
        self.editPreferences.setShortcut("CTRL+P")
        self.saveSessionWithName.setText("Save with name")
        self.saveSessionWithName.setShortcut('CTRL+SHIFT+S')
        self.fullScreenAction.setText('Toggle fullscreen')
        self.fullScreenAction.setShortcut('F11')
        self.exitAction.setText("Exit")
        # menuEdit
        self.menuEdit.setTitle("&Edit")
        self.actionUndo.setText('Undo')
        self.actionUndo.setShortcut('CTRL+Z')
        self.actionRedo.setText('Redo')
        self.actionRedo.setShortcut('CTRL+Y')
        self.selectAll.setText("Select all")
        self.selectAll.setShortcut("CTRL+A")
        self.deselectAll.setText("Deselect all")
        self.deselectAll.setShortcut("CTRL+SHIFT+A")
        self.invertSelection.setText("Invert selection")
        self.invertSelection.setShortcut("CTRL+I")
        self.multiEdit.setText("Edit selected media")
        self.multiEdit.setShortcut("CTRL+SHIFT+E")
        # menuLayout
        self.menuLayout.setTitle("&Layout")
        # menuTools
        self.menuTools.setTitle("&Tools")
        self.multiEdit.setText("Edit selected media")
        # menuAbout
        self.menuAbout.setTitle("&About")
        self.actionAbout.setText("About")
        self.actionAbout_Qt.setText("About Qt")

    def set_layout(self, layout):
        if self.layout is not None:
            self.takeCentralWidget().hide()

            self.multiEdit.triggered.disconnect()
            self.selectAll.triggered.disconnect()
            self.deselectAll.triggered.disconnect()
            self.invertSelection.triggered.disconnect()

        self.layout = layout
        self.setCentralWidget(self.layout)
        self.layout.show()

        self.multiEdit.triggered.connect(self.layout.edit_selected_cues)
        self.selectAll.triggered.connect(self.layout.select_all)
        self.deselectAll.triggered.connect(self.layout.deselect_all)
        self.invertSelection.triggered.connect(self.layout.invert_selection)

    def contextMenuEvent(self, event):
        if self.layout.geometry().contains(event.pos()):
            self.menuEdit.move(event.globalPos())
            self.menuEdit.show()

            # Adjust the menu position
            desktop = qApp.desktop().availableGeometry()
            menu_rect = self.menuEdit.geometry()
    
            if menu_rect.bottom() > desktop.bottom():
                self.menuEdit.move(self.menuEdit.x(),
                                   self.menuEdit.y() - self.menuEdit.height())
            if menu_rect.right() > desktop.right():
                self.menuEdit.move(self.menuEdit.x() - self.menuEdit.width(),
                                   self.menuEdit.y())

    def closeEvent(self, event):
        self._exit()
        event.ignore()

    def register_cue_menu_action(self, name, function, category='', shortcut=''):
        """Register a new-cue choice for the edit-menu

        param name: The name for the MenuAction
        param function: The function that add the new cue(s)
        param category: The optional menu where insert the MenuAction
        param shortcut: An optional shortcut for the MenuAction
        """
        action = QAction(self)
        action.setText(name)
        action.triggered.connect(function)
        if shortcut != '':
            action.setShortcut(shortcut)

        if category != '':
            if category not in self._cue_add_menu:
                menu = QMenu(category, self)
                self._cue_add_menu[category] = menu
                self.menuEdit.insertMenu(self.cueSeparator, menu)

            self._cue_add_menu[category].addAction(action)
        else:
            self.menuEdit.insertAction(self.cueSeparator, action)

    def update_window_title(self):
        saved = MainActionsHandler().is_saved()
        if not saved and not self.windowTitle()[0] == '*':
            self.setWindowTitle('*' + self.windowTitle())
        elif saved and self.windowTitle()[0] == '*':
            self.setWindowTitle(self.windowTitle()[1:])

    def _action_done(self, action):
        self.statusBar.showMessage(action.log())
        self.update_window_title()

    def _action_undone(self, action):
        self.statusBar.showMessage('Undone: ' + action.log())
        self.update_window_title()

    def _action_redone(self, action):
        self.statusBar.showMessage('Redone: ' + action.log())
        self.update_window_title()

    def _save(self):
        if self.filename == '':
            self._save_with_name()
        else:
            self.save_session.emit(self.filename)

    def _save_with_name(self):
        filename, _ = QFileDialog.getSaveFileName(parent=self,
                                                  filter='*.lsp',
                                                  directory=os.getenv('HOME'))
        if filename != '':
            if not filename.endswith('.lsp'):
                filename += '.lsp'
            self.filename = filename
            self._save()

    def _show_preferences(self):
        prefUi = AppSettings(configuration.config_to_dict(), parent=self)
        prefUi.exec_()

        if prefUi.result() == QDialog.Accepted:
            configuration.update_config_from_dict(prefUi.get_configuraton())

    def _load_from_file(self):
        if self._check_saved():
            path, _ = QFileDialog.getOpenFileName(filter='*.lsp',
                                                  directory=os.getenv('HOME'))

            if os.path.exists(path):
                self.open_session.emit(path)
                self.filename = path

    def _new_session(self):
        if self._check_saved():
            self.new_session.emit()

    def _check_saved(self):
        if not MainActionsHandler().is_saved():
            msgBox = QMessageBox(self)
            msgBox.setIcon(QMessageBox.Warning)
            msgBox.setWindowTitle('Close session')
            msgBox.setText('The current session is not saved.')
            msgBox.setInformativeText('Discard the changes?')
            msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Discard |
                                       QMessageBox.Cancel)
            msgBox.setDefaultButton(QMessageBox.Save)

            result = msgBox.exec_()
            if result == QMessageBox.Cancel:
                return False
            elif result == QMessageBox.Save:
                self._save()

        return True

    def _fullscreen(self, enable):
        if enable:
            self.showFullScreen()
        else:
            self.showMaximized()

    def _exit(self):
        if self._check_saved():
            qApp.quit()
class Player(QtWidgets.QMainWindow):
    def __init__(self, muted=False, save_frames=False, master=None):
        QtWidgets.QMainWindow.__init__(self, master)
        self.setWindowIcon(QIcon("icons/app.svg"))
        self.title = "Bilkent Video Annotation Tool"

        self.muted = muted
        self.save_frames = save_frames

        self.setWindowTitle(self.title)
        options = QFileDialog.Options()
        options |= QFileDialog.ShowDirsOnly
        options |= QFileDialog.Directory

        # options |= QFileDialog.DontUseNativeDialog

        supported_formats = [
            ".mp3", ".mp4", ".avi", ".wmv", ".mp4", ".mov", ".ogg", ".wav",
            ".ogm"
        ]

        self.video_paths = []
        while len(self.video_paths) == 0:
            videos_dir = str(
                QFileDialog.getExistingDirectory(self,
                                                 "Select Videos Directory",
                                                 options=options))
            self.video_paths = []
            for fmt in supported_formats:
                self.video_paths += [
                    f for f in glob.glob(videos_dir + "**/*" + fmt,
                                         recursive=False)
                ]
            print(self.video_paths)

            if len(self.video_paths) == 0 or len(videos_dir) == 0:
                QtWidgets.QMessageBox.question(
                    self, 'No videos exist',
                    "Please select a directory containing videos.",
                    QtWidgets.QMessageBox.Ok)

        self.annotations_dir = ""
        while len(self.annotations_dir) == 0:
            self.annotations_dir = str(
                QFileDialog.getExistingDirectory(
                    self, "Select Annotations Directory", options=options))
            print(self.annotations_dir)
            self.annotation_paths = [
                f for f in glob.glob(self.annotations_dir + "**/*.json",
                                     recursive=False)
            ]
            if len(self.annotations_dir) == 0:
                QtWidgets.QMessageBox.question(
                    self, 'No directory selected.',
                    "Please select a directory for annotations",
                    QtWidgets.QMessageBox.Ok)

        self.num_videos = len(self.video_paths)
        self.current_video = 0

        self.annotations = {}

        for annotation_path in self.annotation_paths:
            j = json.load(open(annotation_path, "r"))
            self.annotations[j["name"]] = j

        print(self.annotation_paths)

        self.createVideoPlayer()

        self.createUI()

        self.createToolbar()

        self.statusbar = QStatusBar(self)

        self.setStatusBar(self.statusbar)

        self.current_annotation = "A"

        self.statusbar.showMessage("Current Annotation: " +
                                   self.current_annotation)

        self.createShortcuts()

        is_video_set = False
        for i, video_path in enumerate(self.video_paths):

            if "\\" in video_path:
                video_name = video_path.split("\\")[-1]
            else:
                video_name = video_path.split("/")[-1]

            if video_name not in self.annotations:
                self.file = self.OpenFile(video_path)

                self.current_video_attrs = self.annotations.get(
                    video_name, {
                        "name": video_name,
                        "path": video_path,
                        "annotations": {}
                    })
                self.annotations[self.current_video_attrs[
                    "name"]] = self.current_video_attrs
                self.current_video = i

                is_video_set = True

                break

        if not is_video_set:
            video_path = self.video_paths[0]
            if "\\" in video_path:
                video_name = video_path.split("\\")[-1]
            else:
                video_name = video_path.split("/")[-1]
            self.file = self.OpenFile(video_path)
            self.current_video_attrs = self.annotations.get(
                video_name, {
                    "name": video_name,
                    "path": video_path,
                    "annotations": {}
                })

            self.annotations[
                self.current_video_attrs["name"]] = self.current_video_attrs

        self.play()

        self.next_visible = True
        self.prev_visible = True
        self.setVisibilities()

    def setPrevNextVisibility(self):
        self.prev_visible = self.current_video != 0
        self.next_visible = self.current_video != self.num_videos - 1
        self.remove_visible = self.current_video_attrs[
            "name"] in self.annotations and len(self.annotations[
                self.current_video_attrs["name"]]["annotations"]) > 0

        self.action_previous.setVisible(self.prev_visible)
        self.action_next.setVisible(self.next_visible)
        self.action_remove_annotations.setVisible(self.remove_visible)
        self.statusbar.clearMessage()
        self.statusbar.showMessage("Current Annotation: " +
                                   self.current_annotation)

    def createShortcuts(self):
        self.shortcut_playpause = QShortcut(QKeySequence(QtCore.Qt.Key_Return),
                                            self)
        self.shortcut_playpause.activated.connect(self.playPauseShortcut)

        self.shortcut_previous = QShortcut(QKeySequence(QtCore.Qt.Key_Left),
                                           self)
        self.shortcut_previous.activated.connect(self.previousShortcut)

        self.shortcut_next = QShortcut(QKeySequence(QtCore.Qt.Key_Right), self)
        self.shortcut_next.activated.connect(self.nextShortcut)

        self.shortcut_annotate = QShortcut(QKeySequence(QtCore.Qt.Key_Space),
                                           self)
        self.shortcut_annotate.activated.connect(self.annotate)

        self.shortcut_remove_annotation = QShortcut(
            QKeySequence(QtCore.Qt.Key_Backspace), self)
        self.shortcut_remove_annotation.activated.connect(
            self.removeAnnotations)

        for s in string.ascii_uppercase:
            key = getattr(QtCore.Qt, "Key_" + s)
            shortcut = QShortcut(QKeySequence(key), self)
            shortcut.activated.connect(self.changeAnnotationShortcut(s))

    def changeAnnotationShortcut(self, s):
        def annotationShortcut():
            self.current_annotation = s
            self.statusbar.clearMessage()
            self.statusbar.showMessage("Current Annotation: " +
                                       self.current_annotation)

        return annotationShortcut

    def removeAnnotations(self):

        self.current_video_attrs["annotations"] = {}
        self.annotations[
            self.current_video_attrs["name"]] = self.current_video_attrs

        self.setVisibilities()

    def previousShortcut(self):
        if self.prev_visible:
            self.previous()

    def nextShortcut(self):
        if self.next_visible:
            self.next()

    def setVisibilities(self):
        self.setPrevNextVisibility()

        self.markwidget.setAnnotations(
            self.annotations[self.current_video_attrs["name"]]["annotations"])

    def annotate(self):

        self.current_video_attrs["annotations"][self.current_annotation] = [
            self.mediaplayer.get_position()
        ] + self.current_video_attrs["annotations"].get(
            self.current_annotation, [])

        self.annotations[
            self.current_video_attrs["name"]] = self.current_video_attrs

        self.setVisibilities()

        if self.save_frames:
            self.writeFrameToFile()

    def writeFrameToFile(self):
        path_to_save = os.path.join(self.annotations_dir,
                                    self.current_annotation)
        if not os.path.exists(path_to_save):
            os.mkdir(path_to_save)

        frame_file_name = os.path.join(
            path_to_save,
            f'{self.current_video_attrs["name"]}_{str(self.mediaplayer.get_position())}'
            .replace(".", "_") + '.png')

        self.mediaplayer.video_take_snapshot(0, frame_file_name, 0, 0)

    def saveAnnotation(self, annotation):
        with open(
                os.path.join(self.annotations_dir,
                             annotation["name"] + ".json"), "w+") as f:
            json.dump(annotation, f)

    def playPauseShortcut(self):
        if self.isPaused:
            self.play()
        else:
            self.pause()

    def createVideoPlayer(self):

        self.instance = vlc.Instance()

        self.mediaplayer = self.instance.media_player_new()

        if self.muted:
            self.mediaplayer.audio_set_volume(0)

        self.isPaused = False

    def createToolbar(self):
        toolbar = QToolBar("Manage Video")
        toolbar.setIconSize(QSize(32, 32))

        self.addToolBar(toolbar)

        self.action_play = QAction(QIcon("icons/play-button.png"), "Play",
                                   self)
        self.action_play.triggered.connect(self.play)
        self.action_play.setStatusTip("Play Video [Enter Key]")
        toolbar.addAction(self.action_play)

        self.action_pause = QAction(QIcon("icons/pause.png"), "Pause", self)
        self.action_pause.triggered.connect(self.pause)
        self.action_pause.setVisible(False)
        self.action_pause.setStatusTip("Pause Video [Enter Key]")
        toolbar.addAction(self.action_pause)

        self.action_previous = QAction(QIcon("icons/previous.png"),
                                       "Previous Video", self)
        self.action_previous.setStatusTip("Previous Video [Left Arrow]")
        self.action_previous.triggered.connect(self.previous)
        toolbar.addAction(self.action_previous)

        self.action_next = QAction(QIcon("icons/next.png"), "Next Video", self)
        self.action_next.triggered.connect(self.next)
        self.action_next.setStatusTip("Next Video [Right Arrow]")
        toolbar.addAction(self.action_next)

        self.action_annotate = QAction(
            QIcon("icons/plus.png"), "Annotate to current frame of the video",
            self)
        self.action_annotate.triggered.connect(self.annotate)
        self.action_annotate.setStatusTip(
            "Annotate to current frame of the video [Space Key]")
        toolbar.addAction(self.action_annotate)

        self.action_remove_annotations = QAction(
            QIcon("icons/cancel.png"), "Remove current video's annotations",
            self)
        self.action_remove_annotations.triggered.connect(
            self.removeAnnotations)
        self.action_remove_annotations.setStatusTip(
            "Remove current video's annotations [Backspace Key]")
        toolbar.addAction(self.action_remove_annotations)

    def play(self):
        print("Play clicked")
        self.PlayPause()

    def pause(self):
        print("Pause clicked")
        self.PlayPause()

    def previous(self):
        print("Previous clicked")

        if self.current_video - 1 < 0:
            return

        self.saveAnnotation(self.current_video_attrs)

        if not self.isPaused:
            self.Stop()

        self.current_video -= 1
        video_path = self.video_paths[self.current_video]
        if "\\" in video_path:
            video_name = video_path.split("\\")[-1]
        else:
            video_name = video_path.split("/")[-1]

        self.file = self.OpenFile(video_path)

        if video_name in self.annotations:
            self.current_video_attrs = self.annotations[video_name]
        else:
            self.current_video_attrs = {
                "name": video_name,
                "path": video_path,
                "annotations": {}
            }

            self.annotations[video_name] = self.current_video_attrs

        self.progress.setValue(self.current_video)

        self.setVisibilities()
        self.play()

    def next(self):
        print("Next clicked")

        self.saveAnnotation(self.current_video_attrs)

        if not self.isPaused:
            self.Stop()

        self.current_video += 1

        if self.current_video == self.num_videos:
            QtWidgets.QMessageBox.question(
                self, "No more videos left.",
                "All videos are annotated. Now, opening the first video...",
                QtWidgets.QMessageBox.Ok)
            self.current_video = 0

        video_path = self.video_paths[self.current_video]

        if "\\" in video_path:
            video_name = video_path.split("\\")[-1]
        else:
            video_name = video_path.split("/")[-1]

        self.file = self.OpenFile(video_path)

        if video_name in self.annotations:
            self.current_video_attrs = self.annotations[video_name]
        else:
            self.current_video_attrs = {
                "name": video_name,
                "path": video_path,
                "annotations": {}
            }

            self.annotations[video_name] = self.current_video_attrs

        self.progress.setValue(self.current_video)

        self.setVisibilities()
        self.play()

    def createUI(self):
        """Set up the user interface, signals & slots
        """
        self.widget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.widget)

        # In this widget, the video will be drawn
        # if sys.platform == "darwin": # for MacOS
        #     self.videoframe = QtWidgets.QMacCocoaViewContainer(0)
        # else:
        #     self.videoframe = QtWidgets.QFrame()
        self.videoframe = QtWidgets.QFrame()
        self.palette = self.videoframe.palette()
        self.palette.setColor(QtGui.QPalette.Window, QtGui.QColor(0, 0, 0))
        self.videoframe.setPalette(self.palette)
        self.videoframe.setAutoFillBackground(True)

        self.positionslider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.positionslider.setToolTip("Position")
        self.positionslider.setMaximum(1000)
        self.positionslider.sliderMoved.connect(self.setPosition)

        self.vboxlayout = QtWidgets.QVBoxLayout()
        self.vboxlayout.addWidget(self.videoframe)
        self.vboxlayout.addWidget(self.positionslider)

        self.markwidget = MarkWidget()

        self.vboxlayout.addWidget(self.markwidget)

        self.widget.setLayout(self.vboxlayout)

        self.progress = QtWidgets.QProgressBar(self)
        self.progress.setMaximum(self.num_videos)
        self.vboxlayout.addWidget(self.progress)

        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(100)
        self.timer.timeout.connect(self.updateUI)

    def PlayPause(self):
        """Toggle play/pause status
        """
        if self.mediaplayer.is_playing():
            self.mediaplayer.pause()
            self.action_play.setVisible(True)
            self.action_pause.setVisible(False)
            self.isPaused = True
        else:
            self.mediaplayer.play()
            self.action_play.setVisible(False)
            self.action_pause.setVisible(True)
            self.timer.start()
            self.isPaused = False

    def Stop(self):
        """Stop player
        """
        self.mediaplayer.stop()

    def OpenFile(self, filename=None):
        """Open a media file in a MediaPlayer
        """
        if filename is None or filename is False:
            print("Attempt to openup OpenFile")
            filenameraw = QtWidgets.QFileDialog.getOpenFileName(
                self, "Open File", os.path.expanduser('~'))
            filename = filenameraw[0]

        if not filename:
            return

        # create the media
        if sys.version < '3':
            filename = unicode(filename)
        self.media = self.instance.media_new(filename)
        # put the media in the media player
        self.mediaplayer.set_media(self.media)

        # parse the metadata of the file
        self.media.parse()
        # set the title of the track as window title
        self.setWindowTitle(self.title + " | " + self.media.get_meta(0))

        # the media player has to be 'connected' to the QFrame
        # (otherwise a video would be displayed in it's own window)
        # this is platform specific!
        # you have to give the id of the QFrame (or similar object) to
        # vlc, different platforms have different functions for this
        if sys.platform.startswith('linux'):  # for Linux using the X Server
            self.mediaplayer.set_xwindow(self.videoframe.winId())
        elif sys.platform == "win32":  # for Windows
            self.mediaplayer.set_hwnd(self.videoframe.winId())
        elif sys.platform == "darwin":  # for MacOS
            self.mediaplayer.set_nsobject(int(self.videoframe.winId()))

    def setPosition(self, position):
        """Set the position
        """
        # setting the position to where the slider was dragged
        self.mediaplayer.set_position(position / 1000.0)
        # the vlc MediaPlayer needs a float value between 0 and 1, Qt
        # uses integer variables, so you need a factor; the higher the
        # factor, the more precise are the results
        # (1000 should be enough)

    def updateUI(self):
        """updates the user interface"""
        # setting the slider to the desired position
        self.positionslider.setValue(self.mediaplayer.get_position() * 1000)

        if not self.mediaplayer.is_playing():
            # no need to call this function if nothing is played
            self.timer.stop()

            if not self.isPaused:
                self.Stop()
                self.next()
예제 #27
0
class MainWindow_Ui(QMainWindow):
    def __init__(self, persepolis_setting):
        super().__init__()
        # MainWindow
        self.persepolis_setting = persepolis_setting

        icons = ':/' + \
            str(self.persepolis_setting.value('settings/icons')) + '/'

        self.setWindowTitle("Persepolis Download Manager")
        self.setWindowIcon(
            QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg')))

        self.centralwidget = QWidget(self)
        self.verticalLayout = QVBoxLayout(self.centralwidget)
        # enable drag and drop
        self.setAcceptDrops(True)
        # frame
        self.frame = QFrame(self.centralwidget)

        # download_table_horizontalLayout
        download_table_horizontalLayout = QHBoxLayout()
        tabels_splitter = QSplitter(Qt.Horizontal)
        # category_tree
        self.category_tree_qwidget = QWidget(self)
        category_tree_verticalLayout = QVBoxLayout()
        self.category_tree = CategoryTreeView(self)
        category_tree_verticalLayout.addWidget(self.category_tree)

        self.category_tree_model = QStandardItemModel()
        self.category_tree.setModel(self.category_tree_model)
        category_table_header = ['Category']
        self.category_tree_model.setHorizontalHeaderLabels(
            category_table_header)
        self.category_tree.header().setStretchLastSection(True)

        # queue_panel
        self.queue_panel_widget = QWidget(self)

        queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget)
        # queue_panel_show_button
        self.queue_panel_show_button = QPushButton(self)

        queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button)
        # queue_panel_widget_frame
        self.queue_panel_widget_frame = QFrame(self)
        self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel)
        self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised)

        queue_panel_verticalLayout_main.addWidget(
            self.queue_panel_widget_frame)

        queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame)
        queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1)

        # start_end_frame
        self.start_end_frame = QFrame(self)

        # start time
        start_verticalLayout = QVBoxLayout(self.start_end_frame)
        self.start_checkBox = QCheckBox(self)
        start_verticalLayout.addWidget(self.start_checkBox)

        self.start_frame = QFrame(self)
        self.start_frame.setFrameShape(QFrame.StyledPanel)
        self.start_frame.setFrameShadow(QFrame.Raised)

        start_frame_verticalLayout = QVBoxLayout(self.start_frame)

        self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame)
        self.start_time_qDataTimeEdit.setDisplayFormat('H:mm')
        start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit)

        start_verticalLayout.addWidget(self.start_frame)
        # end time

        self.end_checkBox = QCheckBox(self)
        start_verticalLayout.addWidget(self.end_checkBox)

        self.end_frame = QFrame(self)
        self.end_frame.setFrameShape(QFrame.StyledPanel)
        self.end_frame.setFrameShadow(QFrame.Raised)

        end_frame_verticalLayout = QVBoxLayout(self.end_frame)

        self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame)
        self.end_time_qDateTimeEdit.setDisplayFormat('H:mm')
        end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit)

        start_verticalLayout.addWidget(self.end_frame)

        self.reverse_checkBox = QCheckBox(self)
        start_verticalLayout.addWidget(self.reverse_checkBox)

        queue_panel_verticalLayout.addWidget(self.start_end_frame)

        # limit_after_frame
        self.limit_after_frame = QFrame(self)
        # limit_checkBox
        limit_verticalLayout = QVBoxLayout(self.limit_after_frame)
        self.limit_checkBox = QCheckBox(self)
        limit_verticalLayout.addWidget(self.limit_checkBox)
        # limit_frame
        self.limit_frame = QFrame(self)
        self.limit_frame.setFrameShape(QFrame.StyledPanel)
        self.limit_frame.setFrameShadow(QFrame.Raised)
        limit_verticalLayout.addWidget(self.limit_frame)

        limit_frame_verticalLayout = QVBoxLayout(self.limit_frame)
        # limit_spinBox
        limit_frame_horizontalLayout = QHBoxLayout()
        self.limit_spinBox = QDoubleSpinBox(self)
        self.limit_spinBox.setMinimum(1)
        self.limit_spinBox.setMaximum(1023)
        limit_frame_horizontalLayout.addWidget(self.limit_spinBox)
        # limit_comboBox
        self.limit_comboBox = QComboBox(self)
        self.limit_comboBox.addItem("")
        self.limit_comboBox.addItem("")
        limit_frame_horizontalLayout.addWidget(self.limit_comboBox)
        limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout)
        # limit_pushButton
        self.limit_pushButton = QPushButton(self)
        limit_frame_verticalLayout.addWidget(self.limit_pushButton)

        # after_checkBox
        self.after_checkBox = QtWidgets.QCheckBox(self)
        limit_verticalLayout.addWidget(self.after_checkBox)
        # after_frame
        self.after_frame = QtWidgets.QFrame(self)
        self.after_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.after_frame.setFrameShadow(QtWidgets.QFrame.Raised)
        limit_verticalLayout.addWidget(self.after_frame)

        after_frame_verticalLayout = QVBoxLayout(self.after_frame)
        # after_comboBox
        self.after_comboBox = QComboBox(self)
        self.after_comboBox.addItem("")

        after_frame_verticalLayout.addWidget(self.after_comboBox)
        # after_pushButton
        self.after_pushButton = QPushButton(self)
        after_frame_verticalLayout.addWidget(self.after_pushButton)

        queue_panel_verticalLayout.addWidget(self.limit_after_frame)
        category_tree_verticalLayout.addWidget(self.queue_panel_widget)

        # keep_awake_checkBox
        self.keep_awake_checkBox = QCheckBox(self)
        queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox)

        self.category_tree_qwidget.setLayout(category_tree_verticalLayout)
        tabels_splitter.addWidget(self.category_tree_qwidget)

        # download table widget
        self.download_table_content_widget = QWidget(self)
        download_table_content_widget_verticalLayout = QVBoxLayout(
            self.download_table_content_widget)

        self.download_table = DownloadTableWidget(self)
        download_table_content_widget_verticalLayout.addWidget(
            self.download_table)
        tabels_splitter.addWidget(self.download_table_content_widget)

        self.download_table.setColumnCount(13)
        self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.download_table.verticalHeader().hide()

        # hide gid and download dictioanry section
        self.download_table.setColumnHidden(8, True)
        self.download_table.setColumnHidden(9, True)

        download_table_header = [
            'File Name', 'Status', 'Size', 'Downloaded', 'Percentage',
            'Connections', 'Transfer rate', 'Estimate time left', 'Gid',
            'Link', 'First try date', 'Last try date', 'Category'
        ]
        self.download_table.setHorizontalHeaderLabels(download_table_header)

        # fixing the size of download_table when window is Maximized!
        self.download_table.horizontalHeader().setSectionResizeMode(0)
        self.download_table.horizontalHeader().setStretchLastSection(True)

        tabels_splitter.setStretchFactor(0, 3)  # category_tree width
        tabels_splitter.setStretchFactor(1, 10)  # ratio of tables's width
        download_table_horizontalLayout.addWidget(tabels_splitter)
        self.frame.setLayout(download_table_horizontalLayout)
        self.verticalLayout.addWidget(self.frame)
        self.setCentralWidget(self.centralwidget)

        # menubar
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QRect(0, 0, 600, 24))
        self.setMenuBar(self.menubar)
        fileMenu = self.menubar.addMenu('&File')
        editMenu = self.menubar.addMenu('&Edit')
        viewMenu = self.menubar.addMenu('&View')
        downloadMenu = self.menubar.addMenu('&Download')
        queueMenu = self.menubar.addMenu('&Queue')
        helpMenu = self.menubar.addMenu('&Help')

        # viewMenu submenus
        sortMenu = viewMenu.addMenu('Sort by')
        # statusbar
        self.statusbar = QStatusBar(self)
        self.setStatusBar(self.statusbar)
        self.statusbar.showMessage("Persepolis Download Manager")
        # toolBar
        self.toolBar2 = QToolBar(self)
        self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar2)
        self.toolBar2.setWindowTitle('Menu')
        self.toolBar2.setIconSize(QSize(32, 32))
        self.toolBar2.setFloatable(False)
        self.toolBar2.setMovable(False)

        self.toolBar = QToolBar(self)
        self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.toolBar.setWindowTitle('Toolbar')
        self.toolBar.setIconSize(QSize(32, 32))
        self.toolBar.setFloatable(False)
        self.toolBar.setMovable(False)

        #toolBar and menubar and actions
        self.stopAllAction = QAction(QIcon(icons + 'stop_all'),
                                     'Stop all active downloads',
                                     self,
                                     statusTip='Stop all active downloads',
                                     triggered=self.stopAllDownloads)
        downloadMenu.addAction(self.stopAllAction)

        self.sort_file_name_Action = QAction('File name',
                                             self,
                                             triggered=self.sortByName)
        sortMenu.addAction(self.sort_file_name_Action)

        self.sort_file_size_Action = QAction('File size',
                                             self,
                                             triggered=self.sortBySize)
        sortMenu.addAction(self.sort_file_size_Action)

        self.sort_first_try_date_Action = QAction(
            'First try date', self, triggered=self.sortByFirstTry)
        sortMenu.addAction(self.sort_first_try_date_Action)

        self.sort_last_try_date_Action = QAction('Last try date',
                                                 self,
                                                 triggered=self.sortByLastTry)
        sortMenu.addAction(self.sort_last_try_date_Action)

        self.sort_download_status_Action = QAction('Download status',
                                                   self,
                                                   triggered=self.sortByStatus)
        sortMenu.addAction(self.sort_download_status_Action)

        self.trayAction = QAction('Show system tray icon',
                                  self,
                                  statusTip="Show/Hide system tray icon",
                                  triggered=self.showTray)
        self.trayAction.setCheckable(True)
        viewMenu.addAction(self.trayAction)

        self.showMenuBarAction = QAction('Show menubar',
                                         self,
                                         statusTip='Show menubar',
                                         triggered=self.showMenuBar)
        self.showMenuBarAction.setCheckable(True)
        viewMenu.addAction(self.showMenuBarAction)

        self.showSidePanelAction = QAction('Show side panel',
                                           self,
                                           statusTip='Show side panel',
                                           triggered=self.showSidePanel)
        self.showSidePanelAction.setCheckable(True)
        viewMenu.addAction(self.showSidePanelAction)

        self.minimizeAction = QAction(QIcon(icons + 'minimize'),
                                      'Minimize to system tray',
                                      self,
                                      shortcut="Ctrl+W",
                                      statusTip="Minimize to system tray",
                                      triggered=self.minMaxTray)
        viewMenu.addAction(self.minimizeAction)

        self.addlinkAction = QAction(QIcon(icons + 'add'),
                                     'Add New Download Link',
                                     self,
                                     shortcut="Ctrl+N",
                                     statusTip="Add New Download Link",
                                     triggered=self.addLinkButtonPressed)
        fileMenu.addAction(self.addlinkAction)

        self.addtextfileAction = QAction(
            QIcon(icons + 'file'),
            'Import links from text file',
            self,
            statusTip='Create a Text file and put links in it.line by line!',
            triggered=self.importText)
        fileMenu.addAction(self.addtextfileAction)

        self.resumeAction = QAction(QIcon(icons + 'play'),
                                    'Resume Download',
                                    self,
                                    shortcut="Ctrl+R",
                                    statusTip="Resume Download",
                                    triggered=self.resumeButtonPressed)
        downloadMenu.addAction(self.resumeAction)

        self.pauseAction = QAction(QIcon(icons + 'pause'),
                                   'Pause Download',
                                   self,
                                   shortcut="Ctrl+C",
                                   statusTip="Pause Download",
                                   triggered=self.pauseButtonPressed)
        downloadMenu.addAction(self.pauseAction)

        self.stopAction = QAction(QIcon(icons + 'stop'),
                                  'Stop Download',
                                  self,
                                  shortcut="Ctrl+S",
                                  statusTip="Stop/Cancel Download",
                                  triggered=self.stopButtonPressed)
        downloadMenu.addAction(self.stopAction)

        self.removeAction = QAction(QIcon(icons + 'remove'),
                                    'Remove Download',
                                    self,
                                    shortcut="Ctrl+D",
                                    statusTip="Remove Download",
                                    triggered=self.removeButtonPressed)
        downloadMenu.addAction(self.removeAction)

        self.propertiesAction = QAction(QIcon(icons + 'setting'),
                                        'Properties',
                                        self,
                                        shortcut="Ctrl+P",
                                        statusTip="Properties",
                                        triggered=self.propertiesButtonPressed)
        downloadMenu.addAction(self.propertiesAction)

        self.progressAction = QAction(QIcon(icons + 'window'),
                                      'Progress',
                                      self,
                                      shortcut="Ctrl+Z",
                                      statusTip="Progress",
                                      triggered=self.progressButtonPressed)
        downloadMenu.addAction(self.progressAction)

        self.openFileAction = QAction(QIcon(icons + 'file'),
                                      'Open file',
                                      self,
                                      statusTip='Open file',
                                      triggered=self.openFile)
        fileMenu.addAction(self.openFileAction)

        self.openDownloadFolderAction = QAction(
            QIcon(icons + 'folder'),
            'Open download folder',
            self,
            statusTip='Open download folder',
            triggered=self.openDownloadFolder)
        fileMenu.addAction(self.openDownloadFolderAction)

        self.deleteFileAction = QAction(QIcon(icons + 'trash'),
                                        'Delete file',
                                        self,
                                        statusTip='Delete file',
                                        triggered=self.deleteFile)
        fileMenu.addAction(self.deleteFileAction)

        self.openDefaultDownloadFolderAction = QAction(
            QIcon(icons + 'folder'),
            'Open default download folder',
            self,
            statusTip='Open default download folder',
            triggered=self.openDefaultDownloadFolder)
        fileMenu.addAction(self.openDefaultDownloadFolderAction)

        self.exitAction = QAction(QIcon(icons + 'exit'),
                                  'Exit',
                                  self,
                                  shortcut="Ctrl+Q",
                                  statusTip="Exit",
                                  triggered=self.closeEvent)
        fileMenu.addAction(self.exitAction)

        self.clearAction = QAction(
            QIcon(icons + 'multi_remove'),
            'Clear download list',
            self,
            statusTip='Clear all items in download list',
            triggered=self.clearDownloadList)
        editMenu.addAction(self.clearAction)

        self.selectAction = QAction('Select multiple items ',
                                    self,
                                    statusTip='Select multiple items',
                                    triggered=self.selectDownloads)
        self.selectAction.setCheckable(True)
        editMenu.addAction(self.selectAction)

        self.selectAllAction = QAction(QIcon(icons + 'select_all'),
                                       'Select All',
                                       self,
                                       statusTip='Select All',
                                       triggered=self.selectAll)
        editMenu.addAction(self.selectAllAction)
        self.selectAllAction.setEnabled(False)

        self.removeSelectedAction = QAction(
            QIcon(icons + 'multi_remove'),
            'Remove selected downloads form list',
            self,
            statusTip='Remove selected downloads form list',
            triggered=self.removeSelected)
        editMenu.addAction(self.removeSelectedAction)
        self.removeSelectedAction.setEnabled(False)

        self.deleteSelectedAction = QAction(
            QIcon(icons + 'multi_trash'),
            'Delete selected download files',
            self,
            statusTip='Delete selected download files',
            triggered=self.deleteSelected)
        editMenu.addAction(self.deleteSelectedAction)
        self.deleteSelectedAction.setEnabled(False)

        self.createQueueAction = QAction(QIcon(icons + 'add_queue'),
                                         'Create new queue',
                                         self,
                                         statusTip='Create new download queue',
                                         triggered=self.createQueue)
        queueMenu.addAction(self.createQueueAction)

        self.removeQueueAction = QAction(QIcon(icons + 'remove_queue'),
                                         'Remove this queue',
                                         self,
                                         statusTip='Remove this queue',
                                         triggered=self.removeQueue)
        queueMenu.addAction(self.removeQueueAction)

        self.startQueueAction = QAction(QIcon(icons + 'start_queue'),
                                        'Start this queue',
                                        self,
                                        statusTip='Start this queue',
                                        triggered=self.startQueue)
        queueMenu.addAction(self.startQueueAction)

        self.stopQueueAction = QAction(QIcon(icons + 'stop_queue'),
                                       'Stop this queue',
                                       self,
                                       statusTip='Stop this queue',
                                       triggered=self.stopQueue)
        queueMenu.addAction(self.stopQueueAction)

        self.moveUpAction = QAction(
            QIcon(icons + 'up'),
            'Move up this item',
            self,
            statusTip='Move currently selected item up by one row',
            triggered=self.moveUp)
        queueMenu.addAction(self.moveUpAction)

        self.moveDownAction = QAction(
            QIcon(icons + 'down'),
            'Move down this item',
            self,
            statusTip='Move currently selected item down by one row',
            triggered=self.moveDown)
        queueMenu.addAction(self.moveDownAction)

        self.moveUpSelectedAction = QAction(
            QIcon(icons + 'multi_up'),
            'Move up selected items',
            self,
            statusTip='Move currently selected items up by one row',
            triggered=self.moveUpSelected)
        queueMenu.addAction(self.moveUpSelectedAction)

        self.moveDownSelectedAction = QAction(
            QIcon(icons + 'multi_down'),
            'Move down selected items',
            self,
            statusTip='Move currently selected items down by one row',
            triggered=self.moveDownSelected)
        queueMenu.addAction(self.moveDownSelectedAction)

        self.preferencesAction = QAction(QIcon(icons + 'preferences'),
                                         'Preferences',
                                         self,
                                         statusTip='Preferences',
                                         triggered=self.openPreferences,
                                         menuRole=5)
        editMenu.addAction(self.preferencesAction)

        self.aboutAction = QAction(QIcon(icons + 'about'),
                                   'About',
                                   self,
                                   statusTip='About',
                                   triggered=self.openAbout,
                                   menuRole=4)
        helpMenu.addAction(self.aboutAction)

        self.issueAction = QAction(QIcon(icons + 'about'),
                                   'Report an issue',
                                   self,
                                   statusTip='Report an issue',
                                   triggered=self.reportIssue)
        helpMenu.addAction(self.issueAction)

        self.updateAction = QAction(QIcon(icons + 'about'),
                                    'Check for newer version',
                                    self,
                                    statusTip='Check for newer release',
                                    triggered=self.newUpdate)
        helpMenu.addAction(self.updateAction)

        self.logAction = QAction(QIcon(icons + 'about'),
                                 'Show log file',
                                 self,
                                 statusTip='Help',
                                 triggered=self.showLog)
        helpMenu.addAction(self.logAction)

        self.helpAction = QAction(QIcon(icons + 'about'),
                                  'Help',
                                  self,
                                  statusTip='Help',
                                  triggered=self.persepolisHelp)
        helpMenu.addAction(self.helpAction)

        self.qmenu = MenuWidget(self)

        self.toolBar2.addWidget(self.qmenu)

        # labels
        self.queue_panel_show_button.setText("Hide options")
        self.start_checkBox.setText("Start Time")

        self.end_checkBox.setText("End Time")

        self.reverse_checkBox.setText("Download bottom of\n the list first")

        self.limit_checkBox.setText("Limit Speed")
        self.limit_comboBox.setItemText(0, "KB/S")
        self.limit_comboBox.setItemText(1, "MB/S")
        self.limit_pushButton.setText("Apply")

        self.after_checkBox.setText("After download")
        self.after_comboBox.setItemText(0, "Shut Down")

        self.keep_awake_checkBox.setText("Keep system awake!")
        self.keep_awake_checkBox.setToolTip(
            "<html><head/><body><p>This option is preventing system from going to sleep.\
            This is necessary if your power manager is suspending system automatically. </p></body></html>"
        )

        self.after_pushButton.setText("Apply")

    def changeIcon(self, icons):
        icons = ':/' + str(icons) + '/'

        action_icon_dict = {
            self.stopAllAction: 'stop_all',
            self.minimizeAction: 'minimize',
            self.addlinkAction: 'add',
            self.addtextfileAction: 'file',
            self.resumeAction: 'play',
            self.pauseAction: 'pause',
            self.stopAction: 'stop',
            self.removeAction: 'remove',
            self.propertiesAction: 'setting',
            self.progressAction: 'window',
            self.openFileAction: 'file',
            self.openDownloadFolderAction: 'folder',
            self.deleteFileAction: 'trash',
            self.openDefaultDownloadFolderAction: 'folder',
            self.exitAction: 'exit',
            self.selectAllAction: 'select_all',
            self.removeSelectedAction: 'multi_remove',
            self.deleteSelectedAction: 'multi_trash',
            self.createQueueAction: 'add_queue',
            self.removeQueueAction: 'remove_queue',
            self.startQueueAction: 'start_queue',
            self.stopQueueAction: 'stop_queue',
            self.moveUpAction: 'up',
            self.moveDownAction: 'down',
            self.preferencesAction: 'preferences',
            self.aboutAction: 'about',
            self.issueAction: 'about',
            self.updateAction: 'about',
            self.qmenu: 'menu'
        }
        for key in action_icon_dict.keys():
            key.setIcon(QIcon(icons + str(action_icon_dict[key])))
예제 #28
0
class ProcessDialog(QDialog):
    def __init__(self, port, **kwargs):
        super().__init__()

        self.setWindowTitle('Cooking your TinyGS station...')
        self.setFixedWidth(400)

        self.exception = None

        esptool.sw.progress.connect(self.update_progress)

        self.nam = QNetworkAccessManager()
        self.nrBinFile = QNetworkRequest()
        self.bin_data = b''

        self.setLayout(VLayout(5, 5))
        self.actions_layout = QFormLayout()
        self.actions_layout.setSpacing(5)

        self.layout().addLayout(self.actions_layout)

        self._actions = []
        self._action_widgets = {}

        self.port = port

        self.auto_reset = kwargs.get('auto_reset', False)

        self.file_path = kwargs.get('file_path')
        if self.file_path and self.file_path.startswith('http'):
            self._actions.append('download')

        self.backup = kwargs.get('backup')
        if self.backup:
            self._actions.append('backup')
            self.backup_size = kwargs.get('backup_size')

        self.erase = kwargs.get('erase')
        if self.erase:
            self._actions.append('erase')

        if self.file_path:
            self._actions.append('write')

        self.create_ui()
        self.start_process()

    def create_ui(self):
        for action in self._actions:
            pb = QProgressBar()
            pb.setFixedHeight(35)
            self._action_widgets[action] = pb
            self.actions_layout.addRow(action.capitalize(), pb)

        self.btns = QDialogButtonBox(QDialogButtonBox.Abort)
        self.btns.rejected.connect(self.abort)
        self.layout().addWidget(self.btns)

        self.sb = QStatusBar()
        self.layout().addWidget(self.sb)

    def appendBinFile(self):
        self.bin_data += self.bin_reply.readAll()

    def saveBinFile(self):
        if self.bin_reply.error() == QNetworkReply.NoError:
            self.file_path = self.file_path.split('/')[-1]
            with open(self.file_path, 'wb') as f:
                f.write(self.bin_data)
            self.run_esp()
        else:
            raise NetworkError

    def updateBinProgress(self, recv, total):
        self._action_widgets['download'].setValue(recv // total * 100)

    def download_bin(self):
        self.nrBinFile.setUrl(QUrl(self.file_path))
        self.bin_reply = self.nam.get(self.nrBinFile)
        self.bin_reply.readyRead.connect(self.appendBinFile)
        self.bin_reply.downloadProgress.connect(self.updateBinProgress)
        self.bin_reply.finished.connect(self.saveBinFile)

    def show_connection_state(self, state):
        self.sb.showMessage(state, 0)

    def run_esp(self):
        params = {
            'file_path': self.file_path,
            'auto_reset': self.auto_reset,
            'erase': self.erase
        }

        if self.backup:
            backup_size = f'0x{2 ** self.backup_size}00000'
            params['backup_size'] = backup_size

        self.esp_thread = QThread()
        self.esp = ESPWorker(self.port, self._actions, **params)
        esptool.sw.connection_state.connect(self.show_connection_state)
        self.esp.waiting.connect(self.wait_for_user)
        self.esp.done.connect(self.accept)
        self.esp.error.connect(self.error)
        self.esp.moveToThread(self.esp_thread)
        self.esp_thread.started.connect(self.esp.run)
        self.esp_thread.start()

    def start_process(self):
        if 'download' in self._actions:
            self.download_bin()
            self._actions = self._actions[1:]
        else:
            self.run_esp()

    def update_progress(self, action, value):
        self._action_widgets[action].setValue(value)

    @pyqtSlot()
    def wait_for_user(self):
        dlg = QMessageBox.information(
            self, 'User action required',
            'Please power cycle the device, wait a moment and press OK',
            QMessageBox.Ok | QMessageBox.Cancel)
        if dlg == QMessageBox.Ok:
            self.esp.continue_ok()
        elif dlg == QMessageBox.Cancel:
            self.esp.abort()
            self.esp.continue_ok()
            self.abort()

    def stop_thread(self):
        self.esp_thread.wait(2000)
        self.esp_thread.exit()

    def accept(self):
        self.stop_thread()
        self.done(QDialog.Accepted)

    def abort(self):
        self.sb.showMessage('Aborting...', 0)
        QApplication.processEvents()
        self.esp.abort()
        self.stop_thread()
        self.reject()

    def error(self, e):
        self.exception = e
        self.abort()

    def closeEvent(self, e):
        self.stop_thread()
예제 #29
0
파일: src3.py 프로젝트: HarryNdegwa/gui1
 def _createStatusBar(self):
     statusBar = QStatusBar()
     self.setStatusBar(statusBar)
     statusBar.showMessage("I am the f*****g status bar!")
예제 #30
0
class MainView(QMainWindow):
    def __init__(self, prb, model=None):
        super(MainView, self).__init__()
        self.prb = prb
        if model is not None:
            self._model = model
        self.initUI()

    def initUI(self):

        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.darkGray)
        p.setColor(self.foregroundRole(), Qt.white)
        self.setPalette(p)

        self.setWindowTitle("Spiketag")

        self.status_bar = QStatusBar(self)
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage('Ready')

        self.centralWidget = QWidget(self)
        self.setCentralWidget(self.centralWidget)

        hbox = QHBoxLayout(self)
        self.splitter0 = QSplitter(Qt.Horizontal)
        self.splitter1 = QSplitter(Qt.Horizontal)
        self.splitter2 = QSplitter(Qt.Horizontal)
        self.splitter_fet = QSplitter(Qt.Vertical)
        self.splitter3 = QSplitter(Qt.Vertical)
        self.splitter3.addWidget(self.splitter1)
        self.splitter3.addWidget(self.splitter2)
        self.splitter3.setSizes([70, 30])  # uppper and down (up, down)

        self.splitter_prb_cpu = QSplitter(Qt.Vertical)
        self.prb_view = probe_view()
        self.clu_view = cluster_view()
        self.prb_view.set_data(self.prb, font_size=35)
        self.clu_view.set_data(self._model.clu_manager)
        self.splitter_prb_cpu.addWidget(self.prb_view.native)
        self.splitter_prb_cpu.addWidget(self.clu_view.native)
        self.splitter0.addWidget(self.splitter_prb_cpu)
        self.splitter0.addWidget(self.splitter3)
        self.splitter0.setSizes([20,
                                 180])  # prb_view and all others (left, right)

        hbox.addWidget(self.splitter0)

        self.centralWidget.setLayout(hbox)

        self.spkview = spike_view()
        self.fetview0 = scatter_3d_view()
        self.fetview1 = scatter_3d_view()
        self.ampview = amplitude_view(fs=self.prb.fs, scale=1)
        self.corview = correlogram_view(fs=self.prb.fs)
        # self.treeview = ctree_view()
        self.pfview = pf_view(pc=self._model.pc)
        self.traceview = trace_view(data=self._model.mua.data, fs=self.prb.fs)

        self.splitter1.addWidget(self.traceview.native)
        self.splitter1.addWidget(self.splitter_fet)
        self.splitter_fet.addWidget(self.fetview0.native)
        self.splitter_fet.addWidget(self.fetview1.native)
        self.splitter1.addWidget(self.spkview.native)
        self.splitter1.setSizes([30, 50, 80])  # trace_view, fet_view, spk_view

        self.splitter2.addWidget(self.corview.native)
        self.splitter2.addWidget(self.pfview.native)
        self.splitter2.addWidget(self.ampview.native)
        self.splitter2.setSizes([40, 40, 100])  # corview, treeview, ampview

    def set_data(self, group_id, mua, spk, fet, clu):
        ### init view and set_data

        self.clu = clu
        chs = self.prb[group_id]
        self.spkview.set_data(spk, clu)
        # self.fetview0.set_data(fet, clu)
        # if fet.shape[1]>3:
        self.fetview0.dimension = [0, 1, 2]
        self.fetview0.set_data(fet, clu)  #[:,[0,1,2]].copy()
        self.fetview1.dimension = [0, 1, 3]
        self.fetview1.set_data(fet, clu)  #[:,[0,1,3]].copy()
        # else:
        self.ampview.set_data(spk, clu, mua.spk_times[group_id])
        # self.treeview.set_data(clu)
        self.traceview.set_data(chs, clu, mua.spk_times[group_id])
        try:
            self.corview.set_data(clu, mua.spk_times[group_id])
        except Exception as e:
            pass

        self.pfview.set_data(clu, mua.spk_times[group_id] / self.prb.fs)

        self.traceview.locate_buffer = 1500

        # everytime when view.set_data
        # the corresponding clu will go through its registration process
        # then won'g go through it again
        if self.clu._event_reg_enable is True:
            self.register_event()

    def register_event(self):
        self.spkview.register_event()
        self.fetview0.register_event()
        self.fetview1.register_event()
        self.ampview.register_event()
        self.traceview.register_event()
        self.corview.register_event()
        self.pfview.register_event()  # make sure self.pfview already get pc
        self.clu._event_reg_enable = False

    def set_data_from_model(self, group_id):
        ### init view and set_data
        model = self._model
        chs = self.prb[group_id]
        self.spkview.set_data(model.spk[group_id], model.clu[group_id])
        self.fetview0.dimension = [0, 1, 2]
        self.fetview0.set_data(model.fet[group_id],
                               model.clu[group_id])  #[:,[0,1,2]].copy()
        self.fetview1.dimension = [0, 1, 3]
        self.fetview1.set_data(model.fet[group_id],
                               model.clu[group_id])  #[:,[0,1,3]].copy()
        # else:
        self.ampview.set_data(model.spk[group_id], model.clu[group_id],
                              model.mua.spk_times[group_id])
        # self.treeview.set_data(model.clu[group_id])
        self.traceview.set_data(self.prb[group_id], model.clu[group_id],
                                model.mua.spk_times[group_id])
        # try:
        #     self.corview.set_data(model.clu[group_id], model.mua.spk_times[group_id])
        # except Exception as e:
        #     pass

        self.traceview.locate_buffer = 2000
예제 #31
0
class App(QWidget):
    def __init__(self, data, showRows):
        super().__init__()
        self.data = data
        self.showRows = showRows
        self.initUI()

    def initUI(self):
        self.setWindowTitle('DataFrame Viewer')
        self.showMaximized()

        self.activePage = 0
        self.sortIndex = 0
        self.sortAscending = False

        #Buttons
        self.prevButton = QPushButton("< Prev", self)
        self.nextButton = QPushButton("Next >", self)
        self.lastButton = QPushButton("Last >>", self)
        self.firstButton = QPushButton("<< First", self)

        self.nextButton.clicked.connect(self.nextPage)
        self.prevButton.clicked.connect(self.prevPage)
        self.lastButton.clicked.connect(self.lastPage)
        self.firstButton.clicked.connect(self.firstPage)

        #Search
        self.searchBox = QLineEdit(self)
        self.searchBox.setPlaceholderText('Search in selected column...')
        self.searchBox.returnPressed.connect(self.loadDataFrame)
        self.searchComboBox = QComboBox()
        for col_name in list(self.data.columns):
            self.searchComboBox.addItem(col_name)
        self.searchComboBox.currentIndexChanged.connect(self.loadDataFrame)

        self.searchQueryCheckBox = QCheckBox("Search Query")
        self.searchQueryCheckBox.stateChanged.connect(self.loadDataFrame)

        #Table widget
        self.tableWidget = QTableWidget()
        self.tableWidget.horizontalHeader().sectionDoubleClicked.connect(
            self.changeSortCriteria)

        #Status bar
        self.statusBar = QStatusBar()

        #Layout
        self.Vlayout = QHBoxLayout()
        self.layout = QVBoxLayout()

        self.Vlayout.addWidget(self.searchBox)
        self.Vlayout.addWidget(self.searchComboBox)
        self.Vlayout.addWidget(self.searchQueryCheckBox)
        self.Vlayout.addWidget(self.prevButton)
        self.Vlayout.addWidget(self.nextButton)
        self.Vlayout.addWidget(self.firstButton)
        self.Vlayout.addWidget(self.lastButton)

        self.layout.addLayout(self.Vlayout)
        self.layout.addWidget(self.tableWidget)
        self.layout.addWidget(self.statusBar)
        self.setLayout(self.layout)
        self.loadDataFrame()
        self.show()

    @pyqtSlot()
    def nextPage(self):
        if self.activePage != self.maxPageNumber:
            self.activePage += 1
        self.loadDataFrame()

    def prevPage(self):
        if self.activePage != 0:
            self.activePage -= 1
        self.loadDataFrame()

    def lastPage(self):
        self.activePage = self.maxPageNumber
        self.loadDataFrame()

    def firstPage(self):
        self.activePage = 0
        self.loadDataFrame()

    def changeSortCriteria(self, i):
        if i == self.sortIndex:
            if self.sortAscending == True:
                self.sortAscending = False
            else:
                self.sortAscending = True

        self.sortIndex = i
        self.loadDataFrame()

    def loadDataFrame(self):
        try:
            df = self.data
            if len(self.searchBox.text()) >= 1:
                if self.searchQueryCheckBox.isChecked():
                    #Query mode
                    df = df.query(self.searchBox.text())
                    #We print query to log
                    print("Search Query: {}".format(self.searchBox.text()))
                else:
                    df = df[df[self.searchComboBox.currentText()].astype(
                        str).str.contains(self.searchBox.text())]

            self.rowsCount = df.shape[0]
            self.colsCount = df.shape[1]
            self.maxPageNumber = int(np.ceil(
                self.rowsCount / self.showRows)) - 1
            #to fix wrong page bug in search mode
            if self.activePage > self.maxPageNumber:
                self.activePage = 0
            self.statusBar.showMessage("Page {}/{}, Rows: {} - {}, Total Results : {}"\
                                       .format(self.activePage,\
                                           self.maxPageNumber,\
                                           (self.activePage*self.showRows),\
                                           (self.activePage*self.showRows+self.showRows),\
                                           self.rowsCount))

            df = df.reset_index()\
                .sort_values(self.data.columns[self.sortIndex], ascending=self.sortAscending)\
                .iloc[(self.activePage*self.showRows):(self.activePage*self.showRows+self.showRows)]

            self.tableWidget.setRowCount(0)
            self.tableWidget.setColumnCount(0)
            self.tableWidget.setColumnCount(self.colsCount)
            self.tableWidget.setHorizontalHeaderLabels(list(self.data.columns))
            self.tableWidget.setRowCount(df.shape[0])
            i = 0
            for index, row in df.iterrows():
                for col in range(self.colsCount):
                    w_item = QTableWidgetItem(str(row[col + 1]))
                    self.tableWidget.setItem(i, col, w_item)
                i += 1

        except Exception as e:
            print("An error occured. {}".format(e))
예제 #32
0
파일: qged2dot.py 프로젝트: vmiklos/ged2dot
class Widgets:
    """Contains widgets which store shared state."""
    def __init__(self, window: QWidget) -> None:
        self.input_value = QLineEdit(window)
        self.output_value = QLineEdit(window)
        self.rootfamily_value = QComboBox(window)
        self.familydepth_value = QSpinBox(window)
        self.imagedir_value = QLineEdit(window)
        self.nameorder_value = QCheckBox(window)
        self.statusbar = QStatusBar()

    def set_input(self) -> None:
        """Handler for the input button."""
        try:
            dialog = QFileDialog()
            dialog.setFileMode(QFileDialog.FileMode.ExistingFile)  # pylint: disable=no-member
            dialog.setNameFilters(["GEDCOM files (*.ged)"])
            if not dialog.exec():
                return

            files = dialog.selectedFiles()
            assert len(files) == 1
            ged_path = files[0]
            self.input_value.setText(ged_path)

            import_config = {
                'input': ged_path,
            }
            ged_import = ged2dot.GedcomImport()
            graph = ged_import.load(import_config)
            self.rootfamily_value.clear()
            for node in graph:
                if not isinstance(node, ged2dot.Family):
                    continue
                help_string = ""
                if node.husb and node.husb.get_surname():
                    help_string += node.husb.get_surname()
                help_string += "-"
                if node.wife and node.wife.get_surname():
                    help_string += node.wife.get_surname()
                key = f"{node.get_identifier()} ({help_string})"
                self.rootfamily_value.addItem(key, node.get_identifier())
            self.update_status()
        except Exception:  # pylint: disable=broad-except
            self.print_traceback()

    def set_output(self) -> None:
        """Handler for the output button."""
        dialog = QFileDialog()
        dialog.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)  # pylint: disable=no-member
        name_filters = [
            "SVG files (*.svg)",
            "PNG files (*.png)",
            "Graphviz files (*.dot)",
        ]
        dialog.setNameFilters(name_filters)
        if not dialog.exec():
            return

        files = dialog.selectedFiles()
        assert len(files) == 1
        self.output_value.setText(files[0])
        self.update_status()

    def set_imagedir(self) -> None:
        """Handler for the imagedir button."""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.FileMode.Directory)  # pylint: disable=no-member
        if not dialog.exec():
            return

        files = dialog.selectedFiles()
        assert len(files) == 1
        self.imagedir_value.setText(files[0])

    def convert(self) -> None:
        """Does the actual conversion."""
        try:
            config = {
                "input": self.input_value.text(),
                "output": self.output_value.text(),
                "rootfamily": self.rootfamily_value.currentData(),
                "familydepth": str(self.familydepth_value.value()),
                "imagedir": self.imagedir_value.text(),
                "nameorder": "little",
            }
            if not self.nameorder_value.isChecked():
                config["nameorder"] = "big"
            invoke_dot = False
            if not self.output_value.text().endswith(".dot"):
                invoke_dot = True
                config["output"] = self.output_value.text() + ".dot"
            self.statusbar.showMessage("Converting to " + config["output"] +
                                       "...")
            ged2dot.convert(config)
            if invoke_dot:
                self.statusbar.showMessage("Converting to " +
                                           self.output_value.text() + "...")
                self.to_graphic(config["output"], self.output_value.text())
            webbrowser.open("file://" + self.output_value.text())
            self.statusbar.showMessage("Conversion finished successfully.")
        except Exception:  # pylint: disable=broad-except
            self.print_traceback()

    @staticmethod
    def to_graphic(dot_path: str, graphic_path: str) -> None:
        """Convert the generated .dot further to .png/.svg, using dot."""
        graph = pygraphviz.AGraph(dot_path)
        if graphic_path.endswith(".png"):
            graph.draw(graphic_path, format="png", prog="dot")
        else:
            graph.draw(graphic_path, format="svg", prog="dot")

    @staticmethod
    def print_traceback() -> None:
        """Shows the exception to the user when it would not be caught."""
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Icon.Warning)  # pylint: disable=no-member
        msg.setText("Conversion failed.")
        with io.StringIO() as stream:
            traceback.print_exc(file=stream)
            stream.seek(0)
            msg.setDetailedText(stream.read())
        msg.exec()

    def update_status(self) -> None:
        """Updates the statusbar depending on what should be the next action."""
        if not self.input_value.text():
            message = "Select an input."
        elif not self.output_value.text():
            message = "Select an output."
        else:
            message = "Press OK to start the conversion."
        self.statusbar.showMessage(message)
예제 #33
0
class ScoreDB(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.dbfilename = 'assignment6.dat'
        self.scoredb = []
        self.readScoreDB()
        self.showScoreDB()

    def initUI(self):

        self.setGeometry(300, 300, 500, 250)
        self.setWindowTitle('Assignment6')
        namelable = QLabel("Name : ")
        self.nameedit = QLineEdit()
        agelable = QLabel("Age : ")
        self.ageedit = QLineEdit()
        scorelable = QLabel("Score : ")
        self.scoreedit = QLineEdit()
        vbox = QVBoxLayout()
        hbox1 = QHBoxLayout()
        hbox2 = QHBoxLayout()
        hbox3 = QHBoxLayout()
        hbox4 = QHBoxLayout()
        hbox5 = QHBoxLayout()
        hbox6 = QHBoxLayout()
        hbox7 = QHBoxLayout()

        amountlable = QLabel("Amount : ")
        self.amountedit = QLineEdit()
        keylable = QLabel("Key : ")
        self.selectedkey = QLabel("Age")

        funtionlabel = QLabel("Functions : ")
        addbutton = QPushButton("Add")
        addbutton.clicked.connect(self.addScoreDB)
        delbutton = QPushButton("Del")
        delbutton.clicked.connect(self.delScoreDB)
        findbutton = QPushButton("Find")
        findbutton.clicked.connect(self.findScoreDB)
        incbutton = QPushButton("Inc")
        incbutton.clicked.connect(self.incScoreDB)
        showbutton = QPushButton("Show")
        showbutton.clicked.connect(self.showScoreDB)

        keybuttonlabel = QLabel("Keys : ")
        agebutton = QPushButton("Age")
        agebutton.clicked.connect(self.SetKeyAsAge)
        scorebutton = QPushButton("Score")
        scorebutton.clicked.connect(self.SetKeyAsScore)
        namebutton = QPushButton("Name")
        namebutton.clicked.connect(self.SetKeyAsName)

        resultlable = QLabel("Result:")

        self.resultbox = QTextEdit()

        self.bar = QStatusBar()

        hbox1.addWidget(namelable)
        hbox1.addWidget(self.nameedit)
        hbox1.addWidget(agelable)
        hbox1.addWidget(self.ageedit)
        hbox1.addWidget(scorelable)
        hbox1.addWidget(self.scoreedit)

        hbox2.addStretch(1)
        hbox2.addWidget(amountlable)
        hbox2.addWidget(self.amountedit)
        hbox2.addWidget(keylable)
        hbox2.addWidget(self.selectedkey)

        hbox3.addStretch(1)
        hbox3.addWidget(funtionlabel)
        hbox3.addWidget(addbutton)
        hbox3.addWidget(delbutton)
        hbox3.addWidget(findbutton)
        hbox3.addWidget(incbutton)
        hbox3.addWidget(showbutton)

        hbox4.addStretch(1)
        hbox4.addWidget(keybuttonlabel)
        hbox4.addWidget(agebutton)
        hbox4.addWidget(scorebutton)
        hbox4.addWidget(namebutton)

        hbox5.addWidget(resultlable)
        hbox5.addStretch(1)

        hbox6.addWidget(self.resultbox)

        hbox7.addWidget(self.bar)

        vbox.addLayout(hbox1)
        vbox.addLayout(hbox2)
        vbox.addLayout(hbox3)
        vbox.addLayout(hbox4)
        vbox.addLayout(hbox5)
        vbox.addLayout(hbox6)
        vbox.addLayout(hbox7)
        self.setLayout(vbox)
        self.show()

    def closeEvent(self, event):

        self.writeScoreDB()

    def readScoreDB(self):
        try:
            fH = open(self.dbfilename, 'rb')
        except FileNotFoundError as e:
            self.scoredb = []
            return

        try:
            self.scoredb = pickle.load(fH)
        except:
            pass
        else:
            pass
        fH.close()

    # write the data into person db
    def writeScoreDB(self):
        fH = open(self.dbfilename, 'wb')
        pickle.dump(self.scoredb, fH)
        fH.close()

    def showScoreDB(self):
        self.resultbox.setText("")
        for p in sorted(self.scoredb,
                        key=lambda person: person[self.selectedkey.text()]):
            for attr in sorted(p):
                self.resultbox.insertPlainText(attr + "=" + str(p[attr]) +
                                               "\t")
            self.resultbox.append("")
        pass

    def addScoreDB(self):
        self.bar.showMessage('')
        try:
            record = {
                'Name': self.nameedit.text(),
                'Age': int(self.ageedit.text()),
                'Score': int(self.scoreedit.text())
            }
        except ValueError:
            self.bar.showMessage('Value Error')
        else:
            self.scoredb += [record]
            self.showScoreDB()

    def delScoreDB(self):
        try:
            co_scdb = self.scoredb[:]
            for l in range(len(self.scoredb)):
                for p in self.scoredb:
                    if p['Name'] == self.nameedit.text():
                        self.scoredb.remove(p)
            if len(co_scdb) == len(self.scoredb):
                self.bar.showMessage('Name not found')
        except ValueError:
            self.bar.showMessage('Value Error')
        self.showScoreDB()

    def findScoreDB(self):
        try:
            findedDB = []
            for i in self.scoredb:
                if i['Name'] == self.nameedit.text():
                    findedDB += [i]
            if len(findedDB) > 0:
                self.resultbox.setText("")
                for p in sorted(
                        findedDB,
                        key=lambda person: person[self.selectedkey.text()]):
                    for attr in sorted(p):
                        self.resultbox.insertPlainText(attr + "=" +
                                                       str(p[attr]) + "\t")
                    self.resultbox.append("")
            else:
                self.bar.showMessage('Name not found')
        except ValueError:
            self.bar.showMessage('Value Error')

    def incScoreDB(self):
        try:
            for i in self.scoredb:
                if i['Name'] == self.nameedit.text():
                    i['Score'] += int(self.amountedit.text())
            self.showScoreDB()
        except ValueError:
            self.bar.showMessage('Value Error')

    def SetKeyAsAge(self):
        self.selectedkey.setText("Age")

    def SetKeyAsName(self):
        self.selectedkey.setText("Name")

    def SetKeyAsScore(self):
        self.selectedkey.setText("Score")
예제 #34
0
class ConfigParamEditWindow(QDialog):
    def __init__(self, parent, node, target_node_id, param_struct, update_callback):
        super(ConfigParamEditWindow, self).__init__(parent)
        self.setWindowTitle('Edit configuration parameter')
        self.setModal(True)

        self._node = node
        self._target_node_id = target_node_id
        self._param_struct = param_struct
        self._update_callback = update_callback

        min_val = get_union_value(param_struct.min_value)
        if 'uavcan.protocol.param.Empty' in str(min_val):
            min_val = None

        max_val = get_union_value(param_struct.max_value)
        if 'uavcan.protocol.param.Empty' in str(max_val):
            max_val = None

        value = get_union_value(param_struct.value)
        self._value_widget = None
        value_type = uavcan.get_active_union_field(param_struct.value)

        if value_type == 'integer_value':
            min_val = min_val if min_val is not None else -0x8000000000000000
            max_val = max_val if max_val is not None else 0x7FFFFFFFFFFFFFFF
            if min_val >= -0x80000000 and \
               max_val <= +0x7FFFFFFF:
                self._value_widget = QSpinBox(self)
                self._value_widget.setMaximum(max_val)
                self._value_widget.setMinimum(min_val)
                self._value_widget.setValue(value)
        if value_type == 'real_value':
            min_val = round_float(min_val) if min_val is not None else -3.4028235e+38
            max_val = round_float(max_val) if max_val is not None else 3.4028235e+38
            value = round_float(value)
        if value_type == 'boolean_value':
            self._value_widget = QCheckBox(self)
            self._value_widget.setChecked(bool(value))

        if self._value_widget is None:
            self._value_widget = QLineEdit(self)
            self._value_widget.setText(str(value))
        self._value_widget.setFont(get_monospace_font())

        layout = QGridLayout(self)

        def add_const_field(label, *values):
            row = layout.rowCount()
            layout.addWidget(QLabel(label, self), row, 0)
            if len(values) == 1:
                layout.addWidget(FieldValueWidget(self, values[0]), row, 1)
            else:
                sub_layout = QHBoxLayout(self)
                for idx, v in enumerate(values):
                    sub_layout.addWidget(FieldValueWidget(self, v))
                layout.addLayout(sub_layout, row, 1)

        add_const_field('Name', param_struct.name)
        add_const_field('Type', uavcan.get_active_union_field(param_struct.value).replace('_value', ''))
        add_const_field('Min/Max', min_val, max_val)
        add_const_field('Default', render_union(param_struct.default_value))

        layout.addWidget(QLabel('Value', self), layout.rowCount(), 0)
        layout.addWidget(self._value_widget, layout.rowCount() - 1, 1)

        fetch_button = make_icon_button('refresh', 'Read parameter from the node', self, text='Fetch',
                                        on_clicked=self._do_fetch)
        set_default_button = make_icon_button('fire-extinguisher', 'Restore default value', self, text='Restore',
                                              on_clicked=self._restore_default)
        send_button = make_icon_button('flash', 'Send parameter to the node', self, text='Send',
                                       on_clicked=self._do_send)
        cancel_button = make_icon_button('remove', 'Close this window; unsent changes will be lost', self,
                                         text='Cancel', on_clicked=self.close)

        controls_layout = QGridLayout(self)
        controls_layout.addWidget(fetch_button, 0, 0)
        controls_layout.addWidget(send_button, 0, 1)
        controls_layout.addWidget(set_default_button, 1, 0)
        controls_layout.addWidget(cancel_button, 1, 1)
        layout.addLayout(controls_layout, layout.rowCount(), 0, 1, 2)

        self._status_bar = QStatusBar(self)
        self._status_bar.setSizeGripEnabled(False)
        layout.addWidget(self._status_bar, layout.rowCount(), 0, 1, 2)

        left, top, right, bottom = layout.getContentsMargins()
        bottom = 0
        layout.setContentsMargins(left, top, right, bottom)

        self.setLayout(layout)

    def show_message(self, text, *fmt):
        self._status_bar.showMessage(text % fmt)

    def _assign(self, value_union):
        value = get_union_value(value_union)

        if uavcan.get_active_union_field(value_union) == 'real_value':
            value = round_float(value)

        if hasattr(self._value_widget, 'setValue'):
            self._value_widget.setValue(value)
            self._update_callback(value)
        elif hasattr(self._value_widget, 'setChecked'):
            self._value_widget.setChecked(bool(value))
            self._update_callback(bool(value))
        else:
            self._value_widget.setText(str(value))
            self._update_callback(value)

    def _on_response(self, e):
        if e is None:
            self.show_message('Request timed out')
        else:
            logger.info('Param get/set response: %s', e.response)
            self._assign(e.response.value)
            self.show_message('Response received')

    def _restore_default(self):
        self._assign(self._param_struct.default_value)

    def _do_fetch(self):
        try:
            request = uavcan.protocol.param.GetSet.Request(name=self._param_struct.name)
            self._node.request(request, self._target_node_id, self._on_response, priority=REQUEST_PRIORITY)
        except Exception as ex:
            show_error('Node error', 'Could not send param get request', ex, self)
        else:
            self.show_message('Fetch request sent')

    def _do_send(self):
        value_type = uavcan.get_active_union_field(self._param_struct.value)

        try:
            if value_type == 'integer_value':
                if hasattr(self._value_widget, 'value'):
                    value = int(self._value_widget.value())
                else:
                    value = int(self._value_widget.text())
                self._param_struct.value.integer_value = value
            elif value_type == 'real_value':
                value = float(self._value_widget.text())
                self._param_struct.value.real_value = value
            elif value_type == 'boolean_value':
                value = bool(self._value_widget.isChecked())
                self._param_struct.value.boolean_value = value
            elif value_type == 'string_value':
                value = self._value_widget.text()
                self._param_struct.value.string_value = value
            else:
                raise RuntimeError('This is not happening!')
        except Exception as ex:
            show_error('Format error', 'Could not parse value', ex, self)
            return

        try:
            request = uavcan.protocol.param.GetSet.Request(name=self._param_struct.name,
                                                           value=self._param_struct.value)
            logger.info('Sending param set request: %s', request)
            self._node.request(request, self._target_node_id, self._on_response, priority=REQUEST_PRIORITY)
        except Exception as ex:
            show_error('Node error', 'Could not send param set request', ex, self)
        else:
            self.show_message('Set request sent')
예제 #35
0
class PlottingWidget(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        # super(PrettyWidget, self).__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(600, 300, 1000, 600)
        self.center()
        self.setWindowTitle("Plot Trajectory")

        mainMenu = self.menuBar()
        fileMenu = mainMenu.addMenu("File")

        saveAction = QAction("Save as...")
        saveAction.setShortcut("Ctrl+S")
        saveAction.setStatusTip("Save plot to file")
        saveAction.setMenuRole(QAction.NoRole)
        saveAction.triggered.connect(self.file_save)
        fileMenu.addAction(saveAction)

        exitAction = QAction("&Exit", self)
        exitAction.setShortcut("Ctrl+Q")
        exitAction.setStatusTip("Exit Application")
        exitAction.setMenuRole(QAction.NoRole)
        exitAction.triggered.connect(self.close)
        fileMenu.addAction(exitAction)

        settingsMenu = mainMenu.addMenu("Settings")
        self.setStyleMenu = QMenu("Set Style", self)
        settingsMenu.addMenu(self.setStyleMenu)
        for style_name in [
                "default", "fast", "ggplot", "grayscale", "seaborn"
        ]:
            styleAction = QAction(style_name, self, checkable=True)
            if style_name is CUR_STYLE:
                styleAction.setChecked(True)
            styleAction.triggered.connect(partial(self.set_style, style_name))
            self.setStyleMenu.addAction(styleAction)
        self.setTimeWindowMenu = QMenu("Set Time Window", self)
        settingsMenu.addMenu(self.setTimeWindowMenu)
        for window_str in ["None", "s", "30s", "H", "D"]:
            windowAction = QAction(window_str, self, checkable=True)
            if window_str is TIME_WINDOW:
                windowAction.setChecked(True)
            windowAction.triggered.connect(
                partial(self.set_time_window, window_str))
            self.setTimeWindowMenu.addAction(windowAction)

        # Grid Layout
        grid = QtWidgets.QGridLayout()
        widget = QtWidgets.QWidget(self)
        self.setCentralWidget(widget)
        widget.setLayout(grid)

        # Import CSV Button
        btn1 = QtWidgets.QPushButton("Import CSV", self)
        btn1.resize(btn1.sizeHint())
        btn1.clicked.connect(self.getCSV)
        grid.addWidget(btn1, 1, 0)

        # Canvas and Toolbar
        self.figure = plt.figure(figsize=(15, 5))
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setContextMenuPolicy(Qt.CustomContextMenu)
        self.canvas.customContextMenuRequested.connect(self.popup)
        grid.addWidget(self.canvas, 2, 0, 1, 2)

        # DropDown mean / comboBox
        self.df = pd.DataFrame()
        self.columns = []
        self.plot_list = []

        self.comboBox = QtWidgets.QComboBox(self)
        self.comboBox.addItems(self.columns)
        grid.addWidget(self.comboBox, 0, 0)

        self.comboBox2 = QtWidgets.QComboBox(self)
        self.comboBox2.addItems(self.plot_list)
        grid.addWidget(self.comboBox2, 0, 1)

        # Plot Button
        btn2 = QtWidgets.QPushButton("Plot", self)
        btn2.resize(btn2.sizeHint())
        btn2.clicked.connect(self.plot)
        grid.addWidget(btn2, 1, 1)

        # Progress bar
        self.progress = QProgressBar(self)
        # self.progress.setRange(0, 1)
        grid.addWidget(self.progress, 3, 0, 1, 2)

        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.show()

    def set_style(self, style_name: str):
        global CUR_STYLE
        self.statusBar.showMessage(f"Style set to {style_name}")
        actions = self.setStyleMenu.actions()
        CUR_STYLE = style_name
        for action in actions:
            if action.text() == CUR_STYLE:
                # print(f"✓ {CUR_STYLE}")
                action.setChecked(True)
            else:
                action.setChecked(False)
        print(f"Style set to {CUR_STYLE}")

    def popup(self, pos):
        menu = QMenu()
        saveAction = menu.addAction("Save...")
        action = menu.exec_(self.canvas.viewport().mapToGlobal(pos))
        if action == saveAction:
            self.file_save()

    def file_save(self, target="figure"):
        name = QtGui.QFileDialog.getSaveFileName(self, "Save File")
        if target == "figure":
            self.figure.savefig(name)

    def update_progress_bar(self, i: int):
        self.progress.setValue(i)
        max = self.progress.maximum()
        self.statusBar.showMessage(f"Loading ... {100*i/max:.0f}%")

    def set_progress_bar_max(self, max: int):
        self.progress.setMaximum(max)

    def clear_progress_bar(self):
        self.progress.hide()
        self.statusBar.showMessage("Completed.")

    def getCSV(self):
        self.statusBar.showMessage("Loading CSV...")
        filepath, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, "Open CSV", (QtCore.QDir.homePath()), "CSV (*.csv *.tsv)")

        if filepath != "":
            self.filepath = filepath
            self.loaderThread = QThread()
            self.loaderWorker = QtFileLoader(filepath)
            self.loaderWorker.moveToThread(self.loaderThread)
            self.loaderThread.started.connect(self.loaderWorker.read_in_chunks)
            self.loaderWorker.intReady.connect(self.update_progress_bar)
            self.loaderWorker.progressMaximum.connect(
                self.set_progress_bar_max)
            # self.loaderWorker.read_in_chunks.connect(self.df)
            self.loaderWorker.completed.connect(self.list_to_df)
            self.loaderWorker.completed.connect(self.clear_progress_bar)
            self.loaderThread.finished.connect(self.loaderThread.quit)
            self.loaderThread.start()

    @pyqtSlot(list)
    def list_to_df(self, dfs: list):
        df = pd.concat(dfs)
        self.df = df
        self.columns = self.df.columns.tolist()
        self.plot_list = [
            "Actogram", "Polar Bar", "Polar Histogram", "Trajectory"
        ]
        self.comboBox.clear()
        self.comboBox.addItems(self.columns)
        self.comboBox2.clear()
        self.comboBox2.addItems(self.plot_list)
        self.statusBar.clearMessage()

    def mousePressEvent(self, QMouseEvent):
        if QMouseEvent.button() == Qt.RightButton:

            print("Right Button Clicked")

    def load_project_structure(self, startpath, tree):
        """
        Load Project structure tree
        :param startpath:
        :param tree:
        :return:
        """
        from PyQt5.QtWidgets import QTreeWidgetItem
        from PyQt5.QtGui import QIcon

        for element in os.listdir(startpath):
            path_info = startpath + "/" + element
            parent_itm = QTreeWidgetItem(tree, [os.path.basename(element)])
            if os.path.isdir(path_info):
                self.load_project_structure(path_info, parent_itm)
                parent_itm.setIcon(0, QIcon("assets/folder.ico"))
            else:
                parent_itm.setIcon(0, QIcon("assets/file.ico"))

    def set_time_window(self, window: str):
        global TIME_WINDOW
        TIME_WINDOW = window
        self.statusBar.showMessage(f"Time window set to {window}")
        actions = self.setTimeWindowMenu.actions()
        for action in actions:
            if action.text() == TIME_WINDOW:
                action.setChecked(True)
            else:
                action.setChecked(False)
        print(f"Time window set to {window}")

    def plot(self):
        plt.clf()

        plot_kind = self.comboBox2.currentText()
        self.statusBar.showMessage(f"Plotting {plot_kind}")
        projection = ("polar" if plot_kind in ["Polar Bar", "Polar Histogram"]
                      else "rectilinear")

        ax = self.figure.add_subplot(111, projection=projection)

        title = f"{basename(self.filepath)}"

        # TODO: Move mapping to separate method
        if plot_kind == "Actogram":
            displacement = traja.trajectory.calc_displacement(self.df)
            if TIME_WINDOW != "None":
                displacement = displacement.rolling(TIME_WINDOW).mean()
                # from pyqtgraph.Qt import QtGui, QtCore
            traja.plotting.plot_actogram(displacement,
                                         ax=ax,
                                         interactive=False)
        elif plot_kind == "Trajectory":
            traja.plotting.plot(self.df, ax=ax, interactive=False)
        elif plot_kind == "Quiver":
            traja.plotting.plot_quiver(self.df, ax=ax, interactive=False)
        elif plot_kind == "Polar Bar":
            traja.plotting.polar_bar(self.df,
                                     ax=ax,
                                     title=title,
                                     interactive=False)
        elif plot_kind == "Polar Histogram":
            traja.plotting.polar_bar(self.df,
                                     ax=ax,
                                     title=title,
                                     overlap=False,
                                     interactive=False)
        plt.tight_layout()
        self.canvas.draw()
        self.statusBar.clearMessage()

    def center(self):
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
예제 #36
0
 def showMessage(self, message, timeout):
     if settings.SHOW_STATUS_NOTIFICATIONS:
         self._widgetStatus.hide()
         self._replaceWidget.setVisible(False)
         self.show()
         QStatusBar.showMessage(self, message, timeout)
예제 #37
0
class Dimili(QMainWindow):

    def baslat(self, anaPencere):
        anaPencere.resize(600, 400)
        anaPencere.setWindowTitle("Dimili-Türkçe Sözlük")
        anaPencere.setFixedSize(600,400)

        icon =QIcon()
        icon.addPixmap(QPixmap("Dictionary.png"),QIcon.Normal,QIcon.Off)
        anaPencere.setWindowIcon(icon)
        zemin=QWidget(anaPencere)
        zemin.setGeometry(QRect(0,30,600,390))
        zemin.setStyleSheet("background-color:rgb(167, 196, 233);")
        self.araKutu = QLineEdit(anaPencere)
        self.araKutu.setGeometry(QRect(10, 80, 200, 20))

        self.araKutu.textChanged.connect(self.benzerKelimeler)


        self.kelimeGir = QLabel("Kelimeler:",anaPencere)
        self.kelimeGir.setGeometry(QRect(10, 110, 141, 21))

        self.kelimeGor = QLabel("Kelime Ara",anaPencere)
        self.kelimeGor.setGeometry(QRect(10, 30, 91, 16))
        self.harfGrup=QButtonGroup(anaPencere)
        aharf=QPushButton("â",anaPencere)
        aharf.setGeometry(QRect(10,50,25,25))
        eharf=QPushButton("é",anaPencere)
        eharf.setGeometry(QRect(30,50,25,25))

        self.DilGrup=QButtonGroup(anaPencere)
        self.Dil1 = QPushButton("Zazaca-Türkçe",anaPencere)
        self.Dil1.setGeometry(QRect(230, 80, 91, 23))
        self.Dil1.setCheckable(True)
        self.Dil1.setAutoExclusive(True)
        self.Dil1.setChecked(True)
        self.Dil1.setStyleSheet("background-color: rgb(102, 255, 0);")

        self.Dil2 = QPushButton("Türkçe-Zazaca",anaPencere)
        self.Dil2.setGeometry(QRect(330, 80, 91, 23))
        self.Dil2.setCheckable(True)
        self.Dil2.setAutoExclusive(True)
        self.Dil2.setStyleSheet("background-color: rgb(255, 94, 105);")

        self.DilGrup.addButton(self.Dil1,1)
        self.DilGrup.addButton(self.Dil2,2)
        self.DilGrup.buttonClicked[int].connect(self.dilSecme)
        self.kelimeListesi=QListWidget(anaPencere)
        self.kelimeListesi.setGeometry(QRect(10, 130, 191, 231))

        self.kelimeListesi.itemClicked.connect(self.kelimeAcikla)
        self.kelimeAnlam = QLabel("Kelimenin Anlamı:",anaPencere)
        self.kelimeAnlam.setGeometry(QRect(230, 110, 131, 21))

        self.cumleList1 = QListWidget(anaPencere)
        self.cumleList1.setGeometry(QRect(230, 130, 351, 51))

        self.ornekCumle1 = QLabel("Örnek Zazaca Cümle:",anaPencere)
        self.ornekCumle1.setGeometry(QRect(230, 200, 101, 21))

        self.cumleList2 = QListWidget(anaPencere)
        self.cumleList2.setGeometry(QRect(230, 220, 351, 51))

        self.ornekCumle2 = QLabel("Örnek Türkçe Cümle:",anaPencere)
        self.ornekCumle2.setGeometry(QRect(230, 290, 111, 16))

        self.cumleList3 = QListWidget(anaPencere)
        self.cumleList3.setGeometry(QRect(230, 310, 351, 51))




        self.anaMenu = QMenuBar(anaPencere)
        self.anaMenu.setGeometry(QRect(0, 0, 600, 21))

        self.menuDosya = QMenu("Dosya",self.anaMenu)

        self.menuDuzenle = QMenu("Düzenle",self.anaMenu)

        self.menuYardim = QMenu("Yardım",self.anaMenu)

        anaPencere.setMenuBar(self.anaMenu)

        self.durum = QStatusBar(zemin)
        anaPencere.setStatusBar(self.durum)
        self.durum.setStyleSheet("background-color:white")
        self.durum.showMessage("Hazır")

        self.cikis= QAction(QIcon("Exit.ico"),"&Çıkış",anaPencere)
        self.cikis.setShortcut("Ctrl+X")

        self.cikis.triggered.connect(anaPencere.close)

        self.actionHakkinda = QAction("Hakkında",anaPencere)
        self.actionHakkinda.triggered.connect(self.hakkinda)
        self.actionSecenekler = QAction("Seçenekler",anaPencere)

        self.menuDosya.addAction(self.cikis)
        self.menuDuzenle.addAction(self.actionSecenekler)
        self.menuYardim.addAction(self.actionHakkinda)
        self.anaMenu.addAction(self.menuDosya.menuAction())
        self.anaMenu.addAction(self.menuDuzenle.menuAction())
        self.anaMenu.addAction(self.menuYardim.menuAction())

    def kelimeAcikla(self):
        if self.DilGrup.checkedId()==1:
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()]
            for it in itemtext:
                itemtext=it
            self.im.execute("select Tur from DimTur where Zazaca=?",[itemtext])
            turliste=[tur[0] for tur in self.im.fetchall()]
            for tura in turliste:
                turliste=tura
            self.im.execute("select Turkce from DimTur where Zazaca=?",[itemtext])
            turkAnlam=[tur[0] for tur in self.im.fetchall()]
            for tr in turkAnlam:
                self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr)
            self.im.execute("select OrnekZazacaCumle from DimTur where Zazaca=?",[itemtext])
            ornekZaza=[zaza[0] for zaza in self.im.fetchall()]
            for za in ornekZaza:
                ornekZaza=za
            self.cumleList2.addItem(ornekZaza)
            self.im.execute("select OrnekTurkceCumle from DimTur where Zazaca=?",[itemtext])
            ornekTurk=[turk[0] for turk in self.im.fetchall()]
            for orn in ornekTurk:
                ornekTurk=orn
            self.cumleList3.addItem(ornekTurk)
        if self.DilGrup.checkedId()==2:
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()]
            for it in itemtext:
                itemtext=it
            self.im.execute("select Tur from DimTur where Turkce=?",[itemtext])
            turliste=[tur[0] for tur in self.im.fetchall()]
            for tura in turliste:
                turliste=tura
            self.im.execute("select Zazaca from DimTur where Turkce=?",[itemtext])
            zazaAnlam=[tur[0] for tur in self.im.fetchall()]
            for tr in zazaAnlam:
                self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr)
            self.im.execute("select OrnekZazacaCumle from DimTur where Turkce=?",[itemtext])
            ornekTurk=[turk[0] for turk in self.im.fetchall()]
            for orn in ornekTurk:
                ornekTurk=orn
            self.cumleList2.addItem(ornekTurk)
            self.im.execute("select OrnekTurkceCumle from DimTur where Turkce=?",[itemtext])
            ornekZaza=[zaza[0] for zaza in self.im.fetchall()]
            for za in ornekZaza:
                ornekZaza=za
            self.cumleList3.addItem(ornekZaza)




    def benzerKelimeler(self):
        if self.DilGrup.checkedId()==1:
            self.VT=sqlite3.connect("DimiliVT.sqlite")
            self.im=self.VT.cursor()
            self.kelimeListesi.clear()
            kelime=self.araKutu.text()
            if kelime=="" or kelime==None:
                self.kelimeListesi.clear()
            else:
                self.im.execute("select Zazaca from DimTur where Zazaca like ? order by Zazaca ",[kelime+'%'])
                zazaListe=[za[0] for za in self.im.fetchall()]
                for i in zazaListe:
                 self.kelimeListesi.addItem(i)

        if self.DilGrup.checkedId()==2:
            self.VT=sqlite3.connect("DimiliVT.sqlite")
            self.im=self.VT.cursor()
            kelime=self.araKutu.text()
            self.kelimeListesi.clear()
            if kelime=="" or kelime==None:
                self.kelimeListesi.clear()
            else:
                self.im.execute("select Turkce from DimTur where Turkce like ? ",[kelime+'%'])
                turkListe=[tu[0] for tu in self.im.fetchall()]
                for i in turkListe:
                  self.kelimeListesi.addItem(i)

    def dilSecme(self,ind):
        if ind==1:
            self.araKutu.setText("")
            self.kelimeListesi.clear()
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            self.Dil1.setStyleSheet("background:#66FF00")
            self.Dil2.setStyleSheet("background-color:#E41841")
        if ind==2:
            self.araKutu.setText("")
            self.kelimeListesi.clear()
            self.cumleList1.clear()
            self.cumleList2.clear()
            self.cumleList3.clear()
            self.Dil2.setStyleSheet("background:#66FF00")
            self.Dil1.setStyleSheet("background-color:#E41841")
    def hakkinda(self):
        QMessageBox.about(self, "Program Hakkında",
                "Bu program <b>bla bla</b> tarafından programlanmıştır. 2015")
예제 #38
0
class help_class(QWidget):
	def move_window(self):
		shape=QDesktopWidget().screenGeometry()

		w=shape.width()
		h=shape.height()
		win_w=self.frameGeometry().width()
		win_h=self.frameGeometry().height()

		x=w-win_w
		y=50
		self.move(x,y)

	def help_show(self):
		self.show()
		self.move_window()

	def toggle_visible(self):
		if self.isVisible()==True:
			self.setVisible(False)
		else:
			self.setVisible(True)

		self.move_window()

	def init(self):
		QWidget.__init__(self)
		self.item_height=10
		self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint)
		#self.setFixedSize(400,160)

		self.setStyleSheet(" padding:0px; margin-top:0px; margin-bottom:0px")
		#; border:2px solid rgb(0, 0, 0); 

		self.last=[]
		self.pos=-1

		self.move_window()
		self.vbox = QVBoxLayout()

		#self.vbox.setAlignment(Qt.AlignTop)
		self.box=[]
		self.image=[]
		self.label=[]
		for i in range(0,5):
			l=QHBoxLayout()
			label=QLabel()
			label.setWordWrap(True)
	
			image=QLabel()
			image.setFixedWidth(48)

			self.box.append( QWidget())
			self.image.append(image)
			label.setAlignment(Qt.AlignLeft | Qt.AlignTop)
			self.label.append(label)

			self.box[i].setLayout(l)
			#self.box[i].setFixedSize(380,80)	#setMinimumSize(400, 500)#
			l.addWidget(self.image[i])
			l.addWidget(self.label[i])

		toolbar=QToolBar()
		toolbar.setIconSize(QSize(48, 48))

		self.back = QAction(QIcon(os.path.join(get_image_file_path(),"left.png")), 'Back', self)
		self.back.triggered.connect(self.callback_back)
		toolbar.addAction(self.back)

		self.forward= QAction(QIcon(os.path.join(get_image_file_path(),"right.png")), 'Next', self)
		self.forward.triggered.connect(self.callback_forward)
		toolbar.addAction(self.forward)


		spacer = QWidget()
		spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
		toolbar.addWidget(spacer)


		self.undo = QAction(QIcon(os.path.join(get_image_file_path(),"www.png")), 'Online help', self)
		self.undo.setStatusTip(_("On line help"))
		self.undo.triggered.connect(self.on_line_help)
		toolbar.addAction(self.undo)

		self.undo = QAction(QIcon(os.path.join(get_image_file_path(),"close.png")), 'Hide', self)
		self.undo.setStatusTip(_("Close"))
		self.undo.triggered.connect(self.callback_close)
		toolbar.addAction(self.undo)




		self.vbox.addWidget(toolbar)

		for i in range(0,5):
			self.vbox.addWidget(self.box[i])

		self.vbox.addStretch()

		self.status_bar = QStatusBar()
		self.vbox.addWidget(self.status_bar)
		
		self.setLayout(self.vbox)
		self.show()


	def callback_close(self,widget):
		self.toggle_visible()

	def callback_forward(self,widget):
		self.pos=self.pos+1
		if self.pos>=len(self.last):
			self.pos=len(self.last)-1

		self.update()

	def callback_back(self,widget):
		self.pos=self.pos-1
		if self.pos<0:
			self.pos=0
		self.update()

	def on_line_help(self,widget):
		webbrowser.open('http://www.gpvdm.com/man/index.html')

	def update(self):
		items=int(len(self.last[self.pos])/2)
		for i in range(0,5):
			self.box[i].hide()

		for i in range(0,items):
			pixmap = QPixmap(os.path.join(get_image_file_path(),self.last[self.pos][i*2]))
			self.image[i].setPixmap(pixmap)
			text=self.last[self.pos][i*2+1]+"<br>"
			self.label[i].setText(text)
			height=(len(text)/80)*30
			self.label[i].setFixedSize(380,height)
			self.box[i].show()
			#self.image[i].show()

		self.resize(300, items*self.item_height)

		self.forward.setEnabled(True)
		self.back.setEnabled(True)

		if self.pos==0:
			self.back.setEnabled(False)

		if self.pos==len(self.last)-1:
			self.forward.setEnabled(False)

		self.status_bar.showMessage(str(self.pos)+"/"+str(len(self.last)-1))

	def help_set_help(self,array):
		add=True
		if len(self.last)!=0:
			if self.last[self.pos][1]==array[1]:
				add=False

		if add==True:
			self.pos=self.pos+1
			self.last.append(array)

		self.update()
		self.move_window()

	def help_append(self,array):
		last_item=len(self.last)-1
		self.last[last_item]=self.last[last_item] + array
		self.update()
		#self.resize(300, 150)
		self.move_window()
예제 #39
0
class MainWindow(QMainWindow):

    l = logging.getLogger('MainWindow')

    def __init__(self, app):
        QMainWindow.__init__(self, None)
        self.l.debug('Initializing MainWindow ...')

        self.setWindowTitle('MynPad')
        app.setWindowIcon(QIcon(':/icons/mynpad.png'))

        if os.name == 'nt':
            # On Windows, make sure to use a unique Application User Model Id, otherwise
            # Windows shows the default python icon in the taskbar
            # see http://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7
            myappid = 'afester.mynpad'
            import ctypes; ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

        self.theApplication = app
        app.aboutToQuit.connect(self.saveState)

        # read the local configuration file
        iniPath = 'mynpad.ini'
        if not os.path.exists(iniPath):
            iniPath = os.path.join(expanduser("~"), iniPath)
        self.settings = Settings(iniPath)
        self.settings.load()

        # Set up the menu bar
        menuBar = QMenuBar(self)

        exitAction = QAction("Exit", self, triggered=self.theApplication.exit)
        fileMenu = menuBar.addMenu("&File")
        fileMenu.addAction(exitAction)

        aboutAction = QAction("About ...", self, triggered = self.handleAbout)
        helpMenu = menuBar.addMenu("&Help")
        helpMenu.addAction(aboutAction)

        self.setMenuBar(menuBar)

        # Setup the status bar
        self.statusBar = QStatusBar()
        self.statusBar.showMessage("Ready.")
        self.setStatusBar(self.statusBar)
        self.mainWidget = CentralWidget(self, self.settings)
        self.mainWidget.updateWindowTitle.connect(self.updateWindowTitle)
        self.setCentralWidget(self.mainWidget)

        # Reset main window size and position
        pos = self.settings.getMainWindowPos()
        self.move(pos.x(), pos.y())
        size = self.settings.getMainWindowSize()
        self.resize(size)

        # initialize the browser tree (add the top nodes and expand the saved path)
        self.mainWidget.browserWidget.initialize()


    def updateWindowTitle(self, title):
        self.setWindowTitle('{} - MynPad'.format(title))


    def saveState(self):
        # Make sure that the current notepad page is saved
        self.mainWidget.editorWidget.save()

        # Note: there is no way to have eclipse shutdown the application faithfully,
        # see also http://stackoverflow.com/questions/677531/is-it-possible-for-eclipse-to-terminate-gently-instead-of-using-sigkill
        path = self.mainWidget.browserWidget.getCurrentPath()
        self.settings.setBrowserPath(path)
        self.settings.setMainWindowPos(self.pos())
        self.settings.setMainWindowSize(self.size())
        self.settings.save()

        # Close all notepads - TODO (HACK)
        for x in range (0, self.mainWidget.browserWidget.browserView.topLevelItemCount()):
            notepad = self.mainWidget.browserWidget.browserView.topLevelItem(x).getNotepad()
            notepad.close()


    def handleAbout(self):
        appVersion = "Development version"
        pythonVersion = "%s.%s.%s (%s)" % (sys.version_info[0], sys.version_info[1], sys.version_info[2], sys.version_info[3])
        pyQtVersion = PYQT_VERSION_STR
        pyQtQtVersion = QT_VERSION_STR
        qtRuntimeVersion = qVersion()
        
        platformSystem = platform.system()
        platformRelease = platform.release()

        QMessageBox.about(self, "About MynPad",
                          "Copyright \u00a9 2015 by Andreas Fester<br/>"+
                          "<table>"+
                          "<tr><th align=\"right\">Application version:</th><td>{}</td></tr>".format(appVersion) +
                          "<tr><th align=\"right\">Python version:</th><td>{}</td></tr>".format(pythonVersion) +
                          "<tr><th align=\"right\">PyQt version:</th><td>{} for Qt {}</td></tr>".format(pyQtVersion, pyQtQtVersion) +
                          "<tr><th align=\"right\">Qt runtime version:</th><td>{}</td></tr>".format(qtRuntimeVersion)+
                          "<tr><th align=\"right\">Operating System:</th><td>{} {}</td></tr>".format(platformSystem, platformRelease)+
                          "<tr><th align=\"right\">sqlite version:</th><td>{}</td></tr>".format(sqlite3.version) +
                          "<tr><th align=\"right\">sqlite runtime version:</th><td>{}</td></tr>".format(sqlite3.sqlite_version)+
                          "</table>")
예제 #40
0
class DatasFilterWindow(QMainWindow):
    manual_get_coor = pyqtSignal()

    def __init__(self):
        super(DatasFilterWindow, self).__init__()
        self.setObjectName('MainWindow')
        self.setStyleSheet(StyleTool.readQSS('./style_bright.qss'))
        self.setWindowTitle('数据筛选')
        self.resize(650, 600)
        self.setWindowFlags(Qt.WindowMinimizeButtonHint
                            | Qt.WindowCloseButtonHint)
        self.setFocus(Qt.MouseFocusReason)
        self.setup_ui()
        self.conn = sqlite3.connect('target_company.db')
        self.signal_slot()

        self.area = ''
        self.Id = None
        self.jobId = None
        # 标志
        self.is_begined = False

    def setup_ui(self):
        # 创建布局
        layout = QVBoxLayout()
        layout1 = QHBoxLayout()
        layout2 = QHBoxLayout()
        layout3 = QHBoxLayout()
        layout4 = QHBoxLayout()
        layout5 = QHBoxLayout()

        # 创建控件
        company_name_tag = QLabel('公司名称')
        self.company_name = QLabel('')
        company_addr_tag = QLabel('公司地址')
        self.company_addr = QLabel('')
        company_scale_tag = QLabel('公司规模')
        self.company_scale = QLabel('')
        company_area_tag = QLabel('所处地区')
        self.company_area = QLabel('')
        job_name_tag = QLabel('职位名称')
        self.job_name = QLabel('')
        job_url = QLabel('职位链接')
        self.job_url = QLabel('')
        coordinate_tag = QLabel('经纬度')
        self.coordinate = QLineEdit()
        # QTextBrowser
        self.company_desc_browser = QTextBrowser()
        self.job_desc_browser = QTextBrowser()
        # QLineEdit
        self.note_ledit = QLineEdit()
        self.note_ledit.setPlaceholderText('备注')
        self.possible_ledit = QLineEdit()
        self.possible_ledit.setFixedWidth(132)
        self.possible_ledit.setPlaceholderText('可能性')
        self.keyword_edit = QLineEdit()
        self.keyword_edit.setFixedWidth(62)
        self.keyword_edit.setPlaceholderText('城市')

        # 按钮
        self.save_btn = QPushButton('保存')
        self.save_btn.setContentsMargins(0, 0, 0, 0)
        self.begin_btn = QPushButton('开始')
        self.begin_btn.setContentsMargins(0, 0, 0, 0)
        self.del_btn = QPushButton('删除')
        self.del_btn.setContentsMargins(0, 0, 0, 0)
        self.view_final_result_btn = QPushButton('查看筛选结果')

        # 进度栏
        self.process_bar = QProgressBar()
        self.process_bar.setFormat('%v/%m')
        # 状态栏
        self.status = QStatusBar()
        self.setStatusBar(self.status)
        self.status.setStyleSheet('QStatusBar{color:red;}')
        # 布置布局

        layout.addLayout(layout1)
        layout1.addWidget(job_name_tag)
        layout1.addWidget(self.job_name)
        layout1.addStretch(1)
        layout1.addWidget(self.keyword_edit)
        layout1.addWidget(self.begin_btn)
        layout1.addWidget(self.view_final_result_btn)
        layout.addLayout(layout2)
        layout2.addWidget(company_name_tag)
        layout2.addWidget(self.company_name)
        layout2.addStretch(1)
        layout2.addWidget(self.note_ledit, 1)
        layout.addLayout(layout3)
        layout3.addWidget(company_scale_tag)
        layout3.addWidget(self.company_scale)
        layout3.addStretch(1)
        layout3.addWidget(company_area_tag)
        layout3.addWidget(self.company_area)
        layout3.addStretch(3)
        layout3.addWidget(self.possible_ledit)
        layout.addLayout(layout4)
        layout4.addWidget(company_addr_tag)
        layout4.addWidget(self.company_addr)
        layout4.addStretch(1)
        layout4.addWidget(self.save_btn)
        layout4.addWidget(self.del_btn)
        layout.addLayout(layout5)
        layout5.addWidget(job_url)
        layout5.addWidget(self.job_url)
        layout5.addStretch(1)
        layout5.addWidget(coordinate_tag)
        layout5.addWidget(self.coordinate)

        layout.addWidget(self.company_desc_browser)
        layout.addWidget(self.job_desc_browser)
        layout.addWidget(self.process_bar)

        center_widget = QWidget()
        center_widget.setLayout(layout)
        self.setCentralWidget(center_widget)

    def signal_slot(self):
        self.save_btn.clicked.connect(self.save)
        self.del_btn.clicked.connect(self.delete)
        self.begin_btn.clicked.connect(self.begin)
        self.view_final_result_btn.clicked.connect(self.view_final_result)
        # self.begin_btn.setShortcut(_translate('MainWindow', 'Enter'))
        self.del_shortcut = QShortcut(QKeySequence('Ctrl+D'), self)
        self.del_shortcut.activated.connect(self.delete)
        self.begin_sc = QShortcut(QKeySequence('ctrl+b'), self)
        self.begin_sc.activated.connect(self.begin)
        self.quit_sc = QShortcut(QKeySequence('Meta+q'), self)
        self.quit_sc.activated.connect(
            lambda: sys.exit(QApplication(sys.argv).exec_()))
        self.save_sc = QShortcut(QKeySequence('ctrl+s'), self)
        self.save_sc.activated.connect(self.save)
        self.manual_get_coor.connect(self.manual_save_coor)

    def begin(self):
        c = self.conn.cursor()
        # 根据输入的城市 获取对应的城市数据
        city = self.keyword_edit.text()
        if city:
            self.keyword_edit.clearFocus()
            sql = "select id from areas where area='{}';".format(city)
            print(sql)
            try:
                area_id = c.execute(sql).fetchone()[0]
            except IndexError:
                print('该城市数据不存在')
            except Exception as e:
                print(e)
            # 筛选出该区域的所有数据
            else:
                sql = "select id, company_id, job_id from raw_datas where area_id='{}' and is_read=0 order by weight desc;".format(
                    area_id)
                results = c.execute(sql).fetchall()
                total = len(results)
                self.status.showMessage('数据量:{}'.format(total), 10000)
                self.process_bar.setMaximum(total)
                # 主要效果 阻塞for循环 通过按钮解除阻塞
                self.t = Thread(results)
                self.t.id_pipLine.connect(self.show_loop)
                self.t.valueChange.connect(self.process_bar.setValue)
                self.t.task_finished.connect(self.finished)
                self.t.start()

                self.area = city
                self.is_begined = True
                print('--')
        else:
            print('未输入城市')

    def show_loop(self, e):
        """循环显示"""
        self.Id = e[0]
        company_id = e[1]
        self.jobId = e[2]
        c = self.conn.cursor()
        sql = "select company_name, company_address, company_scale, company_desc from companies where id={};".format(
            company_id)
        self.company_info = c.execute(sql).fetchone()
        sql = "select job_name, job_desc, job_url from jobs where id={};".format(
            self.jobId)
        self.job_info = c.execute(sql).fetchone()
        # print(self.company_info, '\n', self.job_info, sep='')
        if self.company_info and self.job_info:
            self.job_name.setText(self.job_info[0].strip())
            self.company_name.setText(self.company_info[0])
            self.company_scale.setText(self.company_info[2])
            self.company_area.setText(self.area)
            self.company_addr.setText(self.company_info[1])
            self.company_desc_browser.setPlainText(self.company_info[-1])
            self.job_desc_browser.setPlainText(self.job_info[1])
        # todo:职位链接太长
        # self.job_url.setText(self.job_info[2])

    def save(self):
        """
        保存该组数据到新的数据表
        并更新地图用数据
        并显示下一条"""
        possible = self.possible_ledit.text()
        note = self.note_ledit.text()

        if possible:
            c = self.conn.cursor()
            # 获取公司地址的经纬度
            addr = self.company_info[1]
            try:
                result = get_coordinate(addr)
            except requests.exceptions.ConnectTimeout:
                self.status.showMessage('获取坐标超时,请检查网络连接', 5000)
                return
            else:
                print('result', result)
                if not result:
                    self.status.showMessage('抱歉无法获取该位置定位', 3000)
                    self.manual_get_coor.emit()
                elif result['precise'] == 0:
                    self.status.showMessage('该位置的坐标准确性未知', 3000)
                else:
                    # 插入数据到map_datas
                    sql = "insert into map_datas(locate_addr, lat, lng, precise) " \
                          "values('{}', {}, {}, {});".format(result['locate_addr'], result['lat'],
                                                             result['lng'], result['precise'])
                    c.execute(sql)
            # 获取刚刚插入数据的map_id
            sql = "select max(id) from map_datas;"
            max_map_id = c.execute(sql).fetchone()[0]
            # 插入数据到final_datas
            sql = "insert into final_datas(possible, note, raw_id, map_id) values('{}','{}',{}, {});".format(
                possible, note, self.Id, max_map_id)
            c.execute(sql)
            # 更新raw_datas的is_read值 表示已经筛选过,下次不再显示
            sql = "update raw_datas set is_read=1 where id={};".format(self.Id)
            c.execute(sql)
            self.conn.commit()
            # 清除输入控件当前的数据
            self.note_ledit.clear()
            self.possible_ledit.clear()
            self.coordinate.clear()
            self.possible_ledit.clearFocus()
            # 检测当前城市是否还有未筛选的数据组
            if self.is_begined and self.process_bar.value(
            ) < self.process_bar.maximum():
                self.t.next()
            else:
                print('没有next了')
        else:
            # 提醒没有填写可能性
            self.status.showMessage('没填可能性', 3000)

    def delete(self):
        """删除该组数据 并显示下一条"""
        c = self.conn.cursor()
        sql = "delete from raw_datas where id={};".format(self.Id)
        try:
            c.execute(sql)
        except sqlite3.OperationalError:
            self.status.showMessage('当前没有数据', 3000)
            return
        sql = "delete from jobs where id={};".format(self.jobId)
        c.execute(sql)
        self.conn.commit()
        self.note_ledit.clear()
        self.possible_ledit.clear()
        if self.is_begined and self.process_bar.value(
        ) < self.process_bar.maximum():
            self.t.next()
        else:
            print('没有next了')

    def finished(self):
        self.status.showMessage('任务结束', 5000)
        self.job_name.clear()
        self.company_name.clear()
        self.company_scale.clear()
        self.company_addr.clear()
        self.company_area.clear()
        self.note_ledit.clear()
        self.possible_ledit.clear()
        self.company_desc_browser.clear()
        self.job_desc_browser.clear()

    def get_position(self, addr):
        """
        百度坐标系获取
        :param addr:
        :return:
        """
        ak = 'ysZHXY6AwYQYcXLuhTCkV2a1YvOk5Dm2'
        url = 'http://api.map.baidu.com/geocoding/v3/?address={}&output=json&ak={}'.format(
            addr, ak)
        return requests.get(url=url).json()

    def manual_save_coor(self):
        result = self.coordinate.text()
        if result:
            c = self.conn.cursor()
            # 插入数据到map_datas
            result = result.split(',')
            sql = "insert into map_datas(lat, lng) " \
                  "values('{}', {});".format(float(result[0].strip()), float(result[1].strip()))
            c.execute(sql)
            self.conn.commit()
            self.status.showMessage('已手动定位', 3000)
        else:
            return

    def view_final_result(self):
        # 使用poltly制图 对应的数据格式整理
        save_plotly_map(get_plotly_datas())
예제 #41
0
class MainWindow_Ui(QMainWindow):
    def __init__(self):
        super().__init__()
#MainWindow
        self.resize(600, 400)
        self.setMinimumSize(QSize(600, 400))
        self.setMaximumSize(QSize(16777215, 16777215))
        self.setWindowTitle("Persepolis Download Manager")
        self.setWindowIcon(QIcon('icon'))
        
        self.centralwidget = QWidget(self)
        self.verticalLayout = QVBoxLayout(self.centralwidget)
#enable drag and drop 
        self.setAcceptDrops(True)
#frame
        self.frame = QFrame(self.centralwidget)
        self.frame.setGeometry(QRect(10, 10, 581, 251))
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.gridLayout = QGridLayout(self.frame)
 

#tablewidget
        self.download_table = QTableWidget(self.frame)
        self.download_table.setGeometry(QRect(10, 10, 560, 231))
        self.download_table.setSizeIncrement(QSize(0, 0))
        self.download_table.setColumnCount(10)
        self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.download_table.verticalHeader().hide()
        self.download_table.setColumnHidden(8 , True)
        self.download_table.setColumnHidden(9 , True)

        self.gridLayout.addWidget(self.download_table, 0, 0, 1, 1)
        self.verticalLayout.addWidget(self.frame)
 
        self.setCentralWidget(self.centralwidget)

        download_table_header = ['File Name' , 'Status' , 'Size' , 'Downloaded' , 'Percentage' , 'Connections' , 'Transfer rate' , 'Estimate time left' , 'Gid' , 'Info']
        self.download_table.setHorizontalHeaderLabels(download_table_header)    
#fixing the size of download_table when window is Maximized!
        self.download_table.horizontalHeader().setSectionResizeMode(0)
        self.download_table.horizontalHeader().setStretchLastSection(True)
#finding number od row that user selected!
        self.download_table.itemSelectionChanged.connect(self.selectedRow)
   



#menubar
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QRect(0, 0, 600, 24))
        self.setMenuBar(self.menubar)
        fileMenu = self.menubar.addMenu('File')
        editMenu = self.menubar.addMenu('Edit')
        viewMenu = self.menubar.addMenu('View')
        downloadMenu = self.menubar.addMenu('Download')
        helpMenu = self.menubar.addMenu('Help')


#statusbar
        self.statusbar = QStatusBar(self)
        self.setStatusBar(self.statusbar)
        self.statusbar.showMessage("Persepolis Download Manager")
#toolBar
        self.toolBar = QToolBar(self)
        self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.toolBar.setWindowTitle("toolBar")
        self.toolBar.setIconSize(QSize(38 , 38))
        self.toolBar.setFloatable(False)
        self.toolBar.setMovable(False)

#toolBar and menubar and actions
        self.stopAllAction = QAction(QIcon(icons + 'stop_all') , 'Stop all active downloads' , self , statusTip = 'Stop all active downloads', triggered = self.stopAllDownloads )
        downloadMenu.addAction(self.stopAllAction)

        self.pauseAllAction = QAction(QIcon(icons + 'pause_all') , 'Pause all active downloads' , self , statusTip = 'Pause all active downloads', triggered = self.pauseAllDownloads )
        downloadMenu.addAction(self.pauseAllAction)


        self.minimizeAction = QAction(QIcon(icons + 'minimize') , 'Minimize to system tray' , self , shortcut = "Ctrl+W" , statusTip = "Minimize to system tray" , triggered = self.minMaxTray) 
        viewMenu.addAction(self.minimizeAction)

    

        self.addlinkAction = QAction(QIcon(icons + 'add') , 'Add New Download Link' , self , shortcut = "Ctrl+N" , statusTip = "Add New Download Link" , triggered = self.addLinkButtonPressed) 
        fileMenu.addAction(self.addlinkAction)


        self.resumeAction = QAction(QIcon(icons + 'play') , 'Resume Download' , self , shortcut = "Ctrl+R" , statusTip = "Resume Download" , triggered = self.resumeButtonPressed)
        downloadMenu.addAction(self.resumeAction)


        self.pauseAction = QAction(QIcon(icons + 'pause') , 'Pause Download' , self , shortcut = "Ctrl+C" , statusTip = "Pause Download" , triggered = self.pauseButtonPressed)
        downloadMenu.addAction(self.pauseAction)

       

        self.stopAction = QAction(QIcon(icons + 'stop') , 'Stop Download' , self , shortcut = "Ctrl+S" , statusTip = "Stop/Cancel Download" , triggered = self.stopButtonPressed)
        downloadMenu.addAction(self.stopAction)

        self.removeAction = QAction(QIcon(icons + 'trash') , 'Remove Download' , self , shortcut = "Ctrl+D" , statusTip = "Remove Download" , triggered = self.removeButtonPressed)
        downloadMenu.addAction(self.removeAction)

        self.propertiesAction = QAction(QIcon(icons + 'setting') , 'Properties' , self , shortcut = "Ctrl+P" , statusTip = "Properties" , triggered = self.propertiesButtonPressed )
        downloadMenu.addAction(self.propertiesAction)

        self.progressAction = QAction(QIcon(icons + 'window') , 'Progress' , self , shortcut = "Ctrl+Z" , statusTip = "Progress" , triggered = self.progressButtonPressed )
        downloadMenu.addAction(self.progressAction)


        self.exitAction = QAction(QIcon(icons + 'exit') , 'Exit' , self , shortcut = "Ctrl+Q" , statusTip = "Exit" , triggered = self.close)
        fileMenu.addAction(self.exitAction)

        self.preferencesAction = QAction(QIcon(icons + 'preferences') , 'Preferences' , self , statusTip = 'Preferences' , triggered = self.openPreferences)
        editMenu.addAction(self.preferencesAction)

        self.aboutAction = QAction(QIcon(icons + 'about') , 'About' , self , statusTip = 'About' , triggered = self.openAbout)
        helpMenu.addAction(self.aboutAction)

        


        for i in self.addlinkAction,self.resumeAction, self.pauseAction , self.stopAction, self.removeAction , self.propertiesAction, self.progressAction , self.exitAction :
            self.toolBar.addAction(i)
         

        self.toolBar.insertSeparator(self.addlinkAction)
        self.toolBar.insertSeparator(self.resumeAction)     
        self.toolBar.insertSeparator(self.removeAction)
        self.toolBar.insertSeparator(self.exitAction)
        self.toolBar.addSeparator()
예제 #42
0
class ConfigParamEditWindow(QDialog):
    def __init__(self, parent, node, target_node_id, param_struct, update_callback):
        super(ConfigParamEditWindow, self).__init__(parent)
        self.setWindowTitle("Edit configuration parameter")
        self.setModal(True)

        self._node = node
        self._target_node_id = target_node_id
        self._param_struct = param_struct
        self._update_callback = update_callback

        min_val = get_union_value(param_struct.min_value)
        if "uavcan.protocol.param.Empty" in str(min_val):
            min_val = None

        max_val = get_union_value(param_struct.max_value)
        if "uavcan.protocol.param.Empty" in str(max_val):
            max_val = None

        value = get_union_value(param_struct.value)
        self._value_widget = None
        value_type = uavcan.get_active_union_field(param_struct.value)

        if value_type == "integer_value":
            min_val = min_val if min_val is not None else -0x8000000000000000
            max_val = max_val if max_val is not None else 0x7FFFFFFFFFFFFFFF
            if min_val >= -0x80000000 and max_val <= +0x7FFFFFFF:
                self._value_widget = QSpinBox(self)
                self._value_widget.setMaximum(max_val)
                self._value_widget.setMinimum(min_val)
                self._value_widget.setValue(value)
        if value_type == "real_value":
            min_val = round_float(min_val) if min_val is not None else -3.4028235e38
            max_val = round_float(max_val) if max_val is not None else 3.4028235e38
            value = round_float(value)
        if value_type == "boolean_value":
            self._value_widget = QCheckBox(self)
            self._value_widget.setChecked(bool(value))

        if self._value_widget is None:
            self._value_widget = QLineEdit(self)
            self._value_widget.setText(str(value))
        self._value_widget.setFont(get_monospace_font())

        layout = QGridLayout(self)

        def add_const_field(label, *values):
            row = layout.rowCount()
            layout.addWidget(QLabel(label, self), row, 0)
            if len(values) == 1:
                layout.addWidget(FieldValueWidget(self, values[0]), row, 1)
            else:
                sub_layout = QHBoxLayout(self)
                for idx, v in enumerate(values):
                    sub_layout.addWidget(FieldValueWidget(self, v))
                layout.addLayout(sub_layout, row, 1)

        add_const_field("Name", param_struct.name)
        add_const_field("Type", uavcan.get_active_union_field(param_struct.value).replace("_value", ""))
        add_const_field("Min/Max", min_val, max_val)
        add_const_field("Default", render_union(param_struct.default_value))

        layout.addWidget(QLabel("Value", self), layout.rowCount(), 0)
        layout.addWidget(self._value_widget, layout.rowCount() - 1, 1)

        fetch_button = make_icon_button(
            "refresh", "Read parameter from the node", self, text="Fetch", on_clicked=self._do_fetch
        )
        set_default_button = make_icon_button(
            "fire-extinguisher", "Restore default value", self, text="Restore", on_clicked=self._restore_default
        )
        send_button = make_icon_button(
            "flash", "Send parameter to the node", self, text="Send", on_clicked=self._do_send
        )
        cancel_button = make_icon_button(
            "remove", "Close this window; unsent changes will be lost", self, text="Cancel", on_clicked=self.close
        )

        controls_layout = QGridLayout(self)
        controls_layout.addWidget(fetch_button, 0, 0)
        controls_layout.addWidget(send_button, 0, 1)
        controls_layout.addWidget(set_default_button, 1, 0)
        controls_layout.addWidget(cancel_button, 1, 1)
        layout.addLayout(controls_layout, layout.rowCount(), 0, 1, 2)

        self._status_bar = QStatusBar(self)
        self._status_bar.setSizeGripEnabled(False)
        layout.addWidget(self._status_bar, layout.rowCount(), 0, 1, 2)

        left, top, right, bottom = layout.getContentsMargins()
        bottom = 0
        layout.setContentsMargins(left, top, right, bottom)

        self.setLayout(layout)

    def show_message(self, text, *fmt):
        self._status_bar.showMessage(text % fmt)

    def _assign(self, value_union):
        value = get_union_value(value_union)

        if uavcan.get_active_union_field(value_union) == "real_value":
            value = round_float(value)

        if hasattr(self._value_widget, "setValue"):
            self._value_widget.setValue(value)
            self._update_callback(value)
        elif hasattr(self._value_widget, "setChecked"):
            self._value_widget.setChecked(bool(value))
            self._update_callback(bool(value))
        else:
            self._value_widget.setText(str(value))
            self._update_callback(value)

    def _on_response(self, e):
        if e is None:
            self.show_message("Request timed out")
        else:
            logger.info("Param get/set response: %s", e.response)
            self._assign(e.response.value)
            self.show_message("Response received")

    def _restore_default(self):
        self._assign(self._param_struct.default_value)

    def _do_fetch(self):
        try:
            request = uavcan.protocol.param.GetSet.Request(name=self._param_struct.name)
            self._node.request(request, self._target_node_id, self._on_response, priority=REQUEST_PRIORITY)
        except Exception as ex:
            show_error("Node error", "Could not send param get request", ex, self)
        else:
            self.show_message("Fetch request sent")

    def _do_send(self):
        value_type = uavcan.get_active_union_field(self._param_struct.value)

        try:
            if value_type == "integer_value":
                if hasattr(self._value_widget, "value"):
                    value = int(self._value_widget.value())
                else:
                    value = int(self._value_widget.text())
                self._param_struct.value.integer_value = value
            elif value_type == "real_value":
                value = float(self._value_widget.text())
                self._param_struct.value.real_value = value
            elif value_type == "boolean_value":
                value = bool(self._value_widget.isChecked())
                self._param_struct.value.boolean_value = value
            elif value_type == "string_value":
                value = self._value_widget.text()
                self._param_struct.value.string_value = value
            else:
                raise RuntimeError("This is not happening!")
        except Exception as ex:
            show_error("Format error", "Could not parse value", ex, self)
            return

        try:
            request = uavcan.protocol.param.GetSet.Request(name=self._param_struct.name, value=self._param_struct.value)
            logger.info("Sending param set request: %s", request)
            self._node.request(request, self._target_node_id, self._on_response, priority=REQUEST_PRIORITY)
        except Exception as ex:
            show_error("Node error", "Could not send param set request", ex, self)
        else:
            self.show_message("Set request sent")
예제 #43
0
class MainWindow(QMainWindow):
    """
    主窗口界面
    """

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        # 初始化
        self.init()
        # ui设计
        self.setup_ui()
        # 创建右键菜单
        self.create_context_menu()
        # 主框体设计
        self.set_main_form()
        # 加载qss样式
        self.load_qss()

    def init(self):
        self.setGeometry(Const.WIN_X, Const.WIN_Y, Const.WIN_WIDTH, Const.WIN_HEIGHT)
        self.setObjectName('mainWindow')
        self.setWindowIcon(QIcon("./image/Logo/logo.png"))
        self.setWindowTitle('IFR智能公式识别系统')

        # 加载图片缩放公共类
        self.imageScale = ImageScale()

    def setup_ui(self):
        """
        创建状态栏、菜单栏、工具栏
        """

        # 状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage('准备就绪', 5000)
        # self.statusBar().setStyleSheet('background-color:lightGray;')

        # 菜单栏
        self.menubar = QMenuBar()
        self.setMenuBar(self.menubar)
        # self.menuBar().setStyleSheet('background-color:lightGray;')

        # 文件
        self.fileMenu = self.menubar.addMenu('&文件(F)')

        # 调用自定义action
        self.openPimax = Action.action_b_2(self, 'openPimax', '&打开图片文件', 'Ctrl+P', '打开图片文件')
        self.openPimax.setIcon(QIcon('./image/openQpixmap.jpg'))
        self.openText = Action.action_b_2(self, 'openText', '&打开文本文件', 'Ctrl+T', '打开文本文件')
        self.openText.setIcon(QIcon('./image/openText.ico'))
        self.openFile = Action.action_b_3(self, 'openFile', '打开文件', '打开文件', self.fileMenu)
        self.openFile.addAction(self.openPimax)
        self.openFile.addAction(self.openText)

        self.openPimax.triggered.connect(lambda: self.get_image())
        self.openText.triggered.connect(lambda: self.get_text())
        self.openRecentFile = Action.action_a_2(self, 'openRecentFile', '&最近打开的文件', 'Ctrl+O', '最近打开的文件', self.fileMenu)
        # self.openRecentFile.triggered.connect(self.)
        self.save = Action.action_a_2(self, 'save', '&保存分析结果', 'Ctrl+S', '保存数据分析结果', self.fileMenu)
        # self.save.triggered.connect(self.)
        self.saveAs = Action.action_a_2(self, 'saveAs', '&另保存分析结果', 'Ctrl+Shift+S', '另保存数据分析结果', self.fileMenu)
        # self.saveAs.triggered.connect(self.)
        self.printf = Action.action_a_2(self, 'printef', '&打印分析结果', 'Ctrl+P', '打印数据分析结果', self.fileMenu)
        # self.printf.triggered.connect(self.)
        self.exitAction = Action.action_a_1(self, 'exitAction', './image/mainWindowIcon/toolBarIcon/exit.png', '&退出',
                                            'Ctrl+Q', '退出应用程序',
                                            self.fileMenu)
        self.exitAction.triggered.connect(self.close)

        # 编辑
        self.exitMenu = self.menubar.addMenu('&编辑(E)')
        #
        # ####################查找与替换####################开始
        self.search = Action.action_b_2(self, 'search', '&快速查找', 'Ctrl+F', '快速查找')
        self.replace = Action.action_b_2(self, 'replace', '&快速替换', 'Ctrl+H', '快速替换')

        # 新增二级菜单
        self.searchAndReplaceMenu = Action.action_b_3(self, 'searchAndReplaceMenu', '查找与替换', '查找与替换', self.exitMenu)
        self.searchAndReplaceMenu.addAction(self.search)
        self.searchAndReplaceMenu.addAction(self.replace)

        # self.search.triggered.connect(self.)
        # self.replace.triggered.connect(self.)

        # ####################查找与替换####################结束

        self.cut = Action.action_a_2(self, 'cut', '&剪切', 'Ctrl+X', '剪切', self.exitMenu)
        # self.cut.triggered.connect(self.)
        self.copy = Action.action_a_2(self, 'copy', '&复制', 'Ctrl+C', '复制', self.exitMenu)
        # self.copy.triggered.connect(self.)
        self.paste = Action.action_a_2(self, 'paste', '&粘贴', 'Ctrl+V', '粘贴', self.exitMenu)
        # self.paste.triggered.connect(self.)
        self.delete = Action.action_a_2(self, 'delect', '&删除', 'Del', '删除', self.exitMenu)
        # self.delect.triggered.connect(self.)
        self.selectAll = Action.action_a_2(self, 'selectAll', '&全选', 'Ctrl+Alt', '全选', self.exitMenu)
        # self.selectAll.triggered.connect(self.)

        # 视图
        self.viewMenu = self.menubar.addMenu('&视图(V)')

        self.notice = Action.action_a_2(self, 'notice', '&通知', 'Ctrl+Alt+X', '信息通知提醒', self.viewMenu)
        # self.notice.triggered.connect(self.)

        # ####################窗口管理####################开始
        self.window = Action.action_b_3(self, 'window', '&窗口', '展示一些基本窗口', self.viewMenu)

        # ####################窗口管理####################结束
        #
        #
        #
        # ####################工具栏####################开始
        self.tool = Action.action_b_3(self, 'tool', '&工具栏', '基本工具', self.viewMenu)

        self.calculator = Action.action_a_1(self, 'calculator', './image/calculator.jpg', '&计算器',
                                            'C', '计算器', self.viewMenu)
        self.calculator.triggered.connect(lambda: self.calculator_win())

        # ####################工具####################结束
        self.fullScreen = Action.action_a_2(self, 'fullScreen', '&全屏幕', 'Shift+Alt+Enter', '全屏', self.viewMenu)
        # self.fullScreen.triggered.connect(self.)
        self.propertyWindow = Action.action_a_2(self, 'propertyWindow', '&属性窗口', 'F4', '属性窗口', self.viewMenu)
        # self.propertyWindow.triggered.connect(self.)
        #

        # 分析
        self.navigateMenu = self.menubar.addMenu('&分析(N)')
        #

        # 工具
        self.toolMenu = self.menubar.addMenu('&工具(T)')
        #

        # 扩展
        self.extendMenu = self.menubar.addMenu('&扩展(X)')
        #

        # 窗口
        self.windowMenu = self.menubar.addMenu('&窗口(W)')
        #

        # 帮助
        self.helpMenu = self.menubar.addMenu('&帮助(H)')

        self.help = Action.action_a_2(self, 'help ', '&查看帮助', 'Ctrl+F1', '查看帮助', self.helpMenu)
        # self.help.triggered.connect(self.)
        # ####################菜单####################结束

        ################################################################################################################

        # ####################工具栏####################开始
        # 工具

        self.pixmapToolbar = self.addToolBar('打开图形文件')
        self.textToolbar = self.addToolBar('打开文本文件')
        self.pixmapToolbar.addAction(self.openPimax)
        self.textToolbar.addAction(self.openText)

        self.exitToolbar = self.addToolBar('退出')
        self.exitToolbar.addAction(self.exitAction)

        self.calculatorTooolbar = self.addToolBar('计算器')
        self.calculatorTooolbar.addAction(self.calculator)

        # ####################工具栏####################结束

        #  槽函数线程

    # 创建右键菜单
    def create_context_menu(self):
        """
        创建右键菜单
        :return:
        """
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)

        # 创建QMenu
        self.contextMenu = QMenu(self)

        # ####################工具栏管理####################开始
        self.toolBarManagementMenu = Action.action_b_4(self, 'toolBarManagementMenu', '&工具栏管理', self.contextMenu)
        # 未完成
        # ####################工具栏管理####################结束

        self.minAtion = Action.action_a_1(self, 'minAction', './image/min.png', '&最小化', 'Ctrl+M', '最小化窗口',
                                          self.contextMenu)

        self.contextMenu.addSeparator()  # 添加分隔线

        self.cutAction = Action.action_a_2(self, 'cutAction', '&剪切', 'Ctrl+X', '剪切', self.contextMenu)
        self.copyAction = Action.action_a_2(self, 'copyAction', '&复制', 'Ctrl+C', '复制', self.contextMenu)
        self.pasteAction = Action.action_a_2(self, 'pasteAction', '&粘贴', 'Ctrl+V', '粘贴', self.contextMenu)
        self.deleteAction = Action.action_a_2(self, 'delectAction', '&删除', 'Del', '删除', self.contextMenu)
        self.selectAllAction = Action.action_a_2(self, 'selectAllAction', '&全选', 'Ctrl+Alt', '全选', self.contextMenu)

        self.contextMenu.addSeparator()  # 添加分隔线

        self.closeAction = Action.action_a_1(self, 'closeAction', './image/Exit.png', '&退出', 'Ctrl+W', '退出',
                                             self.contextMenu)

        self.minAtion.triggered.connect(self.show_mininized_window)

        self.closeAction.triggered.connect(self.quit_window)
        # self.selectAllAction.triggered.connect(self.)
        # self.cutAction.triggered.connect(self.)
        # self.copyAction.triggered.connect(self.)
        # self.pasteAction.triggered.connect(self.)
        # self.delectAction.triggered.connect(self.)

    # ****************************** 业务逻辑 *********************************
    def load_qss(self):
        """
         加载Qss样式表
        :return:
        """
        style_file = './Window/mainWindow/Qss/mainWindow.qss'
        qss_style = CommonhelperQss.read_qss(style_file)
        self.setStyleSheet(qss_style)

    def set_action_connect(self):
        """
        菜单栏、工具栏槽函数连接
        :return:
        """
        pass

    def calculator_win(self):
        """
        加载计算器窗口
        :return:
        """
        self.calculator_Win = Calculatormainwindow()
        self.calculator_Win.show()

    def set_main_form(self):
        """
        窗体布局以及主框体设计
        :return:
        """
        # 主框体
        self.mainSpiltter = QSplitter(Qt.Vertical)
        self.mainSpiltter.setObjectName('mainSpiltter')

        self.mainSpiltterLayout = QVBoxLayout()

        # 设置主窗口中心窗体
        self.setCentralWidget(self.mainSpiltter)

        # *******工作区间*******
        self.workWidget = QSplitter()
        self.workWidget.setObjectName('workWidget')
        self.mainSpiltter.addWidget(self.workWidget)

        self.workWidgetLayout = QHBoxLayout()
        self.workWidget.setLayout(self.workWidgetLayout)

        self.leftWidget = QFrame()
        self.leftWidget.setObjectName('leftWidget')
        self.leftWidget.setFrameShape(QFrame.StyledPanel)
        self.leftWidget.setMaximumWidth(230)

        self.leftWidgetLayout = QVBoxLayout()
        self.leftWidgetLayout.setContentsMargins(0, 0, 0, 0)
        self.leftWidget.setLayout(self.leftWidgetLayout)

        # self.hideBtn = QLabel()
        # self.hideBtn.setObjectName('hideBtn')
        # self.hideBtn.setPixmap(QPixmap('./image/mainWindowIcon/showAndHideIcon/hide0.ico'))
        #
        # self.showBtn = QLabel()
        # self.showBtn.setObjectName('showBtn')
        # self.showBtn.setPixmap(QPixmap('./image/mainWindowIcon/showAndHideIcon/show0.ico'))

        # 存放按钮
        self.widget = QWidget()
        self.widget.setObjectName('widget')
        self.leftWidgetLayout.addWidget(self.widget)

        pixmap = self.imageScale.pixmap_scale('./image/Logo/logo0.png', 204, 80)

        self.logoIamgeLabel = QLabel(self.widget)
        self.logoIamgeLabel.setObjectName('logoImageLabel')
        self.logoIamgeLabel.setPixmap(pixmap)

        self.widgetLayout = QGridLayout()
        self.widget.setLayout(self.widgetLayout)

        self.widgetLayout.addWidget(self.logoIamgeLabel, 0, 1)

        # 多界面
        # QListWidget + QStackedWidget实现
        self.leftListWidget = QListWidget()  # 左侧选项列表
        self.leftListWidget.setObjectName('leftListWidget')
        self.rightWidget = QStackedWidget()  # 右侧框体
        self.rightWidget.setObjectName('rightWidget')

        self.leftWidgetLayout.addWidget(self.leftListWidget)

        self.workWidgetLayout.addWidget(self.leftWidget)
        self.workWidgetLayout.addWidget(self.rightWidget)

        # ********左侧选项列表布局以及设置******************************
        # 设置左侧选项列表大小
        self.leftListWidget.setMinimumWidth(Const.LEFTWIDGET_WIDTH)
        # 左侧选项列表与右侧框体的index对应绑定
        self.leftListWidget.currentRowChanged.connect(self.rightWidget.setCurrentIndex)
        # 去掉边框
        self.leftListWidget.setFrameShape(QListWidget.NoFrame)
        # 隐藏滚动条
        self.leftListWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.leftListWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        list_str = ['智能识别', '公式生成器', '学习资源区', '设置', '关于']

        # 左侧选项添加
        for i in range(5):
            self.item = QListWidgetItem(list_str[i], self.leftListWidget)
            self.item.setSizeHint(QSize(Const.ITEM_WIDTH, Const.ITEM_HEIGHT))
            # 居中显示
            self.item.setTextAlignment(Qt.AlignCenter)

        # 设置默认选中item[1]
        self.leftListWidget.setCurrentRow(0)

        # ********右侧主框体布局以及设置**********************************
        self.rightForm1 = RightForm1()
        self.rightForm2 = RightForm2()
        self.rightForm3 = RightForm3()
        self.rightForm4 = RightForm4()
        self.rightForm5 = RightForm5()
        self.rightWidget.addWidget(self.rightForm1)
        self.rightWidget.addWidget(self.rightForm2)
        self.rightWidget.addWidget(self.rightForm3)
        self.rightWidget.addWidget(self.rightForm4)
        self.rightWidget.addWidget(self.rightForm5)

        # #############################################################
        # 消息通知框
        self.messageInform = MesageFrame()
        self.messageInform.setObjectName('messageInform')
        # 消息通知框默认隐藏
        self.messageInform.hide()

        self.mainSpiltter.addWidget(self.messageInform)

        # *****侧边栏*****
        # 右侧边栏
        self.rightBar = QFrame()
        self.rightBar.setObjectName('rightBar')
        self.rightBar.setFixedWidth(35)
        self.rightBar.setFrameShape(QFrame.StyledPanel)

        self.rightBarLayout = QVBoxLayout()
        self.rightBar.setLayout(self.rightBarLayout)

        self.workWidgetLayout.addWidget(self.rightBar)

        # 右侧边栏控件

        # 右侧边栏添加控件

        # 下侧边栏
        self.bottomBar = QFrame()
        self.bottomBar.setObjectName('bottomBar')
        self.bottomBar.setMaximumHeight(35)
        self.bottomBar.setFrameShape(QFrame.StyledPanel)

        self.bottomBarLayout = QHBoxLayout()
        self.bottomBarLayout.setAlignment(Qt.AlignRight)  # 右对齐
        self.bottomBar.setLayout(self.bottomBarLayout)

        self.mainSpiltter.addWidget(self.bottomBar)

        # 下侧边栏控件
        # 留白控件
        blank = QLabel(self.bottomBar)
        blank.setObjectName('blank')

        self.informText = QLabel(self.bottomBar)
        self.informText.setObjectName('informText')
        self.informText.setText('通知')

        self.informBtn = QPushButton(self.bottomBar)
        self.informBtn.setObjectName('informBtn')
        self.informBtn.resize(QSize(35, 35))
        self.informBtn.setIcon(QIcon('./image/mainWindowIcon/messageBarBtnIcon/inform0.png'))
        self.informBtn.clicked.connect(lambda: self.open_inform_frame())

        # 下侧边栏添加控件

        self.bottomBarLayout.addWidget(self.informBtn)
        self.bottomBarLayout.addWidget(self.informText)
        self.bottomBarLayout.addWidget(blank)

    # ****************************业务逻辑******************************
    # 右键菜单
    def show_context_menu(self):
        """
        右键点击时调用的函数
        :return:
        """
        # 显示菜单前,将它移动到鼠标点击的位置
        self.contextMenu.exec_(QCursor.pos())

    # 最小化窗口
    def show_mininized_window(self):
        """
        :return:
        """
        self.showMinimized()

    # 最大化窗口
    def show_maximized_window(self):
        """

        :return:
        """
        self.showMaximized()

    # 复原窗口
    def show_restore_window(self):
        """

        :return:
        """
        if self.isMaximized():
            self.showNormal()
        else:
            self.showMaximized()

    # 关闭窗口
    def quit_window(self):
        """

        :return:
        """
        self.close()

    # 打开文件
    def get_image(self):

        """
            getOpenFileName():返回用户所选择文件的名称,并打开该文件
            第一个参数用于指定父组件
            第二个参数指定对话框标题
            第三个参数指定目录
            第四个参数是文件扩展名过滤器
        """
        pass
        # fname, _ = QFileDialog.getOpenFileName(self, '选择图形文件', 'C:\\', "*.jpg *.gif *.png")
        # self.pixmapLabel.setPixmap(QPixmap(fname))

    def get_text(self):
        """

        :return:
        """
        pass
        # # 初始化实例,并设置一些参数
        # # textDialog = QFileDialog()
        # # textDialog.setFileMode(QFileDialog.AnyFile)
        # # textDialog.setFilter(QDir.Files)
        # textDialog = QFileDialog.getOpenFileName(self, '选择文本文件', 'C:\\', "*.txt *.doc *.docx")
        # # 当选择器关闭的时候
        # if textDialog.exec_():
        #     # 拿到所选择的文本
        #     filenames = textDialog.selectedFiles()
        #     # 读取文本内容设置到textEdit中
        #     f = open(filenames[0], 'r')
        #     with f:
        #         data = f.read()
        #         self.textEdit.setText(data)

    def open_inform_frame(self):
        self.messageInform.show()
예제 #44
0
class ShowPoints(QWidget):
	def __init__(self):
		super().__init__()
		self.webView = QtWebEngineWidgets.QWebEngineView()
		self.sourceType = QComboBox()
		self.sourceType.addItems(['国测局坐标GCJ02(MX数据库/高德)','GPS坐标(wgs84/NMEA0183)'])
		self.inputText = QTextEdit()
		self.inputText.setFixedWidth(280)
		self.runButton = QPushButton('确定')
		self.runButton.setFixedWidth(100)
		self.clrButton = QPushButton('清除')
		self.clrButton.setFixedWidth(100)
		self.statusBar = QStatusBar()
		self.statusBar.showMessage(STATUS_TIP+"Ready")
		self.init_ui()

	def init_ui(self):
		path = os.getcwd()
		url = path + HTM_FILE
		self.webView.setUrl(QtCore.QUrl(url))
		self.webView.page().loadFinished.connect(self.load_finished)  # for test

		self.inputText.setEnabled(False)
		self.inputText.setAcceptRichText(False)
		self.inputText.setToolTip("每行一组经纬度,纬度lat在前\n" + "以空格、逗号或制表符分隔")

		self.runButton.clicked.connect(self.add_points)  # show all points in input text window
		self.clrButton.clicked.connect(self.clr_points)

		buttonBox = QHBoxLayout()  # button box
		buttonBox.addStretch()
		buttonBox.addWidget(self.runButton)
		buttonBox.addWidget(self.clrButton)

		rightBox = QVBoxLayout()  # right box
		rightBox.addWidget(self.sourceType)
		rightBox.addWidget(self.inputText)
		rightBox.addLayout(buttonBox)
		rightBox.addWidget(self.statusBar)

		layout = QHBoxLayout()  # main box
		layout.addWidget(self.webView)
		layout.addLayout(rightBox)

		self.setLayout(layout)
		self.setWindowTitle('经纬度地图显示')
		self.show()

	def load_finished(self):
		self.inputText.setEnabled(True)

	def add_marker(self):
		"""
		添加标记,ok
		:return:
		"""
		a = self.webView.page()
		# a.runJavaScript("addMarker(114.39387,30.505299,true,1);")
		# a.runJavaScript("var point = new BMap.Point(114,30);var marker = new BMap.Marker(point);map.addOverlay(marker);")
		a.runJavaScript("testfunc(1);")  # ok
		a.runJavaScript("addMarker(114,30.01,true,2);")

	def run_script(self, script):
		a = self.webView.page()
		a.runJavaScript(script)

	def add_points(self):
		self.statusBar.showMessage(STATUS_TIP+"Running...")
		points_text = self.inputText.toPlainText()  # 获取输入
		source_type = self.sourceType.currentIndex()
		if_mars = 'true' if (source_type == 0) else 'false'

		if points_text == "":  # 使用示例输入
			points_text = SAMPLE_DATA
			self.inputText.setPlainText(points_text)

		points = Point.points_parser(points_text)  # 解析输入
		lats = [p.lat for p in points]
		lons = [p.lon for p in points]

		N = len(lats)  # 共N组经纬度
		G = math.ceil((N - 1) / 9)  # 每10个一组,首尾相接,共G组

		if N == 1:
			G = 1

		for g in range(G):  # 0,1,...,G-1
			index_s = 9 * g
			index_e = 9 * g + 10
			index_e = N if (index_e > N) else index_e
			latsStr = "[" + ",".join(lats[index_s:index_e]) + "]"
			lonsStr = "[" + ",".join(lons[index_s:index_e]) + "]"
			script = "addSimpleMarker(%s,%s,%s);" % (latsStr, lonsStr, if_mars)
			self.run_script(script)
			time.sleep(0.1)  # seconds,延时0.1秒,避免回调函数的执行顺序被打乱

		self.statusBar.showMessage(STATUS_TIP+"Done")

	def clr_points(self):
		self.run_script("clearMarkers();")
		self.inputText.setPlainText("")
		self.statusBar.showMessage(STATUS_TIP+"Ready")
예제 #45
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setObjectName("myGitClone")
        root = QFileInfo.path(QFileInfo(QCoreApplication.arguments()[0]))
        print("root", root)
        self.icon = QIcon(f"{root}/favicon.ico")
        self.setWindowIcon(self.icon)
        self.setGeometry(0, 0, 800, 600)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setMinimumSize(400, 300)
        self.setDocumentMode(True)
        self.settings = QSettings('Axel Schneider', self.objectName())
        self.createStatusbar()
        self.createActions()
        self.createWidgets()
        QMetaObject.connectSlotsByName(self)
        self.readSettings()
        self.statusbar.showMessage("Ready")
        self.setWindowTitle("myGitClone")

        ### process
        ### shell settings
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.process.readyReadStandardError.connect(lambda: self.msg("Error"))
        self.process.started.connect(lambda: self.msg("starting shell"))
        self.process.finished.connect(lambda: self.msg("shell ended"))

    ### widgets ###
    def createWidgets(self):
        self.username = ""
        self.url = "https://github.com/%s?tab=repositories" % self.username
        self.repoList = []
        self.gitList = []
        self.dlFolder = QDir.homePath() + "/Downloads"

        ### table ###
        self.lb = QTableWidget()
        self.lb.setColumnCount(2)
        self.lb.setColumnWidth(0, 60)
        self.lb.horizontalHeader().setStretchLastSection(True)
        self.lb.setHorizontalHeaderItem(0, QTableWidgetItem("Select"))
        self.lb.setHorizontalHeaderItem(1, QTableWidgetItem("Repository Name"))

        ### username field ###
        self.uname = QLineEdit("")
        self.uname.setFixedWidth(180)
        self.uname.setPlaceholderText("insert user name")
        self.uname.returnPressed.connect(self.listRepos)

        ### get repos button ###
        self.uBtn = QPushButton(QIcon(self.icon), "get Repos List")
        self.uBtn.setToolTip("get all repos from user")
        self.uBtn.clicked.connect(self.listRepos)

        ### get repos button ###
        self.dlBtn = QPushButton(QIcon.fromTheme("download"),
                                 "download selected Repos")
        self.dlBtn.setToolTip("download selected repos from user")
        self.dlBtn.setFixedWidth(180)
        self.dlBtn.clicked.connect(self.create_dl_list)

        ### Layout
        self.ubox = QHBoxLayout()
        self.ubox.addWidget(self.uname)
        self.ubox.addWidget(self.uBtn)
        self.ubox.addStretch(1)
        self.ubox.addWidget(self.dlBtn)

        self.layout = QVBoxLayout()
        self.wid = QWidget()

        self.layout.addLayout(self.ubox)
        self.layout.addWidget(self.lb)
        self.wid.setLayout(self.layout)

        self.setCentralWidget(self.wid)

    ### actions ###
    def createActions(self):
        self.tbar = QToolBar()
        self.tbar.setIconSize(QSize(16, 16))
        self.tbar.setMovable(False)
        self.tbar.setToolButtonStyle(0)
        self.tbar.setContextMenuPolicy(Qt.PreventContextMenu)
        self.tbar.setObjectName("tbar")
        self.addToolBar(self.tbar)

        self.actionSettings = QAction(self,
                                      triggered=self.appSettings,
                                      toolTip="set output directory")
        icon = QIcon.fromTheme("preferences-system")
        self.actionSettings.setIcon(icon)
        self.actionSettings.setObjectName("actionSettings")

        self.actionAbout = QAction(self, triggered=self.aboutApp)
        icon = QIcon.fromTheme("help-about")
        self.actionAbout.setIcon(icon)

        self.tbar.addAction(self.actionSettings)
        self.tbar.addAction(self.actionAbout)

        ### statusbar###
    def createStatusbar(self):
        self.statusbar = QStatusBar(self)
        font = QFont()
        font.setPointSize(7)
        self.statusbar.setFont(font)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

    ### get username from textfield
    def changeUsername(self):
        self.username = self.uname.text()
        self.url = "https://github.com/%s?tab=repositories" % self.username

    ### get user repos ##
    def listRepos(self):
        self.changeUsername()
        if self.username == "":
            self.msgBox("please type a username")
        else:
            self.lb.setRowCount(0)
            self.repoList = []
            repositories = self.get_repositories()
            print("%s %s" % ("get repos from", self.username))
            self.repoList = list(repositories)
            self.fillTable()
            self.msg("repos loaded")

    ### fill table with user repos
    def fillTable(self):
        self.lb.setRowCount(len(self.repoList))
        if self.lb.rowCount() > 0:
            for x in range(len(self.repoList)):
                rep = QTableWidgetItem(self.repoList[x])
                checkbox = QCheckBox(self.lb)
                checkbox.setStyleSheet("margin-left:20%; margin-right:10%;")
                checkbox.setCheckState(0)
                self.lb.setCellWidget(x, 0, checkbox)
                self.lb.setItem(x, 1, rep)

    ### table context menu
    def contextMenuEvent(self, event):
        self.menu = QMenu(self)
        if self.lb.selectionModel().hasSelection():
            # copy
            downloadAction = QAction(QIcon.fromTheme("download"),
                                     'download Repo', self)
            downloadAction.triggered.connect(
                lambda: self.downloadRepoFromList())
            ###
            self.menu.addAction(downloadAction)
            self.menu.popup(QCursor.pos())

    def listChanged(self):
        self.create_dl_list()

    ### get download list from selected repos
    def create_dl_list(self):
        r = ""
        self.gitList = []
        for x in range(self.lb.rowCount()):
            if self.lb.cellWidget(x, 0).checkState() == 2:
                r = self.lb.item(x, 1).text()
                self.gitList.append(r)
                print("%s %s" % (r, "is selected"))
                self.downloadRepo(r)

    ### download repo
    def downloadRepo(self, gitrepo):
        merror = ""
        cmd = "git clone --progress --verbose https://github.com/" + str(
            self.username) + "/" + str(gitrepo) + " " + str(
                self.dlFolder) + "/" + str(gitrepo)
        print("%s %s" % ("username is:", self.username))
        print(cmd)
        try:
            self.process.execute(cmd)
        except Exception as e:
            s = str(e)
            self.errorBox(s)

    ### download selected repo (context menu)
    def downloadRepoFromList(self):
        row = self.lb.selectionModel().selectedIndexes()[0].row()
        gitrepo = self.lb.item(row, 1).text()
        cmd = "git clone --progress --verbose https://github.com/" + str(
            self.username) + "/" + str(gitrepo) + " " + str(
                self.dlFolder) + "/" + str(gitrepo)
        print(cmd)
        self.process.execute(cmd)

    ### preferences
    def appSettings(self):
        if self.dlFolder == "":
            self.dlFolder = QDir.homePath()
        self.msg("settings called")
        path = QFileDialog.getExistingDirectory(self, "select Folder",
                                                self.dlFolder)
        if path:
            self.dlFolder = path
            print("%s %s" % ("download folder changed to", self.dlFolder))

    def closeEvent(self, e):
        self.writeSettings()
        e.accept()

    ### read settings from config file
    def readSettings(self):
        print("reading settings")
        if self.settings.contains('geometry'):
            self.setGeometry(self.settings.value('geometry'))
        if self.settings.contains('downloadFolder'):
            self.dlFolder = self.settings.value('downloadFolder')
            self.msg(self.dlFolder)
            print("%s %s" % ("download folder:", self.dlFolder))

    ### write settings to config file
    def writeSettings(self):
        print("writing settings")
        self.settings.setValue('geometry', self.geometry())
        self.settings.setValue('downloadFolder', self.dlFolder)

    ### about window
    def aboutApp(self):
        title = "about myGitClone"
        message = """
                    <span style='color: #3465a4; font-size: 18pt;font-weight: bold;'
                    >myGitClone</strong></span></p>
                    <h3>based on <a title='git_clones' href='https://github.com/rootVIII/git_clones' target='_blank'> git_clones</a> by James</h3>
                    <h4>created by  <a title='Axel Schneider' href='http://goodoldsongs.jimdo.com' target='_blank'>Axel Schneider</a> with PyQt5</h3>
                    <br>
                    <span style='color: #555753; font-size: 9pt;'>©2019 Axel Schneider, James</strong></span></p>
                        """
        self.infobox(title, message)

    ### error messagebox
    def errorBox(self, message):
        mwin = QMessageBox.warning(self, "Error", message)

    ### messagebox
    def infobox(self, title, message):
        QMessageBox.about(self, title, message).show()

    ### set statusbar text
    def msg(self, message):
        self.statusbar.showMessage(message)

    def msgBox(self, message):
        msg = QMessageBox.warning(self, "Information", message)

    ### begin from git_clones ###
    def http_get(self):
        if version_info[0] != 2:
            req = urlopen(self.url)
            return req.read().decode('utf-8')
        req = Request(self.url)
        request = urlopen(req)
        return request.read()

    def get_repo_data(self):
        try:
            response = self.http_get()
        except Exception as e:
            s = str(e)
            self.errorBox(s)
            print("Unable to make request to %s's Github page" % self.username)
            exit(1)
        else:
            pattern = r"<a\s?href\W+%s/(.*)\"\s+" % self.username
            for line in findall(pattern, response):
                yield line.split('\"')[0]

    def get_repositories(self):
        return set([repo for repo in self.get_repo_data()])
예제 #46
0
class MainWindow(QMainWindow, metaclass=QSingleton):
    new_session = pyqtSignal()
    save_session = pyqtSignal(str)
    open_session = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.setMinimumSize(500, 400)
        self.setCentralWidget(QWidget())
        self.centralWidget().setLayout(QVBoxLayout())
        self.centralWidget().layout().setContentsMargins(5, 5, 5, 5)

        self._cue_add_menu = {}
        self.layout = None

        # Status Bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)
        MainActionsHandler.action_done.connect(self._action_done)
        MainActionsHandler.action_undone.connect(self._action_undone)
        MainActionsHandler.action_redone.connect(self._action_redone)

        # Menubar
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 0, 25))
        self.menubar.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)

        self.menuFile = QMenu(self.menubar)
        self.menuEdit = QMenu(self.menubar)
        self.menuLayout = QMenu(self.menubar)
        self.menuTools = QMenu(self.menubar)
        self.menuAbout = QMenu(self.menubar)

        self.menubar.addMenu(self.menuFile)
        self.menubar.addMenu(self.menuEdit)
        self.menubar.addMenu(self.menuLayout)
        self.menubar.addMenu(self.menuTools)
        self.menubar.addMenu(self.menuAbout)

        self.setMenuBar(self.menubar)

        # menuFile
        self.newSessionAction = QAction(self)
        self.newSessionAction.triggered.connect(self._new_session)
        self.openSessionAction = QAction(self)
        self.openSessionAction.triggered.connect(self._load_from_file)
        self.saveSessionAction = QAction(self)
        self.saveSessionAction.triggered.connect(self._save)
        self.saveSessionWithName = QAction(self)
        self.saveSessionWithName.triggered.connect(self._save_with_name)
        self.editPreferences = QAction(self)
        self.editPreferences.triggered.connect(self._show_preferences)
        self.fullScreenAction = QAction(self)
        self.fullScreenAction.triggered.connect(self._fullscreen)
        self.fullScreenAction.setCheckable(True)
        self.exitAction = QAction(self)
        self.exitAction.triggered.connect(self._exit)

        self.menuFile.addAction(self.newSessionAction)
        self.menuFile.addAction(self.openSessionAction)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.saveSessionAction)
        self.menuFile.addAction(self.saveSessionWithName)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.editPreferences)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.fullScreenAction)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.exitAction)

        # menuEdit
        self.actionUndo = QAction(self)
        self.actionUndo.triggered.connect(MainActionsHandler.undo_action)
        self.actionRedo = QAction(self)
        self.actionRedo.triggered.connect(MainActionsHandler.redo_action)
        self.multiEdit = QAction(self)
        self.selectAll = QAction(self)
        self.selectAllMedia = QAction(self)
        self.deselectAll = QAction(self)
        self.invertSelection = QAction(self)

        self.cueSeparator = self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.actionUndo)
        self.menuEdit.addAction(self.actionRedo)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.selectAll)
        self.menuEdit.addAction(self.selectAllMedia)
        self.menuEdit.addAction(self.deselectAll)
        self.menuEdit.addAction(self.invertSelection)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.multiEdit)

        # menuAbout
        self.actionAbout = QAction(self)
        self.actionAbout.triggered.connect(about.About(self).show)

        self.actionAbout_Qt = QAction(self)
        self.actionAbout_Qt.triggered.connect(qApp.aboutQt)

        self.menuAbout.addAction(self.actionAbout)
        self.menuAbout.addSeparator()
        self.menuAbout.addAction(self.actionAbout_Qt)

        # Set component text
        self.retranslateUi()
        # The save file name
        self.filename = ''

    def retranslateUi(self):
        self.setWindowTitle('Linux Show Player')
        # menuFile
        self.menuFile.setTitle(translate('MainWindow', '&File'))
        self.newSessionAction.setText(translate('MainWindow', 'New session'))
        self.newSessionAction.setShortcut(QKeySequence.New)
        self.openSessionAction.setText(translate('MainWindow', 'Open'))
        self.openSessionAction.setShortcut(QKeySequence.Open)
        self.saveSessionAction.setText(translate('MainWindow', 'Save session'))
        self.saveSessionAction.setShortcut(QKeySequence.Save)
        self.editPreferences.setText(translate('MainWindow', 'Preferences'))
        self.editPreferences.setShortcut(QKeySequence.Preferences)
        self.saveSessionWithName.setText(translate('MainWindow', 'Save as'))
        self.saveSessionWithName.setShortcut(QKeySequence.SaveAs)
        self.fullScreenAction.setText(translate('MainWindow', 'Full Screen'))
        self.fullScreenAction.setShortcut(QKeySequence.FullScreen)
        self.exitAction.setText(translate('MainWindow', 'Exit'))
        # menuEdit
        self.menuEdit.setTitle(translate('MainWindow', '&Edit'))
        self.actionUndo.setText(translate('MainWindow', 'Undo'))
        self.actionUndo.setShortcut(QKeySequence.Undo)
        self.actionRedo.setText(translate('MainWindow', 'Redo'))
        self.actionRedo.setShortcut(QKeySequence.Redo)
        self.selectAll.setText(translate('MainWindow', 'Select all'))
        self.selectAllMedia.setText(
            translate('MainWindow', 'Select all media cues'))
        self.selectAll.setShortcut(QKeySequence.SelectAll)
        self.deselectAll.setText(translate('MainWindow', 'Deselect all'))
        self.deselectAll.setShortcut(translate('MainWindow', 'CTRL+SHIFT+A'))
        self.invertSelection.setText(
            translate('MainWindow', 'Invert selection'))
        self.invertSelection.setShortcut(translate('MainWindow', 'CTRL+I'))
        self.multiEdit.setText(translate('MainWindow', 'Edit selected'))
        self.multiEdit.setShortcut(translate('MainWindow', 'CTRL+SHIFT+E'))
        # menuLayout
        self.menuLayout.setTitle(translate('MainWindow', '&Layout'))
        # menuTools
        self.menuTools.setTitle(translate('MainWindow', '&Tools'))
        self.multiEdit.setText(translate('MainWindow', 'Edit selection'))
        # menuAbout
        self.menuAbout.setTitle(translate('MainWindow', '&About'))
        self.actionAbout.setText(translate('MainWindow', 'About'))
        self.actionAbout_Qt.setText(translate('MainWindow', 'About Qt'))

    def set_layout(self, layout):
        if self.layout is not None:
            self.layout.hide()
            self.centralWidget().layout().removeWidget(self.layout)

            self.multiEdit.triggered.disconnect()
            self.selectAll.triggered.disconnect()
            self.selectAllMedia.triggered.disconnect()
            self.deselectAll.triggered.disconnect()
            self.invertSelection.triggered.disconnect()

        self.layout = layout
        self.centralWidget().layout().addWidget(self.layout)
        self.layout.show()

        self.multiEdit.triggered.connect(self.layout.edit_selected_cues)
        self.selectAll.triggered.connect(lambda: self.layout.select_all())
        self.selectAllMedia.triggered.connect(
            lambda: self.layout.select_all(MediaCue))
        self.deselectAll.triggered.connect(lambda: self.layout.deselect_all())
        self.invertSelection.triggered.connect(self.layout.invert_selection)

    def closeEvent(self, event):
        self._exit()
        event.ignore()

    def register_cue_menu_action(self,
                                 name,
                                 function,
                                 category='',
                                 shortcut=''):
        '''Register a new-cue choice for the edit-menu

        param name: The name for the MenuAction
        param function: The function that add the new cue(s)
        param category: The optional menu where insert the MenuAction
        param shortcut: An optional shortcut for the MenuAction
        '''
        action = QAction(self)
        action.setText(translate('MainWindow', name))
        action.triggered.connect(function)
        if shortcut != '':
            action.setShortcut(translate('MainWindow', shortcut))

        if category != '':
            if category not in self._cue_add_menu:
                menu = QMenu(category, self)
                self._cue_add_menu[category] = menu
                self.menuEdit.insertMenu(self.cueSeparator, menu)

            self._cue_add_menu[category].addAction(action)
        else:
            self.menuEdit.insertAction(self.cueSeparator, action)

    def update_window_title(self):
        saved = MainActionsHandler.is_saved()
        if not saved and not self.windowTitle()[0] == '*':
            self.setWindowTitle('*' + self.windowTitle())
        elif saved and self.windowTitle()[0] == '*':
            self.setWindowTitle(self.windowTitle()[1:])

    def _action_done(self, action):
        self.statusBar.showMessage(action.log())
        self.update_window_title()

    def _action_undone(self, action):
        self.statusBar.showMessage(
            translate('MainWindow', 'Undone: ') + action.log())
        self.update_window_title()

    def _action_redone(self, action):
        self.statusBar.showMessage(
            translate('MainWindow', 'Redone: ') + action.log())
        self.update_window_title()

    def _save(self):
        if self.filename == '':
            self._save_with_name()
        else:
            self.save_session.emit(self.filename)

    def _save_with_name(self):
        filename, _ = QFileDialog.getSaveFileName(parent=self,
                                                  filter='*.lsp',
                                                  directory=os.getenv('HOME'))
        if filename != '':
            if not filename.endswith('.lsp'):
                filename += '.lsp'
            self.filename = filename
            self._save()

    def _show_preferences(self):
        prefUi = AppSettings(configuration.config_to_dict(), parent=self)
        prefUi.exec_()

        if prefUi.result() == QDialog.Accepted:
            configuration.update_config_from_dict(prefUi.get_configuraton())

    def _load_from_file(self):
        if self._check_saved():
            path, _ = QFileDialog.getOpenFileName(self,
                                                  filter='*.lsp',
                                                  directory=os.getenv('HOME'))

            if os.path.exists(path):
                self.open_session.emit(path)
                self.filename = path

    def _new_session(self):
        if self._check_saved():
            self.new_session.emit()

    def _check_saved(self):
        if not MainActionsHandler.is_saved():
            msgBox = QMessageBox(self)
            msgBox.setIcon(QMessageBox.Warning)
            msgBox.setWindowTitle(translate('MainWindow', 'Close session'))
            msgBox.setText(
                translate('MainWindow', 'The current session is not saved.'))
            msgBox.setInformativeText(
                translate('MainWindow', 'Discard the changes?'))
            msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Discard
                                      | QMessageBox.Cancel)
            msgBox.setDefaultButton(QMessageBox.Save)

            result = msgBox.exec_()
            if result == QMessageBox.Cancel:
                return False
            elif result == QMessageBox.Save:
                self._save()

        return True

    def _fullscreen(self, enable):
        if enable:
            self.showFullScreen()
        else:
            self.showMaximized()

    def _exit(self):
        if self._check_saved():
            qApp.quit()
예제 #47
0
class MainWindow(QMainWindow, metaclass=QSingleton):

    new_session = QtCore.pyqtSignal()
    save_session = QtCore.pyqtSignal(str)
    open_session = QtCore.pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.setMinimumSize(400, 300)

        self._cue_add_menus = {}
        self.layout = None

        # Define the layout and the main gui's elements
        self.centralwidget = QWidget(self)
        self.setCentralWidget(self.centralwidget)
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setContentsMargins(2, 5, 2, 0)

        # Status Bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)
        ActionsHandler().action_done.connect(self._action_done)
        ActionsHandler().action_undone.connect(self._action_undone)
        ActionsHandler().action_redone.connect(self._action_redone)

        # Menubar
        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 0, 25))
        self.menubar.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)

        self.menuFile = QMenu(self.menubar)
        self.menuEdit = QMenu(self.menubar)
        self.menuLayout = QMenu(self.menubar)
        self.menuTools = QMenu(self.menubar)
        self.menuAbout = QMenu(self.menubar)

        self.menubar.addMenu(self.menuFile)
        self.menubar.addMenu(self.menuEdit)
        self.menubar.addMenu(self.menuLayout)
        self.menubar.addMenu(self.menuTools)
        self.menubar.addMenu(self.menuAbout)

        self.setMenuBar(self.menubar)

        # menuFile
        self.newSessionAction = QAction(self, triggered=self._startup)
        self.openSessionAction = QAction(self, triggered=self._load_from_file)
        self.saveSessionAction = QAction(self, triggered=self.save)
        self.saveSessionWithName = QAction(self, triggered=self.save_with_name)
        self.editPreferences = QAction(self, triggered=self.show_preferences)
        self.fullScreenAction = QAction(self, triggered=self._fullscreen)
        self.fullScreenAction.setCheckable(True)
        self.exitAction = QAction(self, triggered=self.exit)

        self.menuFile.addAction(self.newSessionAction)
        self.menuFile.addAction(self.openSessionAction)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.saveSessionAction)
        self.menuFile.addAction(self.saveSessionWithName)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.editPreferences)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.fullScreenAction)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.exitAction)

        # menuEdit
        self.actionUndo = QAction(self)
        self.actionUndo.triggered.connect(
            lambda: ActionsHandler().undo_action())
        self.actionRedo = QAction(self)
        self.actionRedo.triggered.connect(
            lambda: ActionsHandler().redo_action())
        self.multiEdit = QAction(self)
        self.selectAll = QAction(self)
        self.deselectAll = QAction(self)
        self.invertSelection = QAction(self)

        self.cueSeparator = self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.actionUndo)
        self.menuEdit.addAction(self.actionRedo)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.selectAll)
        self.menuEdit.addAction(self.deselectAll)
        self.menuEdit.addAction(self.invertSelection)
        self.menuEdit.addSeparator()
        self.menuEdit.addAction(self.multiEdit)

        # menuAbout
        self.actionAbout = QAction(self)
        self.actionAbout.triggered.connect(about.About(self).show)

        self.actionAbout_Qt = QAction(self)
        self.actionAbout_Qt.triggered.connect(qApp.aboutQt)

        self.menuAbout.addAction(self.actionAbout)
        self.menuAbout.addSeparator()
        self.menuAbout.addAction(self.actionAbout_Qt)

        # Set component text
        self.retranslateUi()
        # The save file name
        self.file = ''

    def retranslateUi(self):
        self.setWindowTitle('Linux Show Player')
        # menuFile
        self.menuFile.setTitle("&File")
        self.newSessionAction.setText("New session")
        self.newSessionAction.setShortcut("CTRL+N")
        self.openSessionAction.setText("Open")
        self.openSessionAction.setShortcut("CTRL+O")
        self.saveSessionAction.setText("Save session")
        self.saveSessionAction.setShortcut("CTRL+S")
        self.editPreferences.setText("Preferences")
        self.editPreferences.setShortcut("CTRL+P")
        self.saveSessionWithName.setText("Save with name")
        self.saveSessionWithName.setShortcut('CTRL+SHIFT+S')
        self.fullScreenAction.setText('Toggle fullscreen')
        self.fullScreenAction.setShortcut('F11')
        self.exitAction.setText("Exit")
        # menuEdit
        self.menuEdit.setTitle("&Edit")
        self.actionUndo.setText('Undo')
        self.actionUndo.setShortcut('CTRL+Z')
        self.actionRedo.setText('Redo')
        self.actionRedo.setShortcut('CTRL+Y')
        self.selectAll.setText("Select all")
        self.selectAll.setShortcut("CTRL+A")
        self.deselectAll.setText("Deselect all")
        self.deselectAll.setShortcut("CTRL+SHIFT+A")
        self.invertSelection.setText("Invert selection")
        self.invertSelection.setShortcut("CTRL+I")
        self.multiEdit.setText("Edit selected media")
        self.multiEdit.setShortcut("CTRL+SHIFT+E")
        # menuLayout
        self.menuLayout.setTitle("&Layout")
        # menuTools
        self.menuTools.setTitle("&Tools")
        self.multiEdit.setText("Edit selected media")
        # menuAbout
        self.menuAbout.setTitle("&About")
        self.actionAbout.setText("About")
        self.actionAbout_Qt.setText("About Qt")

    def set_layout(self, layout):
        if self.layout is not None:
            self.layout.hide()
            self.gridLayout.removeWidget(self.layout)

            self.multiEdit.triggered.disconnect()
            self.selectAll.triggered.disconnect()
            self.deselectAll.triggered.disconnect()
            self.invertSelection.triggered.disconnect()

        self.layout = layout

        self.multiEdit.triggered.connect(self.layout.edit_selected_cues)
        self.selectAll.triggered.connect(self.layout.select_all)
        self.deselectAll.triggered.connect(self.layout.deselect_all)
        self.invertSelection.triggered.connect(self.layout.invert_selection)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.layout.setSizePolicy(sizePolicy)
        self.gridLayout.addWidget(self.layout, 0, 0)

        self.layout.show()

    def save(self):
        if self.file == '':
            self.save_with_name()
        else:
            self.save_session.emit(self.file)

    def save_with_name(self):
        self.file, _ = QFileDialog.getSaveFileName(parent=self,
                                                   filter='*.lsp',
                                                   directory=os.getenv('HOME'))
        if self.file != '':
            if not self.file.endswith('.lsp'):
                self.file += '.lsp'
            self.save()

    def show_preferences(self):
        prefUi = AppSettings(configuration.config_to_dict(), parent=self)
        prefUi.exec_()

        if(prefUi.result() == QDialog.Accepted):
            configuration.update_config_from_dict(prefUi.get_configuraton())

    def exit(self):
        confirm = QMessageBox.Yes
        if not ActionsHandler().is_saved():
            confirm = QMessageBox.question(self, 'Exit',
                                           'The current session is not saved. '
                                           'Exit anyway?')

        if confirm == QMessageBox.Yes:
            qApp.quit()

    def closeEvent(self, event):
        self.exit()
        event.ignore()

    def register_cue_options_ui(self, name, options_ui, category='',
                                shortcut=''):
        '''
            Register a new-cue choice for the edit-menu

            @param name: The name for the MenuAction
            @param options_ui: A method that provide the options for the new
                               cue(s) (e.g. show a file-dialog)
            @param category: The optional menu where insert the MenuAction
            @param shortcut: An optional shortcut for the MenuAction
        '''
        action = QAction(self)
        action.setText(name)
        action.triggered.connect(lambda: self._add_cues(options_ui()))
        if shortcut != '':
            action.setShortcut(shortcut)

        if category != '':
            if category not in self._cue_add_menus:
                menu = QMenu(category, self)
                self._cue_add_menus[category] = menu
                self.menuEdit.insertMenu(self.cueSeparator, menu)

            self._cue_add_menus[category].addAction(action)
        else:
            self.menuEdit.insertAction(self.cueSeparator, action)

    def update_window_title(self):
        saved = ActionsHandler().is_saved()
        if not saved and not self.windowTitle()[0] == '*':
            self.setWindowTitle('*' + self.windowTitle())
        elif saved and self.windowTitle()[0] == '*':
            self.setWindowTitle(self.windowTitle()[1:])

    def _action_done(self, action):
        self.statusBar.showMessage(action.log())
        self.update_window_title()

    def _action_undone(self, action):
        self.statusBar.showMessage('Undone' + action.log())
        self.update_window_title()

    def _action_redone(self, action):
        self.statusBar.showMessage('Redone' + action.log())
        self.update_window_title()

    def _add_cues(self, options_list):
        for options in options_list:
            try:
                cue = CueFactory.create_cue(options)
                self.layout.add_cue(cue)
            except Exception as e:
                message = ' '.join([str(i) for i in e.args])
                QMessageBox.critical(None, 'Error', message)

    def _load_from_file(self):
        if self._new_session_confirm():
            path = QFileDialog.getOpenFileName(parent=self, filter='*.lsp',
                                               directory=os.getenv('HOME'))[0]

            if os.path.exists(path):
                self.open_session.emit(path)
                self.file = path
                return True

        return False

    def _new_session_confirm(self):
        confirm = QMessageBox.question(self, 'New session',
                                       'The current session will be lost. '
                                       'Continue?')

        return confirm == QMessageBox.Yes

    def _startup(self):
        if self._new_session_confirm():
            self.new_session.emit()

    def _fullscreen(self, enable):
        if enable:
            self.showFullScreen()
        else:
            self.showMaximized()