Exemple #1
0
    def __init__(self, parentWidget):
        QWidget.__init__(self, parentWidget)

        self.formatManager = FormatManager()
        self.formatManager.loadFormats()

        self.editView = StylableTextEdit(self, self.formatManager)
        self.editView.navigate.connect(self.navigate)
        self.editView.objectSelectionChanged.connect(self.objectSelectionChanged)

        toolbar = QWidget(self)
        layout = QHBoxLayout()
        layout.setContentsMargins(0,0,0,0)
        toolbar.setLayout(layout)

        self.actionsSelector = ActionSelector(self)
        layout.addWidget(self.actionsSelector)

        self.textFormatSelector = TextStyleSelector(self)
        self.textFormatSelector.styleChanged.connect(self.editView.applyTextFormat)
        self.editView.updateCharFormat.connect(self.textFormatSelector.setCurrentStyle)
        layout.addWidget(self.textFormatSelector)

        self.styleSelector = BlockStyleSelector(self)
        self.styleSelector.styleChanged.connect(self.editView.applyBlockStyle)
        self.styleSelector.indentLess.connect(self.editView.indentLess)
        self.styleSelector.indentMore.connect(self.editView.indentMore)
        self.styleSelector.insertTable.connect(self.insertTable)
        self.editView.updateBlockFormat.connect(self.styleSelector.setCurrentStyle)
        layout.addWidget(self.styleSelector)

        searchMarker = self.formatManager.getFormat( ('searchMarker', None, None) )
        self.findWidget = FindWidget(self, searchMarker.getCharFormat(), self.editView)
        self.findWidget.hide()

        self.editMathWidget = MathEditWidget(self)
        self.editMathWidget.apply.connect(self.applyMathFormula)
        self.editMathWidget.hide()

        #horizontalSpacer = QSpacerItem(0, 0) # 40, 20) # , QSizePolicy.Expanding, QSizePolicy.Minimum)
        #layout.addItem(horizontalSpacer)

        hLayout = QVBoxLayout(self)
        hLayout.setContentsMargins(0, 0, 0, 0)
        hLayout.addWidget(toolbar)
        hLayout.addWidget(self.findWidget)
        hLayout.addWidget(self.editView)
        hLayout.addWidget(self.editMathWidget)

        # The toolbar should take the minimum space and the edit view the remaining space
        hLayout.setStretch(0, 0)
        hLayout.setStretch(1, 0)
        hLayout.setStretch(2, 1)
        hLayout.setStretch(3, 0.1)
    def __init__(self):
        super().__init__()

        # Data storage
        self.driverMap = {}
        self.gunnerMap = {}
        self.dProfileMapXbox = [{}]
        self.dProfileMapJoystick = [{}]
        self.gProfileMapXbox = [{}]
        self.gProfileMapJoystick = [{}]

        # Init interface
        mainLayout = QHBoxLayout()
        leftHalf = QGroupBox('Controller Info')
        rightHalf = QGroupBox('Assigned Maps')

        vertLeft = QVBoxLayout()
        vertLeft.setStretch(0, 0)
        vertLeft.setSpacing(2)
        vertLeft.addWidget(QLabel('Profile Name'))
        self.profileName = QLineEdit()
        self.profileName.textEdited.connect(self.update_submit)

        vertLeft.addWidget(self.profileName)

        typeChoosers = QHBoxLayout()
        self.pilot = QComboBox()
        self.pilot.addItems(['Driver', 'Gunner'])
        typeChoosers.addWidget(self.pilot)
        self.controller = QComboBox()
        self.controller.addItems(['Xbox Compatible', 'Joystick'])
        typeChoosers.addWidget(self.controller)
        vertLeft.addLayout(typeChoosers)

        keyConfig = QHBoxLayout()
        keys = QVBoxLayout()
        keys.addWidget(QLabel('Key'))
        self.key = QLineEdit()
        self.key.textEdited.connect(self.update_submit)
        keys.addWidget(self.key)
        ports = QVBoxLayout()
        ports.addWidget(QLabel('Port'))
        self.port = QSpinBox()
        self.port.setFixedWidth(110)
        ports.addWidget(self.port)
        keyConfig.addLayout(keys)
        keyConfig.addLayout(ports)
        vertLeft.addLayout(keyConfig)
        vertLeft.addStretch()

        importJSON = QPushButton()
        importJSON.setText('Import from JSON')
        importJSON.clicked.connect(self.import_json)
        self.submit = QPushButton()
        self.submit.setText('Add Entry to List')
        self.submit.clicked.connect(self.process_data)
        self.submit.setEnabled(False)
        vertLeft.addWidget(self.submit)
        vertLeft.addWidget(importJSON)

        leftHalf.setLayout(vertLeft)
        mainLayout.addWidget(leftHalf)
        self.profileList = QTableWidget(0, 2)

        rightVert = QVBoxLayout()
        rightVert.setSpacing(2)
        self.profiles = QComboBox()
        self.profiles.addItems(self.get_profile_names('driver'))
        self.profiles.currentTextChanged.connect(self.update_list)
        self.profiles.setEnabled(False)
        listSelectors = QHBoxLayout()
        listSelectors.addWidget(self.profiles)
        self.pilotSource = QComboBox()
        self.pilotSource.addItems(['Driver', 'Gunner'])
        self.pilotSource.currentTextChanged.connect(self.update_profiles)
        self.controllerSource = QComboBox()
        self.controllerSource.addItems(['Xbox Compatible', 'Joystick'])
        self.controllerSource.currentTextChanged.connect(self.update_list)
        rightVert.addWidget(self.pilotSource)
        listSelectors.addWidget(self.controllerSource)

        rightVert.addLayout(listSelectors)

        # Table
        self.reset_table()
        rightVert.addWidget(self.profileList)
        rightVert.addStretch()

        listControls = QHBoxLayout()
        self.removeItem = QPushButton('Remove Entry')
        self.removeItem.setDisabled(True)
        self.removeItem.clicked.connect(self.remove_list_item)
        listControls.addWidget(self.removeItem)
        self.removeProfile = QPushButton('Remove Profile')
        self.removeProfile.setDisabled(True)
        self.removeProfile.clicked.connect(self.remove_profile)

        listControls.addWidget(self.removeProfile)
        self.export = QPushButton("Export to JSON")
        self.export.clicked.connect(self.export_json)
        self.export.setEnabled(True)
        rightVert.addLayout(listControls)
        rightVert.addWidget(self.export)

        rightHalf.setLayout(rightVert)
        mainLayout.addWidget(rightHalf)

        self.init_gui(mainLayout)
Exemple #3
0
class ObjectFactory(QWidget):
    """Enables creation of new type instances."""
    def __init__(self, *args):
        """Constructor."""
        super().__init__(*args)

        # Cache.
        self.types = TypeCacheModel()
        self.init_types()

        # Set size and position.
        screen = QtWidgets.QDesktopWidget().screenGeometry(0)
        self.resize(int(screen.width() * 0.7), int(screen.height() * 0.7))
        self.move(int(screen.width() * 0.15), int(screen.height() * 0.15))

        # Set window type.
        flags = QtCore.Qt.WindowFlags(QtCore.Qt.WindowStaysOnTopHint
                                      | QtCore.Qt.FramelessWindowHint)
        self.setWindowFlags(flags)

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(50, 50, 50, 50)

        # Pinned types.
        self.hotbar = QToolBar()
        self.hotbar.setStyleSheet("QToolBar { }")
        for index in range(self.types.pinned_count()):
            t = self.types.pinned_type(index)
            url = urlparse(t.icon)
            icon = QIcon(url.path)
            action = QAction(icon, t.name, qApp)
            self.hotbar.addAction(action)
        self.layout.addWidget(self.hotbar)

        # Search bar.
        self.omnibox = QHBoxLayout()
        self.omnibox.setContentsMargins(20, 20, 20, 20)
        self.omnitext = QLineEdit()
        self.omnitext.setStyleSheet(
            "QLineEdit { font-size: 20px; padding: 12px; border: none; border-radius: 10px; }"
        )
        self.omnitext.setFrame(False)  # Doesn't seem to do anything'
        self.omnitext.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False)
        self.omnitext.setPlaceholderText("Search ...")
        self.omnitext.setClearButtonEnabled(True)
        self.omnitext.setTextMargins(20, 20, 20, 20)
        self.omnibox.addWidget(self.omnitext)
        self.layout.addLayout(self.omnibox)

        # Unfiltered types, MRU order (?)
        self.object_table = QVBoxLayout()
        self.object_table.setContentsMargins(20, 20, 20, 20)
        row1 = QLabel("line")
        self.object_table.addWidget(row1)
        self.layout.addLayout(self.object_table)
        self.layout.setStretch(2, 100)

        self.setLayout(self.layout)
        self.hide()
        return

    def init_types(self):
        """Initialize types collection."""

        # List of known types, with index by name, by last use, and by
        # keyword from their description.  Each type has a name, icon, and
        # a description.
        #
        # There's also an ordered list of "pinned" types.

        text = Type()
        text.name = "Text"
        text.description = "Unformatted Unicode document"
        text.impl = "file:///Users/d/work/personal/darqos/darq/types/text.py"
        text.icon = "file:///Users/d/work/personal/darqos/darq/icons/txt.png"
        self.types.add_type(text)
        self.types.append_pinned_type("Text")

        book = Type()
        book.name = "Book Details"
        book.description = "Catalog data for a book"
        book.impl = ""
        book.icon = "file:///Users/d/work/personal/darqos/darq/icons/book.png"
        self.types.add_type(book)
        self.types.append_pinned_type("Book Details")
        return

    def on_create(self):
        o = TextTypeView()
        self.hide()
        return
Exemple #4
0
class YouDao(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def iconActivated(self, reason):
        # reason 没有 QSystemTrayIcon.DoubleClick
        if self.isHidden():
            self.show()
        else:
            self.hide()

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

    def open(self):
        self.show()

    def clearTextClicked(self):
        self.textEdit.clear()
        self.preview.clear()

    def keyPressEvent(self, event):

        if event.key() == Qt.Key_Return:
            self.confirmClicked()
        else:
            super(YouDao, self).keyPressEvent(event)

    def confirmClicked(self):
        q = self.textEdit.toPlainText()
        # 要翻译的内容为空
        if not q.strip():
            alert = QMessageBox(self)
            alert.setText("你什么也没有输入!!!")
            alert.exec()
            return
        data = translate(q)
        # 没有数据就用本地词典
        if not data:
            key, value = localtran(q)
            if key and value:
                self.preview.setHtml('<i>翻译:</i>{}'.format(value))
            else:
                alert = QMessageBox(self)
                alert.setText("出错了")
                alert.exec()
            return

        usPhonetic = ''
        ukPhonetic = ''
        translation = ''
        web = ''

        html = '''
                   <html>
                        <head></head>
                        <body>
                            <p>{translation}</p>
                            {uk-phonetic}
                            {us-phonetic}
                            {web}
                        </body>
                   </html>
               '''
        if data.get('translation'):
            translation = '<i>翻译:</i>' + \
                ''.join(data.get('translation')) + '<br>'

        if data.get('basic'):
            translation += '<br>'.join(data.get('basic').get('explains'))
            if data.get('basic').get('us-phonetic'):
                usPhonetic = '<h6>英音:<span>[{}]</span></h6>'.format(
                    data.get('basic').get('us-phonetic'))
            if data.get('basic').get('uk-phonetic'):
                ukPhonetic = '<h6>美音:<span>[{}]</span></h6>'.format(
                    data.get('basic').get('uk-phonetic'))

        if data.get('web'):
            web = '网络释义:' + '<br>'.join(','.join(value.get('value'))
                                        for value in data.get('web'))

        values = {
            'translation': translation,
            'us-phonetic': usPhonetic,
            'uk-phonetic': ukPhonetic,
            'web': web
        }

        self.preview.setHtml(html.format(**values))

    def initUI(self):
        # 系统托盘
        self.trayIcon = QSystemTrayIcon(self)
        self.trayIcon.setIcon(QIcon(os.path.join(baseDir, "youdao.png")))

        self.openAction = QAction(QIcon(os.path.join(baseDir, "search.png")),
                                  "查单词", self)
        self.openAction.triggered.connect(self.open)
        self.settingAction = QAction(
            QIcon(os.path.join(baseDir, "setting.png")), "设置", self)
        self.quitAction = QAction("退出", self)
        self.quitAction.triggered.connect(QCoreApplication.quit)
        self.qMenu = QMenu(self)
        self.qMenu.addAction(self.openAction)
        self.qMenu.addAction(self.settingAction)
        self.qMenu.addSeparator()
        self.qMenu.addAction(self.quitAction)

        self.trayIcon.setContextMenu(self.qMenu)
        self.trayIcon.activated[QSystemTrayIcon.ActivationReason].connect(
            self.iconActivated)

        self.centralWidget = QWidget(self)

        self.header = QWidget(self)
        self.textEdit = QPlainTextEdit(self.header)
        self.textEdit.setPlaceholderText('请输入')
        self.textEdit.setStyleSheet(
            "QWidget{font-size: 18px;background: #f2f2f2}")

        def enterKeyPressEvent(event):

            if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
                self.confirmClicked()
            else:
                QPlainTextEdit.keyPressEvent(self.textEdit, event)

        # 重写QPlainTextEdit的enter事件,enter确认
        self.textEdit.keyPressEvent = enterKeyPressEvent

        self.clearText = QPushButton("清除")
        self.clearText.setStyleSheet("QPushButton{background: #ffffff;}")
        self.clearText.clicked.connect(self.clearTextClicked)
        self.confirm = QPushButton("翻译")
        self.confirm.clicked.connect(self.confirmClicked)
        self.confirm.setStyleSheet(
            "QPushButton{background: #e02433;color: #ffffff}")

        grid = QGridLayout()
        grid.setSpacing(5)
        grid.setContentsMargins(0, 0, 0, 0)
        # 控件, 第几行,第几列,占几行,占几列
        grid.addWidget(self.textEdit, 0, 0, 1, 2)
        grid.addWidget(self.clearText, 1, 0, 1, 1)
        grid.addWidget(self.confirm, 1, 1, 1, 1)
        self.header.setLayout(grid)

        self.preview = QTextEdit()
        self.preview.setReadOnly(True)
        self.preview.setPlaceholderText('这里什么都没有。。。')

        self.hbox = QVBoxLayout(self.centralWidget)
        self.hbox.setContentsMargins(6, 6, 6, 6)

        self.hbox.addWidget(self.header)
        self.hbox.addWidget(self.preview)

        self.hbox.setStretch(0, 1)
        self.hbox.setStretch(1, 2)

        self.setCentralWidget(self.centralWidget)
        self.setWindowTitle('有道词典')
        self.setWindowIcon(QIcon(os.path.join(baseDir, 'youdao.png')))

        self.setFixedSize(350, 400)
        self.center()
        # self.setFocusPolicy(Qt.StrongFocus)
        self.show()
        self.trayIcon.show()

    def center(self):
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)
Exemple #5
0
    def __init__(self):
        QWidget.__init__(self)
        self.resize(1080, 720)

        #上方布局
        #left(up_l)
        up_l = QVBoxLayout()
        self.btn_local = QPushButton("从文件打开")
        self.btn_db = QPushButton("从数据库打开")
        up_l.addWidget(self.btn_local)
        up_l.addWidget(self.btn_db)
        #middle
        self.progress = Progress()
        #right
        self.btn_run = QPushButton("运行")
        self.btn_run.clicked.connect(self.run)
        self.btn_clear = QPushButton("Clear")
        self.btn_clear.clicked.connect(self.on_btn_clear_clicked)
        self.btn_exit = QPushButton("退出")
        self.btn_exit.clicked.connect(QCoreApplication.quit)
        self.btn_local.clicked.connect(self.data_local)

        #下方布局
        #left(down_l)
        down_l = QVBoxLayout()
        self.label_in = QLabel("输入数据")
        self.label_in.setAlignment(Qt.AlignCenter)
        self.label_in.setContentsMargins(5, 5, 5, 0)
        self.list_in = List()
        self.label_out = QLabel("输出数据")
        self.label_out.setAlignment(Qt.AlignCenter)  #居中对齐
        self.list_out = List()
        self.list_in.update_.connect(self.on_listItem_click)
        self.list_out.update_.connect(self.on_listOutItem_click)
        down_l.addWidget(self.label_in)
        down_l.addWidget(self.list_in)
        down_l.addWidget(self.label_out)
        down_l.addWidget(self.list_out)
        down_l.setStretch(0, 1)
        down_l.setStretch(1, 7)
        down_l.setStretch(2, 1)
        down_l.setStretch(3, 7)
        down_l.setSpacing(0)
        #middle(tabs)
        self.tabs = Tabs()
        #right
        self.oprea = OperateList()
        self.oprea.clickBtn_.connect(self.operateChoose)

        #设置UI上下方布局为水平布局
        #up
        layout_up = QHBoxLayout()
        layout_up.addLayout(up_l)
        layout_up.addWidget(self.progress)
        layout_up.addWidget(self.btn_run)
        # layout_up.addWidget(self.btn_clear)
        layout_up.addWidget(self.btn_exit)
        layout_up.setStretch(0, 2)
        layout_up.setStretch(1, 8)
        layout_up.setStretch(2, 1)
        layout_up.setStretch(3, 1)
        layout_up.setStretch(4, 1)
        #down
        layout_down = QHBoxLayout()
        # layout_down.addWidget(text_test_down)
        layout_down.addLayout(down_l)
        layout_down.addWidget(self.tabs)
        layout_down.addWidget(self.oprea)
        layout_down.setStretch(0, 1)
        layout_down.setStretch(1, 3)
        layout_down.setStretch(2, 1)

        #设置UI总体布局
        layout_main = QVBoxLayout()
        layout_main.addLayout(layout_up)
        layout_main.addLayout(layout_down)
        layout_main.setStretch(0, 1)
        layout_main.setStretch(1, 10)

        self.setLayout(layout_main)
