示例#1
0
class Chart(QWidget):
    def __init__(self, chartKey, data, frame, parent=None):
        super(Chart, self).__init__(parent)
        self.frame = frame
        self.data = data
        self.create_chart(chartKey)

    def create_chart(self, chartKey):
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)
        self.chart = QChart()

        #Add series to the chart
        self.addSeries(chartKey)

        # for the background and title
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("Code Size Visualizer")
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignRight)
        self.chart.setTheme(QChart.ChartThemeBlueCerulean)

        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)

    #each section of the pie chart
    def addSeries(self, key):
        self.chart.removeAllSeries()
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)

        #Show chartview only if the content length is less than 6. Otherwise show a table view
        if len(self.data[key]) < 6:
            #print('length',self.data, key)
            for key, value in self.data[key].items():
                print('key, value', key, value)
                slice_ = QPieSlice(str(key), value)
                self.series.append(slice_)

            self.series.setLabelsVisible()
            self.series.setLabelsPosition(QPieSlice.LabelInsideHorizontal)

            for slice in self.series.slices():
                #slice.setLabel(slice.label())
                slice.setLabel(slice.label() + ' - ' + str(slice.value()) +
                               ' B ')

            self.chart.addSeries(self.series)
            self.frame.frame.hide()
            self.chart.show()
        else:
            self.table = TableView(self.data[key], len(self.data[key]), 1)

            if self.frame.ly.count() > 0:
                self.frame.ly.itemAt(0).widget().setParent(None)

            self.frame.ly.addWidget(self.table)

            self.frame.frame.show()
            self.chart.hide()
示例#2
0
class ErrorLineChart(QFrame):
    def __init__(self, nseries=1, series_names=None):
        super().__init__()
        if nseries < 1:
            raise ValueError(
                'The number of serieses must be larger than zero.')
        self.nseries = nseries
        self.series_names = series_names
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        self.setMinimumHeight(110)
        self.setMinimumWidth(400)

        self.serieses = [QLineSeries() for _ in range(self.nseries)]
        self.chart = QChart()
        if self.series_names is None:
            self.chart.legend().hide()
        for idx, series in enumerate(self.serieses):
            self.chart.addSeries(series)
            if self.series_names is not None:
                series.setName(self.series_names[idx])
        self.chart.createDefaultAxes()
        self.chart.layout().setContentsMargins(0, 0, 0, 0)
        # self.chart.setTheme(QChart.ChartThemeDark)
        self.chart.axisY().setTickCount(3)
        chart_view = QChartView(self.chart)
        chart_view.setRenderHint(QPainter.Antialiasing)
        layout.addWidget(chart_view)

        self.x_max = 2
        self.y_pts = list()

    def append_point(self, x, y, series_idx=0):
        self.serieses[series_idx].append(x, y)
        self.x_max = max(x, self.x_max)
        self.y_pts.append(y)
        if self.x_max > 100:
            self.chart.axisX().setRange(self.x_max - 100, self.x_max)
            y_max = max(self.y_pts[-100:])
            self.serieses[series_idx].remove(self.x_max - 100,
                                             self.y_pts[self.x_max - 101])
        else:
            self.chart.axisX().setRange(1, self.x_max)
            y_max = max(self.y_pts)
        self.chart.axisY().setRange(0, y_max + y_max / 5)

    def clear(self):
        self.chart.removeAllSeries()
        self.serieses = [QLineSeries() for _ in range(self.nseries)]
        for idx, series in enumerate(self.serieses):
            self.chart.addSeries(series)
            if self.series_names is not None:
                series.setName(self.series_names[idx])
        self.chart.createDefaultAxes()
        self.chart.axisY().setTickCount(3)
        self.x_max = 2
        self.y_pts = list()
示例#3
0
class Chart(QWidget):
    def __init__(self, chartKey, parent=None):
        super(Chart, self).__init__(parent)
        self.create_chart(chartKey)
      
        
    def create_chart(self, chartKey):
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)
        self.chart = QChart()
        
        #Add series to the chart
        self.addSeries(chartKey)

	# for the background and title
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("DonutChart Example")
        self.chart.setTheme(QChart.ChartThemeBlueCerulean)

        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)
       
        
        
    def addSeries(self, key):
        self.chart.removeAllSeries()
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)
            
        for key, value in sampleData[key].items():
            print("adding series", str(key), value)
            slice_ = QPieSlice(str(key), value)
            self.series.append(slice_)
       
        self.chart.addSeries(self.series)
        self.series.doubleClicked.connect(self.handle_double_clicked)
             
        
          
    #Show the update chart with the distribution of the selected slice
    def handle_double_clicked(self, slice):
        slice.setExploded()
        slice.setLabelVisible()
     
        if slice.label() in sampleData.keys():
            print("slice",slice.label());
            self.addSeries(slice.label())
示例#4
0
class Chart(QWidget):
    def __init__(self, chartKey, parent=None):
        super(Chart, self).__init__(parent)
        self.create_chart(chartKey, 0)
      
        
    def create_chart(self, chartKey, replace):
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)
        self.chart = QChart()
        
        #Add series to the chart
        self.addSeries(chartKey)

	# for the background and title
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("DonutChart Example")
        self.chart.setTheme(QChart.ChartThemeBlueCerulean)

        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)
       
        
        
    def addSeries(self, key):
        self.chart.removeAllSeries()
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)
        print('chart',key)
            
        for key, value in sampleData[key].items():
            #print("adding series", str(key), value)
            slice_ = QPieSlice(str(key), value)
            self.series.append(slice_)
       
        self.chart.addSeries(self.series)
示例#5
0
class VentanaBenchmark(QtWidgets.QMainWindow):
    def __init__(self, lista_algoritmos, ajustes, entorno, controlador):
        super().__init__()
        self.setWindowIcon(QtGui.QIcon('icon-crop.png'))
        uic.loadUi('ventana_benchmark.ui', self)

        self.lista_algoritmos = lista_algoritmos
        self.entorno = entorno
        self.controlador = controlador

        tupla_algoritmos = tuple(lista_algoritmos)
        eje_x = QBarCategoryAxis()
        eje_x.append(tupla_algoritmos)
        self.eje_y = QLogValueAxis()
        self.eje_y.setRange(0, 100)
        pen = QtGui.QPen()
        pen.setStyle(Qt.DashLine)
        self.eje_y.setGridLinePen(pen)
        self.eje_y.setMinorTickCount(10)
        self.eje_y.setBase(10)
        self.eje_y.setLabelFormat("%g")
        self.eje_y.setTitleText("Número de episodios")

        self.grafico = QChart()
        #self.grafico.addSeries(series)
        self.grafico.setAnimationOptions(QChart.NoAnimation)
        self.grafico.addAxis(eje_x, Qt.AlignBottom)
        self.grafico.addAxis(self.eje_y, Qt.AlignLeft)  # TODO no se muestra
        self.set_ajustes(ajustes, False)
        self.grafico.legend().setVisible(True)
        self.grafico.legend().setAlignment(Qt.AlignTop)
        self.__init_datos()

    def set_ajustes(self, ajustes, actualizar_grafico=True):
        n_ejecuciones = ajustes[utils.AJUSTES_PARAM_N_EJECUCIONES]
        self.formatear_titulo_gafico(n_ejecuciones)
        self.modo = ajustes[utils.AJUSTES_PARAM_MODO_BENCHMARK]
        if actualizar_grafico:
            self.actualizar_grafico()

    def init_grafico(self):
        self.vista_grafico.setChart(self.grafico)

    def actualizar_grafico(self, algoritmo=None, nuevo_dato=None, clear=True):
        """Añade a la barra de algoritmo el nuevo dato"""
        if algoritmo is not None and nuevo_dato is not None:
            self.datos[algoritmo].append(nuevo_dato)
        if clear:
            self.grafico.removeAllSeries()

        if self.modo == utils.AJUSTES_BENCHMARK_MODO_BARRAS:
            self.__actualizar_grafico_barras()
        else:
            self.__actualizar_grafico_cajas()

    def __actualizar_grafico_barras(self):
        self.grafico.legend().setVisible(True)

        medias = [
            math.floor(np.mean(datos)) if len(datos) > 0 else 0
            for datos in self.datos.values()
        ]
        mejores = [
            np.min(datos) if len(datos) > 0 else 0
            for datos in self.datos.values()
        ]
        peores = [
            np.max(datos) if len(datos) > 0 else 0
            for datos in self.datos.values()
        ]
        self.eje_y.setRange(1, max(max(medias), max(peores)))

        barset_media = QBarSet('Media')
        barset_media.append(medias)
        barset_mejor = QBarSet('Mejor')
        barset_mejor.append(mejores)
        barset_peor = QBarSet('Peor')
        barset_peor.append(peores)
        series = QBarSeries()
        series.append(barset_media)
        series.append(barset_mejor)
        series.append(barset_peor)
        series.setLabelsVisible(True)
        self.grafico.addSeries(series)
        series.attachAxis(self.eje_y)
        self.init_grafico()

    def __actualizar_grafico_cajas(self):
        self.grafico.legend().setVisible(False)
        series = QBoxPlotSeries()
        maximo = 0
        minimo = np.inf
        for alg in self.lista_algoritmos:
            eg = QBoxSet()
            if len(self.datos[alg]) > 0:
                ma = np.max(self.datos[alg])
                mi = np.min(self.datos[alg])
                q1 = np.quantile(self.datos[alg], 0.25)
                q3 = np.quantile(self.datos[alg], 0.75)
                iqr = q3 - q1
                low = max(q1 - 1.5 * iqr, mi)
                high = min(q3 + 1.5 * iqr, ma)
                if high >= maximo:
                    maximo = high
                if low <= minimo:
                    minimo = low
                eg.setValue(QBoxSet.LowerExtreme, low)
                eg.setValue(QBoxSet.UpperExtreme, high)
                eg.setValue(QBoxSet.Median, np.median(self.datos[alg]))
                eg.setValue(QBoxSet.LowerQuartile, q3)
                eg.setValue(QBoxSet.UpperQuartile, q1)
            else:
                eg.setValue(QBoxSet.LowerExtreme, 1)
                eg.setValue(QBoxSet.UpperExtreme, 1)
                eg.setValue(QBoxSet.Median, 1)
                eg.setValue(QBoxSet.LowerQuartile, 1)
                eg.setValue(QBoxSet.UpperQuartile, 1)
            series.append(eg)
        self.eje_y.setRange(max(1, minimo), maximo)
        self.grafico.addSeries(series)
        series.attachAxis(self.eje_y)
        self.init_grafico()

    def limpiar_grafico(self):
        self.grafico.removeAllSeries()
        self.init_grafico()
        self.__init_datos()

    def __init_datos(self):
        self.datos = dict([])
        for alg in self.lista_algoritmos:
            self.datos[alg] = []

    def closeEvent(self, event: QtGui.QCloseEvent) -> None:
        self.controlador.deshabilitar_todo(
            False
        )  # Antes de cerrar la ventana habilitamos los botones de ventana princ
        self.controlador.cerrar_benchmark()
        event.accept()

    def formatear_titulo_gafico(self, n_ejecuciones):
        self.grafico.setTitle("Episodios hasta el fin del entrenamiento (" +
                              str(n_ejecuciones) + " ejecuciones)")
示例#6
0
class Chart(QtWidgets.QWidget):
    def __init__(self,chartKey, frame, parent=None):
        super(Chart, self).__init__(parent, QtCore.Qt.Window)  
        self.frame = frame
        self.create_chart(chartKey)
        
        
    @QtCore.pyqtSlot()
    def create_chart(self, chartKey):
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)
        self.chart = QChart()
        
        print('inside chart',self.frame)
        
        #Add series to the chart
        self.addSeries(chartKey)

	# for the background and title
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("DonutChart Example")
        self.chart.setTheme(QChart.ChartThemeBlueCerulean)

        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)
        
        
       
        
        
    def addSeries(self, key):
        self.chart.removeAllSeries()
        self.series = QPieSeries()
        print(self.series)
        self.series.setHoleSize(0.35)
        print('chart',key)
        
        if len(sampleData[key]) == 2:
            for key, value in sampleData[key].items():
                #print("adding series", str(key), value)
                slice_ = QPieSlice(str(key), value)
                self.series.append(slice_)
       
            self.chart.addSeries(self.series)
            #self.frame.frame.hide()
            
            #self.frame.frame.removeWidget(self.table)
            
            self.frame.frame.hide()
            self.chart.show()
        else:
            print('hi')
            
            self.table = TableView(data, 5, 4)
            
            
            if self.frame.ly.count() == 0:
                self.frame.ly.addWidget(self.table)
            
            self.frame.frame.show()
            self.chart.hide()
            #print(frame)
            print('parent', self.parent())
class Interface(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(Interface, self).__init__()
        self.__dataGenerator = None
        self.__wid = QWidget(self)
        self.setCentralWidget(self.__wid)
        self.__layout = QGridLayout()
        self.__layout.setSpacing(5)
        self.__axisx = QValueAxis()
        self.__axisx.setRange(0.0, 100.0)
        self.__axisy = QValueAxis()
        self.__values = list()
        self.__counter = 0
        self.__data_iterator = None
        self.time_ms = 0
        self.timer = QTimer(self)
        self.timerInterval = 1000
        self.timer.setInterval(self.timerInterval)
        self.timer.timeout.connect(self.run_simulation)
        self.initUI()

    def init_values(self):
        self.__counter = 0
        self.__data_iterator = self.__dataGenerator.get_values(100)
        self.time_ms = 0

    def on_tick(self):
        try:
            values = next(self.__data_iterator)
            self.__values.append(values)
        except StopIteration:
            self.timer.stop()

        self.__writeLog()
        self.__drawParetoChart()
        self.__drawComparisonChart()

    def __setWindowProperties(self, parent):
        self.setWindowTitle("Title")
        self.setGeometry(100, 60, 1000, 600)

    def __createOptimisationChartGroupBox(self):
        groupBox = QGroupBox("Множество Парето")
        layout = QGridLayout()
        layout.setSpacing(0)

        self.__pareto_chart = QChart()
        self.__pareto_chart_series = []
        view = QChartView(self.__pareto_chart)
        layout.addWidget(view)
        groupBox.setLayout(layout)
        return groupBox

    def __createButtonsGroupBox(self):
        groupBox = QGroupBox("Кнопки")
        layout = QGridLayout()
        layout.setSpacing(5)
        self.__btn_start = QPushButton("Запуск", self)
        self.__btn_stop = QPushButton("Остановка", self)
        layout.addWidget(self.__btn_start, 1, 1, 1, 3)
        layout.addWidget(self.__btn_stop, 1, 4, 1, 3)
        groupBox.setLayout(layout)
        return groupBox

    def __createQueryParametersGroupBox(self):
        groupBox = QGroupBox("Параметры запросов")
        layout = QGridLayout()
        layout.setSpacing(5)
        label_query_count = QLabel("Количество запросов: ")
        self.spinbox_query_count = QSpinBox()
        self.spinbox_query_count.setRange(100, 1000)
        self.spinbox_query_count.setSingleStep(100)
        label_update_frequency = QLabel("Частота обновления (мсек): ")
        self.spinbox_update_frequency = QSpinBox()
        self.spinbox_update_frequency.setRange(100, 300)
        self.spinbox_update_frequency.setSingleStep(100)
        layout.addWidget(label_query_count, 1, 1, 1, 1)
        layout.addWidget(self.spinbox_query_count, 1, 2, 1, 3)
        layout.addWidget(label_update_frequency, 2, 1, 1, 1)
        layout.addWidget(self.spinbox_update_frequency, 2, 2, 1, 3)
        groupBox.setLayout(layout)
        return groupBox

    def __createLogGroupBox(self):
        groupBox = QGroupBox("Замеры времени")
        self.__plainTextEdit_time_logs = QPlainTextEdit("")
        vbox = QVBoxLayout()
        vbox.addWidget(self.__plainTextEdit_time_logs)
        vbox.addStretch(1)
        groupBox.setLayout(vbox)
        return groupBox

    def __createComparisonChartGroupBox(self):
        groupBox = QGroupBox("Сравнительный график")
        layout = QGridLayout()
        layout.setSpacing(0)
        self.__comparison_chart = QChart()
        self.__comparison_chart_series = []
        self.__comparison_view = QChartView(self.__comparison_chart)
        layout.addWidget(self.__comparison_view)
        groupBox.setLayout(layout)
        return groupBox

    def __start_btn_clicked(self):
        self.__drawParetoChart()
        self.interval = int(self.spinbox_query_count.value())
        self.timerInterval = int(self.spinbox_update_frequency.value())
        self.__dataGenerator = DataGenerator(self.timerInterval * 10)
        self.init_values()
        self.timer.start(self.timerInterval)

    def run_simulation(self):
        self.time_ms += self.timerInterval
        self.on_tick()

    def __stop_btn_clicked(self):
        self.timer.stop()

    def __drawParetoChart(self):
        def make_noise(value, noise_size):
            return value + (noise_size / -2 + noise_size * random.random())

        self.__pareto_chart.removeAllSeries()

        series1 = QScatterSeries()
        series1.setMarkerShape(QScatterSeries.MarkerShapeCircle)
        series1.setMarkerSize(5)
        series1.append(make_noise(23, 2), make_noise(25, 2))
        series1.setBrush(QColor(Qt.red))
        self.__pareto_chart.addSeries(series1)
        self.__axisy.setRange(0.0, 100.0)

        series3 = QScatterSeries()
        series3.setName("Точка утопии")
        series3.setMarkerShape(QScatterSeries.MarkerShapeCircle)
        series3.setMarkerSize(10)
        series3.append(make_noise(2, 0.5), make_noise(23, 2))
        self.__pareto_chart.addSeries(series3)

        series2 = QScatterSeries()
        series2.setName("Оптимальный")
        series2.setMarkerShape(QScatterSeries.MarkerShapeCircle)
        series2.setMarkerSize(7)
        series2.append(make_noise(2, 0.5), make_noise(45, 4))
        self.__pareto_chart.addSeries(series2)

        self.__pareto_chart.setAxisX(self.__axisx, series1)
        self.__pareto_chart.setAxisY(self.__axisy, series1)
        self.__pareto_chart.setAxisX(self.__axisx, series2)
        self.__pareto_chart.setAxisY(self.__axisy, series2)
        self.__pareto_chart.setAxisX(self.__axisx, series3)
        self.__pareto_chart.setAxisY(self.__axisy, series3)

    def __writeLog(self):
        self.__counter += 1
        self.__plainTextEdit_time_logs.moveCursor(QTextCursor.End)
        time_string = ("[%d:%d]" %
                       (self.time_ms / 1000, self.time_ms % 1000 / 100))
        try:
            optimal = self.__values[-1][2] - self.__values[-2][2]
            other = self.__values[-1][1] - self.__values[-2][1]
        except IndexError:
            optimal = 0
            other = 0
        for i in range(self.__counter):
            self.__plainTextEdit_time_logs.insertPlainText(
                '{0} {1:20} {2:1.4} \n'.format(time_string, 'Оптимальный:',
                                               float(optimal)))
            self.__plainTextEdit_time_logs.insertPlainText(
                '{0} {1:20} {2:1.4} \n'.format(time_string, 'Другой:',
                                               float(other)))
        self.__plainTextEdit_time_logs.moveCursor(QTextCursor.End)

    def __drawComparisonChart(self):
        self.__comparison_chart.removeAllSeries()
        series1 = QLineSeries(self)
        series2 = QLineSeries(self)
        series1.setName("Оптимальный")
        series2.setName("Другой")
        [(series1.append(i[0], i[1]), series2.append(i[0], i[2]))
         for i in self.__values]
        self.__comparison_chart.addSeries(series1)
        self.__comparison_chart.addSeries(series2)

        self.__comparison_chart.createDefaultAxes()

    def initUI(self):
        self.__layout.addWidget(self.__createOptimisationChartGroupBox(), 1, 1,
                                8, 5)
        self.__layout.addWidget(self.__createLogGroupBox(), 9, 1, 2, 5)
        self.__layout.addWidget(self.__createButtonsGroupBox(), 1, 6, 1, 5)
        self.__layout.addWidget(self.__createQueryParametersGroupBox(), 2, 6,
                                2, 5)
        self.__layout.addWidget(self.__createComparisonChartGroupBox(), 4, 6,
                                7, 5)
        self.__wid.setLayout(self.__layout)
        self.__btn_start.clicked.connect(self.__start_btn_clicked)
        self.__btn_stop.clicked.connect(self.__stop_btn_clicked)
        self.__setWindowProperties(self)
        self.show()

    def closeEvent(self, event):  # событие закрытия окна
        reply = QMessageBox.question(self, 'Выход',
                                     "Вы уверены, что хотите выйти?",
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def showWarning(self, message):
        q = QMessageBox()
        q.setIcon(QMessageBox.Warning)
        q.setText(message)
        q.setWindowTitle("Ошибка")
        q.setStandardButtons(QMessageBox.Ok)
        q.exec_()
示例#8
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)

        self.resopt = ResOperator()
        self.chart = QChart()
        self.chart.setTheme(QChart.ChartThemeQt)
        self.chart.setTitle("文件类型统计")
        self.chartView.setChart(self.chart)
        self.progressBar.hide()

        self.collectSrcThread = None
        self.calDestThread = None
        self.copyThread = None

        self.collectSrcTask = None
        self.calDestTask = None
        self.copyTask = None

    @pyqtSlot()
    def show(self):
        super().show()
        print('show')

    # 在线程中已完成了文件的收集,在这里更新UI
    @pyqtSlot()
    def on_collect_finished(self):
        # 输出后缀统计扇形图
        suffix_list = self.resopt.get_suffix_list(5)
        all = self.resopt.count_all()
        self.chart.removeAllSeries()
        series = QPieSeries()
        for (suffix, count) in suffix_list:
            series.append(suffix, count)
            all -= count
        if all > 0:
            series.append('others', all)
        series.setLabelsVisible(True)
        self.chart.addSeries(series)
        # 设置按键和进度条
        self.collectPushButton.setEnabled(True)
        self.progressBar.hide()

    @pyqtSlot()
    def on_copy_finished(self):
        self.progressLabel.setText("完成复制")

    @pyqtSlot()
    def on_make_dest_finished(self):
        self.processPushButton.setEnabled(True)

    # 正在生成目标文件路径
    @pyqtSlot(int, str)
    def on_make_dest_running(self, count, path):
        self.progressBar.setValue(count)
        self.progressLabel.setText("计算目标路径:" + path)

    # 正在复制文件
    def on_copy_running(self, count, path):
        self.progressBar.setValue(count)
        self.progressLabel.setText("复制文件:" + path)

    # 选择源路径
    @pyqtSlot()
    def on_srcPushButton_clicked(self):
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.DirectoryOnly)
        dialog.setViewMode(QFileDialog.Detail)
        if dialog.exec_():
            self.srcEdit.setText(dialog.selectedFiles()[0])

    # 选择目标路径
    @pyqtSlot()
    def on_destPushButton_clicked(self):
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.DirectoryOnly)
        dialog.setViewMode(QFileDialog.Detail)
        if dialog.exec_():
            self.destEdit.setText(dialog.selectedFiles()[0])

    # 开始收集源路径中的文件
    @pyqtSlot()
    def on_collectPushButton_clicked(self):
        # 设置UI
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.show()
        self.collectPushButton.setDisabled(True)
        # 创建任务
        self.collectSrcTask = CollectSourceTask(self.srcEdit.text())
        # 将任务移入线程
        self.collectSrcThread = QThread()
        self.collectSrcTask.moveToThread(self.collectSrcThread)
        # 线程的started信号接入任务的doWork槽
        self.collectSrcThread.started.connect(self.collectSrcTask.doWork)
        # 任务完成信号(done)接入线程的quit槽
        self.collectSrcTask.done.connect(self.collectSrcThread.quit)
        # 线程完成后,更新ui
        self.collectSrcThread.finished.connect(self.on_collect_finished)
        # 启动
        self.collectSrcThread.start()

        # 根据收集的结果,开始处理文件

    @pyqtSlot()
    def on_processPushButton_clicked(self):
        count = self.resopt.count_all_unread()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(count)
        self.progressBar.show()
        self.processPushButton.setDisabled(True)
        if self.destEdit.text() is not '':
            self.calDestTask = CalculateDestinationTask(self.destEdit.text())
            self.calDestThread = QThread()
            self.calDestTask.moveToThread(self.calDestThread)
            self.calDestThread.started.connect(self.calDestTask.doWork)
            self.calDestTask.done.connect(self.calDestThread.quit)
            self.calDestTask.update.connect(self.on_make_dest_running)
            self.calDestThread.finished.connect(self.on_make_dest_finished)
            self.calDestThread.start()

    # 开始复制文件
    @pyqtSlot()
    def on_copyPushButton_clicked(self):
        count = self.resopt.count_all_ready()
        if count:
            self.progressBar.show()
            self.progressBar.setValue(0)
            self.progressBar.setMinimum(0)
            self.progressBar.setMaximum(count)
            self.copyTask = CopyTask()
            self.copyThread = QThread()
            self.copyTask.moveToThread(self.copyThread)
            self.copyThread.started.connect(self.copyTask.doWork)
            self.copyTask.update.connect(self.on_copy_running)
            self.copyTask.done.connect(self.copyThread.quit)
            self.copyThread.finished.connect(self.on_copy_finished)
            self.copyThread.start()
示例#9
0
class DistributionPieChart(QChartView):
    """
    Pie chart that shows the distribution of capital according
    to several criteria
    """

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

        # Chart
        self.chart = QChart()
        self.chart.setTheme(QChart.ChartThemeDark)
        self.chart.legend().hide()
        self.chart.createDefaultAxes()
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setBackgroundVisible(False)

        self.chart.setTitle("  ")
        self.chart.setTitleBrush(QBrush(QColor('white')))

        self.setChart(self.chart)
        self.setRenderHint(QPainter.Antialiasing)
        self.setStyleSheet("border: 0px; background-color: rgba(0,0,0,0)")

        self.setupSeries()  # Initialize to all mode

    def setupSeries(self, mode="all"):
        """
        Chart gets updated displaying the new data.
        Modes:
            - all : distribution between all accounts
            - accs : distribution between portfolio accounts
            - cryptoaccs : distribution between crypto accounts
            - strategies : distribution between strategies

        """
        # Series
        self.chart.removeAllSeries()  # Remove any previous series
        self.series = QPieSeries()

        # Get data
        if mode == "all":
            data = balances.get_all_accounts(
            ) + cbalances.get_all_accounts_with_amount_fiat()

        elif mode == "accounts":
            data = balances.get_all_accounts()

        elif mode == "crypto":
            data = cbalances.get_all_accounts_with_amount_fiat()

        elif mode == "currency":
            data = [(confighandler.get_fiat_currency().upper(), balances.get_total_balance_all_accounts(
            )),  ("BTC", cbalances.get_total_balance_all_accounts_fiat())]
        data.sort(key=lambda x: x[1])  # Sort

        # Set Chart Title
        self.total = sum([i[1] for i in data])
        self.setDefaultTitle()

        # Add to series
        for d in data:
            self.series.append(d[0], d[1])

        # Hide little slices' labels
        self.series.setLabelsVisible(True)
        for slc in self.series.slices():
            if slc.angleSpan() < 5:
                slc.setLabelVisible(False)
                slc.setLabelArmLengthFactor(0.05)

        self.chart.addSeries(self.series)

        # Signals and functionality
        self.series.hovered.connect(self.selectSlice)

    def selectSlice(self, _slice, state):
        """ Highlight selected slice """
        font = ChartTitleFont()
        if state:
            font.setPointSize(20)
            _slice.setLabelVisible(True)
            self.chart.setTitle(
                f"{int(_slice.value())} {confighandler.get_fiat_currency().upper()} {round(_slice.percentage()*100,1)}%")
        else:
            font.setBold(False)
            if _slice.angleSpan() < 5:
                _slice.setLabelVisible(False)
            _slice.setExploded(False)
            self.setDefaultTitle()
        _slice.setLabelFont(font)

    def setDefaultTitle(self):
        """ Sets title as total balance from all pie slices """
        self.chart.setTitle(
            f"{int(self.total)} {confighandler.get_fiat_currency().upper()}")
        font = ChartTitleFont(fontsize=20)
        self.chart.setTitleFont(font)
