コード例 #1
0
class MainWindow(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.setGeometry(100, 100, 300, 200)
        self.show()
        self.grid = QGridLayout(self)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.web = QWebEngineView()
        self.web.load(QUrl(link))
        self.grid.addWidget(self.web, 0, 0)

        self.web2 = QWebEngineView()
        self.web2.hide()
        self.web2.load(QUrl(link))
        self.grid.addWidget(self.web2, 0, 0)

        timer = QtCore.QTimer(self)
        timer.timeout.connect(self.refresh)
        timer.start(int(sys.argv[-1]))

    def refresh(self):
        print(int(time.time()))

        def finished():
            browser, another = self.web, self.web2
            if another.isHidden():
                browser, another = another, browser
            time.sleep(1)
            browser.show()
            another.hide()

        if self.web2.isHidden():
            self.web2.reload()
            self.web2.loadFinished.connect(finished)
        else:
            self.web.reload()
            self.web.loadFinished.connect(finished)
コード例 #2
0
ファイル: MainView.py プロジェクト: DragonistYJ/Chart
class ViewMainWindow(QMainWindow, Ui_MainWindow):


    def __init__(self):
        super().__init__()
        self.directory = ''
        self.sizes = []
        self.files = []
        self.chart_views = []
        self.setupUi(self)

        # 打开工作空间按钮
        self.button_load_dir = QPushButton(self.widget_directory)
        self.button_load_dir.setText("打开新的工作空间")
        self.button_load_dir.clicked.connect(self.open_new_directory)
        self.verticalLayout_directory.addWidget(self.button_load_dir)

        # 渲染列表HTML
        self.dir_list_html = QWebEngineView(self.widget_directory)
        self.dir_list_channel = QWebChannel(self.dir_list_html.page())
        self.dir_list_obj = DirListObj()
        self.dir_list_obj.sig_file_item_clicked.connect(self.on_choose_file)
        self.dir_list_channel.registerObject("dir_list_obj", self.dir_list_obj)
        self.dir_list_html.page().setWebChannel(self.dir_list_channel)
        self.dir_list_html.load(QUrl.fromLocalFile(os.path.abspath('view/html/file_list.html')))
        self.verticalLayout_directory.addWidget(self.dir_list_html)
        self.dir_list_html.hide()

        # 打开工作空间按钮与函数绑定
        self.actionNew_Workspace.triggered.connect(self.open_new_directory)

        # 关闭工作空间按钮与函数绑定
        self.actionClose_Workspace.triggered.connect(self.clock_directory)

        # 加载配置文件按钮与函数绑定
        self.actionLoad_Setting.triggered.connect(self.select_setting_file)

        # 加载默认的配置文件
        self.setting = Setting("setting.json")

    def on_choose_file(self, file_id):
        """
        打开一个数据文件
        :param file_id: 文件在内存中的序号
        :return:
        """
        print("try to load", self.files[file_id])
        datas = read_data(os.path.join(self.directory, self.files[file_id]), self.setting.channels)

        # 删除之前存在的图表
        for chart_view in self.chart_views:
            self.verticalLayout_charts.removeWidget(chart_view)
            chart_view.deleteLater()
        self.chart_views.clear()

        # 创建新的图表
        for i in range(self.setting.channels):
            chart_view = View_Chart(self.setting.line_colors[i],
                                    self.setting.background_colors[i],
                                    self.setting.x_axis_colors[i],
                                    self.setting.y_axis_colors[i],
                                    self.setting.tooltip_colors[i],
                                    datas[i])
            self.chart_views.append(chart_view)
            self.verticalLayout_charts.addWidget(chart_view)

    def clock_directory(self):
        """
        关闭当前打开的工作空间
        :return:
        """
        self.dir_list_html.hide()
        self.button_load_dir.show()
        for chart_view in self.chart_views:
            self.verticalLayout_charts.removeWidget(chart_view)
            chart_view.deleteLater()
        self.chart_views.clear()

    def open_new_directory(self):
        """
        打开一个新的目录
        隐藏打开按钮
        显示新的文件列表
        :return:
        """
        self.on_change_directory()
        self.button_load_dir.hide()
        self.dir_list_html.show()

    def on_change_directory(self):
        """
        选择一个新的工作目录
        遍历其中以.data结尾的文件
        显示文件名和大小
        :return:
        """
        self.directory = QFileDialog.getExistingDirectory(self, "选择工作目录")
        if not os.path.exists(self.directory):
            return
        listdir = os.listdir(self.directory)
        self.files.clear()
        self.sizes.clear()
        for _dir in listdir:
            path = os.path.join(self.directory, _dir)
            if os.path.isfile(path) and path.endswith(".data"):
                self.files.append(_dir)
                self.sizes.append(os.path.getsize(path))
        self.dir_list_html.page().runJavaScript("updateList({0},{1})".format(self.files, self.sizes))

    def select_setting_file(self):
        """
        选择配置文件
        :return:
        """
        setting_file = QFileDialog.getOpenFileName(self, "选择配置文件", filter="JSON Files(*.json)")
        self.setting = Setting(setting_file[0])
コード例 #3
0
ファイル: MainView.py プロジェクト: kaileby/EduWatching
class View_Main(QMainWindow, Ui_MainWindow):
    classroom_briefs = []
    class_brief_threads = []
    view_real_time = None

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

        # 四个页面的切换
        self.widget_building.clicked.connect(self.change_page_class)
        self.widget_status.clicked.connect(self.change_page_status)
        self.widget_abnormal.clicked.connect(self.change_page_abnormal)
        self.widget_record.clicked.connect(self.change_page_record)

        # 从数据库读取教室信息
        get_class_briefs(self.classroom_briefs)
        # 多线程完成教室初始化显示
        threads = []
        for brief in self.classroom_briefs:
            threads.append(
                threading.Thread(target=init_thumbnail, args=(brief, )))
        for thread in threads:
            thread.start()
            thread.join()

        # 注册教室列表
        self.class_web = QWebEngineView(self.page_class)
        self.class_channel = QWebChannel(self.class_web.page())
        self.class_obj = ClassObj()

        # 注册按教学楼分类的标题组件
        self.building_title_web = QWebEngineView(self.page_class)
        self.building_title_web.setMaximumHeight(90)
        self.building_title_web.setMinimumHeight(90)
        self.building_title_channel = QWebChannel(
            self.building_title_web.page())
        self.building_title_obj = BuildingTitleObj()

        # 注册按状态分类的标题栏组件
        self.state_title_web = QWebEngineView(self.page_class)
        self.state_title_web.setMinimumHeight(65)
        self.state_title_web.setMaximumHeight(65)
        self.state_title_channel = QWebChannel(self.state_title_web.page())
        self.state_title_obj = StateTitleObj()

        self.setup_class_page()

        # 注册上课回看列表需要的组件
        self.record_list_page = QWebEngineView(self.page_reocrd)
        self.record_list_channel = QWebChannel(self.record_list_page.page())
        self.record_list_obj = RecordListObj()
        self.setup_record_table()

    def setup_class_page(self):
        # 初始化按教学楼搜索标题栏
        self.building_title_obj.sig_confirm_clicked.connect(
            self.sift_by_building)
        self.building_title_channel.registerObject('building_title_obj',
                                                   self.building_title_obj)
        self.building_title_web.page().setWebChannel(
            self.building_title_channel)
        self.building_title_web.load(
            QUrl.fromLocalFile(
                os.path.abspath('view/html/TitleBuilding.html')))

        # 初始化按状态搜索标题栏
        self.state_title_channel.registerObject('state_title_obj',
                                                self.state_title_obj)
        self.state_title_web.page().setWebChannel(self.state_title_channel)
        self.state_title_web.load(
            QUrl.fromLocalFile(os.path.abspath('view/html/TitleState.html')))
        self.state_title_web.hide()

        # 初始化教室页面
        self.class_obj.sig_class_item_clicked.connect(self.open_real_time)
        self.class_channel.registerObject('class_obj', self.class_obj)
        self.class_web.page().setWebChannel(self.class_channel)
        self.class_web.load(
            QUrl.fromLocalFile(os.path.abspath('view/html/ClassTable.html')))
        self.class_web.loadFinished.connect(self.refresh_page)

        self.verticalLayout_7.addWidget(self.building_title_web)
        self.verticalLayout_7.addWidget(self.state_title_web)
        self.verticalLayout_7.addWidget(self.class_web)
        # 统计学生人数线程对象生成
        for brief in self.classroom_briefs:
            self.class_brief_threads.append(
                ClassBriefThread(brief, self.class_web.page()))
        for thread in self.class_brief_threads:
            thread.start()

    def refresh_page(self):
        # 刷新教室列表的显示
        init_table = ''
        for brief in self.classroom_briefs:
            if brief.isShow:
                init_table += HTMLFactory.get_instance().class_brief_box_first(
                    brief)
        self.class_web.page().runJavaScript(
            "setupTable('{0}')".format(init_table))

    def open_real_time(self, class_brief_id):
        for brief in self.classroom_briefs:
            if brief.classroom.classroom_id == class_brief_id:
                print(
                    ">>>>>>>>>>>>>>>>>>>>>> classroom {0} begin to be monitored"
                    .format(class_brief_id))
                for thread in self.class_brief_threads:
                    thread.pause()
                time.sleep(2)
                self.view_real_time = View_RealTime(brief)
                self.view_real_time.sig_on_closed.connect(self.resume)
                self.view_real_time.showMaximized()
                break

    def sift_by_building(self, campus, building, floor):
        # 按照教学楼显示
        # 根据校区、教学楼、教室号来进行筛选
        for brief in self.classroom_briefs:
            if (campus in brief.classroom.campus) and (
                    building in brief.classroom.building) and (
                        floor in brief.classroom.floor):
                if not brief.isShow:
                    self.add_box(brief)
                    brief.isShow = True
            elif brief.isShow:
                self.remove_box(brief)
                brief.isShow = False

    # 初始化上课回看列表
    def setup_record_table(self):
        self.record_list_obj.sig_record_list_item_clicked.connect(
            self.open_replay)
        self.record_list_channel.registerObject('record_list_obj',
                                                self.record_list_obj)
        self.record_list_page.page().setWebChannel(self.record_list_channel)
        self.verticalLayout_10.addWidget(self.record_list_page)
        self.record_list_page.load(
            QUrl.fromLocalFile(os.path.abspath('view/html/Record.html')))

    def open_replay(self, item_id):
        self.view_replay = View_Replay()
        self.view_replay.showMaximized()

    def change_page_class(self):
        for thread in self.class_brief_threads:
            thread.resume()
        self.stackedWidget.setCurrentIndex(0)
        self.building_title_web.show()
        self.state_title_web.hide()

        for brief in self.classroom_briefs:
            if not brief.isShow:
                self.add_box(brief)
                brief.isShow = True

    def change_page_status(self):
        for thread in self.class_brief_threads:
            thread.resume()
        self.stackedWidget.setCurrentIndex(0)
        self.building_title_web.hide()
        self.state_title_web.show()

        for brief in self.classroom_briefs:
            if not brief.isShow:
                self.add_box(brief)
                brief.isShow = True

    def change_page_abnormal(self):
        for thread in self.class_brief_threads:
            thread.resume()
        self.stackedWidget.setCurrentIndex(0)
        self.building_title_web.hide()
        self.state_title_web.hide()

        for brief in self.classroom_briefs:
            if brief.isAbnormal:
                if not brief.isShow:
                    self.add_box(brief)
                brief.isShow = True
            else:
                if brief.isShow:
                    self.remove_box(brief)
                brief.isShow = False

    def add_box(self, brief):
        box = HTMLFactory.get_instance().class_brief_box_first(brief)
        update_class_table_lock.acquire()
        self.class_web.page().runJavaScript("addBox('{0}')".format(box))
        update_class_table_lock.release()

    def remove_box(self, brief):
        update_class_table_lock.acquire()
        self.class_web.page().runJavaScript("removeBox('class_{}')".format(
            brief.classroom.classroom_id))
        update_class_table_lock.release()

    def change_page_record(self):
        self.stackedWidget.setCurrentIndex(1)
        for thread in self.class_brief_threads:
            thread.pause()

    # 关闭实时监控页之后调用
    def resume(self):
        for thread in self.class_brief_threads:
            thread.resume()
コード例 #4
0
ファイル: nexicoMain.py プロジェクト: gromoteur/gromoteur
class Nexico(QMainWindow, Ui_MainWindow):
    """
	Nexico user interface main class
	"""
    def __init__(self,
                 splash,
                 nexicoBase,
                 config,
                 selectionName="standard",
                 parent=None):
        """
		Constructor	
		"""
        QMainWindow.__init__(self)
        self.setupUi(self)
        qfdb = QFontDatabase()
        fi = qfdb.addApplicationFont(":fonts/resources/FreeSans.otf")

        try:
            self.font = qfdb.font(
                qfdb.applicationFontFamilies(fi)[0], "Light", False)
        except:
            self.font = None

        self.config = config
        self.nbBestKids = int(self.config["configuration"]["nbBestKids"])
        self.currentSection = None
        self.selectedWord = ""
        self.selectedTokeni = None
        self.sectList = []
        self.base = nexicoBase
        self.wordTableWidget.setHorizontalHeaderLabels(
            [self.tr("word"), self.tr("frequency")])
        self.autoSelect = 0

        false_positives = set(["aliases", "undefined"])
        self.encodings = set(
            name
            for imp, name, ispkg in pkgutil.iter_modules(encodings.__path__)
            if not ispkg)
        self.encodings.difference_update(false_positives)
        self.encodings = sorted(self.encodings)

        self.statusbar.showMessage(self.tr("Welcome!"), 20000)
        self.fileNameEdit.setText(selectionName)
        self.pb = QtWidgets.QProgressBar(self.statusBar())
        self.statusBar().addPermanentWidget(self.pb)
        self.pb.hide()
        self.splash = splash
        self.selecting = False
        self.graphicsView.setRenderHints(
            QtGui.QPainter.Antialiasing
            or QtGui.QPainter.SmoothPixmapTransform)
        self.ngra = self.ngraDial.sliderPosition()
        self.renoword = re.compile("\W+$", re.U + re.I + re.M)

        self.webView = QWebView()
        self.collocations = Collocations(self)

        #self.gridLayout_3.addWidget(self.graphcanvas, 0, 0, 1, 1)
        self.gridLayout_3.addWidget(self.webView, 0, 0, 1, 1)

        # start with collocation open?
        #openwithcolloc=int(self.config["configuration"]["openwithcolloc"]) # False
        openwithcolloc = False
        self.actionCollocations.setChecked(openwithcolloc)
        self.on_actionCollocations_toggled(openwithcolloc)
        #self.graphButton.setChecked(True)

        #self.specos=None # dict of collocations for current word

        # TODO: solve the memory problem of qsplitter:
        #self.hsplitter=QSplitter(1, self.centralwidget)  # 2=vertical orientation
        #self.centralGridLayout.addWidget(self.hsplitter,  0, 1)
        #self.vspgridLayout = QtGui.QGridLayout(self.hsplitter)
        #self.vspgridLayout.setSpacing(0)
        #self.hsplitter.setHandleWidth(8)
        #self.vspgridLayout.setContentsMargins(2, 0, 2, 0)
        #self.vspgridLayout.addWidget(self.westwidget, 0, 0)
        #self.vspgridLayout.addWidget(self.eastwidget)

        self.load()
        self.filter.textChanged.connect(self.filterChanged)
        self.colfilter.textChanged.connect(self.colfilterChanged)

        self.recenter = RecenterClass()

#

    def load(self, encoding="autodetect"):
        #		self.specTableWidget.hide()
        self.wordTableWidget.clear()
        self.sectionMap.clear()
        #print 14
        self.base.progressChanged.connect(self.updateProgress)
        self.base.finished.connect(self.loadFinished)
        self.base.start()

    def updateProgress(self, i, message="Loading..."):
        if self.pb.isHidden(): self.pb.show()
        self.pb.setValue(i)
        if message:
            self.statusbar.showMessage(message)

    def loadFinished(self):
        """
		loading of base is finished
		"""
        self.base.progressChanged.emit(95.0,
                                       "Showing table for first section...")
        if not len(self.sectionMap):  # first time:
            self.splash.finish(self)
            self.sectrast = self.base.sectrast  #s[0] #my default sectrast is the first of the base i just created
            #self.sectionMap.clear()
            if self.sectrast:
                for si, section in enumerate(
                        self.sectrast.sections):  # pour chaque section
                    #					u"\u25A1" u"◻"
                    carre = QtWidgets.QListWidgetItem("\u25A1",
                                                      self.sectionMap)
                    carre.section = section
                    carre.setToolTip("<b>" + str(section) + ":</b>" +
                                     (self.sectrast.urls[si] or ""))
                    if self.font: carre.setFont(self.font)

                self.sectionMap.setCurrentRow(0)  # select the first square

            #self.actionComputeSpecificity.setEnabled(True)

        self.statusbar.showMessage("Finished loading", 2000)
        self.pb.hide()

        if self.actionCollocations.isChecked():
            # autostart the collocation stuff:
            self.wordTableWidget.selectRow(0)
            self.graphButton.setChecked(True)

    def fillTokenTable(self):
        """
		fills the token table with:
		- all the tokens
		- for each token:
			its total frequency
			its frequency in the selected selection
			its specificity for the selected selection
			
		called for new section selection 
		"""

        if debug: print("fillTokenTable", self.selection)

        self.wordTableWidget.clear()
        self.wordTableWidget.setSortingEnabled(False)
        self.wordTableWidget.setRowCount(len(self.base.d))
        self.wordTableWidget.setColumnCount(4)

        fi = re.compile(str(self.filter.text()))

        for i, tokeni in enumerate(self.base.d):
            s = self.base.d.idtotoken[tokeni]  #.decode("utf-8")
            worditem = QtWidgets.QTableWidgetItem(s)
            if self.renoword.match(s):  # nowords get tooltip
                # TODO: check what's going on here:  0x8e ValueError: no such name
                #for l in s:
                #	print l.encode("utf-8"),type(l),len(l),hex(ord(l))
                #	print unicodedata.name(unicode(l))
                try:
                    worditem.setToolTip(" - ".join(
                        [unicodedata.name(str(l)) for l in s]))
                except ValueError:
                    try:
                        worditem.setToolTip("special control character: " +
                                            " - ".join([
                                                unicodedata.category(str(l)) +
                                                ":" + hex(ord(str(l)))
                                                for l in s
                                            ]))
                    except:
                        print("can't find unicode data for",
                              [s])  #,s.encode("iso-8859-1")
            if debug: print("fillTokenTable", self.selection, 2)
            self.wordTableWidget.setItem(i, 0, worditem)
            if debug: print("fillTokenTable", self.selection, 3)
            self.wordTableWidget.setRowHidden(
                i, not fi.search(self.wordTableWidget.item(i, 0).text()))
            totfreqitem = QtWidgets.QTableWidgetItem()
            if debug: print("fillTokenTable", self.selection, 4)
            #totfreqitem.setData(Qt.EditRole, len(self.sectrast.tokens[token]))
            totfreqitem.setData(Qt.EditRole, self.base.d.freqs[tokeni])
            totfreqitem.setTextAlignment(QtCore.Qt.AlignRight)
            self.wordTableWidget.setItem(i, 1, totfreqitem)
            if debug: print("fillTokenTable", self.selection, 5)

            freqitem = QtWidgets.QTableWidgetItem('%7d' % sum([
                self.base.sectrast.bows[se].get(tokeni, 0)
                for se in self.selection
            ]))
            freqitem.setTextAlignment(QtCore.Qt.AlignRight)
            self.wordTableWidget.setItem(i, 2, freqitem)
            if debug: print("fillTokenTable", self.selection, 6)
            specitem = QtWidgets.QTableWidgetItem()
            #
            try:
                specitem.setData(
                    Qt.EditRole,
                    self.sectrast.specificity[tokeni][self.selection])
            except:
                self.sectrast.computeOtherSpecificity(self.selection)
                specitem.setData(
                    Qt.EditRole,
                    self.sectrast.specificity[tokeni][self.selection])
                self.loadFinished()

            specitem.setTextAlignment(QtCore.Qt.AlignRight)
            if debug: print("fillTokenTable", self.selection, 7)
            self.wordTableWidget.setItem(i, 3, specitem)
            if debug: print("fillTokenTable", self.selection, 8)

        self.wordTableWidget.setHorizontalHeaderLabels([
            self.tr("token"),
            self.tr("totfreq"),
            self.tr("freq"),
            self.tr("spec")
        ])
        self.wordTableWidget.verticalHeader().setStyleSheet(
            "QHeaderView { font-size: 6pt; }")
        self.wordTableWidget.resizeColumnsToContents()
        self.wordTableWidget.setSortingEnabled(True)
        if debug: print("fillTokenTable", self.selection, 9)
        self.wordTableWidget.sortItems(3, 1)  # sort by specificity, descending
        self.actionSaveTable.setEnabled(True)
        self.actionSaveGraph.setEnabled(True)

    def filterChanged(
        self, text
    ):  # TODO: redo that with a real QAbstractItemModel and QSortFilterProxyModel
        try:
            fi = re.compile(str(text))
        except:
            return  # TODO: show errors in regex?
        for i in range(self.wordTableWidget.rowCount()):
            self.wordTableWidget.setRowHidden(
                i, not fi.search(self.wordTableWidget.item(i, 0).text()))

    def colfilterChanged(
        self, text
    ):  # TODO: redo that with a real QAbstractItemModel and QSortFilterProxyModel
        try:
            fi = re.compile(str(text))
        except:
            return  # TODO: show errors in regex?
        for i in range(self.collocTableWidget.rowCount()):
            self.collocTableWidget.setRowHidden(
                i, not fi.search(self.collocTableWidget.item(i, 0).text()))

    #def selectToken(self,token):

    def colloc(self, token):
        """
		
		fills the colloc table
		
		"""

        if debug: print("fillCollocTable", token)

        if self.ngra not in self.sectrast.specollocs:
            self.sectrast.computeCollocations(
                self.ngra)  # compute collocations only the first time

        if not token:
            self.pb.hide()
            return
        #selectedTokeni = self.base.d.token2id[self.selectedWord]
        #d=self.sectrast.specollocs[selectedTokeni]
        #for coi in sorted(d,key=d.get,reverse=True):
        #print "___",self.base.d.idtotoken[coi],d[coi]
        try:
            self.selectedTokeni = self.base.d.token2id[
                token]  # .encode("utf-8")
        except:
            self.selectedTokeni = self.base.d.token2id[token]
        specos = {
            i: sp
            for i, sp in self.sectrast.specollocs[self.ngra][
                self.selectedTokeni].items() if sp != 0
        }
        #print self.selectedTokeni
        self.collocTableWidget.clear()
        self.collocTableWidget.setSortingEnabled(False)
        self.collocTableWidget.setRowCount(len(specos))
        self.collocTableWidget.setColumnCount(4)

        fi = re.compile(str(self.colfilter.text()))

        for i, tokeni in enumerate(specos):
            s = self.base.d.idtotoken[tokeni]  #.decode("utf-8")
            worditem = QtWidgets.QTableWidgetItem(s)
            if self.renoword.match(s):  # nowords get tooltip
                # TODO: check what's going on here:  0x8e ValueError: no such name
                #for l in s:
                #	print l.encode("utf-8"),type(l),len(l),hex(ord(l))
                #	print unicodedata.name(unicode(l))
                try:
                    worditem.setToolTip(" - ".join(
                        [unicodedata.name(str(l)) for l in s]))
                except ValueError:
                    try:
                        worditem.setToolTip("special control character: " +
                                            " - ".join([
                                                unicodedata.category(str(l)) +
                                                ":" + hex(ord(str(l)))
                                                for l in s
                                            ]))
                    except:
                        print("can't find unicode data for",
                              [s])  #,s.encode("iso-8859-1")
            self.collocTableWidget.setItem(i, 0, worditem)
            self.collocTableWidget.setRowHidden(
                i, not fi.search(self.collocTableWidget.item(i, 0).text()))
            totfreqitem = QtWidgets.QTableWidgetItem()
            #totfreqitem.setData(Qt.EditRole, len(self.sectrast.tokens[token]))
            totfreqitem.setData(Qt.EditRole, self.base.d.freqs[tokeni])
            totfreqitem.setTextAlignment(QtCore.Qt.AlignRight)
            self.collocTableWidget.setItem(i, 1, totfreqitem)

            freqitem = QtWidgets.QTableWidgetItem(
                '%7d' %
                self.sectrast.collocs[self.ngra][self.selectedTokeni].get(
                    tokeni, 0))
            freqitem.setTextAlignment(QtCore.Qt.AlignRight)
            self.collocTableWidget.setItem(i, 2, freqitem)

            specitem = QtWidgets.QTableWidgetItem()
            specitem.setData(Qt.EditRole, specos[tokeni])

            #try:
            #specitem.setData(Qt.EditRole, self.sectrast.specificity[tokeni][self.selection] )
            #except:
            #self.sectrast.computeOtherSpecificity(self.selection)
            #specitem.setData(Qt.EditRole, self.sectrast.specificity[tokeni][self.selection])
            #self.loadFinished()

            specitem.setTextAlignment(QtCore.Qt.AlignRight)
            self.collocTableWidget.setItem(i, 3, specitem)

        self.collocTableWidget.setHorizontalHeaderLabels([
            self.tr("token"),
            self.tr("totfreq"),
            self.tr("cooc"),
            self.tr("spec")
        ])
        self.collocTableWidget.verticalHeader().setStyleSheet(
            "QHeaderView { font-size: 6pt; }")
        self.collocTableWidget.resizeColumnsToContents()
        self.collocTableWidget.setSortingEnabled(True)
        #print 7777
        self.collocTableWidget.sortItems(3,
                                         1)  # sort by specificity, descending
        #self.actionSaveTable.setEnabled(True)
        #self.actionSaveGraph.setEnabled(True)
        self.statusbar.showMessage("Finished loading", 3000)
        self.pb.hide()

    def updateInfo(self):
        """
		fills 
		- the text above the token table
		- the information line under the sectionMap
		"""

        if len(self.selection) == 1:
            infospec = "Specificity table for section {nr}.".format(
                nr=str(self.selection[0]))
        elif len(self.selection) < 10:
            infospec = "sections {nr}.".format(nr=str(self.selection)[1:-1])
        else:
            infospec = "{totalselect} sections: {start}...{end}".format(
                totalselect=len(self.selection),
                start=str([s for s in self.selection[:3]])[1:-1],
                end=str([s for s in self.selection[-3:]])[1:-1])
        self.tableBox.setTitle(infospec)
        self.pageNameLabel.setText(
            str(sum([self.sectrast.nrtoks[s]
                     for s in self.selection])) + " tokens"
        )  # todo: think of how to show the names of files: self.selection[0][1].split("/")[-1]+" - "+
        infomap = "Text with {totok} tokens in {totsec} sections.".format(
            totok=self.sectrast.size, totsec=len(self.sectrast.sections))

        if self.selectedWord:
            infograph = "Occurrences of '{token}'".format(
                token=str(self.selectedWord))
            #
            self.graphicsBox.setTitle(infograph)
            if self.graphButton.isChecked():
                self.graphicsBox.setToolTip(
                    infograph +
                    ". Colors show specificity of the token.".format(
                        token=str(self.selectedWord)))

            infomap = infomap + " Colors show occurrences (pink squares) and specifities (red +, green - background) of '{token}'.".format(
                token=str(self.selectedWord))

        self.mapBox.setTitle(infomap)
        self.mapBox.setToolTip(infomap)

    @pyqtSlot()
    def on_sectionMap_itemSelectionChanged(self):
        """
		Slot documentation goes here.
		"""
        if not len(self.sectionMap.selectedItems()): return
        if self.selecting: return
        if debug: print("on_sectionMap_itemSelectionChanged", 1)
        #self.selection=tuple([s.section.id for  s in self.sectionMap.selectedItems()])
        self.selection = tuple(
            [s.section for s in self.sectionMap.selectedItems()])

        if len(self.selection) >= 1:
            remot = re.compile(r"\b(" + str(self.selectedWord) + r")\b", re.U)
            #text=remot.sub(r"<span style='color:red'>\1</span>", self.sectionMap.selectedItems()[0].section.getText())
            text = remot.sub(
                r"<span style='color:red'>\1</span>",
                self.base.rowIdFunction(
                    self.sectionMap.selectedItems()[0].section))
            if debug: print("on_sectionMap_itemSelectionChanged", 2)
            self.editSection.setHtml(text)
            if debug: print("on_sectionMap_itemSelectionChanged", 3)
            #			print text
            self.sectionBox.setTitle(
                "Content of section " + str(self.selection[0]) + " - " +
                (self.sectrast.urls[self.sectrast.sections.index(
                    self.selection[0])] or "").split("/")[-1] + " - " +
                str(self.sectrast.nrtoks[self.selection[0]]) + " tokens")
            if debug: print("on_sectionMap_itemSelectionChanged", 4)
            #print self.sectrast.nrtoks[self.selection[0]]
        else:
            self.sectionBox.setTitle("No section selected ")
            self.editSection.setHtml("")
        self.fillTokenTable()
        self.updateInfo()

    # TODO: make multi-word specificities possible
#	@pyqtSlot()
#	def on_wordTableWidget_itemSelectionChanged(self):
#		print self.wordTableWidget.selectedIndexes()
#		rows=sorted(set([i.row() for i in  self.wordTableWidget.selectedIndexes()] ))
#		self.selectedWords = sorted([unicode(self.wordTableWidget.item(r, 0).text()) for r in rows])
#		self.selectedTokenis = [self.base.d.token2id[unicode(self.wordTableWidget.item(r, 0).text())] for r in rows]
#		print self.selectedTokenis

#@pyqtSignature("QTableWidgetItem*, QTableWidgetItem*")

    @pyqtSlot(QTableWidgetItem, QTableWidgetItem)
    def on_collocTableWidget_currentItemChanged(self, item, previous):
        if not item: item = previous
        print(46546, item, previous)
        try:
            selectedWord = str(
                self.collocTableWidget.item(item.row(), 0).text())
            #self.selectedTokeni = self.base.d.token2id[self.selectedWord]
            print(selectedWord)
            self.selectWordInWordTableWidget(selectedWord)
        except Exception as e:
            print("oh, something wrong", Exception, e)
            #self.selectedTokeni=0

    def selectWordInWordTableWidget(self, word):
        for i in range(self.wordTableWidget.rowCount()):
            if self.wordTableWidget.item(i, 0).text() == word:
                self.wordTableWidget.selectRow(i)
                break

    #@pyqtSignature("QTableWidgetItem*, QTableWidgetItem*")
    def on_wordTableWidget_currentItemChanged(self, item, previous):
        #print "000",item, previous
        if not item: item = previous
        try:
            self.selectedWord = str(
                self.wordTableWidget.item(item.row(), 0).text())
            try:
                self.selectedTokeni = self.base.d.token2id[
                    self.
                    selectedWord]  # TODO: clean this mess up! .encode("utf-8")
            except:
                self.selectedTokeni = self.base.d.token2id[self.selectedWord]
        except Exception as e:
            print("oh, something wrong", Exception, e)
            self.selectedTokeni = 0
        #print 8888

        self.sectionMap.clearSelection()
        red = QtGui.QColor("red")
        green = QtGui.QColor("green")
        whitebrush = QtGui.QBrush(QtCore.Qt.white, QtCore.Qt.NoBrush)
        self.smin, self.smax, self.fmax = 0, 0, 0
        #		print self.currwordsectspecdic
        for i, section in enumerate(self.sectrast.sections):
            #s=self.currwordsectspecdic[(i, )]
            # print i,section,sorted(self.sectrast.specificity[self.selectedTokeni])
            # try:
            s = self.sectrast.specificity[self.selectedTokeni][(
                section, )]  # TODO: check why error on windows!
            # except:s=0
            if s > 0:
                #self.sectionMap.item(i).setBackgroundColor(red.darker(30*s))
                self.sectionMap.item(i).setBackground(
                    QtGui.QBrush(QtGui.QColor(QtCore.Qt.red).darker(30 * s)))
            elif s < 0:
                self.sectionMap.item(i).setBackground(
                    QtGui.QBrush(
                        QtGui.QColor(QtCore.Qt.green).darker(30 * -s)))
            else:
                self.sectionMap.item(i).setBackground(whitebrush)
            freq = self.sectrast.bows[section].get(self.selectedTokeni, 0)
            if freq:
                self.sectionMap.item(i).setForeground(
                    QtGui.QBrush(QtCore.Qt.magenta))
            else:
                self.sectionMap.item(i).setForeground(
                    QtGui.QBrush(QtCore.Qt.black))
            if s > self.smax: self.smax = s
            elif s < self.smin: self.smin = s

            if freq > self.fmax: self.fmax = freq

        self.updateInfo()
        #if self.currwordsectspecdic:
        #print ";.isChecked()",self.graphButton.isChecked()
        #print self.autoSelect,"jjj"
        if self.actionCollocations.isChecked(): self.colloc(self.selectedWord)
        #print self.autoSelect,"uuu"
        if self.autoSelect:
            #sleep(.5)
            #print self.recenter.word
            #if self.recenter.word==self.selectedWord:
            if self.autoSelect and self.graphButton.isChecked():
                #print "sleep",self.recenter.word

                #self.autoSelect=0
                #sleep(.5)
                baseUrl = QUrl.fromLocalFile(
                    QDir.current().absoluteFilePath("lib/resources/about.html")
                )  # any html file to base the setHtml!!!
                self.webView.setHtml(self.collocations.graph(self.nbBestKids),
                                     baseUrl)
                #self.makeCollocGraph()
                #sleep(.5)
                self.webView.page().mainFrame().addToJavaScriptWindowObject(
                    "pyObj", self.recenter)
                #self.autoSelect=1
                #print 111,self.recenter.word
            return

        if self.graphButton.isChecked(): self.makeCollocGraph()
        else: self.makeSpecGraph()
        #print "www"
        self.actionSelect_sections_with_occurrences.setEnabled(True)
        self.actionSelectposspecificsections.setEnabled(True)
        self.actionSelectnegspecificsections.setEnabled(True)

    def makeSpecGraph(self, numMarks=10):
        """
		draws the curve of the evolution of occurrences and specificities in the sections
		"""
        #if self.graphcanvas: self.graphcanvas.hide()
        self.graphicsView.show()
        #print "makeSpecGraph"
        size = self.graphicsView.size()

        scene = QtWidgets.QGraphicsScene(self)
        #		scene.addText(self.selectedWord)
        specpath = QtGui.QPainterPath()
        specpath.setFillRule(Qt.WindingFill)
        freqpath = QtGui.QPainterPath()
        specpath.moveTo(0, 0)
        freqpath.moveTo(0, 0)

        nrsects = len(self.sectrast.sections)

        snry = size.height() / (self.smax - self.smin + 1) * .75
        fnry = size.height() / (self.fmax + 1) * .5

        tex = int(nrsects / numMarks)
        if nrsects > 100: pathw = 1.0
        else: pathw = 3.0

        for i, si in enumerate(self.sectrast.sections):
            s = self.sectrast.specificity[self.selectedTokeni][(si, )]
            specpath.lineTo(
                QtCore.QPointF(i * size.width() * .8 / nrsects, -s * snry))
            freqpath.lineTo(
                QtCore.QPointF(
                    i * size.width() * .8 / nrsects,
                    -self.sectrast.bows[si].get(self.selectedTokeni, 0) *
                    fnry))
            if not tex or not i % tex:
                num = scene.addText(str(i), QtGui.QFont("Helvetica", 6))
                num.setPos(QtCore.QPointF(i * size.width() * .8 / nrsects, 0))
        specpath.lineTo(QtCore.QPointF(i * size.width() * .8 / nrsects, 0))
        freqpath.lineTo(QtCore.QPointF(i * size.width() * .8 / nrsects, 0))
        specpath.lineTo(0, 0)
        freqpath.lineTo(0, 0)

        scene.addPath(
            specpath,
            QtGui.QPen(self.base.specColor, pathw, Qt.SolidLine, Qt.RoundCap,
                       Qt.RoundJoin), QtGui.QBrush(self.base.specColor))
        scene.addPath(
            freqpath,
            QtGui.QPen(self.base.freqColor, pathw, Qt.SolidLine, Qt.RoundCap,
                       Qt.RoundJoin))

        self.graphicsView.centerOn(0, 0)

        scene.addText(self.selectedWord).moveBy(0, 20)
        self.graphicsView.setScene(scene)
        self.graphicsView.fitInView(scene.sceneRect(), 1)

        self.graphicsView.show()
        self.actionCopyGraphToClipboard.setEnabled(True)
#		print self.graphicsView.sceneRect () , size, self.graphicsView.size()

    @pyqtSlot()
    def on_actionSaveGraph_triggered(self):
        if self.selectedWord: filename = self.selectedWord + "-specificity.png"
        else: filename = "specificity.png"
        fileName = QFileDialog.getSaveFileName(
            self, "Save Graph as png, svg, or pdf", filename,
            "PNG Image (*.png);;PDF File(*.pdf);;SVG File(*.svg)")[0]
        if str(fileName).endswith(".png"):
            #pixMap=QPixmap.grabWidget( self.graphicsView)
            pixMap = self.graphicsView.grab()
            pixMap.save(fileName)
        elif str(fileName).endswith(".pdf"):
            pdfPrinter = QPrinter()
            pdfPrinter.setOutputFormat(QPrinter.PdfFormat)
            pdfPrinter.setPaperSize(
                QSizeF(self.graphicsView.width(), self.graphicsView.height()),
                QPrinter.Point)
            pdfPrinter.setFullPage(True)
            pdfPrinter.setOutputFileName(fileName)
            pdfPainter = QPainter()
            pdfPainter.begin(pdfPrinter)
            self.graphicsView.render(pdfPainter)
            pdfPainter.end()
        elif str(fileName).endswith(".svg"):
            svgGen = QSvgGenerator()
            svgGen.setFileName(fileName)
            svgGen.setSize(
                QSize(self.graphicsView.width(), self.graphicsView.height()))
            svgGen.setViewBox(
                QRect(0, 0, self.graphicsView.width(),
                      self.graphicsView.height()))
            svgGen.setTitle(filename)
            svgGen.setDescription("Specificity graph generated by Gromoteur")
            painter = QPainter(svgGen)
            self.graphicsView.render(painter)
            painter.end()

    @pyqtSlot()
    def on_actionOpen_graph_in_browser_triggered(self):
        self.collocations.viewGraphInBrowser()

    @pyqtSlot()
    def on_actionCopyGraphToClipboard_triggered(self):
        #pixMap=QPixmap.grabWidget( self.graphicsView)
        pixMap = self.graphicsView.grab()
        # print type(pixMap)
        clipboard = QApplication.clipboard()

        clipboard.setPixmap(pixMap)

#		QApplication::clipboard()->setPixmap( QPixmap( "path to my png" ) )

    @pyqtSlot()
    def on_actionSaveTable_triggered(self):
        #		self.specTableWidget.show()

        #replacer=re.compile("\n

        filename = QFileDialog.getSaveFileName(self, self.tr("Save the table"),
                                               "nexico-export.csv", "*.*")[0]
        if filename:
            if debug: print("filename", filename)
            out = codecs.open(filename, "w", "utf-8")
            out.write("\t".join([
                str(self.wordTableWidget.horizontalHeaderItem(c).text())
                for c in range(self.wordTableWidget.columnCount())
            ]) + "\n")

            for r in range(self.wordTableWidget.rowCount()):
                out.write("\t".join([
                    str(self.wordTableWidget.item(r, 0).text()).replace(
                        "\n", "↩").replace("\t", "⇥")
                ] + [
                    str(self.wordTableWidget.item(r, c).text()).strip()
                    for c in range(1, self.wordTableWidget.columnCount())
                ]) + "\n")
            out.close()
            self.statusbar.showMessage("Exported " + filename, 3000)

    @pyqtSlot()
    def on_actionSelect_sections_with_occurrences_triggered(self):
        """
		select the sections that contain the selected token
		"""
        if debug: print("actionSelect_sections_with_occurrences")
        self.selecting = True
        for i, si in enumerate(self.sectrast.sections):
            freq = self.sectrast.bows[si].get(self.selectedTokeni, 0)
            if freq:
                self.sectionMap.item(i).setSelected(True)
            else:
                self.sectionMap.item(i).setSelected(False)

        self.selecting = False
        self.on_sectionMap_itemSelectionChanged()

    @pyqtSlot()
    def on_actionSelectposspecificsections_triggered(self):
        """
		select the sections that are marked as positive specificity
		"""
        if debug: print("on_actionSelectposspecificsections_activated")
        self.selecting = True
        for i, si in enumerate(self.sectrast.sections):
            s = self.sectrast.specificity[self.selectedTokeni][(si, )]
            if s > 0:
                self.sectionMap.item(i).setSelected(True)
            else:
                self.sectionMap.item(i).setSelected(False)
        self.selecting = False
        self.on_sectionMap_itemSelectionChanged()

    @pyqtSlot()
    def on_actionSelectnegspecificsections_triggered(self):
        """
		select the sections that are marked as negative specificity
		"""
        if debug: print("on_actionSelectnegspecificsections_activated")
        self.selecting = True
        for i, si in enumerate(self.sectrast.sections):
            s = self.sectrast.specificity[self.selectedTokeni][(si, )]
            if s < 0:
                self.sectionMap.item(i).setSelected(True)
            else:
                self.sectionMap.item(i).setSelected(False)
        self.selecting = False
        self.on_sectionMap_itemSelectionChanged()

    @pyqtSlot()
    def on_actionPreferences_triggered(self):
        """
		opening the help dialog
		"""
        PreferencesDialog(self).exec_()
        self.nbBestKids = int(self.config["configuration"]["nbBestKids"])

    #@pyqtSignature("bool")
    def on_actionCollocations_toggled(self, checked):
        """
		
		"""
        self.colloGroupBox.setVisible(checked)
        self.collocationlabel.setVisible(checked)
        #if checked:
        self.graphButton.setChecked(checked)

        self.wordTableWidget.selectRow(0)

        self.config["configuration"]["openwithcolloc"] = int(checked)
        self.config.write()

    @pyqtSlot()
    def on_ngraDial_sliderReleased(self):
        """
		ngra slider released: new value of ngra
		"""
        self.ngraDial.setEnabled(False)
        self.ngra = self.ngraDial.sliderPosition()
        if self.ngra not in self.sectrast.specollocs:
            self.sectrast.computeCollocations(self.ngra)
        if self.actionCollocations.isChecked(): self.colloc(self.selectedWord)
        self.ngraDial.setEnabled(True)

    @pyqtSlot()
    def on_actionInformationNexico_triggered(self):
        """
		select the sections that are marked as negative specificity
		"""
        QMessageBox.about(
            self, "Nexico! - information",
            "Nexico is a tool for textual statistics inside Gromoteur.\nThis is free software distributed under GPL Version 3.\nPlease visit gromoteur.ilpga.fr for further information."
        )
        #QMessageBox::about ( QWidget * parent, const QString & title, const QString & text )

    def makeCollocGraph(self):
        #print "makeCollocGraph"
        if (self.autoSelect or not self.selectedTokeni
                or self.ngra not in self.sectrast.specollocs):
            return

        self.graphicsBoxTitle = self.graphicsBox.title()
        if debug:
            QtWebKit.QWebSettings.globalSettings().setAttribute(
                QtWebKit.QWebSettings.DeveloperExtrasEnabled, True)
        self.webView.setPage(None)  # necessary for repeated recentering
        #self.recenter=RecenterClass()

        #self.webView.settings().setUserStyleSheetUrl(QUrl(":images/images/graphstyle.css"));

        baseUrl = QUrl.fromLocalFile(
            QDir.current().absoluteFilePath("lib/resources/about.html")
        )  # any html file to base the setHtml!!!
        self.webView.setHtml(self.collocations.graph(self.nbBestKids), baseUrl)
        #self.webView.page().mainFrame().addToJavaScriptWindowObject("pyObj", self.recenter)
        #self.webView.page().mainFrame().addToJavaScriptWindowObject("pyObj", self.recenter)  # 2019 to recreate! https://doc.qt.io/qt-5/qtwebenginewidgets-qtwebkitportingguide.html
        #print 3
        self.graphicsBox.setTitle("Collocations")
        self.actionOpen_graph_in_browser.setEnabled(True)

    #@pyqtSignature("bool")
    def on_graphButton_toggled(self, checked):
        """
		Show and hide the cooc graph
		"""
        if checked:
            self.graphicsView.hide()
            self.makeCollocGraph()
            self.webView.show()

        else:
            self.webView.hide()
            self.graphicsBox.setTitle(self.graphicsBoxTitle)
            self.graphicsView.show()

    def clean(self, text):
        """
		not used
		"""
        text = re.sub(r"\s+", " ", text, re.U)
        text = re.sub(r"\t+", " ", text, re.U)
        text = text.replace("...", "…")
        apost = re.compile(r"[\‘\’]", re.U)
        text = apost.sub(r"'", text)
        return text

    def words(self, text):
        """
		not used
		"""
        text = self.clean(text)
        ponct = re.compile(r"(?<=\w)([\!\,\?\.\:\;»«])", re.U)
        text = ponct.sub(r" \1", text)
        apost = re.compile(r"([\'\(»«\‘\’])", re.U)
        text = apost.sub(r"\1 ", text)
        words = text.split()
        return words
コード例 #5
0
class TrendPage(QWidget):
    def __init__(self, *args, **kwargs):
        super(TrendPage, self).__init__(*args, **kwargs)
        layout = QHBoxLayout(self)
        layout.setContentsMargins(QMargins(0, 0, 0, 1))
        layout.setSpacing(0)
        self.variety_folded = ScrollFoldedBox()
        self.variety_folded.left_mouse_clicked.connect(self.variety_clicked)
        layout.addWidget(self.variety_folded)
        # 右侧是QTableWidget用于显示数据表信息

        # tableinfo_layout.addWidget(self.data_table)
        # layout.addLayout(tableinfo_layout)
        # 右侧是webView
        r_layout = QVBoxLayout(self)
        self.table_lib_btn = QPushButton("数据库", self, objectName='libBtn')
        self.table_lib_btn.setToolTip("点击查看当前品种数据表")
        self.table_lib_btn.setCursor(Qt.PointingHandCursor)
        self.table_lib_btn.hide()
        self.table_lib_btn.clicked.connect(self.reverse_charts_and_table)
        r_layout.addWidget(self.table_lib_btn, alignment=Qt.AlignLeft)
        self.charts_loader = QWebEngineView(self)
        r_layout.addWidget(self.charts_loader)

        self.data_table = DataTableWidget(self)
        r_layout.addWidget(self.data_table)
        self.data_table.hide()

        layout.addLayout(r_layout)

        self.setLayout(layout)
        # 设置折叠窗的样式
        self.variety_folded.setFoldedStyleSheet("""
        QScrollArea{
            border: none;
        }
        #foldedBox{
            border-right: 1px solid rgb(180, 180, 180);
        }
        #foldedHead{
            background-color: rgb(145,202,182);
            border-bottom: 1px solid rgb(200,200,200);
            border-right: 1px solid rgb(180, 180, 180);
            max-height: 30px;
        }
        #headLabel{
            padding:8px 5px;
            font-weight: bold;
            font-size: 15px;
        }
        #foldedBody{
            background-color: rgb(240, 240, 240);
            border-right: 1px solid rgb(180, 180, 180);
        }
        /*折叠窗内滚动条样式*/
        #foldedBox QScrollBar:vertical{
            width: 5px;
            background: transparent;
        }
        #foldedBox QScrollBar::handle:vertical {
            background: rgba(0, 0, 0, 30);
            width: 5px;
            border-radius: 5px;
            border: none;
        }
        #foldedBox QScrollBar::handle:vertical:hover,QScrollBar::handle:horizontal:hover {
            background: rgba(0, 0, 0, 80);
        }
        """)
        self.setStyleSheet("""
        #libBtn{border:1px solid rgb(200,200,200);border-left:none;color:rgb(254,255,255);background-color:rgb(255,87,87);padding:5px 10px;font-size:14px;font-weight:bold;border-bottom-right-radius:5px}
        #libBtn:hover{color:rgb(15,67,146);font-weight:bold;background-color:rgb(74,247,198)}
        """)
        self.charts_loader.load(QUrl(settings.SERVER_ADDR + 'trend/charts/'))

    def resizeEvent(self, event):
        # 设置折叠窗的大小
        box_width = self.parent().width() * 0.228
        self.variety_folded.setFixedWidth(box_width + 8)
        self.variety_folded.setBodyHorizationItemCount()
        self.charts_loader.setFixedWidth(self.parent().width() - box_width - 8)

    # 获取所有品种组和品种
    def getGroupVarieties(self):
        try:
            r = requests.get(url=settings.SERVER_ADDR + 'variety/?way=group')
            if r.status_code != 200:
                raise ValueError('获取失败!')
            response = json.loads(r.content.decode('utf-8'))
        except Exception as e:
            settings.logger.error("【基本分析】模块获取左侧品种菜单失败:{}".format(e))
        else:
            for group_item in response['variety']:
                head = self.variety_folded.addHead(group_item['name'])
                body = self.variety_folded.addBody(head=head)
                for sub_item in group_item['subs']:
                    body.addButton(sub_item['id'], sub_item['name'])
            self.variety_folded.container.layout().addStretch()

    # 点击了品种,显示当前品种下的品种页显示的图形
    def variety_clicked(self, vid, text):
        self.charts_loader.load(
            QUrl(settings.SERVER_ADDR + 'trend/variety-charts/' + str(vid) +
                 '/'))
        self.get_current_variety_table(vid, text)

    # 点击了品种,请求当前品种下的所有数据表
    def get_current_variety_table(self, vid, text):
        try:
            r = requests.get(url=settings.SERVER_ADDR +
                             'variety/{}/trend/table/'.format(vid))
            if r.status_code != 200:
                raise ValueError("获取品种该数据表失败!")
            response = json.loads(r.content.decode('utf8'))
        except Exception as e:
            settings.logger.error("【基本分析】模块获取品种下的数据表失败:{}".format(e))
        else:
            self.data_table.show_tables(response["tables"])
            self.table_lib_btn.show()

    # 切换图形与表格的显示
    def reverse_charts_and_table(self):
        if self.data_table.isHidden():
            self.charts_loader.hide()
            self.data_table.show()
            self.table_lib_btn.setText("图形库")
            self.table_lib_btn.setToolTip("点击查看当前品种图形")
        else:
            self.data_table.hide()
            self.charts_loader.show()
            self.table_lib_btn.setText("数据库")
            self.table_lib_btn.setToolTip("点击查看当前品种数据表")
コード例 #6
0
ファイル: variety_price.py プロジェクト: zizle/rdDataAnalyser
class VarietyPriceWindow(AncestorWindow):
    name = "variety_price"
    export_table_signal = pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(VarietyPriceWindow, self).__init__(*args, **kwargs)
        """绑定公用属性"""
        self.products = None
        self.db_worker = None
        # 线程是否结束标志位
        self.exchange_lib_thread_over = True
        self.selected_variety_thread_over = True
        """总布局"""
        self.vertical_layout = QVBoxLayout()  # 总纵向布局
        top_select = QHBoxLayout()  # 顶部横向条件选择栏
        """交易所选择下拉框"""
        exchange_label = QLabel('选择交易所:')
        self.exchange_lib = QComboBox()
        self.exchange_lib.activated[str].connect(
            self.exchange_lib_selected)  # 选择交易所调用的方法
        """品种选择下拉框"""
        variety_label = QLabel('选择品种:')
        self.variety_lib = QComboBox()
        self.variety_lib.setMinimumSize(80, 20)
        self.variety_lib.activated[str].connect(
            self.variety_lib_selected)  # 选择品种所调用的方法
        """时间选择"""
        begin_time_label = QLabel("起始日期:")
        self.begin_time = QDateEdit(
            QDate.currentDate().addDays(-2))  # 参数为设置的日期
        self.begin_time.setDisplayFormat('yyyy-MM-dd')  # 时间显示格式
        self.begin_time.setCalendarPopup(True)  # 使用日历选择时间
        end_time_label = QLabel("终止日期:")
        self.end_time = QDateEdit(QDate.currentDate().addDays(-1))  # 参数为设置的日期
        self.end_time.setDisplayFormat('yyyy-MM-dd')  # 时间显示格式
        self.end_time.setCalendarPopup(True)  # 使用日历选择时间
        """确认按钮"""
        self.confirm_button = QPushButton("确定")
        self.confirm_button.clicked.connect(self.confirm)
        """水平布局添加控件"""
        top_select.addWidget(exchange_label)
        top_select.addWidget(self.exchange_lib)
        top_select.addWidget(variety_label)
        top_select.addWidget(self.variety_lib)
        top_select.addWidget(begin_time_label)
        top_select.addWidget(self.begin_time)
        top_select.addWidget(end_time_label)
        top_select.addWidget(self.end_time)
        top_select.addWidget(self.confirm_button)
        """自定义部件"""
        # 工具栏
        self.tools = ToolWidget()
        tool_btn = QPushButton("季节图表")
        self.tool_view_all = QPushButton("返回总览")
        self.tool_view_all.setEnabled(False)
        self.tool_view_all.clicked.connect(self.return_view_all)
        self.tools.addTool(tool_btn)
        self.tools.addTool(self.tool_view_all)
        self.tools.addSpacer()
        tool_btn.clicked.connect(self.season_table)
        # 画布
        self.map_widget = MapWidget()
        # 表格
        self.table_widget = TableWidget(4)
        # 设置格式
        self.table_widget.set_style(
            header_labels=['日期', '价格', '成交量合计', '持仓量合计'])
        """创建QSplitter"""
        self.show_splitter = QSplitter()
        self.show_splitter.setOrientation(Qt.Vertical)  # 垂直拉伸
        # 加入自定义控件
        self.show_splitter.addWidget(self.map_widget)
        self.show_splitter.addWidget(self.table_widget)
        """垂直布局添加布局和控件并设置到窗口"""
        self.vertical_layout.addLayout(top_select)
        self.vertical_layout.addWidget(self.tools)
        self.vertical_layout.addWidget(self.show_splitter)
        # 加入控件
        self.web_view = QWebEngineView()
        self.web_view.load(QUrl("file:///static/html/variety_price.html"))
        self.web_view.page().profile().downloadRequested.connect(
            self.download_requested)  # 页面下载请求(导出excel)
        self.show_splitter.addWidget(self.web_view)
        self.web_view.hide()  # 隐藏,刚开始不可见
        """js交互通道"""
        web_channel = QWebChannel(self.web_view.page())
        self.web_view.page().setWebChannel(web_channel)  # 网页设置信息通道
        web_channel.registerObject("season_table", self.tools)  # 注册信号对象
        web_channel.registerObject("export_table", self)  # 导出表格数据信号对象
        self.season_table_file = None  # 季节表的保存路径
        self.setLayout(self.vertical_layout)

    def fill_init_data(self):
        """填充交易所"""
        self.exchange_lib.clear()
        for lib in RESEARCH_LIB:
            self.exchange_lib.addItem(lib)
        # 获取当前交易所的品种并填充
        self.exchange_lib_selected()

    def exchange_lib_selected(self):
        """交易所选择"""
        if not self.exchange_lib_thread_over:
            QMessageBox.information(self, "错误", "您的手速太快啦...", QMessageBox.Ok)
            return
        self.confirm_button.setEnabled(False)
        lib = self.exchange_lib.currentText()
        self.variety_lib.clear()
        if lib == "中国金融期货交易所":
            key = 'cffex'
            self.db_worker = self.cffex_getter
            self.products = CFFEX_PRODUCT_NAMES
        elif lib == "上海期货交易所":
            key = 'shfe'
            self.db_worker = self.shfe_getter
            self.products = SHFE_PRODUCT_NAMES
        elif lib == "大连商品交易所":
            key = 'dce'
            self.db_worker = self.dce_getter
            self.products = DCE_PRODUCT_NAMES
        elif lib == "郑州商品交易所":
            key = 'czce'
            self.db_worker = self.czce_getter
            self.products = CZCE_PRODUCT_NAMES
        else:
            self.db_worker = None
            self.products = None
            QMessageBox.information(self, '错误', "没有此项交易所..", QMessageBox.Ok)
            return
        for variety in GOODS_LIB.get(key):
            self.variety_lib.addItem(variety)

        # 关闭交易所选择
        self.exchange_lib_thread_over = False
        # 品种选择
        self.variety_lib_selected()

    def get_variety_en(self, variety):
        """获取相应的品种英文代号"""
        # 获取品种英文名称
        if not self.products:
            # print("没有品种库:", self.products)
            QMessageBox.warning(self, "错误", "内部发生未知错误")
            return ''
        return self.products.get(variety)

    def variety_lib_selected(self):
        """
        选择品种所调用的方法,线程执行:
        查询当前品种上市的日期
        """
        # 设置确认按钮不可用
        self.confirm_button.setEnabled(False)
        if not self.selected_variety_thread_over:
            QMessageBox.warning(self, "错误", "您手速太快啦...", QMessageBox.Ok)
            return
        # 状态显示
        variety = self.variety_lib.currentText()
        self.message_signal.emit("正在查询" + variety + "的数据时间区间...")
        en_variety = self.get_variety_en(variety)
        self.selected_variety_thread_over = False  # 设置品种选择关闭
        if self.db_worker:
            self.variety_selected_thread = VarietySelectedThread(
                db_worker=self.db_worker, variety=en_variety)
            self.variety_selected_thread.result_signal.connect(
                self.change_time_interval)
            self.variety_selected_thread.start()

    def change_time_interval(self, data):
        """根据品种选择线程的信号改变当前时间显示区间"""
        current_date = datetime.datetime.today()
        min_date = datetime.datetime.strptime(data[0], "%Y%m%d")
        max_date = datetime.datetime.strptime(data[1], "%Y%m%d")
        # 计算天数间隔
        big_time_interval = -(current_date - min_date).days  # 要往前取数,调整为负值
        small_time_interval = -(current_date - max_date).days
        # 设置时间
        self.begin_time.setDate(QDate.currentDate().addDays(big_time_interval))
        self.end_time.setDate(QDate.currentDate().addDays(small_time_interval))
        self.confirm_button.setEnabled(True)  # 设置提交按钮为可用
        # 设置完时间就所有锁打开
        self.exchange_lib_thread_over = True
        self.selected_variety_thread_over = True
        # 状态显示时间区间查询完毕
        self.message_signal.emit("时间区间查询完毕!")

    def clear_map_table(self):
        self.map_widget.delete()

    def confirm(self):
        """确认按钮点击"""
        # 开启定时器
        self.timer.start(1000)
        # 改变确认按钮的状态
        self.confirm_button.setText("提交成功")
        self.confirm_button.setEnabled(False)
        # 清除原图表并设置样式
        self.map_widget.delete()
        self.table_widget.clear()
        self.table_widget.set_style(
            header_labels=['日期', '价格', '成交量合计', '持仓量合计'])

        # 根据时间段取得时间生成器类,查询相关数据,计算结果,返回时间列表及对应的价格列表
        lib = self.exchange_lib.currentText()
        variety = self.variety_lib.currentText()
        variety_en = self.get_variety_en(variety)
        begin_time = re.sub('-', '', str(self.begin_time.date().toPyDate()))
        end_time = re.sub('-', '', str(self.end_time.date().toPyDate()))
        print("确认提交:\n当前交易所:{}\n当前品种:{},英文{}\n起始时间:{}\n终止时间:{}\n".format(
            lib, variety, variety_en, begin_time, end_time))
        # 转成可计算的datetime.datetime时间对象
        begin_time_datetime_cls = datetime.datetime.strptime(
            begin_time, "%Y%m%d")
        end_time_datetime_cls = datetime.datetime.strptime(end_time, "%Y%m%d")
        # 起止时间应早于终止时间
        if begin_time_datetime_cls >= end_time_datetime_cls:
            QMessageBox.warning(self, "错误", "起止时间应早于终止时间", QMessageBox.Ok)
            self.message_signal.emit("时间选择有误!")
            self.timer.stop()
            self.cost_time = 0
            # 设置确认按钮可用
            self.confirm_button.setText("确定")
            self.confirm_button.setEnabled(True)
            return
        # 生成时间器对象
        iterator_cls = GenerateTime(begin=begin_time_datetime_cls,
                                    end=end_time_datetime_cls)
        print("执行线程")
        if self.db_worker:
            # 线程执行查询目标数据
            self.confirm_thread = ConfirmQueryThread(db_worker=self.db_worker,
                                                     iterator=iterator_cls,
                                                     variety=variety_en,
                                                     lib=lib)
            self.confirm_thread.result_signal.connect(self.draw_map_table)
            self.confirm_thread.process_signal.connect(self.show_process)
            self.confirm_thread.start()

    def show_process(self, data):
        self.process_signal.emit(data)

    def draw_map_table(self, data):
        """数据展示"""
        print("结果", data)
        # 设置样式
        self.map_widget.set_style()
        # 画图
        x_data = []
        y_data = []
        tuple_data_list = data.get("data")
        message = data.get("message")
        for item in tuple_data_list:
            x_data.append(item[0])
            y_data.append(item[1])
        self.map_widget.axes.set_title(message)
        self.map_widget.map(x_data=x_data, y_data=y_data)
        # 表格数据填充
        self.table_widget.table(data=tuple_data_list)
        self.message_signal.emit("处理完毕,生成图表成功!")
        self.timer.stop()
        self.cost_time = 0
        self.confirm_button.setText("确定")
        self.confirm_button.setEnabled(True)

    def season_table(self):
        """处理展示季节图表"""
        # 菜单可用状态改变
        main_window = self.parent().parent()
        main_window.export_table.setEnabled(True)
        # 获取表格的行数和列数 col-列,row-行
        # col_count = self.table_widget.columnCount()
        row_count = self.table_widget.rowCount()
        # if not row_count:
        #     return
        # 隐藏与可见的处理
        self.confirm_button.setEnabled(False)
        self.map_widget.hide()
        self.table_widget.hide()
        self.web_view.show()
        self.tool_view_all.setEnabled(True)
        # 获取数据,处理数据,将结果数据传入页面展示
        # print("列数", col_count)
        # print("行数", row_count)
        # 遍历获取数据
        data = OrderedDict()
        for row in range(row_count):
            date = self.table_widget.item(row_count - 1, 0).text()
            # date = date[:4] + "/" + date[4:6] + "/" + date[6:]
            price = self.table_widget.item(row_count - 1, 1).text()
            if date[:4] not in data.keys():
                data[date[:4]] = []
            data[date[:4]].append([date, price])
            # for col in range(col_count):
            #     print(self.table_widget.item(row_count-1, col).text(), ' ', end='')
            row_count -= 1
        # 数据处理
        finally_data = self.data_handler(data)
        # print(finally_data)
        self.tools.tool_click_signal.emit(finally_data)  # 数据传到页面

    def return_view_all(self):
        # 加入自定义控件
        self.confirm_button.setEnabled(True)
        self.web_view.hide()
        self.map_widget.show()
        self.table_widget.show()
        self.tool_view_all.setEnabled(False)
        # 菜单可用状态改变
        main_window = self.parent().parent()
        main_window.export_table.setEnabled(False)

    @staticmethod
    def generate_axis_x():
        """生成横坐标数据, 以闰年计"""
        start_day = datetime.datetime.strptime("20160101", "%Y%m%d")
        end_day = datetime.datetime.strptime("20161231", "%Y%m%d")
        axis_x = []
        for date in GenerateTime(begin=start_day, end=end_day).generate_time():
            axis_x.append(date[4:])
        return axis_x

    def data_handler(self, data):
        """
        页面展示图表的数据处理
        :param data:
        :return: json Data
        """
        axis_x = self.generate_axis_x(
        )  # 生成横坐标,整理用于作折线的原始数据,结果的结构{year:[[date, value], [date, value],...]}
        month_data = OrderedDict()  # 创建一个字典存放数据
        map_data = OrderedDict()  # 存用于作图的数据
        # 将数据以月份为单位分开,结果的结构 {year:{month:[up_down, shock]}}
        for year in data:  # 年为单位的数据
            month_data[year] = {}
            map_data[year] = []
            for year_item in data[year]:  # 每年的各个数据
                for x in axis_x:
                    if x == year_item[0][4:]:
                        map_data[year].append([x,
                                               year_item[1]])  # 放入当天的数据用于作图的
                # 根据时间将数据重新整理
                month = year_item[0][4:6]
                if month not in month_data[year].keys():
                    month_data[year][month] = []
                month_data[year][month].append(
                    year_item
                )  # month_data = json.dumps(month_data)  # {year:{month:[[date, price], ...]}}
        new_month_data = OrderedDict()
        last_price = None
        for y in month_data:  # {year:{month:[[date, price], ...]}}
            if y not in new_month_data:
                new_month_data[y] = OrderedDict()
            for m in [
                    '01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
                    '11', '12'
            ]:
                one_month_data = month_data[y].get(m)
                if one_month_data:
                    last = int(one_month_data[-1][1])
                    # 计算涨跌
                    up_down = None
                    if last_price:
                        up_down = "%.4f" % ((last - last_price) /
                                            last_price) if last_price else "-"
                        up_down = "%.2f" % (float(up_down) *
                                            100) if last_price else "-"
                    last_price = last
                    # 计算波幅
                    data_set = []
                    for item in one_month_data:
                        data_set.append(int(item[1]))
                    min_price = min(data_set)
                    max_price = max(data_set)

                    shock = "%.4f" % ((max_price - min_price) /
                                      min_price) if min_price else "-"  # 波幅
                    shock = "%.2f" % (float(shock) * 100) if min_price else "-"
                    new_month_data[y][m] = []
                    new_month_data[y][m].append(up_down)
                    new_month_data[y][m].append(shock)
                else:
                    last_price = None

        # title的处理
        title = ""
        if self.name == "variety_price":
            title = self.exchange_lib.currentText(
            ) + self.variety_lib.currentText() + "品种权重指数"
        if self.name == "main_contract":
            title = self.exchange_lib.currentText(
            ) + self.variety_lib.currentText() + "主力合约指数"
        # 整理数据
        finally_data = dict()
        finally_data["raw"] = data
        finally_data["result"] = new_month_data
        finally_data["mapData"] = map_data
        finally_data["title"] = title
        return json.dumps(finally_data)

    def download_requested(self, download_item):
        # 保存位置选择,默认桌面
        if not download_item.isFinished() and download_item.state() == 0:
            cur_window = self.parent().parent().window_stack.currentWidget()
            if cur_window.name == "variety_price":
                title = "品种权重指数季节表"
            elif cur_window.name == "main_contract":
                title = "主力合约指数季节表"
            else:
                return
            desktop_path = get_desktop_path()
            save_path = QFileDialog.getExistingDirectory(
                self, "选择保存的位置", desktop_path)
            if not save_path:
                return
            cur_time = datetime.datetime.strftime(datetime.datetime.now(),
                                                  "%Y%m%d")
            excel_name = cur_window.exchange_lib.currentText(
            ) + cur_window.variety_lib.currentText() + title + cur_time
            file_path = save_path + "/" + excel_name + ".xls"
            download_item.setPath(file_path)
            download_item.accept()
            self.season_table_file = file_path
            download_item.finished.connect(self.download_finished)

    def download_finished(self):
        try:
            if self.season_table_file:
                open_dialog = QMessageBox.question(
                    self, "成功", "导出保存成功!\n是否现在打开?",
                    QMessageBox.Yes | QMessageBox.No)
                if open_dialog == QMessageBox.Yes:
                    open_excel(
                        self.season_table_file)  # 调用Microsoft Excel 打开文件
                self.season_table_file = None
        except Exception as e:
            pass