Exemple #6
0
    def initUI(self):
        self.funList = open("scripts/funlist.txt", "r").read().split("\n")
        if self.funList[-1] == '':
            self.funList = self.funList[:-1]

        self.setWindowTitle("Robots' Search")
        self.setGeometry(500, 500, 500, 500)
        self.setWindowIcon(QIcon('robot_reader/utils/robot.png'))

        self.infoLabel = QLabel('here we provide some tips like flag usage ')

        self.searchButton = QPushButton('search')
        self.searchButton.setToolTip('click to run your search')
        self.searchButton.clicked.connect(self.search)

        # self.sgdclfiButton = QRadioButton("Klasyfikator SGD")
        # self.sgdclfiButton.setChecked(True)
        # self.sgdclfiButton.setToolTip("kosinus kąta pomiędzy dwoma wektorami reprezentującymi dokumentów")

        # self.distcosButton = QRadioButton("Dystans Kosinusowy")
        # self.distcosButton.setChecked(True)
        # self.distcosButton.setToolTip("klasyfikator liniowy wykorzystujący Stochastic Gradient Descent")

        self.bow = QRadioButton("Bag of Words")
        self.bow.setChecked(True)
        self.bow.setToolTip("dokumenty reprezentowane jako 'bag of words'")

        self.queryTextEdit = QTextEdit()
        self.queryTextEdit.setToolTip('type in your query')
        self.queryTextEdit.setMaximumHeight(25)
        vbox2 = QVBoxLayout()
        vbox2.addWidget(self.queryTextEdit)
        vbox2.setStretch(1, 0)

        self.recordNumber = QSpinBox()
        self.recordNumber.setMinimum(10)
        self.recordNumber.setMaximum(90)
        vbox2.addWidget(self.recordNumber)

        vbox = QVBoxLayout()
        #vbox.addWidget(self.infoLabel, alignment=QtCore.Qt.AlignLeft)
        vbox.addLayout(vbox2)

        hbox2 = QHBoxLayout()
        # hbox2.addWidget(self.sgdclfiButton)
        # hbox2.addWidget(self.distcosButton)
        hbox2.addWidget(self.bow)
        hbox2.addWidget(self.searchButton)
        vbox.addLayout(hbox2)

        # self.loading = QLabel()
        # vbox.addWidget(self.loading, alignment=QtCore.Qt.AlignCenter)

        hbox = QHBoxLayout()
        self.resultList = QListWidget()
        self.resultList.currentItemChanged.connect(self.setFileContent)
        hbox.addWidget(self.resultList)
        self.fileContent = QLabel()
        self.fileContent.setTextFormat(Qt.RichText)
        self.fileContent.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.contentScroll = QScrollArea()
        self.contentScroll.setWidgetResizable(True)
        self.contentScroll.setWidget(self.fileContent)
        hbox.addWidget(self.contentScroll)
        vbox.addLayout(hbox)

        self.setLayout(vbox)
        self.show()
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self._plot_ref = None
        self.closed_loop_ref = None
        self.bode_plot_ref = None
        self.state_plot_refs = []
        self.pz_plot_refs = []
        self.file_name = None
        self.is_system_identified = False
        self.axis = 0
        self.dt = 0.005
        self.rise_time = 0.13
        self.damping_index = 0.0
        self.detune_coeff = 0.5
        self.kc = 0.0
        self.ki = 0.0
        self.kd = 0.0
        self.figure = plt.figure(1)
        self.figure.subplots_adjust(hspace=0.5, wspace=1.0)
        self.num = []
        self.den = []
        self.sys_id_delays = 1
        self.sys_id_n_zeros = 2
        self.sys_id_n_poles = 2

        # this is the Canvas Widget that displays the `figure`
        # it takes the `figure` instance as a parameter to __init__
        self.canvas = FigureCanvas(self.figure)

        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.toolbar = NavigationToolbar(self.canvas, self)

        self.btn_open_log = QPushButton("Open log")
        self.btn_open_log.clicked.connect(self.loadLog)

        # set the layout
        layout_v = QVBoxLayout()
        layout_h = QHBoxLayout()
        left_menu = QVBoxLayout()
        left_menu.addWidget(self.btn_open_log)

        xyz_group = QHBoxLayout()
        r_x = QRadioButton("x")
        r_x.setChecked(True)
        r_y = QRadioButton("y")
        r_z = QRadioButton("z")
        xyz_group.addWidget(QLabel("Axis"))
        xyz_group.addWidget(r_x)
        xyz_group.addWidget(r_y)
        xyz_group.addWidget(r_z)
        r_x.clicked.connect(self.loadXData)
        r_y.clicked.connect(self.loadYData)
        r_z.clicked.connect(self.loadZData)

        left_menu.addLayout(xyz_group)

        pz_group = QFormLayout()
        self.line_edit_zeros = QSpinBox()
        self.line_edit_zeros.setValue(self.sys_id_n_zeros)
        self.line_edit_zeros.setRange(0, 6)
        self.line_edit_zeros.valueChanged.connect(self.onZerosChanged)
        pz_group.addRow(QLabel("Zeros"), self.line_edit_zeros)
        self.line_edit_poles = QSpinBox()
        self.line_edit_poles.setValue(self.sys_id_n_poles)
        self.line_edit_poles.setRange(0, 6)
        self.line_edit_poles.valueChanged.connect(self.onPolesChanged)
        pz_group.addRow(QLabel("Poles"), self.line_edit_poles)
        self.line_edit_delays = QSpinBox()
        self.line_edit_delays.setValue(self.sys_id_delays)
        self.line_edit_delays.setRange(1, 1000)
        self.line_edit_delays.valueChanged.connect(self.onDelaysChanged)
        pz_group.addRow(QLabel("Delays"), self.line_edit_delays)
        self.btn_run_sys_id = QPushButton("Run identification")
        self.btn_run_sys_id.clicked.connect(self.onSysIdClicked)
        self.btn_run_sys_id.setEnabled(False)
        pz_group.addRow(self.btn_run_sys_id)
        left_menu.addLayout(pz_group)

        layout_tf = self.createTfLayout()
        left_menu.addLayout(layout_tf)

        offset_group = QFormLayout()
        self.line_edit_offset = QDoubleSpinBox()
        self.line_edit_offset.setValue(0.0)
        self.line_edit_offset.setRange(-10.0, 10.0)
        self.line_edit_offset.textChanged.connect(self.onOffsetChanged)
        offset_group.addRow(QLabel("Offset"), self.line_edit_offset)
        left_menu.addLayout(offset_group)
        left_menu.addStretch(1)

        layout_gmvc = self.createGmvcLayout()
        layout_pid = self.createPidLayout()
        layout_controller = QHBoxLayout()
        layout_controller.addLayout(layout_gmvc)
        layout_controller.addLayout(layout_pid)

        layout_plot = QVBoxLayout()
        layout_h.addLayout(left_menu)
        layout_h.addLayout(layout_plot)
        layout_h.setStretch(1, 1)
        layout_plot.addWidget(self.toolbar)
        layout_plot.addWidget(self.canvas)
        layout_v.addLayout(layout_h)
        layout_v.setStretch(0, 1)
        layout_v.addLayout(layout_controller)
        self.setLayout(layout_v)
class ImportWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.init_gui()

    def read_sheet(self, file_data, sheet_name):
        self.model.clear()
        for row in file_data[sheet_name]:
            items = [QStandardItem(str(field)) for field in row]
            self.model.appendRow(items)

    def open_filename(self):
        filename = QFileDialog.getOpenFileName(
            self, self.tr("Abrir archivo"), "/home/luciano",
            self.tr("Hojas de Cálculo (*.ods)"))
        if filename[0] != "":
            self._enable_widgets(True)
            self.file_data = get_data(filename[0])
            for key in self.file_data.keys():
                self.cmb_ods_sheets.addItem(key)
            self.read_sheet(self.file_data, list(self.file_data.keys())[0])

    def import_expenses(self):
        try:
            row = int(self.le_initial_row.text()) - 1
            description_col = int(self.le_description_col.text()) - 1
            date_col = int(self.le_date_col.text()) - 1
            default_date = self.default_date.date()
            date_format = self.le_date_format.text()
            percent = 1.0 / len(list(self.current_group.getMembers()))
            while self.model.item(row) is not None:
                print("Row ", row)

                expense = Expense()
                expense.setDescription(
                    self.model.item(row, description_col).text())
                print("Expense: ", expense.getDescription())
                date = QDate.fromString(
                    self.model.item(row, date_col).text(), date_format)
                if not date.isValid():
                    date = default_date
                expense.setDate(date.toString(Qt.ISODate))
                print("Date: ", expense.getDate())

                cost = 0
                users = []
                for member in self.current_group.getMembers():
                    print("Processing member ", member.getFirstName())
                    member_column = int(
                        self.member_widget_map[member.getId()].text()) - 1
                    paid = 0
                    try:
                        paid = float(
                            self.model.item(row, member_column).text())
                        print("Expense: ",
                              self.model.item(row, member_column).text())
                    except:
                        pass
                    cost = cost + paid
                    expense_user = ExpenseUser()
                    expense_user.setId(member.getId())
                    expense_user.setPaidShare(str(paid))
                    users.append(expense_user)
                for expense_user in users:
                    expense_user.setOwedShare(str(cost * percent))
                if cost == 0:
                    raise Exception(
                        self.tr('No se ha introducido monto para el gasto'))
                expense.setCost(str(cost))
                expense.setUsers(users)
                expense.setGroupId(self.current_group.id)
                self.sObj.createExpense(expense)
                row = row + 1
                self.le_initial_row.setText(str(row + 1))
        except Exception as inst:
            QMessageBox.critical(
                self, self.tr("Error"),
                self.tr("Se ha producido un error en la fila") + str(row + 1) +
                "\n" + str(inst))
            traceback.print_exc()

    def _enable_widgets(self, state):
        self.le_initial_row.setEnabled(state)
        self.cmb_group.setEnabled(state)
        self.cmb_ods_sheets.setEnabled(state)
        self.le_date_col.setEnabled(state)
        self.default_date.setEnabled(state)
        self.le_description_col.setEnabled(state)
        self.btn_import.setEnabled(state)
        self.le_date_format.setEnabled(state)

    def sheet_changed(self, sheet_name):
        self.read_sheet(self.file_data, sheet_name)

    def current_group_changed(self, idx):
        item = self.vlayout.takeAt(1)
        item.layout().deleteLater()
        item.invalidate()
        item = None
        self.vlayout.invalidate()
        self.group_members_layout = QFormLayout()
        self.current_group = self.cmb_group.itemData(idx)
        column_number = 1
        self.member_widget_map = {}
        for member in self.current_group.getMembers():
            self.member_widget_map[member.getId()] = QLineEdit(
                str(column_number))
            self.group_members_layout.addRow(
                self.tr("Columna " + member.getFirstName()),
                self.member_widget_map[member.getId()])
            column_number = column_number + 1
        self.vlayout.insertLayout(1, self.group_members_layout)

    def init_gui(self):
        self.form_layout = QFormLayout()
        self.cmb_ods_sheets = QComboBox()
        self.le_initial_row = QLineEdit("1")
        self.le_initial_row.setValidator(QIntValidator(1, 99999))
        self.cmb_group = QComboBox()
        self.le_date_col = QLineEdit("1")
        self.le_date_col.setValidator(QIntValidator(1, 999999))
        self.default_date = QDateTimeEdit(QDate.currentDate())
        self.default_date.setMinimumDate(QDate.currentDate().addDays(-365))
        self.default_date.setMaximumDate(QDate.currentDate().addDays(365))
        self.default_date.setDisplayFormat("dd.MM.yyyy")
        self.default_date.setCalendarPopup(True)
        self.le_date_format = QLineEdit("d/M/yyyy")

        self.le_description_col = QLineEdit("2")
        self.le_description_col.setValidator(QIntValidator(1, 9999))
        self.sObj = get_splitwise()
        groups = self.sObj.getGroups()

        self.cmb_ods_sheets.currentTextChanged.connect(self.sheet_changed)
        for group in groups:
            self.cmb_group.addItem(group.getName(), group)
        self.cmb_group.currentIndexChanged.connect(self.current_group_changed)
        self.cmb_group.setCurrentIndex(0)
        btn_open_filename = QPushButton("Open")
        btn_open_filename.clicked.connect(self.open_filename)
        self.form_layout.addRow(self.tr("Archivo"), btn_open_filename)
        self.form_layout.addRow(self.tr("Hoja"), self.cmb_ods_sheets)
        self.form_layout.addRow(self.tr("Grupos"), self.cmb_group)
        self.form_layout.addRow(self.tr("Fila Inicial"), self.le_initial_row)
        self.form_layout.addRow(self.tr("Columna Fecha"), self.le_date_col)
        self.form_layout.addRow(self.tr("Formato de fecha"),
                                self.le_date_format)
        self.form_layout.addRow(self.tr("Fecha por defecto"),
                                self.default_date)
        self.form_layout.addRow(self.tr("Columna Concepto"),
                                self.le_description_col)

        self.group_members_layout = QFormLayout()

        self.btn_import = QPushButton(self.tr("Importar"))
        self.btn_import.clicked.connect(self.import_expenses)

        self.model = QStandardItemModel(self)
        tableView = QTableView(self)
        tableView.setModel(self.model)

        self.vlayout = QVBoxLayout()
        self.vlayout.addLayout(self.form_layout)
        self.vlayout.addLayout(self.group_members_layout)
        self.vlayout.addWidget(self.btn_import)
        self.vlayout.setStretch(1, 1)

        hlayout = QHBoxLayout()
        hlayout.addWidget(tableView)
        hlayout.addLayout(self.vlayout)

        hlayout.setStretch(1, 0)
        hlayout.setStretch(0, 1)
        self.setLayout(hlayout)
        self._enable_widgets(False)
        self.show()