示例#10
0
class Ui(mainwindow.Ui_MainWindow):
    def __init__(self, MainWindow):
        #super(Ui, self).__init__(M)
        super(Ui, self).setupUi(MainWindow)
        #uic.loadUi('UI/mainwindow.ui', self)

        self.MainWindow = MainWindow

        self.initialize()

    def close(self):
        self.MainWindow.close()

    def style(self):
        return self.MainWindow.style()

    def initialize(self):
        self.tabWidget.setCurrentIndex(0)
        self.actionExit.triggered.connect(self.close)
        self.action_Plot.setEnabled(False)

        self.actionNext.setIcon(
            self.style().standardIcon(
                QtWidgets.QStyle.SP_ArrowForward))
        self.actionPrevious.setIcon(
            self.style().standardIcon(
                QtWidgets.QStyle.SP_ArrowBack))
        self.action_Open.setIcon(
            self.style().standardIcon(
                QtWidgets.QStyle.SP_DialogOpenButton))
        self.actionSave.setIcon(
            self.style().standardIcon(
                QtWidgets.QStyle.SP_DriveFDIcon))

        self.actionSave.triggered.connect(self.save)

        self.action_Open.triggered.connect(self.getOpenFilename)

        self.actionNext.triggered.connect(self.nextPacket)
        self.actionPrevious.triggered.connect(self.previousPacket)
        self.actionAbout.triggered.connect(self.about)

        self.actionPrevious.setEnabled(False)
        self.actionNext.setEnabled(False)
        self.actionSave.setEnabled(False)
        self.action_Plot.setEnabled(False)
        self.actionPaste.triggered.connect(self.onPasteTriggered)
        # self.actionLog.triggered.connect(self.dockWidget_2.show)
        self.actionSet_IDB.triggered.connect(self.onSetIDBClicked)
        self.plotButton.clicked.connect(self.onPlotButtonClicked)
        self.exportButton.clicked.connect(self.onExportButtonClicked)
        self.action_Plot.triggered.connect(self.onPlotActionClicked)
        self.actionLoad_mongodb.triggered.connect(self.onLoadMongoDBTriggered)
        self.mdb=None

        self.current_row = 0
        self.data=[]
        self.x=[]
        self.y=[]
        self.xlabel='x'
        self.ylabel='y'

        self.chart = QChart()
        self.chart.layout().setContentsMargins(0,0,0,0)
        self.chart.setBackgroundRoundness(0)
        self.savePlotButton.clicked.connect(self.savePlot)
        
        self.chartView = QChartView(self.chart)
        self.gridLayout.addWidget(self.chartView, 1, 0, 1, 15)

        # IDB location

        self.settings = QtCore.QSettings('FHNW', 'stix_parser')
    def onExportButtonClicked(self):
        if self.y:
            filename = str(QtWidgets.QFileDialog.getSaveFileName(
                None, "Save file", "", "*.csv")[0])
            if filename:
                with open(filename,'w') as f:
                    f.write('{},{}\n'.format(self.xlabel,self.ylabel))
                    for xx,yy in zip(self.x,self.y):
                        f.write('{},{}\n'.format(xx,yy))
                    self.showMessage('The data has been written to {}'.format(filename))
        else:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Information)
            msgBox.setText('Plot first!')
            msgBox.setWindowTitle("Warning")
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()


    def savePlot(self):
        #if self.figure.get_axes():
        if self.chart:
            filename = str(QtWidgets.QFileDialog.getSaveFileName(
                None, "Save file", "", "*.png *.jpg")[0])
            if filename:
                if not filename.endswith(('.png','.jpg')):
                    filename+='.png'
                #self.figure.savefig(filename)
                p=self.chartView.grab()
                p.save(filename)
                self.showMessage(('Saved to %s.' % filename))


        else:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Information)
            msgBox.setText('The canvas is empty!')
            msgBox.setWindowTitle("STIX DATA VIEWER")
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()

    def onPasteTriggered(self):
        pass

    def showMessageBox(self, message, content):
        msg = QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Critical)
        msg.setText("Error")
        msg.setInformativeText(message)
        msg.setWindowTitle("Error")
        msg.setDetailedText(content)
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok |
                               QtWidgets.QMessageBox.Cancel)
        retval = msg.exec_()

    def showMessage(self, msg):
        # if destination != 1:
        self.statusbar.showMessage(msg)
        # if destination !=0 :
        #    self.listWidget_2.addItem(msg)

    def onSetIDBClicked(self):
        pass
    def save(self):
        pass

    def setListViewSelected(self, row):
        #index = self.model.createIndex(row, 0);
        # if index.isValid():
        #    self.model.selectionModel().select( index, QtGui.QItemSelectionModel.Select)
        pass

    def about(self):
        msgBox = QtWidgets.QMessageBox()
        msgBox.setIcon(QtWidgets.QMessageBox.Information)
        msgBox.setText("STIX raw data parser and viewer, [email protected]")
        msgBox.setWindowTitle("Stix data viewer")
        msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
        msgBox.exec_()

    def nextPacket(self):
        self.current_row += 1
        length=len(self.data)
        
        if self.current_row>=length:
            self.current_row=length-1
            self.showMessage('No more packet!')
            

        self.showPacket(self.current_row)
        self.setListViewSelected(self.current_row)

    def previousPacket(self):
        self.current_row -= 1
        if self.current_row <0:
            self.current_row=0
            self.showMessage('Reach the first packet!')

        self.showPacket(self.current_row)
        self.setListViewSelected(self.current_row)

    def getOpenFilename(self):
        pass

    def openFile(self, filename):
        pass



    def onDataLoaded(self, data,clear=True):
        if not clear:
            self.data.append(data)
        else:
            self.data = data
        self.displayPackets(clear)

        if self.data:
            self.actionPrevious.setEnabled(True)
            self.actionNext.setEnabled(True)
            self.actionSave.setEnabled(True)
            self.action_Plot.setEnabled(True)

    def displayPackets(self,clear=True):
        if clear:
            self.packetTreeWidget.clear()
        t0=0
        for p in self.data:
            if type(p) is not dict:
                continue
            header = p['header']
            root = QtWidgets.QTreeWidgetItem(self.packetTreeWidget)
            if t0==0:
                t0=header['time']

            root.setText(0, '{:.2f}'.format(header['time']-t0))
            root.setText(1,
                         ('TM({},{}) - {}').format(header['service_type'],
                                                   header['service_subtype'],
                                                   header['DESCR']))
        self.total_packets = len(self.data)
        self.showMessage((('%d packets loaded') % (self.total_packets)))
        self.packetTreeWidget.currentItemChanged.connect(self.onPacketSelected)
        self.showPacket(0)

    def onLoadMongoDBTriggered(self):
        diag=QtWidgets.QDialog()
        diag_ui=mongo_dialog.Ui_Dialog()
        diag_ui.setupUi(diag)
        diag_ui.pushButton.setFocus(True)
        #self.settings = QtCore.QSettings('FHNW', 'stix_parser')
        self.mongo_server= self.settings.value('mongo_server', [], str)
        self.mongo_port= self.settings.value('mongo_port', [], str)
        self.mongo_user= self.settings.value('mongo_user', [], str)
        self.mongo_pwd= self.settings.value('mongo_pwd', [], str)

        if self.mongo_server:
            diag_ui.serverLineEdit.setText(self.mongo_server)
        if self.mongo_port:
            diag_ui.portLineEdit.setText(self.mongo_port)

        if self.mongo_user:
            diag_ui.userLineEdit.setText(self.mongo_user)
        if self.mongo_pwd:
            diag_ui.pwdLineEdit.setText(self.mongo_pwd)

        diag_ui.pushButton.clicked.connect(partial(self.loadRunsFromMongoDB,diag_ui))
        diag_ui.buttonBox.accepted.connect(partial(self.loadDataFromMongoDB,diag_ui,diag))
        diag.exec_()
    def loadRunsFromMongoDB(self,dui):
        server=dui.serverLineEdit.text()
        port=dui.portLineEdit.text()
        user=dui.userLineEdit.text()
        pwd=dui.pwdLineEdit.text()

        self.showMessage('saving setting...')
        if self.mongo_server!=server:
            self.settings.setValue('mongo_server', server)
        if self.mongo_port!=port:
            self.settings.setValue('mongo_port', port)

        if self.mongo_user!=user:
            self.settings.setValue('mongo_user', user)
        if self.mongo_pwd!=pwd:
            self.settings.setValue('mongo_pwd', pwd)


        self.showMessage('connecting Mongo database ...')
        self.mdb=mgdb.MongoDB(server,int(port),user,pwd)
        dui.treeWidget.clear()
        self.showMessage('Fetching data...')
        for run in self.mdb.get_runs():
            root = QtWidgets.QTreeWidgetItem(dui.treeWidget)
            root.setText(0, str(run['_id']))
            root.setText(1, run['file'])
            root.setText(2, run['date'])
            root.setText(3, str(run['start']))
            root.setText(4, str(run['end']))
        self.showMessage('Runs loaded!')
    def loadDataFromMongoDB(self,dui,diag):
        selected_runs=[]
        for item in dui.treeWidget.selectedItems():
            selected_runs.append(item.text(0))
        if not selected_runs:
            self.showMessage('Run not selected!')
        if selected_runs:
            diag.done(0)
            self.showMessage('Loading data ...!')
            data=self.mdb.get_packets(selected_runs[0])
            if data:
                self.onDataLoaded(data,clear=True)
            else:
                self.showMessage('No packets found!')
        #close

    def onPacketSelected(self, cur, pre):
        self.current_row = self.packetTreeWidget.currentIndex().row()
        self.showMessage((('Packet #%d selected') % self.current_row))
        self.showPacket(self.current_row)

    def showPacket(self, row):
        if not self.data:
            return
        header = self.data[row]['header']
        self.showMessage(
            (('Packet %d / %d  %s ') %
             (row, self.total_packets, header['DESCR'])))

        self.paramTreeWidget.clear()

        header_root = QtWidgets.QTreeWidgetItem(self.paramTreeWidget)
        header_root.setText(0, "Header")
        rows = len(header)
        for key, val in header.items():
            root = QtWidgets.QTreeWidgetItem(header_root)
            root.setText(0, key)
            root.setText(1, str(val))

        params = self.data[row]['parameters']
        param_root = QtWidgets.QTreeWidgetItem(self.paramTreeWidget)
        param_root.setText(0, "Parameters")
        self.showParameterTree(params, param_root)
        self.paramTreeWidget.expandItem(param_root)
        self.paramTreeWidget.expandItem(header_root)

    def showParameterTree(self, params, parent):
        for p in params:
            root = QtWidgets.QTreeWidgetItem(parent)
            if not p:
                continue
            try:
                param_name=p['name']
                desc=''
                scos_desc=''
                try:
                    desc=param_desc.PCF[param_name]
                    scos_desc=param_desc.SW[param_name]
                except KeyError:
                    pass
                root.setToolTip(1,scos_desc)
                root.setText(0, param_name)
                root.setText(1, desc)
                root.setText(2, str(p['raw']))
                root.setText(3, str(p['value']))
                if 'child' in p:
                    if p['child']:
                        self.showParameterTree(p['child'], root)
            except KeyError:
                self.showMessage(
                    ('[Error  ]: keyError occurred when adding parameter'))
        self.paramTreeWidget.itemDoubleClicked.connect(self.onTreeItemClicked)

    def walk(self, name, params, header, ret_x, ret_y, xaxis=0, data_type=0):
        if not params:
            return
        timestamp = header['time']
        #parameters=[p for p in params if p['name'] == name] 
        for p in params:
            if type(p) is not dict:
                continue
        #for p in parameters:
            if name == p['name']:
                values = None
                #print('data type:{}'.format(data_type))
                if data_type == 0:
                    values = p['raw']
                else:
                    values = p['value']
                try:
                    yvalue = None
                    if (type(values) is tuple) or (type(values) is list):
                        yvalue = float(values[0])
                    else:
                        yvalue = float(values)
                    ret_y.append(yvalue)
                    if xaxis == 1:
                        ret_x.append(timestamp)
                    else:
                        self.showMessage((('Can not plot %s  ') % str(yvalue)))
                except Exception as e:
                    self.showMessage((('%s ') % str(e)))

            if 'child' in p:
                if p['child']:
                    self.walk(
                        name,
                        p['child'],
                        header,
                        ret_x,
                        ret_y,
                        xaxis,
                        data_type)

    def onPlotButtonClicked(self):
        if self.chart:
            self.chart.removeAllSeries()
        if not self.data:
            return
        self.showMessage('Preparing plot ...')
        name = self.paramNameEdit.text()
        packet_selection = self.comboBox.currentIndex()
        xaxis_type = self.xaxisComboBox.currentIndex()
        data_type = self.dataTypeComboBox.currentIndex()

        timestamp = []
        self.y = []
        packet_id = self.current_row
        params = self.data[packet_id]['parameters']
        header = self.data[packet_id]['header']
        current_spid=header['SPID']
        if packet_selection == 0:
            self.walk(
                name,
                params,
                header,
                timestamp,
                self.y,
                xaxis_type,
                data_type)
        elif packet_selection == 1:
            for packet in self.data:
                header = packet['header']
                if packet['header']['SPID'] != current_spid:
                    continue
                #only look for parameters in the packets of the same type
                params = packet['parameters']
                self.walk(
                    name,
                    params,
                    header,
                    timestamp,
                    self.y,
                    xaxis_type,
                    data_type)

        self.x = []



        if not self.y:
            self.showMessage('No data points')
        elif self.y:
            style = self.styleEdit.text()
            if not style:
                style = '-'
            title = '%s' % str(name)
            desc = self.descLabel.text()
            if desc:
                title += '- %s' % desc

            self.chart.setTitle(title)

            ylabel = 'Raw value'
            xlabel = name
            if data_type == 1:
                ylabel = 'Engineering  value'
            if xaxis_type == 0:
                xlabel = "Packet #"
                self.x = range(0, len(self.y))
            if xaxis_type == 1:
                self.x = [t - timestamp[0] for t in timestamp]
                xlabel = 'Time -T0 (s)'

            #if xaxis_type != 2:
            if True:
                series = QLineSeries()
                series2 = None

                # print(y)
                # print(x)
                for xx, yy in zip(self.x, self.y):
                    series.append(xx, yy)

                if 'o' in style:
                    series2 = QScatterSeries()
                    for xx, yy in zip(self.x, self.y):
                        series2.append(xx, yy)
                    self.chart.addSeries(series2)
                self.chart.addSeries(series)

                self.showMessage('plotted!')

                #self.chart.createDefaultAxes()
                axisX = QValueAxis()
                axisX.setTitleText(xlabel)
                axisY = QValueAxis()
                axisY.setTitleText(ylabel)

                self.chart.setAxisX(axisX)
                self.chart.setAxisY(axisY)
                series.attachAxis(axisX)
                series.attachAxis(axisY)

                # histogram
            #else:
            #    nbins = len(set(self.y))
            #    ycounts, xedges = np.histogram(self.y, bins=nbins)
            #    series = QLineSeries()
            #    for i in range(0, nbins):
            #        meanx = (xedges[i] + xedges[i + 1]) / 2.
            #        series.append(meanx, ycounts[i])
            #    # series.append(dataset)
            #    self.chart.addSeries(series)
            #    #self.chart.createDefaultAxes()
            #    self.showMessage('Histogram plotted!')

            #    axisX = QValueAxis()

            #    axisX.setTitleText(name)
            #    axisY = QValueAxis()

            #    axisY.setTitleText("Counts")

            #    self.chart.setAxisY(axisY)
            #    self.chart.setAxisX(axisX)
            ##    series.attachAxis(axisX)
            #    series.attachAxis(axisY)

            # self.widget.setChart(self.chart)
            self.xlabel=xlabel
            self.ylabel=ylabel
            self.chartView.setRubberBand(QChartView.RectangleRubberBand)
            self.chartView.setRenderHint(QtGui.QPainter.Antialiasing)

    def plotParameter(self, name=None, desc=None):
        self.tabWidget.setCurrentIndex(1)
        if name:
            self.paramNameEdit.setText(name)
        if desc:
            self.descLabel.setText(desc)

    def onPlotActionClicked(self):
        self.tabWidget.setCurrentIndex(1)
        self.plotParameter()

    def onTreeItemClicked(self, it, col):
        #print(it, col, it.text(0))
        self.plotParameter(it.text(0), it.text(1))

    def error(self, msg, description=''):
        self.showMessage((('Error: %s - %s') % (msg, description)))

    def warning(self, msg, description=''):
        self.showMessage((('Warning: %s - %s') % (msg, description)))

    def info(self, msg, description=''):
        self.showMessage((('Info: %s - %s') % (msg, description)))
示例#11
0
class widgetIDChart(QtWidgets.QWidget, qdesignFDChart.Ui_Form):

    actionRequestFromTable = pyqtSignal()

    def __init__(self, parent=None):
        super(widgetIDChart, self).__init__(parent)
        self.setupUi(self)
        tribchartmenustyle(self)
        # Default Settings
        self.nbins = 10

        # Extra Menu Items
        # Distribution Type Selection
        self.comboBoxDistr = XComboBoxDict(self)
        self.comboBoxDistr.setMinimumSize(QtCore.QSize(100, 30))

        self.knowndistr = distr._distrnames()
        self.comboBoxDistr.addItem({'None': 'None'})
        self.comboBoxDistr.addItems(self.knowndistr)
        self.comboBoxDistr.setObjectName("comboBoxDistr")
        self.horizontalLayout.insertWidget(3, self.comboBoxDistr)
        self.comboBoxDistr.currentTextChanged.connect(
            self.onComboBoxDistrChanged)
        self.activeDist = str(
            self.distrfromname(self.comboBoxDistr.currentText()))

        # Spinbox Label
        self.spinBoxLab = QtWidgets.QLabel(self)
        self.spinBoxLab.setText('  Bins: ')
        self.horizontalLayout.insertWidget(4, self.spinBoxLab)

        # Histogram N columns quick select spin box
        self.spinBoxDistr = QtWidgets.QSpinBox(self)
        self.spinBoxDistr.setMinimumSize(QtCore.QSize(50, 30))
        self.spinBoxDistr.setRange(2, 100)
        self.spinBoxDistr.setSingleStep(1)
        self.spinBoxDistr.setValue(self.nbins)
        self.spinBoxDistr.setObjectName("spinBoxDistr")
        self.horizontalLayout.insertWidget(5, self.spinBoxDistr)
        self.spinBoxDistr.valueChanged.connect(self.onSpinBoxChanged)

        # SetUp for Chart to Display Distribution curves and inputs.
        self.chart = QChart()
        self.chart.legend().setVisible(False)

        # SetUp Visible Chart Axes
        self.chart.axisX = QValueAxis()
        self.chart.axisY = QValueAxis()
        self.chart.axisX.setTickCount(10)
        self.chart.axisY.setTickCount(2)
        self.chart.axisX.setTitleText("Value")
        self.chart.axisY.setTitleText("Probability")

        # HistogramAxis
        self.chart.axisHist = QValueAxis()
        self.chart.addAxis(self.chart.axisHist, Qt.AlignRight)
        self.chart.axisHist.setTickCount(10)
        self.chart.axisHist.setTitleText("Count")
        self.chart.axisBins = QValueAxis()
        self.chart.addAxis(self.chart.axisBins, Qt.AlignBottom)
        self.chart.axisBins.setVisible(False)

        # Add Chart to Chartview and Chartview to Widget
        self.chartview = QChartView(self.chart)
        self.verticalLayout.addWidget(self.chartview)
        self.chartview.setRenderHint(QPainter.Antialiasing)

    def axesMinMax(self):
        # returns a length 4 list of the axes min and max values [x1,x2,y1,y2]
        return [
            self.chart.axisX.min(),
            self.chart.axisX.max(),
            self.chart.axisY.min(),
            self.chart.axisY.max()
        ]

    def setAxes(self, series):
        # assigns a series to the chart default axes
        self.chart.setAxisX(self.chart.axisX, series)
        self.chart.setAxisY(self.chart.axisY, series)

    def setAxesMinMax(self, x1, x2, y1, y2):
        # sets the min max values in X and Y
        self.chart.axisX.setMin(x1)
        self.chart.axisX.setMax(x2)
        self.chart.axisY.setMin(y1)
        self.chart.axisY.setMax(y2)

    def setTitle(self, title):
        self.chart.setTitle(title)

    def setRawData(self, datar):
        self.datar = datar
        self.ndata = len(self.datar)

    def addDistrLine(self, n, kstats):
        self.kstats = kstats
        data = distr.distrpdf(self.activeDist, n, **kstats)
        xmin = min(data['X'])
        xmax = max(data['X'])
        ymin = min(data['Y'])
        ymax = max(data['Y'])
        xscal = 0.1 * (xmax - xmin)
        yscal = 0.1 * (ymax - 0)
        self.chart.axisY.setRange(0, ymax + yscal)
        self.lineDist = XLineSeries(data, xkey='X')[0]

    def addHistLine(self):
        # fits a distribution to the histogram and draws a line
        self.kstats = distr.distrfit(self.activeDist, self.datar)  #hist[0])
        self.addDistrLine(1000, self.kstats)

    def addHistogram(self, nbins):
        # accepts a data array datar and int nbins to calculate a histogram
        self.nbins = nbins
        self.spinBoxDistr.setValue(nbins)
        try:
            self.hist = np.histogram(self.datar, bins=nbins)
        except:
            pass
            # create a function which displays a msg in the middle of the chart by raising a data error of sorts
        self.histseries = XDictSet({'Hist': self.hist[0]})
        # return barsets
        self.histsets = self.histseries.findChildren(QBarSet)

    def updateChart(self):
        self.chart.removeAllSeries()
        hmin = self.hist[1][0]
        hmax = self.hist[1][-1]
        cmax = max(self.hist[0]) + 1
        binwidth = self.hist[1][1] - self.hist[1][0]
        binscale = 1 / binwidth

        if self.activeDist == 'None':
            self.chart.axisY.setVisible(False)
            self.chart.axisX.setMin(hmin)
            self.chart.axisX.setMax(hmax)
        else:
            self.chart.axisY.setVisible(True)

        try:  # Add histogram bars
            self.chart.axisBins.setRange(-1, self.nbins)
            self.chart.axisHist.setRange(0, cmax)
            self.chart.addSeries(self.histseries)
            self.histseries.setBarWidth(1)

            # Set Colours
            self.histsets[0].setColor(tribColours.tribBlue)

            # Update Axes
            self.chart.setAxisX(self.chart.axisBins, self.histseries)
            self.chart.setAxisY(self.chart.axisHist, self.histseries)
        except NameError:
            pass

        if self.activeDist != 'None':
            try:  # Add distribution line
                self.addHistLine()

                # Fit Line Formatting
                linepen = QPen()
                linepen.setWidth(2.5)
                linepen.setColor(tribColours.tribCoral)
                self.lineDist.setPen(linepen)

                self.chart.addSeries(self.lineDist)
                self.setAxes(self.lineDist)
                self.chart.axisX.setRange(hmin - binwidth, hmax + binwidth)

            except AttributeError:
                pass

    @pyqtSlot(int)
    def onSpinBoxChanged(self, n):
        self.nbins = n
        self.addHistogram(self.nbins)
        self.updateChart()

    def distrfromname(self, search):
        for key, name in self.knowndistr.items():
            if name == search:
                return key

    @pyqtSlot(str)
    def onComboBoxDistrChanged(self, name):
        self.activeDist = self.comboBoxDistr.currentKey()
        self.addHistogram(self.nbins)
        self.updateChart()

    @pyqtSlot(dict)
    def receiveFromTable(self, datadict):
        self.setRawData(datadict['Value'])
        self.addHistogram(self.nbins)
        self.updateChart()
