Пример #1
0
 def _createButtons(self):
     """Create the buttons."""
     self.buttons = {}
     buttonsLayout = QGridLayout()
     # Button text | position on the QGridLayout
     buttons = {
         "7": (0, 0),
         "8": (0, 1),
         "9": (0, 2),
         "/": (0, 3),
         "C": (0, 4),
         "4": (1, 0),
         "5": (1, 1),
         "6": (1, 2),
         "*": (1, 3),
         "(": (1, 4),
         "1": (2, 0),
         "2": (2, 1),
         "3": (2, 2),
         "-": (2, 3),
         ")": (2, 4),
         "0": (3, 0),
         "00": (3, 1),
         ".": (3, 2),
         "+": (3, 3),
         "=": (3, 4),
     }
     # Create the buttons and add them to the grid layout
     for btnText, pos in buttons.items():
         self.buttons[btnText] = QPushButton(btnText)
         self.buttons[btnText].setFixedSize(40, 40)
         buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1])
     # Add buttonsLayout to the general layout
     self.generalLayout.addLayout(buttonsLayout)
Пример #2
0
class App(QDialog):
    def __init__(self):
        app = QApplication(sys.argv)
        super().__init__()
        self.setWindowTitle('PyQt6 Grid Layout')
        self.setGeometry(100, 100, 320, 100)
        self.CreateGridLayout()

        self.windowLayout = QVBoxLayout()
        self.windowLayout.addWidget(self.horizontalGroupBox)
        self.setLayout(self.windowLayout)

        self.show()
        sys.exit(app.exec())

    def CreateGridLayout(self):
        self.horizontalGroupBox = QGroupBox("Grid")
        self.layout = QGridLayout()
        self.layout.setColumnStretch(2, 4)
        self.layout.setColumnStretch(1, 4)

        for label in "123456789":
            self.MakeButton(label)

        self.horizontalGroupBox.setLayout(self.layout)

    def MakeButton(self, label):
        button = QPushButton(label)
        button.clicked.connect(lambda: self.on_click(button))
        self.layout.addWidget(button)

    def on_click(self, pushButton):
        print('PyQt5 {0} button clicked.'.format(pushButton.text()))
Пример #3
0
class Manual(QWidget):
    def __init__(self, parent=None):
        super(Manual, self).__init__()
        self.manual = QWebEngineView()
        webpage = QtCore.QUrl('https://wingtorres.github.io/morphometrix/')
        self.manual.setUrl(webpage)
        self.grid = QGridLayout()
        self.grid.addWidget(self.manual,1,0)
        self.setLayout(self.grid)
Пример #4
0
    def __init__(self, parent=None):
        super(MainWidget, self).__init__(parent)
        self.setWindowTitle("QThread Demo")
        self.thread = Worker()
        self.listFile = QListWidget()
        self.buttonStart = QPushButton("开始")
        layout = QGridLayout(self)
        layout.addWidget(self.listFile, 0, 0, 1, 2)
        layout.addWidget(self.buttonStart, 1, 1)

        self.buttonStart.clicked.connect(self.slotStart)
        self.thread.sinOut.connect(self.slodAdd)
Пример #5
0
 def show_setting(self, conf: dict, layout: QGridLayout):
     groups = list()
     x = 0
     y = 0
     shape = 3
     for key in conf.keys():
         if type(conf[key]) == bool or type(conf[key]) == str:
             continue
         conf_title = conf[key]["title"]
         conf_enabled = conf[key]["enabled"]
         conf_times = conf[key]["times"]
         group = QGroupBox(conf_title)
         group.setStyleSheet("QGroupBox{border-radius:5px;}")
         group.setToolTip(conf_title + "  的设置")
         enabled = QCheckBox("启用")
         enabled.setObjectName(key)
         enabled.setToolTip("单击切换开关状态")
         enabled.setChecked(conf_enabled)
         enabled.setStyleSheet(
             "QCheckBox::indicator{width:10px;height:10px;border:none;border-radius:5px;background:#9BE3DE;}QCheckBox::indicator:unchecked{background:#BEEBE9;}QCheckBox::indicator:unchecked:hover{background:#9AD3BC;}QCheckBox::indicator:checked{background:#95E1D3;}QCheckBox::indicator:checked:hover{background:#98DED9;}"
         )
         times = QHBoxLayout()
         times_label = QLabel("次数:")
         times_label.setStyleSheet(
             "QLabel{background:transparent;border:none;border-radius:5px;}"
         )
         times_input = EnhancedEdit()
         times_input.setObjectName(key)
         times_input.setText(str(conf_times))
         times_input.setToolTip("仅限正整数")
         times_input.setValidator(
             QRegularExpressionValidator(
                 QRegularExpression("^[1-9][0-9]{1,8}$")))
         times_input.setStyleSheet(
             "QLineEdit{border:1px solid #F3EAC2;border-radius:5px;background:transparent;}QLineEdit:hover{border:1px solid #F5B461;}"
         )
         times.addWidget(times_label)
         times.addWidget(times_input)
         group_layout = QVBoxLayout()
         group_layout.addWidget(enabled)
         group_layout.addLayout(times)
         group.setLayout(group_layout)
         group.setObjectName(key)
         groups.append(group)
     for group in groups:
         if y >= shape:
             x = x + 1
             y = 0
         layout.addWidget(group, x, y)
         y = y + 1
     self.logger.debug("最后的元素位置:(%d,%d)" % (x, y))
     return (x, y)
Пример #6
0
def makeActions(app):
    actionsLayout = QGridLayout()
    actionsLayout.setVerticalSpacing(5)

    actionsLayout.setRowMinimumHeight(0, 30)
    actionsLayout.setRowMinimumHeight(1, 18)
    actionsLayout.setRowMinimumHeight(2, 50)

    signI = QPushButton("IN")
    signO = QPushButton("OUT")
    signI.setSizePolicy(QSizePolicy.Policy.Expanding,
                        QSizePolicy.Policy.Expanding)
    signI.setStyleSheet(
        'QPushButton {background-color: green; color: white; font-size: 28pt; font-weight: bold}'
    )
    signO.setSizePolicy(QSizePolicy.Policy.Expanding,
                        QSizePolicy.Policy.Expanding)
    signO.setStyleSheet(
        'QPushButton {background-color: red; color: white; font-size: 28pt; font-weight: bold}'
    )

    def doIO(io):
        if currentTable != None and lastSelectedRow != None:
            timeManager.signIO(
                currentTable.item(lastSelectedRow, 0).text(), io)
        else:
            print("No item", currentTable != None, lastSelectedRow != None)
        updateNamesTable()

    signI.clicked.connect(lambda: doIO("i"))
    signO.clicked.connect(lambda: doIO("o"))

    more = QPushButton("More user information")
    newUser = QPushButton("New User")
    graph = QPushButton("Graph")
    update = QPushButton("Update")
    quit = QPushButton("Quit")
    more.setSizePolicy(QSizePolicy.Policy.Minimum,
                       QSizePolicy.Policy.Expanding)
    newUser.setSizePolicy(QSizePolicy.Policy.Minimum,
                          QSizePolicy.Policy.Expanding)
    graph.setSizePolicy(QSizePolicy.Policy.Minimum,
                        QSizePolicy.Policy.Expanding)
    update.setSizePolicy(QSizePolicy.Policy.Minimum,
                         QSizePolicy.Policy.Expanding)
    quit.setSizePolicy(QSizePolicy.Policy.Minimum,
                       QSizePolicy.Policy.Expanding)
    quit.setStyleSheet('QPushButton {color: red}')

    update.clicked.connect(updateNamesTable)
    quit.clicked.connect(lambda: app.closeAllWindows())

    actionsLayout.addWidget(signI, 0, 0, 3, 2)
    actionsLayout.addWidget(signO, 0, 2, 3, 2)
    # actionsLayout.addWidget(more, 0, 4, 2, 1)
    actionsLayout.addWidget(newUser, 2, 4)
    # actionsLayout.addWidget(graph, 0, 5)
    actionsLayout.addWidget(update, 1, 5)
    actionsLayout.addWidget(quit, 2, 5)
    return actionsLayout
Пример #7
0
class Workstation(QWidget):
    def __init__(self, parent, top):
        super(QWidget, self).__init__(parent)
        self.top = top
        hlayout = QHBoxLayout()
        self.layout = QGridLayout()
        hlayout.addLayout(self.layout)
        hlayout.setAlignment(hlayout, Qt.Alignment.AlignTop)
        self.setLayout(hlayout)
        self.row = 0

        self.__addLabel__("Federate Name")
        self.federateName = QLineEdit('REMOTE_WORKSTATION')
        self.__addInput__(self.federateName)

        self.__addLabel__("Message Directory Cache")
        self.messageDirectoryCache = QLineEdit(self)
        self.__addInputAndSelect__(self.messageDirectoryCache, self.top)

        self.__addLabel__("Map Data Cache")
        self.mapDataCache = QLineEdit(self)
        self.__addInputAndSelect__(self.mapDataCache, self.top)

        self.__addLabel__("Raster Map Cache")
        self.rasterMapCache = QLineEdit(self)
        self.__addInputAndSelect__(self.rasterMapCache, self.top)

        self.__addLabel__("Remote Control Location")
        self.remoteControlLocation = QLineEdit(self)
        self.__addInputAndSelect__(self.remoteControlLocation, self.top)

    def __addLabel__(self, label):
        lbl = QLabel(label)
        self.layout.addWidget(lbl, self.row, 0, 1, -1)
        self.row += 1

    def __addInput__(self, input):
        self.layout.addWidget(input, self.row, 0, 1, 4)
        self.row += 1

    def __addSelect__(self, input):
        self.layout.addWidget(BrowseButton(self, input), self.row - 1, 4, 1, 1)

    def __addInputAndSelect__(self, input, top):
        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 0, 0)
        hbox.addWidget(input)
        browseButton = BrowseButton(self, input, top)
        browseButton.adjustSize()
        hbox.addWidget(browseButton)
        widget = QWidget(self)
        widget.setLayout(hbox)
        self.layout.addWidget(widget, self.row, 0, 1, -1)
        self.row += 1

    def tabName(self):
        return 'Workstation'
Пример #8
0
    def initUI(self):

        grid = QGridLayout()

        x = 0
        y = 0

        self.text = f'x: {x},  y: {y}'

        self.label = QLabel(self.text, self)
        grid.addWidget(self.label, 0, 0, Qt.AlignmentFlag.AlignTop)

        self.setMouseTracking(True)
        self.setLayout(grid)

        self.setGeometry(300, 300, 450, 300)
        self.setWindowTitle('Event object')
        self.show()
Пример #9
0
    def __init__(self, parent=None):
        super(WinForm, self).__init__(parent)
        self.setWindowTitle("QTimer demo")
        self.listFile = QListWidget()
        self.label = QLabel("显示当前时间")
        self.startButton = QPushButton("开始")
        self.endButton = QPushButton("结束")
        layout = QGridLayout(self)

        # 初始化定时器
        self.timer = QTimer(self)
        # 显示时间
        self.timer.timeout.connect(
            self.showTime)  # timeout 信号连接到特定的槽,当定时器超时,发出 timeout 信号

        layout.addWidget(self.label, 0, 0, 1, 2)
        layout.addWidget(self.startButton, 1, 0)
        layout.addWidget(self.endButton, 1, 1)

        self.startButton.clicked.connect(self.start_timer)
        self.endButton.clicked.connect(self.end_timer)

        self.setLayout(layout)
Пример #10
0
 def __init__(self):
     super(MainUi, self).__init__()
     self.setFixedSize(600,500)
     self.setWindowTitle("妹子图爬虫工具  version: 1.0.0 ")
     self.download_progressbar = QProgressBar()
     self.download_progressbar.setAlignment(QtCore.Qt.Alignment.AlignCenter)#文字居中
     self.download_progressbar.setStyleSheet(".QProgressBar::chunk { background-color: red;}")#背景
     self.download_progressbar.setValue(100)
     label01 = QLabel("下载URL:")
     label02 = QLabel("下载目录:")
     self.url_input    = QLineEdit()
     self.url_input.setText("https://www.mzitu.com/221746")
     self.url_input.setContentsMargins(0,0,0,0)
     self.download_dir = QLineEdit()
     self.download_dir.setContentsMargins(0,0,0,0)
     self.start_btn    = QPushButton("开始爬虫")
     self.start_btn.setFixedHeight(50)
     self.start_btn.setContentsMargins(0,0,0,0)
     inputlayout = QGridLayout()
     inputlayout.addWidget(label01, 0, 0) #第0行 0列
     inputlayout.addWidget(label02, 1, 0)
     inputlayout.addWidget(self.url_input, 0, 1)
     inputlayout.addWidget(self.download_dir, 1, 1)
     inputlayout.addWidget(self.start_btn, 0, 2, 2,1,QtCore.Qt.Alignment.AlignRight) #起始行,起始列, 占行数,占列数
     inputlayout.setColumnStretch(0, 1)  #设置每一列比例
     inputlayout.setColumnStretch(1, 10)
     inputlayout.setColumnStretch(2, 1)
     vlayout = QVBoxLayout()
     vlayout.addLayout(inputlayout)
     vlayout.addWidget(self.download_progressbar)
     self.frame = QFrame()
     self.frame.setFixedHeight(400)
     vlayout.addWidget(self.frame)
     vlayout.addStretch()
     inputlayout.setContentsMargins(0,0,0,0)
     vlayout01 = QVBoxLayout()
     self.frame.setLayout(vlayout01)
     self.qtablewidget = QTableWidget(1,3)
     self.qtablewidget.setHorizontalHeaderLabels(['目录','下载图片总数目', '删除'])
     vlayout01.addWidget(self.qtablewidget)
     self.qtablewidget.setColumnWidth(0, 358)  # 将第0列的单元格,设置成300宽度
     self.qtablewidget.setColumnWidth(1, 100 )  # 将第0列的单元格,设置成50宽度
     self.qtablewidget.verticalHeader().setVisible(False) #隐藏水平表头
     #self.qtablewidget.setDisabled(True) #设置不可编辑
     self.setLayout(vlayout)
     self.current_index = 0
Пример #11
0
    def initUI(self):

        grid = QGridLayout()
        self.setLayout(grid)

        names = ['Cls', 'Bck', '', 'Close',
                 '7', '8', '9', '/',
                 '4', '5', '6', '*',
                 '1', '2', '3', '-',
                 '0', '.', '=', '+']

        positions = [(i, j) for i in range(5) for j in range(4)]

        for position, name in zip(positions, names):

            if name == '':
                continue

            button = QPushButton(name)
            grid.addWidget(button, *position)

        self.move(300, 150)
        self.setWindowTitle('Calculator')
        self.show()
Пример #12
0
    def createLayout(self):
        self.groupBox = QGroupBox(
            "What is your favorite programming language?")

        gridLayout = QGridLayout()

        button1 = QPushButton("Python", self)
        gridLayout.addWidget(button1, 0, 0)

        button2 = QPushButton("C++", self)
        gridLayout.addWidget(button2, 0, 1)

        button3 = QPushButton("Java", self)
        gridLayout.addWidget(button3, 1, 0)

        button4 = QPushButton("C#", self)
        gridLayout.addWidget(button4, 1, 1)

        self.groupBox.setLayout(gridLayout)