Exemple #9
0
class MeasurementWidget(QWidget):
    """description of class"""
    def __init__(self, **kargs):
        super(MeasurementWidget, self).init__()

        self.layout = QGridLayout()
        self.expand = []
        self.labels = []
        self.datatables = []
        self.initUI()

    def initUI(self):

        self.scroll = QScrollArea()
        #self.scroll.setMaximumHeight(550)
        #self.scroll.setMaximumWidth(750)

        self.a = QWidget()
        self.aLayout = self.grid = QGridLayout()

        self.a.setLayout(self.aLayout)
        self.a.setMinimumHeight(1100)

        #labels
        lbl1 = QLabel('<b style="font-size: 12pt">Measurement Details</b>')
        lbl1.move(0, 0)
        lbl1.resize(250, 30)
        self.layout.addWidget(lbl1, 0, 0, 1, 1)
        #self.aLayout.addWidget(lbl1)

        #---------------------------------------------------------------------------------------------------------

        h_headers = [
            'Parameters', 'Measurement', '000_14-04-14', '000_14-04-14',
            '002_14-04-14', '003_14-04-14'
        ]
        v_headers = ['', '', '', '', '', '', '']
        self.chbx1, self.chbx2, self.chbx3, self.chbx4 = QCheckBox(
        ), QCheckBox(), QCheckBox(), QCheckBox()
        data = [['Use', '', self.chbx1, self.chbx2, self.chbx3, self.chbx4],
                [
                    QLabel('<b>Total Q (m3/s)</b>'),
                    QLabel('<b>2</b>'),
                    QLabel('<b>3</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>')
                ], ['Top Q (m3/s)', '5', '6', '4', '5', '66'],
                ['Middle Q (m3/s)', '2', '3', '3', '5', '6'],
                ['Bottom Q (m3/s)', '4', '4', '3', '2', '1'],
                ['Left Q (m3/s)', '2', '3', '44', '2', '22'],
                ['Right Q (m3/s)', '2', '3', '3', '333', '222']]

        self.datatables.append(
            self.create_table(310, data, h_headers, v_headers))

        func = partial(self.table_toggle, table_idx=0)
        label, collapse_widget = self.createTableCollapse("Discharge", func)
        self.labels.append(label)
        self.expand.append(True)
        self.aLayout.addWidget(collapse_widget)
        self.aLayout.addWidget(self.datatables[0])
        #---------------------------------------------------------------------------------------------------------

        self.chbx1, self.chbx2, self.chbx3, self.chbx4 = QCheckBox(
        ), QCheckBox(), QCheckBox(), QCheckBox()
        data = [['Use', '', self.chbx1, self.chbx2, self.chbx3, self.chbx4],
                [
                    QLabel('<b>Total Q (m3/s)</b>'),
                    QLabel('<b>2</b>'),
                    QLabel('<b>3</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>')
                ], ['Top Q (m3/s)', '5', '6', '4', '5', '66'],
                ['Middle Q (m3/s)', '2', '3', '3', '5', '6'],
                ['Bottom Q (m3/s)', '4', '4', '3', '2', '1'],
                ['Left Q (m3/s)', '2', '3', '44', '2', '22'],
                ['Right Q (m3/s)', '2', '3', '3', '333', '222']]

        self.datatables.append(
            self.create_table(310, data, h_headers, v_headers))

        func = partial(self.table_toggle, table_idx=1)
        label, collapse_widget = self.createTableCollapse("The Sequel", func)
        self.labels.append(label)
        self.expand.append(True)
        self.aLayout.addWidget(collapse_widget)
        self.aLayout.addWidget(self.datatables[1])
        #---------------------------------------------------------------------------------------------------------

        self.chbx1, self.chbx2, self.chbx3, self.chbx4 = QCheckBox(
        ), QCheckBox(), QCheckBox(), QCheckBox()
        data = [['Use', '', self.chbx1, self.chbx2, self.chbx3, self.chbx4],
                [
                    QLabel('<b>Total Q (m3/s)</b>'),
                    QLabel('<b>2</b>'),
                    QLabel('<b>3</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>')
                ], ['Top Q (m3/s)', '5', '6', '4', '5', '66'],
                ['Middle Q (m3/s)', '2', '3', '3', '5', '6'],
                ['Bottom Q (m3/s)', '4', '4', '3', '2', '1'],
                ['Left Q (m3/s)', '2', '3', '44', '2', '22'],
                ['Right Q (m3/s)', '2', '3', '3', '333', '222']]

        self.datatables.append(
            self.create_table(310, data, h_headers, v_headers))

        func = partial(self.table_toggle, table_idx=2)
        label, collapse_widget = self.createTableCollapse("The Triquel", func)
        self.labels.append(label)
        self.expand.append(True)
        self.aLayout.addWidget(collapse_widget)
        self.aLayout.addWidget(self.datatables[2])

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        #self.layout.addWidget(self.scroll)
        #layout = new QVBoxLayout(central);
        #q = QSize()
        #q.setHeight(1000)
        #q.setWidth(700)
        #a.setMaximumSize(q)
        self.scroll.setWidget(self.a)
        self.scroll.setWidgetResizable(True)

        self.layout.addWidget(self.scroll, 1, 0, 1, 1)

        self.scroll2 = QScrollArea()
        self.scroll2.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scroll2.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.chbx1, self.chbx2, self.chbx3, self.chbx4 = QCheckBox(
        ), QCheckBox(), QCheckBox(), QCheckBox()
        data = [['Use', '', self.chbx1, self.chbx2, self.chbx3, self.chbx4],
                [
                    QLabel('<b>Total Q (m3/s)</b>'),
                    QLabel('<b>2</b>'),
                    QLabel('<b>3</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>'),
                    QLabel('<b>9</b>')
                ], ['Top Q (m3/s)', '5', '6', '4', '5', '66'],
                ['Middle Q (m3/s)', '2', '3', '3', '5', '6'],
                ['Bottom Q (m3/s)', '4', '4', '3', '2', '1'],
                ['Left Q (m3/s)', '2', '3', '44', '2', '22'],
                ['Right Q (m3/s)', '2', '3', '3', '333', '222']]

        self.scroll2.setWidgetResizable(True)
        #labels

        lbl2 = QLabel('<b style="font-size: 12pt">Messages</b>')
        lbl2.resize(250, 30)
        self.layout.addWidget(lbl2, 2, 0, 1, 1)

        #self.aLayout.addWidget(lbl1)

        self.b = QWidget()
        self.bLayout = QVBoxLayout()
        self.b.setLayout(self.bLayout)
        self.bLayout.addWidget(
            self.create_table(200, data, h_headers, v_headers))
        self.scroll2.setWidget(self.b)
        self.layout.addWidget(self.scroll2, 3, 0, 1, 1)

        self.rightPane = QWidget()
        self.rightLayout = QVBoxLayout()
        self.rightPane.setLayout(self.rightLayout)

        #labels
        lbl3 = QLabel(
            '<b style="font-size: 12pt">Measurement Quality Assessment</b>')
        lbl3.resize(250, 30)
        self.rightLayout.addWidget(lbl3)

        h_headers = ['', 'COV %', '', '% Q']
        v_headers = ['', '', '']
        data = [['Q:', '11.92', 'Left/Right Edge:', '21.81 / 4.03'],
                ['Width:', '8.73', 'Invalid Cells:', '0.64'],
                [
                    'Area:',
                    '11.32',
                    'Invalid Ens:',
                    '0.08',
                ]]

        self.datatables.append(
            self.create_table(110, data, h_headers, v_headers))
        self.datatables[3].setColumnWidth(0, 50)
        self.datatables[3].setColumnWidth(1, 60)
        self.datatables[3].setColumnWidth(2, 100)

        for x in range(len(data)):
            self.datatables[3].setRowHeight(x, 25)

        self.rightLayout.addWidget(self.datatables[3])

        h_headers = ['Parameter', 'Automatic', 'User']
        v_headers = ['', '', '', '', '', '', '']
        data = [['Random 95% Uncertainty', '19.0', ''],
                ['Invalid Data 95% Uncertainty', '0.1', ''],
                ['Edge Q 95% Uncertainty', '7.8', ''],
                ['Extrapolation 95% Uncertainty', '0.6', ''],
                ['Moving-Bed 95% Uncertainty', '1.5', ''],
                ['Systematic 68% Uncertainty', '1.5', ''],
                ['Estimated 95% Uncertainty', '20.8', '20.8']]

        self.datatables.append(
            self.create_table(210, data, h_headers, v_headers))
        for x in range(len(data)):
            self.datatables[4].setRowHeight(x, 25)

        self.rightLayout.addWidget(self.datatables[4])

        lbl4 = QLabel('<b style="font-size: 12pt">User Rating</b>')
        lbl4.resize(250, 30)
        self.rightLayout.addWidget(lbl4)

        self.combo = QComboBox()
        self.combo.addItem('Not Rated')
        self.combo.addItem('Excellent (<2%)')
        self.combo.addItem('Good (2-5%)')
        self.combo.addItem('Fair (5-8%)')
        self.combo.addItem('Poor (>8%)')
        self.rightLayout.addWidget(self.combo)

        lbl5 = QLabel('<b style="font-size: 12pt">Profile Extrapolation</b>')
        lbl5.resize(250, 30)
        self.rightLayout.addWidget(lbl5)

        x = [0, 10, 100]
        y = [3, 4, 5]

        self.mplwidget = MatplotlibWidget()

        self.mplwidget.setObjectName("mplwidget")

        self.mplwidget.plotDataPoints(x, y)

        self.rightLayout.addWidget(self.mplwidget)

        self.rightLayout.setStretch(0, 1)
        self.rightLayout.setStretch(1, 3)
        self.rightLayout.setStretch(2, 5)
        self.rightLayout.setStretch(3, 1)
        self.rightLayout.setStretch(4, 1)
        self.rightLayout.setStretch(5, 1)
        self.rightLayout.setStretch(6, 8)

        self.layout.addWidget(self.rightPane, 0, 1, 4, 1)

        #q = QSize()
        #q.setHeight(1000)
        #q.setWidth(700)
        #a.setMaximumSize(q)

        #self.scroll.setLayout(self.layout)
        self.layout.setRowStretch(0, 1)
        self.layout.setRowStretch(1, 10)
        self.layout.setRowStretch(2, 1)
        self.layout.setColumnStretch(0, 2)
        self.layout.setColumnStretch(1, 1)

        self.setLayout(self.layout)

    def createTableCollapse(self, text, func):

        collapseWidget = QWidget()
        hlayout = QHBoxLayout()
        collapseWidget.setLayout(hlayout)
        button = QPushButton('-')

        hlayout.setSpacing(10)

        button.clicked.connect(func)
        button.setFixedWidth(40)

        label = QLabel('<b style="font-size: 10pt">%s</b>' % text)

        hlayout.addWidget(button, 1)
        hlayout.addWidget(label, 20)

        return (button, collapseWidget)

    def create_table(self, height, data, h_headers, v_headers=None):
        datatable = QTableWidget()
        datatable.setMaximumHeight(height)
        datatable.setRowCount(len(data))
        datatable.setColumnCount(len(data[0]))

        for x in range(len(data)):
            for y in range(len(data[x])):
                if type(data[x][y]) is str:
                    datatable.setItem(x, y, QTableWidgetItem(data[x][y]))
                else:
                    datatable.setCellWidget(x, y, data[x][y])

        datatable.setHorizontalHeaderLabels(h_headers)
        if v_headers is not None:
            datatable.setVerticalHeaderLabels(v_headers)

        datatable.setAlternatingRowColors(True)
        datatable.setSortingEnabled(False)
        datatable.setEditTriggers(QAbstractItemView.NoEditTriggers)
        datatable.setStyleSheet(
            "QHeaderView::section { background-color: #e5e5e5; font-size: 8pt; font-weight: bold} "
            "QTableWidget { font-size: 8pt; } QHeaderView::section:horizontal { height: 30px}"
        )
        datatable.horizontalHeader().setStretchLastSection(True)

        return datatable

    def table_toggle(self, table_idx):

        dt = self.datatables[table_idx]

        def resize_layout():
            dt.setMaximumHeight(0)

        if self.expand[table_idx] == True:
            animation = QPropertyAnimation(self)
            animation.setPropertyName(QByteArray().append('size'))
            animation.setTargetObject(dt)
            animation.setDuration(250)

            ogWidth = dt.width()
            animation.setStartValue(QSize(ogWidth, 310))
            animation.setEndValue(QSize(ogWidth, 0))
            animation.finished.connect(resize_layout)
            animation.start()

            self.labels[table_idx].setText('+')

            self.a.updateGeometry()
            self.a.setMinimumHeight(self.a.minimumHeight() - 320)

        else:
            animation = QPropertyAnimation(self)
            animation.setPropertyName(QByteArray().append('size'))
            animation.setTargetObject(dt)
            animation.setDuration(250)

            dt.setMaximumHeight(310)
            ogWidth = dt.width()
            animation.setStartValue(QSize(ogWidth, 0))
            animation.setEndValue(QSize(ogWidth, 310))
            animation.start()

            self.labels[table_idx].setText('-')

            self.a.updateGeometry()
            self.a.setMinimumHeight(self.a.minimumHeight() + 320)

        self.expand[table_idx] = not self.expand[table_idx]