示例#12
0
class MainView(QWidget, Ui_Dialog):
    def __init__(self):
        super().__init__()
        Ui_Dialog.setupUi(self, self)
        self.pushButton_3.clicked.connect(self.showRecords)
        self.pushButton.clicked.connect(self.start)
        self.recive = False
        self.s = socket.socket()  # Create a socket object
        self.c = socket.socket()  # Create a socket object
        host = "192.168.1.40"  # Get local machine name
        port = 12345  # Reserve a port for your serv
        host = ""  # Get local machine nameice.
        self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.pushButton_3.setDisabled(True)
        self.pushButton.setText("Stop")
        try:
            self.s.bind(("", port))  # Bind to the port
        except:
            print("error")

        # self.s.listen(5)                 # Now wait for client connection.

    def __del__(self):
        self.s.close()

    def showConfiguration(self):
        self.hide()
        self.conf = configureView.configureView(self)
        self.conf.setMain(self)
        self.conf.show()

    def showRecords(self):
        self.w = QWidget()
        self.w.show()
        self.hide()
        self.gridLayout = QtWidgets.QVBoxLayout(self.w)
        self.text = QtWidgets.QLabel(self.w)
        self.chart = QChart()
        self.chart2 = QChart()
        self.chart3 = QChart()
        self.text.setText("none")
        self.backButton = QtWidgets.QPushButton(self.w)
        self.chartView = QChartView(self.chart)
        self.chartView.setRenderHint(QtGui.QPainter.Antialiasing)
        # self.chartView2.setRenderHint(QtGui.QPainter.Antialiasing)
        # self.chartView3.setRenderHint(QtGui.QPainter.Antialiasing)
        self.gridLayout.addWidget(self.chartView)
        # self.gridLayout.addWidget(self.chartView3)
        self.backButton.setText("Back")
        self.gridLayout.addWidget(self.backButton)
        self.backButton.clicked.connect(self.back)
        self.recive = True
        # self.series2 = QLineSeries(self.chart2)
        # self.series3 = QLineSeries(self.chart3)
        self.series = QLineSeries(self.chart)
        self.series2 = QLineSeries(self.chart)
        self.series3 = QLineSeries(self.chart)
        # self.series2.setUseOpenGL(True)
        # self.series3.setUseOpenGL(True)
        self.series.setUseOpenGL(True)
        self.series2.setUseOpenGL(True)
        self.series3.setUseOpenGL(True)
        # self.chart.addSeries(self.series)
        self.startServer()

    def createLineChart(self, dataTable):
        self.chart.setTitle("Sensor1")
        series = QLineSeries(self.chart)
        series2 = QLineSeries(self.chart)
        series3 = QLineSeries(self.chart)
        # series2 = QLineSeries(self.chart)
        # series3 = QLineSeries(self.chart)
        series.setUseOpenGL(True)
        series2.setUseOpenGL(True)
        series3.setUseOpenGL(True)
        # series2.setUseOpenGL(True)
        # series3.setUseOpenGL(True)

        series.replace(self.series.pointsVector())
        series2.replace(self.series2.pointsVector())
        series3.replace(self.series3.pointsVector())
        # series2.replace(self.series2.pointsVector())
        # series3.replace(self.series2.pointsVector())
        self.chart.removeAllSeries()
        self.chart.addSeries(series2)
        self.chart.addSeries(series)
        self.chart.addSeries(series3)
        # self.chart2.removeAllSeries()
        # self.chart2.addSeries(series2)
        # self.chart3.removeAllSeries()
        # self.chart3.addSeries(series3)
        # self.chart.scroll(1,2)

    def startServer(self):
        # Establish connection with client.
        a = []
        QApplication.processEvents()
        self.c.connect(("192.168.1.41", 12346))
        self.c.send(b'RecordView True')
        print("connected")
        index = 0
        while self.recive:

            QApplication.processEvents()  # c, addr = self.s.accept()
            message, adre = self.s.recvfrom(1024)
            # print(message)
            values = message.decode("utf-8").split("-")
            value1 = int(values[0])
            value2 = int(values[1])
            value3 = int(values[2])
            self.series.append(index, value1)
            self.series2.append(index, value2)
            self.series3.append(index, value3)
            # self.series2.append(index, int(message.decode("utf-8")))
            # self.series3.append(index, int(message.decode("utf-8")))
            if self.series.count() > 100:
                self.series.removePoints(0, 1)
                self.series2.removePoints(0, 1)
                self.series3.removePoints(0, 1)
                # self.series2.removePoints(0,1)
                # self.series3.removePoints(0,1)
            index += 1
            a.append(message.decode("utf-8"))
            self.createLineChart(a)
        self.c.connect(("192.168.1.41", 12346))
        self.c.send(b'RecordView False')

    def back(self):
        self.w.hide()
        self.show()
        self.recive = False

    def configure(self, arguments):
        print(arguments)
        self.c.connect(("192.168.1.41", 12346))
        self.c.send(b'Sensor ' + arguments)

    def start(self):
        self.c.connect(("192.168.1.41", 12346))
        if self.pushButton.text() == "Start":
            text = "Stop"
            self.pushButton_3.setEnabled(False)
            self.c.send(b'Record False')
        else:
            text = "Start"
            self.pushButton_3.setEnabled(True)
            self.c.send(b'Record True')

        self.recive = self.pushButton.text() == "Start"
        self.pushButton.setText(text)
示例#13
0
class StatisticsController:
    '''
        Class responsible of changing letting the user
        visualize the data saved in the database through
        a graph.
    '''
    def __init__(self, pView, pModel):
        '''
            Initializes the chart
        '''
        self.model = pModel
        self.view = pView

        self.queries = {
            'Products by category': I.PRODUCTS_BY_CATEGORY,
            'Sellers by gender': I.SELLERS_BY_GENDER,
            'Sellers by age': I.SELLERS_BY_AGE,
            'Total sales by gender': I.SALES_BY_GENDER,
            'Total sales profit by gender': I.PROFITS_BY_GENDER
        }

        # Loads every admin statistic
        for key in self.queries:
            self.view.ui.Statistics_StatisticsInput.addItem(key)

        self.view.ui.Statistics_ShowButton.clicked.connect(self.loadQuery)

        # Sets up the chart
        self.chart = QChart()

        # Embeds the chart in the application
        layout = QVBoxLayout()

        chartView = QChartView(self.chart)

        layout.addWidget(chartView)
        chartView.show()

        self.view.ui.Statistics_StatisticsWidget.setLayout(layout)

    def loadQuery(self):
        '''
            loads a query and its information
        '''
        queryName = self.view.ui.Statistics_StatisticsInput.currentText()
        query = self.queries[queryName]

        result = self.model.query(query)

        self.loadChart(queryName, result)

    def loadChart(self, pTitle, pData):
        '''
            Loads a chart and embeds it in the application
        '''

        # Creates the chart
        self.chart.setTitle(pTitle)
        self.chart.removeAllSeries()

        # Creates the slices
        series = QPieSeries(self.chart)
        for i in range(len(pData)):
            slice = series.append(
                '{} | {} | {}%'.format(str(pData[i][0]), str(pData[i][1]),
                                       str(pData[i][2])), pData[i][2])
            slice.setLabelVisible(True)

        self.chart.addSeries(series)
示例#14
0
class widgetFDChart(QtWidgets.QWidget, qdesignFDChart.Ui_Form):
    def __init__(self, parent=None):
        super(widgetFDChart, self).__init__(parent)
        self.setupUi(self)
        tribchartmenustyle(self)
        # SetUp for Chart to Display Distribution curves and inputs.
        self.chart = QChart()
        self.chart.legend().setVisible(False)

        self.chart.axisX = QValueAxis()
        self.chart.axisY = QValueAxis()
        self.chart.axisX.setTickCount(10)
        self.chart.axisY.setTickCount(10)
        self.chart.axisX.setTitleText("Value")
        self.chart.axisY.setTitleText("Probability")

        self.chartview = QChartView(self.chart)
        self.verticalLayout.addWidget(self.chartview)
        #        self.setAxesMinMax(-3,3,0.01,1.5)
        self.chartview.setRenderHint(QPainter.Antialiasing)
        # self.legend().setVisible(True)
        # self.setAnimationOptions(QChart.SeriesAnimations)
        # self.legend().setAlignment(Qt.AlignBottom)

        # Connect Buttons
        self.pushButtonExportPNG.pressed.connect(self._onActionSavePNG)

    def axesMinMax(self):
        # returns a length 4 list of the axes min and max values [x1,x2,y1,y2]
        return [
            self.chart.axisX.min(),
            self.chart.axisX.max(),
            self.chart.axisY.min(),
            self.chart.axisY.max()
        ]

    def setAxes(self, series):
        # assigns a series to the chart default axes
        self.chart.setAxisX(self.chart.axisX, series)
        self.chart.setAxisY(self.chart.axisY, series)

    def setAxesMinMax(self, x1, x2, y1, y2):
        # sets the min max values in X and Y
        self.chart.axisX.setMin(x1)
        self.chart.axisX.setMax(x2)
        self.chart.axisY.setMin(y1)
        self.chart.axisY.setMax(y2)

    def setTitle(self, title):
        self.chart.setTitle(title)

    def addDistrLine(self, type, n, kstats):
        data = distr.distrpdf(type, n, **kstats)
        xmin = min(data['X'])
        xmax = max(data['X'])
        ymin = min(data['Y'])
        ymax = max(data['Y'])
        self.lineDist = XLineSeries(data, xkey='X')[0]
        self.chart.addSeries(self.lineDist)
        self.setAxes(self.lineDist)
        xscal = 0.1 * (xmax - xmin)
        yscal = 0.1 * (ymax - ymin)
        self.setAxesMinMax(xmin - xscal, xmax + xscal, ymin, ymax + yscal)

    def updateChart(self, tabledata):
        self.activeDist = tabledata[0]
        self.kstats = tabledata[1]
        self.chart.removeAllSeries()
        self.addDistrLine(self.activeDist, 100, self.kstats)

    @pyqtSlot(str)
    def paintChart(self, filename):
        #pixmap = QPixmap()
        pixmap = self.chartview.grab()
        pixmap.save(filename)

    def _onActionSavePNG(self):
        pngfile = QtWidgets.QFileDialog.getSaveFileName(
            self, caption='Export PNG As', directory='~', filter='*.png')
        #try:
        self.paintChart(pngfile[0])
class Ui(mainwindow.Ui_MainWindow):
    def __init__(self, MainWindow):
        super(Ui, self).setupUi(MainWindow)
        self.MainWindow = MainWindow
        self.stix_tctm_parser = stix_parser.StixTCTMParser()
        self.initialize()

    def close(self):
        self.MainWindow.close()

    def style(self):
        return self.MainWindow.style()

    def initialize(self):
        self.tabWidget.setCurrentIndex(0)
        self.actionExit.triggered.connect(self.close)
        self.actionPlot.setEnabled(False)

        self.actionNext.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_ArrowForward))
        self.actionPrevious.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_ArrowBack))
        self.actionOpen.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_DialogOpenButton))
        self.actionSave.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_DriveFDIcon))

        self.actionSave.triggered.connect(self.save)

        self.actionOpen.triggered.connect(self.getOpenFilename)

        self.actionNext.triggered.connect(self.nextPacket)
        self.actionPrevious.triggered.connect(self.previousPacket)
        self.actionAbout.triggered.connect(self.about)

        self.actionPrevious.setEnabled(False)
        self.actionNext.setEnabled(False)
        self.actionSave.setEnabled(False)
        self.actionPlot.setEnabled(False)
        self.actionCopy.triggered.connect(self.onCopyTriggered)

        self.packetTreeWidget.currentItemChanged.connect(self.onPacketSelected)

        self.actionCopy.setEnabled(False)
        self.actionPaste.triggered.connect(self.onPasteTriggered)
        self.actionLog.triggered.connect(self.dockWidget.show)
        self.actionSetIDB.triggered.connect(self.onSetIDBClicked)
        self.plotButton.clicked.connect(self.onPlotButtonClicked)
        self.exportButton.clicked.connect(self.onExportButtonClicked)
        self.actionPlot.triggered.connect(self.onPlotActionClicked)
        self.actionLoadMongodb.triggered.connect(self.onLoadMongoDBTriggered)
        self.actionConnectTSC.triggered.connect(self.onConnectTSCTriggered)
        self.actionPacketFilter.triggered.connect(self.onPacketFilterTriggered)
        self.actionPlugins.triggered.connect(self.onPluginTriggered)
        self.actionOnlineHelp.triggered.connect(self.onOnlineHelpTriggered)
        self.actionViewBinary.triggered.connect(self.onViewBinaryTriggered)

        self.packetTreeWidget.customContextMenuRequested.connect(
            self.packetTreeContextMenuEvent)

        self.mdb = None

        self.current_row = 0
        self.data = []
        self.x = []
        self.y = []
        self.xlabel = 'x'
        self.ylabel = 'y'

        self.buttons_enabled = False

        self.chart = QChart()
        self.chart.layout().setContentsMargins(0, 0, 0, 0)
        self.chart.setBackgroundRoundness(0)
        self.savePlotButton.clicked.connect(self.savePlot)

        self.chartView = QChartView(self.chart)
        self.gridLayout.addWidget(self.chartView, 1, 0, 1, 15)
        #self.packetTreeWidget.itemDoubleClicked.connect(self.onPacketTreeItemDoubleClicked)
        self.selected_services = SELECTED_SERVICES
        self.selected_SPID = []

        # IDB location

        self.settings = QtCore.QSettings('FHNW', 'stix_parser')
        self.idb_filename = self.settings.value('idb_filename', [], str)
        if self.idb_filename:
            idb._stix_idb.reload(self.idb_filename)
        if not idb._stix_idb.is_connected():
            self.showMessage('IDB has not been set!')
        else:
            self.showMessage(
                'IDB location: {} '.format(idb._stix_idb.get_idb_filename()),
                1)

    def packetTreeContextMenuEvent(self, pos):
        menu = QtWidgets.QMenu()
        rawDataAction = menu.addAction('Show raw data')
        menu.addSeparator()
        filterAction = menu.addAction('Filter packets')
        copyPacketAction = menu.addAction('Copy packet')
        menu.addSeparator()
        deleteAllAction = menu.addAction('Delete all packets')
        self.current_row = self.packetTreeWidget.currentIndex().row()

        rawDataAction.triggered.connect(self.onViewBinaryTriggered)
        filterAction.triggered.connect(self.onPacketFilterTriggered)
        copyPacketAction.triggered.connect(self.onCopyTriggered)
        deleteAllAction.triggered.connect(self.onDeleteAllTriggered)
        action = menu.exec_(self.packetTreeWidget.viewport().mapToGlobal(pos))

    def onDeleteAllTriggered(self):
        self.data.clear()
        self.packetTreeWidget.clear()
        self.paramTreeWidget.clear()

    #def onPacketTreeItemDoubleClicked(self):
    #    self.onViewBinaryTriggered()

    def onViewBinaryTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = raw_viewer.Ui_Dialog()
        diag_ui.setupUi(diag)
        if self.data:
            try:
                raw = self.data[self.current_row]['bin']
                header = self.data[self.current_row]['header']
                diag_ui.setPacketInfo('{}({},{})  {}'.format(
                    header['TMTC'], header['service_type'],
                    header['service_subtype'], header['DESCR']))
                diag_ui.displayRaw(raw)
            except (IndexError, KeyError):
                diag_ui.setText('Raw data not available.')
        diag.exec_()

    def onOnlineHelpTriggered(self):
        webbrowser.open('https://github.com/i4Ds/STIX-dataviewer', new=2)

    def onPluginTriggered(self):
        self.plugin_location = self.settings.value('plugin_location', [], str)
        diag = QtWidgets.QDialog()
        diag_ui = plugin.Ui_Dialog()
        diag_ui.setupUi(diag)
        if self.plugin_location:
            diag_ui.setPluginLocation(self.plugin_location)

        diag_ui.setData(self.data, self.current_row)
        diag.exec_()
        location = diag_ui.getPluginLocation()
        if location != self.plugin_location:
            self.settings.setValue('plugin_location', location)

    def onPacketFilterTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = packet_filter.Ui_Dialog()
        diag_ui.setupUi(diag)
        diag_ui.setSelectedServices(self.selected_services)
        diag_ui.buttonBox.accepted.connect(
            partial(self.applyServiceFilter, diag_ui))
        diag.exec_()

    def applyServiceFilter(self, diag_ui):
        self.selected_SPID = diag_ui.getSelectedSPID()
        self.selected_services = diag_ui.getSelectedServices()
        self.showMessage('Applying filter...')

        self.addPacketsToView(self.data, True, show_stat=False)

    def onExportButtonClicked(self):
        if self.y:
            filename = str(
                QtWidgets.QFileDialog.getSaveFileName(None,
                                                      "Save data to file", "",
                                                      "CSV(*.csv)")[0])
            if filename:
                with open(filename, 'w') as f:
                    f.write('{},{}\n'.format(self.xlabel, self.ylabel))
                    for xx, yy in zip(self.x, self.y):
                        f.write('{},{}\n'.format(xx, yy))
                    self.showMessage(
                        'The data has been written to {}'.format(filename))
        else:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Information)
            msgBox.setText('Plot first!')
            msgBox.setWindowTitle("Warning")
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()

    def savePlot(self):
        # if self.figure.get_axes():
        if self.chart:
            filetypes = "PNG (*.png);;JPEG (*.jpg)"
            filename = str(
                QtWidgets.QFileDialog.getSaveFileName(None,
                                                      "Save plot to file", "",
                                                      filetypes)[0])
            if filename:
                if not filename.endswith(('.png', '.jpg')):
                    filename += '.png'
                # self.figure.savefig(filename)
                p = self.chartView.grab()
                p.save(filename)
                self.showMessage(('Saved to %s.' % filename))

        else:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Information)
            msgBox.setText('No figure to save')
            msgBox.setWindowTitle("STIX raw data viewer")
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()

    def onCopyTriggered(self):
        packet_id = self.current_row
        try:
            packet = self.data[packet_id]
            ss = pprint.pformat(packet)
            cb = QtWidgets.QApplication.clipboard()
            cb.clear(mode=cb.Clipboard)
            cb.setText(ss, mode=cb.Clipboard)
            msg = QtWidgets.QMessageBox()
            msg.setIcon(QtWidgets.QMessageBox.Information)
            msg.setText(
                "The data of the selected packet has been copied to the clipboard."
            )
            msg.setWindowTitle("Information")
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            retval = msg.exec_()

        except Exception as e:
            self.showMessage(str(e), 0)

    def onPasteTriggered(self):
        raw_hex = QtWidgets.QApplication.clipboard().text()
        if len(raw_hex) < 16:
            self.showMessage('No data in the clipboard.')
            return
        data_hex = re.sub(r"\s+", "", raw_hex)
        try:
            data_binary = binascii.unhexlify(data_hex)
            packets = self.stix_tctm_parser.parse_binary(data_binary,
                                                         0,
                                                         store_binary=True)
            if not packets:
                return
            self.showMessage('%d packets read from the clipboard' %
                             len(packets))
            self.onDataReady(packets, clear=False, show_stat=False)
        except Exception as e:
            self.showMessageBox(str(e), data_hex)

    def showMessageBox(self, message, content):
        msg = QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Critical)
        msg.setText("Error")
        msg.setInformativeText(message)
        msg.setWindowTitle("Error")
        msg.setDetailedText(content)
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok
                               | QtWidgets.QMessageBox.Cancel)
        retval = msg.exec_()

    def showMessage(self, msg, where=0):
        if where != 1:
            self.statusbar.showMessage(msg)
        if where != 0:
            self.statusListWidget.addItem(msg)
        # if destination !=0 :
        #    self.listWidget_2.addItem(msg)

    def onSetIDBClicked(self):
        self.idb_filename = QtWidgets.QFileDialog.getOpenFileName(
            None, 'Select file', '.', 'IDB file(*.db *.sqlite *.sqlite3)')[0]

        if not self.idb_filename:
            return

        idb._stix_idb.reload(self.idb_filename)
        if idb._stix_idb.is_connected():
            #settings = QtCore.QSettings('FHNW', 'stix_parser')
            self.settings.setValue('idb_filename', self.idb_filename)
        self.showMessage(
            'IDB location: {} '.format(idb._stix_idb.get_idb_filename()), 1)

    def save(self):
        filetypes = 'python compressed pickle (*.pklz);; python pickle file (*.pkl);; binary data (*.dat)'
        self.output_filename = str(
            QtWidgets.QFileDialog.getSaveFileName(None, "Save packets to", "",
                                                  filetypes)[0])

        if not self.output_filename.endswith(('.pklz', '.pkl', '.dat')):
            msg = 'unsupported file format !'
            self.showMessage(msg)
            return

        msg = 'Writing data to file %s' % self.output_filename
        self.showMessage(msg)

        if self.output_filename.endswith(('.pklz', '.pkl')):
            stw = stix_writer.StixPickleWriter(self.output_filename)
            stw.register_run(str(self.input_filename))
            stw.write_all(self.data)
            #stw.done()
        elif self.output_filename.endswith('.dat'):
            stw = stix_writer.StixBinaryWriter(self.output_filename)
            stw.write_all(self.data)
            num_ok = stw.get_num_sucess()
            msg = (
                'The binary data of {} packets written to file {}, total packets {}'
                .format(num_ok, self.output_filename, len(self.data)))
            self.showMessage(msg)

    def setListViewSelected(self, row):
        #index = self.model.createIndex(row, 0);
        # if index.isValid():
        #    self.model.selectionModel().select( index, QtGui.QItemSelectionModel.Select)
        pass

    def about(self):
        msgBox = QtWidgets.QMessageBox()
        msgBox.setIcon(QtWidgets.QMessageBox.Information)
        msgBox.setText("STIX raw data parser and viewer, [email protected]")
        msgBox.setWindowTitle("Stix data viewer")

        msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
        msgBox.exec_()

    def nextPacket(self):
        self.current_row += 1
        length = len(self.data)

        if self.current_row >= length:
            self.current_row = length - 1
            self.showMessage('No more packet!')

        self.showPacket(self.current_row)
        self.setListViewSelected(self.current_row)

    def previousPacket(self):
        self.current_row -= 1
        if self.current_row < 0:
            self.current_row = 0
            self.showMessage('Reach the first packet!')

        self.showPacket(self.current_row)
        self.setListViewSelected(self.current_row)

    def getOpenFilename(self):
        filetypes = (
            'STIX raw data(*.dat *.bin *.binary);; python pickle files (*.pkl *pklz);;'
            'ESA xml files (*xml);;'
            'ESA ascii files(*.ascii);; CMDVS archive files (*.BDF);; All(*)')
        self.input_filename = QtWidgets.QFileDialog.getOpenFileName(
            None, 'Select file', '.', filetypes)[0]
        if not self.input_filename:
            return
        self.openFile(self.input_filename)

    def openFile(self, filename):
        self.packetTreeWidget.clear()
        msg = 'Loading file %s ...' % filename
        self.showMessage(msg)
        self.dataReader = StixFileReader(filename)
        #self.dataReader.dataLoaded.connect(self.onDataReady)
        self.dataReader.packetArrival.connect(self.onPacketArrival)
        self.dataReader.error.connect(self.onDataReaderError)
        self.dataReader.info.connect(self.onDataReaderInfo)
        self.dataReader.warn.connect(self.onDataReaderWarn)
        self.dataReader.start()

    def onDataReaderInfo(self, msg):
        self.showMessage(msg, 0)

    def onDataReaderWarn(self, msg):
        self.showMessage(msg, 1)

    def onDataReaderError(self, msg):
        self.showMessage(msg, 1)

    def onDataReady(self, data, clear=True, show_stat=True):
        if not clear:
            self.data.extend(data)
        else:
            self.data = data
        if data:
            self.addPacketsToView(data, clear=clear, show_stat=show_stat)
            self.enableButtons()

    def enableButtons(self):
        if not self.buttons_enabled:
            self.actionPrevious.setEnabled(True)
            self.actionNext.setEnabled(True)
            self.actionSave.setEnabled(True)
            self.actionCopy.setEnabled(True)
            self.actionPlot.setEnabled(True)
            self.actionViewBinary.setEnabled(True)
            self.buttons_enabled = True

    def addPacketsToView(self, data, clear=True, show_stat=True):
        if clear:
            self.packetTreeWidget.clear()
        #t0 = 0
        for p in data:
            if type(p) is not dict:
                continue
            header = p['header']

            root = QtWidgets.QTreeWidgetItem(self.packetTreeWidget)
            # if t0 == 0:
            #    t0 = header['time']
            timestamp_str = ''
            try:
                timestamp_str = header['utc']
            except KeyError:
                timestamp_str = '{:.2f}'.format(header['time'])
                #- t0)

            root.setText(0, timestamp_str)
            root.setText(
                1,
                '{}({},{}) - {}'.format(header['TMTC'], header['service_type'],
                                        header['service_subtype'],
                                        header['DESCR']))

            if not self.selected_SPID:
                #not set then apply service
                if header['service_type'] not in self.selected_services:
                    root.setHidden(True)
            else:
                if header['SPID'] not in self.selected_SPID:
                    root.setHidden(True)

        if show_stat:
            total_packets = len(self.data)
            self.showMessage(('Total packet(s): %d' % total_packets))

    def onConnectTSCTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = tsc_connection.Ui_Dialog()
        diag_ui.setupUi(diag)
        self.tsc_host = self.settings.value('tsc_host', [], str)
        self.tsc_port = self.settings.value('tsc_port', [], str)
        if self.tsc_host:
            diag_ui.serverLineEdit.setText(self.tsc_host)
        if self.tsc_port:
            diag_ui.portLineEdit.setText(self.tsc_port)
        diag_ui.buttonBox.accepted.connect(partial(self.connectToTSC, diag_ui))
        diag.exec_()

    def connectToTSC(self, dui):
        host = dui.serverLineEdit.text()
        port = dui.portLineEdit.text()
        self.showMessage('Connecting to TSC...')
        self.socketPacketReceiver = StixSocketPacketReceiver(host, int(port))
        self.socketPacketReceiver.packetArrival.connect(self.onPacketArrival)
        self.socketPacketReceiver.error.connect(self.onDataReaderError)
        self.socketPacketReceiver.info.connect(self.onDataReaderInfo)
        self.socketPacketReceiver.warn.connect(self.onDataReaderWarn)
        self.socketPacketReceiver.start()

    def onPacketArrival(self, packets):
        if packets:
            self.onDataReady(packets, clear=False, show_stat=True)

    def onLoadMongoDBTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = mongo_dialog.Ui_Dialog()
        diag_ui.setupUi(diag)
        #self.settings = QtCore.QSettings('FHNW', 'stix_parser')
        self.mongo_server = self.settings.value('mongo_server', [], str)
        self.mongo_port = self.settings.value('mongo_port', [], str)
        self.mongo_user = self.settings.value('mongo_user', [], str)
        self.mongo_pwd = self.settings.value('mongo_pwd', [], str)

        if self.mongo_server:
            diag_ui.serverLineEdit.setText(self.mongo_server)
        if self.mongo_port:
            diag_ui.portLineEdit.setText(self.mongo_port)

        if self.mongo_user:
            diag_ui.userLineEdit.setText(self.mongo_user)
        if self.mongo_pwd:
            diag_ui.pwdLineEdit.setText(self.mongo_pwd)

        diag_ui.pushButton.clicked.connect(
            partial(self.loadRunsFromMongoDB, diag_ui))
        diag_ui.buttonBox.accepted.connect(
            partial(self.loadDataFromMongoDB, diag_ui, diag))
        diag.exec_()

    def loadRunsFromMongoDB(self, dui):
        server = dui.serverLineEdit.text()
        port = dui.portLineEdit.text()
        user = dui.userLineEdit.text()
        pwd = dui.pwdLineEdit.text()

        self.showMessage('saving setting...')
        if self.mongo_server != server:
            self.settings.setValue('mongo_server', server)
        if self.mongo_port != port:
            self.settings.setValue('mongo_port', port)

        if self.mongo_user != user:
            self.settings.setValue('mongo_user', user)
        if self.mongo_pwd != pwd:
            self.settings.setValue('mongo_pwd', pwd)

        self.showMessage('connecting Mongo database ...')
        self.mdb = mgdb.MongoDB(server, int(port), user, pwd)
        if not self.mdb.is_connected():
            return

        dui.treeWidget.clear()
        self.showMessage('Fetching data...')
        for run in self.mdb.get_runs():
            root = QtWidgets.QTreeWidgetItem(dui.treeWidget)
            root.setText(0, str(run['_id']))
            root.setText(1, run['filename'])
            root.setText(2, run['date'])
            root.setText(3, str(run['start']))
            root.setText(4, str(run['end']))

    def loadDataFromMongoDB(self, dui, diag):
        self.showMessage('Loading packets ...')
        selected_runs = []
        for item in dui.treeWidget.selectedItems():
            selected_runs.append(item.text(0))
        if not selected_runs:
            self.showMessage('Run not selected!')
        if selected_runs:
            diag.done(0)
            self.showMessage('Loading data ...!')
            data = self.mdb.get_packets(selected_runs[0])
            if data:
                self.onDataReady(data, clear=True)
            else:
                self.showMessage('No packets found!')
        # close

    def onPacketSelected(self, cur, pre):
        self.current_row = self.packetTreeWidget.currentIndex().row()
        self.showMessage(('Packet #%d selected' % self.current_row))
        self.showPacket(self.current_row)

    def showPacket(self, row):
        if not self.data:
            return
        header = self.data[row]['header']
        total_packets = len(self.data)
        self.showMessage(
            ('Packet %d / %d  %s ' % (row, total_packets, header['DESCR'])))
        self.paramTreeWidget.clear()
        header_root = QtWidgets.QTreeWidgetItem(self.paramTreeWidget)
        header_root.setText(0, "Header")
        rows = len(header)
        for key, val in header.items():
            root = QtWidgets.QTreeWidgetItem(header_root)
            root.setText(0, key)
            root.setText(1, str(val))

        params = self.data[row]['parameters']
        param_root = QtWidgets.QTreeWidgetItem(self.paramTreeWidget)
        param_root.setText(0, "Parameters")
        self.showParameterTree(params, param_root)
        self.paramTreeWidget.expandItem(param_root)
        self.paramTreeWidget.expandItem(header_root)
        self.current_row = row

    def showParameterTree(self, params, parent):
        if not params:
            return
        for p in params:
            root = QtWidgets.QTreeWidgetItem(parent)
            if not p:
                continue
            try:
                param_name = p['name']
                desc = ''  #description of parameter
                if 'desc' in p:
                    desc = p['desc']
                if not desc:
                    desc = idb._stix_idb.get_PCF_description(param_name)
                scos_desc = idb._stix_idb.get_scos_description(param_name)
                if scos_desc:
                    root.setToolTip(1, scos_desc)
                root.setText(0, param_name)
                root.setText(1, desc)
                root.setText(2, str(p['raw']))
                try:
                    root.setToolTip(2, hex(p['raw'][0]))
                except:
                    pass
                root.setText(3, str(p['eng']))
                if 'children' in p:
                    if p['children']:
                        self.showParameterTree(p['children'], root)
            except KeyError:
                self.showMessage(
                    '[Error  ]: keyError occurred when adding parameter')
        self.paramTreeWidget.itemDoubleClicked.connect(self.onTreeItemClicked)

    def walk(self, name, params, header, ret_x, ret_y, xaxis=0, data_type=0):
        if not params:
            return
        timestamp = header['time']
        for p in params:
            if type(p) is not dict:
                continue
            if name == p['name']:
                values = None
                #print('data type:{}'.format(data_type))
                if data_type == 0:
                    values = p['raw']
                else:
                    values = p['eng']
                try:
                    yvalue = None
                    if (type(values) is tuple) or (type(values) is list):
                        yvalue = float(values[0])
                    else:
                        yvalue = float(values)
                    ret_y.append(yvalue)
                    if xaxis == 1:
                        ret_x.append(timestamp)
                    else:
                        self.showMessage(('Can not plot %s  ' % str(yvalue)))
                except Exception as e:
                    self.showMessage(('%s ' % str(e)))

            if 'children' in p:
                if p['children']:
                    self.walk(name, p['children'], header, ret_x, ret_y, xaxis,
                              data_type)

    def onPlotButtonClicked(self):
        if self.chart:
            self.chart.removeAllSeries()
        if not self.data:
            return
        self.showMessage('Preparing plot ...')
        name = self.paramNameEdit.text()
        packet_selection = self.comboBox.currentIndex()
        xaxis_type = self.xaxisComboBox.currentIndex()
        data_type = self.dataTypeComboBox.currentIndex()

        timestamp = []
        self.y = []
        packet_id = self.current_row
        params = self.data[packet_id]['parameters']
        header = self.data[packet_id]['header']
        current_spid = header['SPID']
        if packet_selection == 0:
            self.walk(name, params, header, timestamp, self.y, xaxis_type,
                      data_type)
        elif packet_selection == 1:
            for packet in self.data:
                header = packet['header']
                if packet['header']['SPID'] != current_spid:
                    continue
                params = packet['parameters']
                self.walk(name, params, header, timestamp, self.y, xaxis_type,
                          data_type)

        self.x = []

        if not self.y:
            self.showMessage('No data points')
        elif self.y:
            style = self.styleEdit.text()
            if not style:
                style = '-'
            title = '%s' % str(name)
            desc = self.descLabel.text()
            if desc:
                title += '- %s' % desc

            self.chart.setTitle(title)

            ylabel = 'Raw value'
            xlabel = name
            if data_type == 1:
                ylabel = 'Engineering  value'
            if xaxis_type == 0:
                if packet_selection == 1:
                    xlabel = "Packet #"
                else:
                    xlabel = "Repeat #"
                self.x = range(0, len(self.y))
            if xaxis_type == 1:
                self.x = [t - timestamp[0] for t in timestamp]
                xlabel = 'Time -T0 (s)'

            if xaxis_type != 2:
                series = QLineSeries()
                series2 = None
                for xx, yy in zip(self.x, self.y):
                    series.append(xx, yy)
                if 'o' in style:
                    series2 = QScatterSeries()
                    for xx, yy in zip(self.x, self.y):
                        series2.append(xx, yy)
                    self.chart.addSeries(series2)
                self.chart.addSeries(series)
                axisX = QValueAxis()
                axisX.setTitleText(xlabel)
                axisY = QValueAxis()
                axisY.setTitleText(ylabel)

                self.chart.setAxisX(axisX)
                self.chart.setAxisY(axisY)
                series.attachAxis(axisX)
                series.attachAxis(axisY)
            else:
                nbins = len(set(self.y))
                ycounts, xedges = np.histogram(self.y, bins=nbins)
                series = QLineSeries()
                for i in range(0, nbins):
                    meanx = (xedges[i] + xedges[i + 1]) / 2.
                    series.append(meanx, ycounts[i])
                self.chart.addSeries(series)
                axisX = QValueAxis()
                axisX.setTitleText(name)
                axisY = QValueAxis()
                axisY.setTitleText("Counts")

                self.chart.setAxisY(axisY)
                self.chart.setAxisX(axisX)
                series.attachAxis(axisX)
                series.attachAxis(axisY)

            self.xlabel = xlabel
            self.ylabel = ylabel
            self.chartView.setRubberBand(QChartView.RectangleRubberBand)
            self.chartView.setRenderHint(QtGui.QPainter.Antialiasing)
            msg = 'Y length: {}, min-Y:  {}, max-Y: {}'.format(
                len(self.y), min(self.y), max(self.y))

            self.showMessage(msg, 1)

            self.showMessage('The canvas updated!')

    def plotParameter(self, name=None, desc=None):
        self.tabWidget.setCurrentIndex(1)
        if name:
            self.paramNameEdit.setText(name)
        if desc:
            self.descLabel.setText(desc)

    def onPlotActionClicked(self):
        self.tabWidget.setCurrentIndex(1)
        self.plotParameter()

    def onTreeItemClicked(self, it, col):
        self.plotParameter(it.text(0), it.text(1))
