Пример #1
0
class AsyncCaller(object):
    """Call a Python function after a delay."""
    def __init__(self, delay=10):
        self._delay = delay
        self._timer = None

    def _create_timer(self, f):
        self._timer = QTimer()
        self._timer.timeout.connect(f)
        self._timer.setSingleShot(True)

    def set(self, f):
        """Call a function after a delay, unless another function is set in the meantime."""
        self.stop()
        self._create_timer(f)
        self.start()

    def start(self):
        """Start the timer and call the function after a delay."""
        if self._timer:
            self._timer.start(self._delay)

    def stop(self):
        """Stop the current timer if there is one and cancel the async call."""
        if self._timer:
            self._timer.stop()
            self._timer.deleteLater()
Пример #2
0
class total_countdown(QThread):
    """ This class defines the progressbar update process """
    update_trigger = pyqtSignal()
    end_trigger = pyqtSignal()

    def __init__(self, *args, **kwargs):

        super(self.__class__, self).__init__()
        print("### total_countdown initializeed")

    def start(self, Total_time):

        print("### countdown started")

        self.Total_time = Total_time
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.emit_update_sputter)
        self.timer.start(1000)

    def emit_update_sputter(self):

        self.update_trigger.emit()

    def stop(self):
        self.timer.stop()
        self.timer.deleteLater()
Пример #3
0
class GuiResourceMonitor(ResourceMonitor, QWidget):
    """
    Implementation class of ResourceMonitor by the GUI process. The GUI process uses
    QTimer to implement start() and stop() methods.
    """
    def __init__(self):
        QWidget.__init__(self)
        ResourceMonitor.__init__(self, history_size=GUI_RESOURCE_HISTORY_SIZE)
        self.resource_monitor_timer = None

    def start(self):
        """
        Start the resource monitor by scheduling a QTimer.
        """
        self.resource_monitor_timer = QTimer()
        self.resource_monitor_timer.setSingleShot(False)
        self.resource_monitor_timer.timeout.connect(self.check_resources)
        self.resource_monitor_timer.start(GUI_RESOURCE_CHECK_INTERVAL)

    def stop(self):
        if self.resource_monitor_timer:
            try:
                self.resource_monitor_timer.stop()
                self.resource_monitor_timer.deleteLater()
            except RuntimeError:
                self._logger.error(
                    "Failed to stop GUI resource monitor timer in Debug pane")
Пример #4
0
 def remove_warn(self, timer: QtCore.QTimer, label: QtWidgets.QLabel):
     timer.deleteLater()
     label.setParent(None)
     label.destroy()
     self.parent.setGeometry(0, 20, 300, self.main_layout.count() * 200 - 200)
     if self.main_layout.count() == 0:
         self.parent.hide()
Пример #5
0
class MessageTip(QWidget):
    def __init__(self, msg: str):
        super().__init__()
        self.initUI(msg)

    def initUI(self, msg: str):
        self.setGeometry(300, 300, 350, 120)
        self.setStyleSheet("background-color: blue")
        self.setWindowFlags(Qt.FramelessWindowHint)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        label = QLabel()
        label.setText(msg)
        layout.addWidget(label)
        self.setLayout(layout)
        self.desktop = QDesktopWidget()
        self.move((self.desktop.availableGeometry().width() - self.width()),
                  self.desktop.availableGeometry().height())  #初始化位置到右下角
        self.showAnimation()

    def showAnimation(self):
        #显示弹出框动画
        self.animation = QPropertyAnimation(self, b'pos')
        self.animation.setDuration(500)
        self.animation.setStartValue(QPoint(self.x(), self.y()))
        self.animation.setEndValue(
            QPoint(
                (self.desktop.availableGeometry().width() - self.width()),
                (self.desktop.availableGeometry().height() - self.height())))
        self.animation.start()
        #设置弹出框1秒弹出,然后渐隐
        self.remainTimer = QTimer()
        self.remainTimer.timeout.connect(self.closeAnimation)
        self.remainTimer.start(1000)  #定时器3秒

    def closeAnimation(self):
        #清除Timer和信号槽
        self.remainTimer.stop()
        #self.disconnect(self.remainTimer,SLOT("closeAnimation()"))
        self.remainTimer.timeout.disconnect(self.closeAnimation)
        self.remainTimer.deleteLater()
        self.remainTimer = None
        #弹出框渐隐
        self.animation = QPropertyAnimation(self, b"windowOpacity")
        self.animation.setDuration(1000)
        self.animation.setStartValue(1)
        self.animation.setEndValue(0)
        self.animation.start()
        #动画完成后清理
        #self.connect(self.animation,SIGNAL("finished()"),SLOT("clearAll()"))
        self.animation.finished.connect(self.clearAll)

    def clearAll(self):
        self.close()
Пример #6
0
class Reloj(QObject):
    ''' clase ocupada para manejar los temporizadores '''
    def __init__(self):
        super().__init__()
        self.rapidez_reloj = RAPIDEZ_RELOJ  # ponderador
        self.temporizadores = []
        self.intervalo_clientes = LLEGADA_CLIENTES  # no cambia durante el juego

    def reanudar_reloj(self):
        for temporizador in self.temporizadores:
            temporizador.start()

    def pausar_reloj(self):
        for temporizador in self.temporizadores:
            temporizador.stop()

    def temporizador_chef(self, tiempo, senal, chef):
        tmp_chef = ChefTimer(tiempo * self.rapidez_reloj, senal, chef)
        tmp_chef.start()
        self.temporizadores.append(tmp_chef)

    def temporizador_cliente(self):
        ''' temporizador asociado a un cliente en especifico '''
        tmp_enojarse = QTimer()
        tmp_enojarse.setSingleShot(True)
        tmp_irse = QTimer()
        tmp_irse.setSingleShot(True)
        self.temporizadores.extend([tmp_enojarse, tmp_irse])
        # guardamos el temporizador del ultimo cliente para saber cuando cerrar
        # el DCC:
        self.ultimo_cliente_timer = tmp_irse
        return tmp_enojarse, tmp_irse

    def temporizador_clientes(self, func):
        ''' temporizador asociado a la llegada periodica de clientes '''
        self.tmp_clientes = QTimer()
        self.tmp_clientes.setInterval(self.rapidez_reloj *
                                      self.intervalo_clientes)
        self.tmp_clientes.timeout.connect(func)
        self.tmp_clientes.start()
        self.temporizadores.append(self.tmp_clientes)

    def temporizador_acabar_ronda(self, func):
        self.temporizadores.remove(self.tmp_clientes)
        self.tmp_clientes.deleteLater()  # nos aseguramos
        # que en caso de pausar y reanudar la ronda, no se vuelva a activar
        self.tmp_acabar_ronda = QTimer()
        self.tmp_acabar_ronda.setInterval(self.rapidez_reloj *
                                          self.intervalo_clientes)
        self.tmp_acabar_ronda.setSingleShot(True)
        self.tmp_acabar_ronda.timeout.connect(func)
        self.tmp_acabar_ronda.start()
        self.temporizadores.append(self.tmp_acabar_ronda)
Пример #7
0
class Progress(QDialog):
    def __init__(
            self,
            title,
            status,
            parent=None  # type: Any
    ):
        super().__init__(parent)
        self.setWindowTitle(title)
        buttonBox = QDialogButtonBox(QDialogButtonBox.Cancel)
        buttonBox.rejected.connect(self.reject)
        self._status = status
        self.progressBar = QProgressBar()
        self.progressBar.setRange(0, 1000)
        self.progressBar.setValue(0)
        self.description = QLabel()
        self.description.setText("")
        layout = QVBoxLayout()
        layout.addWidget(self.description)
        layout.addWidget(self.progressBar)
        layout.addWidget(buttonBox)
        self.setLayout(layout)
        self.prev_st = ""
        self.prev_pr = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self._check_status)
        self.timer.start(100)
        self._starter = status["start"]

    def _check_status(self):
        if self._starter is not None:
            self._starter()
            self._starter = None
        cur_pr = int(self._status.get("part", 0.) * 1000)
        if self.prev_pr != cur_pr:
            self.progressBar.setValue(cur_pr)
            self.prev_pr = cur_pr
        cur_st = self._status.get("description", "")
        if self.prev_st != cur_st:
            self.description.setText(cur_st)
            self.prev_st = cur_st
        if self._status.get("complete"):
            self.reject()

    def reject(self):
        try:
            self.timer.stop()
        except RuntimeError:
            pass
        else:
            self.timer.deleteLater()
        self._status["stop"] = True
        return super().reject()
Пример #8
0
class Message(QDialog):
    def __init__(self):
        self.desktop = QDesktopWidget()
        self.move((self.desktop.availableGeometry().width() - self.width()),
                  self.desktop.availableGeometry().height())  # 初始化位置到右下角
        self.showAnimation()

    # 弹出动画
    def showAnimation(self):
        # 显示弹出框动画
        self.animation = QPropertyAnimation(self, "pos")
        self.animation.setDuration(1000)
        self.animation.setStartValue(QPoint(self.x(), self.y()))
        self.animation.setEndValue(
            QPoint((self.desktop.availableGeometry().width() - self.width()),
                   (self.desktop.availableGeometry().height() - self.height() +
                    self.SHADOW_WIDTH)))
        self.animation.start()

        # 设置弹出框1秒弹出,然后渐隐
        self.remainTimer = QTimer()
        self.connect(self.remainTimer, signal("timeout()"), self,
                     signal.__slots__("closeAnimation()"))
        self.remainTimer.start(10000)  # 定时器10秒


# 关闭动画

    @pyqtSlot()
    def closeAnimation(self):
        # 清除Timer和信号槽
        self.remainTimer.stop()
        self.disconnect(self.remainTimer, signal("timeout()"), self,
                        signal.__slots__("closeAnimation()"))
        self.remainTimer.deleteLater()
        self.remainTimer = None
        # 弹出框渐隐
        self.animation = QPropertyAnimation(self, "windowOpacity")
        self.animation.setDuration(1000)
        self.animation.setStartValue(1)
        self.animation.setEndValue(0)
        self.animation.start()
        # 动画完成后清理
        self.connect(self.animation, signal("finished()"), self,
                     signal.__slots__("clearAll()"))

    # 清理及退出
    def clearAll(self):
        self.disconnect(self.animation, signal("finished()"), self,
                        signal.__slots__("clearAll()"))
        sys.exit()  # 退出
Пример #9
0
class ProgressBar(QProgressBar):
    def __init__(self, *args, **kwargs):
        super(ProgressBar, self).__init__(*args, **kwargs)
        self.setValue(0)
        if self.minimum() != self.maximum():
            self.timer = QTimer(self, timeout=self.onTimeout)
            self.timer.start(randint(1, 3) * 1000)

    def onTimeout(self):
        if self.value() >= 100:
            self.timer.stop()
            self.timer.deleteLater()
            del self.timer
            return
        self.setValue(self.value() + 1)
Пример #10
0
def wait_for(ms):
    future = Future()
    timer = QTimer()
    timer.timeout.connect(lambda:
                          (future.set_result(None), timer.deleteLater()))
    timer.setSingleShot(True)
    timer.start(ms)
    return future
Пример #11
0
class ProgressBar(QProgressBar):
    """
    This class is a custom progress bar which shows
    a dynamic loading bar.

    Attributes
    ----------
    timer : QTimer
        Loop iteration duration.

    Methods
    ----------
    onTimeOut()
        Updates the loading bar value.

    """
    def __init__(self, *args, **kwargs):
        super(ProgressBar, self).__init__(*args, **kwargs)
        self.setValue(0)

        if self.minimum() != self.maximum():
            self.timer = QTimer(self, timeout=self.onTimeout)
            self.timer.start(randint(1, 3) * 1000)

    def onTimeout(self):
        """
        This method changes the bar value.

        """

        if self.value() >= 100:
            self.timer.stop()
            self.timer.deleteLater()
            del self.timer
            return

        self.setValue(self.value() + 1)
Пример #12
0
class mainWindow(QMainWindow):

	def __init__(self,obj):
		super().__init__()
		self.setObjectName('Window1')
		self.obj=obj
		self.set=0
		self.initUI()

	def initUI(self):
		self.resize(850,500)
		self.setWindowTitle('Moodly 1.0 Beta - Configure')
		self.setWindowIcon(QIcon(':/Assets/moodly.gif'))
		self.setFixedSize(830,500)
		self.center()

		self.sysTray=QWidget()
		self.tray = SystemTrayIcon(QIcon(':/Assets/moodly.gif'),self.sysTray)
		self.tray.show()
		self.tray.trigger.connect(self.showApp)
		self.tray.qtrigger.connect(self.closeApp)
		self.tray.uptrigger.connect(self.updateNow)
		self.setWidget()

		self.show()


	def setWidget(self):
		if self.obj.configured==0:
			self.setCentralWidget(configureWidget(self))
		elif self.obj.configured==1:
			self.setCentralWidget(setupWidget(self))
		elif self.obj.configured==2:
			self.setStyleSheet('''#Window1{background-color: light gray;}''')
			self.setWindowTitle('Moodly 1.0 Beta')
			self.setMenuBar()
			self.tabWidget = tabWidget(self)
			self.setCentralWidget(self.tabWidget)

			self.tray.updateAction.setEnabled(True)
			self.statusBar = QStatusBar()
			self.setStatusBar(self.statusBar)
			self.statusBar.hide()
			self.statusLbl1 = QLabel()
			self.statusLbl2 = QLabel()
			self.statusLbl2.setAlignment(QtCore.Qt.AlignRight)

			self.statusBar.addWidget(self.statusLbl1)
			self.statusBar.addWidget(self.statusLbl2,QtCore.Qt.AlignRight)

			self.updateTimer()
			self.notifTimer()
			self.i_thread = {}
			self.nt=0


	def showApp(self):
		if self.isMinimized():
			self.showNormal()

		self.show()
		self.activateWindow()

	def closeApp(self):
		self.tray.hide()
		qApp.quit()


	def showStatus(self,msg,id_):
		if id_ == 0:
			self.statusLbl1.setText(msg)
		else:
			self.statusLbl2.setText(msg)

		self.statusBar.show()


	def hideStatus(self,id_):
		if id_==0:
			self.statusLbl1.setText('')
		else:
			self.statusLbl2.setText('')

		if self.statusLbl1.text() == '' and self.statusLbl2.text()=='':
			self.statusBar.hide()


	def updateTimer(self):
		self.current_timer = QTimer()
		delay = int(re.findall(r'\d+', self.obj.upIntval)[0])
		delay = delay*60*60*1000
		self.current_timer.timeout.connect(self.updater)
		self.current_timer.setSingleShot(True)
		if self.set==0:
			self.updater()
		else:
			self.current_timer.start(delay)


	def notifTimer(self):
		if self.obj.nIntval=="Turn Off":
			self.notifier = False
		else:
			delay = int(re.findall(r'\d+', self.obj.nIntval)[0])*60*60
			self.timer1 = QTimer()
			self.timer1.timeout.connect(partial(self.quickNotify))
			self.timer1.setSingleShot(True)
			self.timer1.start(10*60*1000)
			self.notifier= True


	def quickNotify(self):
		if self.obj.n !=0 and self.obj.updating==False:
			str_ = str(self.obj.n)
			self.tray.display_notify("Moodly","You have %s unread notifications"%str_,1)
		self.notifTimer()


	def quickStatus(self,i):
		if self.obj.updating==False:
			if 	i==0:
				self.showStatus('Next Update Scheduled at %s'%str(self.obj.scheduled))
				self.timer2 = QTimer()
				self.timer2.timeout.connect(partial(self.quickStatus,1))
				self.timer2.setSingleShot(True)
				self.timer2.start(6000)

			elif i==1:
				delay = int(re.findall(r'\d+', self.obj.upIntval)[0])*60*60
				self.showStatus('Last Update Scheduled at %s'%str(self.obj.scheduled-datetime.timedelta(0,delay))+'Failed')
				self.timer2 = QTimer()
				self.timer2.timeout.connect(partial(self.quickStatus,2))
				self.timer2.setSingleShot(True)
				self.timer2.start(6000)

			else:
				self.showStatus('Last Successful Update ')
				self.timer2 = QTimer()
				self.timer2.timeout.connect(self.hideStatus)
				self.timer2.setSingleShot(True)
				self.timer2.start(6000)
				self.statusTimer()


	def updater(self):
		self.obj.updating = True
		self.showStatus('Updating Moodly.....',0)
		self.thread=updateThread(self.obj)
		self.thread.finished.connect(self.downloader)
		self.thread.start()

	def downloader(self):
		if int(self.obj.dwnld)==1:
			self.showStatus('Downloading Files.....',0)
			self.dthread=downloadThread(self.obj)
			self.dthread.finished.connect(self.tabUpdater)
			self.dthread.start()
		else:
			self.tabUpdater()


	def closeEvent(self, event):
		self.hide()
		event.ignore()
		self.tray.display_notify('Moodly','Moodly running in notification tray.',1)

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

	def setMenuBar(self):
		exitAction = QAction(QIcon(':/Assets/close.png'), '&Exit', self)
		exitAction.setShortcut('Ctrl+Q')
		exitAction.triggered.connect(self.closeApp)

		self.alreadyOpen = 0

		configAction = QAction(QIcon(':/Assets/setting.png'), '&Configure', self)
		configAction.triggered.connect(self.changeConfig)
		configAction.setShortcut('Ctrl+Shift+C')

		updateAction = QAction(QIcon(':/Assets/sync.png'), '&Update Now', self)
		updateAction.triggered.connect(self.updateNow)
		updateAction.setShortcut('Ctrl+U')

		menubar = self.menuBar()
		fileMenu = menubar.addMenu('&File')
		fileMenu.addAction(configAction)
		fileMenu.addAction(updateAction)
		fileMenu.addAction(exitAction)

	def updateNow(self):
		if self.obj.updating==False:
			self.current_timer.stop()
			self.current_timer.deleteLater()
			self.updater()

		else:
			reply = QMessageBox.information(self,'Moodly',"An update is already in progress. ", QMessageBox.Ok)
			if reply == QMessageBox.Ok:
				pass


	def changeConfig(self):
		if self.alreadyOpen is 0:
			self.tab = reConfigureWidget(self.tabWidget)
			self.tabWidget.addTab(self.tab,QIcon(':/Assets/setting.png'),'Configure')
			self.tabWidget.setTabToolTip(self.tabWidget.indexOf(self.tab),'Configure')
			self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.tab))
			self.alreadyOpen=1
		else:
			self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.tab))


	def verify(self):
		self.obj.saveConfig(1)
		self.thread=WorkThread(self.obj)
		self.thread.finished.connect(self.notify)
		self.thread.start()
		self.set=1
		self.setWidget()



	def notify(self):
		self.setWidget()
		self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1])


	def tabUpdater(self):
		self.set=1
		self.tabWidget.tab1.updater()
		self.tabWidget.tab2.updater()
		for tab in self.tabWidget.tab:
			tab.updater()
		self.obj.updating = False
		self.c_timer = QTimer()
		self.c_timer.timeout.connect(partial(self.hideStatus,0))
		self.c_timer.setSingleShot(True)
		self.showStatus('Update Completed',0)
		self.c_timer.start(5000)
		self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1])
		self.updateTimer()

	def itemsWriter(self,fileName,id1,id2):
		nt=self.getIndex()
		self.i_thread[nt] = itemsWriterThread(fileName,id1,id2,nt,self.obj)
		self.i_thread[nt].finished.connect(partial(self.del_i_thread,self.i_thread[nt].id3))
		self.i_thread[nt].start()


	def del_i_thread(self,id3):
		self.i_thread[id3]=0


	def getIndex(self):
		if self.nt==0:
			return self.nt
		else:
			for i in range(0,self.nt):
				if self.i_thread[i]==0:
					return i
			self.nt+=1
			return self.nt


	def configWriter(self,text1,text2,combo1,combo2,text3,path_):
		self.sid3=self.showStatus('Configuring...',1)
		self.c_thread = configWriterThread(self.obj,text1,text2,combo1,combo2,text3,path_)
		self.c_thread.finished.connect(self.reConfigModify)
		self.c_thread.start()


	def reConfigModify(self):
		if self.alreadyOpen==1:
				self.tab.status_label.setText(self.obj.config_status)
		self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1])
		self.re_timer = QTimer()
		self.re_timer.timeout.connect(partial(self.hideStatus,1))
		self.re_timer.setSingleShot(True)
		self.showStatus(self.obj.config_status,1)
		self.re_timer.start(5000)

		self.tabWidget.updating = False

		if self.obj.intValChanged ==0:
			self.current_timer.stop()
			self.current_timer.deleteLater()
			self.updateTimer()
			self.obj.intValChanged = -1

		elif self.obj.intValChanged ==1:
			if self.notifier == True:
				self.timer1.stop()
				self.timer1.deleteLater()
			self.notifTimer()
			self.obj.intValChanged = -1

		elif self.obj.intValChanged ==2:
			self.current_timer.stop()
			self.current_timer.deleteLater()
			self.updateTimer()

			if self.notifier == True:
				self.timer1.stop()
				self.timer1.deleteLater()
			self.notifTimer()

			self.obj.intValChanged = -1
Пример #13
0
class Timer(QWidget):
    def __init__(self):
        super(Timer, self).__init__()

        self.sec = 0

        self.hourLCDNumber = QLCDNumber()
        self.hourLCDNumber.setDigitCount(2)
        self.hourLCDNumber.display(00)

        self.minLCDNumber = QLCDNumber()
        self.minLCDNumber.setDigitCount(2)
        self.minLCDNumber.display(00)

        self.secLCDNumber = QLCDNumber()
        self.secLCDNumber.setDigitCount(2)
        self.secLCDNumber.display(00)

        self.startSuspendButton = QPushButton('开始')
        self.restartButton = QPushButton('重置')

        self.startSuspendButton.clicked.connect(self.startSuspend)
        self.restartButton.clicked.connect(self.restart)

        hTimerLayout = QHBoxLayout()
        hTimerLayout.addWidget(self.hourLCDNumber)
        hTimerLayout.addWidget(self.minLCDNumber)
        hTimerLayout.addWidget(self.secLCDNumber)

        hButtonLayout = QHBoxLayout()
        hButtonLayout.addWidget(self.startSuspendButton)
        hButtonLayout.addWidget(self.restartButton)

        vLayout = QVBoxLayout()
        vLayout.addLayout(hTimerLayout)
        vLayout.addLayout(hButtonLayout)

        self.setLayout(vLayout)

    def operate(self):
        self.sec += 1
        min, sec = divmod(self.sec, 60)
        hour, min = divmod(min, 60)

        self.hourLCDNumber.display(hour)
        self.minLCDNumber.display(min)
        self.secLCDNumber.display(sec)

    def startSuspend(self):
        bText = self.startSuspendButton.text()
        if bText == '开始' or bText == '继续':
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.operate)
            self.timer.start(1000)
            self.startSuspendButton.setText('暂停')

            GPIO.setup()
            GPIO.loop()
        elif bText == '暂停':
            self.timer.deleteLater()
            self.startSuspendButton.setText('继续')

            GPIO.destroy()

    def restart(self):
        self.sec = -1
        self.operate()
        if self.startSuspendButton.text() == '暂停':
            self.timer.deleteLater()
            GPIO.destroy()
        self.startSuspendButton.setText('开始')
Пример #14
0
class FullscreenToolbar(QWidget):
    def __init__(self, parent=None, flags=0):
        super().__init__(parent)

        uic.loadUi('ui/fullscreenToolbar.ui', self)

        self.setWindowFlags(Qt.Tool|Qt.Widget|Qt.FramelessWindowHint);
        self.setAttribute(Qt.WA_NoSystemBackground, True);
        self.setAttribute(Qt.WA_TranslucentBackground, True); 

        app = QApplication.instance()
        settings = app.settings_manager

        if settings.value("player/volume"):
            self.volume_slider.setValue(int(settings.value("player/volume")))

        parent.playback_started.connect(self.video_playback_started)
        parent.playback_paused.connect(self.video_playback_paused)
        parent.playback_stopped.connect(self.video_playback_stopped)
        parent.playback_error.connect(self.video_playback_error)
        parent.volume_changed.connect(self.video_volume_changed)

        self.play_btn.clicked.connect(self.play_btn_clicked)
        self.stop_btn.clicked.connect(self.stop_btn_clicked)
        self.fullscreen_btn.clicked.connect(self.switch_fullscreen_mode)
        self.volume_slider.sliderMoved.connect(self.volume_changed)

        self.timer = None
        self.epg = None
        self.epg_list = []

        # Set custom icons
        self.play_btn.setIcon(TXIcon('icons/play-button.svg', Qt.white))
        self.stop_btn.setIcon(TXIcon('icons/stop-button.svg', Qt.white))
        self.fullscreen_btn.setIcon(TXIcon('icons/unfullscreen.svg', Qt.white))

        self.show_progress.hide()

    def show(self):
        super().show()
        self.activateWindow()
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update)
        self.timer.start(1000)

    def hide(self):
        super().hide()
        if self.timer:
            self.timer.stop()
            self.timer.deleteLater()
            self.timer = None

    def play_btn_clicked(self, checked=False):
        from videoplayer import VideoPlayerState
        player_state = self.parent().get_state()
        if player_state is VideoPlayerState.PLAYER_PLAYING:
            self.parent().pause()
        else:
            self.parent().unpause()

    def stop_btn_clicked(self, checked=False):
        self.parent().stop()

    def volume_changed(self, level):
        self.parent().volume_changed.disconnect(self.video_volume_changed)
        self.parent().set_volume(level)
        self.parent().volume_changed.connect(self.video_volume_changed)

    def switch_fullscreen_mode(self, checked=False):
        self.parent().exit_fullscreen()

    def epg_data_available(self, epg_list):
        self.epg_list = epg_list

    # Signals

    def video_playback_started(self, channel):
        self.play_btn.setIcon(TXIcon('icons/pause-button.svg', Qt.white))
        self.osd_channel_name.setText(channel.name)
        self.epg = EPGRetriever(channel, datetime.datetime.now().strftime("%Y-%m-%d"))
        self.epg.epg_data_available.connect(self.epg_data_available)
        self.epg.retrieve_epg()

    def video_playback_paused(self, channel):
        self.play_btn.setIcon(TXIcon('icons/play-button.svg', Qt.white))

    def video_playback_stopped(self, channel):
        self.play_btn.setIcon(TXIcon('icons/play-button.svg', Qt.white))

    def video_playback_error(self, channel):
        self.play_btn.setIcon(TXIcon('icons/play-button.svg', Qt.white))

    def video_volume_changed(self, value):
        self.volume_slider.setValue(int(value))

    # Qt Events

    def paintEvent(self, event):
        super().paintEvent(event)
        now = datetime.datetime.now()
        self.clock_label.setText(now.strftime("%X"))

        if self.epg_list:
            hours = [toLocalTime(x[0]) for x in self.epg_list]
            now = datetime.datetime.strptime(datetime.datetime.now().strftime("%H:%M"), "%H:%M")
            current = [x for x in itertools.takewhile(lambda t: now >= datetime.datetime.strptime(t, "%H:%M"), hours)][-1]

            for idx, epg_line in enumerate(self.epg_list):
                if toLocalTime(epg_line[0]) == current:
                    self.show_name_label.setText(epg_line[1])

                    if len(self.epg_list) > idx + 1:
                        start_time = datetime.datetime.strptime(toLocalTime(epg_line[0]), "%H:%M")
                        end_time = datetime.datetime.strptime(toLocalTime(self.epg_list[idx + 1][0]), "%H:%M")
                        elapsed_time = datetime.datetime.strptime(datetime.datetime.now().strftime("%H:%M"), "%H:%M")
                        show_duration = end_time - start_time
                        elapsed_duration = elapsed_time - start_time
                        self.show_progress.setMinimum(0)
                        self.show_progress.setMaximum(show_duration.seconds)
                        self.show_progress.setValue(elapsed_duration.seconds)
                        self.show_progress.show()
                    return

        self.show_name_label.setText("")

    def keyPressEvent(self, event):
        super().keyPressEvent(event)
        self.parent().keyPressEvent(event)