Пример #13
0
class SettingWindow(QDialog):
    def __init__(self, parent: QWidget):
        super().__init__()
        self.logger = logging.getLogger(__name__)
        with open(file="config.json", mode="r",
                  encoding="utf-8") as conf_reader:
            self.conf = json.loads(conf_reader.read())
        self.logger.debug("初始化设置界面。设置内容:%s" % self.conf)
        layout = QGridLayout()
        self.setLayout(layout)
        self.setModal(True)
        self.setParent(parent)
        self.resize(400, 300)
        title = QLabel("设置")
        title.setStyleSheet(
            "QLabel{border:none;border-radius:5px;background:transparent;color:#9AD3BC;font-size:20px;}"
        )
        title.setAlignment(Qt.Alignment.AlignCenter)
        layout.addWidget(title, 0, 1, Qt.Alignment.AlignCenter)
        control_close = QPushButton()
        control_close.setStyleSheet(
            "QPushButton{background:#FFE3ED;border-radius:5px;border:none;}QPushButton:hover{background:#EC524B;}"
        )
        control_close.setToolTip("关闭")
        control_close.setFixedHeight(20)
        control_close.clicked.connect(self.close_callback)
        layout.addWidget(control_close, 0, 0)
        debug_check = QCheckBox("调试模式")
        debug_check.setChecked(self.conf["debug"])
        debug_check.setToolTip("单击切换开关状态")
        debug_check.setStyleSheet(
            "QCheckBox::indicator{width:10px;height:10px;border:none;border-radius:5px;background:#9BE3DE;}QCheckBox::indicator:unchecked{background:#BEEBE9;}QCheckBox::indicator:unchecked:hover{background:#9AD3BC;}QCheckBox::indicator:checked{background:#95E1D3;}QCheckBox::indicator:checked:hover{background:#98DED9;}"
        )
        self.content = QGridLayout()
        (x, y) = self.show_setting(conf=self.conf,
                                   layout=self.content)  # 返回content的最后一个元素的x,y
        proxy = QGroupBox()
        proxy.setObjectName("proxy")
        proxy_layout = QVBoxLayout()
        proxy_label = QLabel("代理地址:")
        proxy_label.setStyleSheet(
            "QLabel{background:transparent;border:none;}")
        proxy_input = EnhancedEdit()
        proxy_input.setText(self.conf["proxy"])
        proxy_input.setToolTip("格式为协议://IP:端口,留空保持直连")
        proxy_input.setStyleSheet(
            "QLineEdit{border:1px solid #F3EAC2;border-radius:5px;background:transparent;}QLineEdit:hover{border:1px solid #F5B461;}"
        )
        proxy_layout.addWidget(proxy_label)
        proxy_layout.addWidget(proxy_input)
        proxy.setLayout(proxy_layout)
        proxy.setStyleSheet("QGroupBox{border-radius:5px;}")
        proxy.setToolTip("代理设置")
        if y + 1 >= 3:
            y_ = 0
            x_ = x + 1
        else:
            y_ = y + 1
            x_ = x
        self.content.addWidget(proxy, x_, y_)
        self.content.addWidget(debug_check)
        layout.addLayout(self.content, 1, 1)

    def close_callback(self):
        self.save_settings()
        self.logger.debug("已保存设置")
        self.close()

    def save_settings(self):
        settings = dict()
        enabled = True
        times = 1
        for i in range(self.content.count()):
            layoutitem = self.content.itemAt(i)
            if type(layoutitem.widget()) == QCheckBox:
                settings["debug"] = layoutitem.widget().isChecked()
            elif type(layoutitem.widget()) == QGroupBox:
                group = layoutitem.widget()
                for j in group.children():
                    if group.objectName() == "proxy":
                        data = ""
                        if type(j) == EnhancedEdit:
                            data = str(j.text())
                    else:
                        if type(j) == QCheckBox:
                            enabled = j.isChecked()
                        elif type(j) == EnhancedEdit:
                            times = int(j.text())
                        data = {
                            "title": group.title(),
                            "enabled": enabled,
                            "times": times
                        }
                    settings[group.objectName()] = data
        self.logger.debug("设置数据:%s" % settings)
        with open(file="config.json", mode="w",
                  encoding="utf-8") as conf_writer:
            conf_writer.write(
                json.dumps(settings,
                           ensure_ascii=False,
                           sort_keys=True,
                           indent=4))

    def show_setting(self, conf: dict, layout: QGridLayout):
        groups = list()
        x = 0
        y = 0
        shape = 3
        for key in conf.keys():
            if type(conf[key]) == bool or type(conf[key]) == str:
                continue
            conf_title = conf[key]["title"]
            conf_enabled = conf[key]["enabled"]
            conf_times = conf[key]["times"]
            group = QGroupBox(conf_title)
            group.setStyleSheet("QGroupBox{border-radius:5px;}")
            group.setToolTip(conf_title + "  的设置")
            enabled = QCheckBox("启用")
            enabled.setObjectName(key)
            enabled.setToolTip("单击切换开关状态")
            enabled.setChecked(conf_enabled)
            enabled.setStyleSheet(
                "QCheckBox::indicator{width:10px;height:10px;border:none;border-radius:5px;background:#9BE3DE;}QCheckBox::indicator:unchecked{background:#BEEBE9;}QCheckBox::indicator:unchecked:hover{background:#9AD3BC;}QCheckBox::indicator:checked{background:#95E1D3;}QCheckBox::indicator:checked:hover{background:#98DED9;}"
            )
            times = QHBoxLayout()
            times_label = QLabel("次数:")
            times_label.setStyleSheet(
                "QLabel{background:transparent;border:none;border-radius:5px;}"
            )
            times_input = EnhancedEdit()
            times_input.setObjectName(key)
            times_input.setText(str(conf_times))
            times_input.setToolTip("仅限正整数")
            times_input.setValidator(
                QRegularExpressionValidator(
                    QRegularExpression("^[1-9][0-9]{1,8}$")))
            times_input.setStyleSheet(
                "QLineEdit{border:1px solid #F3EAC2;border-radius:5px;background:transparent;}QLineEdit:hover{border:1px solid #F5B461;}"
            )
            times.addWidget(times_label)
            times.addWidget(times_input)
            group_layout = QVBoxLayout()
            group_layout.addWidget(enabled)
            group_layout.addLayout(times)
            group.setLayout(group_layout)
            group.setObjectName(key)
            groups.append(group)
        for group in groups:
            if y >= shape:
                x = x + 1
                y = 0
            layout.addWidget(group, x, y)
            y = y + 1
        self.logger.debug("最后的元素位置:(%d,%d)" % (x, y))
        return (x, y)
Пример #14
0
 def __init__(self):
     super().__init__()
     self.setWindowTitle('GitHub Abuz!')
     self.setWindowIcon(QIcon('icon.png'))
     layout = QGridLayout()
     vl = QVBoxLayout()
     hl = QHBoxLayout()
     hl2 = QHBoxLayout()
     hl3 = QHBoxLayout()
     self.y = QComboBox()
     self.name = QLineEdit()
     self.email = QLineEdit()
     self.passw = QLineEdit()
     self.repo = QLineEdit()
     self.type = QLineEdit()
     self.fonts = QComboBox()
     self.err = QMessageBox()
     self.nc = QSpinBox()
     lbl = QLabel('Commits/day:')
     prev = QPushButton('Translate')
     invert = QPushButton('Invert')
     leggo = QPushButton('Do it')
     invert.clicked.connect(self.invert)
     leggo.clicked.connect(self.doit)
     prev.clicked.connect(self.textCheck)
     self.name.textChanged[str].connect(self.rmph)
     self.email.textChanged[str].connect(self.rmph)
     self.passw.textChanged[str].connect(self.rmph)
     self.type.textChanged[str].connect(self.rmph)
     self.repo.textChanged[str].connect(self.rmph)
     self.y.addItem('Year (default: last 52 weeks)')
     for yr in range(datetime.datetime.now().year + 5,
                     datetime.datetime.now().year - 20, -1):
         self.y.addItem(str(yr))
     self.fonts.addItems(os.listdir('Fonts'))
     self.name.setPlaceholderText('Committer name')
     self.email.setPlaceholderText('Committer email')
     self.passw.setPlaceholderText('Password')
     self.passw.setEchoMode(QLineEdit.EchoMode.Password)
     self.repo.setPlaceholderText('Link to repo')
     self.type.setPlaceholderText('Translate text to tile art!')
     self.nc.setMinimum(1)
     self.nc.setValue(1)
     self.err.setWindowIcon(QIcon('icon.png'))
     self.err.setWindowTitle('Error!')
     hl.addWidget(self.name)
     hl.addWidget(self.email)
     hl.addWidget(self.passw)
     hl3.addWidget(self.repo)
     hl3.addWidget(self.y)
     hl3.addWidget(lbl)
     hl3.addWidget(self.nc)
     hl2.addWidget(self.type)
     hl2.addWidget(self.fonts)
     hl2.addWidget(prev)
     hl2.addWidget(invert)
     vl.addLayout(hl)
     vl.addLayout(hl3)
     vl.addLayout(layout)
     vl.addLayout(hl2)
     vl.addWidget(leggo)
     self.setLayout(vl)
     self.checkM = [list() for i in range(7)]
     for i in range(7):
         for j in range(52):
             m = QCheckBox()
             layout.addWidget(m, i, j)
             self.checkM[i].append(m)
Пример #15
0
class Ui(QWidget):
    def __init__(self):

        logger.debug('Ui class initializing')

        self.eog = False
        self.app = QApplication([])

        super().__init__()

        self.field = []
        self.layout = QGridLayout()
        self.gui_init()

    def gui_init(self):
        logger.debug('GUI initialization')
        self.setWindowTitle(f'{APP_NAME} {APP_VERSION}')
        self.setWindowIcon(QIcon('media/icon.png'))
        for x in range(SIZE):
            row = []
            for y in range(SIZE):
                btn = QPushButton(text=f'')
                btn.setFixedWidth(BUTTON_WIDTH)
                btn.setFixedHeight(BUTTON_HEIGHT)
                btn.setAccessibleName(f'{x}/{y}')
                btn.setStyleSheet(REGULAR)

                btn.clicked.connect(self.on_click)
                row.append(btn)

                self.layout.addWidget(btn, x, y)

            self.field.append(row)

        self.setLayout(self.layout)
        logger.debug('GUI initialized')

    @pyqtSlot()
    def on_click(self):
        if self.eog:
            logger.debug('Performing field reset')
            self.eog = False

            for x in range(SIZE):
                for y in range(SIZE):
                    self.field[x][y].setText('')
                    self.field[x][y].setStyleSheet(REGULAR)

            return

        if self.sender().text() == '':
            self.sender().setText(HUM_SMB)
        else:
            return

        self.check_win()

        if not self.eog:
            self.move_it()

    def move_it(self):
        logger.debug('Performing move')

        self.check_win()

        if self.check_pairs(me=True):
            logger.debug('Used my pair rule')
            pass
        elif self.check_pairs(me=False):
            logger.debug('Used enemy pair rule')
            pass
        elif self.check_cc():
            pass
        else:
            logger.debug('Used set any rule')
            self.set_any()

        logger.debug('Checking winning combinations')
        self.check_win()

    def check_win(self):
        for x in range(SIZE):
            if self.field[0][x].text() == self.field[1][x].text(
            ) == self.field[2][x].text() != '':

                if self.field[0][x].text() == HUM_SMB:
                    logger.debug('Human won')
                    style = WIN
                else:
                    logger.debug('UI won')
                    style = LOOSE

                self.field[0][x].setStyleSheet(style)
                self.field[1][x].setStyleSheet(style)
                self.field[2][x].setStyleSheet(style)

                self.eog = True

            if self.field[x][0].text() == self.field[x][1].text(
            ) == self.field[x][2].text() != '':

                if self.field[0][x].text() == HUM_SMB:
                    logger.debug('Human won')
                    style = WIN
                else:
                    logger.debug('UI won')
                    style = LOOSE

                self.field[x][0].setStyleSheet(style)
                self.field[x][1].setStyleSheet(style)
                self.field[x][2].setStyleSheet(style)

                self.eog = True

        if self.field[0][0].text() == self.field[1][1].text(
        ) == self.field[2][2].text() != '':

            if self.field[0][0].text() == HUM_SMB:
                logger.debug('Human won')
                style = WIN
            else:
                logger.debug('UI won')
                style = LOOSE

            self.field[0][0].setStyleSheet(style)
            self.field[1][1].setStyleSheet(style)
            self.field[2][2].setStyleSheet(style)

            self.eog = True

        if self.field[0][2].text() == self.field[1][1].text(
        ) == self.field[2][0].text() != '':

            if self.field[0][2].text() == HUM_SMB:
                logger.debug('Human won')
                style = WIN
            else:
                logger.debug('UI won')
                style = LOOSE

            self.field[0][2].setStyleSheet(style)
            self.field[1][1].setStyleSheet(style)
            self.field[2][0].setStyleSheet(style)

            self.eog = True

    def check_pairs(self, me: bool):

        if me:
            symbol = II_SMB
        else:
            symbol = HUM_SMB

        for x in range(SIZE):
            for y in range(SIZE):

                logger.debug(f'Processing coordinates: {x} {y}')

                logger.debug(
                    f'Checking: ({x}-{y}) == ({(1 + x) % SIZE}-{y}) == {symbol}'
                )
                if self.field[x][y].text() == self.field[(1 + x) % SIZE][y].text() == symbol and \
                        self.field[(2 + x) % SIZE][y].text() == '':
                    self.field[(2 + x) % SIZE][y].setText(II_SMB)

                    logger.debug(
                        f'Pair rule: ({x}-{y}) == ({(1 + x) % SIZE}-{y}) == {symbol}'
                    )

                    return True

                logger.debug(
                    f'Checking: ({y}-{x}) == ({y}-{(1 + x) % SIZE}) == {symbol}'
                )
                if self.field[y][x].text() == self.field[y][(1 + x) % SIZE].text() == symbol and \
                        self.field[y][(2 + x) % SIZE].text() == '':
                    self.field[y][(2 + x) % SIZE].setText(II_SMB)

                    logger.debug(
                        f'Pair rule: ({y}-{x}) == ({y}-{(1 + x) % SIZE}) == {symbol}'
                    )

                    return True

            logger.debug(
                f'Checking: ({x}-{x}) == ({(1 + x) % SIZE}-{(1 + x) % SIZE}) == {symbol}'
            )
            if self.field[x][x].text() == self.field[(1 + x) % SIZE][(1 + x) % SIZE].text() == symbol and \
                    self.field[(2 + x) % SIZE][(2 + x) % SIZE].text() == '':
                self.field[(2 + x) % SIZE][(2 + x) % SIZE].setText(II_SMB)

                logger.debug(
                    f'Pair rule: ({x}-{x}) == ({(1 + x) % SIZE}-{(1 + x) % SIZE}) == {symbol}'
                )

                return True

            logger.debug(
                f'Checking: ({x}-{(2 - x) % SIZE}) == ({(1 + x) % SIZE}-{(1 - x) % SIZE}) == {symbol}'
            )
            if self.field[x][(2 - x) % SIZE].text() == self.field[(1 + x) % SIZE][(1 - x) % SIZE].text() == symbol and \
                    self.field[(2 + x) % SIZE][(- x) % SIZE].text() == '':
                self.field[(2 + x) % SIZE][(-x) % SIZE].setText(II_SMB)

                logger.debug(
                    f'Pair rule: ({x}-{(2 - x) % SIZE}) == ({(1 + x) % SIZE}-{(1 - x) % SIZE}) == {symbol}'
                )

                return True

        return False

    def check_cc(self):
        if self.field[1][1].text() == '':
            self.field[1][1].setText(II_SMB)
            logger.debug('Used center rule')
            return True
        elif self.field[1][1].text() == II_SMB and (
                self.field[0][0].text() == self.field[2][2].text() == HUM_SMB
                or
                self.field[0][2].text() == self.field[2][0].text() == HUM_SMB):
            logger.debug('XOX diagonal detected, making side move')
            if self.field[0][1].text() == '':
                self.field[0][1].setText(II_SMB)
                return True

            elif self.field[1][2].text() == '':
                self.field[1][2].setText(II_SMB)
                return True

            elif self.field[1][0].text() == '':
                self.field[1][0].setText(II_SMB)
                return True

            elif self.field[2][1].text() == '':
                self.field[2][1].setText(II_SMB)
                return True

        if self.field[0][0].text() == '':
            self.field[0][0].setText(II_SMB)
            logger.debug('Used corner rule')
            return True

        if self.field[2][2].text() == '':
            self.field[2][2].setText(II_SMB)
            logger.debug('Used corner rule')
            return True

        if self.field[0][2].text() == '':
            self.field[0][2].setText(II_SMB)
            logger.debug('Used corner rule')
            return True

        if self.field[2][0].text() == '':
            self.field[2][0].setText(II_SMB)
            logger.debug('Used corner rule')
            return True

        return False

    def set_any(self):
        for x in range(SIZE - 1):
            for y in range(SIZE - 1):
                if self.field[x][y].text() == '':
                    self.field[x][y].setText(II_SMB)

                    return

        self.set_result(style=DRAW)
        logger.debug('Draw')
        self.eog = True

    def set_result(self, style):
        for x in range(SIZE):
            for y in range(SIZE):
                self.field[x][y].setStyleSheet(style)

    def start(self):
        self.show()
        sys.exit(self.app.exec())