示例#16
0
class MainWindow(QMainWindow):
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    MAIN_UI_FILE = os.path.join(BASE_DIR, "main.ui")
    NEW_DISH_POPUP_UI_FILE = os.path.join(BASE_DIR, "new_dish_popup.ui")
    NEW_DISH_MULTI_POPUP_UI_FILE = os.path.join(BASE_DIR,
                                                "new_dish_multi_popup.ui")
    NEW_DISH_DATA_POPUP_UI_FILE = os.path.join(BASE_DIR,
                                               "new_dish_data_popup.ui")
    MODIFY_DISH_POPUP_UI_FILE = os.path.join(BASE_DIR, "modify_dish_popup.ui")
    DB_FILE = os.path.join(BASE_DIR, "restaurant.db")

    def __init__(self):
        super(MainWindow, self).__init__()
        # Initialize variable
        self.db_connection = None
        self.new_dish_popup = QWidget()
        self.new_dish_multi_popup = QWidget()
        self.new_dish_data_popup = QWidget()
        self.modify_dish_popup = QWidget()
        self.dish_table_model = QStandardItemModel(0, 6)
        self.dish_table_proxy = TableFilter()
        self.dish_data_table_model = QStandardItemModel(0, 6)
        self.dish_data_table_proxy = TableFilter()
        self.graph_chart = None
        self.graph_series = {}

        # Load UI designs
        uic.loadUi(self.MAIN_UI_FILE, self)
        uic.loadUi(self.NEW_DISH_POPUP_UI_FILE, self.new_dish_popup)
        uic.loadUi(self.NEW_DISH_MULTI_POPUP_UI_FILE,
                   self.new_dish_multi_popup)
        uic.loadUi(self.NEW_DISH_DATA_POPUP_UI_FILE, self.new_dish_data_popup)
        uic.loadUi(self.MODIFY_DISH_POPUP_UI_FILE, self.modify_dish_popup)
        self.init_dish_table()
        self.init_dish_data_table()
        self.init_graph()

        # Connect to database
        self.init_db_connection()

        # MainWindow Bind action triggers
        self.action_new_dish.triggered.connect(self.show_new_dish_popup)
        self.action_new_dish_multi.triggered.connect(
            self.show_new_dish_multi_popup)
        self.action_new_data_multi.triggered.connect(
            lambda: self.modify_new_dish_data_popup_table(show=True))
        self.tabWidget.currentChanged.connect(self.update_graph)

        # Dish Table filter bind
        self.dish_lineEdit.textChanged.connect(
            lambda text, col_idx=1: self.dish_table_proxy.set_col_regex_filter(
                col_idx, text))
        self.lower_price_doubleSpinBox.valueChanged.connect(
            lambda value, col_idx=2: self.dish_table_proxy.
            set_col_number_filter(col_idx, value, -1))
        self.higher_price_doubleSpinBox.valueChanged.connect(
            lambda value, col_idx=2: self.dish_table_proxy.
            set_col_number_filter(col_idx, -1, value))
        self.lower_week_sell_spinBox.valueChanged.connect(
            lambda value, col_idx=3: self.dish_table_proxy.
            set_col_number_filter(col_idx, value, -1))
        self.higher_week_sell_spinBox.valueChanged.connect(
            lambda value, col_idx=3: self.dish_table_proxy.
            set_col_number_filter(col_idx, -1, value))

        # Dish Data Table filter bind
        self.lower_data_dateEdit.dateChanged.connect(
            lambda date, col_idx=1: self.dish_data_table_proxy.
            set_col_date_filter(col_idx, date, -1))
        self.higher_data_dateEdit.dateChanged.connect(
            lambda date, col_idx=1: self.dish_data_table_proxy.
            set_col_date_filter(col_idx, -1, date))
        self.data_lineEdit.textChanged.connect(
            lambda text, col_idx=2: self.dish_data_table_proxy.
            set_col_regex_filter(col_idx, text))
        self.lower_data_doubleSpinBox.valueChanged.connect(
            lambda value, col_idx=3: self.dish_data_table_proxy.
            set_col_number_filter(col_idx, value, -1))
        self.higher_data_doubleSpinBox.valueChanged.connect(
            lambda value, col_idx=3: self.dish_data_table_proxy.
            set_col_number_filter(col_idx, -1, value))
        self.lower_data_spinBox.valueChanged.connect(
            lambda value, col_idx=4: self.dish_data_table_proxy.
            set_col_number_filter(col_idx, value, -1))
        self.higher_data_spinBox.valueChanged.connect(
            lambda value, col_idx=4: self.dish_data_table_proxy.
            set_col_number_filter(col_idx, -1, value))
        self.data_all_check_checkBox.stateChanged.connect(
            lambda state, col_idx=5: self.data_table_check_state(
                state, col_idx))
        self.dish_data_table_model.itemChanged.connect(self.update_series)

        # Popup bind action triggers
        self.new_dish_popup.create_new_dish_btn.clicked.connect(
            self.create_new_dish)
        self.new_dish_multi_popup.pushButton_ok.clicked.connect(
            self.create_new_dish_multi)
        self.new_dish_data_popup.dateEdit.dateChanged.connect(
            self.modify_new_dish_data_popup_table)
        self.new_dish_data_popup.pushButton_ok.clicked.connect(
            self.create_new_dish_data)

        # Get current dishes
        self.load_dish_table()
        self.load_dish_data_table()
        self.new_dish_data_popup.dateEdit.setDate(QtCore.QDate.currentDate())

    def init_dish_table(self):
        self.dish_tableView.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        # Set Header data and stretch
        for col, col_name in enumerate(
            ["ID", "菜品", "价格", "近7天总售出", "操作", "备注"]):
            self.dish_table_model.setHeaderData(col, Qt.Horizontal, col_name,
                                                Qt.DisplayRole)
        self.dish_table_proxy.setSourceModel(self.dish_table_model)
        self.dish_tableView.setModel(self.dish_table_proxy)
        self.dish_tableView.setColumnHidden(0, True)
        for (col, method) in [(1, "Regex"), (2, "Number"), (3, "Number"),
                              (5, "Regex")]:
            self.dish_table_proxy.filter_method[col] = method

    def init_dish_data_table(self):
        self.data_tableView.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        for col, col_name in enumerate(
            ["Dish_ID", "日期", "菜品", "价格", "售出", "选择"]):
            self.dish_data_table_model.setHeaderData(col, Qt.Horizontal,
                                                     col_name, Qt.DisplayRole)
        self.dish_data_table_proxy.setSourceModel(self.dish_data_table_model)
        self.data_tableView.setModel(self.dish_data_table_proxy)
        self.data_tableView.setColumnHidden(0, True)
        for (col, method) in [(1, "Date"), (2, "Regex"), (3, "Number"),
                              (4, "Number")]:
            self.dish_data_table_proxy.filter_method[col] = method

    def init_graph(self):
        self.graph_chart = QChart(title="售出图")
        self.graph_chart.legend().setVisible(True)
        self.graph_chart.setAcceptHoverEvents(True)

        graph_view = QChartView(self.graph_chart)
        graph_view.setRenderHint(QPainter.Antialiasing)
        self.gridLayout_5.addWidget(graph_view)

    def init_db_connection(self):
        self.db_connection = sqlite3.connect(self.DB_FILE)
        cursor = self.db_connection.cursor()
        # check create table if not exist
        sql_create_dish_table = """ CREATE TABLE IF NOT EXISTS dish (
                                        id integer PRIMARY KEY,
                                        name text NOT NULL,
                                        price numeric Not NULL,
                                        remarks text,
                                        UNIQUE (name, price)
                                    ); """
        sql_create_dish_data_table = """ CREATE TABLE IF NOT EXISTS dish_data (
                                            dish_id integer NOT NULL REFERENCES dish(id) ON DELETE CASCADE,
                                            date date,
                                            sell_num integer DEFAULT 0,
                                            PRIMARY KEY (dish_id, date),
                                            CONSTRAINT dish_fk 
                                                FOREIGN KEY (dish_id) 
                                                REFERENCES dish (id) ON DELETE CASCADE 
                                        ); """
        sql_trigger = """
            CREATE TRIGGER IF NOT EXISTS place_holder_data
            AFTER INSERT ON dish
            BEGIN
                INSERT INTO dish_data (dish_id, date, sell_num) VALUES(new.id, null, 0);
            END;
        """
        cursor.execute(sql_create_dish_table)
        cursor.execute(sql_create_dish_data_table)
        cursor.execute("PRAGMA FOREIGN_KEYS = on")
        cursor.execute(sql_trigger)

        cursor.close()

    def load_dish_table(self):
        today = datetime.today()
        sql_select_query = """
            SELECT dish.id, dish.name, dish.price, COALESCE(SUM(dish_data.sell_num), 0), dish.remarks
            FROM dish LEFT JOIN dish_data 
            ON dish.id = dish_data.dish_id
            WHERE dish_data.date IS NULL OR dish_data.date BETWEEN date('{}') and date('{}')
            GROUP BY dish.id
            ORDER BY dish.name, dish.price;""".format(
            (today - timedelta(days=7)).strftime("%Y-%m-%d"),
            today.strftime("%Y-%m-%d"))
        cursor = self.db_connection.cursor()
        cursor.execute(sql_select_query)
        records = cursor.fetchall()
        for row_idx, record in enumerate(records):
            self.dish_table_model.appendRow(create_dish_table_row(*record))
        cursor.close()
        self.dish_tableView.setItemDelegateForColumn(
            4,
            DishTableDelegateCell(self.show_modify_dish_popup,
                                  self.delete_dish, self.dish_tableView))

    def load_dish_data_table(self):
        sql_select_query = """
            SELECT dish_data.dish_id, dish_data.date, dish.name, dish.price, dish_data.sell_num
            FROM dish_data LEFT JOIN dish  
            ON dish_data.dish_id = dish.id
            WHERE dish_data.date IS NOT NULL
            ORDER BY dish_data.date DESC, dish.name, dish.price, dish_data.sell_num;"""
        cursor = self.db_connection.cursor()
        cursor.execute(sql_select_query)
        records = cursor.fetchall()
        for row_idx, record in enumerate(records):
            self.dish_data_table_model.appendRow(
                create_dish_data_table_row(*record))
        cursor.close()
        self.lower_data_dateEdit.setDate(QDate.currentDate().addDays(-7))
        self.higher_data_dateEdit.setDate(QDate.currentDate())
        self.data_tableView.setItemDelegateForColumn(
            5, DishDataTableDelegateCell(self.data_tableView))

    def data_table_check_state(self, state, col):
        for row in range(self.dish_data_table_proxy.rowCount()):
            index = self.dish_data_table_proxy.mapToSource(
                self.dish_data_table_proxy.index(row, col))
            if index.isValid():
                self.dish_data_table_model.setData(index, str(state),
                                                   Qt.DisplayRole)

    def show_new_dish_popup(self):
        # Move popup to center
        point = self.rect().center()
        global_point = self.mapToGlobal(point)
        self.new_dish_popup.move(
            global_point - QtCore.QPoint(self.new_dish_popup.width() // 2,
                                         self.new_dish_popup.height() // 2))
        self.new_dish_popup.show()

    def show_new_dish_multi_popup(self):
        file_name = QFileDialog().getOpenFileName(None, "选择文件", "",
                                                  self.tr("CSV文件 (*.csv)"))[0]
        self.new_dish_multi_popup.tableWidget.setRowCount(0)
        if file_name:
            with open(file_name, "r") as file:
                csv_reader = csv.reader(file, delimiter=",")
                for idx, row_data in enumerate(csv_reader):
                    if len(row_data) == 2:
                        name, price = row_data
                        remark = ""
                    elif len(row_data) == 3:
                        name, price, remark = row_data
                    else:
                        QMessageBox.warning(
                            self, "格式错误",
                            self.tr('格式为"菜品 价格"或者"菜品 价格 备注"\n第{}行输入有误'.format(
                                idx)))
                        return
                    self.new_dish_multi_popup.tableWidget.insertRow(
                        self.new_dish_multi_popup.tableWidget.rowCount())
                    self.new_dish_multi_popup.tableWidget.setItem(
                        idx, 0, QTableWidgetItem(name))
                    price_type = str_type(price)
                    if price_type == str or (isinstance(
                            price_type, (float, int)) and float(price) < 0):
                        QMessageBox.warning(
                            self, "格式错误",
                            self.tr('第{}行价格输入有误'.format(idx + 1)))
                        return
                    self.new_dish_multi_popup.tableWidget.setItem(
                        idx, 1,
                        QTableWidgetItem("{:.2f}".format(float(price))))
                    self.new_dish_multi_popup.tableWidget.setItem(
                        idx, 2, QTableWidgetItem(remark))
            self.new_dish_multi_popup.show()

    def modify_new_dish_data_popup_table(self, *args, show=False):
        sql_select_query = """
                    SELECT id, name, price, dish_data.sell_num
                    FROM dish LEFT JOIN dish_data
                    ON dish.id=dish_data.dish_id
                    WHERE dish_data.date IS NULL OR dish_data.date = date('{}')
                    GROUP BY id, name, price
                    ORDER BY dish.name, dish.price;""".format(
            self.new_dish_data_popup.dateEdit.date().toString("yyyy-MM-dd"))

        cursor = self.db_connection.cursor()
        cursor.execute(sql_select_query)
        records = cursor.fetchall()
        self.new_dish_data_popup.tableWidget.setRowCount(len(records))
        self.new_dish_data_popup.tableWidget.setColumnHidden(0, True)
        for row_idx, record in enumerate(records):
            dish_id, name, price, sell_num = record
            self.new_dish_data_popup.tableWidget.setItem(
                row_idx, 0, QTableWidgetItem(str(dish_id)))
            self.new_dish_data_popup.tableWidget.setItem(
                row_idx, 1, QTableWidgetItem(name))
            self.new_dish_data_popup.tableWidget.setItem(
                row_idx, 2, QTableWidgetItem("{:.2f}".format(price)))
            spin_box = QSpinBox()
            spin_box.setMaximum(9999)
            spin_box.setValue(sell_num)
            self.new_dish_data_popup.tableWidget.setCellWidget(
                row_idx, 3, spin_box)
        cursor.close()
        if show:
            self.new_dish_data_popup.show()

    def create_new_dish(self):
        cursor = self.db_connection.cursor()
        sql_insert = """ INSERT INTO dish(name, price, remarks)
                         VALUES(?,?,?)"""
        dish_name = self.new_dish_popup.dish_name.text()
        dish_price = self.new_dish_popup.dish_price.value()
        dish_remark = self.new_dish_popup.dish_remark.toPlainText()
        try:
            cursor.execute(sql_insert, (dish_name, dish_price, dish_remark))
            new_dish_id = cursor.lastrowid
            cursor.close()
            self.db_connection.commit()
            # Update dish table and dish comboBox in UI
            self.dish_table_model.appendRow(
                create_dish_table_row(new_dish_id, dish_name, dish_price, 0,
                                      dish_remark))
            self.new_dish_popup.hide()
        except sqlite3.Error:
            cursor.close()
            QMessageBox.warning(self, "菜品价格重复", self.tr('菜品价格组合重复,请检查'))

    def create_new_dish_multi(self):
        cursor = self.db_connection.cursor()
        sql_insert = """ 
            INSERT INTO dish(name, price, remarks)     
            VALUES (?, ?, ?)"""
        for row in range(self.new_dish_multi_popup.tableWidget.rowCount()):
            dish_name = self.new_dish_multi_popup.tableWidget.item(row,
                                                                   0).text()
            dish_price = float(
                self.new_dish_multi_popup.tableWidget.item(row, 1).text())
            dish_remark = self.new_dish_multi_popup.tableWidget.item(row,
                                                                     2).text()
            try:
                cursor.execute(sql_insert,
                               (dish_name, dish_price, dish_remark))
                new_dish_id = cursor.lastrowid
                self.dish_table_model.appendRow(
                    create_dish_table_row(new_dish_id, dish_name, dish_price,
                                          0, dish_remark))
            except sqlite3.Error:
                cursor.close()
                QMessageBox.warning(
                    self, "菜品价格重复",
                    self.tr('前{}行已插入。\n第{}行菜品价格组合重复,请检查'.format(row, row + 1)))
                return
        cursor.close()
        self.db_connection.commit()
        self.new_dish_multi_popup.hide()

    def create_new_dish_data(self):
        current_date = self.new_dish_data_popup.dateEdit.date().toString(
            "yyyy-MM-dd")
        table_filter = TableFilter()
        table_filter.setSourceModel(self.dish_data_table_model)
        table_filter.set_col_regex_filter(1, current_date)
        for row in range(table_filter.rowCount()):
            index = table_filter.mapToSource(table_filter.index(0, 1))
            if index.isValid():
                self.dish_data_table_model.removeRow(index.row())
        del table_filter
        cursor = self.db_connection.cursor()
        sql_insert = """ 
            INSERT OR REPLACE INTO dish_data(dish_id, date, sell_num)     
            VALUES (?, ?, ?)"""
        for row in range(self.new_dish_data_popup.tableWidget.rowCount()):
            dish_id = int(
                self.new_dish_data_popup.tableWidget.item(row, 0).text())
            name = self.new_dish_data_popup.tableWidget.item(row, 1).text()
            price = float(
                self.new_dish_data_popup.tableWidget.item(row, 2).text())
            sell_num = self.new_dish_data_popup.tableWidget.cellWidget(
                row, 3).value()
            cursor.execute(sql_insert, (dish_id, current_date, sell_num))
            self.dish_data_table_model.appendRow(
                create_dish_data_table_row(dish_id, current_date, name, price,
                                           sell_num))
        cursor.close()
        self.db_connection.commit()
        self.new_dish_data_popup.hide()

    def delete_dish(self, dish_id):
        cursor = self.db_connection.cursor()
        sql_delete = """ DELETE FROM dish WHERE id=?"""
        cursor.execute(sql_delete, tuple([dish_id]))
        cursor.close()
        self.db_connection.commit()

        # Update dish table and dish comboBox in UI
        for row in self.dish_data_table_model.findItems(str(dish_id)):
            index = row.index()
            if index.isValid():
                self.dish_data_table_model.removeRow(index.row())

        for row in self.dish_table_model.findItems(str(dish_id)):
            index = row.index()
            if index.isValid():
                self.dish_table_model.removeRow(index.row())

    def show_modify_dish_popup(self, dish_id):
        point = self.rect().center()
        global_point = self.mapToGlobal(point)
        self.modify_dish_popup.move(
            global_point - QtCore.QPoint(self.modify_dish_popup.width() // 2,
                                         self.modify_dish_popup.height() // 2))
        # Find the row and get necessary info
        index = self.dish_table_model.match(self.dish_table_model.index(0, 0),
                                            Qt.DisplayRole, str(dish_id))
        if index:
            row_idx = index[0]
            dish_name = self.dish_table_model.data(row_idx.siblingAtColumn(1))
            dish_price = self.dish_table_model.data(row_idx.siblingAtColumn(2))
            dish_remark = self.dish_table_model.data(
                row_idx.siblingAtColumn(5))
            self.modify_dish_popup.dish_name.setText(dish_name)
            self.modify_dish_popup.dish_price.setValue(float(dish_price))
            self.modify_dish_popup.dish_remark.setText(dish_remark)

            try:
                self.modify_dish_popup.modify_dish_btn.clicked.disconnect()
            except TypeError:
                pass
            self.modify_dish_popup.modify_dish_btn.clicked.connect(
                lambda: self.modify_dish(row_idx, dish_id))
            self.modify_dish_popup.show()

    def modify_dish(self, row, dish_id):
        cursor = self.db_connection.cursor()
        sql_update = """ UPDATE dish
                         SET name = ?, price = ?, remarks = ?
                         WHERE id=?"""
        dish_name = self.modify_dish_popup.dish_name.text()
        dish_price = self.modify_dish_popup.dish_price.value()
        dish_remark = self.modify_dish_popup.dish_remark.toPlainText()
        cursor.execute(sql_update,
                       (dish_name, dish_price, dish_remark, dish_id))
        cursor.close()
        self.db_connection.commit()
        self.modify_dish_popup.hide()

        # Update dish table and dish comboBox in UI
        old_name = self.dish_table_model.data(row.siblingAtColumn(1))
        old_price = self.dish_table_model.data(row.siblingAtColumn(2))
        sell_num = self.dish_table_model.data(row.siblingAtColumn(3))
        row_idx = row.row()
        self.dish_table_model.removeRow(row_idx)
        self.dish_table_model.insertRow(
            row_idx,
            create_dish_table_row(dish_id, dish_name, dish_price, sell_num,
                                  dish_remark))

        for row in self.dish_data_table_model.findItems(str(dish_id)):
            index = row.index()
            if index.isValid():
                self.dish_data_table_model.setData(index.siblingAtColumn(2),
                                                   dish_name)
                self.dish_data_table_model.setData(index.siblingAtColumn(3),
                                                   "{:.2f}".format(dish_price))
        old_key = old_name + '(' + old_price + ')'
        if old_key in self.graph_line_series:
            self.graph_line_series[dish_name + '(' + str(dish_price) +
                                   ')'] = self.graph_line_series[old_key]
            del self.graph_line_series[old_key]

    def update_series(self, item: QStandardItem):
        if item.column() == 5:  # check for checkbox column
            item_idx = item.index()
            date = self.dish_data_table_model.data(item_idx.siblingAtColumn(1))
            dish_name = self.dish_data_table_model.data(
                item_idx.siblingAtColumn(2))
            dish_price = self.dish_data_table_model.data(
                item_idx.siblingAtColumn(3))
            sell_num = self.dish_data_table_model.data(
                item_idx.siblingAtColumn(4))
            set_name = dish_name + "(" + dish_price + ")"
            key = str(
                QDateTime(QDate.fromString(date,
                                           "yyyy-MM-dd")).toSecsSinceEpoch())
            if key not in self.graph_series:
                self.graph_series[key] = {}

            if int(item.text()) == 0:
                if set_name in self.graph_series[key]:
                    del self.graph_series[key][set_name]
                if not self.graph_series[key]:
                    del self.graph_series[key]
            else:
                self.graph_series[key][set_name] = int(sell_num)

    def update_graph(self, index):
        if index == 2:
            self.graph_chart.removeAllSeries()

            axis_x = QBarCategoryAxis()
            axis_x.setTitleText("日期")
            if self.graph_chart.axisX():
                self.graph_chart.removeAxis(self.graph_chart.axisX())
            self.graph_chart.addAxis(axis_x, Qt.AlignBottom)

            axis_y = QValueAxis()
            axis_y.setLabelFormat("%i")
            axis_y.setTitleText("售出量")
            if self.graph_chart.axisY():
                self.graph_chart.removeAxis(self.graph_chart.axisY())
            self.graph_chart.addAxis(axis_y, Qt.AlignLeft)

            max_num = 0
            total_date = 0
            set_dict = {}
            for key, data in sorted(self.graph_series.items(),
                                    key=lambda i: int(i[0])):
                axis_x.append(
                    QDateTime.fromSecsSinceEpoch(
                        int(key)).toString("yyyy年MM月dd日"))
                for set_name, value in data.items():
                    if set_name not in set_dict:
                        set_dict[set_name] = QBarSet(set_name)
                        for _ in range(total_date):
                            set_dict[set_name].append(0)
                    set_dict[set_name].append(value)
                    max_num = max(max_num, value)
                total_date += 1
                for _, bar_set in set_dict.items():
                    if bar_set.count() < total_date:
                        bar_set.append(0)
            bar_series = QBarSeries()
            for _, bar_set in set_dict.items():
                bar_series.append(bar_set)
            bar_series.hovered.connect(self.graph_tooltip)
            axis_y.setMax(max_num + 1)
            axis_y.setMin(0)
            self.graph_chart.addSeries(bar_series)
            bar_series.attachAxis(axis_x)
            bar_series.attachAxis(axis_y)

    def graph_tooltip(self, status, index, bar_set: QBarSet):
        if status:
            QToolTip.showText(
                QCursor.pos(),
                "{}\n日期: {}\n售出: {}".format(bar_set.label(),
                                            self.graph_chart.axisX().at(index),
                                            int(bar_set.at(index))))
示例#17
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.setWindowTitle("Demo12_4, 对数坐标轴和多坐标轴")
        self.__buildStatusBar()
        self.ui.frameSetup.setEnabled(False)  #禁用控制面板

        ## 创建QmyChartView对象,并添加到窗口上
        self.ui.chartView.setRenderHint(QPainter.Antialiasing)
        self.ui.chartView.setCursor(Qt.CrossCursor)  #设置鼠标指针为十字星
        self.__iniChart()  # 创建self.chart

##  ==============自定义功能函数========================

    def __buildStatusBar(self):  ##构建状态栏
        self.__labMagXY = QLabel("幅频曲线,")
        self.__labMagXY.setMinimumWidth(250)
        self.ui.statusBar.addWidget(self.__labMagXY)

        self.__labPhaseXY = QLabel("相频曲线,")
        self.__labPhaseXY.setMinimumWidth(250)
        self.ui.statusBar.addWidget(self.__labPhaseXY)

    def __iniChart(self):  ##图表初始化
        self.chart = QChart()  #创建 chart
        self.chart.setTitle("二阶系统频率特性")
        self.chart.legend().setVisible(True)
        self.ui.chartView.setChart(self.chart)  #chart添加到chartView

        ##2. 创建坐标轴
        ## bottom 轴是 QLogValueAxis
        self.__axisFreq = QLogValueAxis()
        self.__axisFreq.setLabelFormat("%.1f")  #标签格式
        self.__axisFreq.setTitleText("角频率(rad/sec)")
        self.__axisFreq.setRange(0.1, 100)
        self.__axisFreq.setMinorTickCount(9)
        self.chart.addAxis(self.__axisFreq, Qt.AlignBottom)

        ## left 轴是 QValueAxis
        self.__axisMag = QValueAxis()
        self.__axisMag.setTitleText("幅度(dB)")
        self.__axisMag.setRange(-40, 10)
        self.__axisMag.setTickCount(6)
        self.__axisMag.setLabelFormat("%.1f")  #标签格式
        self.chart.addAxis(self.__axisMag, Qt.AlignLeft)

        ## right 轴是 QValueAxis
        self.__axisPhase = QValueAxis()
        self.__axisPhase.setTitleText("相位(度)")
        self.__axisPhase.setRange(-200, 0)
        self.__axisPhase.setTickCount(6)
        self.__axisPhase.setLabelFormat("%.0f")  #标签格式
        self.chart.addAxis(self.__axisPhase, Qt.AlignRight)

    def __loadData(self, allLines):  ##从字符串列表读取数据
        rowCnt = len(allLines)  #文本行数
        self.__vectW = [0] * rowCnt
        self.__vectMag = [0] * rowCnt
        self.__VectPhase = [0] * rowCnt

        for i in range(rowCnt):
            lineText = allLines[i].strip()  #一行的文字,必须去掉末尾的\n
            strList = lineText.split()  #分割为字符串列表
            self.__vectW[i] = float(strList[0])  #频率
            self.__vectMag[i] = float(strList[1])  #幅度
            self.__VectPhase[i] = float(strList[2])  #相位

    def __drawBode(self):
        self.chart.removeAllSeries()  #删除所有序列
        ## 创建序列
        pen = QPen(Qt.red)
        pen.setWidth(2)

        seriesMag = QLineSeries()  #幅频曲线序列
        seriesMag.setName("幅频曲线")
        seriesMag.setPen(pen)
        seriesMag.setPointsVisible(False)
        seriesMag.hovered.connect(self.do_seriesMag_hovered)

        seriesPhase = QLineSeries()  #相频曲线序列
        pen.setColor(Qt.blue)
        seriesPhase.setName("相频曲线")
        seriesPhase.setPen(pen)
        seriesPhase.setPointsVisible(True)
        seriesPhase.hovered.connect(self.do_seriesPhase_hovered)

        ## 为序列添加数据点
        count = len(self.__vectW)  #数据点数
        for i in range(count):
            seriesMag.append(self.__vectW[i], self.__vectMag[i])
            seriesPhase.append(self.__vectW[i], self.__VectPhase[i])

    ##设置坐标轴范围
        minMag = min(self.__vectMag)
        maxMag = max(self.__vectMag)
        minPh = min(self.__VectPhase)
        maxPh = max(self.__VectPhase)
        self.__axisMag.setRange(minMag, maxMag)
        self.__axisPhase.setRange(minPh, maxPh)

        ##序列添加到chart,并指定坐标轴
        self.chart.addSeries(seriesMag)
        seriesMag.attachAxis(self.__axisFreq)
        seriesMag.attachAxis(self.__axisMag)

        self.chart.addSeries(seriesPhase)
        seriesPhase.attachAxis(self.__axisFreq)
        seriesPhase.attachAxis(self.__axisPhase)

        for marker in self.chart.legend().markers():  #QLegendMarker类型列表
            marker.clicked.connect(self.do_LegendMarkerClicked)

##  ==============event处理函数==========================

##  ==========由connectSlotsByName()自动连接的槽函数============

    @pyqtSlot()  ##打开数据
    def on_actOpen_triggered(self):
        curPath = QDir.currentPath()  #获取当前路径
        filename, flt = QFileDialog.getOpenFileName(
            self, "打开一个文件", curPath, "频率响应数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return

        aFile = open(filename, 'r')
        allLines = aFile.readlines()  #读取所有行,list类型,每行末尾带有 \n
        aFile.close()
        fileInfo = QFileInfo(filename)
        QDir.setCurrent(fileInfo.absolutePath())

        self.__loadData(allLines)  #解析数据
        self.__drawBode()  #绘制幅频曲线和相频曲线
        self.ui.frameSetup.setEnabled(True)

    @pyqtSlot()  ##放大
    def on_actZoomIn_triggered(self):
        self.ui.chartView.chart().zoom(1.2)

    @pyqtSlot()  ##缩小
    def on_actZoomOut_triggered(self):
        self.ui.chartView.chart().zoom(0.8)

    @pyqtSlot()  ##原始大小
    def on_actZoomReset_triggered(self):
        self.ui.chartView.chart().zoomReset()

##图表外观控制

    @pyqtSlot(int)  ##主题
    def on_comboTheme_currentIndexChanged(self, index):
        self.ui.chartView.chart().setTheme(QChart.ChartTheme(index))

    @pyqtSlot(bool)  ##显示图例
    def on_chkBox_Legend_clicked(self, checked):
        self.ui.chartView.chart().legend().setVisible(checked)

## 幅频曲线设置

    @pyqtSlot()  ##设置坐标范围
    def on_btnMag_SetRange_clicked(self):
        self.__axisMag.setRange(self.ui.spinMag_Min.value(),
                                self.ui.spinMag_Max.value())

    @pyqtSlot(int)  ##分度数
    def on_spinMag_Ticks_valueChanged(self, arg1):
        self.__axisMag.setTickCount(arg1)

    @pyqtSlot(bool)  ##显示数据点
    def on_chkBoxMag_Point_clicked(self, checked):
        seriesMag = self.chart.series()[0]
        seriesMag.setPointsVisible(checked)

## 相频曲线设置

    @pyqtSlot()  ##设置坐标范围
    def on_btnPh_SetRange_clicked(self):
        self.__axisPhase.setRange(self.ui.spinPh_Min.value(),
                                  self.ui.spinPh_Max.value())

    @pyqtSlot(int)  ##分度数
    def on_spinPh_Ticks_valueChanged(self, arg1):
        self.__axisPhase.setTickCount(arg1)

    @pyqtSlot(bool)  ##显示数据点
    def on_chkBoxPh_Point_clicked(self, checked):
        seriesPhase = self.chart.series()[1]
        seriesPhase.setPointsVisible(checked)

## 频率坐标轴

    @pyqtSlot()  ##设置坐标范围
    def on_btnX_SetRange_clicked(self):
        self.__axisFreq.setRange(self.ui.spinX_Min.value(),
                                 self.ui.spinX_Max.value())

    @pyqtSlot(int)  ##次分度数
    def on_spinX_MinorTicks_valueChanged(self, arg1):
        self.__axisFreq.setMinorTickCount(arg1)

##  =============自定义槽函数===============================

    def do_LegendMarkerClicked(self):
        marker = self.sender()  #QLegendMarker
        if (marker.type() != QLegendMarker.LegendMarkerTypeXY):
            return

        marker.series().setVisible(not marker.series().isVisible())
        marker.setVisible(True)
        alpha = 1.0
        if not marker.series().isVisible():
            alpha = 0.5

        brush = marker.labelBrush()  #QBrush
        color = brush.color()  #QColor
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setLabelBrush(brush)

        brush = marker.brush()
        color = brush.color()
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setBrush(brush)

        pen = marker.pen()  #QPen
        color = pen.color()
        color.setAlphaF(alpha)
        pen.setColor(color)
        marker.setPen(pen)

    def do_seriesMag_hovered(self, point, state):
        if state:
            hint = "幅频曲线:频率=%.1f, 幅度=%.1f dB" % (point.x(), point.y())
            self.__labMagXY.setText(hint)
##      else:
##         self.__labMagXY.setText("幅频曲线")

    def do_seriesPhase_hovered(self, point, state):
        if state:
            hint = "相频曲线:频率=%.1f, 相位=%.1f 度" % (point.x(), point.y())
            self.__labPhaseXY.setText(hint)
示例#18
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.setWindowTitle("Demo12_6, 蜡烛图、日期时间坐标轴")
        self.__buildStatusBar()

        self.ui.chartView.setRenderHint(QPainter.Antialiasing)
        self.ui.chartView.setCursor(Qt.CrossCursor)  #设置鼠标指针为十字星

        ## 初始化Model/View结构
        self.itemModel = QStandardItemModel(self)
        self.ui.tableView.setModel(self.itemModel)
        self.ui.tableView.setAlternatingRowColors(True)
        self.ui.tableView.horizontalHeader().setDefaultSectionSize(80)
        self.ui.tableView.verticalHeader().setDefaultSectionSize(24)

        self.__iniChart()  # 初始化图表
        self.ui.chartView.mouseMove.connect(self.do_chartView_mouseMove)

##  ==============自定义功能函数========================

    def __buildStatusBar(self):
        self.__labChartXY = QLabel("Chart Y= ")  ##状态栏显示鼠标点的坐标
        self.__labChartXY.setMinimumWidth(200)
        self.ui.statusBar.addWidget(self.__labChartXY)

        self.__labHoverXY = QLabel("Hovered candle")
        self.__labHoverXY.setMinimumWidth(200)
        self.ui.statusBar.addWidget(self.__labHoverXY)

        self.__labClickXY = QLabel("Clicked candle")
        ##      self.__labClickXY.setMinimumWidth(200)
        self.ui.statusBar.addPermanentWidget(self.__labClickXY)

    def __iniChart(self):
        self.chart = QChart()  #创建 Chart
        self.chart.setTitle("股票日线图")
        self.chart.setTheme(
            QChart.ChartThemeBlueCerulean
        )  #ChartThemeBlueCerulean, ChartThemeQt,ChartThemeBlueNcs,ChartThemeDark
        self.ui.chartView.setChart(self.chart)  #Chart添加到ChartView

        ## X 轴是QDateTimeAxis
        self.__axisX = QDateTimeAxis()
        dateFormat = self.ui.comboDateFormat.currentText()  #如"MM-dd"
        self.__axisX.setFormat(dateFormat)  #标签格式
        self.__axisX.setTickCount(10)  #主分隔个数
        self.__axisX.setTitleText("日期")  #标题

        dateMin = QDateTime.fromString("2018-01-01", "yyyy-MM-dd")
        self.__axisX.setMin(dateMin)
        dateMax = dateMin.addDays(150)
        self.__axisX.setMax(dateMax)
        self.chart.addAxis(self.__axisX, Qt.AlignBottom)

        ## Y 轴是 QValueAxis
        self.__axisY = QValueAxis()
        self.__axisY.setTitleText("Value")
        self.__axisY.setRange(0, 20)
        self.__axisY.setTickCount(5)
        self.__axisY.setLabelFormat("%.2f")  #标签格式
        self.chart.addAxis(self.__axisY, Qt.AlignLeft)

    def __loadData(self, allLines):  ##从字符串列表读取数据构建数据模型
        rowCount = len(allLines)  #文本行数,第1行是标题
        self.itemModel.setRowCount(rowCount - 1)  #实际数据行数
        ## 设置表头
        header = allLines[0].strip()  #第1行是表头
        headerList = header.split()
        self.itemModel.setHorizontalHeaderLabels(headerList)  #设置表头文字

        colCount = len(headerList)  #列数
        self.itemModel.setColumnCount(colCount)  #数据列数

        ## 设置模型数据
        for i in range(rowCount - 1):
            lineText = allLines[i + 1].strip()  #获取 数据区 的一行
            tmpList = lineText.split()
            for j in range(colCount):
                item = QStandardItem(tmpList[j])  #创建item
                item.setTextAlignment(Qt.AlignHCenter)
                self.itemModel.setItem(i, j, item)  #为模型的某个行列位置设置Item

    def __drawChart(self):  ##绘制图表
        self.chart.removeAllSeries()  #删除所有序列
        self.chart.setTitle("股票日线图--" + self.ui.tabWidget.tabText(0))

        ## 1. 创建蜡烛图
        seriesCandle = QCandlestickSeries()
        seriesCandle.setName("蜡烛图")
        seriesCandle.setIncreasingColor(Qt.red)  #暴涨
        seriesCandle.setDecreasingColor(Qt.darkGreen)  #暴跌

        visible = self.ui.chkBox_Outline.isChecked()
        seriesCandle.setBodyOutlineVisible(visible)
        seriesCandle.setCapsVisible(self.ui.chkBox_Caps.isChecked())

        self.chart.addSeries(seriesCandle)
        seriesCandle.attachAxis(self.__axisX)
        seriesCandle.attachAxis(self.__axisY)

        seriesCandle.clicked.connect(self.do_candleClicked)
        seriesCandle.hovered.connect(self.do_candleHovered)

        ## 2. 创建MA曲线
        pen = QPen()
        pen.setWidth(2)

        seriesMA1 = QLineSeries()  #不能使用QSplineSeries
        seriesMA1.setName("MA5")
        pen.setColor(Qt.magenta)
        seriesMA1.setPen(pen)
        self.chart.addSeries(seriesMA1)
        seriesMA1.attachAxis(self.__axisX)
        seriesMA1.attachAxis(self.__axisY)

        seriesMA2 = QLineSeries()
        seriesMA2.setName("MA10")
        pen.setColor(Qt.yellow)
        seriesMA2.setPen(pen)
        self.chart.addSeries(seriesMA2)
        seriesMA2.attachAxis(self.__axisX)
        seriesMA2.attachAxis(self.__axisY)

        seriesMA3 = QLineSeries()
        seriesMA3.setName("MA20")
        pen.setColor(Qt.cyan)
        seriesMA3.setPen(pen)
        self.chart.addSeries(seriesMA3)
        seriesMA3.attachAxis(self.__axisX)
        seriesMA3.attachAxis(self.__axisY)

        seriesMA4 = QLineSeries()
        seriesMA4.setName("MA60")
        pen.setColor(Qt.green)  #green
        seriesMA4.setPen(pen)
        self.chart.addSeries(seriesMA4)
        seriesMA4.attachAxis(self.__axisX)
        seriesMA4.attachAxis(self.__axisY)

        ## 3. 填充数据到序列
        dataRowCount = self.itemModel.rowCount()  #数据点个数
        for i in range(dataRowCount):
            dateStr = self.itemModel.item(i, 0).text()  #日期字符串,如"2017/02/03"
            dateValue = QDate.fromString(dateStr, "yyyy/MM/dd")  #QDate
            dtValue = QDateTime(dateValue)  #日期时间 QDateTime
            timeStamp = dtValue.toMSecsSinceEpoch()  #毫秒数

            oneCandle = QCandlestickSet()  #QCandlestickSet
            oneCandle.setOpen(float(self.itemModel.item(i, 1).text()))  #开盘
            oneCandle.setHigh(float(self.itemModel.item(i, 2).text()))  #最高
            oneCandle.setLow(float(self.itemModel.item(i, 3).text()))  #最低
            oneCandle.setClose(float(self.itemModel.item(i, 4).text()))  #收盘
            oneCandle.setTimestamp(timeStamp)  #时间戳
            seriesCandle.append(oneCandle)  #添加到序列

            M1 = float(self.itemModel.item(i, 5).text())
            M2 = float(self.itemModel.item(i, 6).text())
            M3 = float(self.itemModel.item(i, 7).text())
            M4 = float(self.itemModel.item(i, 8).text())

            seriesMA1.append(timeStamp, M1)
            seriesMA2.append(timeStamp, M2)
            seriesMA3.append(timeStamp, M3)
            seriesMA4.append(timeStamp, M4)

    ## 4. 设置坐标轴范围
        minDateStr = self.itemModel.item(0, 0).text()  #日期字符串,如"2017/02/03"
        minDate = QDate.fromString(minDateStr, "yyyy/MM/dd")  #QDate
        minDateTime = QDateTime(minDate)  #最小日期时间,QDateTime

        maxDateStr = self.itemModel.item(dataRowCount - 1,
                                         0).text()  #日期字符串,如"2017/05/03"
        maxDate = QDate.fromString(maxDateStr, "yyyy/MM/dd")
        maxDateTime = QDateTime(maxDate)  #最大日期时间

        self.__axisX.setRange(minDateTime, maxDateTime)  #日期时间范围
        dateFormat = self.ui.comboDateFormat.currentText()  #格式,如"MM-dd"
        self.__axisX.setFormat(dateFormat)  #标签格式

        self.__axisY.applyNiceNumbers()  #自动

        for marker in self.chart.legend().markers():  #QLegendMarker类型列表
            marker.clicked.connect(self.do_LegendMarkerClicked)

##  ==============event处理函数==========================

##  ==========由connectSlotsByName()自动连接的槽函数============

    @pyqtSlot()  ##“打开文件”按钮
    def on_actOpen_triggered(self):
        curPath = QDir.currentPath()
        filename, flt = QFileDialog.getOpenFileName(
            self, "打开一个文件", curPath, "股票数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return

        aFile = open(filename, 'r')
        allLines = aFile.readlines()  #读取所有行,list类型,每行末尾带有 \n
        aFile.close()
        fileInfo = QFileInfo(filename)
        QDir.setCurrent(fileInfo.absolutePath())
        self.ui.tabWidget.setTabText(0, fileInfo.baseName())

        self.__loadData(allLines)  # 载入数据到数据模型
        self.__drawChart()  # 绘制图表
        self.ui.tab_Setup.setEnabled(True)

    @pyqtSlot()
    def on_actZoomIn_triggered(self):
        self.ui.chartView.chart().zoom(1.2)

    @pyqtSlot()
    def on_actZoomOut_triggered(self):
        self.ui.chartView.chart().zoom(0.8)

    @pyqtSlot()
    def on_actZoomReset_triggered(self):
        self.ui.chartView.chart().zoomReset()

##图表外观控制

    @pyqtSlot(int)  ##主题
    def on_comboTheme_currentIndexChanged(self, index):
        self.ui.chartView.chart().setTheme(QChart.ChartTheme(index))

    @pyqtSlot(bool)  ##显示图例
    def on_chkBox_Legend_clicked(self, checked):
        self.ui.chartView.chart().legend().setVisible(checked)

    ## 蜡烛图
    @pyqtSlot(bool)  ##capsVisible
    def on_chkBox_Caps_clicked(self, checked):
        seriesCandle = self.chart.series()[0]
        seriesCandle.setCapsVisible(checked)

    @pyqtSlot(bool)  ##bodyOutlineVisible
    def on_chkBox_Outline_clicked(self, checked):
        seriesCandle = self.chart.series()[0]
        seriesCandle.setBodyOutlineVisible(checked)

## Y轴--QValueAxis

    @pyqtSlot()  ##设置坐标范围
    def on_btnY_SetRange_clicked(self):
        self.__axisY.setRange(self.ui.spinY_Min.value(),
                              self.ui.spinY_Max.value())

    @pyqtSlot(int)  ##分度数
    def on_spinY_Ticks_valueChanged(self, arg1):
        self.__axisY.setTickCount(arg1)

    ## X轴--QDateTimeAxis
    @pyqtSlot(str)  ##标签格式
    def on_comboDateFormat_currentIndexChanged(self, arg1):
        self.__axisX.setFormat(arg1)

    @pyqtSlot(int)  ##分度数
    def on_btnX_Ticks_valueChanged(self, arg1):
        self.__axisX.setTickCount(arg1)

##  =============自定义槽函数===============================

    def do_LegendMarkerClicked(self):
        marker = self.sender()  #QLegendMarker

        marker.series().setVisible(not marker.series().isVisible())
        marker.setVisible(True)
        alpha = 1.0
        if not marker.series().isVisible():
            alpha = 0.5

        brush = marker.labelBrush()  #QBrush
        color = brush.color()  #QColor
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setLabelBrush(brush)

        brush = marker.brush()
        color = brush.color()
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setBrush(brush)

        pen = marker.pen()  #QPen
        color = pen.color()
        color.setAlphaF(alpha)
        pen.setColor(color)
        marker.setPen(pen)

        if marker.type() == QLegendMarker.LegendMarkerTypeCandlestick:
            QMessageBox.information(self, "提示", "蜡烛图序列无法隐藏")

    def do_chartView_mouseMove(self, point):
        pt = self.chart.mapToValue(point)  #QPointF 转换为图表的数值
        self.__labChartXY.setText("Chart Y=%.2f" % (pt.y()))  #状态栏显示

    def do_candleClicked(self, dataSet):
        valOpen = dataSet.open()
        valClose = dataSet.close()
        valHigh = dataSet.high()
        valLow = dataSet.low()
        price = "开盘%.2f, 收盘%.2f, 最高%.2f, 最低%.2f" % (valOpen, valClose, valHigh,
                                                    valLow)

        timeStamp = dataSet.timestamp()  #时间戳数据
        dt = QDateTime.fromMSecsSinceEpoch(timeStamp)
        dateStr = dt.toString("yyyy-MM-dd, ")

        self.__labClickXY.setText(dateStr + price)

    def do_candleHovered(self, status, dataSet):
        if status == False:
            self.__labHoverXY.setText("Hovered candle")
            return

        valOpen = dataSet.open()
        valClose = dataSet.close()
        valHigh = dataSet.high()
        valLow = dataSet.low()
        price = "开盘%.2f, 收盘%.2f, 最高%.2f, 最低%.2f" % (valOpen, valClose, valHigh,
                                                    valLow)

        timeStamp = dataSet.timestamp()  #时间戳数据
        dt = QDateTime.fromMSecsSinceEpoch(timeStamp)
        dateStr = dt.toString("yyyy-MM-dd, ")

        self.__labHoverXY.setText(dateStr + price)
class Gui:
    def __init__(self):
        # loading widgets elements from ui file
        self.window = uic.loadUi("min_function.ui")

        # Getting widgets elements
        self.single_run_rb = self.window.findChild(QRadioButton,
                                                   'singleRunRadioButton')
        self.multi_run_rb = self.window.findChild(QRadioButton,
                                                  'multiRunRadioButton')
        self.repetitions_sb = self.window.findChild(QSpinBox,
                                                    'repetitionsSpinBox')
        self.population_sb = self.window.findChild(QSpinBox,
                                                   'populationSpinBox')
        self.crossover_dsb = self.window.findChild(QDoubleSpinBox,
                                                   'crossoverDoubleSpinBox')
        self.mutation_dsb = self.window.findChild(QDoubleSpinBox,
                                                  'mutationDoubleSpinBox')
        self.generation_sb = self.window.findChild(QSpinBox,
                                                   'generationSpinBox')
        self.elitism_cb = self.window.findChild(QCheckBox, 'elitismCheckBox')
        self.run_pb = self.window.findChild(QPushButton, 'runPushButton')
        self.x_result_l = self.window.findChild(QLabel, 'xResultLabel')
        self.fx_l = self.window.findChild(QLabel, 'fxLabel')
        self.correct_results_l = self.window.findChild(QLabel,
                                                       'correctResultsLabel')
        self.incorrect_results_l = self.window.findChild(
            QLabel, 'incorrectResultsLabel')
        self.results_single_run_gb = self.window.findChild(
            QGroupBox, 'resultsSingleRunGroupBox')
        self.results_multi_run_gb = self.window.findChild(
            QGroupBox, 'resultsMultiRunGroupBox')
        self.icon_result_l = self.window.findChild(QLabel, 'iconResultLabel')
        self.graph_vbl = self.window.findChild(QVBoxLayout,
                                               'graphVerticalLayout')

        # Connecting
        self.run_pb.clicked.connect(self.on_run_pb_clicked)
        self.multi_run_rb.toggled.connect(self.on_multi_run_rb_toggled)

        # Graph settings
        self.chart = QChart()
        self.chart.setTitle('Chart')
        self.chart_view = QChartView(self.chart)
        self.chart_view.setRenderHint(QPainter.Antialiasing)
        self.graph_vbl.addWidget(self.chart_view)

        self.repetitions_sb.setEnabled(False)
        self.results_multi_run_gb.setEnabled(False)

        # EVEN values ONLY
        self.population_sb.lineEdit().setEnabled(False)

    def on_multi_run_rb_toggled(self):
        if self.multi_run_rb.isChecked():
            self.repetitions_sb.setEnabled(True)
            self.repetitions_sb.setValue(100)
            self.results_single_run_gb.setEnabled(False)
            self.results_multi_run_gb.setEnabled(True)
            self.chart_view.setEnabled(False)
        else:
            self.repetitions_sb.setEnabled(False)
            self.repetitions_sb.setValue(1)
            self.results_single_run_gb.setEnabled(True)
            self.results_multi_run_gb.setEnabled(False)
            self.chart_view.setEnabled(True)

    def on_run_pb_clicked(self):
        self.chart.removeAllSeries()
        min_function = 421.0
        ga_answer = 0.0
        correct = 0
        incorrect = 0

        ga = Ga(self.population_sb.value(), self.crossover_dsb.value(),
                self.mutation_dsb.value(), self.generation_sb.value(),
                self.elitism_cb.isChecked())

        progress_dialog = QProgressDialog('Repetitions...', 'Cancel', 0,
                                          self.repetitions_sb.value(),
                                          self.window)
        progress_dialog.setWindowModality(Qt.WindowModal)
        ga_output = ()
        for i in range(self.repetitions_sb.value()):
            ga_output = ga.run_generation()
            ga_answer = ga_output[0]

            if ga_answer == min_function:
                correct += 1
            else:
                incorrect += 1
            progress_dialog.setValue(i)

            if progress_dialog.wasCanceled():
                break

        progress_dialog.setValue(self.repetitions_sb.value())

        if self.single_run_rb.isChecked():
            self.x_result_l.setText(str(ga_answer))
            self.fx_l.setText('{0:.2f}'.format(ga.calc_function(ga_answer)))
            if ga_answer == min_function:
                self.icon_result_l.setPixmap('correct-icon.png')
            else:
                self.icon_result_l.setPixmap('incorrect-icon.png')

            # Graph
            series_1 = QLineSeries()
            series_1.setName('Average Fit')
            series_2 = QLineSeries()
            series_2.setName('Best Fit')
            for i in range(len(ga_output[1])):
                series_1.append(ga_output[1][i], ga_output[2][i])
                series_2.append(ga_output[1][i], ga_output[3][i])
            self.chart.addSeries(series_1)
            self.chart.addSeries(series_2)
            self.chart.createDefaultAxes()

        else:
            self.correct_results_l.setText(str(correct))
            self.incorrect_results_l.setText(str(incorrect))
示例#20
0
class DiagramForm(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.db = None
        self.tool_bar = QToolBar(self)
        self.action_inout = self.tool_bar.addAction("Доход/расход")
        self.date_edit = CustomCalendar()
        self.date_edit.button_up.clicked.connect(self.date_changed)
        self.date_edit.button_down.clicked.connect(self.date_changed)
        self.tool_bar.addWidget(self.date_edit)
        self.action_inout.setIcon(QIcon("icons/consumption.ico"))
        self.action_inout.triggered.connect(self.change_state_action_inout)
        self.type_inout = False

        #

        #for item in db.get_sum_by_category():
        #    series.append(item[1], item[0])

        # series.append("Еда", 80)
        # series.append("Хозяйственные товары", 40)
        # series.append("Развлечения", 40)
        # series.append("Еда", 80)
        # series.append("Хозяйственные товары", 40)
        # series.append("Развлечения", 40)

        self.chart = QChart()
        self.chart.setTheme(QChart.ChartThemeQt)
        self.chart.setAnimationOptions(QChart.AllAnimations)
        #self.chart.addSeries(series)
        self.chart.legend().setAlignment(Qt.AlignRight)
        font = QFont("Segoi UI", 11)
        self.chart.legend().setFont(font)
        self.chart.legend().setShowToolTips(True)
        self.chart.setTitleFont(QFont("Segoi UI", 16))

        chart_view = QChartView(self.chart)
        chart_view.setRenderHint(QPainter.Antialiasing)
        vbox = QVBoxLayout(self)
        vbox.addWidget(self.tool_bar)
        vbox.addWidget(chart_view)

        #update_diagram()

    def set_db(self, db):
        self.db = db

    def update_diagram(self):
        year = self.date_edit.get_year()
        month = self.date_edit.get_month()
        date_format = f"WHERE strftime(\"%Y\",DATE) = \"{year}\" AND strftime(\"%m\",DATE) = \"{month:02}\""

        series = QPieSeries()
        for item in self.db.get_sum_by_category(date_format, self.type_inout):
            series.append(item[1], item[0])

        for slice in series.slices():
            slice.setLabel(
                slice.label() + ", " + f"{slice.value()}₽" +
                f" ({round(slice.value() / (series.sum() / 100))}%)")
        series.clicked.connect(self.pressed)
        self.chart.removeAllSeries()
        self.chart.addSeries(series)
        self.chart.setTitle("Доходы" if self.type_inout else "Расходы")

    def date_changed(self):
        self.update_diagram()

    def change_state_action_inout(self):
        self.action_inout.setIcon(
            QIcon("icons/income.ico"
                  if not self.type_inout else "icons/consumption.ico"))
        self.type_inout = not self.type_inout
        self.update_diagram()

    def pressed(self, slice):
        for sl in slice.series().slices():
            sl.setExploded(False)
            sl.setLabelVisible(False)
            sl.setPen(QPen(Qt.white, 0))

        slice.setExploded(True)
        slice.setLabelVisible(True)
        slice.setPen(QPen(Qt.black, 2))
class MainW(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.showMaximized()

        self.imagen.setText("aaaaaaa")
        myimg = QtGui.QPixmap(plotImg)
        self.imagen.setPixmap(myimg)
        self.Juego1.clicked.connect(self.runjuego1)
        self.Juego2.clicked.connect(self.runjuego2)
        self.Juego3.clicked.connect(self.runjuego3)
        self.Juego4.clicked.connect(self.runjuego4)
        self.Juego5.clicked.connect(self.runjuego5)
        self.Juego6.clicked.connect(self.runjuego6)
        self.Juego7.clicked.connect(self.runjuego7)
        self.Juego8.clicked.connect(self.runjuego8)
        self.setupgraph()
        self.updatechart()
        self._actualizar.clicked.connect(self.updatechart)

        self._recargar.clicked.connect(self.recargar)

    def runjuego1(self):
        self.window = Ruleta.UIWindow()
        self.window.show()

    def runjuego2(self):
        self.window = Altos_o_Bajos_Codificacionado.MainWindow()
        self.window.show()

    def runjuego3(self):
        self.window = LootBoxGame.MyApp()
        self.window.show()

    def runjuego4(self):
        self.window = SuperTragaPerras.UIWindow()
        self.window.show()

    def runjuego5(self):
        self.window = CapsUI.UIWindow()
        self.window.show()

    def runjuego6(self):
        self.window = casino.MyApp()
        self.window.show()

    def runjuego7(self):
        self.window = keno.UIWindow()
        self.window.show()

    def runjuego8(self):
        self.window = Jackpot.UIWindow()
        self.window.show()

    def recargar(self):
        self.window = menu.MyApp()
        self.window.show()

    def setupgraph(self):
        self.chart = QChart()
        self.chart.createDefaultAxes()
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("Saldo vs Tiempo")
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)
        self._graphlayout.addWidget(self.chartview)

    def updatechart(self):
        self.series = QLineSeries(self)
        self.datos = bd.getData()
        self.c = 0
        for x in self.datos:
            self.series.append(self.c, x)
            self.c += 1
        self.chart.removeAllSeries()
        self.chart.addSeries(self.series)
        self.chart.createDefaultAxes()

    def create_linechart(self):

        self.series = QLineSeries(self)
        self.datos = bd.getData()
        self.c = 0
        for x in self.datos:
            self.series.append(self.c, x)
            self.c += 1
        self.chart = QChart()
        self.chart.addSeries(self.series)
        self.chart.createDefaultAxes()
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("Saldo vs Tiempo")
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)
        self._graphlayout.addWidget(self.chartview)
示例#22
0
class UDPBitrate(QWidget):
    def __init__(self):
        super().__init__()

        self.mainLayout = QVBoxLayout()
        self.headerLayout = QGridLayout()
        self.portLayout = QHBoxLayout()
        self.axisxLayout = QHBoxLayout()
        self.axisyLayout = QHBoxLayout()
        self.smoothLayout = QHBoxLayout()
        self.btnsLayout = QHBoxLayout()
        self.lblPort = QLabel("Port: ")
        self.lblAxisX = QLabel("X-Axis(Time): ")
        self.lblAxisY = QLabel("Y-Axis(Bitrate): ")
        self.lblSmooth = QLabel("Smooth: ")
        self.txtPort = QLineEdit()
        self.txtAxisX = QLineEdit()
        self.txtAxisY = QLineEdit()
        self.txtSmooth = QLineEdit()
        self.chkMode = QCheckBox("Stack Mode")
        self.btnStart = QPushButton("Start")
        self.btnExport = QPushButton("Export")
        self.btnStart.clicked.connect(self.onStartClick)
        self.btnExport.clicked.connect(self.onExportClick)

        self.portLayout.addWidget(self.lblPort)
        self.portLayout.addWidget(self.txtPort)

        self.axisxLayout.addWidget(self.lblAxisX)
        self.axisxLayout.addWidget(self.txtAxisX)

        self.axisyLayout.addWidget(self.lblAxisY)
        self.axisyLayout.addWidget(self.txtAxisY)

        self.smoothLayout.addWidget(self.lblSmooth)
        self.smoothLayout.addWidget(self.txtSmooth)

        self.btnsLayout.addWidget(self.chkMode)
        self.btnsLayout.addWidget(self.btnStart)
        self.btnsLayout.addWidget(self.btnExport)

        self.headerLayout.addLayout(self.portLayout, 0, 0, 1, 3)
        self.headerLayout.addLayout(self.axisxLayout, 0, 3, 1, 2)
        self.headerLayout.addLayout(self.axisyLayout, 0, 5, 1, 2)
        self.headerLayout.addLayout(self.smoothLayout, 0, 7, 1, 2)
        self.headerLayout.addLayout(self.btnsLayout, 0, 9, 1, 2)

        self.chart = QChart()
        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.HighQualityAntialiasing)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.setTitle("UDP Bitrate")

        self.mainLayout.addLayout(self.headerLayout)
        self.mainLayout.addWidget(self.chartview)

        self.timer = QTimer()
        self.timer.timeout.connect(self.onTimeOut)

        self.axis_x_unit_str = ["Sec", "Min", "Hour", "Day"]
        self.axis_y_unit_str = ["bps", "Kbps", "Mbps", "Gbps"]
        self.axis_x_unit_scale = [1, 60, 3600, 3600 * 24]
        self.axis_y_unit_scale = [1, 1e3, 1e6, 1e9]
        self.axis_x_default_resolution = 1000

        self.ports = []
        self.udpthreads = []
        self.smooth_alpha = 0.0

        if os.path.exists("udpbitrate.conf"):
            with open("udpbitrate.conf", "r") as fp:
                try:
                    json_data = json.load(fp)
                    self.txtPort.setText(json_data.get("port", ""))
                    self.txtAxisX.setText(json_data.get("x-axis", "1000s"))
                    self.txtAxisY.setText(json_data.get("y-axis", "10m"))
                    self.txtSmooth.setText(json_data.get("smooth", "0"))
                    self.chkMode.setChecked(json_data.get("mode", False))
                finally:
                    pass

        self.setWindowTitle("UDP Bitrate")
        self.setLayout(self.mainLayout)
        self.resize(960, 600)
        self.show()

    def onStartClick(self):
        if self.btnStart.text() == "Start":
            self.btnStart.setText("Stop")
            self.chkMode.setEnabled(False)
            self.txtPort.setEnabled(False)
            self.txtAxisX.setEnabled(False)
            self.txtAxisY.setEnabled(False)
            self.txtSmooth.setEnabled(False)
            self.parse_port()
            self.parse_axis_x()
            self.parse_axis_y()
            self.parse_smooth()
            self.start_record()
            json_data = {
                "port": self.txtPort.text(),
                "x-axis": self.txtAxisX.text(),
                "y-axis": self.txtAxisY.text(),
                "smooth": self.txtSmooth.text(),
                "mode": self.chkMode.isChecked()
            }
            with open("udpbitrate.conf", "w") as fp:
                json.dump(json_data, fp)
        else:
            self.btnStart.setText("Start")
            self.chkMode.setEnabled(True)
            self.txtPort.setEnabled(True)
            self.txtAxisX.setEnabled(True)
            self.txtAxisY.setEnabled(True)
            self.txtSmooth.setEnabled(True)
            self.stop_record()

    def onExportClick(self):
        image = QApplication.primaryScreen().grabWindow(
            self.chartview.winId()).toImage()
        filename, filetype = QFileDialog.getSaveFileName(
            self, "Export Image", "./udpbitrate.png",
            "PNG Files (*.png);;JEPG Files (*.jpg);;All Files (*)")
        if filename:
            ext = ".jpg" if ".jpg" in filetype else ".png"
            filename = filename + ext if ext not in filename else filename
            image.save(filename)

    def onTimeOut(self):
        if self.chkMode.isChecked():
            bitrate = 0
            for i in range(len(self.udpthreads)):
                length = float(self.udpthreads[i].get_recv_length())
                bitrate += length * 8.0 / self.axis_x_step / self.axis_y_unit_scale[
                    self.axis_y_unit]
                self.add_point(bitrate, self.chart.series()[i])
        else:
            total_bitrate = 0
            for i in range(len(self.udpthreads)):
                length = float(self.udpthreads[i].get_recv_length())
                bitrate = length * 8.0 / self.axis_x_step / self.axis_y_unit_scale[
                    self.axis_y_unit]
                total_bitrate += bitrate
                self.add_point(bitrate, self.chart.series()[i])
            self.add_point(total_bitrate, self.chart.series()[-1])

    def add_point(self, val, series):
        points = series.pointsVector()
        if len(points) == 0:
            points.append(
                QPointF(
                    len(points) * self.axis_x_step /
                    self.axis_x_unit_scale[self.axis_x_unit], val))
        elif len(points) <= self.axis_x_resolution:
            val = self.smooth_alpha * points[-1].y() + (
                1 - self.smooth_alpha) * val
            points.append(
                QPointF(
                    len(points) * self.axis_x_step /
                    self.axis_x_unit_scale[self.axis_x_unit], val))
        else:
            val = self.smooth_alpha * points[-1].y() + (
                1 - self.smooth_alpha) * val
            for i in range(len(points) - 1):
                points[i] = QPointF(
                    i * self.axis_x_step /
                    self.axis_x_unit_scale[self.axis_x_unit],
                    points[i + 1].y())
            points[-1] = QPointF(
                len(points) * self.axis_x_step /
                self.axis_x_unit_scale[self.axis_x_unit], val)
        series.replace(points)

    def parse_port(self):
        self.ports = []
        s = self.txtPort.text()
        sl = map(str.strip, s.split(','))
        p = re.compile('^(\d+)\s?-\s?(\d+)$|^(\d+)$')
        for ss in sl:
            m = p.match(ss)
            if m:
                if m.group(3):
                    cur = int(m.group(3))
                    if len(self.ports) > 16:
                        break
                    if cur > 0:
                        self.ports.append(cur)
                else:
                    start, end = int(m.group(1)), int(m.group(2))
                    for cur in range(start, end + 1):
                        if len(self.ports) > 16:
                            break
                        if cur > 0:
                            self.ports.append(cur)

    def parse_axis_x(self):
        self.axis_x_val = 0
        self.axis_x_unit = 0
        s = self.txtAxisX.text().lower()
        p = re.compile(
            '^(\d+(?:\.\d+)?)\s?(s(?:ec)?|m(?:in)?|h(?:our)?|d(?:ay)?)?$')
        m = p.match(s)
        if m:
            self.axis_x_val = float(m.group(1))
            if m.group(2):
                if m.group(2) == "s" or m.group(2) == "sec":
                    self.axis_x_unit = 0
                elif m.group(2) == "m" or m.group(2) == "min":
                    self.axis_x_unit = 1
                elif m.group(2) == "h" or m.group(2) == "hour":
                    self.axis_x_unit = 2
                elif m.group(2) == "d" or m.group(2) == "day":
                    self.axis_x_unit = 3
        self.axis_x_step = self.axis_x_val * self.axis_x_unit_scale[
            self.axis_x_unit] / self.axis_x_default_resolution
        if self.axis_x_step < 0.1:
            self.axis_x_resolution = int(
                10 * self.axis_x_val *
                self.axis_x_unit_scale[self.axis_x_unit])
            self.axis_x_step = self.axis_x_val * self.axis_x_unit_scale[
                self.axis_x_unit] / self.axis_x_resolution
        else:
            self.axis_x_resolution = self.axis_x_default_resolution

    def parse_axis_y(self):
        self.axis_y_val = 0
        self.axis_y_unit = 0
        s = self.txtAxisY.text().lower()
        p = re.compile('^(\d+(?:\.\d+)?)\s?(k|m|g)?$')
        m = p.match(s)
        if m:
            self.axis_y_val = float(m.group(1))
            if m.group(2):
                if m.group(2) == "k":
                    self.axis_y_unit = 1
                elif m.group(2) == "m":
                    self.axis_y_unit = 2
                elif m.group(2) == "g":
                    self.axis_y_unit = 3

    def parse_smooth(self):
        self.smooth_alpha = 0.0
        s = self.txtSmooth.text()
        p = re.compile('^(\d+(?:\.\d+)?)\s?$')
        m = p.match(s)
        if m:
            self.smooth_alpha = float(m.group(1))
        self.smooth_alpha = self.smooth_alpha if self.smooth_alpha < 0.9999 else 0.9999

    def start_record(self):
        self.chart.removeAllSeries()
        self.series = []

        try:
            for port in self.ports:
                udp = UdpServer(port)
                udp.start()
                self.udpthreads.append(udp)
                series = QLineSeries()
                series.setName(str(port))
                self.chart.addSeries(series)
        finally:
            pass

        if not self.chkMode.isChecked():
            series = QLineSeries()
            series.setName("Total")
            self.chart.addSeries(series)

        self.chart.createDefaultAxes()

        axis_x = self.chart.axisX()
        axis_x.setRange(0, self.axis_x_val)
        axis_x.setLabelFormat("%g")
        axis_x.setTitleText("Time / " + self.axis_x_unit_str[self.axis_x_unit])

        axis_y = self.chart.axisY()
        axis_y.setRange(0, self.axis_y_val)
        axis_y.setLabelFormat("%g")
        axis_y.setTitleText("Bitrate / " +
                            self.axis_y_unit_str[self.axis_y_unit])

        self.timer.start(self.axis_x_step * 1000)

    def stop_record(self):
        if self.timer.isActive():
            self.timer.stop()
        for udp in self.udpthreads:
            udp.stop()
        self.udpthreads = []
示例#23
0
class QmyMainWindow(QMainWindow): 

   def __init__(self, parent=None):
      super().__init__(parent)   #调用父类构造函数,创建窗体
      self.ui=Ui_MainWindow()    #创建UI对象
      self.ui.setupUi(self)      #构造UI界面

      self.setWindowTitle("Demo12_7, QAreaSeries绘制填充图")
      self.__buildStatusBar()
      self.ui.chartView.setRenderHint(QPainter.Antialiasing)
      self.ui.chartView.setCursor(Qt.CrossCursor)  #设置鼠标指针为十字星
      self.ui.chartView.mouseMove.connect(self.do_chartView_mouseMove)

      self.__colorLine=Qt.darkBlue      #曲线颜色,darkBlue
      self.__colorFill=Qt.darkBlue      #填充颜色 gray
      self.__iniChart()       #创建self.chart
##  "填充类型"4个RadioButton关联槽函数
      self.ui.radioFill_Pos.clicked.connect(self.do_redrawFill)   #positive
      self.ui.radioFill_Neg.clicked.connect(self.do_redrawFill)   #negative
      self.ui.radioFill_Both.clicked.connect(self.do_redrawFill)  #both
      self.ui.radioFill_None.clicked.connect(self.do_redrawWave)  #wiggle
      

##  ==============自定义功能函数========================
   def __buildStatusBar(self):
      self.__labFileName = QLabel("数据文件")     
      self.__labFileName.setMinimumWidth(200)
      self.ui.statusBar.addWidget(self.__labFileName)

      self.__labChartXY = QLabel("Chart, X=, Y=") 
      self.__labChartXY.setMinimumWidth(200)
      self.ui.statusBar.addWidget(self.__labChartXY)
      
      self.__labAreaXY = QLabel("AreaSeries,X=, Y=") 
      self.__labAreaXY.setMinimumWidth(200)
      self.ui.statusBar.addWidget(self.__labAreaXY)

   def __iniChart(self):
      self.chart = QChart()    #创建 chart
      self.chart.setTitle("地震波形")
      self.chart.legend().setVisible(False)  #不显示图例
      self.ui.chartView.setChart(self.chart) #chart添加到chartView
## 创建坐标轴X
      self.__axisX = QValueAxis()   # bottom 轴是 QValueAxis
      self.__axisX.setTitleText("时间(秒)")
      self.__axisX.setRange(0, 10)
      self.__axisX.setTickCount(10)
      self.__axisX.setLabelFormat("%.2f")  #标签格式
      self.chart.addAxis(self.__axisX,Qt.AlignBottom)
## 创建坐标轴Y
      self.__axisY = QValueAxis()   # left 轴是 QValueAxis
      self.__axisY.setTitleText("幅度")
      self.__axisY.setRange(-5,5)
      self.__axisY.setTickCount(5)
      self.__axisY.setLabelFormat("%.2f")  #标签格式
      self.chart.addAxis(self.__axisY,Qt.AlignLeft)

##  ==============event处理函数==========================
        
        
##  ==========由connectSlotsByName()自动连接的槽函数============        
##=====工具栏 按钮功能
   @pyqtSlot()    ##“打开文件”按钮
   def on_actOpen_triggered(self):
      curPath=QDir.currentPath()    #获取当前路径
      filename,flt=QFileDialog.getOpenFileName(self,"打开一个文件",curPath,
                  "地震数据文件(*.txt);;所有文件(*.*)")
      if (filename==""):
         return

      aFile=open(filename,'r')
      allLines=aFile.readlines()  #读取所有行,list类型,每行末尾带有 \n
      aFile.close()
      fileInfo=QFileInfo(filename)
      QDir.setCurrent(fileInfo.absolutePath())
      self.__labFileName.setText("数据文件:"+fileInfo.fileName())
      
      rowCnt=len(allLines)    #行数,即数据点数
      self.__vectData=[0]*rowCnt   #列表
      for i in range(rowCnt):      
         lineText=allLines[i].strip()  #字符串表示的数字
         self.__vectData[i]=float(lineText)
      minV=min(self.__vectData)  #最小值
      self.ui.spinY_Min.setValue(minV)
      maxV=max(self.__vectData)  #最大值
      self.ui.spinY_Max.setValue(maxV)
      
      if self.ui.radioFill_None.isChecked():
         self.do_redrawWave()    #绘制波形曲线
      else:
         self.do_redrawFill()    #绘制有填充的波形
      self.ui.frameSetup.setEnabled(True)

   @pyqtSlot()
   def on_actZoomIn_triggered(self):
      self.ui.chartView.chart().zoom(1.2)
      
   @pyqtSlot()
   def on_actZoomOut_triggered(self):
      self.ui.chartView.chart().zoom(0.8)

   @pyqtSlot()
   def on_actZoomReset_triggered(self):
      self.ui.chartView.chart().zoomReset()
      
##   Y轴设置      
   @pyqtSlot()    ##设置坐标范围
   def on_btnY_SetRange_clicked(self):
      self.__axisY.setRange(self.ui.spinY_Min.value(),
                            self.ui.spinY_Max.value())
   @pyqtSlot(int)    ##分度数
   def on_spinY_Ticks_valueChanged(self,arg1):
      self.__axisY.setTickCount(arg1)

   @pyqtSlot(bool)  ##显示网格线
   def on_chkBoxY_GridLine_clicked(self,checked):
      self.__axisY.setGridLineVisible(checked)
      
##    X轴设置
   @pyqtSlot()       ##设置坐标范围
   def on_btnX_SetRange_clicked(self):
      self.__axisX.setRange(self.ui.spinX_Min.value(),
                            self.ui.spinX_Max.value())
   @pyqtSlot(int)    ##分度数
   def on_spinX_Ticks_valueChanged(self,arg1):
      self.__axisX.setTickCount(arg1)

   @pyqtSlot(bool)   ##显示网格线
   def on_chkBoxX_GridLine_clicked(self,checked):
      self.__axisX.setGridLineVisible(checked)
      
           
##  =============自定义槽函数===============================        
   @pyqtSlot()    ##绘制原始波形曲线
   def do_redrawWave(self):
      self.chart.removeAllSeries()  # 删除所有序列
      pen=QPen(self.__colorLine)    # 曲线颜色
      pen.setWidth(2)
      seriesWave = QLineSeries() 
      seriesWave.setUseOpenGL(True) 
      seriesWave.setPen(pen)

      vx=0
      intv=0.001  #1000Hz采样
      pointCount=len(self.__vectData)
      for i in range(pointCount):
         value=self.__vectData[i]
         seriesWave.append(vx,value)
         vx =vx+ intv
      self.__axisX.setRange(0,vx)

      self.chart.addSeries(seriesWave)
      seriesWave.attachAxis(self.__axisX)
      seriesWave.attachAxis(self.__axisY)
      

   @pyqtSlot()    ##绘制3种填充曲线
   def do_redrawFill(self):
      self.chart.removeAllSeries()  #删除所有序列
      pen=QPen(self.__colorLine)    #线条颜色
      pen.setWidth(2)

      seriesFullWave = QLineSeries()      #全波形
      seriesFullWave.setUseOpenGL(True)
      seriesFullWave.setPen(pen)

      seriesPositive = QLineSeries()      #正半部分曲线
      seriesPositive.setUseOpenGL(True)
      seriesPositive.setVisible(False)    #不显示

      seriesNegative = QLineSeries()      #负半部分曲线
      seriesNegative.setUseOpenGL(True)
      seriesNegative.setVisible(False)    #不显示即可

      seriesZero = QLineSeries()          #零均值线
      seriesZero.setUseOpenGL(True)
      seriesZero.setVisible(False)        #不显示即可

   ## 填充数据
      vx=0
      intv=0.001   #1000Hz采样,数据点间隔时间
      pointCount=len(self.__vectData)
      for i in range(pointCount):
         value=self.__vectData[i]
         seriesFullWave.append(vx,value)  #完整波形
         seriesZero.append(vx,0)          #零值线
         if value>0:
            seriesPositive.append(vx,value)  #正半部分波形
            seriesNegative.append(vx,0)
         else:
            seriesPositive.append(vx,0)
            seriesNegative.append(vx,value) #负半部分波形
         vx =vx+intv

      self.__axisX.setRange(0,vx)

   ##  创建QAreaSeries序列,设置上、下界的QLineSeries对象
      pen.setStyle(Qt.NoPen)  #无线条,隐藏填充区域的边线
      if self.ui.radioFill_Pos.isChecked():     #positive fill
         series = QAreaSeries(seriesPositive, seriesZero) #QAreaSeries
         series.setColor(self.__colorFill)      #填充色
         series.setPen(pen)   #不显示线条
         self.chart.addSeries(series)
         series.attachAxis(self.__axisX)
         series.attachAxis(self.__axisY)
         
      elif self.ui.radioFill_Neg.isChecked():  #negative fill
         series = QAreaSeries(seriesZero,seriesNegative)
         series.setColor(self.__colorFill)
         series.setPen(pen)   #不显示线条
         self.chart.addSeries(series)
         series.attachAxis(self.__axisX)
         series.attachAxis(self.__axisY)

      elif self.ui.radioFill_Both.isChecked():  #both fill
         series = QAreaSeries(seriesZero,seriesFullWave)
         series.setColor(self.__colorFill)
         series.setPen(pen)   #不显示线条
         self.chart.addSeries(series)
         series.attachAxis(self.__axisX)
         series.attachAxis(self.__axisY)

      series.clicked.connect(self.do_area_clicked)  #关联槽函数
         
   ## 构建QAreaSeries的两个QLineSeries序列必须添加到chart里,否则程序崩溃
      self.chart.addSeries(seriesZero)       #隐藏
      self.chart.addSeries(seriesPositive)   #隐藏
      self.chart.addSeries(seriesNegative)   #隐藏
      self.chart.addSeries(seriesFullWave)   #全波形曲线,显示

      seriesPositive.attachAxis(self.__axisX)
      seriesPositive.attachAxis(self.__axisY)

      seriesNegative.attachAxis(self.__axisX)
      seriesNegative.attachAxis(self.__axisY)

      seriesZero.attachAxis(self.__axisX)
      seriesZero.attachAxis(self.__axisY)
      
      seriesFullWave.attachAxis(self.__axisX)
      seriesFullWave.attachAxis(self.__axisY)

   def do_chartView_mouseMove(self,point):
      pt=self.ui.chartView.chart().mapToValue(point)  #QPointF 转换为图表的数值
      self.__labChartXY.setText("Chart X=%.2f,Y=%.2f"%(pt.x(),pt.y()))  #状态栏显示

   def do_area_clicked(self,point):
      self.__labAreaXY.setText("AreaSeries X=%.2f,Y=%.2f"
                               %(point.x(),point.y()))   #状态栏显示
示例#24
0
class Ui(mainwindow.Ui_MainWindow):
    def __init__(self, MainWindow):
        super(Ui, self).setupUi(MainWindow)
        self.MainWindow = MainWindow
        self.socketPacketReceiver = None

        self.timmer_is_on = False
        self.hexParser = StixHexStringParser()
        self.socketPacketReceiver = StixSocketPacketReceiver()
        self.socketPacketServer = StixSocketPacketServer()
        self.dataReader = StixFileReader()

        slots = {
            'info': self.onDataReaderInfo,
            'warning': self.onDataReaderWarning,
            'error': self.onDataReaderError,
            'critical': self.onDataReaderCritical,
            'dataLoaded': self.onDataReady,
            'packetArrival': self.onPacketArrival,
            'progress': self.onProgressUpdated
        }

        self.socketPacketReceiver.connectSignalSlots(slots)
        self.dataReader.connectSignalSlots(slots)
        self.hexParser.connectSignalSlots(slots)
        self.socketPacketServer.connectSignalSlots(slots)


        self.tabWidget.setCurrentIndex(0)
        self.actionExit.triggered.connect(self.close)
        self.actionPlot.setEnabled(False)

        self.actionNext.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_ArrowForward))
        self.actionPrevious.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_ArrowBack))
        self.actionOpen.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_DialogOpenButton))
        self.actionSave.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_DriveFDIcon))

        self.actionSave.triggered.connect(self.save)

        self.actionOpen.triggered.connect(self.getOpenFilename)
        self.filterPattern = None

        self.actionNext.triggered.connect(self.nextPacket)
        self.actionPrevious.triggered.connect(self.previousPacket)
        self.actionAbout.triggered.connect(self.about)

        self.actionPrevious.setEnabled(False)
        self.actionNext.setEnabled(False)
        self.actionSave.setEnabled(False)
        self.actionPlot.setEnabled(False)
        self.actionCopy.triggered.connect(self.onCopyTriggered)

        self.packetTreeWidget.currentItemChanged.connect(self.onPacketSelected)

        self.actionCopy.setEnabled(False)
        self.actionPaste.triggered.connect(self.onPasteTriggered)
        self.actionLog.triggered.connect(self.dockWidget.show)
        self.actionSetIDB.triggered.connect(self.onSetIDBClicked)
        self.plotButton.clicked.connect(
            partial(self.onPlotButtonClicked, None))

        #self.progressBar = QtWidgets.QProgressBar()
        #self.statusbar.addPermanentWidget(self.progressBar)
        self.progressDiag = None
        #self.progressBar.hide()

        self.actionPacketServer.triggered.connect(self.startPacketServer)

        self.exportButton.clicked.connect(self.onExportButtonClicked)
        self.actionPlot.triggered.connect(self.onPlotActionClicked)
        self.actionLoadMongodb.triggered.connect(self.onLoadMongoDBTriggered)
        self.actionConnectTSC.triggered.connect(self.onConnectTSCTriggered)
        self.actionPacketFilter.triggered.connect(self.filter)
        self.actionPlugins.triggered.connect(self.onPluginTriggered)
        self.actionOnlineHelp.triggered.connect(self.onOnlineHelpTriggered)
        self.actionViewBinary.triggered.connect(self.onViewBinaryTriggered)
        self.actionTimestampConvertor.triggered.connect(self.onTimestampConvertorTriggered)
        #self.actionPythonConsole.triggered.connect(self.startPythonConsole)
        self.autoUpdateButton.clicked.connect(
            self.onPlotAutoUpdateButtonClicked)

        self.packetTreeWidget.customContextMenuRequested.connect(
            self.packetTreeContextMenuEvent)

        #self.statusListWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        #self.statusListWidget.customContextMenuRequested.connect(self.statusListContextMenuEvent)

        self.mdb = None

        self.current_row = 0
        self.data = []
        self.x = []
        self.y = []
        self.xlabel = 'x'
        self.ylabel = 'y'

        self.buttons_enabled = False

        self.chart = QChart()
        self.chart.layout().setContentsMargins(0, 0, 0, 0)
        self.chart.setBackgroundRoundness(0)
        self.savePlotButton.clicked.connect(self.savePlot)

        self.chartView = QChartView(self.chart)
        self.gridLayout.addWidget(self.chartView, 1, 0, 1, 15)
        self.selected_services = SELECTED_SERVICES
        self.selected_SPID = []
        self.selected_tmtc = 3

        # IDB location

        self.settings = QtCore.QSettings('FHNW', 'stix_parser')
        self.idb_filename = self.settings.value('idb_filename', [], str)
        if self.idb_filename:
            STIX_IDB.reload(self.idb_filename)
        if not STIX_IDB.is_connected():
            self.showMessage('IDB has not been set!')
        else:
            idb_filename = STIX_IDB.get_idb_filename()
            self.showMessage('IDB loaded from : {} '.format(idb_filename), 1)
            if idb_filename != self.idb_filename:
                self.settings.setValue('idb_filename', idb_filename)
                self.idb_filename = idb_filename

    #def startPythonConsole(self):
    #    console.start({'packets': self.data})
    def close(self):
        self.MainWindow.close()
    def style(self):
        return self.MainWindow.style()

    def startPacketServer(self):
        host = 'localhost'
        port = 9096

        self.socketPacketServer.connect(host, port)
        self.socketPacketServer.setData(self.current_row, self.data)
        self.socketPacketServer.start()

        abspath = os.path.dirname(os.path.abspath(__file__))

        template = (
            "import sys\nsys.path.append('{}')\nimport client_packet_request as req\n"
            "packets=req.request(query_str='len', host='{}',port={}, verbose_level=1)\n"
            "#a query_string can be \n"
            "#  -  a python slice notation, for example, ':' '0:-1', 3:-1\n"
            "#  -  'len',  to get the total number of packets,\n"
            "#  -   index ,  to get a packet of the given index"
            "#set verbose_level to 0, to suppress print output  ").format(
                abspath, host, port)
        cb = QtWidgets.QApplication.clipboard()
        cb.clear(mode=cb.Clipboard)
        cb.setText(template, mode=cb.Clipboard)
        msg = QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Information)
        msg.setText(
            "Packet server started and a template to request packet has been copied to your clipboard!"
        )
        retval = msg.exec_()

    def onPlotAutoUpdateButtonClicked(self):
        if not self.timmer_is_on:
            if not self.data:
                return
            num_packets = len(self.data)
            if num_packets > 200:
                packets = self.data[-200:-1]
            else:
                packets = self.data
            self.timer = QTimer()
            self.timer.timeout.connect(
                partial(self.onPlotButtonClicked, packets))
            self.timer.start(2000)
            self.timmer_is_on = True
            self.autoUpdateButton.setText('Stop Auto Update')
        else:
            if self.timer:
                self.timer.stop()
            self.timmer_is_on = False
            self.autoUpdateButton.setText('Start Auto Update')

    #def statusListContextMenuEvent(self,pos):
    #    menu = QtWidgets.QMenu()
    #    clearLogAction= menu.addAction('Empty log')
    #    clearLogAction.triggered.connect(self.clearLog)
    #def clearLog(self):
    #    self.statusListWidget.clear()

    def packetTreeContextMenuEvent(self, pos):
        menu = QtWidgets.QMenu()
        filterAction = menu.addAction('Filter')
        menu.addSeparator()
        rawDataAction = menu.addAction('Raw binary data')
        menu.addSeparator()
        copyPacketAction = menu.addAction('Copy packet')
        menu.addSeparator()
        deleteAllAction = menu.addAction('Delete all packets')
        self.current_row = self.packetTreeWidget.currentIndex().row()

        rawDataAction.triggered.connect(self.onViewBinaryTriggered)
        filterAction.triggered.connect(self.filter)
        copyPacketAction.triggered.connect(self.onCopyTriggered)
        deleteAllAction.triggered.connect(self.onDeleteAllTriggered)
        action = menu.exec_(self.packetTreeWidget.viewport().mapToGlobal(pos))

    def filter(self):
        text, okPressed = QtWidgets.QInputDialog.getText(
            None, "Packet filtering",
            "Filtering by SPID or description (! to exclude):",
            QtWidgets.QLineEdit.Normal, "")
        if okPressed:
            self.filterPattern = text
            self.addPacketsToView(self.data, True, show_stat=False)

    def onDeleteAllTriggered(self):
        self.data.clear()
        self.current_row = 0
        self.packetTreeWidget.clear()
        self.paramTreeWidget.clear()

    #def onPacketTreeItemDoubleClicked(self):
    #    self.onViewBinaryTriggered()

    def onViewBinaryTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = raw_viewer.Ui_Dialog()
        diag_ui.setupUi(diag)
        if self.data:
            try:
                raw = self.data[self.current_row]['bin']
                header = self.data[self.current_row]['header']
                diag_ui.setPacketInfo('{}({},{})  {}'.format(
                    header['TMTC'], header['service_type'],
                    header['service_subtype'], header['descr']))
                diag_ui.displayRaw(raw)
            except (IndexError, KeyError):
                diag_ui.setText('Raw data not available.')
        diag.exec_()

    def onOnlineHelpTriggered(self):
        webbrowser.open(
            'https://github.com/i4Ds/STIX-python-data-parser', new=2)

    def onTimestampConvertorTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = timestamp_convertor.Ui_Dialog()
        diag_ui.setupUi(diag)
        diag.exec_()


    def onPluginTriggered(self):
        self.plugin_location = self.settings.value('plugin_location', [], str)
        diag = QtWidgets.QDialog()
        diag_ui = plugin.Ui_Dialog()
        diag_ui.setupUi(diag)
        if self.plugin_location:
            diag_ui.setPluginLocation(self.plugin_location)

        diag_ui.setData(self.data, self.current_row)
        diag.exec_()
        location = diag_ui.getPluginLocation()
        if location != self.plugin_location:
            self.settings.setValue('plugin_location', location)

    def onPacketFilterTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = packet_filter.Ui_Dialog()
        diag_ui.setupUi(diag)
        self.filterPattern = ''  #empty search string
        diag_ui.setSelectedServices(self.selected_services)

        diag_ui.buttonBox.accepted.connect(
            partial(self.applyServiceFilter, diag_ui))
        diag.exec_()

    def applyServiceFilter(self, diag_ui):
        self.selected_SPID = diag_ui.getSelectedSPID()
        self.selected_services = diag_ui.getSelectedServices()
        self.selected_tmtc = diag_ui.getTMTC()
        self.showMessage('Applying filter...')

        self.addPacketsToView(self.data, True, show_stat=False)

    def onExportButtonClicked(self):
        if self.y:
            filename = str(
                QtWidgets.QFileDialog.getSaveFileName(
                    None, "Save data to file", "", "CSV(*.csv)")[0])
            if filename:
                with open(filename, 'w') as f:
                    f.write('{},{}\n'.format(self.xlabel, self.ylabel))
                    for xx, yy in zip(self.x, self.y):
                        f.write('{},{}\n'.format(xx, yy))
                    self.showMessage(
                        'The data has been written to {}'.format(filename))
        else:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Information)
            msgBox.setText('Plot first!')
            msgBox.setWindowTitle("Warning")
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()

    def savePlot(self):
        # if self.figure.get_axes():
        if self.chart:
            filetypes = "PNG (*.png);;JPEG (*.jpg)"
            filename = str(
                QtWidgets.QFileDialog.getSaveFileName(
                    None, "Save plot to file", "", filetypes)[0])
            if filename:
                if not filename.endswith(('.png', '.jpg')):
                    filename += '.png'
                # self.figure.savefig(filename)
                p = self.chartView.grab()
                p.save(filename)
                self.showMessage(('Has been saved to %s.' % filename))

        else:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Information)
            msgBox.setText('No figure to save')
            msgBox.setWindowTitle("STIX raw data viewer")
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()

    def onCopyTriggered(self):
        packet_id = self.current_row
        try:
            packet = self.data[packet_id]
            ss = pprint.pformat(packet)

            cb = QtWidgets.QApplication.clipboard()
            cb.clear(mode=cb.Clipboard)
            cb.setText(ss, mode=cb.Clipboard)
            msg = QtWidgets.QMessageBox()
            msg.setIcon(QtWidgets.QMessageBox.Information)
            msg.setText(
                "The data of the selected packet has been copied to the clipboard."
            )
            msg.setWindowTitle("Information")
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            retval = msg.exec_()

        except Exception as e:
            self.showMessage(str(e), 0)

    def onPasteTriggered(self):
        raw_hex = QtWidgets.QApplication.clipboard().text()
        if len(raw_hex) < 16:
            self.showMessage('No data in the clipboard.')
            return
        self.hexParser.setHex(raw_hex)
        self.hexParser.start()

    def showMessage(self, msg, where=0):
        if where != 1:
            self.statusbar.showMessage(msg)
        if where != 0:
            self.statusListWidget.addItem(msg)

    def onSetIDBClicked(self):
        self.idb_filename = QtWidgets.QFileDialog.getOpenFileName(
            None, 'Select file', '.', 'IDB file(*.db *.sqlite *.sqlite3)')[0]

        if not self.idb_filename:
            return

        STIX_IDB.reload(self.idb_filename)
        if STIX_IDB.is_connected():
            #settings = QtCore.QSettings('FHNW', 'stix_parser')
            self.settings.setValue('idb_filename', self.idb_filename)
        self.showMessage(
            'IDB location: {} '.format(STIX_IDB.get_idb_filename()), 1)

    def save(self):
        filetypes = 'python compressed pickle (*.pklz);; python pickle file (*.pkl);; binary data (*.dat)'
        self.output_filename = str(
            QtWidgets.QFileDialog.getSaveFileName(None, "Save packets to", "",
                                                  filetypes)[0])

        if not self.output_filename.endswith(('.pklz', '.pkl', '.dat')):
            msg = 'unsupported file format !'
            self.showMessage(msg)
            return

        msg = 'Writing data to file %s' % self.output_filename
        self.showMessage(msg)
        if self.output_filename.endswith(('.pklz', '.pkl')):
            stw = stix_writer.StixPickleWriter(self.output_filename)
            stw.register_run(str(self.input_filename))
            stw.write_all(self.data)
        elif self.output_filename.endswith('.dat'):
            stw = stix_writer.StixBinaryWriter(self.output_filename)
            stw.write_all(self.data)
            num_ok = stw.get_num_sucess()
            msg = (
                'The binary data of {} packets written to file {}, total packets {}'
                .format(num_ok, self.output_filename, len(self.data)))
            self.showMessage(msg)
        msg = 'Packets have been written to %s' % self.output_filename
        self.showMessage(msg)

    def setListViewSelected(self, row):
        #index = self.model.createIndex(row, 0);
        # if index.isValid():
        #    self.model.selectionModel().select( index, QtGui.QItemSelectionModel.Select)
        pass

    def about(self):
        msgBox = QtWidgets.QMessageBox()
        msgBox.setIcon(QtWidgets.QMessageBox.Information)
        msgBox.setText("STIX raw data parser and viewer, [email protected]")
        msgBox.setWindowTitle("Stix data viewer")

        msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
        msgBox.exec_()

    def nextPacket(self):
        self.current_row += 1
        length = len(self.data)

        if self.current_row >= length:
            self.current_row = length - 1
            self.showMessage('No more packet!')

        self.showPacket(self.current_row)
        self.setListViewSelected(self.current_row)

    def previousPacket(self):
        self.current_row -= 1
        if self.current_row < 0:
            self.current_row = 0
            self.showMessage('Reach the first packet!')

        self.showPacket(self.current_row)
        self.setListViewSelected(self.current_row)

    def getOpenFilename(self):

        location = self.settings.value('location', [], str) 
        if not location:
            location = '.'


        filetypes = (
            'Supported file (*.dat *.bin *.binary *.pkl *.pklz *.xml *ascii *BDF *txt) ;; All(*)'
        )
        self.input_filename = QtWidgets.QFileDialog.getOpenFileName(
            None, 'Select file', location, filetypes)[0]
        if not self.input_filename:
            return
        self.settings.setValue('location', os.path.abspath(self.input_filename))

        diag = QtWidgets.QDialog()
        diag_ui = packet_filter.Ui_Dialog()
        diag_ui.setupUi(diag)
        diag_ui.setSelectedServices(SELECTED_SERVICES)
        diag_ui.buttonBox.accepted.connect(
            partial(self.onOpenFile, self.input_filename, diag_ui))
        diag.exec_()

    def onOpenFile(self, input_filename, diag):
        self.selected_SPID = diag.getSelectedSPID()
        self.selected_services = diag.getSelectedServices()
        self.openFile(input_filename, self.selected_services,
                      self.selected_SPID)

    def openFile(self, filename, selected_services=None, selected_SPID=None):
        msg = 'Loading file %s ...' % filename
        self.progressDiag = QtWidgets.QProgressDialog()
        #self.showMessage(msg)
        self.progressDiag.setLabelText(msg)
        self.progressDiag.setWindowTitle('Loading data')
        self.progressDiag.setCancelButtonText('Cancel')
        self.progressDiag.setRange(0, 100)
        self.progressDiag.setMinimumWidth(300)
        self.progressDiag.canceled.connect(self.stopParsing)
        self.filterPattern = ''
        self.dataReader.setPacketFilter(selected_services, selected_SPID)
        self.dataReader.setFilename(filename)
        self.dataReader.start()
        self.progressDiag.show()

    def stopParsing(self):
        if self.dataReader:
            self.dataReader.stopParsing()
            self.progressDiag.hide()

    def onProgressUpdated(self, progress):
        if not self.progressDiag:
            return
        self.progressDiag.setValue(progress)
        if progress >=99:
            self.progressDiag.hide()

    def onDataReaderCritical(self, msg):
        self.showMessage(msg, 1)

    def onDataReaderInfo(self, msg):
        self.showMessage(msg, 0)

    def onDataReaderWarning(self, msg):
        self.showMessage(msg, 1)

    def onDataReaderError(self, msg):
        self.showMessage(msg, 1)

    def onDataReady(self, data, clear=True, show_stat=True):
        #self.progressBar.hide()
        if not clear:
            self.data.extend(data)
        else:
            self.data = data
        if data:
            self.addPacketsToView(data, clear=clear, show_stat=show_stat)
            self.enableButtons()
        else:
            self.showMessage('No packet loaded')

    def enableButtons(self):
        if not self.buttons_enabled:
            self.actionPrevious.setEnabled(True)
            self.actionNext.setEnabled(True)
            self.actionSave.setEnabled(True)
            self.actionCopy.setEnabled(True)
            self.actionPlot.setEnabled(True)
            self.actionViewBinary.setEnabled(True)
            self.buttons_enabled = True

    def addPacketsToView(self, data, clear=True, show_stat=True):
        if clear:
            self.packetTreeWidget.clear()

        for p in data:
            if not isinstance(p, dict):
                continue
            header = p['header']
            root = QtWidgets.QTreeWidgetItem(self.packetTreeWidget)
            colors = {2: '#FFA500', 1: '#000080', 3: '#FF0000', 4: '#800000'}
            tc_color = '#78281F'
            if header['TMTC'] == 'TC':
                root.setForeground(0, QtGui.QBrush(QtGui.QColor(tc_color)))
                root.setForeground(1, QtGui.QBrush(QtGui.QColor(tc_color)))
            else:
                if header['service_type'] == 5:
                    if header['service_subtype'] in colors.keys():
                        root.setForeground(
                            0,
                            QtGui.QBrush(
                                QtGui.QColor(
                                    colors[header['service_subtype']])))
                        root.setForeground(
                            1,
                            QtGui.QBrush(
                                QtGui.QColor(
                                    colors[header['service_subtype']])))

            timestamp_str = stix_datetime.format_datetime(header['unix_time'])
            root.setText(0, timestamp_str)
            description = '{}({},{}) - {}'.format(
                header['TMTC'], header['service_type'],
                header['service_subtype'], header['descr'])
            root.setText(1, description)
            hidden = False

            if self.selected_SPID:
                if header['TMTC'] == 'TC':
                    hidden = True
                elif -int(header['SPID']) in self.selected_SPID or int(
                        header['SPID']) not in self.selected_SPID:
                    hidden = True
            else:
                if int(header['service_type']) not in self.selected_services:
                    hidden = True

            TMTC = header['TMTC']
            if TMTC == 'TM' and self.selected_tmtc in [2, 0]:
                hidden = True
            if TMTC == 'TC' and self.selected_tmtc in [1, 0]:
                hidden = True


            if self.filterPattern:
                to_exclude = False
                pattern = self.filterPattern.strip()
                if pattern.startswith('!'):
                    to_exclude = True
                    pattern = pattern[1:]
                try:
                    spid = int(pattern)
                    hidden = to_exclude == (header['SPID'] == spid)
                    #XNOR operation
                except (TypeError, ValueError):
                    hidden = to_exclude == (pattern in description)

            root.setHidden(hidden)

        if show_stat:
            total_packets = len(self.data)
            self.showMessage(('Total packet(s): %d' % total_packets))

    def onConnectTSCTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = tsc_connection.Ui_Dialog()
        diag_ui.setupUi(diag)
        self.tsc_host = self.settings.value('tsc_host', [], str)
        self.tsc_port = self.settings.value('tsc_port', [], str)
        if self.tsc_host:
            diag_ui.serverLineEdit.setText(self.tsc_host)
        if self.tsc_port:
            diag_ui.portLineEdit.setText(self.tsc_port)
        diag_ui.buttonBox.accepted.connect(partial(self.connectToTSC, diag_ui))
        diag.exec_()

    def connectToTSC(self, dui):
        host = dui.serverLineEdit.text()
        port = dui.portLineEdit.text()
        self.showMessage('Connecting to TSC...')

        self.socketPacketReceiver.connect(host, int(port))
        self.socketPacketReceiver.start()

    def onPacketArrival(self, packets):
        clear = False
        if packets:
            if len(self.data) > MAX_NUM_PACKET_IN_BUFFER:
                clear = True
            self.onDataReady(packets, clear=clear, show_stat=True)

    def onLoadMongoDBTriggered(self):
        diag = QtWidgets.QDialog()
        diag_ui = mongo_dialog.Ui_Dialog()
        diag_ui.setupUi(diag)
        #self.settings = QtCore.QSettings('FHNW', 'stix_parser')
        self.mongo_server = self.settings.value('mongo_server', [], str)
        self.mongo_port = self.settings.value('mongo_port', [], str)
        self.mongo_user = self.settings.value('mongo_user', [], str)
        self.mongo_pwd = self.settings.value('mongo_pwd', [], str)

        if self.mongo_server:
            diag_ui.serverLineEdit.setText(self.mongo_server)
        if self.mongo_port:
            diag_ui.portLineEdit.setText(self.mongo_port)

        if self.mongo_user:
            diag_ui.userLineEdit.setText(self.mongo_user)
        if self.mongo_pwd:
            diag_ui.pwdLineEdit.setText(self.mongo_pwd)

        diag_ui.pushButton.clicked.connect(
            partial(self.loadRunsFromMongoDB, diag_ui))
        diag_ui.buttonBox.accepted.connect(
            partial(self.loadDataFromMongoDB, diag_ui, diag))
        diag.exec_()

    def loadRunsFromMongoDB(self, dui):
        server = dui.serverLineEdit.text()
        port = dui.portLineEdit.text()
        user = dui.userLineEdit.text()
        pwd = dui.pwdLineEdit.text()

        self.showMessage('saving setting...')
        if self.mongo_server != server:
            self.settings.setValue('mongo_server', server)
        if self.mongo_port != port:
            self.settings.setValue('mongo_port', port)

        if self.mongo_user != user:
            self.settings.setValue('mongo_user', user)
        if self.mongo_pwd != pwd:
            self.settings.setValue('mongo_pwd', pwd)

        self.showMessage('connecting Mongo database ...')
        self.mdb = mgdb.MongoDB(server, int(port), user, pwd)
        if not self.mdb.is_connected():
            self.showMessage('Failed to connect to MongoDB')
            return

        dui.treeWidget.clear()
        self.showMessage('Fetching data...')
        for run in self.mdb.select_all_runs():
            root = QtWidgets.QTreeWidgetItem(dui.treeWidget)
            root.setText(0, str(run['_id']))
            root.setText(1, run['filename'])
            root.setText(2, stix_datetime.format_datetime(run['date']))
            root.setText(3, stix_datetime.format_datetime(run['data_start_unix_time']))
            root.setText(4, stix_datetime.format_datetime(run['data_stop_unix_time']))

    def loadDataFromMongoDB(self, dui, diag):
        self.showMessage('Loading packets ...')
        selected_runs = []
        for item in dui.treeWidget.selectedItems():
            selected_runs.append(item.text(0))
        if not selected_runs:
            self.showMessage('Run not selected!')
        if selected_runs:
            diag.done(0)
            self.showMessage('Loading data ...!')
            data = list(self.mdb.select_packets_by_run(selected_runs[0]))
            if data:
                self.onDataReady(data, clear=True)
            else:
                self.showMessage('No packets found!')
        # close

    def onPacketSelected(self, cur, pre):
        self.current_row = self.packetTreeWidget.currentIndex().row()
        self.showMessage(('Packet #%d selected' % self.current_row))
        self.showPacket(self.current_row)

    def showPacket(self, row):
        if not self.data:
            return
        header = self.data[row]['header']
        total_packets = len(self.data)
        self.showMessage(
            ('Packet %d / %d  %s ' % (row, total_packets, header['descr'])))
        self.paramTreeWidget.clear()
        header_root = QtWidgets.QTreeWidgetItem(self.paramTreeWidget)
        header_root.setText(0, "Header")
        rows = len(header)
        for key, val in header.items():
            root = QtWidgets.QTreeWidgetItem(header_root)
            root.setText(0, key)
            root.setText(1, str(val))

        params = self.data[row]['parameters']
        param_root = QtWidgets.QTreeWidgetItem(self.paramTreeWidget)
        param_root.setText(0, "Parameters")
        self.showParameterTree(params, param_root)
        self.paramTreeWidget.expandItem(param_root)
        self.paramTreeWidget.expandItem(header_root)
        self.current_row = row

    def showParameterTree(self, params, parent, parent_id=[]):
        if not params:
            return
        for i, p in enumerate(params):
            root = QtWidgets.QTreeWidgetItem(parent)
            if not p:
                continue
            param = Parameter(p)
            param_name = param['name']
            desc = param['desc']
            current_ids = parent_id[:]
            current_ids.append(i)
            root.setText(0, param_name)

            root.setText(1, desc)
            root.setText(2, str(param['raw']))
            tip='parameter'+''.join(['[{}]'.format(x) for x in current_ids])
            root.setToolTip(0, tip)

            long_desc = STIX_IDB.get_scos_description(param_name)
            if long_desc:
                root.setToolTip(1, long_desc)

            try:
                root.setToolTip(2, hex(param['raw_int']))
            except:
                pass
            unit=STIX_IDB.get_parameter_unit(param_name)
            eng=str(param['eng'])
            root.setText(3, eng)
            root.setText(4, unit)
            if 'NIXG' in param_name:
                root.setHidden(True)
                #groups should not be shown
            if param.children:
                self.showParameterTree(param['children'], root, current_ids)
        self.paramTreeWidget.itemDoubleClicked.connect(self.onTreeItemClicked)

    def walk(self, name, params, header, ret_x, ret_y, xaxis=0, data_type=0):
        if not params:
            return
        timestamp = header['unix_time']
        for p in params:
            if not p:
                continue
            param = Parameter(p)
            if name == param.name:
                values = None
                if data_type == 0:
                    values = param.raw
                else:
                    values = param.eng
                try:
                    yvalue = float(values)
                    ret_y.append(yvalue)
                    if xaxis == 1:
                        ret_x.append(timestamp)
                    else:
                        self.showMessage(('Can not plot %s  ' % str(yvalue)))
                except Exception as e:
                    self.showMessage(('%s ' % str(e)))

            if param.children:
                self.walk(name, param.children, header, ret_x, ret_y, xaxis,
                          data_type)

    def onPlotButtonClicked(self, packets=None):
        if self.chart:
            self.chart.removeAllSeries()
        if packets is None:
            packets = self.data
        if not packets:
            return

        self.showMessage('Preparing plot ...')
        name = self.paramNameEdit.text()
        packet_selection = self.comboBox.currentIndex()
        xaxis_type = self.xaxisComboBox.currentIndex()
        data_type = self.dataTypeComboBox.currentIndex()
        timestamp = []
        self.y = []
        params = self.paramNameEdit.text()
        header = packets[0]['header']
        current_spid = 0
        spid_text = self.spidLineEdit.text()
        if spid_text:
            current_spid = int(spid_text)
        selected_packets=[] 
        if packet_selection == 0:
            selected_packets=[packets[self.current_row]]
        elif packet_selection == 1:
            selected_packets=packets

        for packet in selected_packets:
            header = packet['header']
            if packet['header']['SPID'] != current_spid:
                continue
            params = packet['parameters']
            self.walk(name, params, header, timestamp, self.y, xaxis_type,
                      data_type)


        self.x = []

        if not self.y:
            self.showMessage('No data points')
        elif self.y:
            style = self.styleEdit.text()
            if not style:
                style = '-'
            title = '%s' % str(name)
            desc = self.descLabel.text()
            if desc:
                title += '- %s' % desc

            self.chart.setTitle(title)

            ylabel = 'Raw value'
            xlabel = name
            if data_type == 1:
                ylabel = 'Engineering / Decompressed  value'
            if xaxis_type == 0:
                if packet_selection == 1:
                    xlabel = "Packet #"
                else:
                    xlabel = "Repeat #"
                self.x = range(0, len(self.y))
            if xaxis_type == 1:
                self.x = [t - timestamp[0] for t in timestamp]
                xlabel = 'Time -T0 (s)'

            if xaxis_type != 2:
                series = QLineSeries()
                series2 = None
                for xx, yy in zip(self.x, self.y):
                    series.append(xx, yy)
                if 'o' in style:
                    series2 = QScatterSeries()
                    for xx, yy in zip(self.x, self.y):
                        series2.append(xx, yy)
                    self.chart.addSeries(series2)
                self.chart.addSeries(series)
                axisX = QValueAxis()
                axisX.setTitleText(xlabel)
                axisY = QValueAxis()
                axisY.setTitleText(ylabel)

                self.chart.setAxisX(axisX)
                self.chart.setAxisY(axisY)
                series.attachAxis(axisX)
                series.attachAxis(axisY)
            else:
                nbins = len(set(self.y))
                ycounts, xedges = np.histogram(self.y, bins=nbins)
                series = QLineSeries()
                for i in range(0, nbins):
                    meanx = (xedges[i] + xedges[i + 1]) / 2.
                    series.append(meanx, ycounts[i])
                self.chart.addSeries(series)
                axisX = QValueAxis()
                axisX.setTitleText(name)
                axisY = QValueAxis()
                axisY.setTitleText("Counts")

                self.chart.setAxisY(axisY)
                self.chart.setAxisX(axisX)
                series.attachAxis(axisX)
                series.attachAxis(axisY)

            self.xlabel = xlabel
            self.ylabel = ylabel
            self.chartView.setRubberBand(QChartView.RectangleRubberBand)
            self.chartView.setRenderHint(QtGui.QPainter.Antialiasing)
            msg = 'Number of data points: {}, Ymin: {}, Ymax: {}'.format(
                len(self.y), min(self.y), max(self.y))
            self.showMessage(msg, 1)

            self.showMessage('The canvas updated!')

    def plotParameter(self, SPID=None, pname=None, desc=None):
        self.tabWidget.setCurrentIndex(1)
        if pname:
            self.paramNameEdit.setText(pname)
        if desc:
            self.descLabel.setText(desc)
        if SPID:
            self.spidLineEdit.setText(str(SPID))

    def onPlotActionClicked(self):
        self.tabWidget.setCurrentIndex(1)
        self.plotParameter()

    def onTreeItemClicked(self, it, col):
        SPID = None
        try:
            SPID = self.data[self.current_row]['header']['SPID']
        except IndexError:
            pass
        self.plotParameter(SPID, it.text(0), it.text(1))