Пример #15
0
class PlotWindow(QWidget, Ui_MainWindow):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self)
        """ setup initial parameters """
        self.time_frame = 1  # default update time frame [s] for LOAD LOG data
        self.n_points = int(self.lineEdit_1.text())  # default N points to plot
        self.channel = 0  # channel number 0 or 1
        self.reload_flag = True  # flag that is used to reload data in LOAD LOG
        self.common_path = 'C:/Users/Preparation PC/Documents/Python scripts/Communication_LOG_SERVER_2020/'
        """ connect all signals """
        for i in self.buttons_dict:
            """ direct construction of lambda with argument and state of the button (not used but has to be there) """
            self.buttons_dict[i].clicked.connect(
                lambda state, b=i: self.load_file(b))
        self.lineEdit_1.returnPressed.connect(
            lambda: self.change_n_points(self.lineEdit_1.text()))
        self.lineEdit_2.returnPressed.connect(
            lambda: self.change_channel(self.lineEdit_2.text()))
        self.load_button.clicked.connect(lambda: self.load_file())
        """ create a timer for updating plot (only for Load LOG button) """
        self.timer_update = QTimer(self)
        self.timer_update.timeout.connect(self.update_plot)

    def load_file(self, *server_name):
        """ 
        Read values from saved log file into a local panda frame.
        In case *sever_name is given - starts the server client and does not load
        log file anymore, instead adds new values from the server to the displayed
        data. If there is no *server_name then it shows the open file dialog. 
        
        """
        self.stop()  # stop all running timers/server_clients
        """ Get the file name: either from servers dict or from user dialog"""
        try:
            if server_name:
                self.server_name = server_name[0]
                self.port = LoS.server_list[self.server_name][1]
                self.servers_with_port = [
                    k for k, v in LoS.server_list.items() if v[1] == self.port
                ]  # return servers with this port
                print(self.servers_with_port)
                # TODO: provide full path from log folder
                self.load_file_name = str(self.common_path) + str(
                    self.servers_with_port[0]
                ) + '-log-dynamic.dat'  # takes the first server log with this port
                print(self.load_file_name)
                self.channel = int(LoS.server_list[self.server_name][4])
            else:
                self.load_file_name = QFileDialog.getOpenFileName(
                    self, 'Open file', '', '*.dat')[0]
        except:
            print("error getting file name")
        """ Load data from the file self.load_file_name """
        try:
            with open(self.load_file_name, 'rb') as f:
                self.loaded_data = pd.read_csv(f, sep=",")
            f.close()
        except:
            self.loaded_data = []
            print("error loading file")
            pass
        """ Exctract necessary n_points from self.channel from panda frame """
        if len(self.loaded_data) != 0:
            self.data_to_display = np.array(
                self.loaded_data.tail(self.n_points).iloc[1:,
                                                          self.channel + 1])
        else:
            self.data_to_display = np.array([])
        """ Start the server client or run the timer to reload data from log file """
        if server_name:
            print(f"starting smart {self.server_name} watch")
            self.start_network_client(self.server_name)
        else:
            print("starting standard log watch")
            self.start_reload_log_loop()

    def start_network_client(self, server_name: str):
        """ 
        Starts the separate thread with server client NetworkGetPressure
        to obtain pressure/temp values from the corresponding server.
        Server_dictionary is used to obtain connection parameters.
        """
        print("connecting to server ", server_name)
        self.reload_flag = False
        self.host = LoS.server_list[self.server_name][0]
        self.port = int(LoS.server_list[self.server_name][1])
        self.channel = int(LoS.server_list[self.server_name][4])
        self.networking = NetworkGetPressure(self.host, self.port)  # thread
        self.networking.new_value_trigger.connect(self.update_data_to_display)
        self.networking.start()  # start this thread to get pressure
        gc.collect()

    def update_data_to_display(self, pressure):
        """ Update data array when a new value comes in the networking thread"""
        try:
            self.pressure_preliminary = float(
                pressure.split(',')[self.channel])
            """ If we are getting temperature from the Lakeshore"""
            if self.port == 63205:
                if (self.pressure_preliminary < 500):
                    self.pressure = self.pressure_preliminary
            else:
                """ If we are getting pressure values"""
                if (self.pressure_preliminary >
                        0) and (self.pressure_preliminary < 0.05):
                    self.pressure = self.pressure_preliminary
                    print(self.pressure)
                else:
                    pass
        except:
            self.pressure = 0.0
            pass
        """ Append the value from server to the data which we display (with shift) """
        if len(self.data_to_display) >= self.n_points:
            self.data_to_display = np.append(self.data_to_display,
                                             self.pressure)[1:]
        else:
            self.data_to_display = np.append(self.data_to_display,
                                             self.pressure)

        self.update_plot()  # call the plot update function

    def update_plot(self):
        """ 
        Updates the plot. Depending on the reload_flag it can re-load data 
        from the LOG file (in case LOAD LOG button is used) or just updates 
        the plot after the new value from the server was appended to the data 
        array.
        
        """
        if self.reload_flag:
            try:
                with open(self.load_file_name, 'rb') as f:
                    self.loaded_data = pd.read_csv(f, sep=",")
                f.close()
                self.data_to_display = np.array(
                    self.loaded_data.tail(
                        self.n_points).iloc[1:, self.channel + 1])
                print("reloaded")
            except:
                print("error loading data")
                pass
        """Check the data prior plot"""
        for i in range(len(self.data_to_display)):
            try:
                self.data_to_display[i] = float(self.data_to_display[i])
            except:
                self.data_to_display[i] = 0.0
                pass
        """ Update plot """
        try:
            self.plot_T.clear()
            self.plot_T.plot(np.arange(0, len(self.data_to_display)) *
                             self.time_frame,
                             self.data_to_display,
                             symbolSize=5,
                             symbolBrush="r",
                             symbol='o')
        except:
            print("error in plot")
            pass

    def change_n_points(self, new_n_points: int):
        """ Change number of points in the data array to plot """
        if (int(new_n_points) > 0) and (int(new_n_points) < 360 * 24):
            self.n_points = int(new_n_points)
            print("changed number of points to ", self.n_points)
        else:
            print("invalid number of points")
            pass
        """ Reload once from the log file in case reading from server """
        if not self.reload_flag:
            self.load_file(str(self.server_name))

    def change_channel(self, new_channel: int):
        """ Works only for LOAD LOG case """
        if (int(new_channel) == 0) or (int(new_channel) == 1):
            self.channel = int(new_channel)
            print("changed channel to ", self.channel)
        #            self.label_3.setText(str(self.channels_list[self.channel+1]))
        else:
            print("invalid channel")
            pass

    def start_reload_log_loop(self):
        """ Works only for LOAD LOG case """
        #        self.label_3.setText(str(self.channels_list[self.channel+1]))
        self.plot_T.clear()
        self.reload_flag = True
        self.timer_update.start(self.time_frame * 1000)

    def stop(self):
        try:
            self.timer_update.stop()
        except Exception as e:
            logging.exception(e)
            print(e)
        try:
            self.data_to_display = np.array([])
        except:
            pass
        try:
            self.networking.quit()
            self.networking.wait()
        except Exception as e:
            logging.exception(e)
            print(e)
            pass

    def __del__(self):
        self.stop()
        try:
            self.timer_update.deleteLater()
        except:
            pass

    def closeEvent(self, event):
        try:
            self.__del__()
            self.stop()
        except:
            print("error killing timer")
        event.accept()
Пример #16
0
class SecondWindow(QWidget):
    def __init__(self):
        super(SecondWindow, self).__init__()
        self.setWindowTitle("BME Reaction Time Tester Pro 2000")
        self.label = QLabel(self)
        self.label.resize(MW.dispWidth, MW.dispHeight)

        # self.display_monitor = 1  # the number of the monitor you want to display your widget
        # self.monitor = QDesktopWidget().screenGeometry(self.display_monitor)
        # self.move(self.monitor.left(), self.monitor.top())

        self.showFullScreen()
        self.initUI()
        self.showThisMany = 10
        self.state = 0
        self.imShowed = 0
        self.popped = 0

        self.p = vlc.MediaPlayer("song.mp3")

        self.timeClick = 0
        self.timeImage = 0
        self.reaction = 0
        self.reactions = []

        self.imgLabel = QLabel(self)
        self.image = QPixmap('audi.jpg')
        self.imgLabel.setPixmap(self.image)
        self.imgLabel.move(MW.dispWidth / 2 - self.imgLabel.width() / 2, MW.dispHeight / 2 - self.imgLabel.height() / 2)
        self.instText = QLabel(self)

        self.timer = QTimer(self)
        self.stateMachine()


    def stateMachine(self):
        if self.state == 0:
            self.showInstLabel("Hello " + MW.lineInName.text() + " !")
            if MW.radiobutton.isChecked():
                self.p.play()
            self.state = 1
            self.timer.timeout.connect(self.stateMachine)
            self.timer.start(4000)
        elif self.state == 1:
            self.showInstLabel("Press ENTER when you see the car on the screen!")
            self.state = 2
            self.timer.timeout.connect(self.stateMachine)
            self.timer.start(4000)
        elif self.state == 2:
            self.showInstLabel("Press ENTER to start!")
            self.state = 3
        elif self.state == 4:
            rt = randint(1000, 10000)
            self.timer.timeout.connect(self.showImage)
            self.timer.start(rt)
        elif self.state == 5:
            self.mn = mean(self.reactions)
            MW.fid.write(str(self.mn))
            MW.fid.write("\n")
            MW.fid.close()
            self.showInstLabel("Thank you!" + "\n" + "Your average time was " + str('%.3f' % self.mn) +
                               " s.\n"+"Press ENTER to quit!")
            self.timer.stop()
            self.timer.deleteLater()



    def showInstLabel(self, text):
        self.font = QFont("Courier", MW.dispWidth/40, QFont.Bold)
        self.instText.setStyleSheet('color:white')
        self.instText.setFont(self.font)
        self.instText.setText(text)
        self.instText.adjustSize()
        self.instText.move(MW.dispWidth / 2 - self.instText.width()/2, MW.dispHeight/2)
        self.instText.repaint()
        self.instText.show()

    @pyqtSlot(QImage)
    def setImage(self, image):
        self.label.setPixmap(QPixmap.fromImage(image))

    def initUI(self):
        self.th = Thread(self)
        self.th.changePixmap.connect(self.setImage)
        self.th.start()

    def pressed(self):
        if self.state <= 3:
            self.instText.hide()
            self.state = 4
        elif self.state == 4:
            self.imShowed = self.imShowed + 1
            self.timePress= time.time()
            self.reaction = self.timePress - self.timeImage
            self.imgLabel.hide()
            self.popped = 0
            self.reactions.append(self.reaction)
            self.buff = str(self.reaction) + ";"
            MW.fid.write(self.buff)
            print(str(self.reaction))
            if self.imShowed >= self.showThisMany:
                self.state = 5
                self.stateMachine()
        elif self.state == 5:
            if MW.radiobutton.isChecked():
                self.p.stop()
            self.th.isRunning = False
            self.th.terminate()
            self.close()

    def showImage(self):
        self.imgLabel.move(MW.dispWidth/2 -self.imgLabel.width()/2, MW.dispHeight / 2 - self.imgLabel.height() / 2)
        self.imgLabel.show()
        self.timeImage = time.time()
        if self.popped == 0:
            self.stateMachine()
            self.popped = 1

    def keyPressEvent(self, keyEvent):
        super(SecondWindow, self).keyPressEvent(keyEvent)
        if keyEvent.key() == Qt.Key_Space:
            self.pressed()
        elif keyEvent.key() == Qt.Key_Return:
            self.pressed()
Пример #17
0
class PermitBar(QWidget):
    to_usercenter = pyqtSignal(int)

    def __init__(self, *args, **kwargs):
        super(PermitBar, self).__init__(*args, **kwargs)
        self.user_id = None
        layout = QHBoxLayout(margin=0, spacing=0)
        # 用户头像
        self.avatar = CAvatar(self,
                              shape=CAvatar.Circle,
                              url='media/avatar.png',
                              size=QSize(22, 22),
                              objectName='userAvatar')
        self.avatar.clicked.connect(self.to_user_center)
        layout.addWidget(self.avatar, alignment=Qt.AlignRight)
        # 用户名
        self.username_shown = QPushButton('用户名用户名',
                                          parent=self,
                                          objectName='usernameShown',
                                          clicked=self.to_user_center)
        layout.addWidget(self.username_shown, alignment=Qt.AlignRight)
        # 按钮
        self.login_button = QPushButton('登录',
                                        parent=self,
                                        objectName='loginBtn')
        layout.addWidget(self.login_button, alignment=Qt.AlignRight)
        self.register_button = QPushButton('注册',
                                           parent=self,
                                           objectName='registerBtn')
        layout.addWidget(self.register_button, alignment=Qt.AlignRight)
        self.logout_button = QPushButton('注销',
                                         parent=self,
                                         objectName='logoutBtn')
        layout.addWidget(self.logout_button, alignment=Qt.AlignRight)
        self.setLayout(layout)
        # 样式、属性
        self.username = ''
        self.timer_finished_count = 0
        self.login_button.setCursor(Qt.PointingHandCursor)
        self.register_button.setCursor(Qt.PointingHandCursor)
        self.logout_button.setCursor(Qt.PointingHandCursor)
        self.initial_show()  # 初始显示的控件
        self.setObjectName('permitBar')
        self.setStyleSheet("""
        #permitBar{
            min-height:22px;
            max-height:22px;
        }
        #loginBtn,#registerBtn,#logoutBtn{
            border:none;
            padding-left: 2px;
            padding-right: 4px;
            color: #FFFFFF;
        }
        #logoutBtn{
            margin-right:5px;
        }
        #loginBtn:hover,#registerBtn:hover,#logoutBtn:hover {
            color: rgb(54,220,180);

        }
        #usernameShown{
            margin-left: 3px;
            border:none;
            padding: 0 2px;
        }
        /*
        #userAvatar{
            background-color: rgb(100,255,120);
            min-width:22px;
            border-radius: 12px;
            margin-right: 2px;
        }
        */
        """)

    def initial_show(self):
        self.avatar.hide()
        self.username_shown.hide()
        self.logout_button.hide()

    # 设置用户id
    def set_user_id(self, uid):
        self.user_id = uid

    # 前往用户中心
    def to_user_center(self):
        if not self.user_id:
            return
        self.to_usercenter.emit(self.user_id)

    # 显示用户名
    def show_username(self, username):
        self.avatar.show()
        self.username_shown.setText(username + " ")  # 加空格防止初始动态化的时候跳动
        self.username = username
        self.username_shown.show()
        self.login_button.hide()
        self.register_button.hide()
        self.logout_button.show()
        if hasattr(self, 'timer'):
            self.timer.deleteLater()
            del self.timer
        self.timer = QTimer()
        self.timer.start(500)
        self.timer.timeout.connect(self._dynamic_username)

    # 设置头像
    def setAvatar(self, avatar_url):
        self.avatar.setUrl(avatar_url)

    # 用户注销
    def user_logout(self):
        self.username_shown.setText('')
        self.username = ''
        self.username_shown.hide()
        self.logout_button.hide()
        self.avatar.hide()
        self.login_button.show()
        self.register_button.show()
        if hasattr(self, 'timer'):
            # print('注销销毁定时器piece.base.PermitBar.user_logout()')
            self.timer.stop()
            self.timer.deleteLater()
            del self.timer

    # 设置用户名滚动显示
    def _dynamic_username(self):
        if self.timer_finished_count == len(self.username):
            self.username_shown.setText(self.username + " ")
            self.timer_finished_count = 0
        else:
            text = self.username[
                self.
                timer_finished_count:] + " " + self.username[:self.
                                                             timer_finished_count]
            self.username_shown.setText(text)
            self.timer_finished_count += 1
class ResonanceFrequencyFinder(QMainWindow):

	# AVAILABLE_WINDOW_SIZES = ["5 Sec", "8 Sec", "10 Sec", "15 Sec", "20 Sec"]

	DEFAULT_GRAPH_PADDING = 2

	DEFAULT_FFT_WINDOW_SIZE = 5

	DEFAULT_SAMPLE_PADDING = 2

	DEFAULT_RECORDING_DURATION = 30 + DEFAULT_SAMPLE_PADDING

	DEFAULT_MIN_FREQUENCY = 17

	DEFAULT_MAX_FREQUENCY = 35

	DEFAULT_FREQUENCY_STEP = 2

	# Used to create a band for which the average frequency amplitude is computed
	DEFAULT_FREQUENCY_PADDING = 0.2

	DEFAULT_BANDPASS_MIN = 8

	DEFAULT_BANDPASS_MAX = 40

	DEFAULT_C3_CHANNEL_INDEX = 4

	DEFAULT_CZ_CHANNEL_INDEX = 2

	DEFAULT_C4_CHANNEL_INDEX = 0

	def __init__(self, board: BoardShim):
		super().__init__()
		self.setGeometry(0, 0, 1800, 900)
		self.setWindowTitle("Resonance-Like Frequency")

		self.board = board

		self.recording_progress_dialog = None
		self.eeg_data_buffer = utils.EegData()
		self.reading_timer = QTimer()
		self.recording = False

		self.recording_reference = False
		self.reference_eeg_data = utils.EegData()

		self.index_generator = utils.FrequencyIndexGenerator(global_config.SAMPLING_RATE)
		self.eeg_sample_count = 0

		self.root_widget = QWidget()
		self.root_layout = QGridLayout()
		self.root_widget.setLayout(self.root_layout)
		self.setCentralWidget(self.root_widget)

		title = QLabel("<h1>Resonance Frequency Finder</h1>")
		title.setAlignment(Qt.AlignCenter)
		self.root_layout.addWidget(title, 0, 0, 1, 3)

		# window_size_label = QLabel("window size: ")
		# window_size_label.setAlignment(Qt.AlignRight)

		# self.window_size_combo_box = QComboBox()
		# self.window_size_combo_box.addItems(self.AVAILABLE_WINDOW_SIZES)

		self.root_directory_label = QLabel()
		self.select_root_directory = QPushButton("Select/Change")
		self.select_root_directory.clicked.connect(self.pick_root_directory)

		self.record_btn = QPushButton("Record")
		self.record_btn.setEnabled(False)
		self.record_btn.clicked.connect(self.record_clicked)

		self.record_reference_btn = QPushButton("Record Reference")
		self.record_reference_btn.clicked.connect(self.record_reference_clicked)

		# self.root_layout.addWidget(utils.construct_horizontal_box([
		# 	window_size_label, self.window_size_combo_box, self.record_btn
		# ]), 1, 0, 1, 3)

		self.load_results_btn = QPushButton("Load Existing Data")
		self.load_results_btn.clicked.connect(self.load_existing_data)

		self.root_layout.addWidget(utils.construct_horizontal_box([
			self.record_btn, self.record_reference_btn, self.root_directory_label,
			self.select_root_directory, self.load_results_btn
		]), 1, 0, 1, 3)

		self.current_freq_label = QLabel()

		self.root_layout.addWidget(utils.construct_horizontal_box([self.current_freq_label]), 2, 0, 1, 3)

		self.frequency_slider = QSlider()
		self.frequency_slider.setRange(self.DEFAULT_MIN_FREQUENCY, self.DEFAULT_MAX_FREQUENCY)
		self.frequency_slider.setSingleStep(self.DEFAULT_FREQUENCY_STEP)
		self.frequency_slider.setTickInterval(self.DEFAULT_FREQUENCY_STEP)
		self.frequency_slider.valueChanged.connect(self.update_freq_label)
		self.frequency_slider.setTickPosition(QSlider.TicksBelow)
		self.frequency_slider.setOrientation(Qt.Horizontal)

		min_freq_label = QLabel(f"<b>{self.DEFAULT_MIN_FREQUENCY} Hz</b>")
		max_freq_label = QLabel(f"<b>{self.DEFAULT_MAX_FREQUENCY} Hz</b>")

		self.root_layout.addWidget(utils.construct_horizontal_box([
			min_freq_label, self.frequency_slider, max_freq_label
		]), 3, 0, 1, 3)

		self.c3_amplitude_bar_set = QBarSet("Electrode C3")
		self.cz_amplitude_bar_set = QBarSet("Electrode Cz")
		self.c4_amplitude_bar_set = QBarSet("Electrode C4")

		self.frequencies = []

		for freq in range(self.DEFAULT_MIN_FREQUENCY, self.DEFAULT_MAX_FREQUENCY + 1, self.DEFAULT_FREQUENCY_STEP):
			self.frequencies.append(f"{freq} Hz")
			self.c3_amplitude_bar_set.append(1)
			self.cz_amplitude_bar_set.append(1)
			self.c4_amplitude_bar_set.append(1)

		self.freq_axis = QBarCategoryAxis()
		self.freq_axis.append(self.frequencies)

		self.amplitude_axis = QValueAxis()
		self.amplitude_axis.setRange(0, 4)

		self.freq_chart = QChart()
		self.freq_chart.setAnimationOptions(QChart.SeriesAnimations)

		self.electrodes_data_series = QBarSeries()
		self.electrodes_data_series.append(self.c3_amplitude_bar_set)
		self.electrodes_data_series.append(self.cz_amplitude_bar_set)
		self.electrodes_data_series.append(self.c4_amplitude_bar_set)

		self.freq_chart.addSeries(self.electrodes_data_series)
		self.freq_chart.setTitle("<h1>Frequency Amplitude Increase</h1>")
		self.freq_chart.addAxis(self.freq_axis, Qt.AlignBottom)
		self.freq_chart.addAxis(self.amplitude_axis, Qt.AlignLeft)

		self.electrodes_data_series.attachAxis(self.amplitude_axis)
		self.electrodes_data_series.attachAxis(self.freq_axis)

		self.frequency_amplitude_graph = QChartView(self.freq_chart)
		self.frequency_amplitude_graph.setRenderHint(QPainter.Antialiasing)

		self.root_layout.addWidget(self.frequency_amplitude_graph, 4, 0, 15, 3)

		self.auto_adjust_axis()

	def update_freq_label(self):
		self.current_freq_label.setText("Selected Frequency: {} Hz".format(self.frequency_slider.value()))

	def pick_root_directory(self):
		path = QFileDialog.getExistingDirectory(self, "Root Directory...")
		self.root_directory_label.setText(path)

	def record_clicked(self, reference: bool = False):
		# selected_window_text = self.window_size_combo_box.currentText()
		# window_size_text = selected_window_text.replace(" Sec", "")

		# window_size = -1
		#
		# if utils.is_integer(window_size_text):
		# 	window_size = int(window_size_text)
		# else:
		# 	print("Invalid window size...")
		# 	return

		# window_size_in_samples = window_size * SAMPLING_RATE

		recording_duration_in_samples = self.DEFAULT_RECORDING_DURATION * global_config.SAMPLING_RATE

		if not reference and (self.frequency_slider.value() - self.DEFAULT_MIN_FREQUENCY) % self.DEFAULT_FREQUENCY_STEP != 0:
			err = QErrorMessage(self)
			err.showMessage("Invalid Frequency Selected")
			err.exec()
			return

		self.recording_progress_dialog = \
			QProgressDialog("Reading EEG data from board...", "Stop Recording", 0, int(recording_duration_in_samples), self)
		self.recording_progress_dialog.setWindowTitle("Reading Data, Please Wait...")
		self.recording_progress_dialog.setWindowModality(Qt.WindowModal)
		self.recording_progress_dialog.show()

		if reference:
			self.recording_reference = True
		else:
			self.recording = True
			self.eeg_data_buffer.clear()

		self.board.start_stream()

		self.reading_timer = QTimer()
		self.reading_timer.timeout.connect(self.read_data)
		self.reading_timer.start(100)

	def record_reference_clicked(self):
		print("Record reference clicked")
		if self.reference_eeg_data.get_channel_data(0).shape[0] > 0:
			self.reference_eeg_data.clear()
		self.record_clicked(reference=True)

	def read_data(self):
		if not self.recording and not self.recording_reference:
			return

		recording_duration_in_samples = self.recording_progress_dialog.maximum()

		if self.recording_reference:
			if self.reference_eeg_data.get_channel_data(0).shape[0] > recording_duration_in_samples or\
					self.recording_progress_dialog.wasCanceled():
				self.stop_recording(True)
				return

		if self.recording:
			if self.recording_progress_dialog.wasCanceled() or\
					self.eeg_data_buffer.get_channel_data(0).shape[0] > recording_duration_in_samples:
				self.stop_recording(self.recording_reference)
				return

		if self.board.get_board_data_count() > 0:
			raw_data = self.board.get_board_data()
			raw_eeg_data = utils.extract_eeg_data(raw_data, global_config.BOARD_ID)

			self.eeg_sample_count += raw_eeg_data.shape[1]

			path = self.root_directory_label.text()

			if path != "":
				full_path = path + "/" + global_config.RESONANCE_DATA_FILE_NAME
				DataFilter.write_file(raw_eeg_data, full_path, "a")

			# c3 = raw_eeg_data[self.DEFAULT_C3_CHANNEL_INDEX, :]
			# cz = raw_eeg_data[self.DEFAULT_CZ_CHANNEL_INDEX, :]
			# c4 = raw_eeg_data[self.DEFAULT_C4_CHANNEL_INDEX, :]

			if self.recording_reference:
				self.reference_eeg_data.append_data(raw_eeg_data)
				print(f"reference size: {self.reference_eeg_data.sample_count()}")
				self.recording_progress_dialog.setValue(self.reference_eeg_data.get_channel_data(0).shape[0])
			else:
				self.eeg_data_buffer.append_data(raw_eeg_data)
				print(f"data size: {self.eeg_data_buffer.sample_count()}")
				self.recording_progress_dialog.setValue(self.eeg_data_buffer.get_channel_data(0).shape[0])

	def load_existing_data(self):
		path = QFileDialog.getExistingDirectory(self, "Root Directory...")

		if path == "":
			return

		filter_settings = utils.FilterSettings(global_config.SAMPLING_RATE, self.DEFAULT_BANDPASS_MIN, self.DEFAULT_BANDPASS_MAX)

		frequencies, eeg_data, reference_data = utils.load_slice_and_filter_resonance_data(path, filter_settings)

		print(frequencies)

		size = len(frequencies)

		x = np.arange(size)

		x_ticks = []

		plot_data = np.zeros((3, size))

		for i in range(size):
			current_eeg_data = eeg_data[i]
			freq = frequencies[i]
			x_ticks.append(f"{freq} Hz")
			freq_band = utils.FrequencyBand(
				freq - self.DEFAULT_FREQUENCY_PADDING,
				freq + self.DEFAULT_FREQUENCY_PADDING)

			reference_c3_extractor = reference_data.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_cz_extractor = reference_data.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_c4_extractor = reference_data.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c3_extractor = current_eeg_data.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_cz_extractor = current_eeg_data.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c4_extractor = current_eeg_data.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			c3_diff, cz_diff, c4_diff = self.amplitude_diff(freq_band, reference_c3_extractor, reference_cz_extractor,
															reference_c4_extractor, data_c3_extractor,
															data_cz_extractor, data_c4_extractor)

			plot_data[0, i] = c3_diff
			plot_data[1, i] = cz_diff
			plot_data[2, i] = c4_diff

		plt.figure()
		plt.title("Amplitude Increase")

		plt.bar(x, plot_data[0], width=0.25, label="C3 amplitude increase")
		plt.bar(x + 0.25, plot_data[1], width=0.25, label="Cz amplitude increase")
		plt.bar(x + 0.50, plot_data[2], width=0.25, label="C4 amplitude increase")

		plt.xticks(x + 0.25, x_ticks)
		plt.ylabel("Average Band Amplitude")

		plt.legend(loc="best")
		plt.show()

	def amplitude_diff(self, freq_band, ref_c3_extractor, ref_cz_extractor, ref_c4_extractor, data_c3_extractor, data_cz_extractor, data_c4_extractor):
		ref_c3_amplitude = ref_c3_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		ref_cz_amplitude = ref_cz_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		ref_c4_amplitude = ref_c4_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)

		data_c3_amplitude = data_c3_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		data_cz_amplitude = data_cz_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		data_c4_amplitude = data_c4_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)

		c3_diff = data_c3_amplitude - ref_c3_amplitude
		cz_diff = data_cz_amplitude - ref_cz_amplitude
		c4_diff = data_c4_amplitude - ref_c4_amplitude

		return c3_diff, cz_diff, c4_diff
		# return data_c3_amplitude, data_cz_amplitude, data_c4_amplitude

	def stop_recording(self, reference: bool = False):
		if self.reading_timer is not None:
			self.reading_timer.deleteLater()

		self.board.stop_stream()
		self.recording = False
		self.recording_reference = False
		self.recording_progress_dialog.setValue(self.recording_progress_dialog.maximum())

		recording_duration_in_samples = self.recording_progress_dialog.maximum()
		selected_freq = self.frequency_slider.value()

		if reference:
			sample_count = min(self.reference_eeg_data.get_channel_data(0).shape[0], recording_duration_in_samples)
			sample_count -= global_config.SAMPLING_RATE * self.DEFAULT_SAMPLE_PADDING
			self.index_generator.add_slice(0, self.eeg_sample_count - sample_count, self.eeg_sample_count)
		else:
			sample_count = min(self.eeg_data_buffer.get_channel_data(0).shape[0], recording_duration_in_samples)
			sample_count -= global_config.SAMPLING_RATE * self.DEFAULT_SAMPLE_PADDING
			self.index_generator.add_slice(selected_freq, self.eeg_sample_count - sample_count, self.eeg_sample_count)

		if self.root_directory_label.text() != "":
			self.index_generator.write_to_file(self.root_directory_label.text())

		QApplication.beep()

		start = self.DEFAULT_SAMPLE_PADDING * global_config.SAMPLING_RATE

		if reference:
			print(f"reference size: {self.reference_eeg_data.sample_count()}")
			self.record_btn.setEnabled(True)
			# self.record_reference_btn.setEnabled(False)
			self.reference_eeg_data.filter_all_channels(
				global_config.SAMPLING_RATE, self.DEFAULT_BANDPASS_MIN, self.DEFAULT_BANDPASS_MAX, True
			)
			self.reference_eeg_data = utils.EegData(self.reference_eeg_data.to_row_array()[:, start:])
			print("Reference data saved...")
		else:
			print("Stopping the recording...")

			print("Filtering data...")

			self.eeg_data_buffer.filter_all_channels(
				global_config.SAMPLING_RATE, self.DEFAULT_BANDPASS_MIN, self.DEFAULT_BANDPASS_MAX, subtract_average=True
			)

			self.eeg_data_buffer = utils.EegData(self.eeg_data_buffer.to_row_array()[:, start:])

			print(f"data size: {self.eeg_data_buffer.sample_count()}")

			reference_c3_extractor = self.reference_eeg_data.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_cz_extractor = self.reference_eeg_data.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_c4_extractor = self.reference_eeg_data.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c3_extractor = self.eeg_data_buffer.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_cz_extractor = self.eeg_data_buffer.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c4_extractor = self.eeg_data_buffer.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			for i in range(self.c3_amplitude_bar_set.count()):
				current_freq = int(self.frequencies[i].replace(" Hz", ""))
				if current_freq == selected_freq:
					freq_band = utils.FrequencyBand(
						current_freq - self.DEFAULT_FREQUENCY_PADDING,
						current_freq + self.DEFAULT_FREQUENCY_PADDING)

					c3_diff, cz_diff, c4_diff = self.amplitude_diff(freq_band, reference_c3_extractor,reference_cz_extractor, reference_c4_extractor,
																	data_c3_extractor, data_cz_extractor, data_c4_extractor)

					print(f"C3 diff = {c3_diff}")
					print(f"Cz diff = {cz_diff}")
					print(f"C4 diff = {c4_diff}")

					self.c3_amplitude_bar_set.replace(i, c3_diff)
					self.cz_amplitude_bar_set.replace(i, cz_diff)
					self.c4_amplitude_bar_set.replace(i, c4_diff)

			utils.auto_adjust_axis(self.amplitude_axis,
								[self.c3_amplitude_bar_set, self.cz_amplitude_bar_set, self.c4_amplitude_bar_set], self.DEFAULT_GRAPH_PADDING)

	def auto_adjust_axis(self):
		# Adjust the range so that everything is visible and add some gaps

		c3_min = sys.maxsize
		cz_min = sys.maxsize
		c4_min = sys.maxsize

		c3_max = -sys.maxsize
		cz_max = -sys.maxsize
		c4_max = -sys.maxsize

		for i in range(self.c3_amplitude_bar_set.count()):
			c3_min = min(c3_min, self.c3_amplitude_bar_set.at(i))
			cz_min = min(cz_min, self.cz_amplitude_bar_set.at(i))
			c4_min = min(c4_min, self.c4_amplitude_bar_set.at(i))

			c3_max = max(c3_max, self.c3_amplitude_bar_set.at(i))
			cz_max = max(cz_max, self.cz_amplitude_bar_set.at(i))
			c4_max = max(c4_max, self.c4_amplitude_bar_set.at(i))

		print("c3 min = {}, cz min = {}, c4 min = {}".format(c3_min, cz_min, c4_min))
		print("c3 max = {}, cz max = {}, c4 max = {}".format(c3_max, cz_max, c4_max))

		axis_min = min(0, c3_min, cz_min, c4_min) - self.DEFAULT_GRAPH_PADDING
		axis_max = max(0, c3_max, cz_max, c4_max) + self.DEFAULT_GRAPH_PADDING

		print("axis min = {}, axis max = {}".format(axis_min, axis_max))

		self.amplitude_axis.setMin(axis_min)
		self.amplitude_axis.setMax(axis_max)