Пример #16
0
class DataGUI(QWidget):
    def __init__(self):
        super().__init__()

        self.experiment_file_name = None
        self.experiment_file_directory = None
        self.data_directory = None
        self.max_rois = 50
        self.roi_type = 'freehand'
        self.roi_radius = None
        self.existing_roi_set_paths = {}

        self.current_roi_index = 0
        self.current_z_slice = 0
        self.current_channel = 1  # index
        self.image_series_name = ''
        self.series_number = None
        self.roi_response = []
        self.roi_mask = []
        self.roi_path = []
        self.roi_image = None
        self.roi_path_list = []

        self.blank_image = np.zeros((1, 1))

        self.colors = [
            mcolors.to_rgb(x) for x in list(mcolors.TABLEAU_COLORS)[:20]
        ]

        self.initUI()

    def initUI(self):
        self.grid = QGridLayout(self)

        self.file_control_grid = QGridLayout()
        self.file_control_grid.setSpacing(3)
        self.grid.addLayout(self.file_control_grid, 0, 0)

        self.file_tree_grid = QGridLayout()
        self.file_tree_grid.setSpacing(3)
        self.grid.addLayout(self.file_tree_grid, 1, 0)

        self.group_control_grid = QGridLayout()
        self.group_control_grid.setSpacing(3)
        self.grid.addLayout(self.group_control_grid, 0, 1)

        self.attribute_grid = QGridLayout()
        self.attribute_grid.setSpacing(3)
        self.grid.addLayout(self.attribute_grid, 1, 1)

        self.roi_control_grid = QGridLayout()
        self.roi_control_grid.setSpacing(3)
        self.grid.addLayout(self.roi_control_grid, 0, 2)

        self.plot_grid = QGridLayout()
        self.plot_grid.setSpacing(3)
        self.grid.addLayout(self.plot_grid, 1, 2)

        # # # # File control browser: # # # # # # # # (0,0)
        loadButton = QPushButton("Load expt. file", self)
        loadButton.clicked.connect(self.selectDataFile)
        # Label with current expt file
        self.currentExperimentLabel = QLabel('')
        self.file_control_grid.addWidget(loadButton, 0, 0)
        self.file_control_grid.addWidget(self.currentExperimentLabel, 1, 0)

        directoryButton = QPushButton("Select data directory", self)
        directoryButton.clicked.connect(self.selectDataDirectory)
        self.file_control_grid.addWidget(directoryButton, 0, 1)
        self.data_directory_display = QLabel('')
        self.data_directory_display.setFont(QtGui.QFont('SansSerif', 8))
        self.file_control_grid.addWidget(self.data_directory_display, 1, 1)

        # Attach metadata to file
        attachDatabutton = QPushButton("Attach metadata to file", self)
        attachDatabutton.clicked.connect(self.attachData)
        self.file_control_grid.addWidget(attachDatabutton, 2, 0, 1, 2)

        # Select image data file
        selectImageDataFileButton = QPushButton("Select image data file", self)
        selectImageDataFileButton.clicked.connect(self.selectImageDataFile)
        self.file_control_grid.addWidget(selectImageDataFileButton, 3, 0, 1, 2)

        # # # # File tree: # # # # # # # #  (1,0)
        self.groupTree = QTreeWidget(self)
        self.groupTree.setHeaderHidden(True)
        self.groupTree.itemClicked.connect(self.onTreeItemClicked)
        self.file_tree_grid.addWidget(self.groupTree, 3, 0, 2, 7)

        # # # # Group control: # # # # # # # # (0, 1)
        deleteGroupButton = QPushButton("Delete selected group", self)
        deleteGroupButton.clicked.connect(self.deleteSelectedGroup)
        self.group_control_grid.addWidget(deleteGroupButton, 0, 0, 1, 2)

        # File name display
        self.currentImageFileNameLabel = QLabel('')
        self.group_control_grid.addWidget(self.currentImageFileNameLabel, 1, 0)

        # Channel drop down
        ch_label = QLabel('Channel:')
        self.ChannelComboBox = QComboBox(self)
        self.ChannelComboBox.addItem("1")
        self.ChannelComboBox.addItem("0")
        self.ChannelComboBox.activated.connect(self.selectChannel)
        self.group_control_grid.addWidget(ch_label, 2, 0)
        self.group_control_grid.addWidget(self.ChannelComboBox, 2, 1)

        # # # # Attribute table: # # # # # # # # (1, 1)
        self.tableAttributes = QTableWidget()
        self.tableAttributes.setStyleSheet("")
        self.tableAttributes.setColumnCount(2)
        self.tableAttributes.setObjectName("tableAttributes")
        self.tableAttributes.setRowCount(0)
        item = QTableWidgetItem()
        font = QtGui.QFont()
        font.setPointSize(10)
        item.setFont(font)
        item.setBackground(QtGui.QColor(121, 121, 121))
        brush = QtGui.QBrush(QtGui.QColor(91, 91, 91))
        brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern)
        item.setForeground(brush)
        self.tableAttributes.setHorizontalHeaderItem(0, item)
        item = QTableWidgetItem()
        item.setBackground(QtGui.QColor(123, 123, 123))
        brush = QtGui.QBrush(QtGui.QColor(91, 91, 91))
        brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern)
        item.setForeground(brush)
        self.tableAttributes.setHorizontalHeaderItem(1, item)
        self.tableAttributes.horizontalHeader().setCascadingSectionResizes(
            True)
        self.tableAttributes.horizontalHeader().setHighlightSections(False)
        self.tableAttributes.horizontalHeader().setSortIndicatorShown(True)
        self.tableAttributes.horizontalHeader().setStretchLastSection(True)
        self.tableAttributes.verticalHeader().setVisible(False)
        self.tableAttributes.verticalHeader().setHighlightSections(False)
        item = self.tableAttributes.horizontalHeaderItem(0)
        item.setText("Attribute")
        item = self.tableAttributes.horizontalHeaderItem(1)
        item.setText("Value")

        self.tableAttributes.itemChanged.connect(self.update_attrs_to_file)
        self.attribute_grid.addWidget(self.tableAttributes, 3, 0, 1, 8)

        # # # # Roi control # # # # # # # # (0, 2)
        # ROI type drop-down
        self.RoiTypeComboBox = QComboBox(self)
        self.RoiTypeComboBox.addItem("freehand")
        radii = [1, 2, 3, 4, 6, 8]
        for radius in radii:
            self.RoiTypeComboBox.addItem("circle:" + str(radius))
        self.RoiTypeComboBox.activated.connect(self.selectRoiType)
        self.roi_control_grid.addWidget(self.RoiTypeComboBox, 0, 0)

        # Clear all ROIs button
        self.clearROIsButton = QPushButton("Clear ROIs", self)
        self.clearROIsButton.clicked.connect(self.clearRois)
        self.roi_control_grid.addWidget(self.clearROIsButton, 0, 2)

        # Response display type dropdown
        self.RoiResponseTypeComboBox = QComboBox(self)

        self.RoiResponseTypeComboBox.addItem("RawTrace")
        self.RoiResponseTypeComboBox.addItem("TrialAverage")
        self.RoiResponseTypeComboBox.addItem("TrialResponses")
        self.RoiResponseTypeComboBox.addItem("TrialAverageDFF")
        self.roi_control_grid.addWidget(self.RoiResponseTypeComboBox, 2, 2)

        # ROIset file name line edit box
        self.defaultRoiSetName = "roi_set_name"
        self.le_roiSetName = QLineEdit(self.defaultRoiSetName)
        self.roi_control_grid.addWidget(self.le_roiSetName, 1, 1)

        # Save ROIs button
        self.saveROIsButton = QPushButton("Save ROIs", self)
        self.saveROIsButton.clicked.connect(self.saveRois)
        self.roi_control_grid.addWidget(self.saveROIsButton, 1, 0)

        # Load ROI set combobox
        self.loadROIsComboBox = QComboBox(self)
        self.loadROIsComboBox.addItem("(load existing ROI set)")
        self.loadROIsComboBox.activated.connect(self.selectedExistingRoiSet)
        self.roi_control_grid.addWidget(self.loadROIsComboBox, 1, 2)
        self.updateExistingRoiSetList()

        # Delete current roi button
        self.deleteROIButton = QPushButton("Delete ROI", self)
        self.deleteROIButton.clicked.connect(self.deleteRoi)
        self.roi_control_grid.addWidget(self.deleteROIButton, 2, 0)

        # Current roi slider
        self.roiSlider = QSlider(QtCore.Qt.Orientation.Horizontal, self)
        self.roiSlider.setMinimum(0)
        self.roiSlider.setMaximum(self.max_rois)
        self.roiSlider.valueChanged.connect(self.sliderUpdated)
        self.roi_control_grid.addWidget(self.roiSlider, 2, 1, 1, 1)

        ctx = plt.rc_context({
            'xtick.major.size': 1,
            'axes.spines.top': False,
            'axes.spines.right': False,
            'xtick.labelsize': 'xx-small',
            'ytick.labelsize': 'xx-small',
            'xtick.major.size': 1.0,
            'ytick.major.size': 1.0,
            'xtick.major.pad': 1.0,
            'ytick.major.pad': 1.0
        })
        with ctx:
            self.responseFig = plt.figure(frameon=False, layout='constrained')
            self.responsePlot = self.responseFig.add_subplot(111)
            self.responseCanvas = FigureCanvas(self.responseFig)
        self.responseCanvas.draw_idle()
        self.plot_grid.addWidget(self.responseCanvas, 0, 0)

        # # # # Image canvas # # # # # # # # (1, 2)
        self.roi_fig = plt.figure()
        self.roi_ax = self.roi_fig.add_subplot(111)
        self.roi_canvas = FigureCanvas(self.roi_fig)
        self.toolbar = NavigationToolbar(self.roi_canvas, self)
        self.roi_ax.set_aspect('equal')
        self.roi_ax.set_axis_off()
        self.plot_grid.addWidget(self.toolbar, 1, 0)
        self.plot_grid.addWidget(self.roi_canvas, 2, 0)
        self.plot_grid.setRowStretch(0, 1)
        self.plot_grid.setRowStretch(1, 3)
        self.plot_grid.setRowStretch(2, 3)

        # Current z slice slider
        self.zSlider = QSlider(QtCore.Qt.Orientation.Horizontal, self)
        self.zSlider.setMinimum(0)
        self.zSlider.setMaximum(50)
        self.zSlider.setValue(0)
        self.zSlider.valueChanged.connect(self.zSliderUpdated)
        self.plot_grid.addWidget(self.zSlider, 3, 0)

        self.roi_fig.tight_layout()

        self.setWindowTitle('Visanalysis')
        self.setGeometry(200, 200, 1200, 600)
        self.show()

    def _populateTree(self, widget, dict):
        widget.clear()
        self.fill_item(widget.invisibleRootItem(), dict)

    def fill_item(self, item, value):
        item.setExpanded(True)
        if type(value) is dict:
            for key, val in sorted(value.items()):
                child = QTreeWidgetItem()
                child.setText(0, key)
                item.addChild(child)
                self.fill_item(child, val)
        elif type(value) is list:
            for val in value:
                child = QTreeWidgetItem()
                item.addChild(child)
                if type(val) is dict:
                    child.setText(0, '[dict]')
                    self.fill_item(child, val)
                elif type(val) is list:
                    child.setText(0, '[list]')
                    self.fill_item(child, val)
                else:
                    child.setText(0, val)
                child.setExpanded(True)
        else:
            child = QTreeWidgetItem()
            child.setText(0, value)
            item.addChild(child)

    def onTreeItemClicked(self, item, column):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        group_path = h5io.getPathFromTreeItem(
            self.groupTree.selectedItems()[0])
        self.clearRois()
        self.series_number = None
        if 'series_' in group_path:
            self.series_number = int(
                group_path.split('series_')[-1].split('/')[0])
            if self.plugin.dataIsAttached(file_path, self.series_number):
                self.plugin.updateImagingDataObject(
                    self.experiment_file_directory, self.experiment_file_name,
                    self.series_number)
            # look for image_file_name or ask user to select it
            if self.data_directory is not None:
                image_file_name = h5io.readImageFileName(
                    file_path, self.series_number)
                if image_file_name is None or image_file_name == '':
                    image_file_path, _ = QFileDialog.getOpenFileName(
                        self, "Select image file")
                    print('User selected image file at {}'.format(
                        image_file_path))
                    image_file_name = os.path.split(image_file_path)[-1]
                    self.data_directory = os.path.split(
                        image_file_path)[:-1][0]
                    h5io.attachImageFileName(file_path, self.series_number,
                                             image_file_name)
                    print('Attached image_file_name {} to series {}'.format(
                        image_file_name, self.series_number))
                    print('Data directory is {}'.format(self.data_directory))

                self.image_file_name = image_file_name
                self.currentImageFileNameLabel.setText(self.image_file_name)

        else:  # clicked part of the tree upstream of any series
            self.series_number = None

        if item.parent() is not None:
            if item.parent().text(
                    column) == 'rois':  # selected existing roi group
                roi_set_name = item.text(column)
                # print('Selected roi set {} from series {}'.format(roi_set_name, self.series_number))
                self.le_roiSetName.setText(roi_set_name)
                roi_set_path = h5io.getPathFromTreeItem(
                    self.groupTree.selectedItems()[0])
                self.loadRois(roi_set_path)
                self.redrawRoiTraces()

        if group_path != '':
            attr_dict = h5io.getAttributesFromGroup(file_path, group_path)
            editable_values = True  # user can edit metadata
            self.populate_attrs(attr_dict=attr_dict,
                                editable_values=editable_values)

        # show roi image
        if self.series_number is not None:  # Clicked on node of the tree associated with a single series
            if self.data_directory is not None:  # user has selected a raw data directory
                if self.plugin.dataIsAttached(file_path, self.series_number):
                    self.plugin.updateImageSeries(
                        data_directory=self.data_directory,
                        image_file_name=self.image_file_name,
                        series_number=self.series_number,
                        channel=self.current_channel)
                    self.roi_image = self.plugin.mean_brain
                    self.zSlider.setValue(0)
                    self.zSlider.setMaximum(self.roi_image.shape[2] - 1)
                    self.redrawRoiTraces()
                else:
                    print('Attach metadata to file before drawing rois')

            else:
                print('Select a data directory before drawing rois')

        # # # TEST # # #
        memory_usage = psutil.Process(os.getpid()).memory_info().rss * 10**-9
        print('Current Memory Usage: {:.2f}GB'.format(memory_usage))
        sys.stdout.flush()
        # # # TEST # # #

    def updateExistingRoiSetList(self):
        if self.experiment_file_name is not None:
            file_path = os.path.join(self.experiment_file_directory,
                                     self.experiment_file_name + '.hdf5')
            self.existing_roi_set_paths = self.plugin.getRoiSetPaths(
                file_path)  # dictionary of name: full path
            self.loadROIsComboBox.clear()
            for r_path in self.existing_roi_set_paths:
                self.loadROIsComboBox.addItem(r_path)

            self.show()

    def selectedExistingRoiSet(self):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        roi_set_key = self.loadROIsComboBox.currentText()
        roi_set_path = self.existing_roi_set_paths[roi_set_key]

        _, _, self.roi_path, self.roi_mask = self.plugin.loadRoiSet(
            file_path, roi_set_path)

        if self.series_number is not None:
            self.roi_response = []
            for new_path in self.roi_path:
                new_roi_resp = self.plugin.getRoiDataFromPath(
                    roi_path=new_path)
                self.roi_response.append(new_roi_resp)

            # update slider to show most recently drawn roi response
            self.current_roi_index = len(self.roi_response) - 1
            self.roiSlider.setValue(self.current_roi_index)

            # Update figures
            self.redrawRoiTraces()

    def selectDataFile(self):
        filePath, _ = QFileDialog.getOpenFileName(
            self, "Open experiment (hdf5) file")
        self.experiment_file_name = os.path.split(filePath)[1].split('.')[0]
        self.experiment_file_directory = os.path.split(filePath)[0]

        if self.experiment_file_name != '':
            self.currentExperimentLabel.setText(self.experiment_file_name)
            self.initializeDataAnalysis()
            self.populateGroups()
            self.updateExistingRoiSetList()

    def selectDataDirectory(self):
        filePath = str(
            QFileDialog.getExistingDirectory(self, "Select data directory"))
        self.data_directory = filePath
        self.data_directory_display.setText('..' + self.data_directory[-24:])

    def initializeDataAnalysis(self):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        data_type = h5io.getDataType(file_path)
        # Load plugin based on Rig name in hdf5 file
        if data_type == 'Bruker':
            from visanalysis.plugin import bruker
            self.plugin = bruker.BrukerPlugin()
        elif data_type == 'AODscope':
            from visanalysis.plugin import aodscope
            self.plugin = aodscope.AodScopePlugin()
        else:
            self.plugin = h5io.BasePlugin()

        self.plugin.parent_gui = self

        # # # TEST # # #
        memory_usage = psutil.Process(os.getpid()).memory_info().rss * 10**-9
        print('Current memory usage: {:.2f}GB'.format(memory_usage))
        sys.stdout.flush()
        # # # TEST # # #

    def attachData(self):
        if self.data_directory is not None:
            file_path = os.path.join(self.experiment_file_directory,
                                     self.experiment_file_name + '.hdf5')
            self.plugin.attachData(self.experiment_file_name, file_path,
                                   self.data_directory)
            print('Data attached')
        else:
            print('Select a data directory before attaching new data')

    def selectImageDataFile(self):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')

        image_file_path, _ = QFileDialog.getOpenFileName(
            self, "Select image file")
        print('User selected image file at {}'.format(image_file_path))
        self.image_file_name = os.path.split(image_file_path)[-1]
        self.data_directory = os.path.split(image_file_path)[:-1][0]
        h5io.attachImageFileName(file_path, self.series_number,
                                 self.image_file_name)
        print('Attached image_file_name {} to series {}'.format(
            self.image_file_name, self.series_number))
        print('Data directory is {}'.format(self.data_directory))

        self.currentImageFileNameLabel.setText(self.image_file_name)

        # show roi image
        if self.series_number is not None:
            if self.data_directory is not None:  # user has selected a raw data directory
                self.plugin.updateImageSeries(
                    data_directory=self.data_directory,
                    image_file_name=self.image_file_name,
                    series_number=self.series_number,
                    channel=self.current_channel)
                self.roi_image = self.plugin.mean_brain
                self.zSlider.setValue(0)
                self.zSlider.setMaximum(self.roi_image.shape[2] - 1)
                self.redrawRoiTraces()
            else:
                print('Select a data directory before drawing rois')

    def deleteSelectedGroup(self):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        group_path = h5io.getPathFromTreeItem(
            self.groupTree.selectedItems()[0])
        group_name = group_path.split('/')[-1]

        buttonReply = QMessageBox.question(
            self, 'Delete series',
            "Are you sure you want to delete group {}?".format(group_name),
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
            QMessageBox.StandardButton.No)
        if buttonReply == QMessageBox.StandardButton.Yes:
            h5io.deleteGroup(file_path=file_path, group_path=group_path)
            print('Deleted group {}'.format(group_name))
            self.updateExistingRoiSetList()
            self.populateGroups()
        else:
            print('Delete aborted')

    def populateGroups(self):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        self.group_dset_dict = h5io.getHierarchy(file_path)
        self._populateTree(self.groupTree, self.group_dset_dict)

    def populate_attrs(self, attr_dict=None, editable_values=False):
        """Populate attribute for currently selected group."""
        self.tableAttributes.blockSignals(
            True)  # block udpate signals for auto-filled forms
        self.tableAttributes.setRowCount(0)
        self.tableAttributes.setColumnCount(2)
        self.tableAttributes.setSortingEnabled(False)

        if attr_dict:
            for num, key in enumerate(attr_dict):
                self.tableAttributes.insertRow(self.tableAttributes.rowCount())
                key_item = QTableWidgetItem(key)
                key_item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable
                                  | QtCore.Qt.ItemFlag.ItemIsEnabled)
                self.tableAttributes.setItem(num, 0, key_item)

                val_item = QTableWidgetItem(str(attr_dict[key]))
                if editable_values:
                    val_item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable
                                      | QtCore.Qt.ItemFlag.ItemIsEditable
                                      | QtCore.Qt.ItemFlag.ItemIsEnabled)
                else:
                    val_item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable
                                      | QtCore.Qt.ItemFlag.ItemIsEnabled)
                self.tableAttributes.setItem(num, 1, val_item)

        self.tableAttributes.blockSignals(False)

    def update_attrs_to_file(self, item):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        group_path = h5io.getPathFromTreeItem(
            self.groupTree.selectedItems()[0])

        attr_key = self.tableAttributes.item(item.row(), 0).text()
        attr_val = item.text()

        # update attr in file
        h5io.changeAttribute(file_path=file_path,
                             group_path=group_path,
                             attr_key=attr_key,
                             attr_val=attr_val)
        print('Changed attr {} to = {}'.format(attr_key, attr_val))