示例#25
0
class TestWindow(QMainWindow):
    def __init__(self, scope, parent=None):
        super(TestWindow, self).__init__(parent=parent)

        self.scope = scope
        self.ncurves = 0
        self.chart = QChart()
        self.chart.legend().hide()
        self.view = QChartView(self.chart)
        self.view.setRenderHint(QPainter.Antialiasing)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlWidget = QWidget()
        controlWidget.setLayout(controlLayout)

        self.runButton = QPushButton("Get")
        controlLayout.addWidget(self.runButton)

        self.channel1 = QCheckBox("fetch 12bit")
        controlLayout.addWidget(self.channel1)

        controlLayout.addWidget(QLabel("Delay"))
        self.delay = QLineEdit("0")
        controlLayout.addWidget(self.delay)
        controlLayout.addWidget(QLabel("NumSamples"))
        self.numSamples = QLineEdit("3000")
        controlLayout.addWidget(self.numSamples)

        self.speedsComboBox = LabeledComboBox(
            label='Timebase', items=[str(x) for x in list(range(8))])
        controlLayout.addWidget(self.speedsComboBox)

        self.layout = QVBoxLayout()
        self.layout.addWidget(controlWidget)
        self.layout.addWidget(self.view)

        self.layoutWidget = QWidget()
        self.layoutWidget.setLayout(self.layout)

        self.runButton.clicked.connect(self.on_get)

        self.setCentralWidget(self.layoutWidget)

        self.show()

    @pyqtSlot()
    def on_get(self):
        self.chart.removeAllSeries()

        scope.setSampleSpeed(self.speedsComboBox.getInt())
        scope.set12Bits(self.channel1.isChecked())
        scope.setDelay(int(str(self.delay.displayText())))

        # There is some weird behaviour in 12 bit mode
        numSamples = int(str(self.numSamples.displayText()))
        scope.setSamples(min(7 * 1024 + 512, numSamples))

        ch1data = scope_getSamples(self.scope)

        self.add_data(range(len(ch1data)), ch1data, color=Qt.red)

        self.set_title("Semi live Scope")

    def set_title(self, title):
        self.chart.setTitle(title)

    def add_data(self, xdata, ydata, color):
        curve = QLineSeries()
        pen = curve.pen()
        pen.setColor(color)
        pen.setWidthF(.1)
        curve.setPen(pen)
        curve.setUseOpenGL(True)
        curve.append(series_to_polyline(xdata, ydata))
        self.chart.addSeries(curve)
        self.chart.createDefaultAxes()
        self.ncurves += 1