Пример #19
0
class DebugWindow(QMainWindow):
    """
    The debug window shows various statistics about Tribler such as performed requests, IPv8 statistics and
    community information.
    """
    resize_event = pyqtSignal()

    def __init__(self, settings, tribler_version):
        self._logger = logging.getLogger(self.__class__.__name__)
        QMainWindow.__init__(self)

        self.request_mgr = None
        self.cpu_plot = None
        self.memory_plot = None
        self.initialized_cpu_plot = False
        self.initialized_memory_plot = False
        self.cpu_plot_timer = None
        self.memory_plot_timer = None
        self.tribler_version = tribler_version
        self.profiler_enabled = False
        self.toggling_profiler = False

        uic.loadUi(get_ui_file_path('debugwindow.ui'), self)
        self.setWindowTitle("Tribler debug pane")

        self.window().dump_memory_core_button.clicked.connect(lambda: self.on_memory_dump_button_clicked(True))
        self.window().dump_memory_gui_button.clicked.connect(lambda: self.on_memory_dump_button_clicked(False))
        self.window().toggle_profiler_button.clicked.connect(self.on_toggle_profiler_button_clicked)

        self.window().debug_tab_widget.setCurrentIndex(0)
        self.window().ipv8_tab_widget.setCurrentIndex(0)
        self.window().tunnel_tab_widget.setCurrentIndex(0)
        self.window().system_tab_widget.setCurrentIndex(0)
        self.window().debug_tab_widget.currentChanged.connect(self.tab_changed)
        self.window().ipv8_tab_widget.currentChanged.connect(self.ipv8_tab_changed)
        self.window().tunnel_tab_widget.currentChanged.connect(self.tunnel_tab_changed)
        self.window().events_tree_widget.itemClicked.connect(self.on_event_clicked)
        self.window().system_tab_widget.currentChanged.connect(self.system_tab_changed)
        self.load_general_tab()

        self.window().open_files_tree_widget.header().setSectionResizeMode(0, QHeaderView.Stretch)

        # Enable/disable tabs, based on settings
        self.window().debug_tab_widget.setTabEnabled(2, settings and settings['trustchain']['enabled'])
        self.window().debug_tab_widget.setTabEnabled(3, settings and settings['ipv8']['enabled'])
        self.window().system_tab_widget.setTabEnabled(3, settings and settings['resource_monitor']['enabled'])
        self.window().system_tab_widget.setTabEnabled(4, settings and settings['resource_monitor']['enabled'])

        # Refresh logs
        self.window().log_refresh_button.clicked.connect(lambda: self.load_logs_tab())
        self.window().log_tab_widget.currentChanged.connect(lambda index: self.load_logs_tab())

        # IPv8 statistics enabled?
        self.ipv8_statistics_enabled = settings['ipv8']['statistics']

        # Libtorrent tab
        self.init_libtorrent_tab()

        # Position to center
        frame_geometry = self.frameGeometry()
        screen = QDesktopWidget().screenNumber(QDesktopWidget().cursor().pos())
        center_point = QDesktopWidget().screenGeometry(screen).center()
        frame_geometry.moveCenter(center_point)
        self.move(frame_geometry.topLeft())

        # Refresh timer
        self.refresh_timer = None

    def hideEvent(self, hide_event):
        self.stop_timer()

    def run_with_timer(self, call_fn, timeout=DEBUG_PANE_REFRESH_TIMEOUT):
        call_fn()
        self.stop_timer()
        self.refresh_timer = QTimer()
        self.refresh_timer.setSingleShot(True)
        self.refresh_timer.timeout.connect(lambda _call_fn=call_fn, _timeout=timeout:
                                           self.run_with_timer(_call_fn, timeout=_timeout))
        self.refresh_timer.start(timeout)

    def stop_timer(self):
        if self.refresh_timer:
            try:
                self.refresh_timer.stop()
                self.refresh_timer.deleteLater()
            except RuntimeError:
                self._logger.error("Failed to stop refresh timer in Debug pane")

    def init_libtorrent_tab(self):
        self.window().libtorrent_tab_widget.setCurrentIndex(0)
        self.window().libtorrent_tab_widget.currentChanged.connect(lambda _: self.load_libtorrent_data(export=False))

        self.window().lt_zero_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_one_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_two_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_three_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_export_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=True))

        self.window().lt_zero_hop_btn.setChecked(True)

    def tab_changed(self, index):
        if index == 0:
            self.load_general_tab()
        elif index == 1:
            self.load_requests_tab()
        elif index == 2:
            self.run_with_timer(self.load_trustchain_tab)
        elif index == 3:
            self.ipv8_tab_changed(self.window().ipv8_tab_widget.currentIndex())
        elif index == 4:
            self.tunnel_tab_changed(self.window().tunnel_tab_widget.currentIndex())
        elif index == 5:
            self.run_with_timer(self.load_dht_tab)
        elif index == 6:
            self.run_with_timer(self.load_events_tab)
        elif index == 7:
            self.system_tab_changed(self.window().system_tab_widget.currentIndex())
        elif index == 8:
            self.load_libtorrent_data()
        elif index == 9:
            self.load_logs_tab()

    def ipv8_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_ipv8_general_tab)
        elif index == 1:
            self.run_with_timer(self.load_ipv8_communities_tab)
        elif index == 2:
            self.run_with_timer(self.load_ipv8_community_details_tab)

    def tunnel_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_tunnel_circuits_tab)
        elif index == 1:
            self.run_with_timer(self.load_tunnel_relays_tab)
        elif index == 2:
            self.run_with_timer(self.load_tunnel_exits_tab)

    def system_tab_changed(self, index):
        if index == 0:
            self.load_open_files_tab()
        elif index == 1:
            self.load_open_sockets_tab()
        elif index == 2:
            self.load_threads_tab()
        elif index == 3:
            self.load_cpu_tab()
        elif index == 4:
            self.load_memory_tab()
        elif index == 5:
            self.load_profiler_tab()

    def create_and_add_widget_item(self, key, value, widget):
        item = QTreeWidgetItem(widget)
        item.setText(0, key)
        item.setText(1, "%s" % value)
        widget.addTopLevelItem(item)

    def load_general_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("statistics/tribler", self.on_tribler_statistics)

    def on_tribler_statistics(self, data):
        if not data:
            return
        data = data["tribler_statistics"]
        self.window().general_tree_widget.clear()
        self.create_and_add_widget_item("Tribler version", self.tribler_version, self.window().general_tree_widget)
        self.create_and_add_widget_item("Number of channels", data["num_channels"], self.window().general_tree_widget)
        self.create_and_add_widget_item("Database size", format_size(data["db_size"]),
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("Number of known torrents", data["num_torrents"],
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("", "", self.window().general_tree_widget)

        disk_usage = psutil.disk_usage('/')
        self.create_and_add_widget_item("Total disk space", format_size(disk_usage.total),
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("Used disk space", format_size(disk_usage.used),
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("Free disk space", format_size(disk_usage.free),
                                        self.window().general_tree_widget)

    def load_requests_tab(self):
        self.window().requests_tree_widget.clear()
        for endpoint, method, data, timestamp, status_code in sorted(tribler_performed_requests,
                                                                     key=lambda x: x[3]):
            item = QTreeWidgetItem(self.window().requests_tree_widget)
            item.setText(0, "%s %s %s" % (method, endpoint, data))
            item.setText(1, ("%d" % status_code) if status_code else "unknown")
            item.setText(2, "%s" % strftime("%H:%M:%S", localtime(timestamp)))
            self.window().requests_tree_widget.addTopLevelItem(item)

    def load_trustchain_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("trustchain/statistics", self.on_trustchain_statistics)

    def on_trustchain_statistics(self, data):
        if not data:
            return
        self.window().trustchain_tree_widget.clear()
        for key, value in data["statistics"].items():
            self.create_and_add_widget_item(key, value, self.window().trustchain_tree_widget)

    def load_ipv8_general_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("statistics/ipv8", self.on_ipv8_general_stats)

    def on_ipv8_general_stats(self, data):
        if not data:
            return
        self.window().ipv8_general_tree_widget.clear()
        for key, value in data["ipv8_statistics"].items():
            if key in ('total_up', 'total_down'):
                value = "%.2f MB" % (value / (1024.0 * 1024.0))
            elif key == 'session_uptime':
                value = "%s" % str(datetime.timedelta(seconds=int(value)))
            self.create_and_add_widget_item(key, value, self.window().ipv8_general_tree_widget)

    def load_ipv8_communities_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("ipv8/overlays", self.on_ipv8_community_stats)

    def _colored_peer_count(self, peer_count, overlay_count, master_peer):
        is_discovery = (master_peer == "3081a7301006072a8648ce3d020106052b81040027038192000403b3ab059ced9b20646ab5e01"
                                       "762b3595c5e8855227ae1e424cff38a1e4edee73734ff2e2e829eb4f39bab20d7578284fcba72"
                                       "51acd74e7daf96f21d01ea17077faf4d27a655837d072baeb671287a88554e1191d8904b0dc57"
                                       "2d09ff95f10ff092c8a5e2a01cd500624376aec875a6e3028aab784cfaf0bac6527245db8d939"
                                       "00d904ac2a922a02716ccef5a22f7968")
        limits = [20, overlay_count * 30 + 1] if is_discovery else [20, 31]
        color = 0xF4D03F if peer_count < limits[0] else (0x56F129 if peer_count < limits[1] else 0xF12929)
        return QBrush(QColor(color))

    def on_ipv8_community_stats(self, data):
        if not data:
            return
        self.window().communities_tree_widget.clear()
        for overlay in data["overlays"]:
            item = QTreeWidgetItem(self.window().communities_tree_widget)
            item.setText(0, overlay["overlay_name"])
            item.setText(1, overlay["master_peer"][-12:])
            item.setText(2, overlay["my_peer"][-12:])
            peer_count = len(overlay["peers"])
            item.setText(3, "%s" % peer_count)
            item.setForeground(3, self._colored_peer_count(peer_count, len(data["overlays"]),
                                                           overlay["master_peer"]))

            if "statistics" in overlay and overlay["statistics"]:
                statistics = overlay["statistics"]
                item.setText(4, "%.3f" % (statistics["bytes_up"]/(1024.0 * 1024.0)))
                item.setText(5, "%.3f" % (statistics["bytes_down"]/(1024.0 * 1024.0)))
                item.setText(6, "%s" % statistics["num_up"])
                item.setText(7, "%s" % statistics["num_down"])
                item.setText(8, "%.3f" % statistics["diff_time"])
            else:
                item.setText(4, "N/A")
                item.setText(5, "N/A")
                item.setText(6, "N/A")
                item.setText(7, "N/A")
                item.setText(8, "N/A")

            self.window().communities_tree_widget.addTopLevelItem(item)
            map(self.window().communities_tree_widget.resizeColumnToContents, xrange(10))

    def load_ipv8_community_details_tab(self):
        if self.ipv8_statistics_enabled:
            self.window().ipv8_statistics_error_label.setHidden(True)
            self.request_mgr = TriblerRequestManager()
            self.request_mgr.perform_request("ipv8/overlays/statistics", self.on_ipv8_community_detail_stats)
        else:
            self.window().ipv8_statistics_error_label.setHidden(False)
            self.window().ipv8_communities_details_widget.setHidden(True)

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

        self.window().ipv8_communities_details_widget.setHidden(False)
        self.window().ipv8_communities_details_widget.clear()
        for overlay in data["statistics"]:
            self.window().ipv8_communities_details_widget.setColumnWidth(0, 250)

            for key, stats in overlay.items():
                header_item = QTreeWidgetItem(self.window().ipv8_communities_details_widget)
                header_item.setFirstColumnSpanned(True)
                header_item.setBackground(0, QtGui.QColor('#CCCCCC'))
                header_item.setText(0, key)
                self.window().ipv8_communities_details_widget.addTopLevelItem(header_item)

                for request_id, stat in stats.items():
                    stat_item = QTreeWidgetItem(self.window().ipv8_communities_details_widget)
                    stat_item.setText(0, request_id)
                    stat_item.setText(1, "%.3f" % (stat["bytes_up"] / (1024.0 * 1024.0)))
                    stat_item.setText(2, "%.3f" % (stat["bytes_down"] / (1024.0 * 1024.0)))
                    stat_item.setText(3, "%s" % stat["num_up"])
                    stat_item.setText(4, "%s" % stat["num_down"])
                    self.window().ipv8_communities_details_widget.addTopLevelItem(stat_item)

    def add_items_to_tree(self, tree, items, keys):
        tree.clear()
        for item in items:
            widget_item = QTreeWidgetItem(tree)
            for index, key in enumerate(keys):
                value = format_size(item[key]) if key in ["bytes_up", "bytes_down"] else str(item[key])
                widget_item.setText(index, value)
            tree.addTopLevelItem(widget_item)

    def load_tunnel_circuits_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("ipv8/tunnel/circuits", self.on_tunnel_circuits)

    def on_tunnel_circuits(self, data):
        if data:
            self.add_items_to_tree(self.window().circuits_tree_widget, data.get("circuits"),
                                   ["circuit_id", "goal_hops", "actual_hops", "unverified_hop",
                                    "type", "state", "bytes_up", "bytes_down"])

    def load_tunnel_relays_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("ipv8/tunnel/relays", self.on_tunnel_relays)

    def on_tunnel_relays(self, data):
        if data:
            self.add_items_to_tree(self.window().relays_tree_widget, data["relays"],
                                   ["circuit_from", "circuit_to", "is_rendezvous", "bytes_up", "bytes_down"])

    def load_tunnel_exits_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("ipv8/tunnel/exits", self.on_tunnel_exits)

    def on_tunnel_exits(self, data):
        if data:
            self.add_items_to_tree(self.window().exits_tree_widget, data["exits"],
                                   ["circuit_from", "enabled", "bytes_up", "bytes_down"])

    def load_dht_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("ipv8/dht/statistics", self.on_dht_statistics)

    def on_dht_statistics(self, data):
        if not data:
            return
        self.window().dht_tree_widget.clear()
        for key, value in data["statistics"].items():
            self.create_and_add_widget_item(key, value, self.window().dht_tree_widget)

    def on_event_clicked(self, item):
        event_dict = item.data(0, Qt.UserRole)
        self.window().event_text_box.setPlainText(json.dumps(event_dict))

    def load_events_tab(self):
        self.window().events_tree_widget.clear()
        for event_dict, timestamp in tribler_received_events:
            item = QTreeWidgetItem(self.window().events_tree_widget)
            item.setData(0, Qt.UserRole, event_dict)
            item.setText(0, "%s" % event_dict['type'])
            item.setText(1, "%s" % strftime("%H:%M:%S", localtime(timestamp)))
            self.window().events_tree_widget.addTopLevelItem(item)

    def load_open_files_tab(self):
        # Fill the open files (GUI) tree widget
        my_process = psutil.Process()
        self.window().open_files_tree_widget.clear()
        gui_item = QTreeWidgetItem(self.window().open_files_tree_widget)

        try:
            open_files = my_process.open_files()
            gui_item.setText(0, "GUI (%d)" % len(open_files))
            self.window().open_files_tree_widget.addTopLevelItem(gui_item)

            for open_file in open_files:
                item = QTreeWidgetItem()
                item.setText(0, open_file.path)
                item.setText(1, "%d" % open_file.fd)
                gui_item.addChild(item)
        except psutil.AccessDenied as exc:
            gui_item.setText(0, "Unable to get open files for GUI (%s)" % exc)

        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("debug/open_files", self.on_core_open_files)

    def on_core_open_files(self, data):
        if not data:
            return
        core_item = QTreeWidgetItem(self.window().open_files_tree_widget)
        core_item.setText(0, "Core (%d)" % len(data["open_files"]))
        self.window().open_files_tree_widget.addTopLevelItem(core_item)

        for open_file in data["open_files"]:
            item = QTreeWidgetItem()
            item.setText(0, open_file["path"])
            item.setText(1, "%d" % open_file["fd"])
            core_item.addChild(item)

    def load_open_sockets_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("debug/open_sockets", self.on_core_open_sockets)

    def on_core_open_sockets(self, data):
        if not data:
            return
        self.window().open_sockets_tree_widget.clear()
        self.window().open_sockets_label.setText("Sockets opened by core (%d):" % len(data["open_sockets"]))
        for open_socket in data["open_sockets"]:
            if open_socket["family"] == socket.AF_INET:
                family = "AF_INET"
            elif open_socket["family"] == socket.AF_INET6:
                family = "AF_INET6"
            elif open_socket["family"] == socket.AF_UNIX:
                family = "AF_UNIX"
            else:
                family = "-"

            item = QTreeWidgetItem(self.window().open_sockets_tree_widget)
            item.setText(0, open_socket["laddr"])
            item.setText(1, open_socket["raddr"])
            item.setText(2, family)
            item.setText(3, "SOCK_STREAM" if open_socket["type"] == socket.SOCK_STREAM else "SOCK_DGRAM")
            item.setText(4, open_socket["status"])
            self.window().open_sockets_tree_widget.addTopLevelItem(item)

    def load_threads_tab(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("debug/threads", self.on_core_threads)

    def on_core_threads(self, data):
        if not data:
            return
        self.window().threads_tree_widget.clear()
        for thread_info in data["threads"]:
            thread_item = QTreeWidgetItem(self.window().threads_tree_widget)
            thread_item.setText(0, "%d" % thread_info["thread_id"])
            thread_item.setText(1, thread_info["thread_name"])
            self.window().threads_tree_widget.addTopLevelItem(thread_item)

            for frame in thread_info["frames"]:
                frame_item = QTreeWidgetItem()
                frame_item.setText(2, frame)
                thread_item.addChild(frame_item)

    def load_cpu_tab(self):
        if not self.initialized_cpu_plot:
            vlayout = self.window().cpu_plot_widget.layout()
            self.cpu_plot = CPUPlotMplCanvas(self.window().cpu_plot_widget, dpi=100)
            vlayout.addWidget(self.cpu_plot)
            self.initialized_cpu_plot = True

        self.refresh_cpu_plot()

        # Start timer
        self.cpu_plot_timer = QTimer()
        self.cpu_plot_timer.timeout.connect(self.load_cpu_tab)
        self.cpu_plot_timer.start(5000)

    def refresh_cpu_plot(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("debug/cpu/history", self.on_core_cpu_history)

    def on_core_cpu_history(self, data):
        if not data:
            return
        plot_data = [[], []]
        for cpu_info in data["cpu_history"]:
            if cpu_info["cpu"] == 0.0:
                continue  # Ignore the initial measurement, is always zero
            plot_data[0].append(datetime.datetime.fromtimestamp(cpu_info["time"]))
            plot_data[1].append(cpu_info["cpu"])

        if len(plot_data[0]) == 0:
            plot_data = [[datetime.datetime.now()], [0]]

        self.cpu_plot.plot_data = plot_data
        self.cpu_plot.compute_initial_figure()

    def load_memory_tab(self):
        if not self.initialized_memory_plot:
            vlayout = self.window().memory_plot_widget.layout()
            self.memory_plot = MemoryPlotMplCanvas(self.window().memory_plot_widget, dpi=100)
            vlayout.addWidget(self.memory_plot)
            self.initialized_memory_plot = True

        self.refresh_memory_plot()

        # Start timer
        self.memory_plot_timer = QTimer()
        self.memory_plot_timer.timeout.connect(self.load_memory_tab)
        self.memory_plot_timer.start(5000)

    def load_profiler_tab(self):
        self.window().toggle_profiler_button.setEnabled(False)
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("debug/profiler", self.on_profiler_info)

    def on_profiler_info(self, data):
        if not data:
            return
        self.profiler_enabled = (data["state"] == "STARTED")
        self.window().toggle_profiler_button.setEnabled(True)
        self.window().toggle_profiler_button.setText("%s profiler" %
                                                     ("Stop" if self.profiler_enabled else "Start"))

    def on_toggle_profiler_button_clicked(self):
        if self.toggling_profiler:
            return

        self.toggling_profiler = True
        self.window().toggle_profiler_button.setEnabled(False)
        self.request_mgr = TriblerRequestManager()
        method = "DELETE" if self.profiler_enabled else "PUT"
        self.request_mgr.perform_request("debug/profiler", self.on_profiler_state_changed, method=method)

    def on_profiler_state_changed(self, data):
        if not data:
            return
        self.toggling_profiler = False
        self.window().toggle_profiler_button.setEnabled(True)
        self.load_profiler_tab()

        if 'profiler_file' in data:
            QMessageBox.about(self,
                              "Profiler statistics saved",
                              "The profiler data has been saved to %s." % data['profiler_file'])

    def refresh_memory_plot(self):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("debug/memory/history", self.on_core_memory_history)

    def on_core_memory_history(self, data):
        if not data:
            return
        plot_data = [[], []]
        for mem_info in data["memory_history"]:
            plot_data[0].append(datetime.datetime.fromtimestamp(mem_info["time"]))
            plot_data[1].append(mem_info["mem"] / 1024 / 1024)

        if len(plot_data[0]) == 0:
            plot_data = [[datetime.datetime.now()], [0]]

        self.memory_plot.plot_data = plot_data
        self.memory_plot.compute_initial_figure()

    def on_memory_dump_button_clicked(self, dump_core):
        self.export_dir = QFileDialog.getExistingDirectory(self, "Please select the destination directory", "",
                                                           QFileDialog.ShowDirsOnly)

        if len(self.export_dir) > 0:
            filename = "tribler_mem_dump_%s_%s.json" % \
                       ('core' if dump_core else 'gui', datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"))
            if dump_core:
                self.request_mgr = TriblerRequestManager()
                self.request_mgr.download_file("debug/memory/dump",
                                               lambda data: self.on_memory_dump_data_available(filename, data))
            elif scanner:
                scanner.dump_all_objects(os.path.join(self.export_dir, filename))
            else:
                ConfirmationDialog.show_error(self.window(),
                                              "Error when performing a memory dump",
                                              "meliae memory dumper is not compatible with Python 3")

    def on_memory_dump_data_available(self, filename, data):
        if not data:
            return
        dest_path = os.path.join(self.export_dir, filename)
        try:
            memory_dump_file = open(dest_path, "wb")
            memory_dump_file.write(data)
            memory_dump_file.close()
        except IOError as exc:
            ConfirmationDialog.show_error(self.window(),
                                          "Error when exporting file",
                                          "An error occurred when exporting the torrent file: %s" % str(exc))

    def closeEvent(self, close_event):
        self.request_mgr.cancel_request()
        if self.cpu_plot_timer:
            self.cpu_plot_timer.stop()

        if self.memory_plot_timer:
            self.memory_plot_timer.stop()

    def load_logs_tab(self):
        # Max lines from GUI
        max_log_lines = self.window().max_lines_value.text()

        tab_index = self.window().log_tab_widget.currentIndex()
        tab_name = "core" if tab_index == 0 else "gui"

        self.request_mgr = TriblerRequestManager()
        request_query = "process=%s&max_lines=%s" % (tab_name, max_log_lines)
        self.request_mgr.perform_request("debug/log?%s" % request_query, self.display_logs)

    def display_logs(self, data):
        if not data:
            return
        tab_index = self.window().log_tab_widget.currentIndex()
        log_display_widget = self.window().core_log_display_area if tab_index == 0 \
            else self.window().gui_log_display_area

        log_display_widget.moveCursor(QTextCursor.End)

        key_content = u'content'
        key_max_lines = u'max_lines'

        if not key_content in data or not data[key_content]:
            log_display_widget.setPlainText('No logs found')
        else:
            log_display_widget.setPlainText(data[key_content])

        if not key_max_lines in data or not data[key_max_lines]:
            self.window().max_lines_value.setText('')
        else:
            self.window().max_lines_value.setText(str(data[key_max_lines]))

        sb = log_display_widget.verticalScrollBar()
        sb.setValue(sb.maximum())

    def show(self):
        super(DebugWindow, self).show()

        # this will remove minimized status
        # and restore window with keeping maximized/normal state
        self.window().setWindowState(self.window().windowState() & ~Qt.WindowMinimized | Qt.WindowActive)
        self.window().activateWindow()

    def load_libtorrent_data(self, export=False):
        tab = self.window().libtorrent_tab_widget.currentIndex()
        hop = 0 if self.window().lt_zero_hop_btn.isChecked() \
            else 1 if self.window().lt_one_hop_btn.isChecked() \
            else 2 if self.window().lt_two_hop_btn.isChecked() \
            else 3
        if tab == 0:
            self.load_libtorrent_settings_tab(hop, export=export)
        elif tab == 1:
            self.load_libtorrent_sessions_tab(hop, export=export)

    def load_libtorrent_settings_tab(self, hop, export=False):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("libtorrent/settings?hop=%d" % hop,
                                         lambda data: self.on_libtorrent_settings_received(data, export=export))
        self.window().libtorrent_settings_tree_widget.clear()

    def on_libtorrent_settings_received(self, data, export=False):
        if not data:
            return
        for key, value in data["settings"].items():
            item = QTreeWidgetItem(self.window().libtorrent_settings_tree_widget)
            item.setText(0, key)
            item.setText(1, str(value))
            self.window().libtorrent_settings_tree_widget.addTopLevelItem(item)
        if export:
            self.save_to_file("libtorrent_settings.json", data)

    def load_libtorrent_sessions_tab(self, hop, export=False):
        self.request_mgr = TriblerRequestManager()
        self.request_mgr.perform_request("libtorrent/session?hop=%d" % hop,
                                         lambda data: self.on_libtorrent_session_received(data, export=export))
        self.window().libtorrent_session_tree_widget.clear()

    def on_libtorrent_session_received(self, data, export=False):
        if not data:
            return
        for key, value in data["session"].items():
            item = QTreeWidgetItem(self.window().libtorrent_session_tree_widget)
            item.setText(0, key)
            item.setText(1, str(value))
            self.window().libtorrent_session_tree_widget.addTopLevelItem(item)
        if export:
            self.save_to_file("libtorrent_session.json", data)

    def save_to_file(self, filename, data):
        base_dir = QFileDialog.getExistingDirectory(self, "Select an export directory", "", QFileDialog.ShowDirsOnly)
        if len(base_dir) > 0:
            dest_path = os.path.join(base_dir, filename)
            try:
                torrent_file = open(dest_path, "wb")
                torrent_file.write(json.dumps(data))
                torrent_file.close()
            except IOError as exc:
                ConfirmationDialog.show_error(self.window(), "Error exporting file", str(exc))
Пример #20
0
class OpencvWidget(QLabel):
    def __init__(self, *args, **kwargs):
        super(OpencvWidget, self).__init__(*args, **kwargs)
        self.httpRequestAborted = False
        self.fps = 24
        self.resize(800, 600)

        if not os.path.exists(
                "D:/access55/shape_predictor_68_face_landmarks.dat"):
            self.setText("正在下载数据文件。。。")
            self.outFile = QFile(
                "D:/access55/shape_predictor_68_face_landmarks.dat.bz2")
            if not self.outFile.open(QIODevice.WriteOnly):
                QMessageBox.critical(self, '错误', '无法写入文件')
                return
            self.qnam = QNetworkAccessManager(self)
            self._reply = self.qnam.get(QNetworkRequest(QUrl(URL)))
            self._reply.finished.connect(self.httpFinished)
            self._reply.readyRead.connect(self.httpReadyRead)
            self._reply.downloadProgress.connect(self.updateDataReadProgress)
        else:
            self.startCapture()

    def httpFinished(self):
        self.outFile.close()
        if self.httpRequestAborted or self._reply.error():
            self.outFile.remove()
        self._reply.deleteLater()
        del self._reply
        # 下载完成解压文件并加载摄像头
        self.setText("正在解压数据。。。")
        try:
            bz = BZ2Decompressor()
            data = bz.decompress(
                open('D:/access55/shape_predictor_68_face_landmarks.dat.bz2',
                     'rb').read())
            open('D:/access55/shape_predictor_68_face_landmarks.dat',
                 'wb').write(data)
        except Exception as e:
            self.setText('解压失败:' + str(e))
            return
        self.setText('正在开启摄像头。。。')
        self.startCapture()

    def httpReadyRead(self):
        self.outFile.write(self._reply.readAll())
        self.outFile.flush()

    def updateDataReadProgress(self, bytesRead, totalBytes):
        self.setText('已下载:{} %'.format(round(bytesRead / 64040097 * 100, 2)))

    def startCapture(self):
        self.setText("请稍候,正在初始化数据和摄像头。。。")
        try:
            # 检测相关
            self.detector = dlib.get_frontal_face_detector()
            self.predictor = dlib.shape_predictor(
                "D:/access55/shape_predictor_68_face_landmarks.dat")
            cascade_fn = "D:/access55/lbpcascades/lbpcascade_frontalface.xml"
            self.cascade = cv2.CascadeClassifier(cascade_fn)
            if not self.cascade:
                return QMessageBox.critical(self, "错误", cascade_fn + " 无法找到")
            self.cap = cv2.VideoCapture(0)
            if not self.cap or not self.cap.isOpened():
                return QMessageBox.critical(self, "错误", "打开摄像头失败")
            # 开启定时器定时捕获
            self.timer = QTimer(self, timeout=self.onCapture)
            self.timer.start(1000 / self.fps)
        except Exception as e:
            QMessageBox.critical(self, "错误", str(e))

    def closeEvent(self, event):
        if hasattr(self, "_reply") and self._reply:
            self.httpRequestAborted = True
            self._reply.abort()
            try:
                os.unlink(
                    "D:/access55/shape_predictor_68_face_landmarks.dat.bz2")
            except:
                pass
            try:
                os.unlink("D:/access55/shape_predictor_68_face_landmarks.dat")
            except:
                pass
        if hasattr(self, "timer"):
            self.timer.stop()
            self.timer.deleteLater()
            self.cap.release()
            del self.predictor, self.detector, self.cascade, self.cap
        super(OpencvWidget, self).closeEvent(event)
        self.deleteLater()

    def onCapture(self):
        _, frame = self.cap.read()

        minisize = (int(frame.shape[1] / DOWNSCALE),
                    int(frame.shape[0] / DOWNSCALE))
        tmpframe = cv2.resize(frame, minisize)
        tmpframe = cv2.cvtColor(tmpframe, cv2.COLOR_BGR2GRAY)  # 做灰度处理
        tmpframe = cv2.equalizeHist(tmpframe)

        # minNeighbors表示每一个目标至少要被检测到5次
        faces = self.cascade.detectMultiScale(tmpframe, minNeighbors=5)
        del tmpframe
        if len(faces) < 1:  # 没有检测到脸
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = QImage(frame.data, frame.shape[1], frame.shape[0],
                         frame.shape[1] * 3, QImage.Format_RGB888)
            del frame
            return self.setPixmap(QPixmap.fromImage(img))
        # 特征点检测描绘
        for x, y, w, h in faces:
            x, y, w, h = x * DOWNSCALE, y * DOWNSCALE, w * DOWNSCALE, h * DOWNSCALE
            # 画脸矩形
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0))
            # 截取的人脸部分
            tmpframe = frame[y:y + h, x:x + w]
            # 进行特征点描绘
            rects = self.detector(tmpframe, 1)
            if len(rects) > 0:
                landmarks = numpy.matrix(
                    [[p.x, p.y]
                     for p in self.predictor(tmpframe, rects[0]).parts()])
                for _, point in enumerate(landmarks):
                    pos = (point[0, 0] + x, point[0, 1] + y)
                    # 在原来画面上画点
                    cv2.circle(frame, pos, 3, color=(0, 255, 0))
            # 转成Qt能显示的
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = QImage(frame.data, frame.shape[1], frame.shape[0],
                         frame.shape[1] * 3, QImage.Format_RGB888)
            del frame
            self.setPixmap(QPixmap.fromImage(img))
Пример #21
0
class MainWindow(QtWidgets.QMainWindow, gui_main.Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # Animation
        self.animation = QPropertyAnimation(self, b'windowOpacity')
        self.animation.setDuration(800)
        self.doShow()
        # ProgressBar
        self.progressBar.setValue(0)
        self.progressBar.setTextVisible(False)
        # Buttons
        self.to_page_action.clicked.connect(self.action)
        self.to_page_setting.clicked.connect(self.setting)
        self.to_page_home.clicked.connect(self.home)
        self.to_page_graph.clicked.connect(self.Graph)
        self.setTable.clicked.connect(self.set_to_table)
        self.setGraph.clicked.connect(self.set_to_graph)
        self.export_to_xls_.clicked.connect(self.resetBar)
        # SET
        self.from_data.setDateTime(one_day)
        self.to_date.setDateTime(now)
        self.MCCMNC.setText("*")
        self.ANI.setText("*")
        self.Client.addItem(None)
        self.Vendor.addItem(None)
        # Combo_box
        for i in client:
            self.Client.addItem(i[1])
        for s in vendor:
            self.Vendor.addItem(s[1])

        self.threadpool = QThreadPool()


    def set_to_table(self):
        worker = Worker(self.UserData)
        worker.signals.result.connect(self.run_to_table)
        #worker.signals.finished.connect(self.thread_complete)
        #worker.signals.progress.connect(self.progress_fn)
        self.threadpool.start(worker)

    def set_to_graph(self):
        worker = Worker(self.UserData)
        self.doAction()
        worker.signals.result.connect(self.WebGraph)
        worker.signals.finished.connect(self.resetBar)
        self.threadpool.start(worker)

    def flow(self):
        print('Start')
        worker = Worker(self.UserData)
        self.threadpool.start(worker)

    def doAction(self):
        self.progressBar.setValue(0)
        self.progressBar.setMaximum(0)
        self.progressBar.setMinimum(0)
        if self.progressBar.minimum() != self.progressBar.maximum():
            self.timer = QTimer(self, timeout=self.onTimeout)
            self.timer.start(randint(1, 3) * 1000)

    def resetBar(self):
        self.step = 0
        self.progressBar.setValue(0)
        self.timer.stop()

    def onTimeout(self):
        if self.progressBar.value() >= 100:
            self.timer.stop()
            self.timer.deleteLater()
            del self.timer
            return
        self.progressBar.setValue(self.progressBar.value() + 1)

    def UserData(self):
        fr = self.from_data.dateTime()
        star = fr.toPyDateTime()
        to = self.to_date.dateTime()
        en = to.toPyDateTime()
        mnc = self.MCCMNC.text()
        ani = self.ANI.text()
        cli = self.Client.currentText()
        vnd = self.Vendor.currentText()
        conn = cx_Oracle.connect(setting.connet)
        cursor = conn.cursor()
        cursor.execute(setting.url, src=cli, dst=vnd, st=star, en=en, mnc=mnc, ani=ani)
        result = cursor.fetchall()
        attempts = []
        for row in result:
            attempts.append(row)
        cursor.close()
        conn.close()
        print('OK')
        # print(attempts)
        return attempts

    def WebGraph(self, s):
        self.stackedWidget.setCurrentWidget(self.page_chart)
        attempts = s
        labels = ['Date', 'attempts', 'ok']
        df = pd.DataFrame.from_records(attempts, columns=labels)

        fig = go.Figure()
        fig.add_trace(go.Scatter(x=df['Date'], y=df['attempts'], name='Attempts'))
        fig.add_trace(go.Scatter(x=df['Date'], y=df['ok'], name='Delivrd OK'))
        fig.update_layout(legend_orientation="h", template="plotly_dark",
                          legend=dict(x=.5, xanchor="center"),
                          hovermode="x",
                          margin=dict(l=0, r=0, t=0, b=0))

        fig.update_traces(hoverinfo="all", hovertemplate=" %{x}<br>%{y}")
        raw_html = '<html><head><meta charset="utf-8" />'
        raw_html += '<script src="https://cdn.plot.ly/plotly-latest.min.js"></script></head>'
        raw_html += '<body>'
        raw_html += plotly.offline.plot(fig, include_plotlyjs=False, output_type='div',
                                        config=dict(displayModeBar=False))
        raw_html += '</body></html>'

        self.webGraph.setHtml(raw_html)

    def run_to_table(self, s):
        attempts = s
        self.TABLE.setRowCount(len(attempts))
        self.TABLE.setColumnCount(len(attempts[0]))
        for row_num, row in enumerate(attempts):
            for cell_num, cell_attem in enumerate(row):
                self.TABLE.setItem(row_num, cell_num, QTableWidgetItem(str(cell_attem)))

    def Graph(self):
        self.stackedWidget.setCurrentWidget(self.page_chart)

    def setting(self):
        self.stackedWidget.setCurrentWidget(self.page_setting)

    def action(self):
        self.stackedWidget.setCurrentWidget(self.page_action)

    def home(self):
        self.stackedWidget.setCurrentWidget(self.page_home)

    def doShow(self):
        try:
            self.animation.finished.disconnect(self.close)
        except:
            pass
        self.animation.stop()
        self.animation.setStartValue(0)
        self.animation.setEndValue(1)
        self.animation.start()

        self.show()
Пример #22
0
class ExampleApp(QWidget, Ui_MainWindow):
    
    global com_port_name, get_pos, motor_stop, move_abs, roll_right, roll_left
    global position_LEED, position_EXCH, position_PASS
            
    def __init__(self):
        
        super(self.__class__, self).__init__()
        self.setupUi(self)
        
        """ Start monitoring the current position and connect all signals"""

        self.update_thread = update_position()
        
        self.pushButton.clicked.connect(lambda: self.move_motor(self.lineEdit.text()))
        self.pushButton_1.clicked.connect(self.joystick_operation)
        self.pushButton_2.clicked.connect(self.stop_motor)
        self.pushButton_3.clicked.connect(lambda: self.shift_motor(1,self.lineEdit_3.text()))   # L shift
        self.pushButton_4.clicked.connect(lambda: self.shift_motor(-1,self.lineEdit_3.text()))  # R shift
        self.pushButton_5.clicked.connect(lambda: self.move_motor(self.lineEdit_4.text()))      # LEED
        self.pushButton_6.clicked.connect(lambda: self.move_motor(self.lineEdit_5.text()))      # EXCH
        self.pushButton_7.clicked.connect(lambda: self.move_motor(self.lineEdit_6.text()))      # PASS
        
        self.start()
        
        """ Show the LEED, EXCH and PASS positions """
        self.lineEdit_4.setText(str(position_LEED))
        self.lineEdit_5.setText(str(position_EXCH))
        self.lineEdit_6.setText(str(position_PASS))
        
    def start (self):
            
        self.update_thread.new_value_trigger.connect(self.update_position_label)
        
        self.timer_x = QTimer(self)
        self.timer_x.timeout.connect(self.update_thread.update_position)        
        self.timer_x.start(1000)
        
    def stop_motor(self):
        
        self.command = motor_stop                                            # construct command
        send_motor.send_command(com_port_name, self.command)                   # senf command
        
    def update_position_label (self, value):
        
        self.position_mm = value
        self.lineEdit_2.setText("{:1.1f}".format(self.position_mm))
            
    def roll_motor (self, value):
        
        if (float (value) >= 0):
            print ('rolling right ', value)
            self.command = roll_right+roll_speed.to_bytes(4, byteorder='big',signed=True)        
            send_motor.send_command(com_port_name, self.command)
        else:
            print ('rolling left ', value)
            self.command = roll_left+roll_speed.to_bytes(4, byteorder='big',signed=True)         
            send_motor.send_command(com_port_name, self.command)
            
    def move_motor (self, value):
        
        if (float (value) <= 265) & (float (value) >= 0):
            self.lineEdit.setText(value)
            self.value = convert (float(value), True)
            print ('moving to ', self.value)
            self.command = move_abs + (self.value).to_bytes(4, byteorder='big',signed=True)        
            send_motor.send_command(com_port_name, self.command)

    def shift_motor(self, flag, value):
        
        self.shift=float(value)
        if (self.shift <= 50) & (self.shift >= 0):
            if flag == -1:
                self.shift = (-1)*self.shift
            self.new_value = float(self.lineEdit_2.text())+self.shift
            self.lineEdit.setText(str(self.new_value))
            print (self.new_value)
            self.shift_steps = convert (self.new_value, True)
            print (self.shift_steps)
            self.command = move_abs + (self.shift_steps).to_bytes(4, byteorder='big',signed=True)
            send_motor.send_command(com_port_name, self.command)
    

    def joystick_operation(self):
        
        if self.pushButton_1.isChecked():
            self.pushButton_1.setText("Disable Joystick")
            self.joystick_monitor = joystick_control_class()
            self.joystick_monitor.joystick_trigger.connect (self.joystick_processing)
            
            self.joystick_monitor.start()
        else:
            print ("not checked")
            self.pushButton_1.setText("Enable Joystick")
            self.joystick_monitor.stop()
            
    def joystick_processing(self, parameter):
        
        self.joystick_command = parameter
        
        if self.joystick_command == 'stop':
            self.stop_motor()
        elif self.joystick_command == 'shift_left':
            self.shift_motor(1,self.lineEdit_3.text())
        elif self.joystick_command == 'shift_right':
            self.shift_motor(-1,self.lineEdit_3.text())
        elif self.joystick_command == 'LEED':
            self.move_motor(self.lineEdit_4.text())
        elif self.joystick_command == 'EXCH':
            self.move_motor(self.lineEdit_5.text())
        elif self.joystick_command == 'PASS':
            self.move_motor(self.lineEdit_6.text())
        elif self.joystick_command == 'move_right':
            self.roll_motor(1)
        elif self.joystick_command == 'move_left':
            self.roll_motor(-1)
            
    def __del__ (self):
        
        self.stop_motor()
        self.update_thread.quit()
        self.timer_x.stop()
        self.timer_x.deleteLater()
Пример #23
0
class GraphModule:
    """
    Класс, занимающийся работой с GraphWidget.
    """

    def __init__(self, window: QMainWindow, nodes=None, edges=None, **kwargs):
        """Конструктор класса

        :param window: Окно-родитель для GraphWidget
        :type window: QMainWindow
        :param nodes: Список вида {
            id: Id Вершины,
            args: Список аргументов для конструктора Node
        }
        :param edges: Список вида {
            id: Id Ребра,
            args: Список аргументов для конструктора Edge
        }
        :param kwargs: Аргументы для GraphWidget
        """
        self.window = window
        self.widget = GraphWidget(self.window, **kwargs)
        self.fa2 = ForceAtlas2(
            outboundAttractionDistribution=False,
            scalingRatio=100.0,
            verbose=False,
            gravity=10.0
        )

        self._nodes = {}  # Хранилище вершин
        self._edges = {}  # Хранилище связей
        self._texts = {}  # Хранилище текстов
        self.get_relation_text = lambda item: str(item)
        self.matrix = None
        self.positions = None

        self.gravity_timer = None  # Таймер для работы с гравитацией
        self.widget.item_right_clicked.connect(self._on_item_clicked)

    def add_text(self, id, pos_x, pos_y, parent_item=None, **kwargs):
        """Добавить текст

        :param id: Уникальный id текста
        :param pos_x: x-координата
        :param pos_y: y-координата
        :param parent_node: вершина-родитель
        :param **kwargs: Аргументы конструктора TextItem
        """
        text = TextItem(id=id, parent=parent_item, **kwargs)
        if parent_item:
            pos_x -= parent_item.x()
            pos_y -= parent_item.y()
        text.setPos(pos_x, pos_y)
        text.linkActivated.connect(self._on_text_link_clicked)
        self._texts[id] = text

    def add_node(self, id, pos_x, pos_y, **kwargs):
        """Добавить вершину

        :param id: Уникальный идентификатор вершины
        :param pos_x: x-координата вершины
        :param pos_y: y-координата вершины
        :param **kwargs: Аргументы конструктора Node
        """
        # assert id not in self._nodes
        if id in self._nodes:
            log.warning(f"{id} уже добавлена")
        node = Node(self.widget, id=id, **kwargs)
        node.setPos(pos_x, pos_y)
        self.widget.scene().addItem(node)
        self._nodes[id] = node

    def add_edge(self, id1, id2, ud=False, **kwargs):
        """Добавить ребро

        :param id1: source id
        :param id2: target id
        :param ud: не добавлять связь, если уже есть связь в другую сторону
        :param **kwargs: Аргументы конструктора Edge
        """
        assert (id1, id2) not in self._edges
        if ud and (id2, id1) in self._edges:
            return
        edge = Edge(self._nodes[id1], self._nodes[id2], self.widget, **kwargs)
        self._edges[(id1, id2)] = edge
        self.widget.scene().addItem(edge)

    def _on_text_link_clicked(self, link):
        if link[:11] == 'internal://':
            if re.search(r'close\?id=[0-9\-]+', link):
                id = link[re.search(r'id=[0-9\-]+', link).start()+3:]
                try:
                    self.widget.scene().removeItem(self._texts[id])
                except KeyError:
                    id = int(id)
                    self.widget.scene().removeItem(self._texts[id])
                del self._texts[id]

    def _on_item_clicked(self, item: QGraphicsItem):
        if isinstance(item, Node) and item.info \
                and item.id not in self._texts:
            self.add_text(item.id, item.x() + 15, item.y() + 15,
                          item, html_text=item.info)
        elif isinstance(item, Edge) and item.info \
                and item.id not in self._texts:
            x = (item.dest.x() - item.source.x()) / 2 + item.source.x()
            y = (item.dest.y() - item.source.y()) / 2 + item.source.y()
            self.add_text(item.id, x, y, parent_item=item.source,
                          html_text=self.get_relation_text(item.info))

    def clear(self):
        self._nodes.clear()
        self._edges.clear()
        self._texts.clear()
        self.matrix = None
        self.widget.scene().clear()

    @property
    def nodes(self):
        """Вернуть список вершин.
        Возможно (TODO), здесь будет реализовано скрытие вершин
        """
        return list(self._nodes.values())

    @property
    def edges(self):
        """Вернуть список ребер"""
        return list(self._edges.values())

    def calculate_matrix(self, weight=None):
        head = list(self._nodes.keys())
        self.head = head
        self.matrix = np.zeros(len(head)**2).reshape((len(head), len(head)))
        self.positions = [[0, 0] for _ in range(len(head))]
        for key, edge in self._edges.items():
            id1, id2 = key
            id1, id2 = head.index(id1), head.index(id2)
            self.matrix[id1][id2] = edge.weight if weight is None else weight
            self.matrix[id2][id1] = edge.weight if weight is None else weight
        for id_, node in self._nodes.items():
            self.positions[head.index(id_)] = [node.x(), node.y()]
        self.positions = np.array(self.positions)

    def save_graph(self):
        fig = Plotter.save_to_graph(self)
        Plotter.display(fig)

    def relayout_graph(self, name: str):
        """Расположить вершины графа по какому-то алгоритму.
        Алгоритмы:
            * circular - по кругу
            * kamada_kawai - Kamada-Kawai Algorithm
            * planar - без пересечений ребер
            * random - рандом
            * shell - пока то же, что circular
            * spring - Fruchterman-Reingold Algorithm
        :param name:
        :type name: str
        """
        def kamada_kawai(G):
            return nx.kamada_kawai_layout(G, weight=1)

        # def spectral(G):
        #    return nx.spectral_layout(G, scale=20)

        func_dict = {
            'circular': nx.circular_layout,
            'kamada_kawai': kamada_kawai,
            'planar': nx.planar_layout,
            'random': nx.random_layout,
            'shell': nx.shell_layout,  # TODO
            'spring': nx.spring_layout,
            # 'spectral': spectral
        }
        scale_dict = {
            'circular': 0.5,
            'random': 0.3
        }

        self.calculate_matrix()
        matrix = np.array(self.matrix)
        G = nx.from_numpy_matrix(matrix)  # Получить networkx-граф из матрицы
        try:
            pos = func_dict[name](G)
        except nx.exception.NetworkXException:
            self.box = QMessageBox.critical(self.widget,
                                            'Ошибка', 'Граф не планарен')
            return

        # Расчехлить позиции
        pos = np.array([pos[i] for i in range(len(pos))])

        # Масштабировать
        scale = SupremeSettings()['graphmodule_graph_scale']
        try:
            pos = nx.rescale_layout(pos, scale=scale * scale_dict[name])
        except KeyError:
            pos = nx.rescale_layout(pos, scale=scale)

        # Применить позиции
        for index, position in enumerate(pos):
            x, y = position
            node = self._nodes[self.head[index]]
            if node != self.widget.scene().mouseGrabberItem():
                node.setX(x)
                node.setY(y)
        self._adjust_scene()

    def _adjust_scene(self):
        """ Подровнять сцену под вершины """
        if len(self.nodes) == 0:
            self.widget.scene().setSceneRect(-200, -200, 400, 400)
        min_x, min_y, max_x, max_y = sys.maxsize, sys.maxsize, \
            -sys.maxsize, -sys.maxsize
        for node in self.nodes + list(self._texts.values()):
            min_x = min(node.x(), min_x)
            min_y = min(node.y(), min_y)
            max_x = max(node.x(), max_x)
            max_y = max(node.y(), max_y)
        margin = 30
        x, y = min_x, min_y
        w, h = max(max_x - min_x, 100), max(max_y - min_y, 100)
        self.widget.scene().setSceneRect(x-margin, y-margin,
                                         w+margin*2, h+margin*2)

    def start_gravity(self):
        """ Запустить расчёт взаимодействия вершин """
        if self.gravity_timer \
                or not SupremeSettings()['graphmodule_gravity_enabled']:
            return
        self.gravity_timer = QTimer(self.widget)
        self.gravity_timer.start(
            SupremeSettings()['graphmodule_timer_interval'])
        self.gravity_timer.timeout.connect(self._process_gravity)

    def stop_gravity(self):
        if self.gravity_timer:
            self.gravity_timer.stop()
            self.gravity_timer.deleteLater()
            self.gravity_timer = None

    def do_gravity_ticks(self, ticks):
        """Выполнить нужное количество тиков расчёта гравитации.
        Можно использовать для первоначальной стабилизации сцены.

        :param ticks: Количество тиков
        """
        self.stop_gravity()
        for _ in range(ticks):
            self._process_gravity()
        self.start_gravity()

    def _process_gravity(self, ticks=1):
        """ Один тик обработки взаимодействия вершин """
        self.calculate_matrix()
        if len(self.matrix) > 0:
            positions = self.fa2.forceatlas2(
                self.matrix, pos=self.positions, iterations=ticks)
            for index, position in enumerate(positions):
                x, y = position
                node = self._nodes[self.head[index]]
                if node != self.widget.scene().mouseGrabberItem():
                    node.setX(x)
                    node.setY(y)
            self.positions = np.array(positions)
        self._adjust_scene()
Пример #24
0
class OnlineClassifierGui(QMainWindow):
	"""
		A GUI for testing and training classifiers online.
		This class can be used alone, but is really meant to be the stage after training which
		is done by the Classifier Trainer class.
	"""

	INTERNAL_BUFFER_EXTRA_DURATION = 2

	INTERNAL_BUFFER_EXTRA_SIZE = INTERNAL_BUFFER_EXTRA_DURATION * global_config.SAMPLING_RATE

	CLASS_IMAGE_HEIGHT = 400

	MENTAL_TASK_DELAY = 5000

	EV3_MAC_ADDRESS = "00:16:53:4f:bd:54"

	ROBOT_CONTROL = False

	DEFAULT_ROBOT_SPEED = 10

	classifier: cls.SimpleClassifier

	def __init__(self, classifier: cls.SimpleClassifier, filter_settings: utils.FilterSettings,
				feature_extraction_info: utils.FeatureExtractionInfo,
				feature_types: [],
				trial_classes: [utils.TrialClass],
				parent=None,
				config: OnlineClassifierConfigurations = OnlineClassifierConfigurations()):
		super().__init__(parent)
		self.setWindowTitle("Online Classifier")
		self.setWindowModality(PyQt5.QtCore.Qt.ApplicationModal)

		# self.vibration_serial = serial.Serial(port=utils.vibration_port(), baudrate=115200, timeout=5000)
		# if not self.vibration_serial.isOpen():
		# 	print("Opening port")
		# 	self.vibration_serial.open()
		# else:
		# 	print("Port is already open")

		self.classifier = classifier
		self.filter_settings = filter_settings
		self.feature_extraction_info = feature_extraction_info
		self.feature_types = feature_types
		self.trial_classes = trial_classes
		self.config = config

		self.slice_generator = utils.SliceIndexGenerator(global_config.SAMPLING_RATE, trial_classes)
		self.sample_count = 0

		self.trial_count = 0
		self.correct_count = 0

		self.INTERNAL_BUFFER_EXTRA_SIZE = self.INTERNAL_BUFFER_EXTRA_DURATION * self.feature_extraction_info.sampling_rate

		self.data_buffer = np.array([])

		self.root_layout = QGridLayout()
		self.root_layout.setAlignment(PyQt5.QtCore.Qt.AlignTop)
		self.root_widget = QWidget()
		self.root_widget.setLayout(self.root_layout)
		self.setCentralWidget(self.root_widget)

		title = QLabel("<h1>Online Classifier</h1>")
		title.setAlignment(PyQt5.QtCore.Qt.AlignCenter)
		self.root_layout.addWidget(title, 0, 0, 1, 3)

		self.feature_window_edit = QLineEdit()
		self.feature_window_edit.setText(str(self.config.feature_window_size))

		self.repetition_interval_edit = QLineEdit()
		self.repetition_interval_edit.setText(str(self.config.repetition_interval))

		self.detection_threshold_edit = QLineEdit()
		self.detection_threshold_edit.setText(str(self.config.detection_threshold))

		self.online_training_checkbox = QCheckBox("Online Training")
		self.online_training = False

		self.robot_connect_btn = QPushButton("Connect to EV3")
		self.robot_connect_btn.clicked.connect(self.connect_clicked)

		self.manual_control_checkbox = QCheckBox("Manual Control")

		self.ev3 = ev3.EV3(self.EV3_MAC_ADDRESS)
		self.motor_control = ev3.MotorControl(1, 8, self.ev3)
		self.previous_direction = None

		self.previous_test_set_accuracy = 0.0
		self.previous_cross_validation_accuracy = 0.0

		self.root_layout.addWidget(utils.construct_horizontal_box([
			QLabel("Feature Window Size (sec): "), self.feature_window_edit,
			QLabel("Repetition Interval (sec): "), self.repetition_interval_edit,
			QLabel("Detection Threshold: "), self.detection_threshold_edit,
			self.online_training_checkbox,
			self.robot_connect_btn, self.manual_control_checkbox
		]), 1, 0, 1, 3)

		self.root_directory_label = QLabel()
		self.pick_root_directory_btn = QPushButton("Select/Change")
		self.pick_root_directory_btn.clicked.connect(self.pick_root_directory)

		self.root_layout.addWidget(utils.construct_horizontal_box([
			QLabel("Root directory:"), self.root_directory_label, self.pick_root_directory_btn
		]), 2, 0, 1, 3)

		self.start_btn = QPushButton("Start Streaming")
		self.start_btn.clicked.connect(self.start_clicked)
		self.stop_btn = QPushButton("Stop Streaming")
		self.stop_btn.clicked.connect(self.stop_clicked)

		self.root_layout.addWidget(utils.construct_horizontal_box([
			self.stop_btn, self.start_btn
		]), 3, 0, 1, 3)

		self.class_label = QLabel("Start stream to see result")
		self.class_label.setAlignment(PyQt5.QtCore.Qt.AlignCenter)

		self.root_layout.addWidget(self.class_label, 4, 0, 1, 3)

		self.root_layout.addWidget(utils.construct_horizontal_box([
			QLabel("<h2>Mental Tasks:</h2>")
		]), 5, 0, 1, 3)

		self.training_tasks_widget = QWidget()
		self.training_tasks_layout = QHBoxLayout()
		self.training_tasks_widget.setLayout(self.training_tasks_layout)

		self.class_tiles_list = []

		for trial_class in trial_classes:
			self.class_tiles_list.append(TrainingTaskTile(trial_class, self.CLASS_IMAGE_HEIGHT / 2))
			self.training_tasks_layout.addWidget(self.class_tiles_list[-1])

		self.root_layout.addWidget(self.training_tasks_widget, 6, 0, 1, 3)

		self.class_pixmap = QPixmap()

		self.log_textarea = QPlainTextEdit()

		self.root_layout.addWidget(self.log_textarea, 7, 0, 1, 3)

		self.board = self.initialize_board()
		self.board.prepare_session()

		self.reading_timer = None
		self.samples_push_count = 0
		self.online_training_samples_push_count = 0
		self.online_training_timer = None
		self.current_mental_task = None

		self.show()

	@staticmethod
	def initialize_board() -> BoardShim:
		params = BrainFlowInputParams()
		params.serial_port = utils.cyton_port()

		board = BoardShim(global_config.BOARD_ID, params)
		return board

	def initialize_data_buffer(self):
		self.data_buffer = np.zeros((
				self.feature_extraction_info.range_size(),
				int(self.INTERNAL_BUFFER_EXTRA_SIZE + self.config.feature_window_size * self.feature_extraction_info.sampling_rate)
		), dtype=float)

	def connect_clicked(self):
		self.ev3.connect()

	def pick_root_directory(self):
		path = QFileDialog.getExistingDirectory(self, "Select Root Directory...")
		self.root_directory_label.setText(path)

	def keyPressEvent(self, event: QtGui.QKeyEvent) -> None:
		print("key pressed")
		if self.manual_control_checkbox.isChecked():
			if event.key() == Qt.Key_A:
				self.motor_control.turn_left_from_middle(90, self.DEFAULT_ROBOT_SPEED)
			elif event.key() == Qt.Key_D:
				self.motor_control.turn_right_from_middle(90, self.DEFAULT_ROBOT_SPEED)
			elif event.key() == Qt.Key_W:
				self.motor_control.forward(self.DEFAULT_ROBOT_SPEED)
			elif event.key() == Qt.Key_S:
				self.motor_control.backward(self.DEFAULT_ROBOT_SPEED)

	def close(self) -> bool:
		if self.vibration_serial.isOpen():
			self.vibration_serial.close()
		return super().close()

	def start_clicked(self):

		if utils.is_float(self.feature_window_edit.text()):
			self.config.feature_window_size = float(self.feature_window_edit.text())

		if utils.is_float(self.repetition_interval_edit.text()):
			self.config.repetition_interval = float(self.repetition_interval_edit.text())

		if utils.is_float(self.detection_threshold_edit.text()):
			self.config.detection_threshold = float(self.detection_threshold_edit.text())

		self.online_training = self.online_training_checkbox.isChecked()

		self.log(f"Starting data stream, online training? {self.online_training}")

		if self.online_training:
			self.online_training_timer = QTimer()
			self.online_training_timer.singleShot(self.MENTAL_TASK_DELAY, self.next_mental_task)

		self.initialize_data_buffer()

		self.samples_push_count = 0
		self.online_training_samples_push_count = 0

		if self.reading_timer is None:
			print("Starting data stream...")
			self.board.start_stream()
			self.reading_timer = QTimer()
			self.reading_timer.timeout.connect(self.read_data)
			# TODO: Replace with a config variable
			self.reading_timer.start(100)

	def stop_clicked(self):
		if self.reading_timer is not None:
			self.log("Stopping stream...")
			print("Stopping...")
			self.board.stop_stream()
			self.reading_timer.deleteLater()
			self.reading_timer = None
			self.slice_generator.write_to_file(self.root_directory_label.text())
			if self.online_training:
				if self.online_training_timer is not None:
					self.online_training_timer.deleteLater()
					self.online_training_timer = None
					self.clear_highlight_tile()

				self.log(f"Accuracy during online training: {self.correct_count / self.trial_count * 100}%")
				print(f"Accuracy during online training: {self.correct_count / self.trial_count * 100}%")

	def read_data(self):
		if self.board.get_board_data_count() > 0:
			raw_data = self.board.get_board_data()
			raw_eeg_data = utils.extract_eeg_data(raw_data, global_config.BOARD_ID)

			if self.root_directory_label.text() != "":
				full_path = self.root_directory_label.text() + "/" + global_config.EEG_DATA_FILE_NAME
				DataFilter.write_file(raw_eeg_data, full_path, "a")
				self.slice_generator.write_to_file(self.root_directory_label.text())

			# Make room for new samples, discard the oldest
			self.data_buffer = np.roll(self.data_buffer, shift=-raw_eeg_data.shape[1], axis=1)

			# Insert new samples
			first_index = self.feature_extraction_info.first_electrode() - 1
			last_index = self.feature_extraction_info.last_electrode()  # Not including
			self.data_buffer[:, self.data_buffer.shape[1] - raw_eeg_data.shape[1]:] = raw_eeg_data[first_index:last_index, :]

			self.samples_push_count += raw_eeg_data.shape[1]
			self.sample_count += raw_eeg_data.shape[1]
			if self.online_training and self.online_training_timer is None:
				self.online_training_samples_push_count += raw_eeg_data.shape[1]

			if self.samples_push_count >= self.config.repetition_interval * self.feature_extraction_info.sampling_rate:
				self.classify_data()
				self.samples_push_count = 0

			if self.online_training_samples_push_count >= self.config.feature_window_size * self.feature_extraction_info.sampling_rate:
				self.classify_data(online_training=True)
				self.online_training_samples_push_count = 0
				self.online_training_timer = QTimer()
				self.online_training_timer.singleShot(self.MENTAL_TASK_DELAY, self.next_mental_task)
				self.clear_highlight_tile()

	def clear_highlight_tile(self):
		for tile in self.class_tiles_list:
			if tile.highlighted:
				tile.disable_highlight()
				break

	def classify_data(self, online_training: bool = False):
		filtered_data = self.filter_settings.apply(self.data_buffer[:, self.INTERNAL_BUFFER_EXTRA_SIZE:])

		feature_vector = \
			utils.extract_features([utils.EegData(filtered_data)], self.feature_extraction_info, self.feature_types)[0]

		feature_data = feature_vector.data

		print("Feature Vector extracted successfully...")

		label = self.classifier.classify(feature_data)

		while type(label) == np.ndarray:
			label = label[0]

		print(f"label = {label}")

		direction = None

		if online_training:
			correct_label = self.current_mental_task.label

			self.trial_count += 1

			if label != correct_label:
				self.log("Wrong classification!")
			else:
				self.log("Correct Classification")
				self.correct_count += 1

			# self.classifier.get_data_set().append_to(feature_data, np.array([correct_label]), data.DataSubSetType.TRAINING)
			# TODO: Might block execution for too long
			# self.classifier.train()
			# self.log("Training accuracy: " + self.classifier.training_set_accuracy())

		path = ""
		for trial_class in self.trial_classes:
			if trial_class.label == label:
				path = trial_class.get_image_path()
				direction = trial_class.direction
				break
		self.class_pixmap = QPixmap(path).scaledToHeight(self.CLASS_IMAGE_HEIGHT, Qt.FastTransformation)
		self.class_label.setPixmap(self.class_pixmap)

		if self.ROBOT_CONTROL:
			if direction == utils.Direction.LEFT:
				self.motor_control.turn_left_from_middle(90, self.DEFAULT_ROBOT_SPEED)
				print("left")
			elif direction == utils.Direction.RIGHT:
				self.motor_control.turn_right_from_middle(90, self.DEFAULT_ROBOT_SPEED)
				print("right")
			elif direction == utils.Direction.FORWARD:
				self.motor_control.forward(self.DEFAULT_ROBOT_SPEED)
				print("forward")
			elif direction == utils.Direction.BACKWARD:
				self.motor_control.backward(self.DEFAULT_ROBOT_SPEED)
				print("backward")

	def next_mental_task(self):
		self.current_mental_task = self.random_class()
		print(f"Next mental task is {self.current_mental_task.name}")

		self.slice_generator.add_slice(self.current_mental_task.label,
				self.sample_count, self.sample_count + int(self.config.feature_window_size * self.feature_extraction_info.sampling_rate))

		for tile in self.class_tiles_list:
			if tile.trial_class == self.current_mental_task:
				tile.highlight()
			else:
				tile.disable_highlight()

		if self.online_training_timer is not None:
			self.online_training_timer.deleteLater()
			self.online_training_timer = None

	def random_class(self) -> utils.TrialClass:
		index = random.randint(0, len(self.trial_classes) - 1)
		return self.trial_classes[index]

	def log(self, text: str):
		self.log_textarea.insertPlainText(f"{text}\n")

	def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
		self.board.release_session()
Пример #25
0
class OpencvWidget(QLabel):

    def __init__(self, *args, **kwargs):
        super(OpencvWidget, self).__init__(*args, **kwargs)
        self.fps = 24
        self.resize(800, 600)
        self.setText("请稍候,正在初始化数据和摄像头。。。")

    def start(self):
        try:
            # 检测相关
            self.detector = dlib.get_frontal_face_detector()
            self.predictor = dlib.shape_predictor(
                "data/shape_predictor_68_face_landmarks.dat")
            cascade_fn = "data/lbpcascades/lbpcascade_frontalface.xml"
            self.cascade = cv2.CascadeClassifier(cascade_fn)
            if not self.cascade:
                return QMessageBox.critical(self, "错误", cascade_fn + " 无法找到")
            self.cap = cv2.VideoCapture(0)
            if not self.cap or not self.cap.isOpened():
                return QMessageBox.critical(self, "错误", "打开摄像头失败")
            # 开启定时器定时捕获
            self.timer = QTimer(self, timeout=self.onCapture)
            self.timer.start(1000 / self.fps)
        except Exception as e:
            QMessageBox.critical(self, "错误", str(e))

    def closeEvent(self, event):
        if hasattr(self, "timer"):
            self.timer.stop()
            self.timer.deleteLater()
            self.cap.release()
            del self.predictor, self.detector, self.cascade, self.cap
        super(OpencvWidget, self).closeEvent(event)
        self.deleteLater()

    def onCapture(self):
        _, frame = self.cap.read()

        minisize = (
            int(frame.shape[1] / DOWNSCALE), int(frame.shape[0] / DOWNSCALE))
        tmpframe = cv2.resize(frame, minisize)
        tmpframe = cv2.cvtColor(tmpframe, cv2.COLOR_BGR2GRAY)  # 做灰度处理
        tmpframe = cv2.equalizeHist(tmpframe)

        # minNeighbors表示每一个目标至少要被检测到5次
        faces = self.cascade.detectMultiScale(tmpframe, minNeighbors=5)
        del tmpframe
        if len(faces) < 1:  # 没有检测到脸
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = QImage(
                frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
            del frame
            return self.setPixmap(QPixmap.fromImage(img))
        # 特征点检测描绘
        for x, y, w, h in faces:
            x, y, w, h = x * DOWNSCALE, y * DOWNSCALE, w * DOWNSCALE, h * DOWNSCALE
            # 画脸矩形
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0))
            # 截取的人脸部分
            tmpframe = frame[y:y + h, x:x + w]
            # 进行特征点描绘
            rects = self.detector(tmpframe, 1)
            if len(rects) > 0:
                landmarks = numpy.matrix(
                    [[p.x, p.y] for p in self.predictor(tmpframe, rects[0]).parts()])
                for _, point in enumerate(landmarks):
                    pos = (point[0, 0] + x, point[0, 1] + y)
                    # 在原来画面上画点
                    cv2.circle(frame, pos, 3, color=(0, 255, 0))
            # 转成Qt能显示的
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = QImage(
                frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
            del frame
            self.setPixmap(QPixmap.fromImage(img))
Пример #26
0
class Mosaic(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Mosaic, self).__init__(parent=parent)
        self.setupUi(self)
        self.squares = [[None for _ in range(4)] for _ in range(4)]
        # self.pushButton.isEnabled()
        for i in range(4):
            for j in range(4):
                button_num = 4 * i + j + 1
                button_name = 'pushButton' + ('_' + str(button_num)
                                              if button_num > 1 else '')
                qt_button = getattr(self, button_name)
                qt_button.__class__ = Square
                qt_button.set_cords(i, j)
                qt_button.clicked.connect(self.square_click)
                self.squares[i][j] = qt_button
        self.pushButton_17.clicked.connect(self.new_game)
        self.space_cords = [3, 3]
        self.squares[3][3].setVisible(False)
        self.start_time = None
        self.end_time = None
        self.timer = None
        self.time_cnt = 0
        self.pushButton_19.clicked.connect(self.scoreboard)
        self.pushButton_18.clicked.connect(self.reset_game)
        qApp.installEventFilter(self)

    def move(self, square):
        val = square.text()
        if square.cords[1] == self.space_cords[1] or square.cords[
                0] == self.space_cords[0]:
            cord = 0 if square.cords[1] == self.space_cords[1] else 1
            direc = 1 if self.space_cords[cord] > square.cords[cord] else -1
            for i in range(square.cords[cord], self.space_cords[cord], direc):
                if cord == 0:
                    temp_val = self.squares[i + direc][square.cords[1]].text()
                    self.squares[i + direc][square.cords[1]].setText(val)
                else:
                    temp_val = self.squares[square.cords[0]][i + direc].text()
                    self.squares[square.cords[0]][i + direc].setText(val)
                val = temp_val
            self.squares[self.space_cords[0]][self.space_cords[1]].setEnabled(
                True)
            self.squares[self.space_cords[0]][self.space_cords[1]].setVisible(
                True)
            square.setEnabled(False)
            square.setText('space')
            square.setVisible(False)
            self.space_cords[0] = square.cords[0]
            self.space_cords[1] = square.cords[1]

    def square_click(self):
        self.move(self.sender())
        self.check_end()

    def new_game(self):
        if self.timer:
            self.timer.stop()
            self.timer.deleteLater()
        self.shuffle()
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.tick)
        self.timer.start(1000)
        self.start_time = time.time()
        self.time_cnt = 0
        self.label.setText("Time passed (sec): " + str(self.time_cnt))

    def shuffle(self):
        for t in range(16 * 10):
            if t % 2:
                possible_cords = [
                    i for i in range(4) if i != self.space_cords[0]
                ]
                rnd_cord = possible_cords[randint(0, 2)]
                self.move(self.squares[rnd_cord][self.space_cords[1]])
            else:
                possible_cords = [
                    j for j in range(4) if j != self.space_cords[1]
                ]
                rnd_cord = possible_cords[randint(0, 2)]
                self.move(self.squares[self.space_cords[1]][rnd_cord])

    def check_end(self):
        if self.start_time is not None and self.check_mosaic():
            self.end_game()

    def end_game(self):
        if self.start_time is not None:
            time_data = time.time() - self.start_time
            self.start_time = None
            self.label.setText("Your time (sec): " + str(round(time_data, 2)))
        if self.timer:
            self.timer.stop()
            self.timer.deleteLater()
            self.timer = None
        self.time_cnt = 0
        save_dialog = SaveDialog(self, score=round(time_data, 2))
        if save_dialog.exec():
            with open('scoreboard.txt', 'a+', encoding='utf-8') as csv_file:
                writer = csv.writer(csv_file, delimiter='$')
                writer.writerow([
                    save_dialog.lineEdit.text(),
                    save_dialog.label_5.text(),
                    save_dialog.label_4.text()
                ])
        self.label.setText('Press "New Game" to start new game')

    def reset_game(self):
        self.start_time = None
        if self.timer:
            self.timer.stop()
            self.timer.deleteLater()
            self.timer = None
        self.label.setText('Press "New Game" to start new game')
        for i in range(4):
            for j in range(4):
                button_num = 4 * i + j + 1
                if button_num < 16:
                    self.squares[i][j].setText(str(button_num))
                    if not self.squares[i][j].isEnabled():
                        self.squares[i][j].setVisible(True)
                        self.squares[i][j].setEnabled(True)
        self.squares[3][3].setVisible(False)
        self.squares[3][3].setEnabled(False)
        self.squares[3][3].setText('space')
        self.space_cords = [3, 3]

    def check_mosaic(self):
        for i in range(4):
            for j in range(4):
                button_num = 4 * i + j + 1
                if button_num < 16 and self.squares[i][j].text() != str(
                        button_num):
                    return False
        return True

    def eventFilter(self, source, event):
        if event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Up and self.space_cords[0] + 1 < 4:
                self.move(self.squares[self.space_cords[0] +
                                       1][self.space_cords[1]])
            elif event.key() == Qt.Key_Down and self.space_cords[0] - 1 >= 0:
                self.move(self.squares[self.space_cords[0] -
                                       1][self.space_cords[1]])
            elif event.key() == Qt.Key_Right and self.space_cords[1] - 1 >= 0:
                self.move(
                    self.squares[self.space_cords[0]][self.space_cords[1] - 1])
            elif event.key() == Qt.Key_Left and self.space_cords[1] + 1 < 4:
                self.move(
                    self.squares[self.space_cords[0]][self.space_cords[1] + 1])
            else:
                return super(Mosaic, self).eventFilter(source, event)
            self.check_end()
            return True
        return super(Mosaic, self).eventFilter(source, event)

    def tick(self):
        self.time_cnt += 1
        self.label.setText("Time passed (sec): " + str(self.time_cnt))

    def scoreboard(self):
        scoreBoard = ScoreboardDialog(self)
        scoreBoard.exec()
Пример #27
0
class PoputDialog(QWidget):

    def __init__(self, mainWindow=None):
        super(PoputDialog, self).__init__(None, Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint)
        self.SHADOW_WIDTH = 0
        self.__mw = mainWindow
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('ToolTips')
        self.setStyleSheet('background:gold;')
        # self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint)

        self.btn = QPushButton(self)
        self.btn.setText('调用父窗口方法')
        self.btn.clicked.connect(self.__test)

        self.desktop=QDesktopWidget().availableGeometry()
        self.move(
            (self.desktop.width()),
            self.desktop.height()-self.height()) #初始化位置到右下角
        self.showAnimation()

        self.show()

    def enterEvent(self, e):
        print(0)
        #清除Timer和信号槽
        self.remainTimer.stop()
        self.remainTimer.deleteLater()
        self.remainTimer=None

    def leaveEvent(self, e):
        print(1)
        self.__delay()

    def __test(self):
        self.__mw.do()

    #弹出动画
    def showAnimation(self):
        #显示弹出框动画
        self.animation=QPropertyAnimation(self, b'pos')
        self.animation.setDuration(1000)
        self.animation.setStartValue(QPoint(self.x(),self.y()))
        self.animation.setEndValue(
            QPoint( (self.desktop.width()-self.width()-self.SHADOW_WIDTH),
                (self.desktop.height()-self.height())))
        self.animation.start()


        self.animation.finished.connect(self.__delay)



    def __delay(self):
        self.remainTimer = QTimer(self) #初始化一个定时器
        self.remainTimer.timeout.connect(self.closeAnimation) #计时结束调用operate()方法
        self.remainTimer.start(3000) #设置计时间隔并启动

    def closeAnimation(self):
        #清除Timer和信号槽
        self.remainTimer.stop()
        # self.disconnect(self.remainTimer,pyqtSignal("timeout()"),self,pyqtSlot("closeAnimation()"))
        self.remainTimer.deleteLater()
        self.remainTimer=None
        #弹出框渐隐
        self.animation =QPropertyAnimation(self,b'windowOpacity')
        self.animation.setDuration(1000)
        self.animation.setStartValue(1)
        self.animation.setEndValue(0)
        #动画完成后清理
        self.animation.finished.connect(self.clearAll)
        self.animation.start()


    #清理及退出
    def clearAll(self):
        # self.disconnect(self.animation,pyqtSignal("finished()"),self,pyqtSlot("clearAll()"))
        sys.exit()    #退出
Пример #28
0
class DebugWindow(QMainWindow):
    """
    The debug window shows various statistics about Tribler such as performed requests, IPv8 statistics and
    community information.
    """

    resize_event = pyqtSignal()

    def __init__(self, settings, tribler_version):
        self._logger = logging.getLogger(self.__class__.__name__)
        QMainWindow.__init__(self)

        self.cpu_plot = None
        self.memory_plot = None
        self.initialized_cpu_plot = False
        self.initialized_memory_plot = False
        self.cpu_plot_timer = None
        self.memory_plot_timer = None
        self.tribler_version = tribler_version
        self.profiler_enabled = False
        self.toggling_profiler = False

        uic.loadUi(get_ui_file_path('debugwindow.ui'), self)
        self.setWindowTitle("Tribler debug pane")

        self.window().dump_memory_core_button.clicked.connect(lambda: self.on_memory_dump_button_clicked(True))
        self.window().dump_memory_gui_button.clicked.connect(lambda: self.on_memory_dump_button_clicked(False))
        self.window().toggle_profiler_button.clicked.connect(self.on_toggle_profiler_button_clicked)

        self.window().debug_tab_widget.setCurrentIndex(0)
        self.window().ipv8_tab_widget.setCurrentIndex(0)
        self.window().tunnel_tab_widget.setCurrentIndex(0)
        self.window().dht_tab_widget.setCurrentIndex(0)
        self.window().system_tab_widget.setCurrentIndex(0)
        self.window().debug_tab_widget.currentChanged.connect(self.tab_changed)
        self.window().ipv8_tab_widget.currentChanged.connect(self.ipv8_tab_changed)
        self.window().tunnel_tab_widget.currentChanged.connect(self.tunnel_tab_changed)
        self.window().dht_tab_widget.currentChanged.connect(self.dht_tab_changed)
        self.window().events_tree_widget.itemClicked.connect(self.on_event_clicked)
        self.window().system_tab_widget.currentChanged.connect(self.system_tab_changed)
        self.load_general_tab()

        self.window().open_files_tree_widget.header().setSectionResizeMode(0, QHeaderView.Stretch)

        # Enable/disable tabs, based on settings
        self.window().debug_tab_widget.setTabEnabled(2, settings and settings['trustchain']['enabled'])
        self.window().debug_tab_widget.setTabEnabled(3, settings and settings['ipv8']['enabled'])
        self.window().system_tab_widget.setTabEnabled(3, settings and settings['resource_monitor']['enabled'])
        self.window().system_tab_widget.setTabEnabled(4, settings and settings['resource_monitor']['enabled'])

        # Refresh logs
        self.window().log_refresh_button.clicked.connect(lambda: self.load_logs_tab())
        self.window().log_tab_widget.currentChanged.connect(lambda index: self.load_logs_tab())

        # IPv8 statistics enabled?
        self.ipv8_statistics_enabled = settings['ipv8']['statistics']

        # Libtorrent tab
        self.init_libtorrent_tab()

        # Position to center
        frame_geometry = self.frameGeometry()
        screen = QDesktopWidget().screenNumber(QDesktopWidget().cursor().pos())
        center_point = QDesktopWidget().screenGeometry(screen).center()
        frame_geometry.moveCenter(center_point)
        self.move(frame_geometry.topLeft())

        # Refresh timer
        self.refresh_timer = None
        self.rest_request = None
        self.ipv8_health_widget = None

    def hideEvent(self, hide_event):
        self.stop_timer()
        self.hide_ipv8_health_widget()

    def showEvent(self, show_event):
        if self.ipv8_health_widget and self.ipv8_health_widget.isVisible():
            self.ipv8_health_widget.resume()
            TriblerNetworkRequest("ipv8/asyncio/drift", self.on_ipv8_health_enabled, data={"enable": True},
                                  method='PUT')

    def run_with_timer(self, call_fn, timeout=DEBUG_PANE_REFRESH_TIMEOUT):
        call_fn()
        self.stop_timer()
        self.refresh_timer = QTimer()
        self.refresh_timer.setSingleShot(True)
        self.refresh_timer.timeout.connect(
            lambda _call_fn=call_fn, _timeout=timeout: self.run_with_timer(_call_fn, timeout=_timeout)
        )
        self.refresh_timer.start(timeout)

    def stop_timer(self):
        if self.refresh_timer:
            try:
                self.refresh_timer.stop()
                self.refresh_timer.deleteLater()
            except RuntimeError:
                self._logger.error("Failed to stop refresh timer in Debug pane")

    def init_libtorrent_tab(self):
        self.window().libtorrent_tab_widget.setCurrentIndex(0)
        self.window().libtorrent_tab_widget.currentChanged.connect(lambda _: self.load_libtorrent_data(export=False))

        self.window().lt_zero_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_one_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_two_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_three_hop_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=False))
        self.window().lt_export_btn.clicked.connect(lambda _: self.load_libtorrent_data(export=True))

        self.window().lt_zero_hop_btn.setChecked(True)

    def tab_changed(self, index):
        if index == 0:
            self.load_general_tab()
        elif index == 1:
            self.load_requests_tab()
        elif index == 2:
            self.run_with_timer(self.load_trustchain_tab)
        elif index == 3:
            self.ipv8_tab_changed(self.window().ipv8_tab_widget.currentIndex())
        elif index == 4:
            self.tunnel_tab_changed(self.window().tunnel_tab_widget.currentIndex())
        elif index == 5:
            self.dht_tab_changed(self.window().dht_tab_widget.currentIndex())
        elif index == 6:
            self.run_with_timer(self.load_events_tab)
        elif index == 7:
            self.system_tab_changed(self.window().system_tab_widget.currentIndex())
        elif index == 8:
            self.load_libtorrent_data()
        elif index == 9:
            self.load_logs_tab()

    def ipv8_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_ipv8_general_tab)
        elif index == 1:
            self.run_with_timer(self.load_ipv8_communities_tab)
        elif index == 2:
            self.run_with_timer(self.load_ipv8_community_details_tab)
        elif index == 3:
            self.run_with_timer(self.load_ipv8_health_monitor)

    def tunnel_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_tunnel_circuits_tab)
        elif index == 1:
            self.run_with_timer(self.load_tunnel_relays_tab)
        elif index == 2:
            self.run_with_timer(self.load_tunnel_exits_tab)
        elif index == 3:
            self.run_with_timer(self.load_tunnel_swarms_tab)
        elif index == 4:
            self.run_with_timer(self.load_tunnel_peers_tab)

    def dht_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_dht_statistics_tab)
        elif index == 1:
            self.run_with_timer(self.load_dht_buckets_tab)

    def system_tab_changed(self, index):
        if index == 0:
            self.load_open_files_tab()
        elif index == 1:
            self.load_open_sockets_tab()
        elif index == 2:
            self.load_threads_tab()
        elif index == 3:
            self.load_cpu_tab()
        elif index == 4:
            self.load_memory_tab()
        elif index == 5:
            self.load_profiler_tab()

    def create_and_add_widget_item(self, key, value, widget):
        item = QTreeWidgetItem(widget)
        item.setText(0, key)
        item.setText(1, "%s" % value)
        widget.addTopLevelItem(item)

    def load_general_tab(self):
        TriblerNetworkRequest("statistics/tribler", self.on_tribler_statistics)

    def on_tribler_statistics(self, data):
        if not data:
            return
        data = data["tribler_statistics"]
        self.window().general_tree_widget.clear()
        self.create_and_add_widget_item("Tribler version", self.tribler_version, self.window().general_tree_widget)
        self.create_and_add_widget_item(
            "Python version", sys.version.replace('\n', ''), self.window().general_tree_widget  # to fit in one line
        )
        self.create_and_add_widget_item("Libtorrent version", libtorrent.version, self.window().general_tree_widget)
        self.create_and_add_widget_item("", "", self.window().general_tree_widget)

        self.create_and_add_widget_item("Number of channels", data["num_channels"], self.window().general_tree_widget)
        self.create_and_add_widget_item(
            "Database size", format_size(data["db_size"]), self.window().general_tree_widget
        )
        self.create_and_add_widget_item(
            "Number of known torrents", data["num_torrents"], self.window().general_tree_widget
        )
        self.create_and_add_widget_item("", "", self.window().general_tree_widget)

        disk_usage = psutil.disk_usage('/')
        self.create_and_add_widget_item(
            "Total disk space", format_size(disk_usage.total), self.window().general_tree_widget
        )
        self.create_and_add_widget_item(
            "Used disk space", format_size(disk_usage.used), self.window().general_tree_widget
        )
        self.create_and_add_widget_item(
            "Free disk space", format_size(disk_usage.free), self.window().general_tree_widget
        )

    def load_requests_tab(self):
        self.window().requests_tree_widget.clear()
        for request, status_code in sorted(tribler_performed_requests, key=lambda rq: rq[0].time):
            endpoint = request.url
            method = request.method
            data = request.raw_data
            timestamp = request.time

            item = QTreeWidgetItem(self.window().requests_tree_widget)
            item.setText(0, "%s %s %s" % (method, repr(endpoint), repr(data)))
            item.setText(1, ("%d" % status_code) if status_code else "unknown")
            item.setText(2, "%s" % strftime("%H:%M:%S", localtime(timestamp)))
            self.window().requests_tree_widget.addTopLevelItem(item)

    def load_trustchain_tab(self):
        TriblerNetworkRequest("trustchain/statistics", self.on_trustchain_statistics)

    def on_trustchain_statistics(self, data):
        if not data:
            return
        self.window().trustchain_tree_widget.clear()
        for key, value in data["statistics"].items():
            self.create_and_add_widget_item(key, value, self.window().trustchain_tree_widget)

    def load_ipv8_general_tab(self):
        TriblerNetworkRequest("statistics/ipv8", self.on_ipv8_general_stats)

    def on_ipv8_general_stats(self, data):
        if not data:
            return
        self.window().ipv8_general_tree_widget.clear()
        for key, value in data["ipv8_statistics"].items():
            if key in ('total_up', 'total_down'):
                value = "%.2f MB" % (value / (1024.0 * 1024.0))
            elif key == 'session_uptime':
                value = "%s" % str(datetime.timedelta(seconds=int(value)))
            self.create_and_add_widget_item(key, value, self.window().ipv8_general_tree_widget)

    def load_ipv8_communities_tab(self):
        TriblerNetworkRequest("ipv8/overlays", self.on_ipv8_community_stats)

    def _colored_peer_count(self, peer_count, overlay_count, overlay_name):
        if overlay_name == 'DiscoveryCommunity':
            limits = [20, overlay_count * 30 + 1]
        elif overlay_name == 'DHTDiscoveryCommunity':
            limits = [20, 61]
        elif overlay_name == 'RemoteQueryCommunity':
            limits = [20, 51]
        else:
            limits = [20, 31]
        color = 0xF4D03F if peer_count < limits[0] else (0x56F129 if peer_count < limits[1] else 0xF12929)
        return QBrush(QColor(color))

    def on_ipv8_community_stats(self, data):
        if not data:
            return
        self.window().communities_tree_widget.clear()
        for overlay in data["overlays"]:
            item = QTreeWidgetItem(self.window().communities_tree_widget)
            item.setText(0, overlay["overlay_name"])
            item.setText(1, overlay["master_peer"][-12:])
            item.setText(2, overlay["my_peer"][-12:])
            peer_count = len(overlay["peers"])
            item.setText(3, "%s" % peer_count)
            item.setForeground(3, self._colored_peer_count(peer_count, len(data["overlays"]), overlay["overlay_name"]))

            if "statistics" in overlay and overlay["statistics"]:
                statistics = overlay["statistics"]
                item.setText(4, "%.3f" % (statistics["bytes_up"] / (1024.0 * 1024.0)))
                item.setText(5, "%.3f" % (statistics["bytes_down"] / (1024.0 * 1024.0)))
                item.setText(6, "%s" % statistics["num_up"])
                item.setText(7, "%s" % statistics["num_down"])
                item.setText(8, "%.3f" % statistics["diff_time"])
            else:
                item.setText(4, "N/A")
                item.setText(5, "N/A")
                item.setText(6, "N/A")
                item.setText(7, "N/A")
                item.setText(8, "N/A")

            self.window().communities_tree_widget.addTopLevelItem(item)
            map(self.window().communities_tree_widget.resizeColumnToContents, range(10))

    def load_ipv8_community_details_tab(self):
        if self.ipv8_statistics_enabled:
            self.window().ipv8_statistics_error_label.setHidden(True)
            TriblerNetworkRequest("ipv8/overlays/statistics", self.on_ipv8_community_detail_stats)
        else:
            self.window().ipv8_statistics_error_label.setHidden(False)
            self.window().ipv8_communities_details_widget.setHidden(True)

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

        self.window().ipv8_communities_details_widget.setHidden(False)
        self.window().ipv8_communities_details_widget.clear()
        for overlay in data["statistics"]:
            self.window().ipv8_communities_details_widget.setColumnWidth(0, 250)

            for key, stats in overlay.items():
                header_item = QTreeWidgetItem(self.window().ipv8_communities_details_widget)
                header_item.setFirstColumnSpanned(True)
                header_item.setBackground(0, QtGui.QColor('#CCCCCC'))
                header_item.setText(0, key)
                self.window().ipv8_communities_details_widget.addTopLevelItem(header_item)

                for request_id, stat in stats.items():
                    stat_item = QTreeWidgetItem(self.window().ipv8_communities_details_widget)
                    stat_item.setText(0, request_id)
                    stat_item.setText(1, "%.3f" % (stat["bytes_up"] / (1024.0 * 1024.0)))
                    stat_item.setText(2, "%.3f" % (stat["bytes_down"] / (1024.0 * 1024.0)))
                    stat_item.setText(3, "%s" % stat["num_up"])
                    stat_item.setText(4, "%s" % stat["num_down"])
                    self.window().ipv8_communities_details_widget.addTopLevelItem(stat_item)

    def load_ipv8_health_monitor(self):
        """
        Lazy load and enable the IPv8 core health monitor.
        """
        if self.ipv8_health_widget is None:
            # Add the core monitor widget to the tab widget.
            from PyQt5.QtWidgets import QVBoxLayout
            widget = MonitorWidget()
            layout = QVBoxLayout()
            layout.setContentsMargins(0, 0, 0, 0)
            layout.addWidget(widget)
            self.window().ipv8_health_monitor_widget.setLayout(layout)
            self.window().ipv8_health_monitor_widget.show()
            self.ipv8_health_widget = widget
        else:
            # We already loaded the widget, just resume it.
            self.ipv8_health_widget.resume()
        # Whether the widget is newly loaded or not, start the measurements.
        TriblerNetworkRequest("ipv8/asyncio/drift", self.on_ipv8_health_enabled, data={"enable": True}, method='PUT')

    def hide_ipv8_health_widget(self):
        """
        We need to hide the IPv8 health widget, involving two things:

         1. Stop the smooth graphical updates in the widget.
         2. Remove the observer from the IPv8 core.
        """
        if self.ipv8_health_widget is not None and not self.ipv8_health_widget.is_paused:
            self.ipv8_health_widget.pause()
            TriblerNetworkRequest("ipv8/asyncio/drift", lambda _: None, data={"enable": False}, method='PUT')

    def on_ipv8_health(self, data):
        """
        Measurements came in, send them to the widget for "plotting".
        """
        if not data or 'measurements' not in data or self.ipv8_health_widget is None:
            return
        self.ipv8_health_widget.set_history(data['measurements'])

    def on_ipv8_health_enabled(self, data):
        """
        The request to enable IPv8 completed.

        Start requesting measurements.
        """
        if not data:
            return
        self.run_with_timer(lambda: TriblerNetworkRequest("ipv8/asyncio/drift", self.on_ipv8_health), 100)

    def add_items_to_tree(self, tree, items, keys):
        tree.clear()
        for item in items:
            widget_item = QTreeWidgetItem(tree)
            for index, key in enumerate(keys):
                if key in ["bytes_up", "bytes_down"]:
                    value = format_size(item[key])
                elif key in ["creation_time", "last_lookup"]:
                    value = str(datetime.timedelta(seconds=int(time() - item[key]))) if item[key] > 0 else '-'
                else:
                    value = str(item[key])
                widget_item.setText(index, value)
            tree.addTopLevelItem(widget_item)

    def load_tunnel_circuits_tab(self):
        self.window().circuits_tree_widget.setColumnWidth(3, 200)
        TriblerNetworkRequest("ipv8/tunnel/circuits", self.on_tunnel_circuits)

    def on_tunnel_circuits(self, circuits):
        if not circuits:
            return

        for c in circuits["circuits"]:
            c["hops"] = f"{c['goal_hops']} / {c['goal_hops']}"
            c["exit_flags"] = c["exit_flags"] if c["state"] == "READY" else ""

        self.add_items_to_tree(
            self.window().circuits_tree_widget,
            circuits.get("circuits"),
            ["circuit_id", "hops", "type", "state", "bytes_up", "bytes_down", "creation_time", "exit_flags"],
        )

    def load_tunnel_relays_tab(self):
        TriblerNetworkRequest("ipv8/tunnel/relays", self.on_tunnel_relays)

    def on_tunnel_relays(self, data):
        if data:
            self.add_items_to_tree(
                self.window().relays_tree_widget,
                data["relays"],
                ["circuit_from", "circuit_to", "is_rendezvous", "bytes_up", "bytes_down", "creation_time"],
            )

    def load_tunnel_exits_tab(self):
        TriblerNetworkRequest("ipv8/tunnel/exits", self.on_tunnel_exits)

    def on_tunnel_exits(self, data):
        if data:
            self.add_items_to_tree(
                self.window().exits_tree_widget,
                data["exits"],
                ["circuit_from", "enabled", "bytes_up", "bytes_down", "creation_time"],
            )

    def load_tunnel_swarms_tab(self):
        TriblerNetworkRequest("ipv8/tunnel/swarms", self.on_tunnel_swarms)

    def on_tunnel_swarms(self, data):
        if data:
            self.add_items_to_tree(
                self.window().swarms_tree_widget,
                data.get("swarms"),
                [
                    "info_hash",
                    "num_seeders",
                    "num_connections",
                    "num_connections_incomplete",
                    "seeding",
                    "last_lookup",
                    "bytes_up",
                    "bytes_down",
                ],
            )

    def load_tunnel_peers_tab(self):
        self.window().peers_tree_widget.setColumnWidth(2, 300)
        TriblerNetworkRequest("ipv8/tunnel/peers", self.on_tunnel_peers)

    def on_tunnel_peers(self, data):
        if data:
            self.add_items_to_tree(
                self.window().peers_tree_widget, data.get("peers"), ["ip", "port", "mid", "is_key_compatible", "flags"]
            )

    def load_dht_statistics_tab(self):
        TriblerNetworkRequest("ipv8/dht/statistics", self.on_dht_statistics)

    def on_dht_statistics(self, data):
        if not data:
            return
        self.window().dhtstats_tree_widget.clear()
        for key, value in data["statistics"].items():
            self.create_and_add_widget_item(key, value, self.window().dhtstats_tree_widget)

    def load_dht_buckets_tab(self):
        TriblerNetworkRequest("ipv8/dht/buckets", self.on_dht_buckets)

    def on_dht_buckets(self, data):
        if data:
            for bucket in data["buckets"]:
                bucket["num_peers"] = len(bucket["peers"])
                ts = bucket["last_changed"]
                bucket["last_changed"] = str(datetime.timedelta(seconds=int(time() - ts))) if ts > 0 else '-'
            self.add_items_to_tree(
                self.window().buckets_tree_widget,
                data.get("buckets"),
                [
                    "prefix",
                    "last_changed",
                    "num_peers"
                ],
            )

    def on_event_clicked(self, item):
        event_dict = item.data(0, Qt.UserRole)
        self.window().event_text_box.setPlainText(json.dumps(event_dict))

    def load_events_tab(self):
        self.window().events_tree_widget.clear()
        for event_dict, timestamp in tribler_received_events:
            item = QTreeWidgetItem(self.window().events_tree_widget)
            item.setData(0, Qt.UserRole, event_dict)
            item.setText(0, "%s" % event_dict['type'])
            item.setText(1, "%s" % strftime("%H:%M:%S", localtime(timestamp)))
            self.window().events_tree_widget.addTopLevelItem(item)

    def load_open_files_tab(self):
        # Fill the open files (GUI) tree widget
        my_process = psutil.Process()
        self.window().open_files_tree_widget.clear()
        gui_item = QTreeWidgetItem(self.window().open_files_tree_widget)

        try:
            open_files = my_process.open_files()
            gui_item.setText(0, "GUI (%d)" % len(open_files))
            self.window().open_files_tree_widget.addTopLevelItem(gui_item)

            for open_file in open_files:
                item = QTreeWidgetItem()
                item.setText(0, open_file.path)
                item.setText(1, "%d" % open_file.fd)
                gui_item.addChild(item)
        except psutil.AccessDenied as exc:
            gui_item.setText(0, "Unable to get open files for GUI (%s)" % exc)

        TriblerNetworkRequest("debug/open_files", self.on_core_open_files)

    def on_core_open_files(self, data):
        if not data:
            return
        core_item = QTreeWidgetItem(self.window().open_files_tree_widget)
        core_item.setText(0, "Core (%d)" % len(data["open_files"]))
        self.window().open_files_tree_widget.addTopLevelItem(core_item)

        for open_file in data["open_files"]:
            item = QTreeWidgetItem()
            item.setText(0, open_file["path"])
            item.setText(1, "%d" % open_file["fd"])
            core_item.addChild(item)

    def load_open_sockets_tab(self):
        TriblerNetworkRequest("debug/open_sockets", self.on_core_open_sockets)

    def on_core_open_sockets(self, data):
        if not data:
            return
        self.window().open_sockets_tree_widget.clear()
        self.window().open_sockets_label.setText("Sockets opened by core (%d):" % len(data["open_sockets"]))
        for open_socket in data["open_sockets"]:
            if open_socket["family"] == socket.AF_INET:
                family = "AF_INET"
            elif open_socket["family"] == socket.AF_INET6:
                family = "AF_INET6"
            elif open_socket["family"] == socket.AF_UNIX:
                family = "AF_UNIX"
            else:
                family = "-"

            item = QTreeWidgetItem(self.window().open_sockets_tree_widget)
            item.setText(0, open_socket["laddr"])
            item.setText(1, open_socket["raddr"])
            item.setText(2, family)
            item.setText(3, "SOCK_STREAM" if open_socket["type"] == socket.SOCK_STREAM else "SOCK_DGRAM")
            item.setText(4, open_socket["status"])
            self.window().open_sockets_tree_widget.addTopLevelItem(item)

    def load_threads_tab(self):
        TriblerNetworkRequest("debug/threads", self.on_core_threads)

    def on_core_threads(self, data):
        if not data:
            return
        self.window().threads_tree_widget.clear()
        for thread_info in data["threads"]:
            thread_item = QTreeWidgetItem(self.window().threads_tree_widget)
            thread_item.setText(0, "%d" % thread_info["thread_id"])
            thread_item.setText(1, thread_info["thread_name"])
            self.window().threads_tree_widget.addTopLevelItem(thread_item)

            for frame in thread_info["frames"]:
                frame_item = QTreeWidgetItem()
                frame_item.setText(2, frame)
                thread_item.addChild(frame_item)

    def load_cpu_tab(self):
        if not self.initialized_cpu_plot:
            vlayout = self.window().cpu_plot_widget.layout()
            self.cpu_plot = CPUPlot(self.window().cpu_plot_widget)
            vlayout.addWidget(self.cpu_plot)
            self.initialized_cpu_plot = True

        self.refresh_cpu_plot()

        # Start timer
        self.cpu_plot_timer = QTimer()
        self.cpu_plot_timer.timeout.connect(self.load_cpu_tab)
        self.cpu_plot_timer.start(5000)

    def refresh_cpu_plot(self):
        TriblerNetworkRequest("debug/cpu/history", self.on_core_cpu_history)

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

        self.cpu_plot.reset_plot()
        for cpu_info in data["cpu_history"]:
            self.cpu_plot.add_data(cpu_info["time"], [round(cpu_info["cpu"], 2)])
        self.cpu_plot.render_plot()

    def load_memory_tab(self):
        if not self.initialized_memory_plot:
            vlayout = self.window().memory_plot_widget.layout()
            self.memory_plot = MemoryPlot(self.window().memory_plot_widget)
            vlayout.addWidget(self.memory_plot)
            self.initialized_memory_plot = True

        self.refresh_memory_plot()

        # Start timer
        self.memory_plot_timer = QTimer()
        self.memory_plot_timer.timeout.connect(self.load_memory_tab)
        self.memory_plot_timer.start(5000)

    def load_profiler_tab(self):
        self.window().toggle_profiler_button.setEnabled(False)
        TriblerNetworkRequest("debug/profiler", self.on_profiler_info)

    def on_profiler_info(self, data):
        if not data:
            return
        self.profiler_enabled = data["state"] == "STARTED"
        self.window().toggle_profiler_button.setEnabled(True)
        self.window().toggle_profiler_button.setText("%s profiler" % ("Stop" if self.profiler_enabled else "Start"))

    def on_toggle_profiler_button_clicked(self):
        if self.toggling_profiler:
            return

        self.toggling_profiler = True
        self.window().toggle_profiler_button.setEnabled(False)
        method = "DELETE" if self.profiler_enabled else "PUT"
        TriblerNetworkRequest("debug/profiler", self.on_profiler_state_changed, method=method)

    def on_profiler_state_changed(self, data):
        if not data:
            return
        self.toggling_profiler = False
        self.window().toggle_profiler_button.setEnabled(True)
        self.load_profiler_tab()

        if 'profiler_file' in data:
            QMessageBox.about(
                self, "Profiler statistics saved", "The profiler data has been saved to %s." % data['profiler_file']
            )

    def refresh_memory_plot(self):
        TriblerNetworkRequest("debug/memory/history", self.on_core_memory_history)

    def on_core_memory_history(self, data):
        if not data or data.get("memory_history") is None:
            return
        self.memory_plot.reset_plot()
        for mem_info in data["memory_history"]:
            self.memory_plot.add_data(mem_info["time"], [round(mem_info["mem"], 2)])
        self.memory_plot.render_plot()

    def on_memory_dump_button_clicked(self, dump_core):
        self.export_dir = QFileDialog.getExistingDirectory(
            self, "Please select the destination directory", "", QFileDialog.ShowDirsOnly
        )

        if len(self.export_dir) > 0:
            filename = "tribler_mem_dump_%s_%s.json" % (
                'core' if dump_core else 'gui',
                datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
            )
            if dump_core:
                self.rest_request = TriblerNetworkRequest(
                    "debug/memory/dump", lambda data, _: self.on_memory_dump_data_available(filename, data)
                )
            elif scanner:
                scanner.dump_all_objects(os.path.join(self.export_dir, filename))
            else:
                ConfirmationDialog.show_error(
                    self.window(),
                    "Error when performing a memory dump",
                    "meliae memory dumper is not compatible with Python 3",
                )

    def on_memory_dump_data_available(self, filename, data):
        if not data:
            return
        dest_path = os.path.join(self.export_dir, filename)
        try:
            with open(dest_path, "wb") as memory_dump_file:
                memory_dump_file.write(data)
        except IOError as exc:
            ConfirmationDialog.show_error(
                self.window(),
                "Error when exporting file",
                "An error occurred when exporting the torrent file: %s" % str(exc),
            )

    def closeEvent(self, close_event):
        if self.rest_request:
            self.rest_request.cancel_request()
        if self.cpu_plot_timer:
            self.cpu_plot_timer.stop()

        if self.memory_plot_timer:
            self.memory_plot_timer.stop()

    def load_logs_tab(self):
        # Max lines from GUI
        max_log_lines = self.window().max_lines_value.text()

        tab_index = self.window().log_tab_widget.currentIndex()
        tab_name = "core" if tab_index == 0 else "gui"

        request_query = "process=%s&max_lines=%s" % (tab_name, max_log_lines)
        TriblerNetworkRequest("debug/log?%s" % request_query, self.display_logs)

    def display_logs(self, data):
        if not data:
            return
        tab_index = self.window().log_tab_widget.currentIndex()
        log_display_widget = (
            self.window().core_log_display_area if tab_index == 0 else self.window().gui_log_display_area
        )

        log_display_widget.moveCursor(QTextCursor.End)

        key_content = u'content'
        key_max_lines = u'max_lines'

        if not key_content in data or not data[key_content]:
            log_display_widget.setPlainText('No logs found')
        else:
            log_display_widget.setPlainText(data[key_content])

        if not key_max_lines in data or not data[key_max_lines]:
            self.window().max_lines_value.setText('')
        else:
            self.window().max_lines_value.setText(str(data[key_max_lines]))

        sb = log_display_widget.verticalScrollBar()
        sb.setValue(sb.maximum())

    def show(self):
        super(DebugWindow, self).show()

        # this will remove minimized status
        # and restore window with keeping maximized/normal state
        self.window().setWindowState(self.window().windowState() & ~Qt.WindowMinimized | Qt.WindowActive)
        self.window().activateWindow()

    def load_libtorrent_data(self, export=False):
        tab = self.window().libtorrent_tab_widget.currentIndex()
        hop = (
            0
            if self.window().lt_zero_hop_btn.isChecked()
            else 1
            if self.window().lt_one_hop_btn.isChecked()
            else 2
            if self.window().lt_two_hop_btn.isChecked()
            else 3
        )
        if tab == 0:
            self.load_libtorrent_settings_tab(hop, export=export)
        elif tab == 1:
            self.load_libtorrent_sessions_tab(hop, export=export)

    def load_libtorrent_settings_tab(self, hop, export=False):
        TriblerNetworkRequest(
            "libtorrent/settings?hop=%d" % hop, lambda data: self.on_libtorrent_settings_received(data, export=export)
        )
        self.window().libtorrent_settings_tree_widget.clear()

    def on_libtorrent_settings_received(self, data, export=False):
        if not data:
            return
        for key, value in data["settings"].items():
            item = QTreeWidgetItem(self.window().libtorrent_settings_tree_widget)
            item.setText(0, key)
            item.setText(1, str(value))
            self.window().libtorrent_settings_tree_widget.addTopLevelItem(item)
        if export:
            self.save_to_file("libtorrent_settings.json", data)

    def load_libtorrent_sessions_tab(self, hop, export=False):
        TriblerNetworkRequest(
            "libtorrent/session?hop=%d" % hop, lambda data: self.on_libtorrent_session_received(data, export=export)
        )
        self.window().libtorrent_session_tree_widget.clear()

    def on_libtorrent_session_received(self, data, export=False):
        if not data:
            return
        for key, value in data["session"].items():
            item = QTreeWidgetItem(self.window().libtorrent_session_tree_widget)
            item.setText(0, key)
            item.setText(1, str(value))
            self.window().libtorrent_session_tree_widget.addTopLevelItem(item)
        if export:
            self.save_to_file("libtorrent_session.json", data)

    def save_to_file(self, filename, data):
        base_dir = QFileDialog.getExistingDirectory(self, "Select an export directory", "", QFileDialog.ShowDirsOnly)
        if len(base_dir) > 0:
            dest_path = os.path.join(base_dir, filename)
            try:
                with open(dest_path, "w") as torrent_file:
                    torrent_file.write(json.dumps(data))
            except IOError as exc:
                ConfirmationDialog.show_error(self.window(), "Error exporting file", str(exc))