# %% # # # # # # # # ROI SELECTOR WIDGET # # # # # # # # # # # # # # # # # # #

    def refreshLassoWidget(self, keep_paths=False):
        self.roi_ax.clear()
        init_lasso = False
        if self.roi_image is not None:
            if len(self.roi_mask) > 0:
                newImage = plot_tools.overlayImage(
                    self.roi_image[:, :, self.current_z_slice],
                    self.roi_mask,
                    0.5,
                    self.colors,
                    z=self.current_z_slice)
            else:
                newImage = self.roi_image[:, :, self.current_z_slice]
            self.roi_ax.imshow(newImage, cmap=cm.gray)
            init_lasso = True
        else:
            self.roi_ax.imshow(self.blank_image)
        self.roi_ax.set_axis_off()

        self.roi_canvas.draw()

        if not keep_paths:
            self.roi_path_list = []

        if init_lasso:
            if self.roi_type == 'circle':
                self.lasso_1 = EllipseSelector(self.roi_ax,
                                               onselect=self.newEllipse,
                                               button=1)
            elif self.roi_type == 'freehand':
                self.lasso_1 = LassoSelector(self.roi_ax,
                                             onselect=self.newFreehand,
                                             button=1)
                self.lasso_2 = LassoSelector(self.roi_ax,
                                             onselect=self.appendFreehand,
                                             button=3)
            else:
                print(
                    'Warning ROI type not recognized. Choose circle or freehand'
                )

    def newFreehand(self, verts):
        new_roi_path = path.Path(verts)
        new_roi_path.z_level = self.zSlider.value()
        new_roi_path.channel = self.current_channel
        self.updateRoiSelection([new_roi_path])

    def appendFreehand(self, verts):
        print('Appending rois, hit Enter/Return to finish')
        new_roi_path = path.Path(verts)
        new_roi_path.z_level = self.zSlider.value()
        new_roi_path.channel = self.current_channel
        self.roi_path_list.append(new_roi_path)

    def keyPressEvent(self, event):
        if type(event) == QtGui.QKeyEvent:
            if np.any([
                    event.key() == QtCore.Qt.Key.Key_Return,
                    event.key() == QtCore.Qt.Key.Key_Enter
            ]):
                if len(self.roi_path_list) > 0:
                    event.accept()
                    self.updateRoiSelection(self.roi_path_list)
                else:
                    event.ignore()
            else:
                event.ignore()
        else:
            event.ignore()

    def newEllipse(self, pos1, pos2, definedRadius=None):
        x1 = np.round(pos1.xdata)
        x2 = np.round(pos2.xdata)
        y1 = np.round(pos1.ydata)
        y2 = np.round(pos2.ydata)

        radiusX = np.sqrt((x1 - x2)**2) / 2
        radiusY = np.sqrt((y1 - y2)**2) / 2
        if self.roi_radius is not None:
            radiusX = self.roi_radius

        center = (np.round((x1 + x2) / 2), np.round((y1 + y2) / 2))
        new_roi_path = path.Path.circle(center=center, radius=radiusX)
        new_roi_path.z_level = self.zSlider.value()
        new_roi_path.channel = self.current_channel
        self.updateRoiSelection([new_roi_path])

    def updateRoiSelection(self, new_roi_path):
        mask = self.plugin.getRoiMaskFromPath(new_roi_path)
        new_roi_resp = self.plugin.getRoiDataFromPath(roi_path=new_roi_path)
        if mask.sum() == 0:
            print('No pixels in the roi you just drew')
            return
        # update list of roi data
        self.roi_mask.append(mask)
        self.roi_path.append(new_roi_path)  # list of lists of paths
        self.roi_response.append(new_roi_resp)
        # update slider to show most recently drawn roi response
        self.current_roi_index = len(self.roi_response) - 1
        self.roiSlider.setValue(self.current_roi_index)

        # Update figures
        self.redrawRoiTraces()

    def sliderUpdated(self):
        self.current_roi_index = self.roiSlider.value()
        self.redrawRoiTraces()

    def zSliderUpdated(self):
        self.current_z_slice = self.zSlider.value()
        if self.roi_image is not None:
            self.refreshLassoWidget(keep_paths=True)

    def redrawRoiTraces(self):
        self.clearRoiArtists()
        if self.current_roi_index < len(self.roi_response):
            current_raw_trace = np.squeeze(
                self.roi_response[self.current_roi_index])
            fxn_name = self.RoiResponseTypeComboBox.currentText()
            display_trace = getattr(self.plugin,
                                    'getRoiResponse_{}'.format(fxn_name))(
                                        [current_raw_trace])
            self.responsePlot.plot(display_trace,
                                   color=self.colors[self.current_roi_index],
                                   linewidth=1,
                                   alpha=0.5)
            self.responsePlot.set_xlim([0, len(display_trace)])
            y_min = np.nanmin(display_trace)
            y_max = np.nanmax(display_trace)
            self.responsePlot.set_ylim([y_min, y_max])
        self.responseCanvas.draw()

        self.refreshLassoWidget(keep_paths=False)


# %% # # # # # # # # LOADING / SAVING / COMPUTING ROIS # # # # # # # # # # # # # # # # # # #

    def loadRois(self, roi_set_path):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        self.roi_response, self.roi_image, self.roi_path, self.roi_mask = self.plugin.loadRoiSet(
            file_path, roi_set_path)
        self.zSlider.setValue(0)
        self.zSlider.setMaximum(self.roi_image.shape[2] - 1)

    def saveRois(self):
        file_path = os.path.join(self.experiment_file_directory,
                                 self.experiment_file_name + '.hdf5')
        roi_set_name = self.le_roiSetName.text()
        if roi_set_name in h5io.getAvailableRoiSetNames(
                file_path, self.series_number):
            buttonReply = QMessageBox.question(
                self, 'Overwrite roi set',
                "Are you sure you want to overwrite roi set: {}?".format(
                    roi_set_name),
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                QMessageBox.StandardButton.No)
            if buttonReply == QMessageBox.StandardButton.Yes:
                self.plugin.saveRoiSet(file_path,
                                       series_number=self.series_number,
                                       roi_set_name=roi_set_name,
                                       roi_mask=self.roi_mask,
                                       roi_response=self.roi_response,
                                       roi_image=self.roi_image,
                                       roi_path=self.roi_path)
                print('Saved roi set {} to series {}'.format(
                    roi_set_name, self.series_number))
                self.populateGroups()
                self.updateExistingRoiSetList()
            else:
                print('Overwrite aborted - pick a unique roi set name')
        else:
            self.plugin.saveRoiSet(file_path,
                                   series_number=self.series_number,
                                   roi_set_name=roi_set_name,
                                   roi_mask=self.roi_mask,
                                   roi_response=self.roi_response,
                                   roi_image=self.roi_image,
                                   roi_path=self.roi_path)
            print('Saved roi set {} to series {}'.format(
                roi_set_name, self.series_number))
            self.populateGroups()
            self.updateExistingRoiSetList()

    def deleteRoi(self):
        if self.current_roi_index < len(self.roi_response):
            self.roi_mask.pop(self.current_roi_index)
            self.roi_response.pop(self.current_roi_index)
            self.roi_path.pop(self.current_roi_index)
            self.roiSlider.setValue(self.current_roi_index - 1)
            self.redrawRoiTraces()

    def clearRois(self):
        self.roi_mask = []
        self.roi_response = []
        self.roi_path = []
        self.roi_image = None
        self.clearRoiArtists()
        self.redrawRoiTraces()
        self.roi_ax.clear()

    def clearRoiArtists(self):
        for artist in self.responsePlot.lines + self.responsePlot.collections:
            artist.remove()

    def selectRoiType(self):
        self.roi_type = self.RoiTypeComboBox.currentText().split(':')[0]
        if 'circle' in self.RoiTypeComboBox.currentText():
            self.roi_radius = int(
                self.RoiTypeComboBox.currentText().split(':')[1])
        else:
            self.roi_radius = None
        self.redrawRoiTraces()

    def selectChannel(self):
        self.current_channel = int(self.ChannelComboBox.currentText())

        # show roi image
        if self.series_number is not None:
            if self.data_directory is not None:  # user has selected a raw data directory
                self.plugin.updateImageSeries(
                    data_directory=self.data_directory,
                    image_file_name=self.image_file_name,
                    series_number=self.series_number,
                    channel=self.current_channel)
                self.roi_image = self.plugin.mean_brain
                self.zSlider.setValue(0)
                self.zSlider.setMaximum(self.roi_image.shape[2] - 1)
                self.redrawRoiTraces()
            else:
                print('Select a data directory before drawing rois')
Пример #17
0
import sys
from PyQt6.QtWidgets import QApplication,QGridLayout,QPushButton,QWidget