示例#26
0
class PieChart(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)

        self.setObjectName("main")
        self.setStyleSheet("""
                    QWidget{
                        border:1px solid #148CD2;
                        border-radius:10px;
                    }
        """)
        self.create_piechart()

        timer = QTimer(self)
        timer.timeout.connect(self.redraw)
        timer.start(5 * 60 * 1000)  # update every 5 minutes

        layout = QHBoxLayout(self)
        layout.setContentsMargins(5, 5, 50, 5)
        layout.addWidget(self.chartview)

        self.setLayout(layout)
        self.setFixedSize(500, 400)

    def create_piechart(self):
        today = datetime.date.today()
        Day = selectday(today)
        catogeries = Day['allCategory']
        catogeries = dict(sorted(catogeries.items(), key=lambda x: -x[1])[:5])
        print(f"--------------------{catogeries}--------")
        series = QPieSeries()

        tot_val = 0
        for name, value in catogeries.items():
            tot_val += value

        tot_val = max(tot_val, 1)
        for name, value in catogeries.items():
            if value == 0:
                value = 0.2
            _slice = series.append(name, 100 * (value / tot_val))
            _slice.setLabelVisible(True)  # can be removed if unnecessary

        self.chart = QChart()
        self.chart.legend().hide()
        self.chart.addSeries(series)
        self.chart.createDefaultAxes()
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("Categories")

        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)

        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)

    def redraw(self):
        # remove pieChart
        self.chart.removeAllSeries()

        today = datetime.date.today()
        Day = selectday(today)
        catogeries = Day['allCategory']
        catogeries = dict(sorted(catogeries.items(), key=lambda x: -x[1])[:5])
        print(f"--------------------{catogeries}--------")
        series = QPieSeries()

        tot_val = 0
        for name, value in catogeries.items():
            tot_val += value

        for name, value in catogeries.items():
            _slice = series.append(name, 100 * (value / tot_val))
            _slice.setLabelVisible(True)  # can be removed if unnecessary

        self.chart.addSeries(series)

        self.chartview.setChart((self.chart))
        self.chartview.setRenderHint(QPainter.Antialiasing)
        self.chartview.repaint()