Пример #29
0
class ExampleApp(QWidget, Ui_MainWindow):

    global com_port_name, get_pos, motor_stop, move_abs
    global position_LEED, position_EXCH, position_PASS

    def __init__(self):

        super(self.__class__, self).__init__()
        self.setupUi(self)
        """ Start monitoring the current position and connect all signals"""

        self.update_thread = update_position()

        self.pushButton.clicked.connect(
            lambda: self.move_motor(self.lineEdit.text()))
        self.pushButton_2.clicked.connect(self.stop_motor)
        self.pushButton_3.clicked.connect(
            lambda: self.shift_motor(1, self.lineEdit_3.text()))  # L shift
        self.pushButton_4.clicked.connect(
            lambda: self.shift_motor(-1, self.lineEdit_3.text()))  # R shift
        self.pushButton_5.clicked.connect(
            lambda: self.move_motor(self.lineEdit_4.text()))  # LEED
        self.pushButton_6.clicked.connect(
            lambda: self.move_motor(self.lineEdit_5.text()))  # EXCH
        self.pushButton_7.clicked.connect(
            lambda: self.move_motor(self.lineEdit_6.text()))  # PASS

        self.start()
        """ Show the LEED, EXCH and PASS positions """
        self.lineEdit_4.setText(str(position_LEED))
        self.lineEdit_5.setText(str(position_EXCH))
        self.lineEdit_6.setText(str(position_PASS))

    def start(self):

        self.update_thread.new_value_trigger.connect(
            self.update_position_label)

        self.timer_x = QTimer(self)
        self.timer_x.timeout.connect(self.update_thread.update_position)
        self.timer_x.start(1000)

    def stop_motor(self):

        self.command = motor_stop  # construct command
        send_motor.send_command(com_port_name, self.command)  # senf command

    def update_position_label(self, value):

        self.position_mm = value
        self.lineEdit_2.setText("{:1.1f}".format(self.position_mm))

    def move_motor(self, value):

        if (float(value) <= 265) & (float(value) >= 0):
            self.lineEdit.setText(value)
            self.value = convert(float(value), True)
            print('moving to ', self.value)
            self.command = move_abs + (self.value).to_bytes(
                4, byteorder='big', signed=True)
            send_motor.send_command(com_port_name, self.command)

    def shift_motor(self, flag, value):

        self.shift = float(value)
        if (self.shift <= 50) & (self.shift >= 0):
            if flag == -1:
                self.shift = (-1) * self.shift
            self.new_value = float(self.lineEdit_2.text()) + self.shift
            self.lineEdit.setText(str(self.new_value))
            print(self.new_value)
            self.shift_steps = convert(self.new_value, True)
            print(self.shift_steps)
            self.command = move_abs + (self.shift_steps).to_bytes(
                4, byteorder='big', signed=True)
            send_motor.send_command(com_port_name, self.command)

    def __del__(self):

        self.stop_motor()
        self.update_thread.quit()
        self.timer_x.stop()
        self.timer_x.deleteLater()