app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Grid Layout')
layout = QGridLayout()
layout.addWidget(QPushButton('Top Right'),0,0)
layout.addWidget(QPushButton('Center'),1,1)
layout.addWidget(QPushButton('Bottom Left from Center'),2,1,1,2)
window.setLayout(layout)
window.show()
sys.exit(app.exec())
Пример #18
0
class About(QWidget):
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        hlayout = QHBoxLayout()
        self.layout = QGridLayout()
        hlayout.addLayout(self.layout)
        hlayout.setAlignment(hlayout, Qt.Alignment.AlignTop)
        self.setLayout(hlayout)
        self.row = 0

        self.__addLine__(
            "Python Version:",
            "{}.{}.{} {}".format(sys.version_info.major,
                                 sys.version_info.minor,
                                 sys.version_info.micro,
                                 sys.version_info.releaselevel))

        self.__addLine__("Qt Version:", PYQT_VERSION_STR)

        if path.isfile('/etc/system-release'):
            with open('/etc/system-release', 'r') as reader:
                dist = reader.readline()
                self.__addLine__("Distribution:", dist.strip())
        elif path.isfile('/etc/lsb-release'):
            with open('/etc/lsb-release') as reader:
                lsb = reader.readlines()
                line = str(lsb[-1])
                dist = line.strip().split("=")[-1].strip('"')
                self.__addLine__("Distribution:", dist)

        self.__addLine__("Operating System:", platform.uname().system)

        self.__addLine__("Kernel Release:", platform.uname().release)

        self.__addLine__(
            "Total Physical Memory:",
            "{:.1f} GiB".format(psutil.virtual_memory().total / (1024**3)))

        self.__addLine__(
            "Root Disk Space as Total/Used/Free:",
            "{:.1f} GiB/{:.1f} GiB/{:.1f} GiB".format(
                psutil.disk_usage('/').total / (1024**3),
                psutil.disk_usage('/').used / (1024**3),
                psutil.disk_usage('/').free / (1024**3)))

        self.__addLine__(
            "Swap Space as Total/Used/Free:",
            "{:.1f} GiB/{:.2f} GiB/{:.1f} GiB".format(
                psutil.swap_memory().total / (1024**3),
                psutil.swap_memory().used / (1024**3),
                psutil.swap_memory().free / (1024**3)))

        if hasattr(psutil, 'cpu-thermal') and callable(
                getattr(psutil, 'cpu-thermal')):
            self.__addLine__(
                "CPU Temperature:", "{:.1f}\xb0 C".format(
                    psutil.sensors_temperatures()['cpu-thermal'][0].current))
        elif hasattr(psutil, 'thermal-fan-est') and callable(
                getattr(psutil, 'thermal-fan-est')):
            self.__addLine__(
                "CPU Temperature:",
                "{:.1f}\xb0 C".format(psutil.sensors_temperatures()
                                      ['thermal-fan-est'][0].current))

    def __addLine__(self, label, value):
        lbl = QLabel(label)
        lbl.setAlignment(Qt.Alignment.AlignRight)
        self.layout.addWidget(lbl, self.row, 0)

        lbl = QLabel(value)
        lbl.setAlignment(Qt.Alignment.AlignTop)
        self.layout.addWidget(lbl, self.row, 1)
        self.row += 1

    def tabName(self):
        return 'About'
    def setUpWindow(self):
        """Set up the dialog's widgets and layout."""
        header_label = QLabel("""<p style='color:#65888C'>
            Welcome to Database Manager</p>""")
        header_label.setFont(QFont("Arial", 24))
        header_label.setAlignment(Qt.AlignmentFlag.AlignCenter)

        self.info_label = QLabel("""<p style='color:#65888C'>
            Sign into your account.</p>""")
        self.info_label.setAlignment(Qt.AlignmentFlag.AlignHCenter)

        username_label = QLabel("Username:"******"Password:"******"Log In", QDialogButtonBox.ButtonRole.AcceptRole)
        button_box.accepted.connect(self.clickedLogInButton)

        log_in_grid = QGridLayout()
        log_in_grid.addWidget(header_label, 0, 0, 1, 3,
                              Qt.AlignmentFlag.AlignCenter)
        log_in_grid.addWidget(self.info_label, 1, 0, 1, 3,
                              Qt.AlignmentFlag.AlignCenter)
        log_in_grid.addWidget(username_label, 2, 0)
        log_in_grid.addWidget(self.username_line, 2, 1)
        log_in_grid.addWidget(password_label, 3, 0)
        log_in_grid.addWidget(self.password_line, 3, 1)
        log_in_grid.addWidget(button_box, 4, 1)
        self.setLayout(log_in_grid)