示例#27
0
class ProdDetail(QWidget):
    def __init__(self):
        super().__init__()
        hbox=QHBoxLayout()
        hbox2=QHBoxLayout()
        hbox3=QHBoxLayout()
        hbox4=QHBoxLayout()

        self.prod_combo=QComboBox()
        self.lineEditProdName=QLineEdit()
        namelabel=QLabel("스토어팜주소")
        self.farm_combo=QComboBox()
        self.li=['https://smartstore.naver.com/heyhannah','https://smartstore.naver.com/monsclub']
        self.farm_combo.addItems(self.li)
        self.shop_title_label=QLabel()
        self.show_farm_name()
        self.btn_show_prod_detail=QPushButton('조회')
        self.btn_show_prod_detail.setIcon(QtGui.QIcon('update.png'))

        hbox.addWidget(namelabel)
        hbox.addWidget(self.farm_combo)
        hbox.addWidget(self.shop_title_label)

        hbox2.addWidget(QLabel("상품명"))
        hbox2.addWidget(self.prod_combo)
        
        hbox2.addStretch()
        hbox3.addWidget(QLabel("직접입력"))
        

        hbox3.addWidget(self.lineEditProdName)
        hbox3.addWidget(self.btn_show_prod_detail)
        hbox3.addStretch()

        self.init_prod_combo()
        self.btn_show_prod_detail.clicked.connect(self.get_prod_detail)
        self.farm_combo.currentTextChanged.connect(self.show_farm_name)
        self.prod_combo.currentTextChanged.connect(self.input_prod_title)

        vbox=QVBoxLayout()
   
        self.linechart=QChart()
        self.linechart2=QChart()
        self.linechart3=QChart()
        
        self.chartview = QChartView(self.linechart)
        self.chartview2 = QChartView(self.linechart2)
        self.chartview3 = QChartView(self.linechart3)

        self.tablewidget=QTableWidget()

        self.chartgroup=QGroupBox()
        self.chartvbox=QVBoxLayout()
        self.chartvbox.addWidget(self.chartview)
        self.chartvbox.addWidget(self.chartview2)
        self.chartvbox.addWidget(self.chartview3)
        
        self.chartgroup.setLayout(self.chartvbox)

        hbox4.addWidget(self.tablewidget)
        # hbox4.addWidget(self.chartview)
        hbox4.addWidget(self.chartgroup)

        self.updateProdDetail()
        self.groupbox=QGroupBox()
        self.groupbox2=QGroupBox()
        self.groupbox3=QGroupBox()
        self.groupbox4=QGroupBox()

        self.groupbox.setLayout(hbox)
        self.groupbox2.setLayout(hbox2)
        self.groupbox3.setLayout(hbox3)
        self.groupbox4.setLayout(hbox4)
        
        vbox.addWidget(self.groupbox)
        vbox.addWidget(self.groupbox2)
        vbox.addWidget(self.groupbox3)
        vbox.addWidget(self.groupbox4)
        
        self.setLayout(vbox)

    def init_prod_combo(self):
        mall_url=self.farm_combo.currentText()
        conn=sqlite3.connect('emaildb.sqlite')
        cur=conn.cursor()
        sql=f"Select distinct title from PROD3 where link like '{mall_url}%'"
 
        cur.execute(sql)
        conn.commit()
        
        rows=cur.fetchall()

        li=[]
        for row in rows:
            li.append(row[0])
 
        self.prod_combo.clear()
        self.prod_combo.addItems(li)

        cur.close()
        conn.close()
        self.lineEditProdName.setText(self.prod_combo.currentText())

    def drawChart(self):
        conn=sqlite3.connect('emaildb.sqlite')
        cur=conn.cursor()

        title=self.lineEditProdName.text()
        mall_url=self.farm_combo.currentText()
        sql=f"select dt, jjim, sold, review from PROD3 where title='{title}'"
        cur.execute(sql)
        conn.commit()
        rows=cur.fetchall()
        series=[]
        # series = QLineSeries(self)
        series.append(QLineSeries(self))
        series.append(QLineSeries(self))
        series.append(QLineSeries(self))
        
        tod=datetime.today()
        nextday=datetime.today()+timedelta(days=1)
        d=QDate(2020,1,3)
        dt=QDateTime(d)
        d2=d.addDays(1)
        dt2=dt.addDays(1)

        for i,row in enumerate(rows):
            for j, serie in enumerate(series):
                # serie.append((dt.addDays(i)).toMSecsSinceEpoch(),int(row[j+1]))
                serie.append(i,int(row[j+1]))

        for serie in series:
            serie.setPointsVisible(True)
            
        self.linechart.removeAllSeries()
        self.linechart2.removeAllSeries()
        self.linechart3.removeAllSeries()
        

        self.linechart.addSeries(series[0])
        self.linechart2.addSeries(series[1])
        self.linechart3.addSeries(series[2])
        
        dateAxis=QDateTimeAxis()
        dateAxis2=QDateTimeAxis()
        dateAxis3=QDateTimeAxis()
        
        self.linechart.addAxis(dateAxis, Qt.AlignBottom)
        self.linechart2.addAxis(dateAxis2, Qt.AlignBottom)
        self.linechart3.addAxis(dateAxis3, Qt.AlignBottom)
        
        self.linechart.createDefaultAxes()
        self.linechart2.createDefaultAxes()
        self.linechart3.createDefaultAxes()
                   
        self.linechart.setAnimationOptions(QChart.SeriesAnimations)
        self.linechart.setTitle("찜")
        self.linechart.legend().setVisible(True)

        self.linechart2.setAnimationOptions(QChart.SeriesAnimations)
        self.linechart2.setTitle("구매")
        self.linechart2.legend().setVisible(True)

        self.linechart3.setAnimationOptions(QChart.SeriesAnimations)
        self.linechart3.setTitle("리뷰")
        self.linechart3.legend().setVisible(True)


        self.chartview.setRenderHint(QPainter.Antialiasing)
        self.chartview2.setRenderHint(QPainter.Antialiasing)
        self.chartview3.setRenderHint(QPainter.Antialiasing)

        cur.close()
        conn.close()
        
    def updateProdDetail(self):
        self.tablewidget.clear()
        self.tablewidget.setRowCount(300)
        self.tablewidget.setColumnCount(6)
        self.tablewidget.setItem(0,0,QTableWidgetItem("날짜"))
        self.tablewidget.setItem(0,1,QTableWidgetItem("찜"))
        self.tablewidget.setItem(0,2,QTableWidgetItem("구매"))
        self.tablewidget.setItem(0,3,QTableWidgetItem("리뷰"))

        conn=sqlite3.connect('emaildb.sqlite')
        cur=conn.cursor()

        title=self.lineEditProdName.text()

        mall_url=self.farm_combo.currentText()
        sql=f"Select dt, jjim, sold, review from PROD3 where title='{title}' order by dt desc"

        cur.execute(sql)
        conn.commit()
        
        rows=cur.fetchall()

        for i,row in enumerate(rows):
            # print(i, row[0])
            for j, elem in enumerate(row):
                
            #     print(i+1,j,elem)
            #     self.tablewidget.setItem(i+1,j,QTableWidgetItem(elem))
                self.tablewidget.setItem(i+1,j,QTableWidgetItem(str(row[j])))
            # print(row[1])
                # self.tablewidget.setItem(i+1,1,QTableWidgetItem(str(row[1])))
                
        self.tablewidget.resizeColumnToContents(0)
        cur.close()
        conn.close()

        return len(rows)
    def input_prod_title(self):
        self.lineEditProdName.setText(self.prod_combo.currentText())

    def get_prod_detail(self):
        url=self.farm_combo.currentText()
        prod_title=self.lineEditProdName.text()
        self.tablewidget.clear()
        self.updateProdDetail()
        self.drawChart()

    def setFarm(self,li):
        self.farmlist=FarmList(self.li)
        # print(self.li)
        # self.farm_combo.addItems(self.li)
        self.farmlist.show()
        
    def show_farm_name(self):
        '''스토어팜 주소를 콤보박스에서 변경시에 검색하여 스토어팜 이름 표시
        prod_combo도 변경함
        '''
        # self.shop_title_label.setText("sssss")
        url=self.farm_combo.currentText()
        req=requests.get(url)
        soup=BeautifulSoup(req.text, 'html.parser')
        self.shop_title_label.setText(soup.find('title').text.strip())
        self.init_prod_combo()