Exemple #10
0
    def create_left_column(self):
        # Create a vertical layout for the left column
        leftColumnLayout = QVBoxLayout()

        # Valve override group
        vorGroup = QGroupBox("Valve override")
        vorLayout = QHBoxLayout()

        self.vorNormalButton = QPushButton("Normal")
        self.vorNormalButton.setMinimumWidth(50)
        self.vorNormalButton.setFixedHeight(75)
        self.vorNormalButton.setCheckable(True)
        self.vorNormalButton.clicked.connect(self.update_vor_normal)

        self.vorClosedButton = QPushButton("Closed")
        self.vorClosedButton.setMinimumWidth(50)
        self.vorClosedButton.setFixedHeight(75)
        self.vorClosedButton.setCheckable(True)
        self.vorClosedButton.clicked.connect(self.update_vor_closed)

        self.vorOpenButton = QPushButton("Open")
        self.vorOpenButton.setMinimumWidth(50)
        self.vorOpenButton.setFixedHeight(75)
        self.vorOpenButton.setCheckable(True)
        self.vorOpenButton.clicked.connect(self.update_vor_open)

        vorState = self.controller.get_valve_override()
        if vorState == "Normal":
            self.vorNormalButton.setChecked(True)
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(False)
        elif vorState == "Closed":
            self.vorNormalButton.setChecked(False)
            self.vorClosedButton.setChecked(True)
            self.vorOpenButton.setChecked(False)
        elif vorState == "Open":
            self.vorNormalButton.setChecked(False)
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(True)
        else:
            raise ValueError(f"Unexpected vor state: {vorState}")

        vorLayout.addWidget(self.vorNormalButton)
        vorLayout.addWidget(self.vorClosedButton)
        vorLayout.addWidget(self.vorOpenButton)

        vorGroup.setLayout(vorLayout)
        vorGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        leftColumnLayout.addWidget(vorGroup, alignment=Qt.AlignTop)

        # Process configuration group
        processGroup = QGroupBox("Process configuration")
        processLayout = QFormLayout()

        self.gasFactorEdit = QLineEdit()
        self.gasFactorEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.gasFactorEdit.editingFinished.connect(self.update_gas_factor)
        self.gasFactorEdit.setText("{:.5f}".format(self.controller.get_gas()))

        self.pvFullScaleEdit = QLineEdit()
        self.pvFullScaleEdit.setValidator(
            QRegExpValidator(QRegExp("(-|)[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.pvFullScaleEdit.editingFinished.connect(self.update_pv_full_scale)
        self.pvFullScaleEdit.setText(str(self.controller.get_pv_full_scale()))

        self.pvSigtypeDropdown = QComboBox()
        self.pvSigtypeDropdown.addItems(Controller.INPUT_PORT_TYPES.keys())
        self.pvSigtypeDropdown.currentTextChanged.connect(
            self.update_pv_signal_type)
        self.pvSigtypeDropdown.setCurrentText(
            str(self.controller.get_pv_signal_type()))

        self.spFullScaleEdit = QLineEdit()
        self.spFullScaleEdit.setValidator(
            QRegExpValidator(QRegExp("(-|)[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.spFullScaleEdit.editingFinished.connect(self.update_sp_full_scale)
        self.spFullScaleEdit.setText(str(self.controller.get_sp_full_scale()))

        self.spSigtypeDropdown = QComboBox()
        self.spSigtypeDropdown.addItems(Controller.OUTPUT_PORT_TYPES.keys())
        self.spSigtypeDropdown.currentTextChanged.connect(
            self.update_sp_signal_type)
        self.spSigtypeDropdown.setCurrentText(
            str(self.controller.get_sp_signal_type()))

        self.spSourceDropdown = QComboBox()
        self.spSourceDropdown.addItems(Controller.SP_SOURCES.keys())
        self.spSourceDropdown.currentTextChanged.connect(self.update_source)
        self.spSourceDropdown.setCurrentText(str(self.controller.get_source()))

        self.decimalDropdown = QComboBox()
        self.decimalDropdown.addItems(Controller.DECIMAL_POINTS.keys())
        self.decimalDropdown.currentTextChanged.connect(
            self.update_decimal_point)
        self.decimalDropdown.setCurrentText(
            str(self.controller.get_decimal_point()))

        self.measureUnitsDropdown = QComboBox()
        self.measureUnitsDropdown.addItems(Controller.MEASUREMENT_UNITS.keys())
        self.measureUnitsDropdown.currentTextChanged.connect(
            self.update_measure_units)
        self.measureUnitsDropdown.setCurrentText(
            str(self.controller.get_measurement_units()))

        self.timebaseDropdown = QComboBox()
        self.timebaseDropdown.addItems(Controller.RATE_TIME_BASE.keys())
        self.timebaseDropdown.currentTextChanged.connect(self.update_time_base)
        self.timebaseDropdown.setCurrentText(
            str(self.controller.get_time_base()))

        processLayout.addRow(QLabel("Gas factor"), self.gasFactorEdit)
        processLayout.addRow(QLabel("PV Full Scale"), self.pvFullScaleEdit)
        processLayout.addRow(QLabel("PV Signal Type"), self.pvSigtypeDropdown)
        processLayout.addRow(QLabel("SP Full Scale"), self.spFullScaleEdit)
        processLayout.addRow(QLabel("SP Signal Type"), self.spSigtypeDropdown)
        processLayout.addRow(QLabel("Setpoint source"), self.spSourceDropdown)
        processLayout.addRow(QLabel("Decimal point"), self.decimalDropdown)
        processLayout.addRow(QLabel("Measurement units"),
                             self.measureUnitsDropdown)
        processLayout.addRow(QLabel("Time base"), self.timebaseDropdown)

        processGroup.setLayout(processLayout)
        processGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        leftColumnLayout.addWidget(processGroup, alignment=Qt.AlignTop)
        leftColumnLayout.setStretch(1, 100)

        runtimeGroup = QGroupBox("Runtime options")
        runtimeLayout = QVBoxLayout()

        layout = QHBoxLayout()

        self.bufferSizeEdit = QLineEdit()
        self.bufferSizeEdit.setText("64")
        self.bufferSizeEdit.setValidator(QIntValidator())
        self.bufferSizeEdit.editingFinished.connect(self.update_buffer_size)

        layout.addWidget(QLabel("Sample buffer size"))
        layout.addWidget(self.bufferSizeEdit)
        layout.addWidget(QLabel("samples"))

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.intervalEdit = QLineEdit()
        self.intervalEdit.setText("1")
        self.intervalEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.intervalEdit.editingFinished.connect(self.update_graph_timer)

        layout.addWidget(QLabel("Data update interval"))
        layout.addWidget(self.intervalEdit)
        layout.addWidget(QLabel("minutes"))

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.setpointEdit = QLineEdit()
        self.setpointEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.setpointEdit.editingFinished.connect(self.update_setpoint)
        self.setpointEdit.setText(str(self.controller.get_setpoint()))

        self.setpointUnitsLabel = QLabel(
            f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
        )

        layout.addWidget(QLabel("Setpoint"))
        layout.addWidget(self.setpointEdit)
        layout.addWidget(self.setpointUnitsLabel)

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        manualMeasureButton = QPushButton("Get measurement")
        manualMeasureButton.clicked.connect(self.update_plot)
        self.saveCsvButton = QPushButton("Start saving to CSV")
        self.saveCsvButton.clicked.connect(self.save_to_csv_start)

        layout.addWidget(manualMeasureButton)
        layout.addWidget(self.saveCsvButton)

        runtimeLayout.addLayout(layout)

        runtimeGroup.setLayout(runtimeLayout)
        runtimeGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        runtimeGroup.setFixedHeight(150)

        leftColumnLayout.addWidget(runtimeGroup, alignment=Qt.AlignBottom)

        return leftColumnLayout
Exemple #11
0
class RecommendMusicDetailBase(ScrollArea):
    def __init__(self, parent=None):
        """推荐歌单tabbase"""
        super().__init__()
        self.parent = parent
        self.setObjectName("RecommendMusicDetail")
        self.musicList = []

        self.frame.setContentsMargins(0, 0, 0, 0)

        # 主布局。
        self.mainLayout = QVBoxLayout(self.frame)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)

        self.topLayout = QHBoxLayout()
        self.topLayout.setContentsMargins(0, 0, 0, 0)
        self.picLabel = PicLabel(width=180, height=180)
        self.topLayout.addWidget(self.picLabel)

        self.topRightLayout = QVBoxLayout()
        self.topRightLayout.setContentsMargins(0, 0, 0, 0)
        self.topRightLayout.setSpacing(0)
        self.topLayout.addLayout(self.topRightLayout)

        self.topRightLayoutTitle = QHBoxLayout()
        self.topRightLayoutTitle.setContentsMargins(0, 0, 0, 0)
        self.topRightLayoutTitle.setSpacing(0)
        self.gedanButton = QPushButton("歌单")
        self.gedanButton.setMaximumSize(36, 20)
        self.titleLabel = QLabel()
        self.titleLabel.setWordWrap(True)
        self.titleLabel.setMaximumHeight(40)
        self.topRightLayoutTitle.addWidget(self.gedanButton)
        self.topRightLayoutTitle.addWidget(self.titleLabel)
        self.topRightLayout.addLayout(self.topRightLayoutTitle)

        self.authorLabel = QLabel()
        self.authorLabel.setMaximumHeight(28)
        self.topRightLayout.addWidget(self.authorLabel)

        self.playAllButton = QPushButton("全部播放")
        self.playAllButton.setIcon(QIcon('icons/playAll.png'))
        self.playAllButton.setObjectName('playAllButton')
        self.playAllButton.setMaximumSize(90, 24)
        self.topRightLayout.addWidget(self.playAllButton)

        self.topRightLayoutDesc = QHBoxLayout()
        self.topRightLayoutDesc.setContentsMargins(0, 0, 0, 0)
        self.topRightLayoutDesc.setSpacing(0)
        self.descLabel = QLabel("简介:")
        self.descriptionText = QTextEdit()
        self.descriptionText.setReadOnly(True)
        self.descriptionText.setMinimumWidth(450)
        self.descriptionText.setMinimumHeight(100)
        self.descriptionText.setMaximumHeight(100)
        self.topRightLayoutDesc.addWidget(self.descLabel)
        self.topRightLayoutDesc.addWidget(self.descriptionText)
        self.topRightLayout.addLayout(self.topRightLayoutDesc)

        self.topLayout.addLayout(self.topRightLayout)
        self.mainLayout.addLayout(self.topLayout)

        self.contentsTab = QTabWidget()
        self.singsTable = QTableWidget()
        self.singsTable.verticalHeader().setVisible(False)
        self.singsTable.setAlternatingRowColors(True)
        #self.singsTable.horizontalHeader().setStretchLastSection(True)
        self.singsTable.setColumnCount(4)
        #注意必须在初始化行列之后进行,否则,没有效果
        self.singsTable.setHorizontalHeaderLabels(['序号', '音乐标题', '歌手', '时长'])
        self.singsTable.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.singsTable.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Interactive)
        self.singsTable.horizontalHeader().setSectionResizeMode(
            3, QHeaderView.Interactive)
        self.singsTable.setColumnWidth(0, 40)
        self.singsTable.setColumnWidth(3, 100)
        self.singsTable.setObjectName('singsTable')
        """
        self.singsTable.setMinimumWidth(self.width())
        self.singsTable.setColumnWidths({i: j for i, j in zip(range(3),
                  [self.width() / 3 * 1.25, self.width() / 3 * 1.25,
                   self.width() / 3 * 0.5])})
        """
        self.contentsTab.addTab(self.singsTable, "歌曲列表")

        self.mainLayout.addWidget(self.contentsTab)
        self.mainLayout.setStretch(0, 3)
        self.mainLayout.setStretch(1, 7)

        self.singsTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.singsTable.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.singsTable.horizontalHeader().setStyleSheet(
            "QHeaderView::section{background:#1C394D;}")

        self.singsTable.itemDoubleClicked.connect(self.musicItemDoubleClick)

        self.singsTable.setContextMenuPolicy(Qt.CustomContextMenu)
        self.singsTable.customContextMenuRequested.connect(
            self.singsTableContextMenu)

    def musicItemDoubleClick(self, item):
        #print(item)
        currentRow = self.singsTable.currentRow()
        """
        player = self.parent.player
        import os
        import random
        names = [name for name in os.listdir(r"F:\musicdowmload") if ".MP3" in name]
        url = r"F:\musicdowmload\{}".format(random.choice(names))
        player.playMusic(QUrl.fromLocalFile(url))
        """

        self.palyMusic(self.musicList[currentRow])

    def singsTableContextMenu(self, pos):
        currentRow = self.singsTable.currentRow()

        pmenu = QMenu(self)
        downloadAct = QAction("下载", pmenu)
        pmenu.addAction(downloadAct)
        downloadAct.triggered.connect(lambda: self.downloadMusic(currentRow))
        #pmenu.popup(self.singsTable.mapToGlobal(pos))
        pmenu.popup(QCursor.pos())

    async def downloadMusic(self, currentRow):
        pass

    async def palyMusic(self, data):
        pass
class ProjectDockWidget(DockWidget):

    FOLDER = "folder"
    MAKE_FILE = "mark_file"
    MAKE_ITEM = "mark_item"
    OriginImage = "image"

    current_item_changed_signal = pyqtSignal(QtTreePropertyBrowser)
    delete_mark_item_signal = pyqtSignal(Project, MarkItem)
    double_click_mark_item = pyqtSignal(Project, MarkItem)

    def __init__(self, parent=None):
        super(ProjectDockWidget, self).__init__("标注项目", parent)

        self.setObjectName("projectTreeDockWidget")

        self._item_to_project = {}
        self._project_to_root_index = {}

        self.project_tree = QTreeWidget(self)
        self.project_tree.setColumnCount(1)
        self.project_tree.setHeaderHidden(True)
        self.project_tree.setEditTriggers(QAbstractItemView.DoubleClicked)

        print(type(QAbstractItemView.DoubleClicked))
        print(QAbstractItemView.DoubleClicked)

        self.project_tree.setObjectName("projectTree")
        self.project_tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.project_tree.customContextMenuRequested.connect(
            self.project_tree_item_context_menu)

        self.project_tree_mark_item_context_menu = self._create_mark_item_child_context_menu(
        )

        self.project_tree.currentItemChanged.connect(self.current_item_changed)
        self.project_tree.doubleClicked.connect(self.mouse_double_clicked)

        self._widget = QWidget(self)
        self._layout = QVBoxLayout(self._widget)
        self._layout.setStretch(0, 0)
        self._layout.setContentsMargins(0, 6, 6, 6)
        self._layout.addWidget(self.project_tree)
        self.setWidget(self._widget)

    def _create_mark_item_child_context_menu(self):
        menu = QMenu(self.project_tree)

        remove_self_action = menu.addAction(
            "删除")  # create_action(menu, "删除", slot=self.delete_self)
        remove_self_action.triggered.connect(self.delete_self)
        rename_action = create_action(menu, "重命名...", slot=self.rename)
        add_actions(menu, (remove_self_action, None, rename_action))
        return menu

    def create_project(self, project):
        if project in self._project_to_root_index:
            return

        root = TopLevelTreeItem(project, self.project_tree)
        root.setSelected(True)

        # 原始图片
        original_img_child = QTreeWidgetItem()
        original_img_child.setText(0, os.path.basename(project.image_path))
        original_img_child.setToolTip(0, project.image_path)
        original_img_child.setIcon(0, QIcon(":/img_icon.png"))
        original_img_child.setWhatsThis(0, self.OriginImage)
        root.addChild(original_img_child)

        self._project_to_root_index[
            project] = self.project_tree.indexOfTopLevelItem(root)

    def add_mark_item(self, project, mark_item: MarkItem):
        if project not in self._project_to_root_index:
            return
        mark_item_child = MarkTreeItem(mark_item)
        mark_item_child.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEditable
                                 | Qt.ItemIsEnabled)
        self._item_to_project[mark_item] = project
        self.project_tree.topLevelItem(
            self._project_to_root_index[project]).addChild(mark_item_child)

    def project_tree_item_context_menu(self, point):
        point = self.project_tree.mapToGlobal(point)
        current_item = self.project_tree.currentItem()
        if current_item:
            if not current_item.parent():
                """TODO"""
            else:
                what_file = current_item.whatsThis(0)
                if what_file == self.MAKE_ITEM:
                    self.project_tree_mark_item_context_menu.exec_(point)

    def rename(self):
        current_item = self.project_tree.currentItem()
        new_name, ok = QInputDialog.getText(self,
                                            "重命名",
                                            "请输入新的名字:",
                                            text=current_item.text(0))
        if ok and current_item.text(0) != new_name:
            if isinstance(current_item, MarkTreeItem):
                current_item.get_mark_item().item_name = new_name

    def mouse_double_clicked(self) -> None:
        """"""
        current_item = self.project_tree.currentItem()
        if isinstance(current_item, MarkTreeItem):
            item = current_item.get_mark_item()
            self.double_click_mark_item.emit(self._item_to_project[item], item)
        elif isinstance(current_item, TopLevelTreeItem):
            project = current_item.get_project()
            self.double_click_mark_item.emit(project, None)

    def current_item_changed(self, current_item, p):
        if isinstance(current_item, AbstractProjectTreeItem):
            self.current_item_changed_signal.emit(
                current_item.get_item_browser())

    def delete_all_file(self):
        """"""

    def delete_all_mark_file(self):
        """"""

    def delete_all_mark_item(self):
        """"""

    def selected_mark_changed(self, selected_item: MarkItem):
        """"""
        # self.project_tree.
        if selected_item in self._item_to_project:
            project = self._item_to_project[selected_item]
            top_level_index = self._project_to_root_index[project]
            top_level_item = self.project_tree.topLevelItem(top_level_index)
            for index in range(top_level_item.childCount()):
                item = top_level_item.child(index)
                if isinstance(item, MarkTreeItem):
                    if item.get_mark_item() == selected_item:
                        self.project_tree.setCurrentItem(item)
                        return

    def close_project(self, project):
        if project not in self._project_to_root_index:
            return
        self.project_tree.takeTopLevelItem(
            self._project_to_root_index[project])

    def delete_self(self):

        current_item = self.project_tree.currentItem()
        if isinstance(current_item, MarkTreeItem):
            project = self._item_to_project[current_item.get_mark_item()]
            self.delete_mark_item_signal.emit(project,
                                              current_item.get_mark_item())

            parent = current_item.parent()
            parent.removeChild(current_item)

            if current_item.get_mark_item() in self._item_to_project:
                del self._item_to_project[current_item.get_mark_item()]
            del current_item

    def setting_selection(self):
        """"""

    def outline_detect(self):
        """"""

    # 标注项目属性的设置
    def property_setting(self):
        pass
Exemple #13
0
    def initUi(self):

        self.statusBar().showMessage('加载中...')

        self.setGeometry(100, 60, 600, 400)
        self.setWindowTitle('王梅的股票查询分析系统')
        self.setWindowIcon(QIcon('logo.jpg'))

        self.themeSetAct = QAction('更换图表主题(&T)', self)
        self.themeSetAct.setShortcut('Ctrl+T')
        # 默认浅色主题
        self.themeIndex = 0
        self.themeSetAct.setStatusTip(Visualization.themesTip[self.themeIndex])
        #self.themeSetAct.triggered.connect(self.changeTheme)

        menubar = self.menuBar()
        setMenu = menubar.addMenu('设置(&S)')
        setMenu.addAction(self.themeSetAct)

        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        # 添加web view
        self.leftTopView = QWebEngineView()
        self.leftTopView.setContextMenuPolicy(Qt.NoContextMenu)

        self.BottomView = QWebEngineView()
        self.BottomView.setContextMenuPolicy(Qt.NoContextMenu)

        self.StockLineEdit = QLineEdit(" ")
        search_Btn = QPushButton('搜索')
        search_Btn.clicked.connect(self.searchStock)

        # 搜索布局
        h0box = QHBoxLayout()
        h0box.addWidget(self.StockLineEdit)
        h0box.addWidget(search_Btn)
        h0box.setStretch(0, 4)
        h0box.setStretch(1, 1)

        # 左上布局
        lefttopbox = QVBoxLayout()
        lefttopbox.addLayout(h0box)
        lefttopbox.addWidget(self.leftTopView)
        lefttopbox.setStretch(0, 1)
        lefttopbox.setStretch(1, 1)

        # 右上布局
        h1box = QHBoxLayout()
        h1box.addLayout(lefttopbox)
        h1box.addWidget(RightTableView())
        #h1box.addWidget(self.leftTopView)
        h1box.setStretch(0, 1)
        h1box.setStretch(1, 1)

        # 底部布局
        h2box = QHBoxLayout()
        h2box.addWidget(self.BottomView)

        # 整个界面布局
        vbox = QVBoxLayout()
        vbox.addLayout(h1box)
        vbox.addLayout(h2box)
        vbox.setStretch(0, 1)
        vbox.setStretch(1, 1)

        self.widget.setLayout(vbox)
class Appearance(SettingsSection):

    Name = 'Appearance'

    DEFAULT_STYLE = 'background: rgb(70, 70, 70);' + \
                    'border: 1 solid rgb(0, 0, 0);' + \
                    'border-radius: 6;'

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

        self.verticalLayout = QVBoxLayout(self)

        self.textEditGroup = QGroupBox(self)
        self.horizontalLayout = QHBoxLayout(self.textEditGroup)

        self.textEdit = QTextEdit(self.textEditGroup)
        self.horizontalLayout.addWidget(self.textEdit)

        self.verticalLayout.addWidget(self.textEditGroup)

        self.fontSizeGroup = QGroupBox(self)
        self.horizontalLayout_1 = QHBoxLayout(self.fontSizeGroup)

        self.fontSizeSpin = QSpinBox(self.fontSizeGroup)
        self.horizontalLayout_1.addWidget(self.fontSizeSpin)

        self.verticalLayout.addWidget(self.fontSizeGroup)

        self.colorGroup = QGroupBox(self)
        self.horizontalLayout_2 = QHBoxLayout(self.colorGroup)

        self.colorBButton = QPushButton(self.colorGroup)
        self.horizontalLayout_2.addWidget(self.colorBButton)

        self.colorFButton = QPushButton(self.colorGroup)
        self.horizontalLayout_2.addWidget(self.colorFButton)

        self.verticalLayout.addWidget(self.colorGroup)

        self.previewGroup = QGroupBox(self)
        self.horizontalLayout_3 = QHBoxLayout(self.previewGroup)

        self.beforeLabel = QLabel(self.previewGroup)
        self.beforeLabel.setStyleSheet(self.DEFAULT_STYLE)
        self.beforeLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.horizontalLayout_3.addWidget(self.beforeLabel)

        self.nowLabel = QLabel(self.previewGroup)
        self.nowLabel.setStyleSheet(self.DEFAULT_STYLE)
        self.nowLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.horizontalLayout_3.addWidget(self.nowLabel)

        self.verticalLayout.addWidget(self.previewGroup)

        self.textEdit.textChanged.connect(self.changeText)
        self.fontSizeSpin.valueChanged.connect(self.updatePreview)
        self.colorBButton.clicked.connect(self.changeBColor)
        self.colorFButton.clicked.connect(self.changeFColor)

        self.warning = QLabel(self)
        self.warning.setText("The real appearance depends on the layout")
        self.warning.setAlignment(QtCore.Qt.AlignCenter)
        self.warning.setStyleSheet("color: red; font-weight: bold")

        self.verticalLayout.addWidget(self.warning)

        self.verticalLayout.setStretch(0, 3)
        self.verticalLayout.setStretch(1, 1)
        self.verticalLayout.setStretch(2, 1)
        self.verticalLayout.setStretch(3, 2)
        self.verticalLayout.setStretch(4, 1)

        self.retranslateUi()

        self.bColor = 'rgb(0,0,0)'
        self.fColor = 'rgb(177,177,177)'
        self.fontSizeSpin.setValue(11)

    def retranslateUi(self):
        self.textEditGroup.setTitle("Shown Text")
        self.textEdit.setText("Empty")
        self.fontSizeGroup.setTitle("Set Font Size")
        self.colorGroup.setTitle("Color")
        self.colorBButton.setText("Select background color")
        self.colorFButton.setText("Select font color")
        self.previewGroup.setTitle("Preview")
        self.beforeLabel.setText("Before")
        self.nowLabel.setText("After")

    def enable_check(self, enable):
        self.textEditGroup.setCheckable(enable)
        self.textEditGroup.setChecked(False)

        self.fontSizeGroup.setCheckable(enable)
        self.fontSizeGroup.setChecked(False)

        self.colorGroup.setCheckable(enable)
        self.colorGroup.setChecked(False)

    def get_configuration(self):
        conf = {}

        checked = self.textEditGroup.isCheckable()

        if(not (checked and not self.textEditGroup.isChecked())):
            conf['name'] = self.textEdit.toPlainText()
        if(not (checked and not self.colorGroup.isChecked())):
            conf['background'] = self.bColor
            conf['color'] = self.fColor
        if(not (checked and not self.fontSizeGroup.isChecked())):
            conf['font-size'] = self.fontSizeSpin.value()

        return conf

    def set_configuration(self, conf):
        if(conf is not None):
            if('name' in conf):
                self.textEdit.setText(conf['name'])
                self.nowLabel.setText(conf['name'])
            if('background' in conf):
                self.bColor = conf['background']
            if('color' in conf):
                self.fColor = conf['color']
            if('font-size' in conf):
                self.fontSizeSpin.setValue(conf['font-size'])

            self.updatePreview()
            self.beforeLabel.setStyleSheet(self.nowLabel.styleSheet())

    def updatePreview(self):
        self.nowLabel.setStyleSheet('background: ' + self.bColor + ';\
                     border: 1 solid rgb(0,0,0);\
                     border-radius: 6;\
                     color: ' + self.fColor + ';\
                     font-size: ' + str(self.fontSizeSpin.value()) + 'pt;')

    def changeBColor(self):
        initial = QColor(*map(int, re.findall('\d{1,3}', self.bColor)))
        color = QColorDialog.getColor(initial, parent=self)

        if(color.isValid()):
            self.bColor = 'rgb' + str(color.getRgb())
            self.updatePreview()

    def changeFColor(self):
        initial = QColor(*map(int, re.findall('\d{1,3}', self.fColor)))
        color = QColorDialog.getColor(initial, parent=self)

        if(color.isValid()):
            self.fColor = 'rgb' + str(color.getRgb())
            self.updatePreview()

    def changeText(self):
        self.nowLabel.setText(self.textEdit.toPlainText())
Exemple #15
0
    def initWindow(self):
        QToolTip.setFont(QFont('SansSerif', 10))
        # main layout
        frameWidget = QWidget()
        mainWidget = QSplitter(Qt.Horizontal)
        frameLayout = QVBoxLayout()
        self.settingWidget = QWidget()
        self.settingWidget.setProperty("class","settingWidget")
        self.receiveSendWidget = QSplitter(Qt.Vertical)
        self.functionalWiget = QWidget()
        settingLayout = QVBoxLayout()
        sendReceiveLayout = QVBoxLayout()
        sendFunctionalLayout = QVBoxLayout()
        mainLayout = QHBoxLayout()
        self.settingWidget.setLayout(settingLayout)
        self.receiveSendWidget.setLayout(sendReceiveLayout)
        self.functionalWiget.setLayout(sendFunctionalLayout)
        mainLayout.addWidget(self.settingWidget)
        mainLayout.addWidget(self.receiveSendWidget)
        mainLayout.addWidget(self.functionalWiget)
        mainLayout.setStretch(0,2)
        mainLayout.setStretch(1, 6)
        mainLayout.setStretch(2, 2)
        menuLayout = QHBoxLayout()
        mainWidget.setLayout(mainLayout)
        frameLayout.addLayout(menuLayout)
        frameLayout.addWidget(mainWidget)
        frameWidget.setLayout(frameLayout)
        self.setCentralWidget(frameWidget)

        # option layout
        self.settingsButton = QPushButton()
        self.skinButton = QPushButton("")
        self.waveButton = QPushButton("")
        self.aboutButton = QPushButton()
        self.functionalButton = QPushButton()
        self.encodingCombobox = ComboBox()
        self.encodingCombobox.addItem("ASCII")
        self.encodingCombobox.addItem("UTF-8")
        self.encodingCombobox.addItem("UTF-16")
        self.encodingCombobox.addItem("GBK")
        self.encodingCombobox.addItem("GB2312")
        self.encodingCombobox.addItem("GB18030")
        self.settingsButton.setProperty("class", "menuItem1")
        self.skinButton.setProperty("class", "menuItem2")
        self.aboutButton.setProperty("class", "menuItem3")
        self.functionalButton.setProperty("class", "menuItem4")
        self.waveButton.setProperty("class", "menuItem5")
        self.settingsButton.setObjectName("menuItem")
        self.skinButton.setObjectName("menuItem")
        self.aboutButton.setObjectName("menuItem")
        self.functionalButton.setObjectName("menuItem")
        self.waveButton.setObjectName("menuItem")
        menuLayout.addWidget(self.settingsButton)
        menuLayout.addWidget(self.skinButton)
        menuLayout.addWidget(self.waveButton)
        menuLayout.addWidget(self.aboutButton)
        menuLayout.addStretch(0)
        menuLayout.addWidget(self.encodingCombobox)
        menuLayout.addWidget(self.functionalButton)


        # widgets receive and send area
        self.receiveArea = QTextEdit()
        self.sendArea = QTextEdit()
        self.clearReceiveButtion = QPushButton(parameters.strClearReceive)
        self.sendButtion = QPushButton(parameters.strSend)
        self.sendHistory = ComboBox()
        sendWidget = QWidget()
        sendAreaWidgetsLayout = QHBoxLayout()
        sendWidget.setLayout(sendAreaWidgetsLayout)
        buttonLayout = QVBoxLayout()
        buttonLayout.addWidget(self.clearReceiveButtion)
        buttonLayout.addStretch(1)
        buttonLayout.addWidget(self.sendButtion)
        sendAreaWidgetsLayout.addWidget(self.sendArea)
        sendAreaWidgetsLayout.addLayout(buttonLayout)
        sendReceiveLayout.addWidget(self.receiveArea)
        sendReceiveLayout.addWidget(sendWidget)
        sendReceiveLayout.addWidget(self.sendHistory)
        sendReceiveLayout.setStretch(0, 7)
        sendReceiveLayout.setStretch(1, 2)
        sendReceiveLayout.setStretch(2, 1)

        # widgets serial settings
        serialSettingsGroupBox = QGroupBox(parameters.strSerialSettings)
        serialSettingsLayout = QGridLayout()
        serialReceiveSettingsLayout = QGridLayout()
        serialSendSettingsLayout = QGridLayout()
        serialPortLabek = QLabel(parameters.strSerialPort)
        serailBaudrateLabel = QLabel(parameters.strSerialBaudrate)
        serailBytesLabel = QLabel(parameters.strSerialBytes)
        serailParityLabel = QLabel(parameters.strSerialParity)
        serailStopbitsLabel = QLabel(parameters.strSerialStopbits)
        self.serialPortCombobox = ComboBox()
        self.serailBaudrateCombobox = ComboBox()
        self.serailBaudrateCombobox.addItem("9600")
        self.serailBaudrateCombobox.addItem("19200")
        self.serailBaudrateCombobox.addItem("38400")
        self.serailBaudrateCombobox.addItem("57600")
        self.serailBaudrateCombobox.addItem("115200")
        self.serailBaudrateCombobox.setCurrentIndex(4)
        self.serailBaudrateCombobox.setEditable(True)
        self.serailBytesCombobox = ComboBox()
        self.serailBytesCombobox.addItem("5")
        self.serailBytesCombobox.addItem("6")
        self.serailBytesCombobox.addItem("7")
        self.serailBytesCombobox.addItem("8")
        self.serailBytesCombobox.setCurrentIndex(3)
        self.serailParityCombobox = ComboBox()
        self.serailParityCombobox.addItem("None")
        self.serailParityCombobox.addItem("Odd")
        self.serailParityCombobox.addItem("Even")
        self.serailParityCombobox.addItem("Mark")
        self.serailParityCombobox.addItem("Space")
        self.serailParityCombobox.setCurrentIndex(0)
        self.serailStopbitsCombobox = ComboBox()
        self.serailStopbitsCombobox.addItem("1")
        self.serailStopbitsCombobox.addItem("1.5")
        self.serailStopbitsCombobox.addItem("2")
        self.serailStopbitsCombobox.setCurrentIndex(0)
        self.checkBoxRts = QCheckBox("rts")
        self.checkBoxDtr = QCheckBox("dtr")
        self.serialOpenCloseButton = QPushButton(parameters.strOpen)
        serialSettingsLayout.addWidget(serialPortLabek,0,0)
        serialSettingsLayout.addWidget(serailBaudrateLabel, 1, 0)
        serialSettingsLayout.addWidget(serailBytesLabel, 2, 0)
        serialSettingsLayout.addWidget(serailParityLabel, 3, 0)
        serialSettingsLayout.addWidget(serailStopbitsLabel, 4, 0)
        serialSettingsLayout.addWidget(self.serialPortCombobox, 0, 1)
        serialSettingsLayout.addWidget(self.serailBaudrateCombobox, 1, 1)
        serialSettingsLayout.addWidget(self.serailBytesCombobox, 2, 1)
        serialSettingsLayout.addWidget(self.serailParityCombobox, 3, 1)
        serialSettingsLayout.addWidget(self.serailStopbitsCombobox, 4, 1)
        serialSettingsLayout.addWidget(self.checkBoxRts, 5, 0,1,1)
        serialSettingsLayout.addWidget(self.checkBoxDtr, 5, 1,1,1)
        serialSettingsLayout.addWidget(self.serialOpenCloseButton, 6, 0,1,2)
        serialSettingsGroupBox.setLayout(serialSettingsLayout)
        settingLayout.addWidget(serialSettingsGroupBox)

        # serial receive settings
        serialReceiveSettingsGroupBox = QGroupBox(parameters.strSerialReceiveSettings)
        self.receiveSettingsAscii = QRadioButton(parameters.strAscii)
        self.receiveSettingsHex = QRadioButton(parameters.strHex)
        self.receiveSettingsAscii.setChecked(True)
        self.receiveSettingsAutoLinefeed = QCheckBox(parameters.strAutoLinefeed)
        self.receiveSettingsAutoLinefeedTime = QLineEdit(parameters.strAutoLinefeedTime)
        self.receiveSettingsAutoLinefeed.setMaximumWidth(75)
        self.receiveSettingsAutoLinefeedTime.setMaximumWidth(75)
        serialReceiveSettingsLayout.addWidget(self.receiveSettingsAscii,1,0,1,1)
        serialReceiveSettingsLayout.addWidget(self.receiveSettingsHex,1,1,1,1)
        serialReceiveSettingsLayout.addWidget(self.receiveSettingsAutoLinefeed, 2, 0, 1, 1)
        serialReceiveSettingsLayout.addWidget(self.receiveSettingsAutoLinefeedTime, 2, 1, 1, 1)
        serialReceiveSettingsGroupBox.setLayout(serialReceiveSettingsLayout)
        settingLayout.addWidget(serialReceiveSettingsGroupBox)

        # serial send settings
        serialSendSettingsGroupBox = QGroupBox(parameters.strSerialSendSettings)
        self.sendSettingsAscii = QRadioButton(parameters.strAscii)
        self.sendSettingsHex = QRadioButton(parameters.strHex)
        self.sendSettingsAscii.setChecked(True)
        self.sendSettingsScheduledCheckBox = QCheckBox(parameters.strScheduled)
        self.sendSettingsScheduled = QLineEdit(parameters.strScheduledTime)
        self.sendSettingsScheduledCheckBox.setMaximumWidth(75)
        self.sendSettingsScheduled.setMaximumWidth(75)
        self.sendSettingsCFLF = QCheckBox(parameters.strCRLF)
        self.sendSettingsCFLF.setChecked(False)
        serialSendSettingsLayout.addWidget(self.sendSettingsAscii,1,0,1,1)
        serialSendSettingsLayout.addWidget(self.sendSettingsHex,1,1,1,1)
        serialSendSettingsLayout.addWidget(self.sendSettingsScheduledCheckBox, 2, 0, 1, 1)
        serialSendSettingsLayout.addWidget(self.sendSettingsScheduled, 2, 1, 1, 1)
        serialSendSettingsLayout.addWidget(self.sendSettingsCFLF, 3, 0, 1, 2)
        serialSendSettingsGroupBox.setLayout(serialSendSettingsLayout)
        settingLayout.addWidget(serialSendSettingsGroupBox)

        settingLayout.setStretch(0, 5)
        settingLayout.setStretch(1, 2.5)
        settingLayout.setStretch(2, 2.5)

        # right functional layout
        self.addButton = QPushButton(parameters.strAdd)
        functionalGroupBox = QGroupBox(parameters.strFunctionalSend)
        functionalGridLayout = QGridLayout()
        functionalGridLayout.addWidget(self.addButton,0,1)
        functionalGroupBox.setLayout(functionalGridLayout)
        sendFunctionalLayout.addWidget(functionalGroupBox)
        self.isHideFunctinal = True
        self.hideFunctional()

        # main window
        self.statusBarStauts = QLabel()
        self.statusBarStauts.setMinimumWidth(80)
        self.statusBarStauts.setText("<font color=%s>%s</font>" %("#008200", parameters.strReady))
        self.statusBarSendCount = QLabel(parameters.strSend+"(bytes): "+"0")
        self.statusBarReceiveCount = QLabel(parameters.strReceive+"(bytes): "+"0")
        self.statusBar().addWidget(self.statusBarStauts)
        self.statusBar().addWidget(self.statusBarSendCount,2)
        self.statusBar().addWidget(self.statusBarReceiveCount,3)
        # self.statusBar()

        self.resize(800, 500)
        self.MoveToCenter()
        self.setWindowTitle(parameters.appName+" V"+str(helpAbout.versionMajor)+"."+str(helpAbout.versionMinor))
        icon = QIcon()
        print("icon path:"+self.DataPath+"/"+parameters.appIcon)
        icon.addPixmap(QPixmap(self.DataPath+"/"+parameters.appIcon), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)
        if sys.platform == "win32":
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("comtool")
        self.show()
        return
class App(QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'CSA Program Chapter Tracker'
        self.left = 50
        self.top = 75
        self.width = 1350
        self.height = 700
        self.init_UI()

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

        self.create_student_table()
        self.create_record_table()
        self.recordTableWidget.setEditTriggers(
            QAbstractItemView.NoEditTriggers)
        self.create_calendar()

        # l is label
        self.lname = QLabel("Name", self)
        self.lnumber = QLabel("Student ID", self)
        self.lgrade = QLabel("Grade", self)
        self.lhours = QLabel("Hours", self)
        self.lcsa = QLabel("CSA", self)
        self.lstart = QLabel(self.my_calendar.selectedDate().toString(), self)
        self.lend = QLabel(self.my_calendar.selectedDate().toString(), self)

        self.lname.move(102.5, 540)
        self.lnumber.move(252.5, 540)
        self.lgrade.move(425, 540)
        self.lhours.move(562.5, 540)
        self.lcsa.move(710, 540)
        self.lstart.move(1025, 350)
        self.lend.move(1180, 350)

        self.lstart.setFrameStyle(QFrame.Panel | QFrame.Raised)
        self.lend.setFrameStyle(QFrame.Panel | QFrame.Raised)

        self.lstart.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.lstart.setAlignment(Qt.AlignCenter)
        self.lend.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.lend.setAlignment(Qt.AlignCenter)
        self.lstart.resize(self.lstart.sizeHint().width() + 6,
                           self.lstart.sizeHint().height() + 3)
        self.lend.resize(self.lend.sizeHint().width() + 6,
                         self.lend.sizeHint().height() + 3)

        # tb is textbox
        self.tbname = QLineEdit(self)
        self.tbnumber = QLineEdit(self)
        self.tbhours = QLineEdit(self)

        # b is combobox
        self.bgrade = QComboBox(self)
        self.bcsa = QComboBox(self)
        self.btimespan = QComboBox(self)

        self.bgrade.addItem("9th")
        self.bgrade.addItem("10th")
        self.bgrade.addItem("11th")
        self.bgrade.addItem("12th")

        self.bcsa.addItem("N/A")
        self.bcsa.addItem("CSA Community")
        self.bcsa.addItem("CSA Service")
        self.bcsa.addItem("CSA Achievement")

        self.btimespan.addItem("Weeks")
        self.btimespan.addItem("Months")
        self.btimespan.addItem("Custom")

        self.bgrade.move(368, 570)
        self.bcsa.move(652.5, 570)
        self.btimespan.move(815, 105)

        self.tbname.move(50, 570)
        self.tbnumber.move(200, 570)
        self.tbhours.move(510, 570)

        self.tbname.resize(140, 25)
        self.tbnumber.resize(165, 25)
        self.tbhours.resize(140, 25)

        self.bgrade.resize(140, 25)
        self.bcsa.resize(155, 25)

        self.bgrade.currentText()

        self.add_button = QPushButton('Add', self)
        self.add_button.setToolTip('Add student to database with given data')
        self.add_button.move(810, 567.5)
        self.add_button.clicked.connect(self.add_student)

        self.delete_button = QPushButton('Delete', self)
        self.delete_button.setToolTip('Delete selected rows from database')
        self.delete_button.move(810, 245)
        self.delete_button.clicked.connect(self.remove_students)

        self.print_button = QPushButton('Compile Data', self)
        self.print_button.setToolTip(
            'Compile the current student data as a pdf')
        self.print_button.move(810, 65)
        self.print_button.resize(self.print_button.sizeHint())
        self.print_button.clicked.connect(self.compile_pdf)

        self.generate_button = QPushButton('Generate Student', self)
        self.generate_button.setToolTip('Generate a random student')
        self.generate_button.move(810, 605)
        self.generate_button.resize(self.generate_button.sizeHint())
        self.generate_button.clicked.connect(self.generate_students)

        self.start_date_button = QPushButton('Set Start', self)
        self.start_date_button.setToolTip(
            'Set the start date for the data to compile at')
        self.start_date_button.move(1030, 315)
        self.start_date_button.resize(self.start_date_button.sizeHint())
        self.start_date_button.clicked.connect(self.set_start_date)

        self.end_date_button = QPushButton('Set End', self)
        self.end_date_button.setToolTip(
            'Set the end date for the data to compile to')
        self.end_date_button.move(1185, 315)
        self.end_date_button.resize(self.end_date_button.sizeHint())
        self.end_date_button.clicked.connect(self.set_end_date)

        self.btimespan.resize(self.print_button.sizeHint())

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(50, 70, 550, 200)

        self.layout.addWidget(self.recordTableWidget)
        self.layout.addWidget(self.studentTableWidget)
        self.layout.setSpacing(29)
        self.layout.setStretch(0, 3)
        self.layout.setStretch(1, 5)

        self.setLayout(self.layout)
        self.edit = True

        self.show()

    def create_student_table(self):
        self.studentTableWidget = QTableWidget()

        row_count = c.execute("SELECT COUNT(*) FROM studentdata").fetchone()[0]
        self.studentTableWidget.setRowCount(row_count)
        self.studentTableWidget.setColumnCount(5)
        self.studentTableWidget.setShowGrid(True)
        self.studentTableWidget.move(0, 0)
        self.studentTableWidget.setHorizontalHeaderLabels(
            ['Name', 'Student ID', 'Grade Level', 'Hours', 'CSA'])

        self.header = self.studentTableWidget.horizontalHeader()
        self.header.setSectionResizeMode(0, QHeaderView.Stretch)
        self.header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
        self.header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
        self.header.setSectionResizeMode(4, QHeaderView.ResizeToContents)

        self.populate_student_data()
        self.studentTableWidget.itemChanged.connect(self.log_change)

    def create_record_table(self):
        self.recordTableWidget = QTableWidget()

        row_count = c.execute("SELECT COUNT(*) FROM recorddata").fetchone()[0]
        self.recordTableWidget.setRowCount(row_count)
        self.recordTableWidget.setColumnCount(4)
        self.recordTableWidget.setShowGrid(True)
        self.recordTableWidget.setHorizontalHeaderLabels(
            ['Date', 'Name', 'Student ID', 'Hours Added'])

        self.header = self.recordTableWidget.horizontalHeader()
        self.header.setSectionResizeMode(0, QHeaderView.Stretch)
        self.header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
        self.header.setSectionResizeMode(2, QHeaderView.ResizeToContents)

        self.populate_record_data()

    def create_calendar(self):
        self.my_calendar = QCalendarWidget(self)
        self.my_calendar.move(1000, 70)
        self.my_calendar.resize(300, 200)
        self.ldate = QLabel(self)
        self.ldate.move(1100, 280)
        self.ldate.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.ldate.setLineWidth(2)
        self.my_calendar.clicked[QDate].connect(self.on_date_selection)

        self.ldate.setText(self.my_calendar.selectedDate().toString())
        self.ldate.resize(self.ldate.sizeHint())

    def on_date_selection(self, date):
        self.ldate.setText(date.toString())
        self.ldate.resize(self.ldate.sizeHint())

    def populate_student_data(self):
        c.execute("SELECT * FROM studentdata")
        student_data = c.fetchall()
        self.edit = False
        self.studentTableWidget.setRowCount(0)
        self.studentTableWidget.setRowCount(len(student_data))
        for i in range(len(student_data)):
            self.studentTableWidget.setItem(
                i, 0, QTableWidgetItem(str(student_data[i][0])))
            self.studentTableWidget.setItem(
                i, 1, QTableWidgetItem(str(student_data[i][1])))
            self.studentTableWidget.setItem(
                i, 2, QTableWidgetItem(str(student_data[i][2])))
            self.studentTableWidget.setItem(
                i, 3, QTableWidgetItem(str(student_data[i][3])))
            self.studentTableWidget.setItem(
                i, 4, QTableWidgetItem(str(student_data[i][4])))
        self.edit = True

    def populate_record_data(self):
        c.execute("SELECT * FROM recorddata")
        record_data = c.fetchall()[::-1]
        self.recordTableWidget.setRowCount(0)
        self.recordTableWidget.setRowCount(len(record_data))
        for i in range(len(record_data)):
            self.recordTableWidget.setItem(
                i, 0, QTableWidgetItem(str(record_data[i][0])))
            self.recordTableWidget.setItem(
                i, 1, QTableWidgetItem(str(record_data[i][1])))
            self.recordTableWidget.setItem(
                i, 2, QTableWidgetItem(str(record_data[i][2])))
            self.recordTableWidget.setItem(
                i, 3, QTableWidgetItem(str(record_data[i][3])))

    def log_change(self, item):
        if self.edit:
            cols = {0: "name", 1: "number", 2: "grade", 3: "hours", 4: "csa"}
            c.execute("SELECT * FROM studentdata")
            student_data = c.fetchall()
            student_number = student_data[item.row()][1]
            student_name = student_data[item.row()][0]
            old_hours = student_data[item.row()][3]

            if item.column() == 3:
                hours = item.text()
                if hours.isdigit() == False:
                    try:
                        hours = eval(hours)
                        c.execute(
                            "UPDATE studentdata SET hours = ? WHERE number = ?",
                            (
                                hours,
                                student_number,
                            ))
                        self.update_csa(float(hours), student_number, item)

                        c.execute("INSERT INTO recorddata VALUES (?, ?, ?, ?)", (datetime.now().strftime("%B %d, %Y %I:%M %p"), \
                        student_name, student_number, str('%.3f' % (float(hours)-old_hours)).rstrip('0').rstrip('.'),))
                        self.populate_record_data()
                    except Exception as e:
                        value_error = QMessageBox()
                        value_error.setIcon(QMessageBox.Critical)
                        value_error.setInformativeText(
                            'Please enter a valid expression or number')
                        value_error.setWindowTitle("Error: Value")
                        value_error.exec_()
                else:
                    c.execute(
                        "UPDATE studentdata SET hours = ? WHERE number = ?", (
                            hours,
                            student_number,
                        ))
                    self.update_csa(float(hours), student_number, item)

                    c.execute("INSERT INTO recorddata VALUES (?, ?, ?, ?)", (datetime.now().strftime("%B %d, %Y %I:%M %p"), \
                    student_name, student_number, str('%.3f' % (float(hours)-old_hours)).rstrip('0').rstrip('.'),))
                    self.populate_record_data()

            else:
                try:
                    c.execute(
                        "UPDATE studentdata SET {} = ? WHERE number = ?".
                        format(cols[item.column()]), (
                            item.text(),
                            student_number,
                        ))
                    if item.column() == 0 or item.column() == 1:
                        c.execute(
                            "UPDATE recorddata SET {} = ? WHERE number = ?".
                            format(cols[item.column()]), (
                                item.text(),
                                student_number,
                            ))
                        self.populate_record_data()
                except Exception as e:
                    insert_error = QMessageBox()
                    insert_error.setIcon(QMessageBox.Critical)
                    insert_error.setInformativeText(
                        'Please check your Student ID is unique')
                    insert_error.setWindowTitle("Error: Values")
                    insert_error.exec_()
                    replace_list = [
                        '/' * (i + 1) for i in range(len(student_data))
                    ]
                    replace_existing = [
                        i[1] for i in student_data if i[1] in replace_list
                    ]
                    replace_new = [
                        i for i in replace_list if i not in replace_existing
                    ]
                    replace_new.sort(key=len)
                    c.execute(
                        "UPDATE studentdata SET number = ? WHERE number = ?", (
                            replace_new[0],
                            student_number,
                        ))
                    c.execute(
                        "UPDATE recorddata SET number = ? WHERE number = ?", (
                            replace_new[0],
                            student_number,
                        ))
                    self.studentTableWidget.setItem(
                        item.row(), item.column(),
                        QTableWidgetItem(replace_new[0]))

            conn.commit()

    def update_csa(self, hours, student_number, item):
        csa_switcher = {
            50: "CSA Community",
            200: "CSA Service",
            500: "CSA Achievement"
        }
        adjusted_hours = 500 if hours >= 500 else 200 if hours >= 200 else 50 if hours >= 50 else 0
        csa_award = csa_switcher.get(adjusted_hours, "N/A")
        c.execute("UPDATE studentdata SET csa = ? WHERE number = ?",
                  (csa_award, student_number))
        conn.commit()

        try:
            self.studentTableWidget.blockSignals(True)
            self.studentTableWidget.setItem(item.row(), 4,
                                            QTableWidgetItem(str(csa_award)))
            self.studentTableWidget.setItem(
                item.row(), 3,
                QTableWidgetItem(str('%.3f' % hours).rstrip('0').rstrip('.')))
            self.studentTableWidget.blockSignals(False)
        except Exception as e:
            print(e)

        c.execute("SELECT * FROM studentdata")

    @pyqtSlot()
    def add_student(self):
        # i is input
        iname = self.tbname.text()
        inumber = self.tbnumber.text()
        igrade = str(self.bgrade.currentText())
        ihours = self.tbhours.text()
        icsa = str(self.bcsa.currentText())
        try:
            for i in range(5):
                if [iname, inumber, igrade, ihours, icsa][i] == '':
                    raise Exception
            int(ihours)
            c.execute('''INSERT INTO studentdata VALUES (?, ?, ?, ?, ?)''', (
                iname,
                inumber,
                igrade,
                ihours,
                icsa,
            ))
            c.execute('''INSERT INTO recorddata VALUES (?, ?, ?, ?)''', (
                datetime.now().strftime("%B %d, %Y %I:%M %p"),
                iname,
                inumber,
                ihours,
            ))
            conn.commit()

            self.populate_student_data()
            self.populate_record_data()
        except Exception as e:

            insert_error = QMessageBox()
            insert_error.setIcon(QMessageBox.Critical)
            insert_error.setInformativeText(
                'Please check your Student ID is unique, all inputs are filled out, and hours is a number'
            )
            insert_error.setWindowTitle("Error: Values")
            insert_error.exec_()

    @pyqtSlot()
    def remove_students(self):
        selected = self.studentTableWidget.selectedItems()
        selected_dict = {}
        for item in selected:
            if item.row() in selected_dict:
                selected_dict[item.row()] += 1
            else:
                selected_dict[item.row()] = 1

        c.execute('''SELECT * FROM studentdata''')
        student_data = c.fetchall()
        numbers = ()

        for key in reversed(list(selected_dict.keys())):
            if selected_dict[key] == 5:
                self.studentTableWidget.removeRow(key)
                numbers += (student_data[key][1], )

        c.execute(
            "DELETE FROM studentdata WHERE number IN ({})".format(", ".join(
                "?" * len(numbers))), numbers)
        c.execute(
            "DELETE FROM recorddata WHERE number IN ({})".format(", ".join(
                "?" * len(numbers))), numbers)
        self.populate_record_data()

        conn.commit()

    @pyqtSlot()
    def compile_pdf(self):
        pdf = FPDF()
        pdf.add_page()
        pdf.set_font("courier", size=12)

        if self.btimespan.currentText() == "Weeks":
            start_range = (datetime.now() - timedelta(7))
            end_range = datetime.now()
            txt = "Last Week Report"
        elif self.btimespan.currentText() == "Months":
            start_range = (datetime.now() - timedelta(30))
            end_range = datetime.now()
            txt = "Last Week Report"
        else:
            start_range = datetime.strptime(self.lstart.text(), "%a %b %d %Y")
            end_range = datetime.strptime(self.lend.text(), "%a %b %d %Y")
            txt = "Custom Report: %s - %s" % (start_range.strftime(
                "%B %d, %Y"), end_range.strftime("%B %d, %Y"))

        pdf.cell(200, 10, txt=txt, ln=1, align="C")
        c.execute('''SELECT * FROM recorddata''')
        datafetch = c.fetchall()
        record_data = [record for record in datafetch if datetime.strptime(record[0], ("%B %d, %Y %I:%M %p")) >= start_range and\
             datetime.strptime(record[0], ("%B %d, %Y %I:%M %p")) <= end_range][::-1]

        if record_data == []:
            insert_error = QMessageBox()
            insert_error.setIcon(QMessageBox.Critical)
            insert_error.setInformativeText('No data to Compile')
            insert_error.setWindowTitle("Error: Data")
            insert_error.exec_()
        else:
            field1_max = len(
                max([str(record[0]) for record in record_data], key=len))
            field2_max = len(
                max([str(record[1]) for record in record_data], key=len))
            field3_max = len(
                max([str(record[2]) for record in record_data], key=len))
            field4_max = len(
                max([str(record[3]) for record in record_data], key=len))

            field_maxes = [field1_max, field2_max, field3_max, field4_max]
            xpos = 200
            ypos = 15
            yline = 35
            iconst = 2.725
            sconst = 2.4
            spacer = 0 if sum(field_maxes) > 75 else int(
                (75 - sum(field_maxes)) / 3)
            line_count = 0
            page_lines = 17

            if spacer == 0:
                pdf.set_font("courier", size=9)
                spacer = 0 if sum(field_maxes) > 100 else int(
                    (100 - sum(field_maxes)) / 3)
                iconst *= 0.75
                sconst *= 0.75

            for record in record_data:
                txt = ''
                for i in range(len(list(record))):
                    txt += str(
                        record[i]) + ' ' * int(field_maxes[i] -
                                               len(str(record[i])) + spacer)

                pdf.cell(xpos, ypos, txt=txt, ln=1, align="L")
                pdf.line(0, yline, 400, yline)
                yline += 15
                line_count += 1

                newx = 0
                if line_count % page_lines == 0:
                    yline = 10
                    title_space = 25 if line_count == page_lines else 10
                    for i in field_maxes[0:3]:
                        newx += (i) * iconst + (spacer) * sconst
                        pdf.line(newx, title_space, newx, 20 + 15 * page_lines)
                elif line_count == len(record_data):
                    title_space = 25 if line_count < page_lines else 10
                    footer_space = 20 if line_count < page_lines else 10
                    for i in field_maxes[0:3]:
                        newx += (i) * iconst + (spacer) * sconst
                        pdf.line(newx, title_space, newx,
                                 footer_space + 15 * (line_count % page_lines))

            if len(record_data) > page_lines:
                pdf.line(0, yline, 400, yline)

            c.execute('''SELECT name, number FROM studentdata''')
            student_data = c.fetchall()
            for student in student_data:
                if student[1] in [record[2] for record in record_data]:
                    total_user_hours = str(
                        round(
                            sum([
                                record[3] for record in record_data
                                if record[2] == student[1]
                            ]), 3))
                    txt = ' ' * int(
                        sum(field_maxes) + spacer * 3 - len(total_user_hours) -
                        len(student[0]) -
                        2) + student[0] + ': ' + total_user_hours
                    pdf.cell(xpos, ypos, txt=txt, ln=1, align="L")

            total_hours = str(
                round(sum([record[3] for record in record_data]), 3))
            txt = ' ' * int(
                sum(field_maxes) + spacer * 3 - len(total_hours) -
                13) + "Total Hours: " + total_hours

            pdf.cell(xpos, ypos, txt=txt, ln=1, align="L")

            pdf.output("community_service_program.pdf")

    #generate random student with hours added on a random date
    @pyqtSlot()
    def generate_students(self):
        start_dt = date.today().replace(day=1, month=1).toordinal()
        end_dt = date.today().toordinal()
        random_day = date.fromordinal(random.randint(
            start_dt, end_dt)).strftime("%B %d, %Y %I:%M %p")

        random_name = fake.name()
        random_id = fake.ssn()
        random_grade = random.choice(['9th', '10th', '11th', '12th'])
        random_hours = random.randint(1, 500)
        csa_award = 'CSA Community' if random_hours >= 500 else (
            'CSA Service' if random_hours >= 200 else
            ('CSA Achievement' if random_hours >= 50 else 'N/A'))
        c.execute('''INSERT INTO studentdata VALUES (?, ?, ?, ?, ?)''', (
            random_name,
            str(random_id),
            random_grade,
            random_hours,
            csa_award,
        ))
        c.execute('''INSERT INTO recorddata VALUES (?, ?, ?, ?)''', (
            str(random_day),
            random_name,
            str(random_id),
            random_hours,
        ))
        conn.commit()

        self.populate_record_data()
        self.populate_student_data()

    @pyqtSlot()
    def set_start_date(self):
        if datetime.strptime(
                self.lend.text(), "%a %b %d %Y") < datetime.strptime(
                    self.my_calendar.selectedDate().toString(), "%a %b %d %Y"):
            self.lend.setText(self.my_calendar.selectedDate().toString())
            self.lend.resize(self.lend.sizeHint())
        self.lstart.setText(self.my_calendar.selectedDate().toString())
        self.lstart.resize(self.lstart.sizeHint().width() + 6,
                           self.lstart.sizeHint().height() + 3)

    @pyqtSlot()
    def set_end_date(self):
        if datetime.strptime(self.my_calendar.selectedDate().toString(),
                             "%a %b %d %Y") < datetime.strptime(
                                 self.lstart.text(), "%a %b %d %Y"):
            date_error = QMessageBox()
            date_error.setIcon(QMessageBox.Critical)
            date_error.setInformativeText(
                'End date cannot be before start date')
            date_error.setWindowTitle("Error: Date")
            date_error.exec_()
        else:
            self.lend.setText(self.my_calendar.selectedDate().toString())
            self.lend.resize(self.lend.sizeHint().width() + 6,
                             self.lend.sizeHint().height() + 3)
Exemple #17
0
class MainWindow(QMainWindow):
    errorSignal = pyqtSignal(str, str)
    hintSignal = pyqtSignal(str, str)
    updateProgressSignal = pyqtSignal(str, int, int, str)
    updateProgressPrintSignal = pyqtSignal(str)
    showSerialComboboxSignal = pyqtSignal()
    downloadResultSignal = pyqtSignal(bool, str)
    DataPath = "./"
    app = None

    def __init__(self,app):
        super().__init__()
        self.app = app
        self.programStartGetSavedParameters()
        self.initVar()
        self.initWindow()
        self.initEvent()
        self.updateFrameParams()

    def __del__(self):
        pass

    def initVar(self):
        self.burning = False
        self.isDetectSerialPort = False
        self.DataPath = parameters.dataPath
        self.kflash = KFlash(print_callback=self.kflash_py_printCallback)
        self.saveKfpkDir = ""

    def setWindowSize(self, w=520, h=550):
        self.resize(w, h)

    def initWindow(self):
        QToolTip.setFont(QFont('SansSerif', 10))
        # main layout
        self.frameWidget = QWidget()
        mainWidget = QSplitter(Qt.Horizontal)
        self.frameLayout = QVBoxLayout()
        self.settingWidget = QWidget()
        settingLayout = QVBoxLayout()
        self.settingWidget.setProperty("class","settingWidget")
        mainLayout = QVBoxLayout()
        self.settingWidget.setLayout(settingLayout)
        mainLayout.addWidget(self.settingWidget)
        mainLayout.setStretch(0,2)
        menuLayout = QHBoxLayout()
        
        self.progressHint = QLabel()
        self.progressHint.hide()

        self.progressbarRootWidget = QWidget()
        progressbarLayout = QVBoxLayout()
        self.progressbarRootWidget.setProperty("class","progressbarWidget")
        self.progressbarRootWidget.setLayout(progressbarLayout)
        
        self.downloadWidget = QWidget()
        downloadLayout = QVBoxLayout()
        self.downloadWidget.setProperty("class","downloadWidget")
        self.downloadWidget.setLayout(downloadLayout)

        mainWidget.setLayout(mainLayout)
        # menu
        # -----
        # settings and others
        # -----
        # progress bar
        # -----
        # download button
        # -----
        # status bar
        self.frameLayout.addLayout(menuLayout)
        self.frameLayout.addWidget(mainWidget)
        self.frameLayout.addWidget(self.progressHint)
        self.frameLayout.addWidget(self.progressbarRootWidget)
        self.frameLayout.addWidget(self.downloadWidget)
        self.frameWidget.setLayout(self.frameLayout)
        self.setCentralWidget(self.frameWidget)
        self.setFrameStrentch(1)

        # option layout
        self.langButton = QPushButton()
        self.skinButton = QPushButton()
        self.aboutButton = QPushButton()
        self.langButton.setProperty("class", "menuItemLang")
        self.skinButton.setProperty("class", "menuItem2")
        self.aboutButton.setProperty("class", "menuItem3")
        self.langButton.setObjectName("menuItem")
        self.skinButton.setObjectName("menuItem")
        self.aboutButton.setObjectName("menuItem")
        menuLayout.addWidget(self.langButton)
        menuLayout.addWidget(self.skinButton)
        menuLayout.addWidget(self.aboutButton)
        menuLayout.addStretch(0)
        
        # widgets file select
        self.fileSelectGroupBox = QGroupBox(tr("SelectFile"))
        settingLayout.addWidget(self.fileSelectGroupBox)
        self.fileSelectLayout = QVBoxLayout()
        self.fileSelectGroupBox.setLayout(self.fileSelectLayout)
        oneFilePathWidget = QWidget()
        oneFilePathWidgetLayout = QHBoxLayout()
        oneFilePathWidget.setLayout(oneFilePathWidgetLayout)
        filePathWidget = QLineEdit()
        openFileButton = QPushButton(tr("OpenFile"))
        oneFilePathWidgetLayout.addWidget(filePathWidget)
        oneFilePathWidgetLayout.addWidget(openFileButton)
        oneFilePathWidgetLayout.setStretch(0, 3)
        oneFilePathWidgetLayout.setStretch(1, 1)
        self.fileSelectLayout.addWidget(oneFilePathWidget)
        self.fileSelectWidgets = [["kfpkg", oneFilePathWidget, oneFilePathWidgetLayout, filePathWidget, None, openFileButton]]
                  # for "button": ["button", addoneWidget, addoneWidgetLayout, addFileButton, packFileButton]
                  # for "bin":    ["bin", oneFilePathWidget, oneFilePathWidgetLayout, filePathWidget, fileBurnAddrWidget, openFileButton, fileBurnEncCheckbox]
        # widgets board select
        boardSettingsGroupBox = QGroupBox(tr("BoardSettings"))
        settingLayout.addWidget(boardSettingsGroupBox)
        boardSettingsLayout = QGridLayout()
        boardSettingsGroupBox.setLayout(boardSettingsLayout)
        self.boardLabel = QLabel(tr("Board"))
        self.boardCombobox = ComboBox()
        self.boardCombobox.addItem(parameters.SipeedMaixDock)
        self.boardCombobox.addItem(parameters.SipeedMaixBit)
        self.boardCombobox.addItem(parameters.SipeedMaixBitMic)
        self.boardCombobox.addItem(parameters.SipeedMaixduino)
        self.boardCombobox.addItem(parameters.SipeedMaixGo)
        self.boardCombobox.addItem(parameters.SipeedMaixGoD)
        self.boardCombobox.addItem(parameters.KendryteKd233)
        self.boardCombobox.addItem(parameters.kendryteTrainer)
        self.boardCombobox.addItem(parameters.Auto)
        self.burnPositionLabel = QLabel(tr("BurnTo"))
        self.burnPositionCombobox = ComboBox()
        self.burnPositionCombobox.addItem(tr("Flash"))
        self.burnPositionCombobox.addItem(tr("SRAM"))
        boardSettingsLayout.addWidget(self.boardLabel, 0, 0)
        boardSettingsLayout.addWidget(self.boardCombobox, 0, 1)
        boardSettingsLayout.addWidget(self.burnPositionLabel, 1, 0)
        boardSettingsLayout.addWidget(self.burnPositionCombobox, 1, 1)

        # widgets serial settings
        serialSettingsGroupBox = QGroupBox(tr("SerialSettings"))
        serialSettingsLayout = QGridLayout()
        serialPortLabek = QLabel(tr("SerialPort"))
        serailBaudrateLabel = QLabel(tr("SerialBaudrate"))
        slowModeLabel = QLabel(tr("Speed mode"))
        self.serialPortCombobox = ComboBox()
        self.serailBaudrateCombobox = ComboBox()
        self.serailBaudrateCombobox.addItem("115200")
        self.serailBaudrateCombobox.addItem("921600")
        self.serailBaudrateCombobox.addItem("1500000")
        self.serailBaudrateCombobox.addItem("2000000")
        self.serailBaudrateCombobox.addItem("3500000")
        self.serailBaudrateCombobox.addItem("4000000")
        self.serailBaudrateCombobox.addItem("4500000")
        self.serailBaudrateCombobox.setCurrentIndex(1)
        self.serailBaudrateCombobox.setEditable(True)
        self.slowModeCombobox = ComboBox()
        self.slowModeCombobox.addItem(tr("Slow mode"))
        self.slowModeCombobox.addItem(tr("Fast mode"))
        
        serialSettingsLayout.addWidget(serialPortLabek,0,0)
        serialSettingsLayout.addWidget(serailBaudrateLabel, 1, 0)
        serialSettingsLayout.addWidget(slowModeLabel, 2, 0)
        serialSettingsLayout.addWidget(self.serialPortCombobox, 0, 1)
        serialSettingsLayout.addWidget(self.serailBaudrateCombobox, 1, 1)
        serialSettingsLayout.addWidget(self.slowModeCombobox, 2, 1)
        serialSettingsGroupBox.setLayout(serialSettingsLayout)
        settingLayout.addWidget(serialSettingsGroupBox)

        # set stretch
        settingLayout.setStretch(0,1)
        settingLayout.setStretch(1,1)
        settingLayout.setStretch(2,2)

        # widgets progress bar
        
        self.progressbar = QProgressBar(self.progressbarRootWidget)
        self.progressbar.setValue(0)
        self.progressbarRootWidget.hide()

        # widgets download area
        self.downloadButton = QPushButton(tr("Download"))
        downloadLayout.addWidget(self.downloadButton)

        # main window
        self.statusBarStauts = QLabel()
        self.statusBarStauts.setMinimumWidth(80)
        self.statusBarStauts.setText("<font color=%s>%s</font>" %("#1aac2d", tr("DownloadHint")))
        self.statusBar().addWidget(self.statusBarStauts)

        self.setWindowSize()
        self.MoveToCenter()
        self.setWindowTitle(parameters.appName+" V"+str(helpAbout.versionMajor)+"."+str(helpAbout.versionMinor))
        icon = QIcon()
        print("icon path:"+self.DataPath+"/"+parameters.appIcon)
        icon.addPixmap(QPixmap(self.DataPath+"/"+parameters.appIcon), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)
        if sys.platform == "win32":
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(parameters.appName)
        
        self.show()
        self.progressbar.setGeometry(10, 0, self.downloadWidget.width()-25, 40)
        print("config file path:", parameters.configFilePath)

    def initEvent(self):
        self.serialPortCombobox.clicked.connect(self.portComboboxClicked)
        self.errorSignal.connect(self.errorHint)
        self.hintSignal.connect(self.hint)
        self.downloadResultSignal.connect(self.downloadResult)
        self.showSerialComboboxSignal.connect(self.showCombobox)
        self.updateProgressSignal.connect(self.updateProgress)
        self.updateProgressPrintSignal.connect(self.updateProgressPrint)
        self.langButton.clicked.connect(self.langChange)
        self.skinButton.clicked.connect(self.skinChange)
        self.aboutButton.clicked.connect(self.showAbout)
        self.downloadButton.clicked.connect(self.download)
        self.fileSelectWidget_Button(0).clicked.connect(lambda:self.selectFile(self.fileSelectWidget_Path(0)))

        self.myObject=MyClass(self)
        slotLambda = lambda: self.indexChanged_lambda(self.myObject)
        self.serialPortCombobox.currentIndexChanged.connect(slotLambda)

    def setFrameStrentch(self, mode):
        if mode == 0:
            self.frameLayout.setStretch(0,1)
            self.frameLayout.setStretch(1,3)
            self.frameLayout.setStretch(2,3)
            self.frameLayout.setStretch(3,1)
            self.frameLayout.setStretch(4,1)
            self.frameLayout.setStretch(5,1)
        else:
            self.frameLayout.setStretch(0,0)
            self.frameLayout.setStretch(1,0)
            self.frameLayout.setStretch(2,1)
            self.frameLayout.setStretch(3,1)
            self.frameLayout.setStretch(4,1)
            self.frameLayout.setStretch(5,1)
    
    def fileSelectWidget_Type(self, index):
        return self.fileSelectWidgets[index][0]

    def fileSelectWidget_Widget(self, index):
        return self.fileSelectWidgets[index][1]
    
    def fileSelectWidget_Layout(self, index):
        return self.fileSelectWidgets[index][2]

    def fileSelectWidget_Path(self, index):
        return self.fileSelectWidgets[index][3]

    def fileSelectWidget_Addr(self, index):
        return self.fileSelectWidgets[index][4]
    
    def fileSelectWidget_Button(self, index):
        return self.fileSelectWidgets[index][5]
    
    def fileSelectWidget_Prefix(self, index):
        return self.fileSelectWidgets[index][6]
    
    def fileSelectWidget_Close(self, index):
        return self.fileSelectWidgets[index][7]

    # @QtCore.pyqtSlot(str)
    def indexChanged_lambda(self, obj):
        mainObj = obj.arg
        self.serialPortCombobox.setToolTip(mainObj.serialPortCombobox.currentText())

    def portComboboxClicked(self):
        self.detectSerialPort()

    def MoveToCenter(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
    def removeFileSelection(self, button):
        index = -1
        for i in range(len(self.fileSelectWidgets)):
            if len(self.fileSelectWidgets[i]) >= 8:
                if self.fileSelectWidget_Close(i) == button:
                    index = i
        print(index)
        if index == -1:
            return
        if len(self.fileSelectWidgets) > 2:
            self.fileSelectWidget_Button(index).clicked.disconnect()
            self.fileSelectWidget_Close(index).clicked.disconnect()
            self.fileSelectWidget_Widget(index).setParent(None)
            self.fileSelectWidgets.remove(self.fileSelectWidgets[index])
        if len(self.fileSelectWidgets) == 2:
            self.fileSelectWidget_Close(0).clicked.disconnect()
            self.fileSelectWidget_Close(0).setParent(None)
            self.fileSelectWidgets[0].remove(self.fileSelectWidget_Close(0))
        self.downloadWidget.resize(self.downloadWidget.width(), 58)
        self.setWindowSize(self.width())

    def addAddFileWidget(self):
        if len(self.fileSelectWidgets) == 2:
            removeButton0 = QPushButton()
            removeButton0.setProperty("class", "remove_file_selection")
            self.fileSelectWidgets[0][2].addWidget(removeButton0)
            self.fileSelectWidgets[0].append(removeButton0)
            removeButton0.clicked.connect(lambda:self.removeFileSelection(removeButton0))
        oneFilePathWidget = QWidget()
        oneFilePathWidgetLayout = QHBoxLayout()
        oneFilePathWidget.setLayout(oneFilePathWidgetLayout)
        filePathWidget = QLineEdit()
        fileBurnAddrWidget = QLineEdit("0x00000")
        fileBurnEncCheckbox = QCheckBox(tr("Prefix"))
        openFileButton = QPushButton(tr("OpenFile"))
        removeButton = QPushButton()
        removeButton.setProperty("class", "remove_file_selection")
        oneFilePathWidgetLayout.addWidget(filePathWidget)
        oneFilePathWidgetLayout.addWidget(fileBurnAddrWidget)
        oneFilePathWidgetLayout.addWidget(fileBurnEncCheckbox)
        oneFilePathWidgetLayout.addWidget(openFileButton)
        oneFilePathWidgetLayout.addWidget(removeButton)
        oneFilePathWidgetLayout.setStretch(0, 4)
        oneFilePathWidgetLayout.setStretch(1, 2)
        oneFilePathWidgetLayout.setStretch(2, 1)
        oneFilePathWidgetLayout.setStretch(3, 2)
        # oneFilePathWidgetLayout.setStretch(4, 1)
        index = len(self.fileSelectWidgets)-1
        self.fileSelectWidgets.insert(index, ["bin", oneFilePathWidget, oneFilePathWidgetLayout, filePathWidget, fileBurnAddrWidget, openFileButton, fileBurnEncCheckbox, removeButton])
        self.fileSelectLayout.insertWidget(index, oneFilePathWidget)
        openFileButton.clicked.connect(lambda:self.selectFile(filePathWidget))
        removeButton.clicked.connect(lambda:self.removeFileSelection(removeButton))

    def fileSelectShowKfpkg(self, index, name):
        if index==0 and self.fileSelectWidget_Type(0) == "kfpkg": #only one kgpkg before
            self.fileSelectWidget_Path(index).setText(name)
        else:# have bin file before, remove all and add one for kfpkg
            for i in range(len(self.fileSelectWidgets)):
                if self.fileSelectWidget_Type(i)=="button":
                    self.fileSelectWidgets[i][3].clicked.disconnect()
                    self.fileSelectWidgets[i][4].clicked.disconnect()
                else:
                    self.fileSelectWidget_Button(i).clicked.disconnect()
                # self.fileSelectLayout.removeWidget(self.fileSelectWidget_Widget(i))
                self.fileSelectWidget_Widget(i).setParent(None)
            self.fileSelectWidgets.clear()
            oneFilePathWidget = QWidget()
            oneFilePathWidgetLayout = QHBoxLayout()
            oneFilePathWidget.setLayout(oneFilePathWidgetLayout)
            filePathWidget = QLineEdit()
            openFileButton = QPushButton(tr("OpenFile"))
            oneFilePathWidgetLayout.addWidget(filePathWidget)
            oneFilePathWidgetLayout.addWidget(openFileButton)
            oneFilePathWidgetLayout.setStretch(0, 3)
            oneFilePathWidgetLayout.setStretch(1, 1)
            self.fileSelectLayout.addWidget(oneFilePathWidget)
            self.fileSelectWidgets.append(["kfpkg", oneFilePathWidget, oneFilePathWidgetLayout, filePathWidget, None, openFileButton])
            openFileButton.clicked.connect(lambda:self.selectFile(filePathWidget))
            filePathWidget.setText(name)
            # TODO: resize window

    def fileSelectShowBin(self, index, name, addr=None, prefix=None, prefixAuto=False, closeButton=False ):
        if index==0 and self.fileSelectWidget_Type(0) == "kfpkg": #only one kgpkg before
            self.fileSelectWidget_Button(index).clicked.disconnect()
            # self.fileSelectLayout.removeWidget(self.fileSelectWidget_Widget(index))
            self.fileSelectWidget_Widget(index).setParent(None)
            self.fileSelectWidgets.clear()
            oneFilePathWidget = QWidget()
            oneFilePathWidgetLayout = QHBoxLayout()
            oneFilePathWidget.setLayout(oneFilePathWidgetLayout)
            filePathWidget = QLineEdit()
            fileBurnAddrWidget = QLineEdit("0x00000")
            fileBurnEncCheckbox = QCheckBox(tr("Prefix"))
            openFileButton = QPushButton(tr("OpenFile"))
            if closeButton:
                removeButton = QPushButton()
                removeButton.setProperty("class", "remove_file_selection")
            oneFilePathWidgetLayout.addWidget(filePathWidget)
            oneFilePathWidgetLayout.addWidget(fileBurnAddrWidget)
            oneFilePathWidgetLayout.addWidget(fileBurnEncCheckbox)
            oneFilePathWidgetLayout.addWidget(openFileButton)
            if closeButton:
                oneFilePathWidgetLayout.addWidget(removeButton)
            oneFilePathWidgetLayout.setStretch(0, 4)
            oneFilePathWidgetLayout.setStretch(1, 2)
            oneFilePathWidgetLayout.setStretch(2, 1)
            oneFilePathWidgetLayout.setStretch(3, 2)
            # oneFilePathWidgetLayout.setStretch(4, 1)
            self.fileSelectLayout.addWidget(oneFilePathWidget)
            openFileButton.clicked.connect(lambda:self.selectFile(filePathWidget))
            if closeButton:
                self.fileSelectWidgets.append(["bin", oneFilePathWidget, oneFilePathWidgetLayout, filePathWidget, fileBurnAddrWidget, openFileButton, fileBurnEncCheckbox, removeButton])
                removeButton.clicked.connect(lambda:self.removeFileSelection(removeButton))
                print(removeButton)
            else:
                self.fileSelectWidgets.append(["bin", oneFilePathWidget, oneFilePathWidgetLayout, filePathWidget, fileBurnAddrWidget, openFileButton, fileBurnEncCheckbox])
            # add ADD button
            addoneWidget = QWidget()
            addoneWidgetLayout = QHBoxLayout()
            addoneWidget.setLayout(addoneWidgetLayout)
            addFileButton = QPushButton(tr("Add File"))
            packFileButton = QPushButton(tr("Pack to kfpkg"))
            addoneWidgetLayout.addWidget(addFileButton)
            addoneWidgetLayout.addWidget(packFileButton)
            self.fileSelectLayout.addWidget(addoneWidget)
            self.fileSelectWidgets.append(["button", addoneWidget, addoneWidgetLayout, addFileButton, packFileButton])
            addFileButton.clicked.connect(self.addAddFileWidget)
            packFileButton.clicked.connect(self.packFile)

        self.fileSelectWidget_Path(index).setText(name)

        if prefixAuto:
            if name.endswith(".bin"):
                self.fileSelectWidget_Prefix(index).setChecked(True)
            else:
                self.fileSelectWidget_Prefix(index).setChecked(False)
        elif prefix:
            self.fileSelectWidget_Prefix(index).setChecked(True)
        if addr:
                self.fileSelectWidget_Addr(index).setText("0x%06x" %(addr))

    # return: ("kfpkg", [(file path, burn addr, add prefix),...])
    #      or ("bin", file path)
    #      or (None, None)
    def getBurnFilesInfo(self):
        files = []
        if self.fileSelectWidgets[0][0] == "kfpkg":
            path = self.fileSelectWidget_Path(0).text().strip()
            if path=="" or not os.path.exists(path):
                self.errorSignal.emit(tr("Error"), tr("Line {}: ").format(i+1)+tr("File path error")+":"+path)
                return (None, None)
            return ("kfpkg", path)
        for i in range(len(self.fileSelectWidgets)):
            if self.fileSelectWidgets[i][0] == "bin":
                path = self.fileSelectWidget_Path(i).text().strip()
                if path=="":
                    continue
                if not os.path.exists(path):
                    self.errorSignal.emit(tr("Error"), tr("Line {}: ").format(i+1)+tr("File path error")+":"+path)
                    return (None, None)
                try:
                    addr = int(self.fileSelectWidgets[i][4].text(), 16)
                except Exception:
                    self.errorSignal.emit(tr("Error"), tr("Line {}: ").format(i+1)+tr("Address error")+self.fileSelectWidgets[i][4].text())
                    return (None, None)
                files.append( (path, addr, self.fileSelectWidgets[i][6].isChecked()) )
        return ("bin", files)

    class KFPKG():
        def __init__(self):
            self.fileInfo = {"version": "0.1.0", "files": []}
            self.filePath = {}
            self.burnAddr = []
        
        def addFile(self, addr, path, prefix=False):
            if not os.path.exists(path):
                raise ValueError(tr("FilePathError"))
            if addr in self.burnAddr:
                raise ValueError(tr("Burn dddr duplicate")+":0x%06x" %(addr))
            f = {}
            f_name = os.path.split(path)[1]
            f["address"] = addr
            f["bin"] = f_name
            f["sha256Prefix"] = prefix
            self.fileInfo["files"].append(f)
            self.filePath[f_name] = path
            self.burnAddr.append(addr)

        def listDumps(self):
            kfpkg_json = json.dumps(self.fileInfo, indent=4)
            return kfpkg_json

        def listDump(self, path):
            with open(path, "w") as f:
                f.write(json.dumps(self.fileInfo, indent=4))

        def listLoads(self, kfpkgJson):
            self.fileInfo = json.loads(kfpkgJson)

        def listLload(self, path):
            with open(path) as f:
                self.fileInfo = json.load(f)

        def save(self, path):
            listName = os.path.join(tempfile.gettempdir(), "kflash_gui_tmp_list.json")
            self.listDump(listName)
            try:
                with zipfile.ZipFile(path, "w") as zip:
                    for name,path in self.filePath.items():
                        zip.write(path, arcname=name, compress_type=zipfile.ZIP_LZMA)
                    zip.write(listName, arcname="flash-list.json", compress_type=zipfile.ZIP_LZMA)
                    zip.close()
            except Exception as e:
                os.remove(listName)
                raise e
            os.remove(listName)

    def packFile(self):
        # generate flash-list.json
        fileType, files = self.getBurnFilesInfo()
        if not fileType or not files or fileType=="kfpkg":
            self.errorSignal.emit(tr("Error"), tr("File path error"))
            return
        kfpkg = self.KFPKG()
        try:
            for path, addr, prefix in files:
                kfpkg.addFile(addr, path, prefix)
        except Exception as e:
            self.errorSignal.emit(tr("Error"), tr("Pack kfpkg fail")+":"+str(e))
            return
        # select saving path
        if not os.path.exists(self.saveKfpkDir):
            self.saveKfpkDir = os.getcwd()
        fileName_choose, filetype = QFileDialog.getSaveFileName(self,  
                                    tr("Save File"),  
                                    self.saveKfpkDir,
                                    "k210 packages (*.kfpkg)")

        if fileName_choose == "":
            self.errorSignal.emit(tr("Error"), tr("File path error"))
            return
        if not fileName_choose.endswith(".kfpkg"):
            fileName_choose += ".kfpkg"
        self.saveKfpkDir = os.path.split(fileName_choose)[0]
        # print("save to ", fileName_choose)
        
        # write kfpkg file
        try:
            kfpkg.save(fileName_choose)
        except Exception as e:
            self.errorSignal.emit(tr("Error"), tr("Pack kfpkg fail")+":"+str(e))
            return
        self.hintSignal.emit(tr("Success"), tr("Save kfpkg success"))

    def selectFile(self, pathobj):
        index = -1
        for i in range(len(self.fileSelectWidgets)):
            if len(self.fileSelectWidgets[i]) >= 4:
                if pathobj == self.fileSelectWidget_Path(i):
                    index = i
        if index == -1:
            return
        tmp = index
        while tmp>=0:
            oldPath = self.fileSelectWidget_Path(tmp).text()
            if oldPath != "":
                break
            tmp -= 1
        if oldPath=="":
            oldPath = os.getcwd()
        fileName_choose, filetype = QFileDialog.getOpenFileName(self,  
                                    tr("SelectFile"),  
                                    oldPath,
                                    "All Files (*);;bin Files (*.bin);;k210 packages (*.kfpkg);;kmodel (*.kmodel);;encrypted kmodle(*.smodel)")   # 设置文件扩展名过滤,用双分号间隔

        if fileName_choose == "":
            return
        if not self.isFileValid(fileName_choose):
            self.errorSignal.emit(tr("Error"), tr("File path error"))
            return
        if self.isKfpkg(fileName_choose):
            self.fileSelectShowKfpkg(index, fileName_choose)
        else:
            self.fileSelectShowBin(index, fileName_choose, prefixAuto=True, closeButton=False)

    def errorHint(self, title, str):
        QMessageBox.critical(self, title, str)
    
    def hint(self, title, str):
        QMessageBox.information(self, title, str)

    def findSerialPort(self):
        self.port_list = list(serial.tools.list_ports.comports())
        return self.port_list

    def portChanged(self):
        self.serialPortCombobox.setCurrentIndex(0)
        self.serialPortCombobox.setToolTip(str(self.portList[0]))

    def detectSerialPort(self):
        if not self.isDetectSerialPort:
            self.isDetectSerialPort = True
            t = threading.Thread(target=self.detectSerialPortProcess)
            t.setDaemon(True)
            t.start()

    def showCombobox(self):
        self.serialPortCombobox.showPopup()

    def isKfpkg(self, name):
        if name.endswith(".kfpkg"):
            return True
        return False

    def isFileValid(self, name):
        if not os.path.exists(name):
            return False
        return True

    def detectSerialPortProcess(self):
        while(1):
            portList = self.findSerialPort()
            if len(portList)>0:
                currText = self.serialPortCombobox.currentText()
                self.serialPortCombobox.clear()
                for i in portList:
                    showStr = str(i[0])+" ("+str(i[1])+")"
                    self.serialPortCombobox.addItem(showStr)
                index = self.serialPortCombobox.findText(currText)
                if index>=0:
                    self.serialPortCombobox.setCurrentIndex(index)
                else:
                    self.serialPortCombobox.setCurrentIndex(0)
                break
            time.sleep(1)
        self.showSerialComboboxSignal.emit()
        self.isDetectSerialPort = False

    def programExitSaveParameters(self):
        paramObj = paremeters_save.ParametersToSave()
        paramObj.board    = self.boardCombobox.currentText()
        paramObj.burnPosition = self.burnPositionCombobox.currentText()
        paramObj.baudRate = self.serailBaudrateCombobox.currentIndex()
        paramObj.skin = self.param.skin
        paramObj.language = translation.current_lang
        path = self.fileSelectWidget_Path(0).text()
        if path.endswith(".kfpkg"):
            paramObj.files.append(path)
        else:
            for i in range(len(self.fileSelectWidgets)):
                try:
                    addr = int(self.fileSelectWidget_Addr(i).text(),16)
                except Exception:
                    continue
                paramObj.files.append( (self.fileSelectWidget_Path(i).text(), addr, self.fileSelectWidget_Prefix(i).isChecked()) )
        if self.slowModeCombobox.currentIndex()==0:
            paramObj.slowMode = True
        else:
            paramObj.slowMode = False
        paramObj.save(parameters.configFilePath)

    def programStartGetSavedParameters(self):
        paramObj = paremeters_save.ParametersToSave()
        paramObj.load(parameters.configFilePath)
        translation.setLanguage(paramObj.language)
        self.param = paramObj

    def updateFrameParams(self):
        pathLen = len(self.param.files)
        if pathLen == 1 and type(self.param.files[0])==str and self.param.files[0].endswith(".kfpkg"):
            self.fileSelectWidget_Path(0).setText(self.param.files[0])
        elif pathLen != 0:
            index = 0
            for path, addr, prefix  in self.param.files:
                prefix = None if (not prefix) else True
                if index!=0:
                    self.addAddFileWidget()
                if pathLen > 1 and index != 0:
                    closeButton = True
                else:
                    closeButton = False
                self.fileSelectShowBin(index, path, addr, prefix, closeButton=closeButton)
                index += 1
        self.boardCombobox.setCurrentText(self.param.board)
        self.burnPositionCombobox.setCurrentText(self.param.burnPosition)
        self.serailBaudrateCombobox.setCurrentIndex(self.param.baudRate)
        if self.param.slowMode:
            self.slowModeCombobox.setCurrentIndex(0)
        else:
            self.slowModeCombobox.setCurrentIndex(1)

    def closeEvent(self, event):
        try:
            self.programExitSaveParameters()
        finally:
            event.accept()

    def langChange(self):
        if self.param.language == translation.language_en:
            translation.setLanguage(translation.language_zh)
            lang = tr("Chinese language")
        else:
            translation.setLanguage(translation.language_en)
            lang = tr("English language")
        
        self.hint(tr("Hint"), tr("Language Changed to ") + lang + "\n"+ tr("Reboot to take effect"))
        self.frameWidget.style().unpolish(self.downloadButton)
        self.frameWidget.style().polish(self.downloadButton)
        self.frameWidget.update()

    def skinChange(self):
        if self.param.skin == 1: # light
            file = open(self.DataPath + '/assets/qss/style-dark.qss', "r")
            self.param.skin = 2
        else: # elif self.param.skin == 2: # dark
            file = open(self.DataPath + '/assets/qss/style.qss', "r")
            self.param.skin = 1
        self.app.setStyleSheet(file.read().replace("$DataPath", self.DataPath))

    def showAbout(self):
        QMessageBox.information(self, tr("About"),"<h1 style='color:#f75a5a';margin=10px;>"+parameters.appName+
                                '</h1><br><b style="color:#08c7a1;margin = 5px;">V'+str(helpAbout.versionMajor)+"."+
                                str(helpAbout.versionMinor)+"."+str(helpAbout.versionDev)+
                                "</b><br><br>"+helpAbout.date+"<br><br>"+helpAbout.strAbout())

    def autoUpdateDetect(self):
        auto = autoUpdate.AutoUpdate()
        if auto.detectNewVersion():
            auto.OpenBrowser()

    def openDevManagement(self):
        os.system('start devmgmt.msc')

    def updateProgress(self, fileTypeStr, current, total, speedStr):
        currBurnPos = self.burnPositionCombobox.currentText()
        if currBurnPos == tr("SRAM") or currBurnPos == tr_en("SRAM"):
            fileTypeStr = tr("ToSRAM")
        percent = current/float(total)*100
        hint = "<font color=%s>%s %s:</font>   <font color=%s> %.2f%%</font>   <font color=%s> %s</font>" %("#ff7575", tr("Downloading"), fileTypeStr, "#2985ff", percent, "#1aac2d", speedStr)
        self.progressHint.setText(hint)
        self.progressbar.setValue(percent)
    
    def updateProgressPrint(self, str):
        self.statusBarStauts.setText(str)

    def kflash_py_printCallback(self, *args, end = "\n"):
        msg = ""
        for i in args:
            msg += str(i)
        msg.replace("\n", " ")
        self.updateProgressPrintSignal.emit(msg)

    def progress(self, fileTypeStr, current, total, speedStr):
        self.updateProgressSignal.emit(fileTypeStr, current, total, speedStr)

    def download(self):
        if self.burning:
            self.terminateBurn()
            return
        tmpFile = ""
        fileType, filesInfo = self.getBurnFilesInfo()
        if not fileType or not filesInfo:
            self.errorSignal.emit(tr("Error"), tr("File path error"))
            return
        if fileType == "kfpkg":
            filename = filesInfo
        else:#generate kfpkg
            tmpFile = os.path.join(tempfile.gettempdir(), "kflash_gui_tmp.kfpkg")
            kfpkg = self.KFPKG()
            try:
                for path, addr, prefix in filesInfo:
                    kfpkg.addFile(addr, path, prefix)
                kfpkg.save(tmpFile)
            except Exception as e:
                os.remove(tmpFile)
                self.errorSignal.emit(tr("Error"), tr("Pack kfpkg fail")+":"+str(e))
                return
            filename = os.path.abspath(tmpFile)
        
        self.burning = True
        # if not self.checkFileName(filename):
        #     self.errorSignal.emit(tr("Error"), tr("FilePathError"))
        #     self.burning = False
        #     return
        color = False
        board = "dan"
        boardText = self.boardCombobox.currentText()
        if boardText == parameters.SipeedMaixGo:
            board = "goE"
        elif boardText == parameters.SipeedMaixGoD:
            board = "goD"
        elif boardText == parameters.SipeedMaixduino:
            board = "maixduino"
        elif boardText == parameters.SipeedMaixBit:
            board = "bit"
        elif boardText == parameters.SipeedMaixBitMic:
            board = "bit_mic"
        elif boardText == parameters.KendryteKd233:
            board = "kd233"
        elif boardText == parameters.kendryteTrainer:
            board = "trainer"
        elif boardText == parameters.Auto:
            board = None

        sram = False
        if self.burnPositionCombobox.currentText()==tr("SRAM") or \
            self.burnPositionCombobox.currentText()==tr_en("SRAM"):
            sram = True
        try:
            baud = int(self.serailBaudrateCombobox.currentText())
        except Exception:
            self.errorSignal.emit(tr("Error"), tr("BaudrateError"))
            self.burning = False
            return
        dev = ""
        try:
            dev  = self.serialPortCombobox.currentText().split()[0]
        except Exception:
            pass
        if dev=="":
            self.errorSignal.emit(tr("Error"), tr("PleaseSelectSerialPort"))
            self.burning = False
            return
        slow = self.slowModeCombobox.currentIndex()==0
        # hide setting widgets
        self.setFrameStrentch(1)
        self.settingWidget.hide()
        self.progressbar.setValue(0)
        self.progressbar.setGeometry(10, 0, self.downloadWidget.width()-25, 40)
        self.progressbarRootWidget.show()
        self.progressHint.show()
        self.downloadButton.setText(tr("Cancel"))
        self.downloadButton.setProperty("class", "redbutton")
        self.downloadButton.style().unpolish(self.downloadButton)
        self.downloadButton.style().polish(self.downloadButton)
        self.downloadButton.update()
        self.statusBarStauts.setText("<font color=%s>%s ...</font>" %("#1aac2d", tr("Downloading")))
        hint = "<font color=%s>%s</font>" %("#ff0d0d", tr("DownloadStart"))
        self.progressHint.setText(hint)
        # download
        self.burnThread = threading.Thread(target=self.flashBurnProcess, args=(dev, baud, board, sram, filename, self.progress, tmpFile!="", color, slow))
        self.burnThread.setDaemon(True)
        self.burnThread.start()

    def flashBurnProcess(self, dev, baud, board, sram, filename, callback, cleanFile, color, slow):
        success = True
        errMsg = ""
        try:
            if board:
                self.kflash.process(terminal=False, dev=dev, baudrate=baud, board=board, sram = sram, file=filename, callback=callback, noansi=not color, slow_mode=slow)
            else:
                self.kflash.process(terminal=False, dev=dev, baudrate=baud, sram = sram, file=filename, callback=callback, noansi=not color, slow_mode=slow)
        except Exception as e:
            errMsg = str(e)
            if str(e) != "Burn SRAM OK":
                success = False
        if cleanFile:
            os.remove(filename)
        if success:
            self.downloadResultSignal.emit(True, errMsg)
        else:
            self.downloadResultSignal.emit(False, errMsg)
            

    def downloadResult(self, success, msg):
        if success:
            self.hintSignal.emit(tr("Success"), tr("DownloadSuccess"))
            self.statusBarStauts.setText("<font color=%s>%s</font>" %("#1aac2d", tr("DownloadSuccess")))
        else:
            if msg == "Cancel":
                self.statusBarStauts.setText("<font color=%s>%s</font>" %("#ff1d1d", tr("DownloadCanceled")))
            else:
                msg = tr("ErrorSettingHint") + "\n\n"+msg
                self.errorSignal.emit(tr("Error"), msg)
                self.statusBarStauts.setText("<font color=%s>%s</font>" %("#ff1d1d", tr("DownloadFail")))
            self.progressHint.setText("")
        self.downloadButton.setText(tr("Download"))
        self.downloadButton.setProperty("class", "normalbutton")
        self.downloadButton.style().unpolish(self.downloadButton)
        self.downloadButton.style().polish(self.downloadButton)
        self.downloadButton.update()
        self.setFrameStrentch(0)
        self.progressbarRootWidget.hide()
        self.progressHint.hide()
        self.settingWidget.show()
        self.burning = False

    def terminateBurn(self):
        hint = "<font color=%s>%s</font>" %("#ff0d0d", tr("DownloadCanceling"))
        self.progressHint.setText(hint)
        self.kflash.kill()