Пример #20
0
class SetPwdDialog(QDialog):
    new_infos = pyqtSignal(object)

    def __init__(self, parent=None):
        super(SetPwdDialog, self).__init__(parent)
        self.infos = []
        self.initUI()
        self.update_text()
        self.setStyleSheet(dialog_qss_style)

    def set_values(self, infos):
        self.infos = infos
        self.update_text()  # 更新界面

    def set_tip(self):  # 用于提示状态
        self.setWindowTitle("请稍等……")

    def initUI(self):
        self.setWindowTitle("请稍等……")
        self.setWindowIcon(QIcon(SRC_DIR + "password.ico"))
        self.lb_oldpwd = QLabel()
        self.lb_oldpwd.setText("当前提取码:")
        self.lb_oldpwd.setAlignment(Qt.AlignmentFlag.AlignRight
                                    | Qt.AlignmentFlag.AlignTrailing
                                    | Qt.AlignmentFlag.AlignVCenter)
        self.tx_oldpwd = QLineEdit()
        # 当前提取码 只读
        self.tx_oldpwd.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        self.tx_oldpwd.setReadOnly(True)
        self.lb_newpwd = QLabel()
        self.lb_newpwd.setText("新的提取码:")
        self.lb_newpwd.setAlignment(Qt.AlignmentFlag.AlignRight
                                    | Qt.AlignmentFlag.AlignTrailing
                                    | Qt.AlignmentFlag.AlignVCenter)
        self.tx_newpwd = QLineEdit()

        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Orientation.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.StandardButton.Ok
            | QDialogButtonBox.StandardButton.Cancel)
        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定")
        self.buttonBox.button(
            QDialogButtonBox.StandardButton.Cancel).setText("取消")

        self.grid = QGridLayout()
        self.grid.setSpacing(10)
        self.grid.addWidget(self.lb_oldpwd, 1, 0)
        self.grid.addWidget(self.tx_oldpwd, 1, 1)
        self.grid.addWidget(self.lb_newpwd, 2, 0)
        self.grid.addWidget(self.tx_newpwd, 2, 1)
        self.grid.addWidget(self.buttonBox, 3, 0, 1, 2)
        self.setLayout(self.grid)
        self.buttonBox.accepted.connect(self.btn_ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.accepted.connect(self.set_tip)
        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.rejected.connect(self.set_tip)
        self.setMinimumWidth(280)

    def update_text(self):
        num = len(self.infos)
        if num == 1:
            self.tx_oldpwd.setVisible(True)
            self.lb_oldpwd.setVisible(True)
            infos = self.infos[0]
            if infos.has_pwd:
                self.tx_oldpwd.setText(str(infos.pwd))
                self.tx_oldpwd.setPlaceholderText("")
            else:
                self.tx_oldpwd.setText("")
                self.tx_oldpwd.setPlaceholderText("无")

            if isinstance(infos, FileInfos):  # 文件  通过size列判断是否为文件
                self.setWindowTitle("修改文件提取码")
                self.tx_newpwd.setPlaceholderText("2-6位字符,关闭请留空")
                self.tx_newpwd.setMaxLength(6)  # 最长6个字符
            else:  # 文件夹
                self.setWindowTitle("修改文件夹名提取码")
                self.tx_newpwd.setPlaceholderText("2-12位字符,关闭请留空")
                self.tx_newpwd.setMaxLength(12)  # 最长12个字符
        elif num > 1:
            self.tx_oldpwd.setVisible(False)
            self.lb_oldpwd.setVisible(False)
            self.setWindowTitle(f"批量修改{num}个文件(夹)的提取码")
            self.tx_newpwd.setPlaceholderText("2-12位字符,关闭请留空")
            self.tx_newpwd.setMaxLength(12)  # 最长12个字符
            self.tx_newpwd.setText('')
            for infos in self.infos:
                if isinstance(infos, FileInfos):  # 文件
                    self.tx_newpwd.setPlaceholderText("2-6位字符,文件无法关闭")
                    self.tx_newpwd.setMaxLength(6)  # 最长6个字符
                    break

    def btn_ok(self):
        new_pwd = self.tx_newpwd.text()
        for infos in self.infos:
            infos.new_pwd = new_pwd
        self.new_infos.emit(self.infos)  # 最后一位用于标示文件还是文件夹
Пример #21
0
 def __init__(self, parent: QWidget):
     super().__init__()
     self.logger = logging.getLogger(__name__)
     with open(file="config.json", mode="r",
               encoding="utf-8") as conf_reader:
         self.conf = json.loads(conf_reader.read())
     self.logger.debug("初始化设置界面。设置内容:%s" % self.conf)
     layout = QGridLayout()
     self.setLayout(layout)
     self.setModal(True)
     self.setParent(parent)
     self.resize(400, 300)
     title = QLabel("设置")
     title.setStyleSheet(
         "QLabel{border:none;border-radius:5px;background:transparent;color:#9AD3BC;font-size:20px;}"
     )
     title.setAlignment(Qt.Alignment.AlignCenter)
     layout.addWidget(title, 0, 1, Qt.Alignment.AlignCenter)
     control_close = QPushButton()
     control_close.setStyleSheet(
         "QPushButton{background:#FFE3ED;border-radius:5px;border:none;}QPushButton:hover{background:#EC524B;}"
     )
     control_close.setToolTip("关闭")
     control_close.setFixedHeight(20)
     control_close.clicked.connect(self.close_callback)
     layout.addWidget(control_close, 0, 0)
     debug_check = QCheckBox("调试模式")
     debug_check.setChecked(self.conf["debug"])
     debug_check.setToolTip("单击切换开关状态")
     debug_check.setStyleSheet(
         "QCheckBox::indicator{width:10px;height:10px;border:none;border-radius:5px;background:#9BE3DE;}QCheckBox::indicator:unchecked{background:#BEEBE9;}QCheckBox::indicator:unchecked:hover{background:#9AD3BC;}QCheckBox::indicator:checked{background:#95E1D3;}QCheckBox::indicator:checked:hover{background:#98DED9;}"
     )
     self.content = QGridLayout()
     (x, y) = self.show_setting(conf=self.conf,
                                layout=self.content)  # 返回content的最后一个元素的x,y
     proxy = QGroupBox()
     proxy.setObjectName("proxy")
     proxy_layout = QVBoxLayout()
     proxy_label = QLabel("代理地址:")
     proxy_label.setStyleSheet(
         "QLabel{background:transparent;border:none;}")
     proxy_input = EnhancedEdit()
     proxy_input.setText(self.conf["proxy"])
     proxy_input.setToolTip("格式为协议://IP:端口,留空保持直连")
     proxy_input.setStyleSheet(
         "QLineEdit{border:1px solid #F3EAC2;border-radius:5px;background:transparent;}QLineEdit:hover{border:1px solid #F5B461;}"
     )
     proxy_layout.addWidget(proxy_label)
     proxy_layout.addWidget(proxy_input)
     proxy.setLayout(proxy_layout)
     proxy.setStyleSheet("QGroupBox{border-radius:5px;}")
     proxy.setToolTip("代理设置")
     if y + 1 >= 3:
         y_ = 0
         x_ = x + 1
     else:
         y_ = y + 1
         x_ = x
     self.content.addWidget(proxy, x_, y_)
     self.content.addWidget(debug_check)
     layout.addLayout(self.content, 1, 1)
Пример #22
0
    def initUI(self):

        title = QLabel('Title')
        author = QLabel('Author')
        review = QLabel('Review')

        titleEdit = QLineEdit()
        authorEdit = QLineEdit()
        reviewEdit = QTextEdit()

        grid = QGridLayout()
        grid.setSpacing(10)

        grid.addWidget(title, 1, 0)
        grid.addWidget(titleEdit, 1, 1)

        grid.addWidget(author, 2, 0)
        grid.addWidget(authorEdit, 2, 1)

        grid.addWidget(review, 3, 0)
        grid.addWidget(reviewEdit, 3, 1, 5, 1)

        self.setLayout(grid)

        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('Review')
        self.show()
Пример #23
0
class UI(QWidget):
    update_signal = pyqtSignal(str)
    show_qr_signal = pyqtSignal(bytes)
    finish_signal = pyqtSignal()
    close_qr_signal = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.logger = logging.getLogger(__name__)
        formatter = logging.Formatter(
            fmt="%(asctime)s-%(levelname)s-%(message)s",
            datefmt="%Y-%m-%d %H:%M:%S")
        filehandler = logging.FileHandler(filename="logs.log",
                                          mode="w",
                                          encoding="utf-8")
        handler = QLogger(update_signal=self.update_signal)
        handler.setLevel(logging.INFO)
        filehandler.setLevel(logging.INFO)
        self.logger.setLevel(logging.INFO)
        if os.path.exists("config.json") == False:
            self.gen_conf()
        with open(file="config.json", mode="r",
                  encoding="utf-8") as conf_reader:
            conf = json.loads(conf_reader.read())
        debug = bool(conf["debug"])
        if debug == True:
            handler.setLevel(logging.DEBUG)
            filehandler.setLevel(logging.DEBUG)
            self.logger.setLevel(logging.DEBUG)
        handler.setFormatter(formatter)
        filehandler.setFormatter(formatter)
        self.logger.addHandler(handler)
        self.logger.addHandler(filehandler)
        self.logger.debug("当前调试状态:%s" % debug)
        self.resize(1024, 768)
        self.setWindowOpacity(0.9)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
        self.setWindowFlag(Qt.WindowFlags.FramelessWindowHint)
        self.setAutoFillBackground(True)
        self.work = Work(show_qr_signal=self.show_qr_signal,
                         finish_signal=self.finish_signal,
                         close_qr_signal=self.close_qr_signal)
        self.work_thread = QThread()
        self.work.moveToThread(self.work_thread)
        self.main_layout = QGridLayout()
        self.setLayout(self.main_layout)
        self.title = QLabel("ChinaUniOnlineGUI")
        self.title.setStyleSheet(
            "QLabel{border:none;border-radius:5px;background:transparent;color:#9AD3BC;font-size:60px;}"
        )
        self.title.setAlignment(Qt.Alignment.AlignCenter)
        handler.widget.setStyleSheet(
            "QPlainTextEdit{font-family:Microsoft YaHei;background:#F3EAC2;border:none;border-radius:5px;}QScrollBar:vertical,QScrollBar::handle:vertical{background:#F3EAC2;border:none;border-radius:8px;width:16px;}QScrollBar::handle:vertical:hover{background:#F5B461;}QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:#FFFDF9;border:none;border-radius:8px;width:16px;}QScrollBar::down-arrow:vertical,QScrollBar::up-arrow:vertical{background:#F5B461;border:none;border-radius:8px;width:16px;height:16px;}QScrollBar::sub-line:vertical,QScrollBar::add-line:vertical{background:transparent;border:none;}"
        )
        self.control = QVBoxLayout()
        self.control_close = QPushButton()
        self.control_close.setToolTip("关闭")
        self.control_close.setStyleSheet(
            "QPushButton{background:#FFE3ED;border-radius:5px;border:none;}QPushButton:hover{background:#EC524B;}"
        )
        self.contron_max = QPushButton()
        if self.isMaximized() == False:
            self.contron_max.setToolTip("最大化")
        else:
            self.contron_max.setToolTip("还原")
        self.contron_max.setStyleSheet(
            "QPushButton{background:#FFFDF9;border-radius:5px;border:none;}QPushButton:hover{background:#F5B461;}"
        )
        self.control_min = QPushButton()
        self.control_min.setToolTip("最小化")
        self.control_min.setStyleSheet(
            "QPushButton{background:#BEEBE9;border-radius:5px;border:none;}QPushButton:hover{background:#F3EAC2;}"
        )
        self.start_button = QPushButton("开始(&S)")
        self.start_button.setStyleSheet(
            "QPushButton{background:#9BE3DE;border:none;border-radius:5px;font-size:20px;font-family:DengXian;}QPushButton:hover{background:#9AD3BC;}"
        )
        self.start_button.setToolTip("开始")
        self.start_button.setFixedSize(120, 60)
        self.start_button.setDefault(True)
        setting_button = QPushButton("设置")
        setting_button.setToolTip("设置")
        setting_button.setFixedSize(60, 60)
        setting_button.setStyleSheet(
            "QPushButton{background:#9BE3DE;border:none;border-radius:5px;font-size:20px;font-family:DengXian;}QPushButton:hover{background:#9AD3BC;}"
        )
        setting_button.clicked.connect(self.setting_callback)
        start = QHBoxLayout()
        start.addWidget(self.start_button, 2)
        start.addWidget(setting_button, 1)
        self.control_close.clicked.connect(self.close)
        self.control_min.clicked.connect(self.min_callback)
        self.contron_max.clicked.connect(self.max_callback)
        self.start_button.clicked.connect(self.start_callback)
        self.work_thread.started.connect(self.work.start)
        self.finish_signal.connect(self.finish_callback)
        self.close_qr_signal.connect(self.close_qr)
        self.control.addWidget(self.control_min)
        self.control.addWidget(self.contron_max)
        self.control.addWidget(self.control_close)
        self.main_layout.addLayout(self.control, 0, 0)
        self.main_layout.addWidget(self.title, 0, 1)
        self.main_layout.addLayout(start, 0, 2)
        self.main_layout.addWidget(handler.widget, 1, 1)
        self.update_signal.connect(handler.widget.appendPlainText)
        handler.widget.textChanged.connect(handler.scroll_widget_to_bottom)
        self.show_qr_signal.connect(self.show_qr)
        self.logger.debug("已初始化UI")

    def min_callback(self):
        if self.isMinimized() == False:
            self.showMinimized()

    def max_callback(self):
        if self.isMaximized() == False:
            self.showMaximized()
            self.contron_max.setToolTip("还原")
        else:
            self.showNormal()
            self.contron_max.setToolTip("最大化")

    def start_callback(self):
        self.start_time = time.time()
        self.work_thread.start()
        self.start_button.setEnabled(False)
        self.start_button.setText("执行中...")

    def finish_callback(self):
        self.start_button.setEnabled(True)
        self.start_button.setText("开始")
        passed_time = time.time() - self.start_time
        mins, secs = divmod(passed_time, 60)
        hours, mins = divmod(mins, 60)
        self.logger.info("执行完成,共计用时 {:0>2d}:{:0>2d}:{:0>2d}".format(
            int(hours), int(mins), int(secs)))

    def show_qr(self, qr: bytes):
        title_label = QLabel("请使用微信扫描小程序码完成登陆")
        title_label.setStyleSheet(
            "QLabel{color:#ffe3ed;border:none;background-color:transparent;border-radius:5px;}"
        )
        title_label.setAlignment(Qt.Alignment.AlignCenter)
        title_label.setFixedHeight(20)
        qr_label = QLabel()
        pixmap = QPixmap()
        pixmap.loadFromData(qr)
        qr_label.setPixmap(pixmap)
        qr_label.setStyleSheet(
            "QLabel{color:#ffe3ed;border:none;background-color:transparent;border-radius:5px;}"
        )
        layout_ = QVBoxLayout()
        layout_.addWidget(title_label, 1)
        layout_.addWidget(qr_label, 9)
        self.qr_dialog = QWidget(self)
        self.qr_dialog.setLayout(layout_)
        self.main_layout.addWidget(self.qr_dialog, 1, 1,
                                   Qt.Alignment.AlignCenter)
        self.qr_dialog.show()

    def close_qr(self):
        self.qr_dialog.close()

    def setting_callback(self):
        setting = SettingWindow(parent=self)
        setting.setStyleSheet(
            "QDialog{border:none;border-radius:5px;background:#F3EAC2;}")
        setting.show()

    def gen_conf(self):
        default_conf = {
            "debug": False,
            "hero": {
                "title": "英雄篇",
                "enabled": True,
                "times": 1
            },
            "revival": {
                "title": "复兴篇",
                "enabled": True,
                "times": 1
            },
            "creation": {
                "title": "创新篇",
                "enabled": True,
                "times": 1
            },
            "belief": {
                "title": "信念篇",
                "enabled": True,
                "times": 1
            },
            "limit_time": {
                "title": "限时赛",
                "enabled": True,
                "times": 1
            },
            "rob": {
                "title": "抢十赛",
                "enabled": True,
                "times": 1
            }
        }
        with open(file="config.json", mode="w",
                  encoding="utf-8") as conf_writer:
            conf_writer.write(
                json.dumps(default_conf,
                           indent=4,
                           sort_keys=True,
                           ensure_ascii=False))
        self.logger.info("已生成默认配置文件")

    def mousePressEvent(self, event: QMouseEvent):
        self.logger.debug("触发鼠标按压事件")
        super().mousePressEvent(event)
        self.setFocus()
        self.m_flag = True
        if event.button() == Qt.MouseButtons.LeftButton and self.isMaximized(
        ) == False and self.hasFocus() == True:
            self.old_pos = event.globalPosition()  #获取鼠标相对窗口的位置
            self.logger.debug("已获取鼠标位置")
            self.setCursor(QtGui.QCursor(
                Qt.CursorShape.SizeAllCursor))  #更改鼠标图标

    def mouseMoveEvent(self, event: QMouseEvent):
        self.logger.debug("触发鼠标移动事件")
        super().mouseMoveEvent(event)
        if self.m_flag == True:
            delta_x = int(event.globalPosition().x() - self.old_pos.x())
            delta_y = int(event.globalPosition().y() - self.old_pos.y())
            self.move(self.x() + delta_x, self.y() + delta_y)  #更改窗口位置
            self.logger.debug("已更改窗口位置")
            self.old_pos = event.globalPosition()

    def mouseReleaseEvent(self, event: QMouseEvent):
        self.logger.debug("触发鼠标释放事件")
        super().mouseReleaseEvent(event)
        self.m_flag = False
        self.setCursor(QtGui.QCursor(Qt.CursorShape.ArrowCursor))
Пример #24
0
class MoveFileDialog(QDialog):
    '''移动文件对话框'''
    new_infos = pyqtSignal(object)

    def __init__(self, parent=None):
        super(MoveFileDialog, self).__init__(parent)
        self.infos = None
        self.dirs = {}
        self.initUI()
        self.setStyleSheet(dialog_qss_style)

    def update_ui(self):
        names = "\n".join([i.name for i in self.infos])
        names_tip = "\n".join([i.name for i in self.infos])
        self.tx_name.setText(names)
        self.tx_name.setToolTip(names_tip)

        self.tx_new_path.clear()
        f_icon = QIcon(SRC_DIR + "folder.gif")
        for f_name, fid in self.dirs.items():
            if len(f_name) > 50:  # 防止文件夹名字过长?
                f_name = f_name[:47] + "..."
            self.tx_new_path.addItem(f_icon,
                                     "id:{:>8},name:{}".format(fid, f_name))

    def set_values(self, infos, all_dirs_dict):
        self.infos = infos
        self.dirs = all_dirs_dict
        self.update_ui()
        self.exec()

    def initUI(self):
        self.setWindowTitle("移动文件(夹)")
        self.setWindowIcon(QIcon(SRC_DIR + "move.ico"))
        self.lb_name = QLabel()
        self.lb_name.setText("文件(夹)名:")
        self.lb_name.setAlignment(Qt.AlignmentFlag.AlignRight
                                  | Qt.AlignmentFlag.AlignTrailing
                                  | Qt.AlignmentFlag.AlignVCenter)
        self.tx_name = AutoResizingTextEdit()
        self.tx_name.setFocusPolicy(Qt.FocusPolicy.NoFocus)  # 只读
        self.tx_name.setReadOnly(True)
        self.lb_new_path = QLabel()
        self.lb_new_path.setText("目标文件夹:")
        self.lb_new_path.setAlignment(Qt.AlignmentFlag.AlignRight
                                      | Qt.AlignmentFlag.AlignTrailing
                                      | Qt.AlignmentFlag.AlignVCenter)
        self.tx_new_path = QComboBox()

        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Orientation.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.StandardButton.Ok
            | QDialogButtonBox.StandardButton.Cancel)
        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定")
        self.buttonBox.button(
            QDialogButtonBox.StandardButton.Cancel).setText("取消")

        self.grid = QGridLayout()
        self.grid.setSpacing(10)
        self.grid.addWidget(self.lb_name, 1, 0)
        self.grid.addWidget(self.tx_name, 1, 1)
        self.grid.addWidget(self.lb_new_path, 2, 0)
        self.grid.addWidget(self.tx_new_path, 2, 1)
        self.grid.addWidget(self.buttonBox, 3, 0, 1, 2)
        self.setLayout(self.grid)
        self.buttonBox.accepted.connect(self.btn_ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.setMinimumWidth(280)

    def btn_ok(self):
        new_id = self.tx_new_path.currentText().split(",")[0].split(":")[1]
        for index in range(len(self.infos)):
            self.infos[index].new_id = int(new_id)
        self.new_infos.emit(self.infos)
Пример #25
0
    def createEditingBar(self):
        """Create dock widget for editing tools."""
        #TODO: Add a tab widget for the different editing tools
        self.editing_bar = QDockWidget("Tools")
        self.editing_bar.setAllowedAreas(
            Qt.DockWidgetAreas.LeftDockWidgetArea
            | Qt.DockWidgetAreas.RightDockWidgetArea)
        self.editing_bar.setMinimumWidth(90)

        # Create editing tool buttons
        filters_label = QLabel("Filters")

        convert_to_grayscale = QToolButton()
        convert_to_grayscale.setIcon(
            QIcon(os.path.join(icon_path, "grayscale.png")))
        convert_to_grayscale.clicked.connect(self.image_label.convertToGray)

        convert_to_RGB = QToolButton()
        convert_to_RGB.setIcon(QIcon(os.path.join(icon_path, "rgb.png")))
        convert_to_RGB.clicked.connect(self.image_label.convertToRGB)

        convert_to_sepia = QToolButton()
        convert_to_sepia.setIcon(QIcon(os.path.join(icon_path, "sepia.png")))
        convert_to_sepia.clicked.connect(self.image_label.convertToSepia)

        change_hue = QToolButton()
        change_hue.setIcon(QIcon(os.path.join(icon_path, "")))
        change_hue.clicked.connect(self.image_label.changeHue)

        brightness_label = QLabel("Brightness")
        self.brightness_slider = QSlider(Qt.Orientations.Horizontal)
        self.brightness_slider.setRange(-255, 255)
        self.brightness_slider.setTickInterval(35)
        self.brightness_slider.setTickPosition(QSlider.TickPosition.TicksAbove)
        self.brightness_slider.valueChanged.connect(
            self.image_label.changeBrighteness)

        contrast_label = QLabel("Contrast")
        self.contrast_slider = QSlider(Qt.Orientations.Horizontal)
        self.contrast_slider.setRange(-255, 255)
        self.contrast_slider.setTickInterval(35)
        self.contrast_slider.setTickPosition(QSlider.TickPosition.TicksAbove)
        self.contrast_slider.valueChanged.connect(
            self.image_label.changeContrast)

        # Set layout for dock widget
        editing_grid = QGridLayout()
        #editing_grid.addWidget(filters_label, 0, 0, 0, 2, Qt.AlignTop)
        editing_grid.addWidget(convert_to_grayscale, 1, 0)
        editing_grid.addWidget(convert_to_RGB, 1, 1)
        editing_grid.addWidget(convert_to_sepia, 2, 0)
        editing_grid.addWidget(change_hue, 2, 1)
        editing_grid.addWidget(brightness_label, 3, 0)
        editing_grid.addWidget(self.brightness_slider, 4, 0, 1, 0)
        editing_grid.addWidget(contrast_label, 5, 0)
        editing_grid.addWidget(self.contrast_slider, 6, 0, 1, 0)
        editing_grid.setRowStretch(7, 10)

        container = QWidget()
        container.setLayout(editing_grid)

        self.editing_bar.setWidget(container)

        self.addDockWidget(Qt.DockWidgetAreas.LeftDockWidgetArea,
                           self.editing_bar)

        self.tools_menu_act = self.editing_bar.toggleViewAction()
Пример #26
0
class PlayerBox(QGroupBox):
    """PlayerBox Subclass of QGroupBox.

    Returns GroupBoxWidget data and cards for each player.
    """

    offsheet = """QGroupBox {
        font-size: 14pt;
        padding: 4px;
        margin: 5px;
        color: #efeefe;
        border: 9px solid #dfa;}"""

    onsheet = """QGroupBox {
        color: red;
        padding: 4px;
        margin: 5px;
        border: 5px solid red;
        border-radius: 2px;}"""

    labelsheet = """QLabel {
        color: #efeefe;
        margin-bottom: 8px;
        font-weight: bold;
        font-size: 14pt;
        font-style: italic;}"""

    scoresheet = """QLabel {
        border: 1px solid #efeefe;
        padding: 3px;
        margin-bottom: 8px;
        color: #efeefe;
        font-weight: bold;
        font-size: 16pt;
        font-style: italic;}"""

    def __init__(self, title, parent=None, player=None):
        """Construct a PlayerBox Widget.

        Args:
            parent (QWidget, optional) Parent widget object. Defaults to None.
            player (Player) The player this box will be assigned to.
        """
        super().__init__(title, parent=parent)
        self.player = player
        self._turn = False
        self.player.set_box(self)
        self.setStyleSheet(self.offsheet)
        self._setupUi()

    def _setupUi(self):
        """Create UI elements."""
        self.vbox = QVBoxLayout()
        self.vbox.setObjectName(self.player.title + "BoxVertLayout")
        self.grid = QGridLayout()
        self.grid.setObjectName(self.player.title + "BoxCardPicsLayout")
        self.hbox = QHBoxLayout()
        self.hbox.setObjectName(self.player.title + "BoxHorizLayout")
        self.vbox.addLayout(self.hbox)
        self.vbox.addLayout(self.grid)
        self.setLayout(self.vbox)
        self._setupLabels()
        self._setupCards()

    def _setupLabels(self):
        """Set up window labels."""
        expolicy = QSizePolicy.Policy.MinimumExpanding
        minpolicy = QSizePolicy.Policy.Minimum
        self.label = QLabel("Score: ")
        self.label.setObjectName("ScoreLabel")
        self.label.setStyleSheet(self.labelsheet)
        self.hbox.addWidget(self.label)
        self.hbox.addSpacerItem(QSpacerItem(10, 0, minpolicy, minpolicy))
        self.scorelabel = QLabel("0")
        self.scorelabel.setObjectName("ScoreValue")
        self.scorelabel.setStyleSheet(self.scoresheet)
        self.hbox.addWidget(self.scorelabel)
        self.hbox.addSpacerItem(QSpacerItem(50, 0, expolicy, minpolicy))

    def _setupCards(self):
        """Create card covers."""
        card = CardWidget(parent=self)
        card.setObjectName("Card1")
        self.addCard(card)
        self.grid.addWidget(card, 0, 0, -1, -1)
        card2 = CardWidget(parent=self)
        card2.setObjectName(self.player.title + "Card2")
        self.addCard(card2)
        self.grid.addWidget(card2, 0, 1, -1, -1)

    @property
    def cardCount(self):
        """Count cards in players hand.

        Returns:
            int: Total number of cards in players hand.
        """
        return len(self.player.cards)

    @property
    def cards(self):
        """Shortcut method accessing players cards property.

        Returns:
            list: List of card widgets.
        """
        return self.player.cards

    def addCard(self, card):
        """Shortcut for adding card widget to players list of cards.

        Args:
            card (obj): CardWidget object.
        """
        self.player.cards.append(card)

    def deleteCard(self, card):
        """Remove card from Players list of cards property."""
        if card in self.player.cards:
            self.player.cards.remove(card)

    def reset(self):
        """Clear PlayerBox of all widgets.

        Called when current round ends and new deal begins.
        """
        while len(self.cards) > 0:
            card = self.cards[0]
            self.grid.removeWidget(card)
            card.setVisible(False)
            card.hide()
            card.destroy(True, True)
            self.deleteCard(card)
            del card
            self.repaint()
            self.update()

    def addWidget(self, card):
        """Add another card to Window.

        Args:
            card (obj): Card object from deck.

        Returns:
            bool: True if successful else None
        """
        if self.cardCount <= 2:
            for widget in self.cards:
                if not widget.has_card():
                    return widget.setCard(card)
        widget = CardWidget(card=card)
        widget.setObjectName("Card" + str(self.cardCount))
        self.grid.addWidget(widget, 0, self.cardCount, -1, -1)
        return self.addCard(widget)

    def isTurn(self):
        """Return True if currently players turn.

        Returns:
            bool: True if it's players turn else false.
        """
        return self._turn

    def turn(self):
        """Flip `self.turn` property False or True.

        Changes the style of PlayerBox to indicate if it
        is or isn't currently players turn.
        """
        if self.isTurn():
            self._turn = False
            self.setStyleSheet(self.offsheet)
        else:
            self._turn = True
            self.setStyleSheet(self.onsheet)
Пример #27
0
class MainWindow(QWidget):
    def reload(self):
        if len(self.file_list): return
        self.webEngineView.reload()

    def on_downloadRequestState(self,event):
        if not len(self.file_list):
            self.label.setText('Статус:...')
            self.reload()
            try:
                for b in self.buttons: b.setEnabled(True)
            except: pass
            return
        if event.value>1:
            if event.value==2:
                if len(self.file_list[-1])>5:
                    h0=self.file_list[-1][6]
                    h1=gethash(self.file_list[-1][-1])
                    if h0==h1:
                        try:
                            tm=mktime(datetime.strptime(self.file_list[-1][4],"%d.%m.%Y %H:%M").timetuple())
                            tm+=(int(self.file_list[-1][5])%60)
                            utime(self.file_list[-1][-1],(tm,tm))
                        except: pass
                    else:
                        print('Error. ("%s") - %i'%(self.file_list[-1][-1],event.value))
                        self.label.setText('Статус: ошибка скачивания файла ("'+self.file_list[-1][-1]+'")')
                self.file_list.pop()
                self.download_files()
            else:
                print('Error. ("%s") - %i'%(self.file_list[-1][-1],event.value))
                self.label.setText('Статус: ошибка скачивания файла ("%s", код ошибки: %i)!'%(self.file_list[-1][-1],event.value))
                self.reload()
                try:
                    for b in self.buttons: b.setEnabled(True)
                except: pass

    def check_canceled(self,event):
        if event: self.canceled_callback()

    def on_downloadRequested(self,event):
        self.webEngineView.page().runJavaScript(\
            """
            function check_canceled(){
                if(window.process_canceled) return 1;
                else return 0;
            };
            check_canceled();
            """,self.check_canceled)
        if event.state().value==0:
            event.stateChanged.connect(lambda event: self.on_downloadRequestState(event))
            event.accept()

    def download_files(self):
        if len(self.file_list):
            if not self.file_number: self.file_number=len(self.file_list)
            tmp=self.file_list[-1]
            if exists(tmp[-1]):
                try: remove(tmp[-1])
                except: pass
            self.webEngineView.page().profile().downloadRequested.connect(lambda event:\
                self.on_downloadRequested(event))
            self.label.setText('Статус: скачивание файла "%s" ( %i из %i )'%\
                               (tmp[2],self.file_number-len(self.file_list)+1,self.file_number))
            self.webEngineView.page().download(QUrl(tmp[3]),tmp[-1])
        else:
            self.webEngineView.page().profile().downloadRequested.disconnect()
            self.label.setText('Статус:...')
            self.reload()
            try:
                for b in self.buttons: b.setEnabled(True)
            except: pass

    def canceled_callback(self):
        self.label.setText('Статус: операция отменена!')
        self.file_list=[]
        self.file_number=0
        self.reload()
        try:
            for b in self.buttons: b.setEnabled(True)
        except: pass

    def getfilelist_error_callback(self):
        self.label.setText('Статус: ошибка при получении списка файлов для скачивания!')
        self.file_list=[]
        self.file_number=0
        self.reload()
        try:
            for b in self.buttons: b.setEnabled(True)
        except: pass

    def getfilelist_success_callback(self,links):
        for link in links:
            path=join(self.basepath,link[0],link[1])
            try: makedirs(path,exist_ok=True)
            except: return
            link.append(realpath(join(path,link[2])))
            self.file_list.append(link)
        if len(self.file_list):
            self.download_files()

    def progress_callback(self,counter):
        self.label.setText('Статус: получение списка файлов для скачивания (получено %d ссылок)...'%counter)

    def getfileslist(self):
        if len(self.file_list): return
        self.url=self.webEngineView.url().toString()
        if not('Files/prt0' in self.url): return
        self.file_list=[]
        self.file_number=0
        try:
            for b in self.buttons: b.setEnabled(False)
        except: pass
        self.label.setText('Статус: получение списка файлов для скачивания...')
        self.webEngineView.page().runJavaScript(\
            self.qwebchannel_js+self.busy+"""
            function get_sig_links_details_parse(file_links,details_links,partitions,partition,section,data){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                var parser=new DOMParser();
                var doc=parser.parseFromString(data,'text/html');
                var req=doc.querySelectorAll('a[href*=\"GetFile\"]');
                for(const e of req){
                    if(e.text.includes('.sig')){
                        file_links.push([pd_replace(partition),sec_replace(section),e.text,e.href]);
                        progress(file_links);
                    };
                };
                if(details_links.length) get_sig_links_details(file_links,details_links,partitions);
                else success(file_links);
            };
            function start_parser(){
                var file_links=[];
                var details_links=[];
                var url=window.location.href.toString();
                var path='';
                if(url.includes('ProjectDocuments')) path='ProjectDocuments';
                else if(url.includes('RIIDocuments')) path='RIIDocuments';
                    else if(url.includes('SmetaDocuments')) path='SmetaDocuments';
                        else if(url.includes('IrdDocuments')) path='IrdDocuments';
                var href=''.concat('https://lk.spbexp.ru/Grid/',path,'FilesRead/own',
                    window.location.href.toString().split('\/').pop());
                var v=document.querySelector('span[style=\"font-weight:600; color:darkblue\"]');\
                if(v==null) return;
                var section=v.textContent;
                var links=[[path,section,href]];
                new QWebChannel(qt.webChannelTransport,(channel)=>{
                    window.qtwebchannel=channel.objects.backend;
                });
                get_pd_links_details(links,file_links,details_links,[]);
            };
            start_parser();
            """,lambda x: None)

    def getallfileslist(self):
        if len(self.file_list): return
        self.url=self.webEngineView.url().toString()
        if not('lk.spbexp.ru/Zeg/Zegmain' in self.url or\
               ('lk.spbexp.ru/SF/' in self.url and '/prt0/' in self.url)): return
        self.file_list=[]
        self.file_number=0
        try:
            for b in self.buttons: b.setEnabled(False)
        except: pass
        self.label.setText('Статус: получение списка файлов для скачивания...')
        self.webEngineView.page().runJavaScript(\
            self.qwebchannel_js+self.busy+"""
            function get_sig_links_details_parse(file_links,details_links,partitions,partition,section,data){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                var parser=new DOMParser();
                var doc=parser.parseFromString(data,'text/html');
                var req=doc.querySelectorAll('a[href*=\"GetFile\"]');
                for(const e of req){
                    if(e.text.includes('.sig')){
                        file_links.push([pd_replace(partition),sec_replace(section),e.text,e.href]);
                        progress(file_links);
                    };
                };
                if(details_links.length) get_sig_links_details(file_links,details_links,partitions);
                else get_file_links(file_links,details_links,partitions);
            };
            function get_pd_links_parse(path,file_links,details_links,partitions,data){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                var links=[];
                for(const d of data.Data){
                    if(d['NumberOfFiles']){
                        var href=''.concat('https://lk.spbexp.ru/Grid/',path,'FilesRead/own',d['IDRow']);
                        if(path.includes('IrdDocuments')) links.push([path,d['Content'],href]);
                        else links.push([path,d['Nazvanie'],href]);
                    };
                };
                if(links.length) get_pd_links_details(links,file_links,details_links,partitions);
            };
            async function get_pd_links(path,file_links,details_links,partitions){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                var req=document.querySelector('a[href*="/Zeg/Zegmain1"]');
                if(req){
                    var href=''.concat('https://lk.spbexp.ru/Grid/',path,'Read/own',req.pathname.split('\/').pop());
                    return await fetch(href)
                                .then(async (response) => {
                                const j=await response.json();
                                get_pd_links_parse(path,file_links,details_links,partitions,j);
                                }).catch((error) => { errlog(error); });
                };
            };
            function get_file_links(file_links,details_links,partitions){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                if(partitions.length) get_pd_links(partitions.pop(),file_links,details_links,partitions);
                else success(file_links);
            };
            function start_parser(){
                var file_links=[];
                var details_links=[];
                var partitions=['ProjectDocuments','RIIDocuments','SmetaDocuments','IrdDocuments'];
                new QWebChannel(qt.webChannelTransport,(channel)=>{
                    window.qtwebchannel=channel.objects.backend;
                });
                get_file_links(file_links,details_links,partitions);
            };
            start_parser();
            """,lambda x: None)

    def __init__(self):
        super().__init__()
        self.setWindowTitle('ExpGet')
        self.busy="""
            window.process_canceled=false;
            function errlog(error){
                window.qtwebchannel.backrun_error(error);
            };
            function success(file_links){
                window.qtwebchannel.backrun_success(file_links);
            };
            function progress(file_links){
                window.qtwebchannel.backrun_progress(file_links.length);
            };
            async function cancel(){
                window.qtwebchannel.backrun_cancel();
            };
            function pd_replace(partition){
                switch(partition){
                    case 'ProjectDocuments': return 'ПД';
                    case 'RIIDocuments': return 'РИИ';
                    case 'SmetaDocuments': return 'СД';
                    case 'IrdDocuments': return 'ИРД';
                };
            };
            function sec_replace(section){
                return section.trim().replaceAll('"','_').slice(0,64).trim();
            };
            async function get_sig_links_details(file_links,details_links,partitions){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                if(details_links.length){
                    var d=details_links.pop();
                    return await fetch(d[2])
                                .then(async (response) => {
                                    const j=await response.text();
                                    get_sig_links_details_parse(file_links,details_links,partitions,d[0],d[1],j);
                                }).catch((error) => { errlog(error); });
                };
            };
            function get_pd_links_details_parse(links,file_links,details_links,partitions,partition,section,data){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                for(const d of data.Data){
                    file_links.push([pd_replace(partition),sec_replace(section),d['Nazvanie'],
                        ''.concat('https://lk.spbexp.ru/File/GetFile/',d['IDRow']),d['sDateTo'],d['Number'],d['sMD5']]);
                    progress(file_links);
                    details_links.push([partition,section,''.concat('https://lk.spbexp.ru/SF/FileCspViewer/',d['IDRow'])]);
                };
                if(links.length) get_pd_links_details(links,file_links,details_links,partitions);
                else get_sig_links_details(file_links,details_links,partitions);
            };
            async function get_pd_links_details(links,file_links,details_links,partitions){
                if(window.process_canceled){
                    cancel();
                    return;
                };
                if(links.length){
                    var d=links.pop();
                    return await fetch(d[2])
                                .then(async (response) => {
                                    const j=await response.json();
                                    get_pd_links_details_parse(links,file_links,details_links,partitions,d[0],d[1],j);
                                }).catch((error) => { errlog(error); });
                };
            };
            function button_click(){
                window.process_canceled=true;
            };
            class ProgressRing extends HTMLElement{
                constructor(){
                    super();
                    const stroke=this.getAttribute('stroke');
                    const radius=this.getAttribute('radius');
                    const normalizedRadius=radius-stroke*2;
                    this._circumference=normalizedRadius*2*Math.PI;
                    this._root=this.attachShadow({mode:'open'});
                    this._root.innerHTML=`
                        <svg height="${radius*2}" width="${radius*2}">
                            <circle
                                class="ring"
                                stroke="#3c3b3a"
                                stroke-width="${stroke*2}"
                                stroke-opacity="0.5"
                                fill="transparent"
                                r="${normalizedRadius}"
                                cx="${radius}"
                                cy="${radius}"
                                shape-rendering="geometricPrecision"
                            />
                            <circle
                                class="ring"
                                stroke="#c8c5c3"
                                stroke-dasharray="${this._circumference} ${this._circumference}"
                                style="stroke-dashoffset:${this._circumference}"
                                stroke-width="${stroke}"
                                fill="transparent"
                                r="${normalizedRadius}"
                                cx="${radius}"
                                cy="${radius}"
                                shape-rendering="geometricPrecision"
                            />
                            <circle
                                class="button"
                                stroke="#191919"
                                stroke-width="1"
                                fill="#f44336"
                                r="${normalizedRadius-stroke}"
                                cx="${radius}"
                                cy="${radius}"
                                shape-rendering="geometricPrecision"
                                onclick="button_click()"
                            />
                            <text class="txt" x="50%" y="52%" text-rendering="geometricPrecision">STOP</text>
                            <circle
                                class="ring"
                                stroke="#000000"
                                stroke-width="1"
                                stroke-opacity="0.5"
                                fill="transparent"
                                r="${normalizedRadius+8}"
                                cx="${radius}"
                                cy="${radius}"
                                shape-rendering="geometricPrecision"
                            />
                        </svg>
                        <style>
                            .ring {
                                transition: stroke-dashoffset 0.35s;
                                transform: rotate(-90deg);
                                transform-origin: 50% 50%;
                                pointer-events: none;
                            }
                            .button:hover {
                                fill: #ce000f;
                                opacity: 1;
                            }
                            .txt {
                                font: bold 40px sans-serif;
                                fill: #323232;
                                stroke: #4c4c4c;
                                stroke-width: 1px;
                                text-anchor: middle;
                                dominant-baseline: middle;
                                pointer-events: none;
                            }
                        </style>
                    `;
                }
                setProgress(percent){
                    const offset=this._circumference-(percent/100*this._circumference);
                    const circle=this._root.querySelectorAll('circle')[1];
                    circle.style.strokeDashoffset=offset;
                }
                setTransition(value){
                    const circle=this._root.querySelectorAll('circle')[1];
                    circle.style.transition='stroke-dashoffset '+value+'s';
                }
                static get observedAttributes(){ return ['progress','transition']; }
                attributeChangedCallback(name,oldValue,newValue){
                    if(name==='progress') this.setProgress(newValue);
                    if(name==='transition') this.setTransition(newValue);
                }
            }
            function overlay() {
                [].forEach.call(document.querySelectorAll('nav'), function (el) {
                    el.style.visibility = 'hidden';
                });
                [].forEach.call(document.querySelectorAll('*[class*=popover]'), function (el) {
                    el.style.visibility = 'hidden';
                });
                var overlay=document.createElement("div");
                overlay.style.opacity=0.9;
                overlay.style.width='100%';
                overlay.style.height='100%';
                overlay.style.top='0px';
                overlay.style.left='0px';
                overlay.style.backgroundColor='#666666';
                overlay.style.zIndex='1000';
                overlay.style.position = 'absolute';
                document.getElementsByTagName('body')[0].appendChild(overlay);
                window.customElements.define('progress-ring',ProgressRing);
                const circle=document.createElement("div");
                circle.innerHTML=`<progress-ring stroke="8" radius="88" progress="0"></progress-ring>`
                circle.style.top='50%';
                circle.style.left='50%';
                circle.style.marginTop='-88px'
                circle.style.marginLeft='-88px'
                circle.style.zIndex='2000';
                circle.style.position='absolute';
                window.cprogress=0;
                document.body.appendChild(circle);
                document.body.style.overflow='hidden';
            };
            overlay();
            const interval=setInterval(()=>{
                const el=document.querySelector('progress-ring');
                if(window.cprogress==200){
                    el.setAttribute('transition','0');
                    window.cprogress=0;
                    el.setAttribute('progress',window.cprogress);
                }
                else{
                    if(window.cprogress==0) el.setAttribute('transition','0.35');
                    window.cprogress+=2;
                    el.setAttribute('progress',window.cprogress);
                };
            },100);
        """

        self.webEngineView=QWebEngineView()
        ws=self.webEngineView.page().profile().defaultProfile()
        ws.setHttpCacheMaximumSize(0)
        ws=self.webEngineView.settings()
        ws.setAttribute(ws.WebAttribute.AutoLoadImages,True)
        ws.setAttribute(ws.WebAttribute.PluginsEnabled,False)

        qwebchannel_js=QFile(':/qtwebchannel/qwebchannel.js')
        if not qwebchannel_js.open(QIODeviceBase.OpenModeFlag.ReadOnly):
            raise SystemExit(
                'Failed to load qwebchannel.js with error: %s' %
                qwebchannel_js.errorString())
        self.qwebchannel_js=bytes(qwebchannel_js.readAll()).decode('utf-8')
        self.channel=QWebChannel()
        self.handler=CallHandler()
        self.handler.set_parent(self)
        self.channel.registerObject('backend',self.handler)
        self.webEngineView.page().setWebChannel(self.channel)

        self.grid=QGridLayout()
        self.grid.setContentsMargins(0,0,0,0)
        self.grid.setVerticalSpacing(0)
        self.grid.setHorizontalSpacing(0)
        self.hbox=QHBoxLayout()
        self.hbox.setSpacing(0)
        self.reload_button=QPushButton('Обновить страницу')
        self.get_data_button=QPushButton('Получить данные')
        self.get_all_data_button=QPushButton('Скачать данные проекта')
        self.buttons=[self.reload_button,self.get_data_button,self.get_all_data_button]
        self.hbox.addWidget(self.reload_button,1)
        self.hbox.addWidget(self.get_data_button,1)
        self.hbox.addWidget(self.get_all_data_button,1)
        self.grid.addLayout(self.hbox,0,0)
        self.grid.addWidget(self.webEngineView,1,0)
        self.label=QLabel('Статус:...')
        self.label.setStyleSheet("QLabel {background-color:gray;color:black;}")
        self.grid.addWidget(self.label,2,0)
        self.grid.setRowStretch(0,0)
        self.grid.setRowStretch(1,1)
        self.grid.setRowStretch(2,0)
        self.setLayout(self.grid)

        self.webEngineView.load(QUrl('https://lk.spbexp.ru'))
        self.webEngineView.loadFinished.connect(self.login)

        self.file_list=[]
        self.file_number=0
        self.lock=False
        self.basepath=realpath('out')
        try: makedirs(self.basepath,exist_ok=True)
        except: pass

        self.reload_button.clicked.connect(self.reload)
        self.get_data_button.clicked.connect(self.getfileslist)
        self.get_all_data_button.clicked.connect(self.getallfileslist)

    def goto_projects(self):
        self.webEngineView.loadFinished.disconnect()
        self.webEngineView.load(QUrl('https://lk.spbexp.ru/SF/Zayava/'))

    def login_callback(self,result):
        if len(result):
            self.webEngineView.loadFinished.connect(self.goto_projects)

    def login(self):
        l=p=''
        try:
            f=open('login','r')
            d=f.readlines()
            f.close()
            l=d[0].strip()
            p=d[1].strip()
        except:
            self.webEngineView.loadFinished.disconnect()
            return
        self.webEngineView.page().runJavaScript("""
            function find_login_form(){
                var v=document.querySelector('input[id=Login]');
                if(v!=null){
                    v.value=`%s`;
                    v=document.querySelector('input[id=Password]');
                    if(v!=null){
                        v.value=`%s`;
                        v=document.querySelector('button[type=submit]');
                        if(v!=null){
                            v.click();
                            return 'ok';
                        };
                    };
                };
                return '';
            };
            find_login_form();"""%(l,p),self.login_callback)
Пример #28
0
class RenameDialog(QDialog):
    out = pyqtSignal(object)

    def __init__(self, parent=None):
        super(RenameDialog, self).__init__(parent)
        self.infos = []
        self.min_width = 400
        self.initUI()
        self.update_text()
        self.setStyleSheet(dialog_qss_style)

    def set_values(self, infos=None):
        self.infos = infos or []
        self.update_text()  # 更新界面

    def initUI(self):
        self.setWindowIcon(QIcon(SRC_DIR + "desc.ico"))
        self.lb_name = QLabel()
        self.lb_name.setText("文件夹名:")
        self.lb_name.setAlignment(Qt.AlignmentFlag.AlignRight
                                  | Qt.AlignmentFlag.AlignTrailing
                                  | Qt.AlignmentFlag.AlignVCenter)
        self.tx_name = QLineEdit()
        self.lb_desc = QLabel()
        self.tx_desc = QTextEdit()
        self.lb_desc.setText("描  述:")
        self.lb_desc.setAlignment(Qt.AlignmentFlag.AlignRight
                                  | Qt.AlignmentFlag.AlignTrailing
                                  | Qt.AlignmentFlag.AlignVCenter)

        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Orientation.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.StandardButton.Ok
            | QDialogButtonBox.StandardButton.Cancel)
        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText("确定")
        self.buttonBox.button(
            QDialogButtonBox.StandardButton.Cancel).setText("取消")

        self.grid = QGridLayout()
        self.grid.setSpacing(10)
        self.grid.addWidget(self.lb_name, 1, 0)
        self.grid.addWidget(self.tx_name, 1, 1)
        self.grid.addWidget(self.lb_desc, 2, 0)
        self.grid.addWidget(self.tx_desc, 2, 1, 5, 1)
        self.grid.addWidget(self.buttonBox, 7, 1, 1, 1)
        self.setLayout(self.grid)
        self.buttonBox.accepted.connect(self.btn_ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

    def update_text(self):
        self.tx_desc.setFocus()
        num = len(self.infos)
        if num == 1:
            self.lb_name.setVisible(True)
            self.tx_name.setVisible(True)
            infos = self.infos[0]
            self.buttonBox.button(
                QDialogButtonBox.StandardButton.Ok).setToolTip("")  # 去除新建文件夹影响
            self.buttonBox.button(
                QDialogButtonBox.StandardButton.Ok).setEnabled(
                    True)  # 去除新建文件夹影响
            self.setWindowTitle("修改文件夹名与描述")
            self.tx_name.setText(str(infos.name))
            if infos.desc:
                self.tx_desc.setText(str(infos.desc))
                self.tx_desc.setToolTip('原描述:' + str(infos.desc))
            else:
                self.tx_desc.setText("")
                self.tx_desc.setToolTip('')
            self.tx_desc.setPlaceholderText("无")
            self.min_width = len(str(infos.name)) * 8
            if infos.is_file:
                self.setWindowTitle("修改文件描述")
                self.tx_name.setFocusPolicy(Qt.FocusPolicy.NoFocus)
                self.tx_name.setReadOnly(True)
            else:
                self.tx_name.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
                self.tx_name.setReadOnly(False)
                self.tx_name.setFocus()
        elif num > 1:
            self.lb_name.setVisible(False)
            self.tx_name.setVisible(False)
            self.setWindowTitle(f"批量修改{num}个文件(夹)的描述")
            self.tx_desc.setText('')
            self.tx_desc.setPlaceholderText("建议160字数以内。")

        else:
            self.setWindowTitle("新建文件夹")
            self.tx_name.setText("")
            self.buttonBox.button(
                QDialogButtonBox.StandardButton.Ok).setEnabled(False)
            self.buttonBox.button(
                QDialogButtonBox.StandardButton.Ok).setToolTip("请先输入文件名!")
            self.tx_name.textChanged.connect(self.slot_new_ok_btn)
            self.tx_name.setPlaceholderText("不支持空格,如有会被自动替换成 _")
            self.tx_name.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
            self.tx_name.setReadOnly(False)
            self.tx_desc.setPlaceholderText("可选项,建议160字数以内。")
            self.tx_name.setFocus()
        if self.min_width < 400:
            self.min_width = 400
        self.resize(self.min_width, 200)

    def slot_new_ok_btn(self):
        """新建文件夹槽函数"""
        self.buttonBox.button(
            QDialogButtonBox.StandardButton.Ok).setEnabled(True)
        self.buttonBox.button(
            QDialogButtonBox.StandardButton.Ok).setToolTip("")

    def btn_ok(self):
        new_name = self.tx_name.text()
        new_des = self.tx_desc.toPlainText()
        info_len = len(self.infos)
        if info_len == 0:  # 在 work_id 新建文件夹
            if new_name:
                self.out.emit(("new", new_name, new_des))
        elif info_len == 1:
            if new_name != self.infos[0].name or new_des != self.infos[0].desc:
                self.infos[0].new_des = new_des
                self.infos[0].new_name = new_name
                self.out.emit(("change", self.infos))
        else:
            if new_des:
                for infos in self.infos:
                    infos.new_des = new_des
                self.out.emit(("change", self.infos))
Пример #29
0
class Services(QWidget):
    def __init__(self, parent, top):
        super(QWidget, self).__init__(parent)
        self.top = top
        hlayout = QHBoxLayout()
        self.layout = QGridLayout()
        hlayout.addLayout(self.layout)
        hlayout.setAlignment(hlayout, Qt.Alignment.AlignTop)
        self.setLayout(hlayout)
        self.row = 0

        self.__addLabel__("Gateway Services")
        self.__addLabel__("Gateway Host Name/IP Address")
        self.gatewayHostName = QLineEdit(self)
        self.__addInput__(self.gatewayHostName)

        self.__addLabel__("Exercise Data Server Host Name/IP Address")
        self.productionEDS = QLineEdit(self)
        self.prodEnable = QRadioButton("Production")
        self.prodEnable.setChecked(True)
        self.prodEnable.toggled.connect(self.radioProdClicked)
        self.prodEnable.setStyleSheet("QRadioButton{ width: 100; }")
        self.__addInputAndRadio__(self.productionEDS, self.prodEnable)
        self.testEDS = QLineEdit(self)
        self.testEnable = QRadioButton("Test")
        self.testEnable.toggled.connect(self.radioTestClicked)
        self.testEnable.setStyleSheet("QRadioButton{ width: 100; }")
        self.__addInputAndRadio__(self.testEDS, self.testEnable)

        self.__addLabel__("Messaging Port")
        self.messagePort = QLineEdit("61616")
        self.__addInput__(self.messagePort)

    def radioProdClicked(self):
        if self.sender().isChecked():
            self.testEnable.setChecked(False)

    def radioTestClicked(self):
        if self.sender().isChecked():
            self.prodEnable.setChecked(False)

    def __addLabel__(self, label):
        lbl = QLabel(label)
        self.layout.addWidget(lbl, self.row, 0, 1, -1)
        self.row += 1

    def __addInput__(self, input):
        self.layout.addWidget(input, self.row, 0, 1, 4)
        self.row += 1

    def __addInputAndRadio__(self, input, radio):
        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 0, 0)
        hbox.addWidget(input)
        hbox.addWidget(radio)
        widget = QWidget(self)
        widget.setLayout(hbox)
        self.layout.addWidget(widget, self.row, 0, 1, -1)
        self.row += 1

    def tabName(self):
        return 'Services'