示例#28
0
class Chart(QWidget):
    def __init__(self, chartKey, data, frame, parent=None):
        super(Chart, self).__init__(parent)
        self.frame = frame
        self.data = data

        self.pt = self.parent()

        #add the to the main window
        #self.toolbar = QToolBar("Edit", self)
        #self.pt.addToolBar(self.toolbar)

        #ly = QtWidgets.QVBoxLayout()
        #self.frame = QtWidgets.QFrame()
        #self.frame.setLayout(ly)

        #self.layout = QtWidgets.QGridLayout()

        #print('----------------',self.frame)

        self.create_chart(chartKey)
        clicked = QtCore.pyqtSignal(QtCore.QModelIndex)
        #self.pt.addToolBar(self.navigationBar(data))

    def create_chart(self, chartKey):
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)
        self.chart = QChart()

        #Add series to the chart
        self.addSeries(chartKey)

        # for the background and title
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setTitle("DonutChart Example")
        self.chart.setTheme(QChart.ChartThemeBlueCerulean)

        self.chartview = QChartView(self.chart)
        self.chartview.setRenderHint(QPainter.Antialiasing)

        #navigation = Navigation(classObj, self)
        #self.addToolBar(navigation.toolbar)

        #clicked = QtCore.pyqtSignal(QtCore.QModelIndex)

    def navigationBar(self, data):
        self.toolbar = QtWidgets.QToolBar()
        self.toolbar.actionTriggered.connect(self.on_actionTriggered)
        self.model = QtGui.QStandardItemModel(self)
        dict_to_model(self.model.invisibleRootItem(), data)
        it = self.model.item(0, 0)
        ix = self.model.indexFromItem(it)
        root_action = self.toolbar.addAction(it.text())
        root_action.setData(QtCore.QPersistentModelIndex(ix))
        self.listview = QtWidgets.QListView()
        self.listview.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        #self.series.doubleClicked.connect(self.on_clicked)
        self.listview.setModel(self.model)
        self.listview.setRootIndex(ix)
        self.a = 10

        return self.toolbar

    #make the listed items clickable
    #@QtCore.pyqtSlot(QtCore.QModelIndex)
    def on_clicked(self, index):
        if not self.model.hasChildren(index):
            self.clicked.emit(index)
            return
        action = self.toolbar.addAction(index.data())
        action.setData(QtCore.QPersistentModelIndex(index))
        self.listview.setRootIndex(index)
        print(index.data())
        self.chart.addSeries(index.data())

    #make the breadcrumbs clickable in order to go back and forth
    #@QtCore.pyqtSlot(QtWidgets.QAction)
    def on_actionTriggered(self, action):
        ix = action.data()
        self.chart.addSeries(ix.data())
        model = ix.model()
        self.listview.setRootIndex(QtCore.QModelIndex(ix))
        self.toolbar.clear()
        ixs = []
        while ix.isValid():
            ixs.append(ix)
            ix = ix.parent()
        for ix in reversed(ixs):
            action = self.toolbar.addAction(ix.data())
            action.setData(ix)

    def addSeries(self, key):
        self.chart.removeAllSeries()
        self.series = QPieSeries()
        self.series.setHoleSize(0.35)

        #Show chartview only if the content length is less than 6. Otherwise show a table view
        if len(self.data[key]) < 6:
            for key, value in self.data[key].items():
                slice_ = QPieSlice(str(key), value)
                self.series.append(slice_)

            for slice in self.series.slices():
                slice.setLabel(slice.label())

            self.chart.addSeries(self.series)
            self.frame.frame.hide()
            self.chart.show()
        else:
            for m, item in self.data[key].items():
                print(m, item)

            self.table = TableView(self.data[key], len(self.data[key]), 1)

            if self.frame.ly.count() > 0:
                self.frame.ly.itemAt(0).widget().setParent(None)

            self.frame.ly.addWidget(self.table)

            self.frame.frame.show()
            self.chart.hide()

        self.series.doubleClicked.connect(self.handle_double_clicked)

    #Show the update chart with the distribution of the selected slice
    def handle_double_clicked(self, slice):
        slice.setExploded()
        slice.setLabelVisible()

        if slice.label() in self.data.keys():
            print("slice", slice.label())
            self.addSeries(slice.label())