Пример #30
0
class Form(QtWidgets.QDialog):
    def __init__(self, parent=None):
        QtWidgets.QDialog.__init__(self, parent)

        self.ui = uic.loadUi("./res/vocatest.ui", self)
        self.ui.show()

        #초기화면 시작 버튼 생성 & 초기화
        self.bnStart = QPushButton(self)
        self.bnStart.setDefault(False)
        self.bnStart.setGeometry(80, 40, 400, 320)
        self.bnStart.setIcon(QIcon(QPixmap("./res/start.jpg")))
        self.bnStart.setIconSize(QSize(390, 310))
        # self.bnStart.setStyleSheet("background-image: url('start.jpg'); border: none;")
        self.bnStart.clicked.connect(self.bnStart_clicked)

        #정답 선택 라벨 마우스 이벤트 설정
        #self.ui.label_select4.mousePressEvent = self.slot_label_select_clicked
        self.ui.label_select1.installEventFilter(self)
        self.ui.label_select2.installEventFilter(self)
        self.ui.label_select3.installEventFilter(self)
        self.ui.label_select4.installEventFilter(self)

        #폰트
        #font = QFont()
        #font.setFamily(_fromUtf8(""))
        #font.setBold(True)
        quesFont = QFont("Times", 21, QFont.Bold)
        self.ui.label_question.setFont(quesFont)
        self.ui.label_question.setStyleSheet(
            "QLabel { background-color : #ffd732; color : black; }")

        scoreFont = QFont("Times", 14, QFont.Bold)
        self.ui.label_score.setFont(scoreFont)
        self.ui.label_score.setStyleSheet("QLabel { color : blue; }")
        #"background-color : white;}");
        #"border:1px solid rgb(100, 100, 255);}");

        answFont = QFont("굴림", 11, QFont.Normal)
        self.ui.label_select1.setFont(answFont)
        self.ui.label_select2.setFont(answFont)
        self.ui.label_select3.setFont(answFont)
        self.ui.label_select4.setFont(answFont)

        #변수 초기화
        self.timer = None
        self.testNum = 0
        self.selAnswer = ''  #유저가 선택한 답(정답 A,B형인 경우 '1' ~ '4', C형일 경우 'string')
        self.cntAnswer = 0  #정답개수

        #csv 파일 load
        self.vocas = csv.DictReader(open("../data/test.csv"))
        self.vocas = list(self.vocas)
        self.nTestTotal = len(self.vocas)

        self.retImg = QLabel(self)
        self.retImg.setGeometry(30, 270, 190, 120)

        self.label_counter = QLabel(self)
        self.label_counter.setGeometry(510, 70, 50, 50)
        self.label_counter.setFont(quesFont)
        self.label_counter.setStyleSheet("QLabel { color : red; }")
        self.label_counter.setText("%d" % TIMEOUT)
        # "background-color : white;}");
        # "border:1px solid rgb(100, 100, 255);}");

        self.showControls(False)
        self.bnStart.show()
        self.updateScore()
        self.setWindowTitle('뇌새김 단어 맞추기')

    def init_vocaTest(self):
        self.timer = None
        self.testNum = 0
        self.selAnswer = ''  # 유저가 선택한 답(정답 A,B형인 경우 '1' ~ '4', C형일 경우 'string')
        self.cntAnswer = 0  # 정답개수
        self.updateScore()

    def start_timer(self, slot, count=1, interval=1000):
        counter = 0

        def handler():
            nonlocal counter
            counter += 1
            slot(counter)
            '''
            if counter >= count:
                self.timer.stop()
                self.timer.deleteLater()
            '''

        self.timer = QTimer()
        self.timer.timeout.connect(handler)
        self.timer.start(interval)

    def stop_timer(self):
        if self.timer != None:
            self.timer.stop()
            self.timer.deleteLater()
            self.timer = None

    def timer_func(self, count):
        print('Timer:', count)

        if count >= TIMEOUT:
            self.checkTest('')
            #print("Timeout - 다음 문제로 넘어 갑니다.")
            self.testNum += 1
            self.goNextTest(self.testNum)
            self.label_counter.setText("%d" % TIMEOUT)
        else:
            self.label_counter.setText("%d" % (TIMEOUT - count))

    def bnStart_clicked(self):
        self.bnStart.hide()
        self.showControls(True)
        self.init_vocaTest()
        self.setVocaTest(self.testNum)

    def showControls(self, bShow):
        if bShow:
            self.ui.label_descript.show()
            self.ui.label_question.show()
            self.ui.label_select1.show()
            self.ui.label_select2.show()
            self.ui.label_select3.show()
            self.ui.label_select4.show()
            self.ui.label_score.show()
            self.label_counter.show()
        else:
            self.ui.label_descript.hide()
            self.ui.label_question.hide()
            self.ui.label_select1.hide()
            self.ui.label_select2.hide()
            self.ui.label_select3.hide()
            self.ui.label_select4.hide()
            self.ui.label_score.hide()
            self.label_counter.hide()

    #시험문제 준비
    def setVocaTest(self, currNum):
        self.stop_timer()
        test = self.vocas[currNum]
        type = test["TYPE"]
        if type == 'A':
            descript = "{0}. 다음 영단어의 뜻을 고르시오.".format(currNum + 1)
        elif type == 'B':
            descript = "{0}. 다음 뜻과 일치하는 영단어를 고르시오.".format(currNum + 1)
        elif type == 'C':
            descript = "{0}. 다음에 해당하는 영단어 철자를 입력하시오".format(currNum + 1)

        self.ui.label_descript.setText(descript)
        self.ui.label_question.setText(test["QUESTION"])  #폰트 크게

        if type != 'C':
            strSel = '① ' + test["SELECT1"]
            self.ui.label_select1.setText(strSel)
            strSel = '② ' + test["SELECT2"]
            self.ui.label_select2.setText(strSel)
            strSel = '③ ' + test["SELECT3"]
            self.ui.label_select3.setText(strSel)
            strSel = '④ ' + test["SELECT4"]
            self.ui.label_select4.setText(strSel)

        #타이머
        self.start_timer(self.timer_func, TIMEOUT)

    def checkTest(self, selAnswer):
        #정답인 경우
        test = self.vocas[self.testNum]
        answer = test["ANSWER"]
        if selAnswer == answer:
            QSound.play("./res/good.wav")
            imgpath = "./res/good.png"
            self.cntAnswer += 1
        else:
            QSound.play("./res/wrong.wav")
            imgpath = "./res/nogood.png"

        temp = QPixmap(imgpath)
        pixmap = temp.scaled(self.retImg.width(), self.retImg.height())
        self.retImg.setPixmap(pixmap)
        self.retImg.show()
        self.retImg.repaint()  #hide하기 전에 repaint를 해줘야 제대로 보이네... update는 안먹힘
        time.sleep(0.5)  #결과이미지 보여주고 2초간 대기
        self.retImg.hide()

        self.updateScore()

    def updateScore(self):
        self.strScore = "%d / %d" % (self.cntAnswer, self.nTestTotal)
        self.ui.label_score.setText(self.strScore)

    def eventFilter(self, source, event):
        if event.type() == QEvent.MouseButtonPress:
            if source == self.ui.label_select1:
                selAnswer = '1'
            elif source == self.ui.label_select2:
                selAnswer = '2'
            elif source == self.ui.label_select3:
                selAnswer = '3'
            else:
                selAnswer = '4'
            print("The sender is:", source.text())

            self.checkTest(selAnswer)
            # 다음문제로...
            self.testNum += 1
            self.goNextTest(self.testNum)

        return super(Form, self).eventFilter(source, event)

    def goNextTest(self, testNum):
        if testNum < self.nTestTotal:
            self.setVocaTest(testNum)
        elif testNum >= self.nTestTotal:
            # 테스트종료
            self.stop_timer()
            choice = QMessageBox.question(
                self, '시험 끝 ',
                "맞은 개수 : %d\n틀린 개수 : %d\n종합 점수 : %d점\n\n재시도 하시겠습니까?" %
                (self.cntAnswer, self.nTestTotal - self.cntAnswer,
                 self.cntAnswer / self.nTestTotal * 100),
                QMessageBox.Yes | QMessageBox.No)
            if choice == QMessageBox.Yes:
                self.bnStart_clicked()
            else:
                sys.exit()

    '''
Пример #31
0
class App(QDialog):
    def __init__(self):
        '''
        Initializes and loads the GUI PyQt file
        '''
        super(App, self).__init__()
        self.vid = None
        self.name = None
        self.capture = None
        self.len = None
        self.l = 0
        loadUi('gui.xml', self)
        self.startButton.clicked.connect(self.on_start_clicked)
        self.lButton.clicked.connect(self.open_file)
        self.playButton.clicked.connect(self.play_video)

    def play_video(self):
        '''
        A function to play a given video
        '''
        self.capture = cv2.VideoCapture(self.videoOut)
        frame_rate = self.capture.get(cv2.CAP_PROP_FPS)
        self.len = int(self.capture.get(cv2.CAP_PROP_FRAME_COUNT))

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.dispayImage)
        self.timer.start(frame_rate)

    def dispayImage(self):
        '''
        Each video frame is read and loaded
        '''
        self.l += 1

        if self.l >= self.len:
            self.timer.stop()
            self.timer.deleteLater()
            self.l = 0

        ret, img = self.capture.read()
        qformat = QImage.Format_RGB888

        outImage = QImage(img, img.shape[1], img.shape[0], qformat)
        outImage = outImage.rgbSwapped()
        self.video.setPixmap(QPixmap.fromImage(outImage))

    def open_file(self):
        '''
        Opens Files
        '''
        filename, _ = QFileDialog.getOpenFileName(self, 'Open Video File',
                                                  '../', 'All Files(*)')
        if filename:
            self.vid = filename
            base = os.path.basename(filename)
            self.name = os.path.splitext(base)[0]
            self.nameLabel.setText(base)

    def on_start_clicked(self):
        '''
        Reads the input from the GUI and uses the parameters to start the program
        '''
        self.finished.clear()
        QApplication.instance().processEvents()

        alpha = float(self.alpha.text())
        cutoff = float(self.cutoff.text())
        low = float(self.low.text())
        high = float(self.high.text())
        chromAttenuation = float(self.chromAtt.text())
        linearAttenuation = self.linearAtt.isChecked()
        mode = self.comboBox.currentIndex()

        if mode == 0:
            butterworth_filter.start(self.vid, alpha, cutoff, low, high,
                                     linearAttenuation, chromAttenuation,
                                     self.name)
        else:
            if mode == 1:
                ideal_filter.start(self.vid, alpha, low, high,
                                   chromAttenuation, self.name)

        self.finished.setText('Done!')

        self.videoOut = self.name + "Out.avi"
Пример #32
0
class Widget(QMainWindow):
    logger.info("---------- STARTED ----------")
    stop_signal = pyqtSignal(
    )  # sinaliza que o usuário clicou em "Stop Data Colleting"
    logout_signal = pyqtSignal()

    date = datetime.datetime.strptime(RELEASE_DATE, '%Y-%m-%d')
    version = VERSION

    # Check if all files/folders are present.
    if not os.path.exists("Data"):
        os.mkdir("Data")

    if not os.path.exists("Data\\Training Data"):
        os.mkdir("Data\\Training Data")

    try:
        with open("config.json", "r") as f:
            logger.info('Loading config file')
            output = json.loads(f.read())
            used_key = output["Used key"]
            username = output['User']
            ignore_login = output['Ignore Login Popup']
            first_time_running = output['First Time Running']
            token = output['Token']

    except Exception as e:
        logger.error(e)

        output = {
            "Used key": "C",
            "User": "",
            "Ignore Login Popup": False,
            "First Time Running": True,
            "Token": ""
        }

        used_key = output["Used key"]
        username = output['User']
        ignore_login = output['Ignore Login Popup']
        first_time_running = output['First Time Running']
        token = output['Token']

        with open("config.json", 'w') as f:
            json.dump(output, f, indent=2)

        logger.info("Fixed config file")

    logger.info('Config file loaded')

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

        self.initUI()

        # Starting threads for startup verification
        self.loading_dialog = Loading()

        if DEV:
            wait_time = 100
        else:
            wait_time = random.randint(3550, 4500)

        # Defining control variables:
        self.auth_done = False
        self.update_check_done = False
        self.call_update_box = False
        self.call_accnt_box = False
        self.update_available = False
        self.wait_counter = 0
        self.online = False
        self.bot_btn_clicks = 0

        # Startup processes:
        self.startup_authorize_user()
        self.startup_update_check()

        self.loading_timer = QTimer()
        self.loading_timer.timeout.connect(self.loading)
        self.loading_timer.start(wait_time)

        # Icons:
        self.setWindowIcon(QtGui.QIcon('media\\logo\\logo.ico'))
        self.dog_getting_up = QtGui.QMovie(
            'media\\animations\\Dog Getting Up4.gif')
        self.dog_running = QtGui.QMovie('media\\animations\\Dog Running4.gif')
        self.dog_idle = QtGui.QMovie('media\\animations\\Dog Idle2.gif')
        self.dog_sitting_down = QtGui.QMovie(
            "media\\animations\\Dog Sitting Down4.gif")

        self.icons_label.setMovie(self.dog_idle)
        self.icons_label_2.setMovie(self.dog_idle)
        self.dog_idle.start()

        # Setting default labels and texts:
        self.v_label.setText("v{}".format(self.version))
        self.v_label_2.setText("v{}".format(self.version))

        # Defining button/checkbox actions
        self.data_start.clicked.connect(self.data_start_action)
        self.data_stop.clicked.connect(self.data_stop_action)
        self.send_btn.clicked.connect(self.send_data)
        self.bot_btn.clicked.connect(self.bot_controller)

    def initUI(self):
        logger.info("Initializing UI")

        loadUi('designs\\MainWindow.ui', self)

        # Main Window
        self.setFixedSize(333, 493)

        # Toolbar
        self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint
                            | Qt.WindowMinimizeButtonHint)

        # Bug Report Tab
        self.send_message_btn.clicked.connect(self.send_message)

        # Menu
        self.logout_btn = self.menu.addAction('Logout')
        self.logout_btn.triggered.connect(self.logout)
        self.logout_btn.setVisible(False)

        self.login_btn = self.menu.addAction('Login')
        self.login_btn.triggered.connect(self.runtime_login)
        self.login_btn.setVisible(False)

        visit_ranking = self.menu.addAction('Ranking')
        visit_ranking.triggered.connect(lambda: webbrowser.open(RANKING_URL))

        website = self.menu.addAction('GitHub')
        website.triggered.connect(
            lambda: webbrowser.open("https://github.com/Setti7/SVFB-GUI"))

        self.config = self.menu.addAction('Fast Config')
        self.config.triggered.connect(self.fast_config)

        logger.info("UI Initialized")

    # Loading screen controller
    def loading(self):

        if self.auth_done and self.update_check_done:
            logger.info("Loading main aplication finished")
            self.loading_timer.stop()
            self.loading_timer.deleteLater()

            self.call_accnt_box = True
            self.call_update_box = True
            self.loading_dialog.close()
            self.show()

    def fast_config(self):

        config_dialog = ChangeKey(self.used_key)
        if config_dialog.exec_():
            self.used_key = config_dialog.new_key

    # Send message
    def send_message(self):

        msg = self.message_text.toPlainText()

        if self.update_available:

            bug_box = QMessageBox()
            bug_box.setIcon(QMessageBox.Warning)
            bug_box.setText(
                "<strong>You can't send bug reports while using an outdated version!</strong>"
            )
            bug_box.setInformativeText(
                """Please click <i>Ok</i> to download the newer one. Maybe your bug is already fixed."""
            )
            bug_box.setWindowTitle("Please update before sending bug reports")
            bug_box.setWindowIcon(QtGui.QIcon('media\\logo\\logo.ico'))

            bug_box.setEscapeButton(QMessageBox.Close)
            bug_box.addButton(QMessageBox.Close)

            ok = bug_box.addButton(QMessageBox.Ok)
            ok.clicked.connect(lambda: webbrowser.open(
                "https://github.com/Setti7/SVFB-GUI/releases"))
            bug_box.exec_()

        elif len(msg) > 1000:

            self.message_status_label.clear()
            self.message_status_label.setStyleSheet("color: #dc3545;")

            self.timer_msg0 = QTimer()
            self.timer_msg0.timeout.connect(
                lambda: self.message_status_label.setText(
                    "Your message is to big!\nThe maximum is 1000 chars."))
            self.timer_msg0.timeout.connect(self.timer_msg0.stop)
            self.timer_msg0.timeout.connect(self.timer_msg0.deleteLater)
            self.timer_msg0.start(200)

        else:

            self.message_text.clear()

            try:

                data = {
                    'message': msg,
                    'user': self.username,
                    'version': self.version,
                }

                headers = {'Authorization': f'Token {self.token}'}

                response = requests.post(BUG_REPORT_URL,
                                         data=data,
                                         headers=headers)

                result = json.loads(response.text)

                if result['success']:

                    self.message_status_label.setText(
                        "Message successfully sent!")
                    self.message_status_label.setStyleSheet("color: #28a745;")

                else:
                    logger.error(
                        f"Error while sending message: {result['error']}")
                    self.message_status_label.setText(
                        "There was an error while sending!")
                    self.message_status_label.setStyleSheet("color: #dc3545;")

                self.timer_msg = QTimer()
                self.timer_msg.timeout.connect(self.message_status_label.clear)
                self.timer_msg.timeout.connect(self.timer_msg.stop)
                self.timer_msg.timeout.connect(self.timer_msg.deleteLater)
                self.timer_msg.start(5000)

            except Exception as e:
                print(e)
                logger.error(e)

    # Startup Processes and connection functions:
    def startup_update_check(self):
        logger.info("Searching for updates")
        self.check_thread = QThread()
        self.checker = CheckForUpdates()
        self.checker.moveToThread(self.check_thread)

        self.checker.update_text.connect(self.update_check_over)

        self.check_thread.started.connect(self.checker.do_work)
        self.check_thread.start()

    def update_check_over(self, update_info):
        self.checker.deleteLater()
        self.check_thread.quit()
        self.check_thread.deleteLater()
        self.check_thread.wait()

        self.update_timer = QTimer()
        self.update_timer.timeout.connect(
            lambda: self.update_message_box(update_info))
        self.update_timer.start(200)

        self.update_check_done = True

    def startup_authorize_user(self):
        logger.info("Trying to login user")

        # Thread:
        self.login_thread = QThread()
        self.login_worker = LoginWorker(self.username, self.token)
        self.login_worker.moveToThread(self.login_thread)

        self.login_worker.result.connect(self.login_control)

        self.login_worker.result.connect(self.login_worker.deleteLater)
        self.login_worker.result.connect(self.login_thread.quit)

        self.login_thread.finished.connect(self.login_thread.deleteLater)
        self.login_thread.finished.connect(self.login_thread.wait)

        self.login_thread.started.connect(self.login_worker.do_work)
        self.login_thread.start()

    # If the user clicks the retry connection button too much:
    def wait_motherfucker(self, *args):
        self.wait_counter += 1

        if self.wait_counter >= 5:
            self.wait_counter = 0
            wait = QMessageBox()
            wait.setIcon(QMessageBox.Warning)
            wait.setText(
                "<strong>I AM TRYING TO CONNECT ALREADY. STOP MASHING THAT DAMN BUTTON"
            )
            wait.setInformativeText(
                """I'm doing my best ok? Just have a little patience please."""
            )
            wait.setWindowTitle("FOR GOD'S SAKE, WAIT!")
            wait.setWindowIcon(QtGui.QIcon('media\\logo\\logo.ico'))

            close = wait.addButton(QMessageBox.Close)
            close.setText("Ok... I will stop")
            wait.setEscapeButton(QMessageBox.Close)
            wait.exec_()

    def retry_connection(self, *args):
        # *args are necessary so it can be called from the mousePressEvent

        # Label
        self.username_label.setText("Connecting")
        self.username_label.mousePressEvent = lambda x: self.wait_motherfucker(
        )

        self.username_label_2.setText("Connecting")
        self.username_label_2.mousePressEvent = lambda x: self.wait_motherfucker(
        )

        # Thread:
        self.login_thread = QThread()
        self.login_worker = LoginWorker(self.username, self.token)
        self.login_worker.moveToThread(self.login_thread)

        # Finished proccess
        self.login_worker.result.connect(self.login_worker.deleteLater)
        self.login_worker.result.connect(self.login_thread.quit)
        self.login_thread.finished.connect(self.login_thread.deleteLater)

        # Response from thread
        self.login_worker.result.connect(self.login_control)

        # Thread starting
        self.login_thread.started.connect(self.login_worker.do_work)
        self.login_thread.start()

        # Verifying new versions:
        self.check_thread = QThread()
        self.checker = CheckForUpdates()
        self.checker.moveToThread(self.check_thread)

        self.checker.update_text.connect(self.update_check_over)

        self.check_thread.started.connect(self.checker.do_work)
        self.check_thread.start()

        # As gui has already loaded, we jump through the code made to stop the message box from appearing while loading
        self.call_update_box = True

    def update_score(self, **kwargs):

        # if 'offline' in kwargs.keys():
        #     self.score_label.setText("")
        #     # self.score_label.setText("Score: Offline")
        #
        # if 'waiting' in kwargs.keys():
        #     self.score_label.setText("")
        #     # self.score_label.setText("Score: Waiting Connection")
        #
        # if 'not_logged' in kwargs.keys():
        #     self.score_label.setText("")
        #     # self.score_label.setText("Score: Not Logged")

        if 'online_score' in kwargs.keys():
            self.score_label.setVisible(True)
            self.line.setVisible(True)
            self.score_label.setText("Online Score: {}".format(
                kwargs['online_score']))

        else:
            self.score_label.setVisible(False)
            self.line.setVisible(False)

    def dog_go_idle(self):
        self.icons_label.setMovie(self.dog_idle)
        self.dog_idle.start()
        self.dog_timer2.stop()

    def dog_run(self):
        self.icons_label.setMovie(self.dog_running)
        self.dog_running.start()
        self.dog_timer.stop()

    # Notification of new version:
    def call_not_critical_update_message_box(self, *args, **kwargs):
        current_version = kwargs['current_version']
        new_version = kwargs['new_version']
        changes = kwargs['changes']

        updateBox = QMessageBox()
        updateBox.setIcon(QMessageBox.Information)
        updateBox.setText(
            """This new version has no critical changes, so you can choose to download it or not. Check the changelog below!"""
        )
        updateBox.setWindowTitle("New Update Available")
        updateBox.setWindowIcon(QtGui.QIcon('media\\logo\\logo.ico'))

        text = """Version available: {1}\n\n{2}""".format(
            current_version, new_version, changes)
        updateBox.setDetailedText(text)

        updateBox.setEscapeButton(QMessageBox.Close)
        updateBox.addButton(QMessageBox.Close)

        ok = updateBox.addButton(QMessageBox.Ok)
        ok.setText('Update')
        ok.clicked.connect(lambda: webbrowser.open(HOME_PAGE_URL))
        updateBox.exec_()

    def update_message_box(self, update_info):

        if self.call_update_box:
            self.update_timer.stop()
            self.update_timer.deleteLater()

            update = update_info['Update']
            logger.info("Update available: %s" % update)

        else:
            update = False

        if update:
            self.update_available = True

            current_version = update_info['Current Version']
            new_version = update_info['New Version']
            changes = update_info['Changes']
            critical = update_info['Critical']
            logger.info("Update critical: %s" % critical)

            if not critical:

                self.v_label.setText(
                    "v{} (<a href='#'>update to v{}</a>)".format(
                        self.version, new_version))
                self.v_label.mousePressEvent = lambda args: self.call_not_critical_update_message_box(
                    current_version=current_version,
                    new_version=new_version,
                    changes=changes,
                )

                self.v_label_2.setText(
                    "v{} (<a href='#'>update to v{}</a>)".format(
                        self.version, new_version))
                self.v_label_2.mousePressEvent = lambda args: self.call_not_critical_update_message_box(
                    current_version=current_version,
                    new_version=new_version,
                    changes=changes,
                )

            if critical:
                updateBox = QMessageBox()
                updateBox.setIcon(QMessageBox.Warning)
                updateBox.setText(
                    "<strong>Your version is super outdated and is not useful anymore!</strong>"
                )
                updateBox.setInformativeText(
                    """Please click <i>Ok</i> to download the newer one. You can also see the changelog details below! <small>(The critical change is highlighted)</small>"""
                )
                updateBox.setWindowTitle("Unsupported Version")
                updateBox.setWindowIcon(QtGui.QIcon('media\\logo\\logo.ico'))

                text = """Version available: {1}\n\n{2}""".format(
                    current_version, new_version, changes)
                updateBox.setDetailedText(text)

                updateBox.setEscapeButton(QMessageBox.Close)
                updateBox.addButton(QMessageBox.Close)
                self.v_label.setText("v{} (v{} REQUIRED)".format(
                    self.version, new_version))
                self.v_label_2.setText("v{} (v{} REQUIRED)".format(
                    self.version, new_version))

                ok = updateBox.addButton(QMessageBox.Ok)
                ok.clicked.connect(lambda: webbrowser.open(HOME_PAGE_URL))
                updateBox.exec_()
                self.close()

    # Data processes:
    def data_start_action(self):
        # Flag to indicate data collection is running
        self.data_running = True

        self.data_start.setEnabled(False)
        self.data_stop.setEnabled(True)
        self.send_btn.setEnabled(False)
        self.logout_btn.setEnabled(False)
        self.login_btn.setEnabled(False)

        # Indicating user about the key being used:
        self.send_status_label.setText(
            f'Using "{self.used_key}" key. Change it in "Fast Config".')
        self.send_status_label.setStyleSheet("color: #007bff;")
        QTimer.singleShot(3000, self.send_status_label.clear)

        # Icon
        self.icons_label.setMovie(self.dog_getting_up)
        self.dog_getting_up.start()
        self.dog_timer = QTimer()
        self.dog_timer.timeout.connect(self.dog_run)
        self.dog_timer.start(370)

        try:  # this is necessary to make the dog don't go idle if the user clicks start>stop too fast.
            self.dog_timer2.deleteLater()
        except:
            pass  # fight me

        # Thread: __init__
        logger.info("Creating data thread")
        self.thread = QThread()

        logger.info(f"Using: {self.used_key}")

        if self.used_key.upper() == "LEFT-CLICK":
            self.worker = SaveData(0x01)
        else:
            self.worker = SaveData(self.used_key)

        self.stop_signal.connect(
            self.worker.stop)  # connect stop signal to worker stop method
        self.worker.moveToThread(self.thread)

        self.worker.finished.connect(
            self.thread.quit
        )  # connect the workers finished signal to stop thread
        self.worker.finished.connect(
            self.worker.deleteLater
        )  # connect the workers finished signal to clean up worker
        self.thread.finished.connect(
            self.thread.deleteLater
        )  # connect threads finished signal to clean up thread

        self.thread.started.connect(self.worker.main)
        self.thread.finished.connect(self.worker.stop)

        self.worker.send_data.connect(self.send_data)

        self.thread.start()

    def data_stop_action(self):
        # Flag to indicate data collection is not running
        self.data_running = False

        if hasattr(self, 'bot_running'):
            if not self.bot_running:
                self.logout_btn.setEnabled(True)
                self.login_btn.setEnabled(True)
        else:
            self.logout_btn.setEnabled(True)
            self.login_btn.setEnabled(True)

        self.data_start.setEnabled(True)
        self.data_stop.setEnabled(False)

        if self.online:
            self.send_btn.setEnabled(True)

        logger.info("Data stopped")
        self.stop_signal.emit()  # emit the finished signal on stop

        # Icon
        self.dog_timer.deleteLater()
        self.icons_label.setMovie(self.dog_sitting_down)
        self.dog_sitting_down.start()

        self.dog_timer2 = QTimer()
        self.dog_timer2.timeout.connect(self.dog_go_idle)
        self.dog_timer2.start(370)

    def send_data(self):
        """
        Creates thread to send data and don't stop the execution of the program while it is uploading.
        Every time the button is clicked, it is created a new thread, that is deleted after the upload.
        """

        self.send_btn.setEnabled(False)
        if self.online:
            try:
                logger.info("Starting send data thread")
                self.send_data_thread = QThread()  # Thread criado
                self.send_data_worker = SendData(version=self.version,
                                                 token=self.token,
                                                 username=self.username)
                self.send_data_worker.moveToThread(self.send_data_thread)

                self.send_data_worker.status_code.connect(
                    self.auto_send_response_code_controller)
                self.send_data_worker.status_code.connect(
                    self.score_worker.single_check_online_score)

                self.send_data_worker.status_code.connect(
                    self.send_data_worker.deleteLater
                )  # Finished then deletes thread and worker
                self.send_data_worker.status_code.connect(
                    self.send_data_thread.quit)
                self.send_data_thread.finished.connect(
                    self.send_data_thread.deleteLater)

                self.send_data_thread.started.connect(
                    self.send_data_worker.send_data)

                self.send_data_thread.start()
                logger.info('Send data thread started')

            except Exception as e:
                logger.error("Could not start thread to send data: %s" % e)
                QMessageBox.information(
                    self, "Oops!",
                    "Could not start thread to send data: %s" % e)

        else:
            # Raises the little offline message
            self.auto_send_response_code_controller(-2)

    def auto_send_response_code_controller(self, code):
        if code == 200:
            self.send_status_label.setText("Success! Thank you for helping!")
            self.send_status_label.setStyleSheet("color: #28a745;")
            self.send_btn.setText("Send Data")

        elif code == -1:
            self.send_status_label.setText('Everything was already sent!')
            self.send_status_label.setStyleSheet("color: #dc3545;")
            self.send_btn.setText("Send Data")

        elif code == -2:
            self.send_status_label.setText(
                'Could not connect to server. Session is saved.')
            self.send_status_label.setStyleSheet("color: #ffaf00;")
            self.update_score(waiting=True)
            self.send_btn.setText("Send Data (upload pending)")

        else:
            self.send_status_label.setText("Verify your connection")
            self.send_status_label.setStyleSheet("color: #dc3545;")
            self.update_score(offline=True)

        QTimer.singleShot(5000, self.send_status_label.clear)

        if hasattr(self, 'data_running'):
            if not self.data_running:
                self.send_btn.setEnabled(True)
        else:
            self.send_btn.setEnabled(True)

    # Bot Functions
    def bot_controller(self):
        self.bot_btn_clicks += 1

        if self.bot_btn_clicks == 1:

            # Configuring control variables
            self.bot_running = True

            # Changing labels
            self.bot_btn.setText("Stop")

            # Disabling buttons that could cause problems
            self.logout_btn.setEnabled(False)
            self.login_btn.setEnabled(False)
            self.change_dataset_btn.setEnabled(False)

        else:

            # Configuring control variables
            self.bot_btn_clicks = 0
            self.bot_running = False

            # Changing labels
            self.bot_btn.setText("Start")

            # Enabling buttons
            self.change_dataset_btn.setEnabled(True)

            if hasattr(self, 'data_running'):
                if not self.data_running:
                    self.logout_btn.setEnabled(True)
                    self.login_btn.setEnabled(True)
            else:
                self.logout_btn.setEnabled(True)
                self.login_btn.setEnabled(True)

    # Account functions:
    def login_control(self, results):
        self.auth_done = True

        if "Logged" in results.keys():
            if results['Logged']:
                logger.info("User successfully logged in")

                self.user_has_logged({
                    "Username": results['Username'],
                    "Token": results['Token'],
                    "Session": results['Session']
                })

            else:
                # If user has failed to login, keep calling the function until loading stops, so it does not pop up
                # with the loading screen still on.
                self.accnt_timer = QTimer()
                self.accnt_timer.timeout.connect(self.login_error)
                self.accnt_timer.start(200)

        if "Offline" in results.keys():
            self.online = False
            self.update_score(offline=True)
            logger.warning("Offline")

            self.login_btn.setVisible(False)
            self.logout_btn.setVisible(False)

            self.username_label.mousePressEvent = self.retry_connection
            self.username_label.setText(
                '<a href="#"><span style=" text-decoration: underline; color:#0000ff;">Retry Connection</span></a>'
            )

            self.username_label_2.mousePressEvent = self.retry_connection
            self.username_label_2.setText(
                '<a href="#"><span style=" text-decoration: underline; color:#0000ff;">Retry Connection</span></a>'
            )
            self.wait_counter = 0

            if self.first_time_running:
                welcome_dialog = WelcomeDialog()
                if welcome_dialog.exec_():
                    self.first_time_running = False

    def login_error(self):
        # when the loading has finished, call the accnt manager pop up if the login failed
        if self.call_accnt_box:
            logger.info("Opening account manager")
            self.accnt_timer.stop()
            self.accnt_timer.deleteLater()

            self.login_btn.setVisible(True)
            self.logout_btn.setVisible(False)

            if not self.ignore_login:
                self.accnt_manager = AccountManager()
                self.accnt_manager.user_logged.connect(self.user_has_logged)
                self.accnt_manager.rejected.connect(self.login_rejected)

                self.accnt_manager.exec_()

            else:
                self.username_label.setText("Not logged")
                self.username_label_2.setText("Not logged")
                self.username_label.mousePressEvent = None
                self.username_label_2.mousePressEvent = None

                self.update_score(not_logged=True)

            if self.first_time_running:
                welcome_dialog = WelcomeDialog()
                if welcome_dialog.exec_():
                    self.first_time_running = False

    def login_rejected(self):

        self.username_label.setText("Not logged")
        self.username_label_2.setText("Not logged")
        self.username_label.mousePressEvent = None
        self.username_label_2.mousePressEvent = None

        self.logout_btn.setVisible(False)
        self.login_btn.setVisible(True)
        self.update_score(not_logged=True)

        with open("config.json", 'r') as f:
            output = json.loads(f.read())
            output["Ignore Login Popup"] = True

        with open("config.json", "w") as f:
            json.dump(output, f, indent=2)

    def user_has_logged(self, user_info):
        # When the user has logged in, create a score thread with its user/password to get the online score.
        # Check the online score as soon as possible.
        logger.info("User logged")
        self.username = user_info['Username']
        self.token = user_info['Token']

        # Checking if there is data to be sent
        if os.listdir('Data\\Training Data'):
            self.send_btn.setText("Send data (upload pending)")
        else:
            self.send_btn.setText("Send data")

        self.online = True
        self.username_label.setText(self.username)
        self.username_label_2.setText(self.username)

        self.send_message_btn.setEnabled(True)
        self.send_message_btn.setText("Send cool message")

        self.login_btn.setVisible(False)
        self.logout_btn.setVisible(True)

        # Fixes bug where offline user collecting data could retry connecting to the server, re-enabling the buttons.
        if hasattr(self, 'data_running'):
            if not self.data_running:
                self.send_btn.setEnabled(True)
                self.data_start.setEnabled(True)
        else:
            self.send_btn.setEnabled(True)
            self.data_start.setEnabled(True)

        # Score Thread initialization
        try:
            self.score_thread = QThread()  # Thread criado
            self.score_worker = QuickCheck(token=self.token,
                                           username=self.username)  #
            self.score_worker.moveToThread(self.score_thread)

            # If logout signal is emmitted, delete the worker and quit then delete the thread too
            self.logout_signal.connect(self.score_worker.deleteLater)
            self.logout_signal.connect(self.score_thread.quit)
            self.score_thread.finished.connect(self.score_thread.deleteLater)

            self.score_worker.online_score.connect(
                lambda ol_score: self.update_score(online_score=ol_score))

            self.score_thread.start()
            logger.info("Score thread started")
            self.score_worker.single_check_online_score()

        except Exception as e:
            logger.error("Could not start score thread: %s" % e)
            QMessageBox.information(self, "Oops!",
                                    "Could not start score thread: %s" % e)

    # When user tries to login with the login button at the menu
    def runtime_login(self):
        self.ignore_login = False
        self.login_control({'Logged': False})

    def logout(self):
        # When user logs out, emit a signal that kills the score_thread and score_worker, because the session will change
        # if the user logs in with another account.
        self.logout_signal.emit()
        logger.info("User logged out")

        self.username = None
        self.token = None

        self.username_label.setText("Not logged")
        self.username_label_2.setText("Not logged")

        self.send_btn.setText("Can't send data while offline")
        self.send_btn.setEnabled(False)
        self.send_message_btn.setEnabled(False)

        with open('config.json', 'r') as f:
            output = json.loads(f.read())
            output['User'] = self.username
            output['Token'] = self.token

        with open('config.json', 'w') as f:
            json.dump(output, f, indent=2)

        self.update_score(not_logged=True)
        self.login_control({"Logged": False})

    def closeEvent(self, event):
        stop_time = datetime.datetime.now()
        runtime = (stop_time - start_time).total_seconds()
        logger.info('---------- CLOSED. Runtime: %ss ----------' % runtime)
        event.accept()  #.ignore
Пример #33
0
class DebugWindow(QMainWindow):
    """
    The debug window shows various statistics about Tribler such as performed requests, IPv8 statistics and
    community information.
    """

    resize_event = pyqtSignal()

    def __init__(self, settings, gui_settings, tribler_version):
        self._logger = logging.getLogger(self.__class__.__name__)
        QMainWindow.__init__(self)

        self.core_cpu_plot = None
        self.gui_cpu_plot = None
        self.initialized_cpu_plot = False
        self.cpu_plot_timer = None

        self.core_memory_plot = None
        self.gui_memory_plot = None
        self.initialized_memory_plot = False
        self.memory_plot_timer = None

        self.tribler_version = tribler_version
        self.profiler_enabled = False
        self.toggling_profiler = False

        uic.loadUi(get_ui_file_path('debugwindow.ui'), self)
        self.setWindowTitle("Tribler debug pane")

        connect(self.window().toggle_profiler_button.clicked,
                self.on_toggle_profiler_button_clicked)

        self.window().debug_tab_widget.setCurrentIndex(0)
        self.window().ipv8_tab_widget.setCurrentIndex(0)
        self.window().tunnel_tab_widget.setCurrentIndex(0)
        self.window().dht_tab_widget.setCurrentIndex(0)
        self.window().system_tab_widget.setCurrentIndex(0)
        connect(self.window().debug_tab_widget.currentChanged,
                self.tab_changed)
        connect(self.window().ipv8_tab_widget.currentChanged,
                self.ipv8_tab_changed)
        connect(self.window().communities_tree_widget.itemClicked,
                self.on_community_clicked)
        connect(self.window().tunnel_tab_widget.currentChanged,
                self.tunnel_tab_changed)
        connect(self.window().dht_tab_widget.currentChanged,
                self.dht_tab_changed)
        connect(self.window().events_tree_widget.itemClicked,
                self.on_event_clicked)
        connect(self.window().system_tab_widget.currentChanged,
                self.system_tab_changed)
        self.load_general_tab()

        self.window().open_files_tree_widget.header().setSectionResizeMode(
            0, QHeaderView.Stretch)

        self.window().community_peers_tree_widget.hide()

        # Enable/disable tabs, based on settings
        self.window().debug_tab_widget.setTabEnabled(2, settings is not None)
        self.window().debug_tab_widget.setTabEnabled(
            3, settings and settings['ipv8']['enabled'])
        self.window().system_tab_widget.setTabEnabled(
            3, settings and settings['resource_monitor']['enabled'])
        self.window().system_tab_widget.setTabEnabled(
            4, settings and settings['resource_monitor']['enabled'])

        # Refresh logs
        connect(self.window().log_refresh_button.clicked,
                lambda _: self.load_logs_tab())
        connect(self.window().log_tab_widget.currentChanged,
                lambda index: self.load_logs_tab())

        # IPv8 statistics enabled?
        self.ipv8_statistics_enabled = settings['ipv8']['statistics']

        # Libtorrent tab
        self.init_libtorrent_tab()

        # Channels tab
        connect(self.window().channels_tab_widget.currentChanged,
                self.channels_tab_changed)
        self.window().channels_tab_widget.setCurrentIndex(0)

        # Position to center
        frame_geometry = self.frameGeometry()
        screen = QDesktopWidget().screenNumber(QDesktopWidget().cursor().pos())
        center_point = QDesktopWidget().screenGeometry(screen).center()
        frame_geometry.moveCenter(center_point)
        self.move(frame_geometry.topLeft())

        # Refresh timer
        self.refresh_timer = None
        self.rest_request = None
        self.ipv8_health_widget = None

        # GUI resource monitor
        self.resource_monitor = GuiResourceMonitor()
        self.resource_monitor.start()

        # QT settings
        self.gui_settings = gui_settings

    def hideEvent(self, hide_event):
        self.stop_timer()
        self.hide_ipv8_health_widget()

    def showEvent(self, show_event):
        if self.ipv8_health_widget and self.ipv8_health_widget.isVisible():
            self.ipv8_health_widget.resume()
            TriblerNetworkRequest("ipv8/asyncio/drift",
                                  self.on_ipv8_health_enabled,
                                  data={"enable": True},
                                  method='PUT')

    def run_with_timer(self, call_fn, timeout=DEBUG_PANE_REFRESH_TIMEOUT):
        call_fn()
        self.stop_timer()
        self.refresh_timer = QTimer()
        self.refresh_timer.setSingleShot(True)
        connect(
            self.refresh_timer.timeout,
            lambda _call_fn=call_fn, _timeout=timeout: self.run_with_timer(
                _call_fn, timeout=_timeout),
        )
        self.refresh_timer.start(timeout)

    def stop_timer(self):
        if self.refresh_timer:
            try:
                self.refresh_timer.stop()
                self.refresh_timer.deleteLater()
            except RuntimeError:
                self._logger.error(
                    "Failed to stop refresh timer in Debug pane")

    def init_libtorrent_tab(self):
        self.window().libtorrent_tab_widget.setCurrentIndex(0)
        connect(self.window().libtorrent_tab_widget.currentChanged,
                lambda _: self.load_libtorrent_data(export=False))

        connect(self.window().lt_zero_hop_btn.clicked,
                lambda _: self.load_libtorrent_data(export=False))
        connect(self.window().lt_one_hop_btn.clicked,
                lambda _: self.load_libtorrent_data(export=False))
        connect(self.window().lt_two_hop_btn.clicked,
                lambda _: self.load_libtorrent_data(export=False))
        connect(self.window().lt_three_hop_btn.clicked,
                lambda _: self.load_libtorrent_data(export=False))
        connect(self.window().lt_export_btn.clicked,
                lambda _: self.load_libtorrent_data(export=True))

        self.window().lt_zero_hop_btn.setChecked(True)

    def tab_changed(self, index):
        if index == 0:
            self.load_general_tab()
        elif index == 1:
            self.load_requests_tab()
        elif index == 2:
            self.run_with_timer(self.load_bandwidth_accounting_tab)
        elif index == 3:
            self.ipv8_tab_changed(self.window().ipv8_tab_widget.currentIndex())
        elif index == 4:
            self.tunnel_tab_changed(
                self.window().tunnel_tab_widget.currentIndex())
        elif index == 5:
            self.dht_tab_changed(self.window().dht_tab_widget.currentIndex())
        elif index == 6:
            self.run_with_timer(self.load_events_tab)
        elif index == 7:
            self.system_tab_changed(
                self.window().system_tab_widget.currentIndex())
        elif index == 8:
            self.load_libtorrent_data()
        elif index == 9:
            self.load_logs_tab()
        elif index == 10:
            self.channels_tab_changed(
                self.window().channels_tab_widget.currentIndex())

    def ipv8_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_ipv8_general_tab)
        elif index == 1:
            self.run_with_timer(self.load_ipv8_communities_tab)
        elif index == 2:
            self.run_with_timer(self.load_ipv8_community_details_tab)
        elif index == 3:
            self.run_with_timer(self.load_ipv8_health_monitor)

    def tunnel_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_tunnel_circuits_tab)
        elif index == 1:
            self.run_with_timer(self.load_tunnel_relays_tab)
        elif index == 2:
            self.run_with_timer(self.load_tunnel_exits_tab)
        elif index == 3:
            self.run_with_timer(self.load_tunnel_swarms_tab)
        elif index == 4:
            self.run_with_timer(self.load_tunnel_peers_tab)

    def dht_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_dht_statistics_tab)
        elif index == 1:
            self.run_with_timer(self.load_dht_buckets_tab)

    def system_tab_changed(self, index):
        if index == 0:
            self.load_open_files_tab()
        elif index == 1:
            self.load_open_sockets_tab()
        elif index == 2:
            self.load_threads_tab()
        elif index == 3:
            self.load_cpu_tab()
        elif index == 4:
            self.load_memory_tab()
        elif index == 5:
            self.load_profiler_tab()

    def create_and_add_widget_item(self, key, value, widget):
        item = QTreeWidgetItem(widget)
        item.setText(0, key)
        item.setText(1, f"{value}")
        widget.addTopLevelItem(item)

    def load_general_tab(self):
        TriblerNetworkRequest("statistics/tribler", self.on_tribler_statistics)

    def on_tribler_statistics(self, data):
        if not data:
            return
        data = data["tribler_statistics"]
        self.window().general_tree_widget.clear()
        self.create_and_add_widget_item("Tribler version",
                                        self.tribler_version,
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item(
            "Python version",
            sys.version.replace('\n', ''),
            self.window().general_tree_widget  # to fit in one line
        )
        self.create_and_add_widget_item("Libtorrent version",
                                        libtorrent.version,
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("BEP33 support", has_bep33_support(),
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("", "",
                                        self.window().general_tree_widget)

        self.create_and_add_widget_item("Number of channels",
                                        data["num_channels"],
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("Database size",
                                        format_size(data["db_size"]),
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("Number of known torrents",
                                        data["num_torrents"],
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("", "",
                                        self.window().general_tree_widget)

        disk_usage = psutil.disk_usage('/')
        self.create_and_add_widget_item("Total disk space",
                                        format_size(disk_usage.total),
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("Used disk space",
                                        format_size(disk_usage.used),
                                        self.window().general_tree_widget)
        self.create_and_add_widget_item("Free disk space",
                                        format_size(disk_usage.free),
                                        self.window().general_tree_widget)

        # Show GUI settings
        self.show_gui_settings()

    def show_gui_settings(self):
        # Empty line at the beginning
        self.create_and_add_widget_item("", "",
                                        self.window().general_tree_widget)
        # Heading: GUI Settings
        self.create_and_add_widget_item("GUI Settings:", "",
                                        self.window().general_tree_widget)
        # Location of the settings file
        self.create_and_add_widget_item("Qt file",
                                        self.gui_settings.fileName(),
                                        self.window().general_tree_widget)

        selected_settings = {
            "api_key":
            lambda val: val,
            "api_port":
            lambda val: val,
            "pos":
            lambda val: f"(x : {val.x()} px,  y : {val.y()} px)",
            "size":
            lambda val:
            f"(width : {val.width()} px,  height : {val.height()} px)",
            "ask_download_settings":
            lambda val: val,
            "autocommit_enabled":
            lambda val: val,
            "debug":
            lambda val: val,
            "family_filter":
            lambda val: val,
            "first_discover":
            lambda val: val,
            "use_monochrome_icon":
            lambda val: val,
            "recent_download_locations":
            lambda val:
            [unhexlify(url).decode('utf-8') for url in val.split(",")],
        }

        # List only selected gui settings
        for key in self.gui_settings.allKeys():
            if key in selected_settings:
                value = selected_settings[key](self.gui_settings.value(
                    key, 'N/A'))
                self.create_and_add_widget_item(
                    key, value,
                    self.window().general_tree_widget)

    def load_requests_tab(self):
        self.window().requests_tree_widget.clear()
        for request, status_code in sorted(tribler_performed_requests,
                                           key=lambda rq: rq[0].time):
            endpoint = request.url
            method = request.method
            data = request.raw_data
            timestamp = request.time

            item = QTreeWidgetItem(self.window().requests_tree_widget)
            item.setText(0, f"{method} {repr(endpoint)} {repr(data)}")
            item.setText(1, ("%d" % status_code) if status_code else "unknown")
            item.setText(2, f"{strftime('%H:%M:%S', localtime(timestamp))}")
            self.window().requests_tree_widget.addTopLevelItem(item)

    def load_bandwidth_accounting_tab(self) -> None:
        """
        Initiate a request to the Tribler core to fetch statistics on bandwidth accounting.
        """
        TriblerNetworkRequest("bandwidth/statistics",
                              self.on_bandwidth_statistics)

    def on_bandwidth_statistics(self, data: Dict) -> None:
        """
        We received bandwidth statistics from the core.
        :param data: The bandwidth statistics, in JSON format.
        """
        if not data:
            return
        self.window().bandwidth_tree_widget.clear()
        for key, value in data["statistics"].items():
            self.create_and_add_widget_item(
                key, value,
                self.window().bandwidth_tree_widget)

    def load_ipv8_general_tab(self):
        TriblerNetworkRequest("statistics/ipv8", self.on_ipv8_general_stats)

    def on_ipv8_general_stats(self, data):
        if not data:
            return
        self.window().ipv8_general_tree_widget.clear()
        for key, value in data["ipv8_statistics"].items():
            if key in ('total_up', 'total_down'):
                value = f"{value / (1024.0 * 1024.0):.2f} MB"
            elif key == 'session_uptime':
                value = f"{str(datetime.timedelta(seconds=int(value)))}"
            self.create_and_add_widget_item(
                key, value,
                self.window().ipv8_general_tree_widget)

    def load_ipv8_communities_tab(self):
        TriblerNetworkRequest("ipv8/overlays", self.on_ipv8_community_stats)

    def _colored_peer_count(self, peer_count, max_peers):
        limits = [20, max_peers + 1]
        color = 0xF4D03F if peer_count < limits[0] else (
            0x56F129 if peer_count < limits[1] else 0xF12929)
        return QBrush(QColor(color))

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

        for overlay in data["overlays"]:
            item = None
            item_exists = False

            # Check if this item is already rendered
            for ind in range(
                    self.window().communities_tree_widget.topLevelItemCount()):
                existing_item = self.window(
                ).communities_tree_widget.topLevelItem(ind)
                if existing_item.data(0, Qt.UserRole)["id"] == overlay["id"]:
                    item = existing_item
                    item_exists = True
                    break

            if not item:
                # Create a new one
                item = QTreeWidgetItem(self.window().communities_tree_widget)

            item.setData(0, Qt.UserRole, overlay)
            item.setText(0, overlay["overlay_name"])
            item.setText(1, overlay["id"][:10])
            item.setText(2, overlay["my_peer"][-12:])
            peer_count = len(overlay["peers"])
            item.setText(3, f"{peer_count}")
            item.setForeground(
                3, self._colored_peer_count(peer_count, overlay["max_peers"]))

            if "statistics" in overlay and overlay["statistics"]:
                statistics = overlay["statistics"]
                item.setText(
                    4, f"{statistics['bytes_up'] / (1024.0 * 1024.0):.3f}")
                item.setText(
                    5, f"{statistics['bytes_down'] / (1024.0 * 1024.0):.3f}")
                item.setText(6, f"{statistics['num_up']}")
                item.setText(7, f"{statistics['num_down']}")
                item.setText(8, f"{statistics['diff_time']:.3f}")
            else:
                item.setText(4, "N/A")
                item.setText(5, "N/A")
                item.setText(6, "N/A")
                item.setText(7, "N/A")
                item.setText(8, "N/A")

            if not item_exists:
                self.window().communities_tree_widget.addTopLevelItem(item)
            map(self.window().communities_tree_widget.resizeColumnToContents,
                range(10))

        # Reload the window with peers
        selected_items = self.window().communities_tree_widget.selectedItems()
        if len(selected_items) > 0:
            self.update_community_peers(selected_items[0])

    def on_community_clicked(self, item, _):
        self.window().community_peers_tree_widget.show()
        self.update_community_peers(item)

    def update_community_peers(self, item):
        self.window().community_peers_tree_widget.clear()
        peers_info = item.data(0, Qt.UserRole)["peers"]

        for peer_info in peers_info:
            item = QTreeWidgetItem(self.window().community_peers_tree_widget)
            item.setText(0, peer_info["ip"])
            item.setText(1, f"{peer_info['port']}")
            item.setText(2, peer_info["public_key"])
            self.window().community_peers_tree_widget.addTopLevelItem(item)

    def load_ipv8_community_details_tab(self):
        if self.ipv8_statistics_enabled:
            self.window().ipv8_statistics_error_label.setHidden(True)
            TriblerNetworkRequest("ipv8/overlays/statistics",
                                  self.on_ipv8_community_detail_stats)
        else:
            self.window().ipv8_statistics_error_label.setHidden(False)
            self.window().ipv8_communities_details_widget.setHidden(True)

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

        self.window().ipv8_communities_details_widget.setHidden(False)
        self.window().ipv8_communities_details_widget.clear()
        for overlay in data["statistics"]:
            self.window().ipv8_communities_details_widget.setColumnWidth(
                0, 250)

            for key, stats in overlay.items():
                header_item = QTreeWidgetItem(
                    self.window().ipv8_communities_details_widget)
                header_item.setFirstColumnSpanned(True)
                header_item.setBackground(0, QtGui.QColor('#CCCCCC'))
                header_item.setText(0, key)
                self.window().ipv8_communities_details_widget.addTopLevelItem(
                    header_item)

                for request_id, stat in stats.items():
                    stat_item = QTreeWidgetItem(
                        self.window().ipv8_communities_details_widget)
                    stat_item.setText(0, request_id)
                    stat_item.setText(
                        1, f"{stat['bytes_up'] / (1024.0 * 1024.0):.3f}")
                    stat_item.setText(
                        2, f"{stat['bytes_down'] / (1024.0 * 1024.0):.3f}")
                    stat_item.setText(3, f"{stat['num_up']}")
                    stat_item.setText(4, f"{stat['num_down']}")
                    self.window(
                    ).ipv8_communities_details_widget.addTopLevelItem(
                        stat_item)

    def load_ipv8_health_monitor(self):
        """
        Lazy load and enable the IPv8 core health monitor.
        """
        if self.ipv8_health_widget is None:
            # Add the core monitor widget to the tab widget.
            from PyQt5.QtWidgets import QVBoxLayout

            widget = MonitorWidget()
            layout = QVBoxLayout()
            layout.setContentsMargins(0, 0, 0, 0)
            layout.addWidget(widget)
            self.window().ipv8_health_monitor_widget.setLayout(layout)
            self.window().ipv8_health_monitor_widget.show()
            self.ipv8_health_widget = widget
        else:
            # We already loaded the widget, just resume it.
            self.ipv8_health_widget.resume()
        # Whether the widget is newly loaded or not, start the measurements.
        TriblerNetworkRequest("ipv8/asyncio/drift",
                              self.on_ipv8_health_enabled,
                              data={"enable": True},
                              method='PUT')

    def hide_ipv8_health_widget(self):
        """
        We need to hide the IPv8 health widget, involving two things:

         1. Stop the smooth graphical updates in the widget.
         2. Remove the observer from the IPv8 core.
        """
        if self.ipv8_health_widget is not None and not self.ipv8_health_widget.is_paused:
            self.ipv8_health_widget.pause()
            TriblerNetworkRequest("ipv8/asyncio/drift",
                                  lambda _: None,
                                  data={"enable": False},
                                  method='PUT')

    def on_ipv8_health(self, data):
        """
        Measurements came in, send them to the widget for "plotting".
        """
        if not data or 'measurements' not in data or self.ipv8_health_widget is None:
            return
        self.ipv8_health_widget.set_history(data['measurements'])

    def on_ipv8_health_enabled(self, data):
        """
        The request to enable IPv8 completed.

        Start requesting measurements.
        """
        if not data:
            return
        self.run_with_timer(
            lambda: TriblerNetworkRequest("ipv8/asyncio/drift", self.
                                          on_ipv8_health), 100)

    def add_items_to_tree(self, tree, items, keys):
        tree.clear()
        for item in items:
            widget_item = QTreeWidgetItem(tree)
            for index, key in enumerate(keys):
                if key in ["bytes_up", "bytes_down"]:
                    value = format_size(item[key])
                elif key in ["creation_time", "last_lookup"]:
                    value = str(
                        datetime.timedelta(
                            seconds=int(time() -
                                        item[key]))) if item[key] > 0 else '-'
                else:
                    value = str(item[key])
                widget_item.setText(index, value)
            tree.addTopLevelItem(widget_item)

    def load_tunnel_circuits_tab(self):
        self.window().circuits_tree_widget.setColumnWidth(3, 200)
        TriblerNetworkRequest("ipv8/tunnel/circuits", self.on_tunnel_circuits)

    def on_tunnel_circuits(self, circuits):
        if not circuits:
            return

        for c in circuits["circuits"]:
            c["hops"] = f"{c['goal_hops']} / {c['goal_hops']}"
            c["exit_flags"] = c["exit_flags"] if c["state"] == "READY" else ""

        self.add_items_to_tree(
            self.window().circuits_tree_widget,
            circuits.get("circuits"),
            [
                "circuit_id", "hops", "type", "state", "bytes_up",
                "bytes_down", "creation_time", "exit_flags"
            ],
        )

    def load_tunnel_relays_tab(self):
        TriblerNetworkRequest("ipv8/tunnel/relays", self.on_tunnel_relays)

    def on_tunnel_relays(self, data):
        if data:
            self.add_items_to_tree(
                self.window().relays_tree_widget,
                data["relays"],
                [
                    "circuit_from", "circuit_to", "is_rendezvous", "bytes_up",
                    "bytes_down", "creation_time"
                ],
            )

    def load_tunnel_exits_tab(self):
        TriblerNetworkRequest("ipv8/tunnel/exits", self.on_tunnel_exits)

    def on_tunnel_exits(self, data):
        if data:
            self.add_items_to_tree(
                self.window().exits_tree_widget,
                data["exits"],
                [
                    "circuit_from", "enabled", "bytes_up", "bytes_down",
                    "creation_time"
                ],
            )

    def load_tunnel_swarms_tab(self):
        TriblerNetworkRequest("ipv8/tunnel/swarms", self.on_tunnel_swarms)

    def on_tunnel_swarms(self, data):
        if data:
            self.add_items_to_tree(
                self.window().swarms_tree_widget,
                data.get("swarms"),
                [
                    "info_hash",
                    "num_seeders",
                    "num_connections",
                    "num_connections_incomplete",
                    "seeding",
                    "last_lookup",
                    "bytes_up",
                    "bytes_down",
                ],
            )

    def load_tunnel_peers_tab(self):
        self.window().peers_tree_widget.setColumnWidth(2, 300)
        TriblerNetworkRequest("ipv8/tunnel/peers", self.on_tunnel_peers)

    def on_tunnel_peers(self, data):
        if data:
            self.add_items_to_tree(
                self.window().peers_tree_widget, data.get("peers"),
                ["ip", "port", "mid", "is_key_compatible", "flags"])

    def load_dht_statistics_tab(self):
        TriblerNetworkRequest("ipv8/dht/statistics", self.on_dht_statistics)

    def on_dht_statistics(self, data):
        if not data:
            return
        self.window().dhtstats_tree_widget.clear()
        for key, value in data["statistics"].items():
            self.create_and_add_widget_item(key, value,
                                            self.window().dhtstats_tree_widget)

    def load_dht_buckets_tab(self):
        TriblerNetworkRequest("ipv8/dht/buckets", self.on_dht_buckets)

    def on_dht_buckets(self, data):
        if data:
            for bucket in data["buckets"]:
                bucket["num_peers"] = len(bucket["peers"])
                ts = bucket["last_changed"]
                bucket["last_changed"] = str(
                    datetime.timedelta(seconds=int(time() -
                                                   ts))) if ts > 0 else '-'
            self.add_items_to_tree(
                self.window().buckets_tree_widget,
                data.get("buckets"),
                ["prefix", "last_changed", "num_peers"],
            )

    def on_event_clicked(self, item, _):
        event_dict = item.data(0, Qt.UserRole)
        self.window().event_text_box.setPlainText(json.dumps(event_dict))

    def load_events_tab(self):
        self.window().events_tree_widget.clear()
        for event_dict, timestamp in tribler_received_events:
            item = QTreeWidgetItem(self.window().events_tree_widget)
            item.setData(0, Qt.UserRole, event_dict)
            item.setText(0, f"{event_dict['type']}")
            item.setText(1, f"{strftime('%H:%M:%S', localtime(timestamp))}")
            self.window().events_tree_widget.addTopLevelItem(item)

    def load_open_files_tab(self):
        # Fill the open files (GUI) tree widget
        my_process = psutil.Process()
        self.window().open_files_tree_widget.clear()
        gui_item = QTreeWidgetItem(self.window().open_files_tree_widget)

        try:
            open_files = my_process.open_files()
            gui_item.setText(0, "GUI (%d)" % len(open_files))
            self.window().open_files_tree_widget.addTopLevelItem(gui_item)

            for open_file in open_files:
                item = QTreeWidgetItem()
                item.setText(0, open_file.path)
                item.setText(1, "%d" % open_file.fd)
                gui_item.addChild(item)
        except psutil.AccessDenied as exc:
            gui_item.setText(0, f"Unable to get open files for GUI ({exc})")

        TriblerNetworkRequest("debug/open_files", self.on_core_open_files)

    def on_core_open_files(self, data):
        if not data:
            return
        core_item = QTreeWidgetItem(self.window().open_files_tree_widget)
        core_item.setText(0, "Core (%d)" % len(data["open_files"]))
        self.window().open_files_tree_widget.addTopLevelItem(core_item)

        for open_file in data["open_files"]:
            item = QTreeWidgetItem()
            item.setText(0, open_file["path"])
            item.setText(1, "%d" % open_file["fd"])
            core_item.addChild(item)

    def load_open_sockets_tab(self):
        TriblerNetworkRequest("debug/open_sockets", self.on_core_open_sockets)

    def on_core_open_sockets(self, data):
        if not data:
            return
        self.window().open_sockets_tree_widget.clear()
        self.window().open_sockets_label.setText(
            "Sockets opened by core (%d):" % len(data["open_sockets"]))
        for open_socket in data["open_sockets"]:
            if open_socket["family"] == socket.AF_INET:
                family = "AF_INET"
            elif open_socket["family"] == socket.AF_INET6:
                family = "AF_INET6"
            elif open_socket["family"] == socket.AF_UNIX:
                family = "AF_UNIX"
            else:
                family = "-"

            item = QTreeWidgetItem(self.window().open_sockets_tree_widget)
            item.setText(0, open_socket["laddr"])
            item.setText(1, open_socket["raddr"])
            item.setText(2, family)
            item.setText(
                3, "SOCK_STREAM"
                if open_socket["type"] == socket.SOCK_STREAM else "SOCK_DGRAM")
            item.setText(4, open_socket["status"])
            self.window().open_sockets_tree_widget.addTopLevelItem(item)

    def load_threads_tab(self):
        TriblerNetworkRequest("debug/threads", self.on_core_threads)

    def on_core_threads(self, data):
        if not data:
            return
        self.window().threads_tree_widget.clear()
        for thread_info in data["threads"]:
            thread_item = QTreeWidgetItem(self.window().threads_tree_widget)
            thread_item.setText(0, "%d" % thread_info["thread_id"])
            thread_item.setText(1, thread_info["thread_name"])
            self.window().threads_tree_widget.addTopLevelItem(thread_item)

            for frame in thread_info["frames"]:
                frame_item = QTreeWidgetItem()
                frame_item.setText(2, frame)
                thread_item.addChild(frame_item)

    def load_cpu_tab(self):
        if not self.initialized_cpu_plot:
            self.core_cpu_plot = CPUPlot(self.window().tab_system_cpu,
                                         process='Core')
            self.gui_cpu_plot = CPUPlot(self.window().tab_system_cpu,
                                        process='GUI')

            vlayout = self.window().system_cpu_layout.layout()
            vlayout.addWidget(self.core_cpu_plot)
            vlayout.addWidget(self.gui_cpu_plot)

            self.initialized_cpu_plot = True

        self.refresh_cpu_plot()

        # Start timer
        self.cpu_plot_timer = QTimer()
        connect(self.cpu_plot_timer.timeout, self.load_cpu_tab)
        self.cpu_plot_timer.start(5000)

    def refresh_cpu_plot(self):
        # To update the core CPU graph, call Debug REST API to get the history
        # and update the CPU graph after receiving the response.
        TriblerNetworkRequest("debug/cpu/history", self.on_core_cpu_history)

        # GUI CPU graph can be simply updated using the data from GuiResourceMonitor object.
        self._update_cpu_graph(self.gui_cpu_plot,
                               self.resource_monitor.get_cpu_history_dict())

    def on_core_cpu_history(self, data):
        if not data or "cpu_history" not in data:
            return

        self._update_cpu_graph(self.core_cpu_plot, data['cpu_history'])

    def _update_cpu_graph(self, cpu_graph, history_data):
        cpu_graph.reset_plot()
        for cpu_info in history_data:
            process_cpu = [round(cpu_info["cpu"], 2)]
            cpu_graph.add_data(cpu_info["time"], process_cpu)
        cpu_graph.render_plot()

    def load_memory_tab(self):
        if not self.initialized_memory_plot:
            self.core_memory_plot = MemoryPlot(self.window().tab_system_memory,
                                               process='Core')
            self.gui_memory_plot = MemoryPlot(self.window().tab_system_memory,
                                              process='GUI')

            vlayout = self.window().system_memory_layout.layout()
            vlayout.addWidget(self.core_memory_plot)
            vlayout.addWidget(self.gui_memory_plot)

            self.initialized_memory_plot = True

        self.refresh_memory_plot()

        # Start timer
        self.memory_plot_timer = QTimer()
        connect(self.memory_plot_timer.timeout, self.load_memory_tab)
        self.memory_plot_timer.start(5000)

    def load_profiler_tab(self):
        self.window().toggle_profiler_button.setEnabled(False)
        TriblerNetworkRequest("debug/profiler", self.on_profiler_info)

    def on_profiler_info(self, data):
        if not data:
            return
        self.window().toggle_profiler_button.setEnabled(True)
        self.profiler_enabled = data["state"] == "STARTED"
        self.window().toggle_profiler_button.setText(
            f"{'Stop' if self.profiler_enabled else 'Start'} profiler")

    def on_toggle_profiler_button_clicked(self, checked=False):
        if self.toggling_profiler:
            return

        self.toggling_profiler = True
        self.window().toggle_profiler_button.setEnabled(False)
        method = "DELETE" if self.profiler_enabled else "PUT"
        TriblerNetworkRequest("debug/profiler",
                              self.on_profiler_state_changed,
                              method=method)

    def on_profiler_state_changed(self, data):
        if not data:
            return
        self.toggling_profiler = False
        self.window().toggle_profiler_button.setEnabled(True)
        self.load_profiler_tab()

        if 'profiler_file' in data:
            QMessageBox.about(
                self, "Profiler statistics saved",
                f"The profiler data has been saved to {data['profiler_file']}."
            )

    def refresh_memory_plot(self):
        # To update the core memory graph, call Debug REST API to get the history
        # and update the memory graph after receiving the response.
        TriblerNetworkRequest("debug/memory/history",
                              self.on_core_memory_history)

        # GUI memory graph can be simply updated using the data from GuiResourceMonitor object.
        self._update_memory_graph(
            self.gui_memory_plot,
            self.resource_monitor.get_memory_history_dict())

    def on_core_memory_history(self, data):
        if not data or data.get("memory_history") is None:
            return
        self._update_memory_graph(self.core_memory_plot,
                                  data["memory_history"])

    def _update_memory_graph(self, memory_graph, history_data):
        memory_graph.reset_plot()
        for mem_info in history_data:
            process_memory = round(mem_info["mem"] / MB, 2)
            memory_graph.add_data(mem_info["time"], [process_memory])
        memory_graph.render_plot()

    def closeEvent(self, close_event):
        if self.rest_request:
            self.rest_request.cancel_request()
        if self.cpu_plot_timer:
            self.cpu_plot_timer.stop()

        if self.memory_plot_timer:
            self.memory_plot_timer.stop()

    def load_logs_tab(self):
        # Max lines from GUI
        max_log_lines = self.window().max_lines_value.text()

        tab_index = self.window().log_tab_widget.currentIndex()
        tab_name = "core" if tab_index == 0 else "gui"

        request_query = f"process={tab_name}&max_lines={max_log_lines}"
        TriblerNetworkRequest(f"debug/log?{request_query}", self.display_logs)

    def display_logs(self, data):
        if not data:
            return
        tab_index = self.window().log_tab_widget.currentIndex()
        log_display_widget = (self.window().core_log_display_area if tab_index
                              == 0 else self.window().gui_log_display_area)

        log_display_widget.moveCursor(QTextCursor.End)

        key_content = 'content'
        key_max_lines = 'max_lines'

        if not key_content in data or not data[key_content]:
            log_display_widget.setPlainText('No logs found')
        else:
            log_display_widget.setPlainText(data[key_content])

        if not key_max_lines in data or not data[key_max_lines]:
            self.window().max_lines_value.setText('')
        else:
            self.window().max_lines_value.setText(str(data[key_max_lines]))

        sb = log_display_widget.verticalScrollBar()
        sb.setValue(sb.maximum())

    def show(self):
        super().show()

        # this will remove minimized status
        # and restore window with keeping maximized/normal state
        self.window().setWindowState(self.window().windowState()
                                     & ~Qt.WindowMinimized | Qt.WindowActive)
        self.window().activateWindow()

    def load_libtorrent_data(self, export=False):
        tab = self.window().libtorrent_tab_widget.currentIndex()
        hop = (0 if self.window().lt_zero_hop_btn.isChecked() else
               1 if self.window().lt_one_hop_btn.isChecked() else
               2 if self.window().lt_two_hop_btn.isChecked() else 3)
        if tab == 0:
            self.load_libtorrent_settings_tab(hop, export=export)
        elif tab == 1:
            self.load_libtorrent_sessions_tab(hop, export=export)

    def load_libtorrent_settings_tab(self, hop, export=False):
        TriblerNetworkRequest(
            "libtorrent/settings?hop=%d" % hop,
            lambda data: self.on_libtorrent_settings_received(data,
                                                              export=export))
        self.window().libtorrent_settings_tree_widget.clear()

    def on_libtorrent_settings_received(self, data, export=False):
        if not data:
            return
        for key, value in data["settings"].items():
            item = QTreeWidgetItem(
                self.window().libtorrent_settings_tree_widget)
            item.setText(0, key)
            item.setText(1, str(value))
            self.window().libtorrent_settings_tree_widget.addTopLevelItem(item)
        if export:
            self.save_to_file("libtorrent_settings.json", data)

    def load_libtorrent_sessions_tab(self, hop, export=False):
        TriblerNetworkRequest(
            "libtorrent/session?hop=%d" % hop,
            lambda data: self.on_libtorrent_session_received(data,
                                                             export=export))
        self.window().libtorrent_session_tree_widget.clear()

    def on_libtorrent_session_received(self, data, export=False):
        if not data:
            return
        for key, value in data["session"].items():
            item = QTreeWidgetItem(
                self.window().libtorrent_session_tree_widget)
            item.setText(0, key)
            item.setText(1, str(value))
            self.window().libtorrent_session_tree_widget.addTopLevelItem(item)
        if export:
            self.save_to_file("libtorrent_session.json", data)

    def save_to_file(self, filename, data):
        base_dir = QFileDialog.getExistingDirectory(
            self, "Select an export directory", "", QFileDialog.ShowDirsOnly)
        if len(base_dir) > 0:
            dest_path = os.path.join(base_dir, filename)
            try:
                with open(dest_path, "w") as torrent_file:
                    torrent_file.write(json.dumps(data))
            except OSError as exc:
                ConfirmationDialog.show_error(self.window(),
                                              "Error exporting file", str(exc))

    def on_channels_peers(self, data):
        widget = self.window().channels_peers_tree_widget
        widget.clear()
        if not data:
            return

        for c in data["channels_list"]:
            channel_item = QTreeWidgetItem()
            channel_item.setText(0, str(c["channel_name"]))
            channel_item.setText(1, str(c["channel_pk"]))
            channel_item.setText(2, str(c["channel_id"]))
            channel_item.setData(3, Qt.DisplayRole,
                                 len(c["peers"]))  #  Peers count
            for p in c["peers"]:
                peer_item = QTreeWidgetItem()
                peer_item.setText(1, str(p[0]))  # Peer mid
                peer_item.setData(4, Qt.DisplayRole, p[1])  # Peer age
                channel_item.addChild(peer_item)
            widget.addTopLevelItem(channel_item)

    def load_channels_peers_tab(self):
        TriblerNetworkRequest("remote_query/channels_peers",
                              self.on_channels_peers)

    def channels_tab_changed(self, index):
        if index == 0:
            self.run_with_timer(self.load_channels_peers_tab)
        elif index == 1:
            pass