Пример #30
0
class Window(QWidget):

    def __init__(self, parent=None):
        #init methods runs every time, use for core app stuff)
        super(Window, self).__init__()
        #self.setWindowTitle("MorphoMetriX")
        #self.setGeometry(50, 50, 100, 200)  #x,y,width,height
        #self.setStyleSheet("background-color: rgb(0,0,0)") #change color
        #self.setStyleSheet("font-color: rgb(0,0,0)") #change color

        self.label_id = QLabel("Image ID")
        self.id = QLineEdit()
        self.id.setText('0000')

        #Define custom attributes for pixel -> SI conversion
        self.label_foc = QLabel("Focal Length (mm):")
        self.focal = QLineEdit()
        self.focal.setText('50')

        self.label_alt = QLabel("Altitude (m):")
        self.altitude = QLineEdit()
        self.altitude.setText('50')

        self.label_pd = QLabel("Pixel Dimension (mm/pixel)")
        self.pixeldim = QLineEdit()
        self.pixeldim.setText('0.00391667')

        self.label_widths = QLabel("# Width Segments:")
        self.numwidths = QLineEdit()
        self.numwidths.setText('10')

        self.label_not = QLabel("Notes:")
        self.notes = QPlainTextEdit()

        # self.manual = QWebEngineView()
        #fpath = os.path.abspath('/Users/WalterTorres/Dropbox/KC_WT/MorphoMetrix/morphometrix/README.html')
        #webpage = QtCore.QUrl.fromLocalFile(fpath)
        # webpage = QtCore.QUrl('https://wingtorres.github.io/morphometrix/')
        # self.manual.setUrl(webpage)

        self.exit = QPushButton("Exit", self)
        self.exit.clicked.connect(self.close_application)

        self.grid = QGridLayout()
        self.grid.addWidget(self.label_id, 1, 0)
        self.grid.addWidget(self.id, 1, 1)
        self.grid.addWidget(self.label_foc, 2, 0)
        self.grid.addWidget(self.focal, 2, 1)
        self.grid.addWidget(self.label_alt, 3, 0)
        self.grid.addWidget(self.altitude, 3, 1)
        self.grid.addWidget(self.label_pd, 4, 0)
        self.grid.addWidget(self.pixeldim, 4, 1)
        self.grid.addWidget(self.label_widths, 5, 0)
        self.grid.addWidget(self.numwidths, 5, 1)
        self.grid.addWidget(self.label_not, 6, 0)
        self.grid.addWidget(self.notes, 6, 1)
        # self.grid.addWidget(self.manual, 8,0,1,4)
        self.grid.addWidget(self.exit, 7, 3)
        self.setLayout(self.grid)

    def close_application(self):
        choice = QMessageBox.question(self, 'exit', "Exit program?",
                                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        if choice == QMessageBox.StandardButton.Yes:
            self.parent().deleteLater()
            self.parent().close()
        else:
            pass