Beispiel #1
0
class ButtonBar(QFrame):
    buttonClicked = pyqtSignal(
        str, int
    )  # Indicates the iteration number and iteration name of the button that was clicked

    def __init__(self, items: t_.Sequence[str], parent=None):
        super().__init__(parent=parent)
        # self.setFrameStyle(QFrame.Panel)
        self._bGroup = QButtonGroup(self)
        l = QHBoxLayout(self)
        for i, itemName in enumerate(items):
            b = QPushButton(itemName, parent=self)
            b.setCheckable(True)  # Toggleable
            self._bGroup.addButton(b, id=i)
            l.addWidget(b)
        self._selectedButtonId = self._bGroup.id(self._bGroup.buttons()[0])
        self._bGroup.buttons()[0].click(
        )  # Make sure at least one button is selected.
        self._bGroup.buttonClicked.connect(self._buttonSelected)
        l.setSpacing(1)  # Move buttons close together
        l.setContentsMargins(0, 0, 0, 0)
        w = QFrame(self)
        w.setFrameStyle(QFrame.Box)
        w.setLayout(l)
        scrollArea = QScrollArea(parent=self)
        scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        scrollArea.setStyleSheet("""QScrollBar:horizontal {
             height:10px;     
         }""")
        scrollArea.setWidget(w)
        scrollArea.setFixedHeight(10 + w.height())
        ll = QHBoxLayout()
        ll.setContentsMargins(0, 0, 0, 0)
        ll.addWidget(scrollArea)
        self.setLayout(ll)

    def _buttonSelected(self, btn):
        self._selectedButtonId = self._bGroup.id(btn)
        self.buttonClicked.emit(btn.text(), self._bGroup.id(btn))

    def getSelectedButtonId(self):
        return self._selectedButtonId

    def selectNextButton(self):
        id = self._selectedButtonId + 1
        if id >= len(self._bGroup.buttons()):
            id = 0
        self.setButtonSelected(id)

    def setButtonSelected(self, ID: int):
        btn = self._bGroup.button(ID)
        btn.click()
Beispiel #2
0
class GSideToolbar(QWidget):
    selectionChanged = pyqtSignal(str)

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

        self.selectedId = None

        self.mainLayout = QVBoxLayout(self)
        self.buttonGroup = QButtonGroup()
        self.buttons = {}

        for button in buttons:
            b = QPushButton(button.name)
            self.buttonGroup.addButton(b)
            self.buttonGroup.setId(b, button.id)
            self.buttons[button.id] = b
            self.mainLayout.addWidget(b)

        self.buttonGroup.buttonClicked.connect(self.buttonClicked)

        self.mainLayout.addStretch()

    def buttonState(self, state):
        pass

    def buttonClicked(self, button : QPushButton):
        buttonId = self.buttonGroup.id(button)
        buttonName = self.buttons[buttonId].text()
        self.selectionChanged.emit(buttonName)

    @staticmethod
    def createButton(text, icon):
        pass
Beispiel #3
0
class GSideToolbar(QWidget):
    selectionChanged = pyqtSignal(str)

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

        self.selectedId = None

        self.mainLayout = QVBoxLayout(self)
        self.buttonGroup = QButtonGroup()
        self.buttons = {}

        for button in buttons:
            b = QPushButton(button.name)
            self.buttonGroup.addButton(b)
            self.buttonGroup.setId(b, button.id)
            self.buttons[button.id] = b
            self.mainLayout.addWidget(b)

        self.buttonGroup.buttonClicked.connect(self.buttonClicked)

        self.mainLayout.addStretch()

    def buttonState(self, state):
        pass

    def buttonClicked(self, button: QPushButton):
        buttonId = self.buttonGroup.id(button)
        buttonName = self.buttons[buttonId].text()
        self.selectionChanged.emit(buttonName)

    @staticmethod
    def createButton(text, icon):
        pass
Beispiel #4
0
class PstnSettingsWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.layout = QVBoxLayout()
        self.form_layout = QFormLayout()

        self.setup_heading()

        self.button_group = QGroupBox("Mandatory Fields are Marked with *")
        self.layout.addWidget(self.button_group)
        self.v_box = QVBoxLayout()
        self.button_group.setLayout(self.v_box)

        self.setup_pstn_settings_form()
        self.v_box.addLayout(self.form_layout)

        self.setup_ip_form()
        self.v_box.addLayout(self.ip_form_layout)

        self.init_settings()

        self.setup_buttons()
        self.v_box.addWidget(QLabel())
        self.v_box.addLayout(self.button_layout)

        self.setLayout(self.layout)

    def setup_buttons(self):
        self.button_layout = QHBoxLayout()

        back_button_creator = BackButton()
        self.back_button = back_button_creator.create_back_button()
        self.button_layout.addWidget(self.back_button)

        self.add_ip_address_button = QPushButton("Add IP Address", self)
        self.add_ip_address_button.setToolTip("Add another contact IP address")
        self.button_layout.addWidget(self.add_ip_address_button)

        self.apply_settings_button = QPushButton("Apply")
        self.apply_settings_button.setToolTip(
            "Update Sip Trunk settings for contact between your IVR and telephone provider")
        self.button_layout.addWidget(self.apply_settings_button)

    def setup_ip_form(self):
        self.ip_form_layout = QFormLayout()
        self.ip_addresses = []
        self.delete_button_group = QButtonGroup(self)
        self.delete_layouts = []
        self.settings = QSettings("gp_ivr_settings", "GP_IVR_Settings")

    def setup_pstn_settings_form(self):
        self.form_layout.addRow("", QLabel())

        self.pjsip_port = QLineEdit()
        self.pjsip_port.setToolTip("The port that your telephone provider will connect to the IVR with")
        self.provider_address = QLineEdit()
        self.provider_address.setToolTip("The SIP address that the IVR can contact the telephone provider through")
        self.provider_port = QLineEdit()
        self.provider_port.setToolTip("The port through which the telephone provider uses in communications")

        self.form_layout.addRow("Asterisk PJSIP Port (default is 5160):", self.pjsip_port)
        self.form_layout.addRow("*Provider Contact Address:", self.provider_address)
        self.form_layout.addRow("Provider Contact Port:", self.provider_port)
        grow_label = QLabel()
        self.form_layout.addRow("Provider Contact IP Addresses:", grow_label)
        grow_label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)

    def setup_heading(self):
        heading_font = QFont('Arial', 12)
        heading_font.setBold(True)

        heading = QLabel("SIP Trunk Settings:")
        heading.setFont(heading_font)
        self.layout.addWidget(QLabel())
        self.layout.addWidget(heading)

        page_info = QLabel(
            "You can change your telephone service provider SIP trunk settings here.\nThese settings must be updated from the default before running an IVR.\nMake sure that you have created a SIP trunk with your telephone provider.")
        self.layout.addWidget(page_info)
        self.layout.addWidget(QLabel())

    def init_settings(self):
        self.pjsip_port.setText(self.settings.value("pjsip port"))
        self.provider_address.setText(self.settings.value("provider contact address"))
        self.provider_port.setText(self.settings.value("provider contact port"))
        saved_ip_addresses = self.settings.value("provider ip addresses")

        if saved_ip_addresses is not None:
            new_ip_addresses = list(saved_ip_addresses.split(","))
            del new_ip_addresses[-1]
            for ip_address in new_ip_addresses:
                self.add_ip_address(value=ip_address)

    def add_ip_address(self, value=None):
        layout = QHBoxLayout()
        delete_ip_address_button = QPushButton("Delete", self)
        delete_ip_address_button.setToolTip("Remove this contact IP address")
        new_ip_address = QLineEdit()
        new_ip_address.setToolTip("IP address that the telephone provider will contact the IVR with")
        layout.addWidget(new_ip_address)
        layout.addWidget(delete_ip_address_button)
        if value is not None:
            new_ip_address.setText(value)
        self.ip_form_layout.addRow("IP Address " + str(len(self.ip_addresses)), layout)
        self.ip_addresses.append(new_ip_address)
        self.delete_button_group.addButton(delete_ip_address_button)

    def apply_settings(self):
        self.save_settings()
        ip_addresses = []

        if not self.pjsip_port.text():
            pjsip_port_text = "5160"
        else:
            pjsip_port_text = self.pjsip_port.text()

        if not self.provider_port.text():
            provider_port_text = "5060"
        else:
            provider_port_text = self.provider_port.text()

        for ip_address in self.ip_addresses:
            ip_addresses.append(ip_address.text())
        create_pjsip = SettingsToPjsip(asterisk_constants.PJSIP_CONF_PATH, pjsip_port_text, self.provider_address.text(), provider_port_text, ip_addresses)
        create_pjsip.create_config()

    def save_settings(self):
        self.settings.setValue("pjsip port", self.pjsip_port.text())
        self.settings.setValue("provider contact address", self.provider_address.text())
        self.settings.setValue("provider contact port", self.provider_port.text())
        ip_address_list = ""
        for ip_address in self.ip_addresses:
            ip_address_list += ip_address.text() + ","
        if ip_address_list is not None:
            self.settings.setValue("provider ip addresses", ip_address_list)

    def delete_ip_address(self, button):
        ip_index = - 2 - self.delete_button_group.id(button)
        self.ip_form_layout.removeRow(ip_index)
        del self.ip_addresses[ip_index]
        for button in self.delete_button_group.buttons():
            button_id = self.delete_button_group.id(button)
            if(button_id < - 2 - ip_index):
                self.delete_button_group.setId(button, button_id + 1)
Beispiel #5
0
class SettingsDialog(QDialog, Ui_Dialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.setupUi(self)

        self.lineEdit_loginUsername.setText(
            app.settings.get("account", "username"))
        self.lineEdit_loginPassword.setText(
            app.settings.get("account", "password"))
        self.checkBox_autoLogin.setChecked(
            app.settings.getbool("account", "autologin"))
        self.checkBox_autoStartFrontend.setChecked(
            self.doesAutoStartFileExists())

        self.checkBox_enableDevelopersTools.setChecked(
            app.settings.getbool("frontend", "enabledeveloperstools"))
        self.checkBox_allowFlash.setChecked(
            app.settings.getbool("frontend", "allowflash"))
        self.checkBox_minimizeToSystray.setChecked(
            app.settings.getbool("frontend", "minimizetosystray"))
        self.checkBox_closeToMinimize.setChecked(
            app.settings.getbool("frontend", "closetominimize"))
        self.checkBox_popNotifications.setChecked(
            app.settings.getbool("frontend", "popnotifications"))
        self.checkBox_notifyBySound.setChecked(
            app.settings.getbool("frontend", "notifybysound"))
        self.checkBox_showMonitorWindow.setChecked(
            app.settings.getbool("frontend", "showmonitorwindow"))
        self.spinBox_monitorFullSpeed.setValue(
            app.settings.getint("frontend", "monitorfullspeed"))
        # clipboard related
        self.checkBox_watchClipboard.stateChanged.connect(
            self.slotWatchClipboardToggled)
        self.checkBox_watchClipboard.setChecked(
            app.settings.getbool("frontend", "watchclipboard"))
        self.slotWatchClipboardToggled(
            self.checkBox_watchClipboard.checkState())
        self.plaintext_watchPattern.setPlainText(
            app.settings.get("frontend", "watchpattern"))

        self.btngrp_etmStartWhen = QButtonGroup()
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen1, 1)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen2, 2)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen3, 3)

        try:
            startEtmWhen = callXwaredInterface("getStartEtmWhen")
            self.btngrp_etmStartWhen.button(startEtmWhen).setChecked(True)
        except SocketDoesntExist:
            self.group_etmStartWhen.setEnabled(False)

        self.btn_addMount.clicked.connect(self.slotAddMount)
        self.btn_removeMount.clicked.connect(self.slotRemoveMount)
        self.btn_refreshMount.clicked.connect(self.setupMounts)

        # Mounts
        self.setupMounts()

        # backend setting is a different thing!
        self.setupETM()

    @staticmethod
    def doesAutoStartFileExists():
        return os.path.lexists(constants.FRONTEND_AUTOSTART_FILE)

    @pyqtSlot(int)
    def slotWatchClipboardToggled(self, state):
        # disable pattern settings, before
        # 1. complete patterns
        # 2. test glib key file compatibility
        self.plaintext_watchPattern.setReadOnly(True)
        self.plaintext_watchPattern.setEnabled(state)

    @pyqtSlot()
    def setupMounts(self):
        self.table_mounts.setRowCount(0)
        self.table_mounts.clearContents()

        permissionCheckResult = app.mountsFaker.permissionCheck()
        permissionCheckFailed = [
            "无法获得检测权限。运行{}查看原因。".format(constants.PERMISSIONCHECK)
        ]

        mountsMapping = app.mountsFaker.getMountsMapping()
        for i, mount in enumerate(app.mountsFaker.mounts):
            # mounts = ['/path/to/1', 'path/to/2', ...]
            self.table_mounts.insertRow(i)
            self.table_mounts.setItem(i, 0, QTableWidgetItem(mount))
            # drive1: the drive letter it should map to, by alphabetical order
            drive1 = chr(ord('C') + i) + ":"
            self.table_mounts.setItem(i, 1, QTableWidgetItem(drive1))
            # drive2: the drive letter it actually is assigned to
            drive2 = mountsMapping.get(mount, "无")

            # check 1: permission
            errors = permissionCheckResult.get(mount, permissionCheckFailed)

            # check 2: mapping
            if drive1 != drive2:
                errors.append(
                    "警告:盘符映射在'{actual}',而不是'{should}'。需要重启后端修复。".format(
                        actual=drive2, should=drive1))

            brush = QBrush()
            if errors:
                brush.setColor(Qt.red)
                errString = "\n".join(errors)
            else:
                brush.setColor(Qt.darkGreen)
                errString = "正常"
            errWidget = QTableWidgetItem(errString)
            errWidget.setForeground(brush)

            self.table_mounts.setItem(i, 2, errWidget)
            del brush, errWidget

        self.table_mounts.resizeColumnsToContents()

    @pyqtSlot()
    def slotAddMount(self):
        fileDialog = QFileDialog(self, Qt.Dialog)
        fileDialog.setFileMode(QFileDialog.Directory)
        fileDialog.setOption(QFileDialog.ShowDirsOnly, True)
        fileDialog.setViewMode(QFileDialog.List)
        fileDialog.setDirectory(os.environ["HOME"])
        if fileDialog.exec():
            selected = fileDialog.selectedFiles()[0]
            if selected in self.newMounts:
                return
            row = self.table_mounts.rowCount()
            self.table_mounts.insertRow(row)
            self.table_mounts.setItem(row, 0, QTableWidgetItem(selected))
            self.table_mounts.setItem(row, 1, QTableWidgetItem("新近添加"))
            self.table_mounts.setItem(row, 2, QTableWidgetItem("新近添加"))

    @pyqtSlot()
    def slotRemoveMount(self):
        row = self.table_mounts.currentRow()
        self.table_mounts.removeRow(row)

    @pyqtSlot()
    def accept(self):
        app.settings.set("account", "username",
                         self.lineEdit_loginUsername.text())
        app.settings.set("account", "password",
                         self.lineEdit_loginPassword.text())
        app.settings.setbool("account", "autologin",
                             self.checkBox_autoLogin.isChecked())
        doesAutoStartFileExists = self.doesAutoStartFileExists()
        if self.checkBox_autoStartFrontend.isChecked(
        ) and not doesAutoStartFileExists:
            # mkdir if autostart dir doesn't exist
            try:
                os.mkdir(os.path.dirname(constants.FRONTEND_AUTOSTART_FILE))
            except OSError:
                pass  # already exists
            os.symlink(constants.DESKTOP_FILE_LOCATION,
                       constants.FRONTEND_AUTOSTART_FILE)
        elif (not self.checkBox_autoStartFrontend.isChecked()
              ) and doesAutoStartFileExists:
            os.remove(constants.FRONTEND_AUTOSTART_FILE)

        app.settings.setbool("frontend", "enabledeveloperstools",
                             self.checkBox_enableDevelopersTools.isChecked())
        app.settings.setbool("frontend", "allowflash",
                             self.checkBox_allowFlash.isChecked())
        app.settings.setbool("frontend", "minimizetosystray",
                             self.checkBox_minimizeToSystray.isChecked())

        # A possible Qt bug
        # https://bugreports.qt-project.org/browse/QTBUG-37695
        app.settings.setbool("frontend", "closetominimize",
                             self.checkBox_closeToMinimize.isChecked())
        app.settings.setbool("frontend", "popnotifications",
                             self.checkBox_popNotifications.isChecked())
        app.settings.setbool("frontend", "notifybysound",
                             self.checkBox_notifyBySound.isChecked())

        app.settings.setbool("frontend", "showmonitorwindow",
                             self.checkBox_showMonitorWindow.isChecked())
        app.settings.setint("frontend", "monitorfullspeed",
                            self.spinBox_monitorFullSpeed.value())
        app.settings.setbool("frontend", "watchclipboard",
                             self.checkBox_watchClipboard.isChecked())
        # app.settings.set("frontend", "watchpattern",
        #                         self.plaintext_watchPattern.toPlainText())

        if self.group_etmStartWhen.isEnabled():
            startEtmWhen = self.btngrp_etmStartWhen.id(
                self.btngrp_etmStartWhen.checkedButton())
            try:
                callXwaredInterface("setStartEtmWhen", startEtmWhen)
            except SocketDoesntExist:
                QMessageBox.warning(
                    None, "Xware Desktop",
                    "选项未能成功设置:{}。".format(self.group_etmStartWhen.title()),
                    QMessageBox.Ok, QMessageBox.Ok)

        app.settings.save()

        app.mountsFaker.mounts = self.newMounts
        app.settings.applySettings.emit()
        super().accept()

    @property
    def newMounts(self):
        return list(
            map(lambda row: self.table_mounts.item(row, 0).text(),
                range(self.table_mounts.rowCount())))

    @pyqtSlot()
    def setupETM(self):
        # fill values
        lcPort = app.xwaredpy.lcPort
        self.lineEdit_lcport.setText(str(lcPort) if lcPort else "不可用")

        etmSettings = app.etmpy.getSettings()
        if etmSettings:
            self.spinBox_dSpeedLimit.setValue(etmSettings.dLimit)
            self.spinBox_uSpeedLimit.setValue(etmSettings.uLimit)
            self.spinBox_maxRunningTasksNum.setValue(
                etmSettings.maxRunningTasksNum)

            # connect signals
            self.accepted.connect(self.saveETM)
        else:
            self.spinBox_dSpeedLimit.setEnabled(False)
            self.spinBox_uSpeedLimit.setEnabled(False)
            self.spinBox_maxRunningTasksNum.setEnabled(False)

    @pyqtSlot()
    def saveETM(self):
        newsettings = EtmSetting(
            dLimit=self.spinBox_dSpeedLimit.value(),
            uLimit=self.spinBox_uSpeedLimit.value(),
            maxRunningTasksNum=self.spinBox_maxRunningTasksNum.value())

        app.etmpy.saveSettings(newsettings)
Beispiel #6
0
class MainWindow(QMainWindow):

    sizeButtonGroup = None
    OtherSize = QStyle.PM_CustomBase
    otherSpinBox = None

    def createImagesGroupBox(self):
        imagesGroupBox = QGroupBox("Images")
        labels = ("Images", "Mode", "State")

        self.imagesTable = QTableWidget()
        self.imagesTable.setSelectionMode(QAbstractItemView.NoSelection)
        self.imagesTable.setItemDelegate(ImageDelegate(self))
        self.imagesTable.horizontalHeader().setDefaultSectionSize(90)
        self.imagesTable.setColumnCount(3)
        self.imagesTable.setHorizontalHeaderLabels(labels)
        self.imagesTable.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.imagesTable.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Fixed)
        self.imagesTable.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.Fixed)
        self.imagesTable.verticalHeader().hide()
        self.imagesTable.itemChanged.connect(self.changeIcon)

        layout = QVBoxLayout(imagesGroupBox)
        layout.addWidget(self.imagesTable)
        return imagesGroupBox

    def createIconSizeGroupBox(self):
        iconSizeGroupBox = QGroupBox("Icon Size")
        self.sizeButtonGroup = QButtonGroup(iconSizeGroupBox)
        self.sizeButtonGroup.setExclusive(True)

        self.sizeButtonGroup.buttonToggled.connect(self.triggerChangeSize)

        smallRadioButton = QRadioButton()
        smallRadioButton.setChecked(True)
        self.sizeButtonGroup.addButton(smallRadioButton,
                                       QStyle.PM_SmallIconSize)
        largeRadioButton = QRadioButton()
        self.sizeButtonGroup.addButton(largeRadioButton,
                                       QStyle.PM_LargeIconSize)
        toolBarRadioButton = QRadioButton()
        self.sizeButtonGroup.addButton(toolBarRadioButton,
                                       QStyle.PM_ToolBarIconSize)
        iconViewRadioButton = QRadioButton()
        self.sizeButtonGroup.addButton(iconViewRadioButton,
                                       QStyle.PM_IconViewIconSize)
        listViewRadioButton = QRadioButton()
        self.sizeButtonGroup.addButton(listViewRadioButton,
                                       QStyle.PM_ListViewIconSize)
        tabBarRadioButton = QRadioButton()
        self.sizeButtonGroup.addButton(tabBarRadioButton,
                                       QStyle.PM_TabBarIconSize)
        otherRadioButton = QRadioButton("Other:")
        self.sizeButtonGroup.addButton(otherRadioButton, self.OtherSize)
        self.otherSpinBox = IconSizeSpinBox()
        self.otherSpinBox.setRange(8, 256)
        spinBoxToolTip = "Enter a custom size within {}..{}".format(
            self.otherSpinBox.minimum(), self.otherSpinBox.maximum())
        self.otherSpinBox.setValue(64)
        self.otherSpinBox.setToolTip(spinBoxToolTip)
        otherRadioButton.setToolTip(spinBoxToolTip)

        self.otherSpinBox.valueChanged.connect(self.triggerChangeSize)

        otherSizeLayout = QHBoxLayout()
        otherSizeLayout.addWidget(otherRadioButton)
        otherSizeLayout.addWidget(self.otherSpinBox)
        otherSizeLayout.addStretch()

        layout = QGridLayout(iconSizeGroupBox)
        layout.addWidget(smallRadioButton, 0, 0)
        layout.addWidget(largeRadioButton, 1, 0)
        layout.addWidget(toolBarRadioButton, 2, 0)
        layout.addWidget(listViewRadioButton, 0, 1)
        layout.addWidget(iconViewRadioButton, 1, 1)
        layout.addWidget(tabBarRadioButton, 2, 1)
        layout.addLayout(otherSizeLayout, 3, 0, 1, 2)
        layout.setRowStretch(4, 1)

        return iconSizeGroupBox

    def loadImages(self, fileNames):
        for fileName in fileNames:
            row = self.imagesTable.rowCount()
            self.imagesTable.setRowCount(row + 1)
            fileInfo = QFileInfo(fileName)
            imageName = fileInfo.baseName()
            fileImage2x = fileInfo.absolutePath(
            ) + '/' + imageName + "@2x." + fileInfo.suffix()
            fileInfo2x = QFileInfo(fileImage2x)
            image = QImage(fileName)
            toolTip = "Directory: {}\nFile: {}\nFile@2x: {}\nSize: {}x{}".format(
                QDir.toNativeSeparators(fileInfo.absolutePath()),
                fileInfo.fileName(),
                fileInfo2x.fileName() if fileInfo2x.exists else "<None>",
                image.width(), image.height())
            fileItem = QTableWidgetItem(imageName)
            fileItem.setData(Qt.UserRole, fileName)
            fileItem.setIcon(QIcon(QPixmap.fromImage(image)))
            fileItem.setFlags((fileItem.flags() | Qt.ItemIsUserCheckable)
                              & ~Qt.ItemIsEditable)
            fileItem.setToolTip(toolTip)
            self.imagesTable.setItem(row, 0, fileItem)

            mode = QIcon.Normal
            state = QIcon.Off

            if self.guessModeStateAct.isChecked():
                if "_act" in imageName:
                    mode = QIcon.Active
                elif "_dis" in imageName:
                    mode = QIcon.Disabled
                elif "_sel" in imageName:
                    mode = QIcon.Selected

                if "_on" in imageName:
                    mode = QIcon.On

            modeItem = QTableWidgetItem(IconPreviewArea.iconModeNames()[
                IconPreviewArea.iconModes().index(mode)])
            modeItem.setToolTip(toolTip)
            self.imagesTable.setItem(row, 1, modeItem)
            stateItem = QTableWidgetItem(IconPreviewArea.iconStateNames()[
                IconPreviewArea.iconStates().index(state)])
            stateItem.setToolTip(toolTip)
            self.imagesTable.setItem(row, 2, stateItem)
            self.imagesTable.openPersistentEditor(modeItem)
            self.imagesTable.openPersistentEditor(stateItem)
            fileItem.setCheckState(Qt.Checked)

    def addImages(self, directory):
        fileDialog = QFileDialog(self, "Open Images", directory)
        mimeTypeFilters = []
        for mimeTypeName in QImageReader.supportedMimeTypes():
            mimeTypeFilters.append(str(mimeTypeName))
        mimeTypeFilters.sort()
        fileDialog.setMimeTypeFilters(mimeTypeFilters)
        fileDialog.selectMimeTypeFilter('image/png')
        fileDialog.setAcceptMode(QFileDialog.AcceptOpen)
        fileDialog.setFileMode(QFileDialog.ExistingFiles)
        if not self.nativeFileDialogAct.isChecked():
            fileDialog.setOption(QFileDialog.DontUseNativeDialog)
        if fileDialog.exec_() == QDialog.Accepted:
            self.loadImages(fileDialog.selectedFiles())

    def addSampleImages(self):
        self.addImages("C:/Users/hungbn/Pictures")

    def addOtherImages(self):
        pass

    def removeAllImages(self):
        self.imagesTable.setRowCount(0)
        self.changeIcon()

    def createActions(self):
        fileMenu = self.menuBar().addMenu("&File")
        addSampleImagesAct = QAction("Add &Sample Images...", self)
        addSampleImagesAct.triggered.connect(self.addSampleImages)
        fileMenu.addAction(addSampleImagesAct)

        addOtherImagesAct = QAction("&Add Images...", self)
        addOtherImagesAct.setShortcut(QKeySequence.Open)
        addOtherImagesAct.triggered.connect(self.addOtherImages)
        fileMenu.addAction(addOtherImagesAct)

        removeAllImagesAct = QAction("&Remove All Images", self)
        removeAllImagesAct.setShortcut("CTRL+R")
        removeAllImagesAct.triggered.connect(self.removeAllImages)
        fileMenu.addAction(removeAllImagesAct)

        fileMenu.addSeparator()

        exitAct = QAction("&Quit", self)
        exitAct.triggered.connect(QWidget.close)
        exitAct.setShortcuts(QKeySequence.Quit)
        fileMenu.addAction(exitAct)

        viewMenu = self.menuBar().addMenu("&View")

        self.styleActionGroup = QActionGroup(self)
        for styleName in QStyleFactory.keys():
            action = QAction("{} Style".format(styleName),
                             self.styleActionGroup)
            action.setData(styleName)
            action.setCheckable(True)
            action.triggered.connect(self.changeStyle)
            viewMenu.addAction(action)

        settingsMenu = self.menuBar().addMenu("&Settings")

        self.guessModeStateAct = QAction("&Guess Image Mode/State", self)
        self.guessModeStateAct.setCheckable(True)
        self.guessModeStateAct.setChecked(True)
        settingsMenu.addAction(self.guessModeStateAct)

        self.nativeFileDialogAct = QAction("&Use Native File Dialog", self)
        self.nativeFileDialogAct.setCheckable(True)
        self.nativeFileDialogAct.setChecked(True)
        settingsMenu.addAction(self.nativeFileDialogAct)

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

        centerWidget = QWidget(self)

        self.setCentralWidget(centerWidget)

        mainLayout = QGridLayout(centerWidget)

        previewGroupBox = QGroupBox("Preview")
        self.previewArea = IconPreviewArea(previewGroupBox)
        previewLayout = QVBoxLayout(previewGroupBox)
        previewLayout.addWidget(self.previewArea)

        mainLayout.addWidget(previewGroupBox, 0, 0, 1, 2)
        mainLayout.addWidget(self.createImagesGroupBox(), 1, 0)

        vbox = QVBoxLayout()
        vbox.addWidget(self.createIconSizeGroupBox())
        #vbox.addWidget(self.createHighDpiIconSizeGroupBox())
        vbox.addItem(
            QSpacerItem(0, 0, QSizePolicy.Ignored,
                        QSizePolicy.MinimumExpanding))
        mainLayout.addLayout(vbox, 1, 1)

        self.createActions()

        self.setWindowTitle("Icons")
        self.checkCurrentStyle()

    def about(self):
        QMessageBox.about(
            self, "About Icons"
            "The <b>Icons</b> example illustrates how Qt renders an icon in " +
            "different modes (active, normal, disabled, and selected) and " +
            "states (on and off) based on a set of images.")

    def checkCurrentStyle(self):
        for action in self.styleActionGroup.actions():
            styleName = action.data()
            candidate = QStyleFactory.create(styleName)
            if candidate.metaObject().className() == QApplication.style(
            ).metaObject().className():
                action.trigger()
                return

    def changeStyle(self, checked):
        if (not checked):
            return

        action = self.sender()
        style = QStyleFactory.create(action.data())
        QApplication.setStyle(style)

        for button in self.sizeButtonGroup.buttons():
            metric = self.sizeButtonGroup.id(button)
            value = style.pixelMetric(metric)
            {
                QStyle.PM_SmallIconSize:
                lambda: button.setText("Small ({} x {})".format(value, value)),
                QStyle.PM_LargeIconSize:
                lambda: button.setText("Large ({} x {})".format(value, value)),
                QStyle.PM_ToolBarIconSize:
                lambda: button.setText("Toolbars ({} x {})".format(
                    value, value)),
                QStyle.PM_ListViewIconSize:
                lambda: button.setText("List views ({} x {})".format(
                    value, value)),
                QStyle.PM_IconViewIconSize:
                lambda: button.setText("Icon views ({} x {})".format(
                    value, value)),
                QStyle.PM_TabBarIconSize:
                lambda: button.setText("Tab bars ({} x {})".format(
                    value, value)),
            }.get(metric, lambda: "")()

        self.triggerChangeSize()

    def changeIcon(self):
        icon = QIcon()

        for row in range(self.imagesTable.rowCount()):
            fileItem = self.imagesTable.item(row, 0)
            modeItem = self.imagesTable.item(row, 1)
            stateItem = self.imagesTable.item(row, 2)

            if fileItem.checkState() == Qt.Checked:
                modeIndex = IconPreviewArea.iconModeNames().index(
                    modeItem.text())
                stateIndex = IconPreviewArea.iconStateNames().index(
                    stateItem.text())
                mode = IconPreviewArea.iconModes()[modeIndex]
                state = IconPreviewArea.iconStates()[stateIndex]
                fileName = fileItem.data(Qt.UserRole)
                image = QImage(fileName)
                if not image.isNull():
                    icon.addPixmap(QPixmap.fromImage(image), mode, state)

        self.previewArea.setIcon(icon)

    def changeSize(self, id, checked):
        if (not checked):
            return

        other = (id == self.OtherSize)
        extend = self.otherSpinBox.value() if other else QApplication.style(
        ).pixelMetric(id)
        self.previewArea.setSize(QSize(extend, extend))
        self.otherSpinBox.setEnabled(other)

    def triggerChangeSize(self):
        self.changeSize(self.sizeButtonGroup.checkedId(), True)
class VistaListaDipendenti(
        QWidget):  # Apre la vista che visualizza la lista dei dipendenti.
    def __init__(self):
        super(VistaListaDipendenti, self).__init__()
        self.controller = ControllerListaDipendenti()

        # Inserisce in 'lista_dipendenti' le informazioni della 'lista-dipendenti.json'.
        # Se la lista è vuota l'utente è notificato con un messaggio di errore.

        self.stylesheet_label = """
            QLabel{
                background-color: #99cbff;
                border: 1px solid #dfdfdf;
            }
        """

        self.stylesheet_window = """
            QWidget{
                background-color: #dfdfdf
            }
        """

        self.stylesheet_button_back = """
            QPushButton{
                border-radius: 15px;
                background-color: transparent;
            }
            
            QPushButton::Pressed{
                background-color: transparent;
            }
        """

        self.stylesheet_button = """
            QPushButton{
                background-color: #cc3234;
                color: white;
                border-radius: 15px;
            }
            
            QPushButton::Pressed{
                background-color: grey
            }
        """

        self.stylesheet_table = """
            QTableWidget{
                background-color: white;
            }
        """

        self.stylesheet_pagamento = """
                    QPushButton{
                        background-color: transparent;
                        border-color: transparent;
                    }

                    QPushButton::Pressed{
                        background-color: grey;
                    }
                """

        # Inserimento e impostazioni grafiche dell'immagine dello sfondo della finestra.
        self.imagePath = "Image/foto.png"
        self.image = QImage(self.imagePath)
        self.label = QLabel(self)
        self.label.setPixmap(QPixmap.fromImage(self.image))
        self.label.setScaledContents(True)
        self.label.setGeometry(0, 0, 1400, 750)

        # Inserimento della tabella e intestazione delle colonne.
        self.table = QTableWidget(self)
        self.table.setColumnCount(6)
        self.table.setRowCount(1)
        self.table.setItem(0, 0, QTableWidgetItem("Apri"))
        self.table.setItem(0, 1, QTableWidgetItem("ID"))
        self.table.setItem(0, 2, QTableWidgetItem("Nome"))
        self.table.setItem(0, 3, QTableWidgetItem("Cognome"))
        self.table.setItem(0, 4, QTableWidgetItem("Mansione"))
        self.table.setItem(0, 5, QTableWidgetItem("Elimina"))

        self.set_data(
        )  # Inserisce nella tabella i dati contenuti nella lista_dipendenti.

        # Impostazioni grafiche della tabella.
        self.table.setGeometry(25, 30, 1200, 550)
        self.table.setColumnWidth(0, 90)
        self.table.setColumnWidth(1, 100)
        self.table.setColumnWidth(2, 300)
        self.table.setColumnWidth(3, 300)
        self.table.setColumnWidth(4, 300)
        self.table.setColumnWidth(5, 90)
        self.table.setStyleSheet(self.stylesheet_table)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().hide()
        self.table.horizontalScrollBar().setDisabled(True)
        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table.verticalHeader().hide()
        self.table.setEditTriggers(self.table.NoEditTriggers)
        self.table.setSelectionMode(self.table.NoSelection)
        self.table.setFocusPolicy(Qt.NoFocus)

        # Inserimento e impostazioni grafiche del bottone per tornare alla vista precedente.
        self.button_back = QPushButton(self)
        self.button_back.setIcon(QIcon('Image/back.png'))
        self.button_back.setIconSize(QSize(90, 90))
        self.button_back.setGeometry(70, 600, 90, 90)
        self.button_back.setStyleSheet(self.stylesheet_button_back)
        self.button_back.clicked.connect(self.go_back)

        # Inserimento e impostazioni grafiche del bottone per inserire un nuovo dipendente nella lista.
        self.button_new_dipendente = QPushButton(self)
        self.button_new_dipendente.setText("Nuovo Dipendente")
        self.font_button = QFont("Times", 11)
        self.button_new_dipendente.setFont(self.font_button)
        self.button_new_dipendente.setGeometry(1000, 620, 190, 50)
        self.button_new_dipendente.setStyleSheet(self.stylesheet_button)
        self.button_new_dipendente.clicked.connect(self.go_new_dipendente)

        # Impostazioni grafiche generali della finestra del programma.
        self.setWindowTitle("Lista Dipendenti")
        self.resize(1250, 700)
        self.setFixedSize(self.size())
        self.setStyleSheet(self.stylesheet_window)

    # == set_data ==
    # La funzione si occupa di salvare le informazioni relative al dipendente e contenute nel file
    # 'lista_dipendenti.pickle' nella tabella della VistaListaDipendenti.
    def set_data(self):
        self.button_group_apri = QButtonGroup()
        self.button_group_elimina = QButtonGroup()
        self.apri_icon = QIcon("Image/apri_icon.png")
        self.cancella_icon = QIcon("Image/delete.png")
        i = 1
        self.lista_dipendenti = self.controller.get_lista_dipendenti()
        n_righe = len(self.controller.get_lista_dipendenti())
        self.table.setRowCount(n_righe + 1)
        self.button_group_apri.buttonClicked.connect(self.on_selection_apri)
        self.button_group_elimina.buttonClicked.connect(
            self.on_selection_elimina)
        for dipendente in self.controller.get_lista_dipendenti():
            self.controller_dipendente = ControllerDipendente(dipendente)
            self.apri = QPushButton()
            self.apri.setIcon(self.apri_icon)
            self.apri.setIconSize(QSize(30, 30))
            self.apri.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_apri.addButton(self.apri, i)
            self.table.setCellWidget(i, 0, self.apri)
            self.table.setItem(
                i, 1, QTableWidgetItem(self.controller_dipendente.get_id()))
            self.table.setItem(
                i, 2, QTableWidgetItem(self.controller_dipendente.get_nome()))
            self.table.setItem(
                i, 3,
                QTableWidgetItem(self.controller_dipendente.get_cognome()))
            self.table.setItem(
                i, 4,
                QTableWidgetItem(self.controller_dipendente.get_mansione()))
            self.delete = QPushButton()
            self.delete.setIcon(self.cancella_icon)
            self.delete.setIconSize(QSize(35, 35))
            self.delete.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_elimina.addButton(self.delete, i)
            self.table.setCellWidget(i, 5, self.delete)
            i = i + 1

    # == go_new_dipendente ==
    # La funzione si occupa di aprire la VistaNuovoDipendente.
    def go_new_dipendente(self):
        self.vista_nuovo_dipendente = VistaNuovoDipendente()
        self.vista_nuovo_dipendente.show()
        self.close()

    # == go_back ==
    # La funzione si occupa di aprire la finestra precedente.
    def go_back(self):
        self.go_home = VistaHomeSegretario.VistaHomeSegretario()
        self.go_home.show()
        self.close()

    # == go_apri ==
    # La funzione si occupa di aprire la VistaCliente corrispondente al cliente scelto.
    def go_apri(self, i):
        dipendente = self.lista_dipendenti[i - 1]
        self.go_dipendente = VistaDipendente(dipendente, False)
        self.go_dipendente.show()
        self.close()

    # == go_elimina ==
    # La funzione, dopo aver chiesto conferma all'utente, cancella le informazioni relative al
    # cliente scelto.
    def go_elimina(self, i):
        conferma = QMessageBox.question(
            self, "Attenzione",
            "Sei sicuro di voler eliminare questo dipendente?", QMessageBox.No,
            QMessageBox.Yes)
        if conferma == QMessageBox.Yes:
            self.controller.rimuovi_dipendente_by_index(i - 1)
            self.refresh()
        else:
            return

    def refresh(self):
        self.go_lista = VistaListaDipendenti()
        self.go_lista.show()
        self.close()

    def on_selection_apri(self, selected):
        self.go_apri(self.button_group_apri.id(selected))

    def on_selection_elimina(self, selected):
        self.go_elimina(self.button_group_elimina.id(selected))
Beispiel #8
0
class DependenciesDialog(QDialog):
    """Dependencies dialog for python dependencies"""

    column = AttrDict(
        zip(("button", "status", "name", "version", "required_version",
             "description"), range(6)))
    column_headers = ("", "Status", "Package", "Version", "Required",
                      "Description")

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

        self.setWindowTitle("Installer")

        # Button group for install buttons
        self.buttGroup = QButtonGroup()
        self.buttGroup.buttonClicked.connect(self.on_butt_install)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.setContentsMargins(10, 10, 10, 10)
        self.setLayout(self.mainLayout)

        self.tree = QTreeWidget()
        self.mainLayout.addWidget(self.tree, 4)

        self.tree.setHeaderLabels(self.column_headers)
        self.tree.setRootIsDecorated(False)
        self.tree.setSelectionMode(QTreeWidget.NoSelection)

        self.update_load()

    def sizeHint(self):
        """Overloaded method"""

        return QSize(700, 200)

    def update_load(self):

        self.tree.clear()

        for idx, module in enumerate(OPTIONAL_DEPENDENCIES):
            item = QTreeWidgetItem()
            item.setText(self.column.name, module.name)
            version = module.version if module.version else "Not installed"
            item.setText(self.column.version, str(version))
            item.setText(self.column.required_version,
                         str(module.required_version))
            item.setText(self.column.description, module.description)
            self.tree.addTopLevelItem(item)

            if module.is_installed():
                color = "#DBFEAC"
                status = "Installed"
            else:
                status = "Not installed"
                color = "#F3FFBB"
                butt = QToolButton()
                butt.setText("Install")
                butt.setEnabled(PIP_MODULE.is_installed())
                self.tree.setItemWidget(item, self.column.button, butt)
                self.buttGroup.addButton(butt, idx)

            item.setText(self.column.status, status)
            item.setBackground(self.column.status, QColor(color))

    def on_butt_install(self, butt):
        """One of install buttons pressed"""

        butt.setDisabled(True)
        idx = self.buttGroup.id(butt)

        dial = InstallPackageDialog(self, module=OPTIONAL_DEPENDENCIES[idx])
        dial.exec_()
        self.update_load()
Beispiel #9
0
class SendConfigDialog(QDialog):
    def __init__(self):
        super().__init__()
        self.setMinimumWidth(640)
        self.setWindowTitle('Send configuration to device')
        self.settings = QSettings('tasmotizer.cfg', QSettings.IniFormat)

        self.commands = None
        self.module_mode = 0

        self.createUI()
        self.loadSettings()

    def createUI(self):
        vl = VLayout()
        self.setLayout(vl)

        # Wifi groupbox
        self.gbWifi = QGroupBox('WiFi')
        self.gbWifi.setCheckable(True)
        self.gbWifi.setChecked(False)
        flWifi = QFormLayout()
        self.leAP = QLineEdit()
        self.leAPPwd = QLineEdit()
        self.leAPPwd.setEchoMode(QLineEdit.Password)
        flWifi.addRow('SSID', self.leAP)
        flWifi.addRow('Password', self.leAPPwd)
        self.gbWifi.setLayout(flWifi)

        # Recovery Wifi groupbox
        self.gbRecWifi = QGroupBox('Recovery WiFi')
        self.gbRecWifi.setCheckable(True)
        self.gbRecWifi.setChecked(False)
        flRecWifi = QFormLayout()
        lbRecAP = QLabel('Recovery')
        lbRecAP.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        lbRecAPPwd = QLabel('a1b2c3d4')
        lbRecAPPwd.setAlignment(Qt.AlignVCenter | Qt.AlignRight)

        flRecWifi.addRow('SSID', lbRecAP)
        flRecWifi.addRow('Password', lbRecAPPwd)
        self.gbRecWifi.setLayout(flRecWifi)

        vl_wifis = VLayout(0)
        vl_wifis.addWidgets([self.gbWifi, self.gbRecWifi])

        # MQTT groupbox
        self.gbMQTT = QGroupBox('MQTT')
        self.gbMQTT.setCheckable(True)
        self.gbMQTT.setChecked(False)
        flMQTT = QFormLayout()
        self.leBroker = QLineEdit()
        self.sbPort = SpinBox()
        self.sbPort.setValue(1883)
        self.leTopic = QLineEdit()
        self.leTopic.setText('tasmota')
        self.leFullTopic = QLineEdit()
        self.leFullTopic.setText('%prefix%/%topic%/')
        self.leFriendlyName = QLineEdit()
        self.leMQTTUser = QLineEdit()
        self.leMQTTPass = QLineEdit()
        self.leMQTTPass.setEchoMode(QLineEdit.Password)

        flMQTT.addRow('Host', self.leBroker)
        flMQTT.addRow('Port', self.sbPort)
        flMQTT.addRow('Topic', self.leTopic)
        flMQTT.addRow('FullTopic', self.leFullTopic)
        flMQTT.addRow('FriendlyName', self.leFriendlyName)
        flMQTT.addRow('User [optional]', self.leMQTTUser)
        flMQTT.addRow('Password [optional]', self.leMQTTPass)
        self.gbMQTT.setLayout(flMQTT)

        # Module/template groupbox
        self.gbModule = GroupBoxV('Module/template')
        self.gbModule.setCheckable(True)
        self.gbModule.setChecked(False)

        hl_m_rb = HLayout()
        self.rbModule = QRadioButton('Module')
        self.rbModule.setChecked(True)
        self.rbTemplate = QRadioButton('Template')
        hl_m_rb.addWidgets([self.rbModule, self.rbTemplate])

        self.rbgModule = QButtonGroup(self.gbModule)
        self.rbgModule.addButton(self.rbModule, 0)
        self.rbgModule.addButton(self.rbTemplate, 1)

        self.cbModule = QComboBox()
        for mod_id, mod_name in MODULES.items():
            self.cbModule.addItem(mod_name, mod_id)

        self.leTemplate = QLineEdit()
        self.leTemplate.setPlaceholderText('Paste template string here')
        self.leTemplate.setVisible(False)

        self.gbModule.addLayout(hl_m_rb)
        self.gbModule.addWidgets([self.cbModule, self.leTemplate])
        self.rbgModule.buttonClicked[int].connect(self.setModuleMode)

        # layout all widgets
        hl_wifis_mqtt = HLayout(0)
        hl_wifis_mqtt.addLayout(vl_wifis)
        hl_wifis_mqtt.addWidget(self.gbMQTT)

        vl.addLayout(hl_wifis_mqtt)
        vl.addWidget(self.gbModule)

        btns = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close)
        btns.accepted.connect(self.accept)
        btns.rejected.connect(self.reject)
        vl.addWidget(btns)

    def loadSettings(self):
        self.gbWifi.setChecked(self.settings.value('gbWifi', False, bool))
        self.leAP.setText(self.settings.value('AP'))

        self.gbRecWifi.setChecked(self.settings.value('gbRecWifi', False,
                                                      bool))

        self.gbMQTT.setChecked(self.settings.value('gbMQTT', False, bool))
        self.leBroker.setText(self.settings.value('Broker'))
        self.sbPort.setValue(self.settings.value('Port', 1883, int))
        self.leTopic.setText(self.settings.value('Topic', 'tasmota'))
        self.leFullTopic.setText(
            self.settings.value('FullTopic', '%prefix%/%topic%/'))
        self.leFriendlyName.setText(self.settings.value('FriendlyName'))
        self.leMQTTUser.setText(self.settings.value('MQTTUser'))

        self.gbModule.setChecked(self.settings.value('gbModule', False, bool))

        module_mode = self.settings.value('ModuleMode', 0, int)
        for b in self.rbgModule.buttons():
            if self.rbgModule.id(b) == module_mode:
                b.setChecked(True)
                self.setModuleMode(module_mode)
        self.cbModule.setCurrentText(self.settings.value('Module', 'Generic'))
        self.leTemplate.setText(self.settings.value('Template'))

    def setModuleMode(self, radio):
        self.module_mode = radio
        self.cbModule.setVisible(not radio)
        self.leTemplate.setVisible(radio)

    def accept(self):
        ok = True

        if self.gbWifi.isChecked() and (len(self.leAP.text()) == 0
                                        or len(self.leAPPwd.text()) == 0):
            ok = False
            QMessageBox.warning(self, 'WiFi details incomplete',
                                'Input WiFi AP and Password')

        if self.gbMQTT.isChecked() and not self.leBroker.text():
            ok = False
            QMessageBox.warning(self, 'MQTT details incomplete',
                                'Input broker hostname')

        if self.module_mode == 1 and len(self.leTemplate.text()) == 0:
            ok = False
            QMessageBox.warning(self, 'Template string missing',
                                'Input template string')

        if ok:
            backlog = []

            if self.gbWifi.isChecked():
                backlog.extend([
                    'ssid1 {}'.format(self.leAP.text()),
                    'password1 {}'.format(self.leAPPwd.text())
                ])

            if self.gbRecWifi.isChecked():
                backlog.extend(['ssid2 Recovery', 'password2 a1b2c3d4'])

            if self.gbMQTT.isChecked():
                backlog.extend([
                    'mqtthost {}'.format(self.leBroker.text()),
                    'mqttport {}'.format(self.sbPort.value())
                ])

                topic = self.leTopic.text()
                if topic and topic != 'tasmota':
                    backlog.append('topic {}'.format(topic))

                fulltopic = self.leFullTopic.text()
                if fulltopic and fulltopic != '%prefix%/%topic%/':
                    backlog.append('fulltopic {}'.format(fulltopic))

                fname = self.leFriendlyName.text()
                if fname:
                    backlog.append('friendlyname {}'.format(fname))

                mqttuser = self.leMQTTUser.text()
                if mqttuser:
                    backlog.append('mqttuser {}'.format(mqttuser))

                    mqttpassword = self.leMQTTPass.text()
                    if mqttpassword:
                        backlog.append('mqttpassword {}'.format(mqttpassword))

            if self.gbModule.isChecked():
                if self.module_mode == 0:
                    backlog.append('module {}'.format(
                        self.cbModule.currentData()))

                elif self.module_mode == 1:
                    backlog.extend([
                        'template {}'.format(self.leTemplate.text()),
                        'module 0'
                    ])

            self.commands = 'backlog {}\n'.format(';'.join(backlog))

            self.done(QDialog.Accepted)
Beispiel #10
0
class VistaListaDocumenti(
        QWidget):  # Apre la vista che visualizza la lista dei documenti.
    def __init__(self):
        super(VistaListaDocumenti, self).__init__()
        self.controller = ControllerListaDocumenti()
        self.lista_documenti = []

        # Inserisce in 'lista_documenti' le informazioni della 'lista_documenti.json'
        # Se la lista è vuota l'utente è notificato con un messaggio di errore.
        self.lista_documenti = self.controller.get_lista_documenti()
        if not self.lista_documenti:
            QMessageBox.critical(self, "Attenzione",
                                 "Nessun documento trovato", QMessageBox.Ok)

        self.stylesheet_window = """
                    QWidget{
                        background-color: #dfdfdf
                    }
                """
        self.stylesheet_button = """
                   QPushButton{
                       background-color: #cc3234;
                       color: white;
                       border-radius: 15px;
                   }

                   QPushButton::Pressed{
                       background-color: grey
                   }        
               """

        self.stylesheet_table = """
                    QTableWidget{
                        background-color: white;
                    }
                """

        self.stylesheet_button_back = """
                   QPushButton{
                       border-radius: 15px;
                       background-color: transparent;
                   }

                   QPushButton::Pressed{
                       background-color: transparent;
                   }        
               """
        self.stylesheet_pagamento = """
                    QPushButton{
                        background-color: transparent;
                        border-color: transparent;
                    }

                    QPushButton::Pressed{
                        background-color: grey;
                    }
                """

        # Inserimento e impostazioni grafiche dell'immagine dello sfondo della finestra.
        self.imagePath = "Image/foto.png"
        self.image = QImage(self.imagePath)
        self.label = QLabel(self)
        self.label.setPixmap(QPixmap.fromImage(self.image))
        self.label.setScaledContents(True)
        self.label.setGeometry(0, 0, 1000, 600)

        # Impostazioni grafiche generali della finestra del programma.
        self.setWindowTitle("Lista Documenti")
        self.resize(1000, 600)
        self.setFixedSize(self.size())
        self.setStyleSheet(self.stylesheet_window)

        # Inserimento della tabella e intestazione delle colonne.
        self.table = QTableWidget(self)
        self.table.setColumnCount(3)
        self.table.setRowCount(1)
        self.table.setItem(0, 0, QTableWidgetItem("Apri"))
        self.table.setItem(0, 1, QTableWidgetItem("Nome"))
        self.table.setItem(0, 2, QTableWidgetItem("Elimina"))

        self.set_data(
        )  # Inserisce nella tabella i dati contenuti nella lista_documenti.

        # Impostazioni grafiche della tabella.
        self.table.setGeometry(70, 50, 850, 400)
        self.table.setColumnWidth(0, 75)
        self.table.setColumnWidth(1, 700)
        self.table.setColumnWidth(2, 75)
        self.table.setStyleSheet(self.stylesheet_table)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().hide()
        self.table.horizontalScrollBar().setDisabled(True)
        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table.verticalHeader().hide()
        self.table.setSelectionMode(self.table.NoSelection)
        self.table.setEditTriggers(self.table.NoEditTriggers)
        self.table.setFocusPolicy(Qt.NoFocus)

        # Inserimento e impostazioni grafiche del bottone che consente di caricare un nuovo documento
        # nel sistema.
        self.button_upload_document = QPushButton(self)
        self.button_upload_document.setText("Carica")
        self.font_button = QFont("Times", 11)
        self.button_upload_document.setFont(self.font_button)
        self.button_upload_document.setGeometry(800, 500, 140, 50)
        self.button_upload_document.setStyleSheet(self.stylesheet_button)
        self.button_upload_document.clicked.connect(self.upload_document)

        # Inserimento e impostazioni grafiche del bottone per tornare alla vista precedente.
        self.button_back = QPushButton(self)
        self.button_back.setIcon(QIcon('Image/back.png'))
        self.button_back.setIconSize(QSize(90, 90))
        self.button_back.setGeometry(60, 490, 90, 90)
        self.button_back.setStyleSheet(self.stylesheet_button_back)
        self.button_back.clicked.connect(self.go_back)

    # == set_data ==
    # La funzione si occupa di salvare le informazioni relative al documento e contenute nel file
    # 'lista_documenti.json' nella tabella della VistaListaDocumenti.
    def set_data(self):
        self.button_group_apri = QButtonGroup()
        self.button_group_elimina = QButtonGroup()
        self.apri_icon = QIcon("Image/Visualizza.png")
        self.cancella_icon = QIcon("Image/delete.png")
        i = 1
        self.lista_documenti = self.controller.get_lista_documenti()
        n_righe = len(self.lista_documenti)
        self.table.setRowCount(n_righe + 1)
        self.button_group_apri.buttonClicked.connect(self.on_selection_apri)
        self.button_group_elimina.buttonClicked.connect(
            self.on_selection_elimina)
        for documento in self.lista_documenti:
            self.apri = QPushButton()
            self.apri.setIcon(self.apri_icon)
            self.apri.setIconSize(QSize(25, 25))
            self.apri.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_apri.addButton(self.apri, i)
            self.table.setCellWidget(i, 0, self.apri)
            self.table.setItem(i, 1, QTableWidgetItem(documento))
            self.delete = QPushButton()
            self.delete.setIcon(self.cancella_icon)
            self.delete.setIconSize(QSize(35, 35))
            self.delete.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_elimina.addButton(self.delete, i)
            self.table.setCellWidget(i, 2, self.delete)
            self.table.currentRow()
            i = i + 1

    # == open_document ==
    # La funzione, dopo che è stato selezionato un documento dalla lista,
    # apre la VistaDocumento.
    def open_document(self, i):
        documento = self.controller.get_lista_documenti()[i - 1]
        self.vista_documento = VistaDocumento(documento)
        self.vista_documento.show()
        self.close()

    # == go_back ==
    # La funzione si occupa di aprire la finestra precedente.
    def go_back(self):
        self.go_lista_documenti = VistaHomeSegretario.VistaHomeSegretario()
        self.go_lista_documenti.show()
        self.close()

    # == upload_document ==
    # La funzione permette di caricare nel sistema un file .pdf scelto dai file
    # contenuti nel computer del dipendente.
    def upload_document(self):
        filename = QFileDialog.getOpenFileName(self, 'open file', '/home',
                                               'Images(*.pdf)')
        if filename[0]:
            f = open(filename[0], 'r')
            src = f.name
            des = 'Documents/'
            shutil.copy2(src, des)
            self.refresh()
        else:
            return

    # == remove_document ==
    # La funzione, dopo aver inviato un messaggio di conferma all'utente, effettua
    # l'eliminazione del documento dalla lista. La finestra viene poi refreshata per aggiornare
    # la lista.
    def remove_document(self, i):
        conferma = QMessageBox.question(
            self, "Attenzione",
            "Sei sicuro di voler eliminare questo documento?", QMessageBox.No,
            QMessageBox.Yes)
        if conferma == QMessageBox.Yes:
            documento = self.controller.get_lista_documenti()[i - 1]
            self.controller.rimuovi_documento(documento)
            self.refresh()
        else:
            return

    # == refresh ==
    # La funzione si occupa di riaprire la VistaListaDocumenti per aggiornarla dopo
    # che sono state effettuate modifiche.
    def refresh(self):
        self.go_vista_documenti = VistaListaDocumenti()
        self.go_vista_documenti.show()
        self.close()

    def on_selection_apri(self, selected):
        self.open_document(self.button_group_apri.id(selected))

    def on_selection_elimina(self, selected):
        self.remove_document(self.button_group_elimina.id(selected))
Beispiel #11
0
class AppScreenQ(QMainWindow):
    def __init__(self):
        super(AppScreenQ, self).__init__()
        self.setWindowTitle("Mistrz szachownicy QT")

        self.timeCounter = TIME_LIMIT
        self.gameFlag = False
        self.bar = None
        self.engine = AppModel()

        self.mainLayout = QVBoxLayout()
        self.setMinimumSize(800, 800)
        self._menuSetUp()
        self._boardSetUp()
        self._progressSetUp()
        self._controlSetUp()
        self._statsSetUp()

        widget = QWidget()
        widget.setLayout(self.mainLayout)
        self.setCentralWidget(widget)
        self.show()

    def _menuSetUp(self):
        fileMenu = self.menuBar().addMenu("&Menu")
        newAct = QAction('Opis gry', self)
        newAct.triggered.connect(self._overviewDisplay)
        fileMenu.addAction(newAct)

    def _overviewDisplay(self):
        dlg = QDialog(self)
        dlg.setWindowTitle("Opis gry!")
        overviewLayout = QVBoxLayout()
        overview = QLabel(OVERVIEW_TEXT)
        overview.setWordWrap(True)
        overviewLayout.addWidget(overview)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
        buttonBox.setCenterButtons(True)
        buttonBox.accepted.connect(dlg.accept)
        overviewLayout.addWidget(buttonBox)

        dlg.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        dlg.setLayout(overviewLayout)

        dlg.show()

    def _statsSetUp(self):
        style = """ 
        border: 2px solid gray;
        border-radius: 10px;
        padding: 8px;
        selection-background-color: darkgray;"""
        self.stats = QHBoxLayout()

        self.scoreStatic = QLabel("Aktualny wynik:")
        self.scoreStatic.setMinimumHeight(40)
        self.scoreStatic.setMaximumHeight(40)
        self.scoreStatic.setStyleSheet(style)
        self.scoreStatic.setAlignment(QtCore.Qt.AlignCenter)

        self.score = QLabel("0")
        self.score.setMinimumHeight(40)
        self.score.setMaximumHeight(40)
        self.score.setStyleSheet(style)
        self.score.setAlignment(QtCore.Qt.AlignCenter)

        self.coordStatic = QLabel("Znajdź:")
        self.coordStatic.setMinimumHeight(40)
        self.coordStatic.setMaximumHeight(40)
        self.coordStatic.setStyleSheet(style)
        self.coordStatic.setAlignment(QtCore.Qt.AlignCenter)

        self.coord = QLabel("")
        self.coord.setMinimumHeight(40)
        self.coord.setMaximumHeight(40)
        self.coord.setStyleSheet(style)
        self.coord.setAlignment(QtCore.Qt.AlignCenter)

        self.stats.addWidget(self.scoreStatic)
        self.stats.addWidget(self.score)
        self.stats.addWidget(self.coordStatic)
        self.stats.addWidget(self.coord)
        self.mainLayout.addLayout(self.stats)

    def _controlSetUp(self):
        style = """ 
        border-style: solid;
        border-color: gray;
        border-width: 2px;
        border-radius: 10px;"""

        self.menu = QHBoxLayout()

        self.startButton = QPushButton('Start', self)
        self.startButton.setStyleSheet(style)
        self.startButton.setMinimumHeight(40)
        self.startButton.clicked.connect(self._onButtonStart)

        self.stopButton = QPushButton('Stop', self)
        self.stopButton.setStyleSheet(style)
        self.stopButton.setMinimumHeight(40)
        self.stopButton.clicked.connect(self._onButtonStop)
        self.stopButton.setEnabled(False)

        self.menu.addWidget(self.startButton)
        self.menu.addWidget(self.stopButton)

        self.mainLayout.addLayout(self.menu)

    def _progressSetUp(self):
        self.progress = QProgressBar(self)
        self.progress.setTextVisible(False)
        self.progress.setStyleSheet("border: 2px solid grey;"
                                    "border-radius: 5px;"
                                    "text-align: center;"
                                    )
        self.mainLayout.addWidget(self.progress)
        self.progress.setMaximum(TIME_LIMIT)

    def _boardSetUp(self):
        frameWidget = QWidget()
        frameLayout = QHBoxLayout()
        frameLayout.addStretch()
        frameWidget.setFixedSize(560, 560)
        frameLayout.addWidget(frameWidget)
        frameLayout.addStretch()
        self.mainLayout.addLayout(frameLayout)
        squareLayout = QGridLayout(frameWidget)
        squareLayout.setSpacing(0)
        self.squares = QButtonGroup()
        for i in range(8 * 8):
            newButton = QPushButton()
            policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
            newButton.setSizePolicy(policy)
            x = getX(i)
            y = getY(i)
            if (x + y) % 2 == 0:
                newButton.setStyleSheet("background-color: linen")
            else:
                newButton.setStyleSheet("background-color: sienna")
            self.squares.addButton(newButton, i)
            squareLayout.addWidget(newButton, x, y)
        self.squares.setExclusive(True)
        self.squares.buttonPressed.connect(self._onSquareClick)
        self.squares.buttonReleased.connect(self._onSquareRelease)
        self.mainLayout.addLayout(squareLayout)

    def _onButtonStart(self):
        if self.gameFlag:
            return
        self.startButton.setEnabled(False)
        self.stopButton.setEnabled(True)
        self.gameFlag = True

        self.timeCounter = TIME_LIMIT
        self.bar = QTimer()
        self.bar.timeout.connect(self._onClockChanged)
        self.bar.start(TIME_INTERVAL)

        self.engine.counterReset()
        self.engine.getNextPosition()
        self.coord.setText(self.engine.getCurrentNotation())
        self.score.setText("0")

    def _onButtonStop(self):
        if not self.gameFlag:
            return
        self.bar.stop()
        self.stopButton.setEnabled(False)
        self.startButton.setEnabled(True)
        self.gameFlag = False

    def _onClockChanged(self):
        if (self.timeCounter == 0) or (self.gameFlag is False):
            self.startButton.setEnabled(True)
            self.stopButton.setEnabled(False)
            self.gameFlag = False
        self.timeCounter -= 1
        self.progress.setValue(self.timeCounter)

    def _onSquareClick(self, btn):
        if not self.gameFlag:
            return
        i = self.squares.id(btn)
        x = getX(i)
        y = getY(i)

        if self.engine.getCurrentPosition() == (x, y):
            btn.setStyleSheet("background-color: green")
            self.engine.counterAdd()
            self.engine.getNextPosition()
            self.coord.setText(self.engine.getCurrentNotation())
            self.score.setText(str(self.engine.getCounter()))
            return
        btn.setStyleSheet("background-color: red")

    def _onSquareRelease(self, btn):
        i = self.squares.id(btn)
        x = getX(i)
        y = getY(i)
        if (x + y) % 2 == 0:
            btn.setStyleSheet("background-color: linen")
        else:
            btn.setStyleSheet("background-color: sienna")
Beispiel #12
0
class SettingsDialog(QDialog, Ui_Dialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.setupUi(self)

        self.lineEdit_loginUsername.setText(app.settings.get("account", "username"))
        self.lineEdit_loginPassword.setText(app.settings.get("account", "password"))
        self.checkBox_autoLogin.setChecked(app.settings.getbool("account", "autologin"))
        self.checkBox_autoStartFrontend.setChecked(self.doesAutoStartFileExists())

        self.checkBox_enableDevelopersTools.setChecked(
            app.settings.getbool("frontend", "enabledeveloperstools"))
        self.checkBox_allowFlash.setChecked(app.settings.getbool("frontend", "allowflash"))
        self.checkBox_minimizeToSystray.setChecked(
            app.settings.getbool("frontend", "minimizetosystray"))
        self.checkBox_closeToMinimize.setChecked(
            app.settings.getbool("frontend", "closetominimize"))
        self.checkBox_popNotifications.setChecked(
            app.settings.getbool("frontend", "popnotifications"))
        self.checkBox_notifyBySound.setChecked(
            app.settings.getbool("frontend", "notifybysound"))
        self.checkBox_showMonitorWindow.setChecked(
            app.settings.getbool("frontend", "showmonitorwindow"))
        self.spinBox_monitorFullSpeed.setValue(
            app.settings.getint("frontend", "monitorfullspeed"))
        # clipboard related
        self.checkBox_watchClipboard.stateChanged.connect(self.slotWatchClipboardToggled)
        self.checkBox_watchClipboard.setChecked(app.settings.getbool("frontend", "watchclipboard"))
        self.slotWatchClipboardToggled(self.checkBox_watchClipboard.checkState())
        self.plaintext_watchPattern.setPlainText(app.settings.get("frontend", "watchpattern"))

        self.btngrp_etmStartWhen = QButtonGroup()
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen1, 1)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen2, 2)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen3, 3)

        try:
            startEtmWhen = callXwaredInterface("getStartEtmWhen")
            self.btngrp_etmStartWhen.button(startEtmWhen).setChecked(True)
        except SocketDoesntExist:
            self.group_etmStartWhen.setEnabled(False)

        self.btn_addMount.clicked.connect(self.slotAddMount)
        self.btn_removeMount.clicked.connect(self.slotRemoveMount)
        self.btn_refreshMount.clicked.connect(self.setupMounts)

        # Mounts
        self.setupMounts()

        # backend setting is a different thing!
        self.setupETM()

    @staticmethod
    def doesAutoStartFileExists():
        return os.path.lexists(constants.FRONTEND_AUTOSTART_FILE)

    @pyqtSlot(int)
    def slotWatchClipboardToggled(self, state):
        # disable pattern settings, before
        # 1. complete patterns
        # 2. test glib key file compatibility
        self.plaintext_watchPattern.setReadOnly(True)
        self.plaintext_watchPattern.setEnabled(state)

    @pyqtSlot()
    def setupMounts(self):
        self.table_mounts.setRowCount(0)
        self.table_mounts.clearContents()

        permissionCheckResult = app.mountsFaker.permissionCheck()
        permissionCheckFailed = ["无法获得检测权限。运行{}查看原因。".format(constants.PERMISSIONCHECK)]

        mountsMapping = app.mountsFaker.getMountsMapping()
        for i, mount in enumerate(app.mountsFaker.mounts):
            # mounts = ['/path/to/1', 'path/to/2', ...]
            self.table_mounts.insertRow(i)
            self.table_mounts.setItem(i, 0, QTableWidgetItem(mount))
            # drive1: the drive letter it should map to, by alphabetical order
            drive1 = chr(ord('C') + i) + ":"
            self.table_mounts.setItem(i, 1, QTableWidgetItem(drive1))
            # drive2: the drive letter it actually is assigned to
            drive2 = mountsMapping.get(mount, "无")

            # check 1: permission
            errors = permissionCheckResult.get(mount, permissionCheckFailed)

            # check 2: mapping
            if drive1 != drive2:
                errors.append(
                    "警告:盘符映射在'{actual}',而不是'{should}'。需要重启后端修复。".format(
                        actual = drive2,
                        should = drive1))

            brush = QBrush()
            if errors:
                brush.setColor(Qt.red)
                errString = "\n".join(errors)
            else:
                brush.setColor(Qt.darkGreen)
                errString = "正常"
            errWidget = QTableWidgetItem(errString)
            errWidget.setForeground(brush)

            self.table_mounts.setItem(i, 2, errWidget)
            del brush, errWidget

        self.table_mounts.resizeColumnsToContents()

    @pyqtSlot()
    def slotAddMount(self):
        fileDialog = QFileDialog(self, Qt.Dialog)
        fileDialog.setFileMode(QFileDialog.Directory)
        fileDialog.setOption(QFileDialog.ShowDirsOnly, True)
        fileDialog.setViewMode(QFileDialog.List)
        fileDialog.setDirectory(os.environ["HOME"])
        if fileDialog.exec():
            selected = fileDialog.selectedFiles()[0]
            if selected in self.newMounts:
                return
            row = self.table_mounts.rowCount()
            self.table_mounts.insertRow(row)
            self.table_mounts.setItem(row, 0, QTableWidgetItem(selected))
            self.table_mounts.setItem(row, 1, QTableWidgetItem("新近添加"))
            self.table_mounts.setItem(row, 2, QTableWidgetItem("新近添加"))

    @pyqtSlot()
    def slotRemoveMount(self):
        row = self.table_mounts.currentRow()
        self.table_mounts.removeRow(row)

    @pyqtSlot()
    def accept(self):
        app.settings.set("account", "username", self.lineEdit_loginUsername.text())
        app.settings.set("account", "password", self.lineEdit_loginPassword.text())
        app.settings.setbool("account", "autologin", self.checkBox_autoLogin.isChecked())
        doesAutoStartFileExists = self.doesAutoStartFileExists()
        if self.checkBox_autoStartFrontend.isChecked() and not doesAutoStartFileExists:
            # mkdir if autostart dir doesn't exist
            try:
                os.mkdir(os.path.dirname(constants.FRONTEND_AUTOSTART_FILE))
            except OSError:
                pass  # already exists
            os.symlink(constants.DESKTOP_FILE_LOCATION,
                       constants.FRONTEND_AUTOSTART_FILE)
        elif (not self.checkBox_autoStartFrontend.isChecked()) and doesAutoStartFileExists:
            os.remove(constants.FRONTEND_AUTOSTART_FILE)

        app.settings.setbool("frontend", "enabledeveloperstools",
                             self.checkBox_enableDevelopersTools.isChecked())
        app.settings.setbool("frontend", "allowflash",
                             self.checkBox_allowFlash.isChecked())
        app.settings.setbool("frontend", "minimizetosystray",
                             self.checkBox_minimizeToSystray.isChecked())

        # A possible Qt bug
        # https://bugreports.qt-project.org/browse/QTBUG-37695
        app.settings.setbool("frontend", "closetominimize",
                             self.checkBox_closeToMinimize.isChecked())
        app.settings.setbool("frontend", "popnotifications",
                             self.checkBox_popNotifications.isChecked())
        app.settings.setbool("frontend", "notifybysound",
                             self.checkBox_notifyBySound.isChecked())

        app.settings.setbool("frontend", "showmonitorwindow",
                             self.checkBox_showMonitorWindow.isChecked())
        app.settings.setint("frontend", "monitorfullspeed",
                            self.spinBox_monitorFullSpeed.value())
        app.settings.setbool("frontend", "watchclipboard",
                             self.checkBox_watchClipboard.isChecked())
        # app.settings.set("frontend", "watchpattern",
        #                         self.plaintext_watchPattern.toPlainText())

        if self.group_etmStartWhen.isEnabled():
            startEtmWhen = self.btngrp_etmStartWhen.id(self.btngrp_etmStartWhen.checkedButton())
            try:
                callXwaredInterface("setStartEtmWhen", startEtmWhen)
            except SocketDoesntExist:
                QMessageBox.warning(None, "Xware Desktop",
                                    "选项未能成功设置:{}。".format(self.group_etmStartWhen.title()),
                                    QMessageBox.Ok, QMessageBox.Ok)

        app.settings.save()

        app.mountsFaker.mounts = self.newMounts
        app.settings.applySettings.emit()
        super().accept()

    @property
    def newMounts(self):
        return list(map(lambda row: self.table_mounts.item(row, 0).text(),
                        range(self.table_mounts.rowCount())))

    @pyqtSlot()
    def setupETM(self):
        # fill values
        lcPort = app.xwaredpy.lcPort
        self.lineEdit_lcport.setText(str(lcPort) if lcPort else "不可用")

        etmSettings = app.etmpy.getSettings()
        if etmSettings:
            self.spinBox_dSpeedLimit.setValue(etmSettings.dLimit)
            self.spinBox_uSpeedLimit.setValue(etmSettings.uLimit)
            self.spinBox_maxRunningTasksNum.setValue(etmSettings.maxRunningTasksNum)

            # connect signals
            self.accepted.connect(self.saveETM)
        else:
            self.spinBox_dSpeedLimit.setEnabled(False)
            self.spinBox_uSpeedLimit.setEnabled(False)
            self.spinBox_maxRunningTasksNum.setEnabled(False)

    @pyqtSlot()
    def saveETM(self):
        newsettings = EtmSetting(dLimit = self.spinBox_dSpeedLimit.value(),
                                 uLimit = self.spinBox_uSpeedLimit.value(),
                                 maxRunningTasksNum = self.spinBox_maxRunningTasksNum.value())

        app.etmpy.saveSettings(newsettings)
Beispiel #13
0
class SettingsDialog(QDialog, Ui_Dialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setWindowModality(Qt.WindowModal)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.mainWin = parent
        self.setupUi(self)

        self.lineEdit_loginUsername.setText(self.settings.get("account", "username"))
        self.lineEdit_loginPassword.setText(self.settings.get("account", "password"))
        self.checkBox_autoLogin.setChecked(self.settings.getbool("account", "autologin"))

        self.checkBox_enableDevelopersTools.setChecked(
            self.settings.getbool("frontend", "enabledeveloperstools"))
        self.checkBox_allowFlash.setChecked(self.settings.getbool("frontend", "allowflash"))
        self.checkBox_minimizeToSystray.setChecked(self.settings.getbool("frontend", "minimizetosystray"))
        self.checkBox_closeToMinimize.setChecked(self.settings.getbool("frontend", "closetominimize"))
        self.checkBox_popNotifications.setChecked(self.settings.getbool("frontend", "popnotifications"))
        self.checkBox_notifyBySound.setChecked(self.settings.getbool("frontend", "notifybysound"))
        self.checkBox_showMonitorWindow.setChecked(self.settings.getbool("frontend", "showmonitorwindow"))
        self.spinBox_monitorFullSpeed.setValue(self.settings.getint("frontend", "monitorfullspeed"))
        # clipboard related
        self.checkBox_watchClipboard.stateChanged.connect(self.slotWatchClipboardToggled)
        self.checkBox_watchClipboard.setChecked(self.settings.getbool("frontend", "watchclipboard"))
        self.slotWatchClipboardToggled(self.checkBox_watchClipboard.checkState())
        self.plaintext_watchPattern.setPlainText(self.settings.get("frontend", "watchpattern"))

        from PyQt5.QtWidgets import QButtonGroup
        self.btngrp_etmStartWhen = QButtonGroup()
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen1, 1)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen2, 2)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen3, 3)
        self.btngrp_etmStartWhen.button(self.settings.getint("xwared", "startetmwhen")).setChecked(True)

        self.accepted.connect(self.writeSettings)

        self.btn_addMount.clicked.connect(self.slotAddMount)
        self.btn_removeMount.clicked.connect(self.slotRemoveMount)
        self.btn_refreshMount.clicked.connect(self.setupMounts)

        # Mounts
        self.setupMounts()

        # backend setting is a different thing!
        self.setupETM()

    # shorthand
    @property
    def settings(self):
        return self.mainWin.settings
    # shorthand ends

    @staticmethod
    def permissionCheck():
        import re
        ansiEscape = re.compile(r'\x1b[^m]*m')

        import subprocess
        with subprocess.Popen([constants.PERMISSIONCHECK], stdout = subprocess.PIPE, stderr = subprocess.PIPE) as proc:
            output = proc.stdout.read().decode("utf-8")
            output = ansiEscape.sub('', output)
            lines = output.split("\n")

        prevLine = None
        currMount = None
        result = {}
        for line in lines:
            if len(line.strip()) == 0:
                continue

            if all(map(lambda c: c == '=', line)):
                if currMount:
                    result[currMount] = result[currMount][:-1]

                result[prevLine] = []
                currMount = prevLine
                continue

            if currMount:
                if line != "正常。":
                    result[currMount].append(line)

            prevLine = line

        return result

    @pyqtSlot(int)
    def slotWatchClipboardToggled(self, state):
        # disable pattern settings, before
        # 1. complete patterns
        # 2. test glib key file compatibility
        self.plaintext_watchPattern.setReadOnly(True)
        self.plaintext_watchPattern.setEnabled(state)

    @pyqtSlot()
    def setupMounts(self):
        self.table_mounts.setRowCount(0)
        self.table_mounts.clearContents()

        PermissionError = self.permissionCheck()

        mountsMapping = self.mainWin.mountsFaker.getMountsMapping()
        for i, mount in enumerate(self.mainWin.mountsFaker.mounts):
            # mounts = ['/path/to/1', 'path/to/2', ...]
            self.table_mounts.insertRow(i)
            self.table_mounts.setItem(i, 0, QTableWidgetItem(mount))
            drive1 = chr(ord('C') + i) + ":" # the drive letter it should map to, by alphabetical order
            self.table_mounts.setItem(i, 1, QTableWidgetItem(drive1))
            drive2 = mountsMapping.get(mount, "无") # the drive letter it actually is assigned to

            # check 1: permission
            errors = PermissionError.get(mount, ["无法获得检测权限。运行/opt/xware_desktop/permissioncheck查看原因。"])

            # check 2: mapping
            if drive1 != drive2:
                errors.append("警告:盘符映射在'{actual}',而不是'{should}'。需要重启后端修复。".format(actual = drive2, should = drive1))

            from PyQt5.Qt import Qt
            from PyQt5.QtGui import QBrush

            brush = QBrush()
            if errors:
                brush.setColor(Qt.red)
                errString = "\n".join(errors)
            else:
                brush.setColor(Qt.darkGreen)
                errString = "正常"
            errWidget = QTableWidgetItem(errString)
            errWidget.setForeground(brush)

            self.table_mounts.setItem(i, 2, errWidget)
            del brush, errWidget

        self.table_mounts.resizeColumnsToContents()

    @pyqtSlot()
    def slotAddMount(self):
        import os
        from PyQt5.QtWidgets import QFileDialog
        from PyQt5.Qt import Qt

        fileDialog = QFileDialog(self, Qt.Dialog)
        fileDialog.setFileMode(QFileDialog.Directory)
        fileDialog.setOption(QFileDialog.ShowDirsOnly, True)
        fileDialog.setViewMode(QFileDialog.List)
        fileDialog.setDirectory(os.environ["HOME"])
        if (fileDialog.exec()):
            selected = fileDialog.selectedFiles()[0]
            if selected in self.newMounts:
                return
            row = self.table_mounts.rowCount()
            self.table_mounts.insertRow(row)
            self.table_mounts.setItem(row, 0, QTableWidgetItem(selected))
            self.table_mounts.setItem(row, 1, QTableWidgetItem("新近添加"))
            self.table_mounts.setItem(row, 2, QTableWidgetItem("新近添加"))

    @pyqtSlot()
    def slotRemoveMount(self):
        row = self.table_mounts.currentRow()
        self.table_mounts.removeRow(row)

    @pyqtSlot()
    def writeSettings(self):
        self.settings.set("account", "username", self.lineEdit_loginUsername.text())
        self.settings.set("account", "password", self.lineEdit_loginPassword.text())
        self.settings.setbool("account", "autologin", self.checkBox_autoLogin.isChecked())

        self.settings.setbool("frontend", "enabledeveloperstools",
                                self.checkBox_enableDevelopersTools.isChecked())
        self.settings.setbool("frontend", "allowflash",
                                self.checkBox_allowFlash.isChecked())
        self.settings.setbool("frontend", "minimizetosystray",
                                self.checkBox_minimizeToSystray.isChecked())

        # A possible Qt bug
        # https://bugreports.qt-project.org/browse/QTBUG-37695
        self.settings.setbool("frontend", "closetominimize",
                                self.checkBox_closeToMinimize.isChecked())
        self.settings.setbool("frontend", "popnotifications",
                                self.checkBox_popNotifications.isChecked())
        self.settings.setbool("frontend", "notifybysound",
                                self.checkBox_notifyBySound.isChecked())

        self.settings.setbool("frontend", "showmonitorwindow",
                                self.checkBox_showMonitorWindow.isChecked())
        self.settings.setint("frontend", "monitorfullspeed",
                                self.spinBox_monitorFullSpeed.value())
        self.settings.setbool("frontend", "watchclipboard",
                                self.checkBox_watchClipboard.isChecked())
        # self.settings.set("frontend", "watchpattern",
        #                         self.plaintext_watchPattern.toPlainText())
        self.settings.setint("xwared", "startetmwhen",
                          self.btngrp_etmStartWhen.id(self.btngrp_etmStartWhen.checkedButton()))

        startETMWhen = self.settings.getint("xwared", "startetmwhen")
        if startETMWhen == 1:
            self.settings.setbool("xwared", "startetm", True)

        self.settings.save()

        self.mainWin.mountsFaker.setMounts(self.newMounts)
        self.settings.applySettings.emit()

    @property
    def newMounts(self):
        return list(map(lambda row: self.table_mounts.item(row, 0).text(),
                        range(self.table_mounts.rowCount())))

    @pyqtSlot()
    def setupETM(self):
        etmpy = self.mainWin.etmpy

        # fill values
        self.lineEdit_lcport.setText(etmpy.cfg.get("local_control.listen_port", "不可用"))

        etmSettings = etmpy.getSettings()
        if etmSettings:
            self.spinBox_dSpeedLimit.setValue(etmSettings.dLimit)
            self.spinBox_uSpeedLimit.setValue(etmSettings.uLimit)
            self.spinBox_maxRunningTasksNum.setValue(etmSettings.maxRunningTasksNum)

            # connect signals
            self.accepted.connect(self.saveETM)
        else:
            self.spinBox_dSpeedLimit.setEnabled(False)
            self.spinBox_uSpeedLimit.setEnabled(False)
            self.spinBox_maxRunningTasksNum.setEnabled(False)

    @pyqtSlot()
    def saveETM(self):
        import etmpy

        newsettings = etmpy.EtmSetting(dLimit = self.spinBox_dSpeedLimit.value(),
                                       uLimit = self.spinBox_uSpeedLimit.value(),
                                       maxRunningTasksNum = self.spinBox_maxRunningTasksNum.value())

        self.mainWin.etmpy.saveSettings(newsettings)
Beispiel #14
0
class Test(QWidget):
    def __init__(self, topic_id, user_id):
        super().__init__()
        self.initUI()
        self.button_group = QButtonGroup()
        self.step = 0
        self.user_answers = []
        self.topic_id = topic_id
        self.user_id = user_id
        self.length = len(get_data(self.topic_id))

        self.test(self.step)

    def initUI(self):
        self.setGeometry(100, 100, 650, 300)
        self.setWindowTitle('Тест')

        self.input_first = QLabel(self)
        self.input_first.setGeometry(QRect(50, -10, 250, 100))
        self.input_first.setText('Вопрос')
        self.input_first.setFont(QtGui.QFont('Arial', 13))

        self.own_result = QLabel(self)
        self.question = QLabel(self)
        self.question.move(50, 70)
        self.layout = QFrame(self)
        self.init_button()

    def test(self, step):
        a = 0
        j = 0

        data = get_data(self.topic_id)

        correct = data[step]

        self.question.setText(correct[2])
        self.question.setGeometry(QRect(50, 52, 600, 80))
        font = QtGui.QFont()
        font.setPointSize(13)
        self.question.setFont(font)
        self.question.setWordWrap(True)

        numbers = (self.length - 1 if self.length < 4 else 3)
        failed = random.sample(get_unique_data(self.topic_id, correct[1]), numbers)
        for i in random.sample(failed + [correct], numbers + 1):
            a += 30
            j += 1
            button_name = "radioButton" + str(j)
            button_name = QRadioButton(self.layout)
            if correct[0] != i[0]:
                self.button_group.addButton(button_name, correct[0])
            else:
                self.button_group.addButton(button_name, 0)

            button_name.setGeometry(QRect(50, 100 + a, 255, 17))
            button_name.setObjectName("radioButton" + str(j))
            button_name.setText(i[1])
            button_name.toggled.connect(self.get_answer)
            button_name.show()

        self.input_first.setText('Вопрос № ' + str(self.step + 1) + ' из ' + str(self.length))

    def get_answer(self):
        self.btn.setEnabled(True)

    def init_button(self):
        self.btn = QPushButton('Перейти к следующему вопросу.', self)
        self.btn.setEnabled(False)
        self.btn.resize(200, 40)
        self.btn.move(50, 250)
        self.btn.clicked.connect(self.validate)

    def validate(self):
        for children in self.button_group.buttons():
            if children.isChecked() and self.button_group.id(children) > 0:
                self.user_answers.append(self.button_group.id(children))
            children.hide()

        self.btn.setEnabled(False)
        self.step += 1

        if self.step < self.length:
            self.test(self.step)
        else:
            if self.user_answers:
                self.input_first.setText('Ошибки:')
                self.conclusion()
            else:
                self.input_first.setText('Ошибок нет. Молодец!')
                self.conclusion()

    def conclusion(self):
        con = sqlite3.connect('quiz_db.db')
        cur = con.cursor()
        query = cur.execute("SELECT * FROM qa WHERE id in (%s)" %
                            (', '.join(str(i) for i in self.user_answers))).fetchall()
        con.commit()
        con.close()

        result = 99 + ((self.length - len(self.user_answers) * 100) // self.length)
        save_score(self.user_id, self.topic_id, result)
        text = ''
        for i in query:
            text += i[1] + ' — ' + i[2] + '\n'

        self.own_result.setGeometry(QRect(50, 175, 275, 100))
        self.own_result.setText('Ваш результат составляет: ' + str(result) + '%')
        self.own_result.setFont(QtGui.QFont('Arial', 13))

        self.question.setText(text)
        self.question.move(50, 75)
        self.btn.setText('Вернуться на главную страницу.')
        self.btn.setEnabled(True)
        self.btn.clicked.connect(self.restart)

    def restart(self):
        self.cl = SelectQuiz(self.user_id)
        self.cl.show()
        self.close()
Beispiel #15
0
class SettingsDialog(QDialog, Ui_Dialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.setupUi(self)

        self.lineEdit_loginUsername.setText(app.settings.get("adapter-legacy", "username"))
        self.lineEdit_loginPassword.setText(app.settings.get("adapter-legacy", "password"))
        self.checkBox_autoLogin.setChecked(app.settings.getbool("legacy", "autologin"))
        self.checkBox_autoStartFrontend.setChecked(app.autoStart)
        if sys.platform == "linux":
            self.checkBox_autoStartFrontend.setEnabled(True)

        adapter = app.adapterManager[0]

        # Xwared Management
        managedBySystemd = adapter.daemonManagedBySystemd
        managedByUpstart = adapter.daemonManagedByUpstart
        managedByAutostart = adapter.daemonManagedByAutostart

        self.radio_managedBySystemd.setChecked(managedBySystemd)
        self.radio_managedByUpstart.setChecked(managedByUpstart)
        self.radio_managedByAutostart.setChecked(managedByAutostart)
        self.radio_managedByNothing.setChecked(
            not (managedBySystemd or managedByUpstart or managedByAutostart))

        initType = getInitType()
        self.radio_managedBySystemd.setEnabled(initType == InitType.SYSTEMD)
        self.radio_managedByUpstart.setEnabled(initType == InitType.UPSTART)

        if not adapter.useXwared:
            self.group_etmStartWhen.setEnabled(False)
            self.group_initManaged.setEnabled(False)

        self.btngrp_etmStartWhen = QButtonGroup()
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen1, 1)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen2, 2)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen3, 3)

        if adapter.useXwared:
            startEtmWhen = adapter.startEtmWhen
            self.btngrp_etmStartWhen.button(startEtmWhen).setChecked(True)

        # frontend
        self.checkBox_enableDevelopersTools.setChecked(
            app.settings.getbool("legacy", "enabledeveloperstools"))
        self.checkBox_allowFlash.setChecked(app.settings.getbool("legacy", "allowflash"))
        self.checkBox_minimizeToSystray.setChecked(
            app.settings.getbool("frontend", "minimizetosystray"))
        self.checkBox_closeToMinimize.setChecked(
            app.settings.getbool("frontend", "closetominimize"))
        self.checkBox_popNotifications.setChecked(
            app.settings.getbool("frontend", "popnotifications"))
        self.checkBox_notifyBySound.setChecked(
            app.settings.getbool("frontend", "notifybysound"))
        self.checkBox_showMonitorWindow.setChecked(
            app.settings.getbool("frontend", "showmonitorwindow"))
        self.spinBox_monitorFullSpeed.setValue(
            app.settings.getint("frontend", "monitorfullspeed"))

        # clipboard related
        self.checkBox_watchClipboard.stateChanged.connect(self.slotWatchClipboardToggled)
        self.checkBox_watchClipboard.setChecked(app.settings.getbool("frontend", "watchclipboard"))
        self.slotWatchClipboardToggled(self.checkBox_watchClipboard.checkState())
        self.plaintext_watchPattern.setPlainText(app.settings.get("frontend", "watchpattern"))

        self.btn_addMount.clicked.connect(self.slotAddMount)
        self.btn_removeMount.clicked.connect(self.slotRemoveMount)

        # Mounts
        self.setupMounts()

        # backend setting is a different thing!
        self.setupETM()

    @pyqtSlot(int)
    def slotWatchClipboardToggled(self, state):
        self.plaintext_watchPattern.setEnabled(state)

    @pyqtSlot()
    def setupMounts(self):
        adapter = app.adapterManager[0]
        if not adapter.useXwared:
            self.tab_mount.setEnabled(False)
            return
        self.table_mounts.setRowCount(0)
        self.table_mounts.clearContents()

        mountsMapping = app.adapterManager[0].mountsFaker.getMountsMapping()
        for i, mount in enumerate(app.adapterManager[0].mountsFaker.mounts):
            self.table_mounts.insertRow(i)
            # drive1: the drive letter it should map to, by alphabetical order
            drive1 = app.adapterManager[0].mountsFaker.driveIndexToLetter(i)
            self.table_mounts.setItem(i, 0, QTableWidgetItem(drive1 + "\\TDDOWNLOAD"))

            # mounts = ['/path/to/1', 'path/to/2', ...]
            self.table_mounts.setItem(i, 1, QTableWidgetItem(mount))

            # drive2: the drive letter it actually is assigned to
            drive2 = mountsMapping.get(mount, "无")

            errors = []

            # check: mapping
            if drive1 != drive2:
                errors.append(
                    "错误:盘符映射在'{actual}',而不是'{should}'。\n"
                    "如果这是个新挂载的文件夹,请尝试稍等,或重启后端,可能会修复此问题。"
                    .format(actual = drive2, should = drive1))

            brush = QBrush()
            if errors:
                brush.setColor(Qt.red)
                errString = "\n".join(errors)
            else:
                brush.setColor(Qt.darkGreen)
                errString = "正常"
            errWidget = QTableWidgetItem(errString)
            errWidget.setForeground(brush)

            self.table_mounts.setItem(i, 2, errWidget)
            del brush, errWidget

        self.table_mounts.resizeColumnsToContents()

    @pyqtSlot()
    def slotAddMount(self):
        fileDialog = QFileDialog(self, Qt.Dialog)
        fileDialog.setFileMode(QFileDialog.Directory)
        fileDialog.setOption(QFileDialog.ShowDirsOnly, True)
        fileDialog.setViewMode(QFileDialog.List)
        fileDialog.setDirectory(os.environ["HOME"])
        if fileDialog.exec():
            selected = fileDialog.selectedFiles()[0]
            if selected in self.newMounts:
                return
            row = self.table_mounts.rowCount()
            self.table_mounts.insertRow(row)
            self.table_mounts.setItem(
                row, 0,
                QTableWidgetItem(app.adapterManager[0].mountsFaker.driveIndexToLetter(row) +
                                 "\\TDDOWNLOAD"))
            self.table_mounts.setItem(row, 1, QTableWidgetItem(selected))
            self.table_mounts.setItem(row, 2, QTableWidgetItem("新近添加"))

    @pyqtSlot()
    def slotRemoveMount(self):
        row = self.table_mounts.currentRow()
        self.table_mounts.removeRow(row)

    @pyqtSlot()
    def accept(self):
        app.settings.set("adapter-legacy", "username", self.lineEdit_loginUsername.text())
        app.settings.set("adapter-legacy", "password", self.lineEdit_loginPassword.text())
        app.settings.setbool("legacy", "autologin", self.checkBox_autoLogin.isChecked())

        app.autoStart = self.checkBox_autoStartFrontend.isChecked()

        app.adapterManager[0].daemonManagedBySystemd = self.radio_managedBySystemd.isChecked()
        app.adapterManager[0].daemonManagedByUpstart = self.radio_managedByUpstart.isChecked()
        app.adapterManager[0].daemonManagedByAutostart = self.radio_managedByAutostart.isChecked()

        app.settings.setbool("legacy", "enabledeveloperstools",
                             self.checkBox_enableDevelopersTools.isChecked())
        app.settings.setbool("legacy", "allowflash",
                             self.checkBox_allowFlash.isChecked())
        app.settings.setbool("frontend", "minimizetosystray",
                             self.checkBox_minimizeToSystray.isChecked())

        # A possible Qt bug
        # https://bugreports.qt-project.org/browse/QTBUG-37695
        app.settings.setbool("frontend", "closetominimize",
                             self.checkBox_closeToMinimize.isChecked())
        app.settings.setbool("frontend", "popnotifications",
                             self.checkBox_popNotifications.isChecked())
        app.settings.setbool("frontend", "notifybysound",
                             self.checkBox_notifyBySound.isChecked())

        app.settings.setbool("frontend", "showmonitorwindow",
                             self.checkBox_showMonitorWindow.isChecked())
        app.settings.setint("frontend", "monitorfullspeed",
                            self.spinBox_monitorFullSpeed.value())
        app.settings.setbool("frontend", "watchclipboard",
                             self.checkBox_watchClipboard.isChecked())
        app.settings.set("frontend", "watchpattern",
                         self.plaintext_watchPattern.toPlainText())

        if self.group_etmStartWhen.isEnabled():
            startEtmWhen = self.btngrp_etmStartWhen.id(self.btngrp_etmStartWhen.checkedButton())
            app.adapterManager[0].startEtmWhen = startEtmWhen

        app.settings.save()

        if self.tab_mount.isEnabled():
            app.adapterManager[0].mountsFaker.mounts = self.newMounts
        app.applySettings.emit()
        super().accept()

    @property
    def newMounts(self):
        return list(map(lambda row: self.table_mounts.item(row, 1).text(),
                        range(self.table_mounts.rowCount())))

    @pyqtSlot()
    def setupETM(self):
        # fill values
        adapter = app.adapterManager[0]
        settings = adapter.backendSettings
        etmRunning = adapter.etmPid != 0
        if etmRunning and settings.initialized:
            self.spinBox_dSpeedLimit.setValue(settings.downloadSpeedLimit)
            self.spinBox_uSpeedLimit.setValue(settings.uploadSpeedLimit)
            self.spinBox_maxRunningTasksNum.setValue(settings.maxRunTaskNumber)

            # connect signals
            self.accepted.connect(self.saveETM)
        else:
            self.spinBox_dSpeedLimit.setEnabled(False)
            self.spinBox_uSpeedLimit.setEnabled(False)
            self.spinBox_maxRunningTasksNum.setEnabled(False)

    @pyqtSlot()
    def saveETM(self):
        adapter = app.adapterManager[0]
        adapter.do_applySettings({
            "downloadSpeedLimit": self.spinBox_dSpeedLimit.value(),
            "uploadSpeedLimit": self.spinBox_uSpeedLimit.value(),
            "maxRunTaskNumber": self.spinBox_maxRunningTasksNum.value(),
        })
Beispiel #16
0
 def create_rows(self, layout, sarea):
     u"""Build the rows of the dialog box"""
     play_button_group = QButtonGroup(sarea)
     old_play_button_group = QButtonGroup(sarea)
     for num, entry in enumerate(self.entries_list, 2):
         tt_text = self.build_text_help_label(entry)
         ico_label = QLabel('', sarea)
         ico_label.setToolTip(tt_text)
         if entry.icon:
             ico_label.setPixmap(QPixmap.fromImage(entry.icon))
         layout.addWidget(ico_label, num, 0)
         tt_label = QLabel(entry.display_word, sarea)
         tt_label.setToolTip(tt_text)
         layout.addWidget(tt_label, num, 1)
         if self.hide_text:
             tt_label.hide()
         # Play button.
         t_play_button = QPushButton(sarea)
         play_button_group.addButton(t_play_button, num-2)
         t_play_button.setToolTip(self.play_help)
         t_play_button.setIcon(QIcon(os.path.join(icons_dir, 'play.png')))
         layout.addWidget(t_play_button, num, self.play_column)
         if self.note[entry.audio_field_name]:
             t_play_old_button = QPushButton(sarea)
             old_play_button_group.addButton(t_play_old_button, num-2)
             t_play_old_button.setIcon(
                 QIcon(os.path.join(icons_dir, 'play.png')))
             if not self.hide_text:
                 t_play_old_button.setToolTip(
                     self.note[entry.audio_field_name])
             else:
                 t_play_old_button.setToolTip(self.play_old_help_short)
             layout.addWidget(t_play_old_button, num, self.play_old_column)
         else:
             dummy_label = QLabel('', sarea)
             dummy_label.setToolTip(self.play_old_empty_line_help)
             layout.addWidget(dummy_label, num, self.play_old_column)
         # The group where we later look what to do:
         t_button_group = QButtonGroup(sarea)
         t_button_group.setExclusive(True)
         # Now the four buttons
         t_add_button = QPushButton(sarea)
         t_add_button.setCheckable(True)
         t_add_button.setFlat(True)
         t_add_button.setToolTip(self.add_help_text_short)
         t_add_button.setIcon(QIcon(os.path.join(icons_dir, 'add.png')))
         layout.addWidget(t_add_button, num, self.add_column)
         t_button_group.addButton(t_add_button, Action.Add)
         t_keep_button = QPushButton(sarea)
         t_keep_button.setCheckable(True)
         t_keep_button.setFlat(True)
         t_keep_button.setToolTip(self.keep_help_text_short)
         t_keep_button.setIcon(QIcon(os.path.join(icons_dir, 'keep.png')))
         layout.addWidget(t_keep_button, num, self.keep_column)
         t_button_group.addButton(t_keep_button, Action.Keep)
         t_delete_button = QPushButton(sarea)
         t_delete_button.setCheckable(True)
         t_delete_button.setFlat(True)
         t_delete_button.setToolTip(self.delete_help_text_short)
         t_delete_button.setIcon(
             QIcon(os.path.join(icons_dir, 'delete.png')))
         layout.addWidget(t_delete_button, num, self.delete_column)
         t_button_group.addButton(t_delete_button,  Action.Delete)
         t_blacklist_button = QPushButton(sarea)
         t_blacklist_button.setCheckable(True)
         t_blacklist_button.setFlat(True)
         t_blacklist_button.setToolTip(self.blacklist_help_text_short)
         t_blacklist_button.setIcon(
             QIcon(os.path.join(icons_dir, 'blacklist.png')))
         if entry.entry_hash:
             layout.addWidget(
                 t_blacklist_button, num, self.blacklist_column)
         else:
             t_blacklist_button.hide()
             dummy_label_bl = QLabel('', sarea)
             dummy_label_bl.setToolTip(self.blacklist_empty_line_help)
             layout.addWidget(dummy_label_bl, num, self.blacklist_column)
         t_button_group.button(entry.action).setChecked(True)
         # New: check a button based on how good the downloader is.
         t_button_group.addButton(t_blacklist_button, Action.Blacklist)
         self.buttons_groups.append(t_button_group)
     play_button_group.buttonClicked.connect(
         lambda button: play(
             self.entries_list[play_button_group.id(button)].file_path))
     # N.B.: anki.sound.play() plays files from anywhere, not just
     # from the colection.media folder. We should be good,
     # here. (This behaviour may be a security risk, idk.)
     old_play_button_group.buttonClicked.connect(
         lambda button: playFromText(
             self.note[
                 self.entries_list[
                     old_play_button_group.id(button)].audio_field_name]))
Beispiel #17
0
class SettingsDialog(QDialog, Ui_Dialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.setupUi(self)

        self.lineEdit_loginUsername.setText(
            app.settings.get("account", "username"))
        self.lineEdit_loginPassword.setText(
            app.settings.get("account", "password"))
        self.checkBox_autoLogin.setChecked(
            app.settings.getbool("account", "autologin"))
        self.checkBox_autoStartFrontend.setChecked(app.autoStart)

        # Xwared Management
        managedBySystemd = app.xwaredpy.managedBySystemd
        managedByUpstart = app.xwaredpy.managedByUpstart
        managedByAutostart = app.xwaredpy.managedByAutostart

        self.radio_managedBySystemd.setChecked(managedBySystemd)
        self.radio_managedByUpstart.setChecked(managedByUpstart)
        self.radio_managedByAutostart.setChecked(managedByAutostart)
        self.radio_managedByNothing.setChecked(not (
            managedBySystemd or managedByUpstart or managedByAutostart))

        initType = getInitType()
        self.radio_managedBySystemd.setEnabled(initType == InitType.SYSTEMD)
        self.radio_managedByUpstart.setEnabled(initType == InitType.UPSTART)

        # frontend
        self.checkBox_enableDevelopersTools.setChecked(
            app.settings.getbool("frontend", "enabledeveloperstools"))
        self.checkBox_allowFlash.setChecked(
            app.settings.getbool("frontend", "allowflash"))
        self.checkBox_minimizeToSystray.setChecked(
            app.settings.getbool("frontend", "minimizetosystray"))
        self.checkBox_closeToMinimize.setChecked(
            app.settings.getbool("frontend", "closetominimize"))
        self.checkBox_popNotifications.setChecked(
            app.settings.getbool("frontend", "popnotifications"))
        self.checkBox_notifyBySound.setChecked(
            app.settings.getbool("frontend", "notifybysound"))
        self.checkBox_showMonitorWindow.setChecked(
            app.settings.getbool("frontend", "showmonitorwindow"))
        self.spinBox_monitorFullSpeed.setValue(
            app.settings.getint("frontend", "monitorfullspeed"))

        # clipboard related
        self.checkBox_watchClipboard.stateChanged.connect(
            self.slotWatchClipboardToggled)
        self.checkBox_watchClipboard.setChecked(
            app.settings.getbool("frontend", "watchclipboard"))
        self.slotWatchClipboardToggled(
            self.checkBox_watchClipboard.checkState())
        self.plaintext_watchPattern.setPlainText(
            app.settings.get("frontend", "watchpattern"))

        self.btngrp_etmStartWhen = QButtonGroup()
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen1, 1)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen2, 2)
        self.btngrp_etmStartWhen.addButton(self.radio_backendStartWhen3, 3)

        startEtmWhen = app.xwaredpy.startEtmWhen
        if startEtmWhen:
            self.btngrp_etmStartWhen.button(startEtmWhen).setChecked(True)
        else:
            self.group_etmStartWhen.setEnabled(False)

        self.btn_addMount.clicked.connect(self.slotAddMount)
        self.btn_removeMount.clicked.connect(self.slotRemoveMount)

        # Mounts
        self.setupMounts()

        # backend setting is a different thing!
        self.setupETM()

    @pyqtSlot(int)
    def slotWatchClipboardToggled(self, state):
        self.plaintext_watchPattern.setEnabled(state)

    @pyqtSlot()
    def setupMounts(self):
        self.table_mounts.setRowCount(0)
        self.table_mounts.clearContents()

        mountsMapping = app.mountsFaker.getMountsMapping()
        for i, mount in enumerate(app.mountsFaker.mounts):
            self.table_mounts.insertRow(i)
            # drive1: the drive letter it should map to, by alphabetical order
            drive1 = app.mountsFaker.driveIndexToLetter(i)
            self.table_mounts.setItem(
                i, 0, QTableWidgetItem(drive1 + "\\TDDOWNLOAD"))

            # mounts = ['/path/to/1', 'path/to/2', ...]
            self.table_mounts.setItem(i, 1, QTableWidgetItem(mount))

            # drive2: the drive letter it actually is assigned to
            drive2 = mountsMapping.get(mount, "无")

            errors = []

            # check: mapping
            if drive1 != drive2:
                errors.append("错误:盘符映射在'{actual}',而不是'{should}'。\n"
                              "如果这是个新挂载的文件夹,请尝试稍等,或重启后端,可能会修复此问题。".format(
                                  actual=drive2, should=drive1))

            brush = QBrush()
            if errors:
                brush.setColor(Qt.red)
                errString = "\n".join(errors)
            else:
                brush.setColor(Qt.darkGreen)
                errString = "正常"
            errWidget = QTableWidgetItem(errString)
            errWidget.setForeground(brush)

            self.table_mounts.setItem(i, 2, errWidget)
            del brush, errWidget

        self.table_mounts.resizeColumnsToContents()

    @pyqtSlot()
    def slotAddMount(self):
        fileDialog = QFileDialog(self, Qt.Dialog)
        fileDialog.setFileMode(QFileDialog.Directory)
        fileDialog.setOption(QFileDialog.ShowDirsOnly, True)
        fileDialog.setViewMode(QFileDialog.List)
        fileDialog.setDirectory(os.environ["HOME"])
        if fileDialog.exec():
            selected = fileDialog.selectedFiles()[0]
            if selected in self.newMounts:
                return
            row = self.table_mounts.rowCount()
            self.table_mounts.insertRow(row)
            self.table_mounts.setItem(
                row, 0,
                QTableWidgetItem(
                    app.mountsFaker.driveIndexToLetter(row) + "\\TDDOWNLOAD"))
            self.table_mounts.setItem(row, 1, QTableWidgetItem(selected))
            self.table_mounts.setItem(row, 2, QTableWidgetItem("新近添加"))

    @pyqtSlot()
    def slotRemoveMount(self):
        row = self.table_mounts.currentRow()
        self.table_mounts.removeRow(row)

    @pyqtSlot()
    def accept(self):
        app.settings.set("account", "username",
                         self.lineEdit_loginUsername.text())
        app.settings.set("account", "password",
                         self.lineEdit_loginPassword.text())
        app.settings.setbool("account", "autologin",
                             self.checkBox_autoLogin.isChecked())

        app.autoStart = self.checkBox_autoStartFrontend.isChecked()

        app.xwaredpy.managedBySystemd = self.radio_managedBySystemd.isChecked()
        app.xwaredpy.managedByUpstart = self.radio_managedByUpstart.isChecked()
        app.xwaredpy.managedByAutostart = self.radio_managedByAutostart.isChecked(
        )

        app.settings.setbool("frontend", "enabledeveloperstools",
                             self.checkBox_enableDevelopersTools.isChecked())
        app.settings.setbool("frontend", "allowflash",
                             self.checkBox_allowFlash.isChecked())
        app.settings.setbool("frontend", "minimizetosystray",
                             self.checkBox_minimizeToSystray.isChecked())

        # A possible Qt bug
        # https://bugreports.qt-project.org/browse/QTBUG-37695
        app.settings.setbool("frontend", "closetominimize",
                             self.checkBox_closeToMinimize.isChecked())
        app.settings.setbool("frontend", "popnotifications",
                             self.checkBox_popNotifications.isChecked())
        app.settings.setbool("frontend", "notifybysound",
                             self.checkBox_notifyBySound.isChecked())

        app.settings.setbool("frontend", "showmonitorwindow",
                             self.checkBox_showMonitorWindow.isChecked())
        app.settings.setint("frontend", "monitorfullspeed",
                            self.spinBox_monitorFullSpeed.value())
        app.settings.setbool("frontend", "watchclipboard",
                             self.checkBox_watchClipboard.isChecked())
        app.settings.set("frontend", "watchpattern",
                         self.plaintext_watchPattern.toPlainText())

        if self.group_etmStartWhen.isEnabled():
            startEtmWhen = self.btngrp_etmStartWhen.id(
                self.btngrp_etmStartWhen.checkedButton())
            try:
                app.xwaredpy.startEtmWhen = startEtmWhen
            except InvalidSocket:
                QMessageBox.warning(
                    None, "Xware Desktop",
                    "选项未能成功设置:{}。".format(self.group_etmStartWhen.title()),
                    QMessageBox.Ok, QMessageBox.Ok)

        app.settings.save()

        app.mountsFaker.mounts = self.newMounts
        app.settings.applySettings.emit()
        super().accept()

    @property
    def newMounts(self):
        return list(
            map(lambda row: self.table_mounts.item(row, 1).text(),
                range(self.table_mounts.rowCount())))

    @pyqtSlot()
    def setupETM(self):
        # fill values
        lcPort = app.xwaredpy.lcPort
        self.lineEdit_lcport.setText(str(lcPort) if lcPort else "不可用")

        etmSettings = app.etmpy.getSettings()
        if etmSettings:
            self.spinBox_dSpeedLimit.setValue(etmSettings.dLimit)
            self.spinBox_uSpeedLimit.setValue(etmSettings.uLimit)
            self.spinBox_maxRunningTasksNum.setValue(
                etmSettings.maxRunningTasksNum)

            # connect signals
            self.accepted.connect(self.saveETM)
        else:
            self.spinBox_dSpeedLimit.setEnabled(False)
            self.spinBox_uSpeedLimit.setEnabled(False)
            self.spinBox_maxRunningTasksNum.setEnabled(False)

    @pyqtSlot()
    def saveETM(self):
        newsettings = EtmSetting(
            dLimit=self.spinBox_dSpeedLimit.value(),
            uLimit=self.spinBox_uSpeedLimit.value(),
            maxRunningTasksNum=self.spinBox_maxRunningTasksNum.value())

        app.etmpy.saveSettings(newsettings)
class WeatherInput(QWidget):
    """
    Weather parameter input for GUI. Contains selector on whether to scrape, import, or ignore with corresponding
    windows for each based on current selection e.g. parameter input fields if scraping.
    """

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

        self.__init_weather()
        self.__init_design()

    def __init_weather(self):
        self.layout = QVBoxLayout()

        self.__scrape()
        self.__import()
        self.__none()
        self.__revolver()
        self.__selector()

        self.layout.addWidget(self.selector)
        self.layout.addWidget(self.revolver)

        self.layout.addWidget(QLabel("Powered by the <a href=\"https://www.weatherbit.io/\">Weatherbit API</a>"))

        self.setLayout(self.layout)

    def __scrape(self):
        input_fields = [("City", "text"), ("State", "text"), ("Country", "text"), ("Days", "text"),
                        ("weatherbit.io Key", "text")]
        input_defaults = {"City": "Cambridge", "State": "MA", "Country": "US", "Days": "14"}
        self.scrape_layout, self.scrape_fields = basic_form_creator(input_fields, input_defaults)

        # adding "Imperial Units" and "Save Weather" options as checkboxes in same row.
        imperial = QCheckBox("Imperial Units")
        imperial.setChecked(True)  # default is checked
        save = QCheckBox("Save")
        self.scrape_fields["Imperial Units"] = imperial
        self.scrape_fields["Save Weather"] = save

        self.checkbox_layout = QHBoxLayout()
        self.checkbox_layout.addWidget(imperial)
        self.checkbox_layout.addWidget(save)
        self.checkbox_layout.addStretch()

        checkbox = QWidget()
        checkbox.setLayout(self.checkbox_layout)
        self.scrape_layout.addWidget(checkbox)

        self.scrape = QWidget(self)
        self.scrape.setLayout(self.scrape_layout)

    def __import(self):
        self.import_layout = QVBoxLayout()

        button = QPushButton("Browse")

        self.import_path = QPlainTextEdit()
        font_height = self.import_path.fontMetrics().height()
        num_rows = 5  # size of browse window, plenty of space to display full path
        self.import_path.setFixedHeight(int(num_rows * font_height))

        self.import_layout.addWidget(button, 0, Qt.AlignTop | Qt.AlignLeft)  # align top-left corner
        self.import_layout.addWidget(self.import_path, 0, Qt.AlignTop | Qt.AlignLeft)

        button.clicked.connect(lambda: self.import_path.setPlainText(QFileDialog.getOpenFileName()[0]))

        self.import_ = QWidget(self)
        self.import_.setLayout(self.import_layout)

    def __selector(self):
        self.selector_layout = QHBoxLayout()
        self.selector_button_group = QButtonGroup()
        self.selector_button_group.setExclusive(True)

        self.none_button = QRadioButton("None")
        self.scrape_button = QRadioButton("Scrape")
        self.import_button = QRadioButton("Import")

        self.selector_button_group.addButton(self.none_button, 1)
        self.selector_button_group.addButton(self.scrape_button, 2)  # need 1-index because 0 means not found
        self.selector_button_group.addButton(self.import_button, 3)
        self.selector_layout.addWidget(self.none_button)
        self.selector_layout.addWidget(self.scrape_button)
        self.selector_layout.addWidget(self.import_button)
        self.selector_layout.addStretch()
        self.scrape_button.setChecked(True)

        self.selector = QWidget(self)
        self.selector.setLayout(self.selector_layout)

    def __none(self):
        self.none_ = QWidget()

    def __revolver(self):
        self.revolver = QStackedWidget()
        self.revolver.addWidget(self.none_)
        self.revolver.addWidget(self.scrape)
        self.revolver.addWidget(self.import_)
        self.revolver.setCurrentIndex(1)  # default setting is scrape

    def switch_window(self, button):
        """
        Switch input fields based on current selection.
        :param button: radio button of current selection
        :return: nothing, mutates object
        """
        self.revolver.setCurrentIndex(self.selector_button_group.id(button) - 1)  # make up for 1-index

    def __init_design(self):
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        self.scrape_layout.setContentsMargins(0, 3, 11, 0)  # effort to line up to TwilightInput
        self.scrape_layout.setSpacing(5)
        self.import_layout.setSpacing(10)
        self.import_layout.addStretch(1)
        self.selector_layout.setContentsMargins(0, 0, 0, 11)
        self.checkbox_layout.setContentsMargins(0, 0, 0, 0)
        self.scrape_layout.addStretch(25)  # stretch large enough to move checkboxes close to other fields

        self.default_border = self.scrape_fields["City"].styleSheet()  # just get from any existing line edit
        self.error_border = "border: 1px solid red;"
Beispiel #19
0
class AddVoiceFilesWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.layout = QVBoxLayout()

        self.settings = QSettings("voice_file_settings", "GP_IVR_Settings")

        self.error = False

        self.browse_button_group = QButtonGroup(self)

        self.setup_heading()

        self.voiceflow_settings = QSettings("simplified_voiceflow",
                                            "GP_IVR_Settings")
        self.voice_files = {}
        self.node_ids = []
        self.setup_voice_files_form()
        self.init_settings()

        self.setup_buttons()

        self.setLayout(self.layout)

    def setup_heading(self):
        heading_font = QFont('Arial', 12)
        heading_font.setBold(True)

        rules_font = QFont('Arial', 10)
        rules_font.setItalic(True)

        self.layout.addWidget(QLabel())
        heading = QLabel("Add Recorded Voice Files to IVR:")
        heading.setFont(heading_font)

        page_info = QLabel(
            "You can add personal recorded voice files in place of the automatically\n generated voice files for each "
            "question in the IVR.")

        file_type_rule = QLabel("* WAV Files Only")
        file_type_rule.setFont(rules_font)

        self.layout.addWidget(heading)
        self.layout.addWidget(page_info)
        self.layout.addWidget(file_type_rule)

    def setup_buttons(self):
        button_layout = QHBoxLayout()

        back_button_creator = BackButton()
        self.back_button = back_button_creator.create_back_button()
        button_layout.addWidget(self.back_button)

        self.apply_settings_button = QPushButton("Apply")
        self.apply_settings_button.setToolTip(
            "Replace IVR voice files with updated files")
        button_layout.addWidget(self.apply_settings_button)

        self.layout.addWidget(QLabel())
        self.layout.addLayout(button_layout)

    def init_settings(self):
        for node in self.voice_files:
            node_value = self.settings.value(node)
            if node_value:
                self.voice_files[node].setText(node_value)

    def setup_voice_files_form(self):
        voiceflow_settings = GetVoiceflowSettings(
            self.voiceflow_settings.value("simplified json"))
        ivr_texts = voiceflow_settings.get_ivr_texts()

        if ivr_texts == -1:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Error\n\nYou have not set up an IVR")
            msg.setWindowTitle("Error")
            msg.exec_()
            return

        for node in ivr_texts:
            self.add_voice_file_input(ivr_texts[node], node)

    def add_voice_file_input(self, ivr_text, ivr_node):
        ivr_text = QLabel(ivr_text)
        ivr_text.setWordWrap(True)
        voice_file = WavFileEdit(self)

        self.button_group = QGroupBox()
        self.layout.addWidget(self.button_group)
        self.v_box = QHBoxLayout()
        self.button_group.setLayout(self.v_box)
        browse_files_button = QPushButton("Browse", self)
        browse_files_button.setToolTip("Browse file manager for WAV file")

        self.v_box.addWidget(ivr_text)
        grow_label = QLabel()
        self.v_box.addWidget(grow_label)
        grow_label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        self.v_box.addWidget(voice_file)
        self.v_box.addWidget(browse_files_button)

        self.voice_files[ivr_node] = voice_file
        self.browse_button_group.addButton(browse_files_button)
        self.node_ids.append(ivr_node)

    def get_files(self, voice_file_edit):
        filepath = QFileDialog.getOpenFileName(self, 'Single File', "~",
                                               '*.wav')
        voice_file_edit.setText(filepath[0])

    def apply_settings(self):
        self.save_settings()
        voice_file_paths = []
        node_ids = []

        for node in self.voice_files:

            voice_file_path_text = self.voice_files[node].text()
            voice_file_path = Path(voice_file_path_text)

            if not voice_file_path.is_file():
                if not voice_file_path_text:
                    continue
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Critical)
                msg.setText("Error\n\nThe Path Specified is not a File")
                msg.setWindowTitle("Error")
                msg.exec_()
                self.error = True
                return

            node_ids.append(node)
            voice_file_paths.append(self.voice_files[node].text())
        if voice_file_paths:
            modify_voice_files = ModifyVoiceFiles(
                asterisk_constants.VOICE_FILE_PATH, node_ids, voice_file_paths)
            modify_voice_files.replace_asterisk_voice_files()

    def save_settings(self):
        self.settings.clear()
        for node in self.voice_files:
            if self.voice_files[node].text():
                self.settings.setValue(node, self.voice_files[node].text())

    def browse_files(self, button):
        voice_file_index = -2 - self.browse_button_group.id(button)
        self.get_files(self.voice_files[self.node_ids[voice_file_index]])
Beispiel #20
0
class ToolBar(QWidget):
    mouseEntered = pyqtSignal()
    mouseLeft = pyqtSignal()

    toolChanged = pyqtSignal(str)
    primaryInkChanged = pyqtSignal(str)
    secondaryInkChanged = pyqtSignal(str)

    def __init__(self):

        super(ToolBar, self).__init__()

        self.setAttribute(Qt.WA_StaticContents)
        self.setAttribute(Qt.WA_NoSystemBackground)

        self.setFont(ResourcesCache.get("BigFont"))

        self._registeredTools = {}
        self._registeredInks = {}

        self._toolSlots = []
        self._inkSlots = []

        self._currentActiveToolSlot = None
        self._previousActiveToolSlot = None

        self._currentEditedInkSlot = None
        self._previousEditedInkSlot = None

        self._editMode = False

        self._backgroundColor = QColor(40, 40, 40)
        self._toolLabelColor = QColor(112, 231, 255)

        self._layout = QVBoxLayout()
        self._layout.setAlignment(Qt.AlignTop)
        self._layout.setContentsMargins(4, 4, 4, 4)

        top_layout = QHBoxLayout()

        self._layout.addLayout(top_layout)

        self._toolsLayout = QHBoxLayout()
        self._inksLayout = QHBoxLayout()

        self._toolsLayout.setContentsMargins(0, 0, 0, 0)
        self._toolsLayout.setAlignment(Qt.AlignLeft)

        self._inksLayout.setContentsMargins(0, 0, 0, 0)
        self._inksLayout.setAlignment(Qt.AlignRight)

        top_layout.addLayout(self._toolsLayout)
        top_layout.addLayout(self._inksLayout)

        self._toolsButtonGroup = QButtonGroup()
        self._toolsButtonGroup.buttonClicked.connect(
            self._on_tool_slot_triggered)

        self._inksButtonGroup = QButtonGroup()
        self._inksButtonGroup.setExclusive(False)
        self._inksButtonGroup.buttonClicked.connect(
            self._on_ink_slot_triggered)

        self.setLayout(self._layout)

        self._toolbarSubPanel = None
        self._toolsListWidget = None
        self._toolsOptionsPanel = None

        self._init_edit_panel()

        self._add_ink_slot(0)
        self._add_ink_slot(1)

        self.resize(0, 50)

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

    def get_tool_by_name(self, name):

        return self._registeredTools[name]

    def register_tool(self, tool, is_default=None):

        if tool.name not in self._registeredTools:

            self._registeredTools[tool.name] = tool
            self._toolsListWidget.addItem(tool.name)

            if is_default is True:
                self._toolsListWidget.setCurrentRow(0)

            self._build_tool_options_pane(tool)

            if len(self._toolSlots) < 4:
                slot_index = self._add_tool_slot(is_default)
                self._assign_tool_to_slot(tool, slot_index)

    def register_ink(self, ink, slot):

        if not ink.name in self._registeredInks:
            self._registeredInks[ink.name] = ink

            self._inksListWidget.addItem(ink.name)

            self._build_ink_options_pane(ink)

            if self._inkSlots[slot]['id'] is None:
                self._assign_ink_to_slot(ink, slot)

    def switch_tool_slot(self, slot):

        self._previousActiveToolSlot = self._currentActiveToolSlot

        self._currentActiveToolSlot = slot

        if self._currentActiveToolSlot == self._previousActiveToolSlot:
            return

        tool_name = self._toolSlots[slot]['id']

        self._toolSlots[slot]['button'].setChecked(True)

        self.toolChanged.emit(tool_name)

        self._select_tool_on_list(tool_name)

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

    def _go_back_to_last_tool(self):
        self.switch_tool_slot(self._previousActiveToolSlot)

    def _add_tool_slot(self, selected=None):

        slot_button = QPushButton()
        slot_button.setCheckable(True)

        index = len(self._toolSlots)

        if selected is not None and selected is True:
            slot_button.setChecked(True)

        slot = {'id': None, 'button': slot_button}

        if selected:
            self._currentActiveToolSlot = index

        self._toolSlots.append(slot)

        self._toolsButtonGroup.addButton(slot_button, index)

        self._toolsLayout.addWidget(slot_button)

        return index

    def _add_ink_slot(self, slot_number):

        slot_button = QPushButton()
        slot_button.setFont(self.font())
        slot_button.setStyleSheet(
            "border-color: rgb(56,56,56); background-color: rgb(17,17,"
            "17); font-size: 12pt;")

        index = len(self._inkSlots)

        if slot_number == 0:

            icon = QIcon()
            icon.addPixmap(QPixmap(":/icons/ico_mouse_button1"), QIcon.Normal,
                           QIcon.Off)

            slot_button.setIcon(icon)
            slot_button.setIconSize(QSize(18, 23))

        elif slot_number == 1:

            icon = QIcon()
            icon.addPixmap(QPixmap(":/icons/ico_mouse_button2"), QIcon.Normal,
                           QIcon.Off)

            slot_button.setIcon(icon)
            slot_button.setIconSize(QSize(18, 23))

        slot = {'id': None, 'button': slot_button}

        self._inkSlots.append(slot)

        self._inksButtonGroup.addButton(slot_button)

        self._inksButtonGroup.setId(slot_button, index)

        self._inksLayout.addWidget(slot_button)

        return index

    def _assign_tool_to_slot(self, tool, slot):

        if slot < 0 or slot > len(self._toolSlots) - 1:
            raise Exception(
                '[ToolBar] > _assignToolToSlot : invalid slot parameter')

        self._toolSlots[slot]['id'] = tool.name

        icon = tool.icon

        if icon is not None:
            tool_button = self._toolSlots[slot]['button']
            tool_button.setIcon(tool.icon)
            tool_button.setIconSize(QSize(24, 24))

    def _assign_ink_to_slot(self, ink, slot):

        if slot != 0 and slot != 1:
            raise Exception(
                '[ToolBar] > _assignInkToSlot : invalid slot parameter')

        ink_name = ink.name

        self._inkSlots[slot]['id'] = ink_name
        self._inkSlots[slot]['button'].setText(ink_name)

        if slot == 0:
            self.primaryInkChanged.emit(ink_name)
        elif slot == 1:
            self.secondaryInkChanged.emit(ink_name)

    def _init_edit_panel(self):

        self._toolbarSubPanel = QStackedWidget()

        # 1. Initialize Tools Control Panel -----------------------------------

        self._toolsListWidget = QListWidget()

        self._toolsListWidget.currentRowChanged.connect(
            lambda v: self._toolsOptionsPanel.setCurrentIndex(v))

        self._toolsListWidget.setMaximumSize(QSize(150, 200))

        self._toolsListWidget.itemClicked.connect(
            self._on_tool_list_item_clicked)

        # Tools Subpanel ------------------------------------------------------

        tools_control_panel = QWidget()

        tools_control_panel_layout = QHBoxLayout()

        tools_control_panel.setLayout(tools_control_panel_layout)

        tools_control_panel_layout.setAlignment(Qt.AlignLeft)

        # Tools List ----------------------------------------------------------

        tools_list_sublayout = QVBoxLayout()

        tools_list_sublayout.setAlignment(Qt.AlignTop)

        tools_list_sublayout.setContentsMargins(0, 0, 0, 0)

        tools_list_sublayout.addWidget(QLabel("Tools"))

        tools_list_sublayout.addWidget(self._toolsListWidget)

        tools_control_panel_layout.addLayout(tools_list_sublayout)

        # Tools Options -------------------------------------------------------

        tools_options_sublayout = QVBoxLayout()

        tools_options_sublayout.setAlignment(Qt.AlignTop)

        tools_control_panel_layout.addLayout(tools_options_sublayout)

        self._toolsOptionsPanel = QStackedWidget()

        tools_options_sublayout.addWidget(QLabel("Tools Options"))

        tools_options_sublayout.addWidget(self._toolsOptionsPanel)

        self._toolbarSubPanel.addWidget(tools_control_panel)

        # 2. Initialize Inks Control Panel ------------------------------------

        self._inksListWidget = QListWidget()

        self._inksListWidget.currentRowChanged.connect(
            lambda v: self._inksOptionsPanel.setCurrentIndex(v))

        self._inksListWidget.setMaximumSize(QSize(150, 200))

        self._inksListWidget.itemClicked.connect(
            self._on_ink_list_item_clicked)

        # Inks Subpanel -------------------------------------------------------

        inks_control_panel = QWidget()

        inks_control_panel_layout = QHBoxLayout()

        inks_control_panel.setLayout(inks_control_panel_layout)

        inks_control_panel_layout.setAlignment(Qt.AlignLeft)

        # Inks List -----------------------------------------------------------

        inks_list_sublayout = QVBoxLayout()

        inks_list_sublayout.setAlignment(Qt.AlignTop)

        inks_list_sublayout.setContentsMargins(0, 0, 0, 0)

        inks_list_sublayout.addWidget(QLabel("Inks"))

        inks_list_sublayout.addWidget(self._inksListWidget)

        inks_control_panel_layout.addLayout(inks_list_sublayout)

        # Inks Options --------------------------------------------------------

        inks_options_sublayout = QVBoxLayout()

        inks_options_sublayout.setAlignment(Qt.AlignTop)

        inks_control_panel_layout.addLayout(inks_options_sublayout)

        self._inksOptionsPanel = QStackedWidget()

        inks_options_sublayout.addWidget(QLabel("Ink Options"))

        inks_options_sublayout.addWidget(self._inksOptionsPanel)

        self._toolbarSubPanel.addWidget(inks_control_panel)

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

        self._layout.addWidget(self._toolbarSubPanel)

        self._toolbarSubPanel.setVisible(False)

    def _build_tool_options_pane(self, tool):

        pane = QWidget()

        pane_layout = QVBoxLayout()
        pane_layout.setAlignment(Qt.AlignTop)
        pane.setLayout(pane_layout)

        for prop in tool.properties.values():
            field_layout = QHBoxLayout()

            field_layout.addWidget(QLabel(prop.description))

            prop_widget = prop.build_property_widget()

            field_layout.addWidget(prop_widget)

            pane_layout.addLayout(field_layout)

        self._toolsOptionsPanel.addWidget(pane)

    def _build_ink_options_pane(self, ink):

        pane = QWidget()

        pane_layout = QVBoxLayout()
        pane_layout.setAlignment(Qt.AlignTop)
        pane.setLayout(pane_layout)

        for prop in ink.properties.values():
            field_layout = QHBoxLayout()
            field_layout.addWidget(QLabel(prop.description))

            prop_widget = prop.build_property_widget()

            field_layout.addWidget(prop_widget)

            pane_layout.addLayout(field_layout)

        self._inksOptionsPanel.addWidget(pane)

    def _select_tool_on_list(self, tool_name):

        tool_list_item = \
            self._toolsListWidget.findItems(tool_name, Qt.MatchExactly)[0]

        if tool_list_item is not None:
            self._toolsListWidget.setCurrentItem(tool_list_item)

    def _select_ink_on_list(self, ink_name):

        ink_list_item = \
            self._inksListWidget.findItems(ink_name, Qt.MatchExactly)[0]

        if ink_list_item is not None:
            self._inksListWidget.setCurrentItem(ink_list_item)

    def _toggle_edit_mode(self):

        if not self._editMode:

            self._show_sub_panel()

        else:

            self._hide_sub_panel()

        self.update()

    def _show_sub_panel(self):

        self._editMode = True
        self.resize(self.width(), 300)
        self._toolbarSubPanel.setVisible(True)

    def _hide_sub_panel(self):

        self._editMode = False
        self.resize(self.width(), 50)
        self._toolbarSubPanel.setVisible(False)

        self._finish_ink_edit_mode()

    def _finish_ink_edit_mode(self):

        if self._currentEditedInkSlot is not None:
            self._inksButtonGroup.button(self._currentEditedInkSlot). \
                setStyleSheet("border-color: rgb(56,56,56);")
            self._currentEditedInkSlot = None
            self._previousEditedInkSlot = None
            self._inksListWidget.setCurrentRow(0)
            self._toolbarSubPanel.setCurrentIndex(0)

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

    def mousePressEvent(self, e):

        self._toggle_edit_mode()

        e.accept()

    def wheelEvent(self, e):

        e.accept()

    def enterEvent(self, e):

        self.mouseEntered.emit()
        self.setCursor(Qt.PointingHandCursor)

    def leaveEvent(self, e):

        self.mouseLeft.emit()

    def _on_tool_slot_triggered(self):

        self._toolbarSubPanel.setCurrentIndex(0)

        triggered_slot = self._toolsButtonGroup.checkedId()

        if self._currentEditedInkSlot is not None:
            self._finish_ink_edit_mode()

        self.switch_tool_slot(triggered_slot)

        self.update()

    def _on_ink_slot_triggered(self, slot_button):

        if not self._editMode:
            self._show_sub_panel()

        triggered_slot_id = self._inksButtonGroup.id(slot_button)

        if triggered_slot_id != self._currentEditedInkSlot:

            self._previousEditedInkSlot = self._currentEditedInkSlot

            self._currentEditedInkSlot = triggered_slot_id

            if self._previousEditedInkSlot is not None:
                self._inksButtonGroup. \
                    button(self._previousEditedInkSlot). \
                    setStyleSheet("border-color: rgb(56,56,56);")

            slot_button.setStyleSheet("border-color: rgb(255,0,0);")

            self._toolbarSubPanel.setCurrentIndex(1)

            ink_name = self._inkSlots[triggered_slot_id]['id']

            self._select_ink_on_list(ink_name)

            if triggered_slot_id == 0:
                self.primaryInkChanged.emit(ink_name)
            elif triggered_slot_id == 1:
                self.secondaryInkChanged.emit(ink_name)

        else:

            self._hide_sub_panel()

    def _on_tool_list_item_clicked(self, new_item):

        new_item_name = new_item.text()
        self._assign_tool_to_slot(self.get_tool_by_name(new_item_name),
                                  self._currentActiveToolSlot)
        self.toolChanged.emit(new_item_name)
        self._toolbarSubPanel.update()

    def _on_ink_list_item_clicked(self, item):

        item_name = item.text()

        ink = self._registeredInks[item_name]

        if ink is not None:
            self._assign_ink_to_slot(ink, self._currentEditedInkSlot)
class VistaListaPrenotazioni(
        QWidget):  # Apre la vista che visualizza la lista delle prenotazioni.
    def __init__(self, tipo):
        super(VistaListaPrenotazioni, self).__init__()
        self.tipo = tipo
        self.controller = ControllerListaPrenotazioni()

        # Inserisce in 'lista_prenotazioni' le informazioni della 'lista_prenotazioni.pickle'.
        # Se la lista è vuota l'utente è notificato con un messaggio di errore

        self.stylesheet_label = """
                QLabel{
                    background-color: grey;
                    border: 1px solid #dfdfdf;
                }
            """

        self.stylesheet_window = """
                QWidget{
                    background-color: #dfdfdf
                }
            """

        self.stylesheet_button_back = """
                QPushButton{
                    border-radius: 15px;
                    background-color: transparent;
                }

                QPushButton::Pressed{
                    background-color: transparent;
                }        
            """

        self.stylesheet_button = """
                QPushButton{
                    background-color: #cc3234;
                    color: white;
                    border-radius: 15px;
                }

                QPushButton::Pressed{
                    background-color: grey;
                }        
            """

        self.stylesheet_table = """
                QTableWidget{
                    background-color: white;
                }
            """

        self.stylesheet_pagamento = """
                QPushButton{
                    background-color: transparent;
                    border-color: transparent;
                }

                QPushButton::Pressed{
                    background-color: grey;
                }
            """

        # Inserimento e impostazioni grafiche dell'immagine dello sfondo della finestra.
        self.imagePath = "Image/foto.png"
        self.image = QImage(self.imagePath)
        self.label = QLabel(self)
        self.label.setPixmap(QPixmap.fromImage(self.image))
        self.label.setScaledContents(True)
        self.label.setGeometry(0, 0, 970, 750)

        # Inserimento della tabella e intestazione delle colonne.
        self.table = QTableWidget(self)
        self.table.setColumnCount(4)
        self.table.setRowCount(1)
        self.table.setItem(0, 0, QTableWidgetItem("ID"))
        self.table.setItem(0, 1, QTableWidgetItem("Tipo"))
        self.table.setItem(0, 2, QTableWidgetItem("Data"))
        self.table.setItem(0, 3, QTableWidgetItem("Elimina"))

        self.set_data(
        )  # Inserisce nella tabella i dati contenuti nella lista_prenotazioni.

        # Impostazioni grafiche della tabella.
        self.table.setGeometry(50, 30, 870, 550)
        self.table.setColumnWidth(0, 100)
        self.table.setColumnWidth(1, 350)
        self.table.setColumnWidth(2, 350)
        self.table.setColumnWidth(3, 70)
        self.table.setStyleSheet(self.stylesheet_table)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().hide()
        self.table.horizontalScrollBar().setDisabled(True)
        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table.verticalHeader().hide()
        self.table.setEditTriggers(self.table.NoEditTriggers)
        self.table.setSelectionMode(self.table.NoSelection)
        self.table.setFocusPolicy(Qt.NoFocus)

        # Inserimento e impostazioni grafiche del bottone per tornare alla vista precedente.
        self.button_back = QPushButton(self)
        self.button_back.setIcon(QIcon('Image/back.png'))
        self.button_back.setIconSize(QSize(90, 90))
        self.button_back.setGeometry(50, 600, 90, 90)
        self.button_back.setStyleSheet(self.stylesheet_button_back)
        self.button_back.clicked.connect(self.go_back)

        # Inserimento e impostazioni grafiche del bottone che consente di aggiungere un orario per
        # le prenotazioni.
        self.button_new_prenotazione = QPushButton(self)
        self.button_new_prenotazione.setText("Aggiungi orari")
        self.font_button = QFont("Times", 11)
        self.button_new_prenotazione.setFont(self.font_button)
        self.button_new_prenotazione.setGeometry(780, 620, 140, 50)
        self.button_new_prenotazione.setStyleSheet(self.stylesheet_button)
        self.button_new_prenotazione.clicked.connect(self.go_aggiungi_orari)

        # Impostazioni grafiche generali della finestra del programma.
        self.setWindowTitle("Lista Prenotazioni")
        self.resize(970, 700)
        self.setFixedSize(self.size())
        self.setStyleSheet(self.stylesheet_window)

    # == set_data ==
    # La funzione si occupa di salvare le informazioni relative alla prenotazione e contenute nel file
    # 'lista_prenotazioni.pickle' nella tabella della VistaListaPrenotazioni.
    def set_data(self):
        self.button_group_elimina = QButtonGroup()
        self.cancella_icon = QIcon("Image/delete.png")
        i = 1
        n_righe = len(self.controller.get_lista_prenotazioni())
        self.table.setRowCount(n_righe + 1)
        self.button_group_elimina.buttonClicked.connect(
            self.on_selection_elimina)
        for prenotazione in self.controller.get_lista_prenotazioni():
            self.controller_prenotazione = ControllerPrenotazione(prenotazione)
            self.table.setItem(
                i, 0, QTableWidgetItem(self.controller_prenotazione.get_id()))
            self.table.setItem(
                i, 1,
                QTableWidgetItem(self.controller_prenotazione.get_tipo()))
            self.table.setItem(
                i, 2,
                QTableWidgetItem(self.controller_prenotazione.get_data()))
            if i % 2 != 0:
                for j in range(0, 3):
                    self.table.item(i, j).setBackground(QColor(224, 224, 224))
            self.delete = QPushButton()
            self.delete.setIcon(self.cancella_icon)
            self.delete.setIconSize(QSize(35, 35))
            self.delete.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_elimina.addButton(self.delete, i)
            self.table.setCellWidget(i, 3, self.delete)
            i = i + 1

    # == go_back ==
    # La funzione si occupa di aprire la finestra precedente.
    def go_back(self):
        self.go_prenotazioni = VistaHomeIstruttore.VistaHomeIstruttore(
            self.tipo)
        self.go_prenotazioni.show()
        self.close()

    # == go_aggiungi_orari ==
    # La funzione si occupa di aprire la VistaAggiungiOrari.
    def go_aggiungi_orari(self):
        self.aggiungi_orari = VistaAggiungiOrari(self.tipo)
        self.aggiungi_orari.show()
        self.close()

    def go_elimina(self, i):
        conferma = QMessageBox.question(
            self, "Attenzione", "Sei sicuro di voler eliminare questo orario?",
            QMessageBox.No, QMessageBox.Yes)
        if conferma == QMessageBox.Yes:
            self.controller.rimuovi_prenotazione_by_index(i - 1)
            self.refresh()
        else:
            return

    def refresh(self):
        self.go_lista = VistaListaPrenotazioni(self.tipo)
        self.go_lista.show()
        self.close()

    def on_selection_elimina(self, selected):
        self.go_elimina(self.button_group_elimina.id(selected))
Beispiel #22
0
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        self.path = os.path.join(os.getcwd(),
                                 "Projects")  # Путь к папке с проектами
        self.projects = os.listdir(self.path)  # Проекты
        self.current_project = ""  # Имя проекта
        self.current_test = ""  # Имя испытания
        self.data = pd.DataFrame()  # Data from excel
        self.x = []  # Data for x
        self.x_name = ""  # Имя столбца по оси X
        self.y = []  # Chosen columns
        self.type_flag = False  # Необходимо для проверки данных на соответствие типу данных (число)
        self.table_ready = False
        self.file_path = ""  # Отвечает за путь к .xlsx файлу
        self.additional_data_flag = False  # Флаг, обозначающий, что данные нужно дополнить
        self.x_min = 0  # Нижняя граница дополнения
        self.x_max = 0  # Верхняя граница дополнения
        self.changed_flag = False
        self.y_filtered = {}  # Фильтрованные данные (y)
        self.incorrect_data = {}  # Данные с ошибками
        self.many_cells = False  # Флаг для метода изменения значений в нескольких ячейках
        self.is_loading = False  # Флаг текущей загрузки

        self.setWindowTitle("Excel to data")
        self.central_widget = QWidget(self)  # Создаём центральный виджет
        self.setCentralWidget(self.central_widget)

        # Создаём все расположения
        main_layout = QHBoxLayout()  # Главное
        left_layout = QVBoxLayout(
        )  # Для проектов, испытаний и вывода данных и .data
        self.project_layout = QVBoxLayout()  # Для проектов
        self.tests_layout = QVBoxLayout()  # Для испытаний
        data_layout = QHBoxLayout()  # Для представления данных
        graph_layout = QVBoxLayout()  # Для графиков

        # Часть для окна с данными
        self.table = QTableWidget(self)  # Пустая таблица
        self.table.setMinimumWidth(
            int(QApplication.desktop().availableGeometry().width() * 0.3))
        self.table.cellChanged.connect(
            self.change_cell)  # Возможность редактирования данных

        # Часть для графиков
        pg.setConfigOption('foreground', pg.mkColor("000000"))
        # Создаём поле для графика
        self.originalGraphWidget = pg.PlotWidget()
        self.originalGraphWidget.setBackground('w')
        self.originalGraphWidget.setTitle("Исходные данные")
        self.originalGraphWidget.setLabel('left', 'Values')
        self.originalGraphWidget.setLabel('bottom', 'X')
        self.originalGraphWidget.showGrid(x=True, y=True)
        self.originalGraphWidget.addLegend()  # Описание: цвет - график

        # Создаём поле для изменённого графика
        self.changedGraphWidget = pg.PlotWidget()
        self.changedGraphWidget.setBackground('w')
        self.changedGraphWidget.setTitle("Изменённые данные")
        self.changedGraphWidget.setLabel('left', 'Values')
        self.changedGraphWidget.setLabel('bottom', 'X')
        self.changedGraphWidget.showGrid(x=True, y=True)
        self.changedGraphWidget.addLegend()

        self.original_plt = []
        self.changed_plt = []

        # Часть для вывода
        self.out_text = QTextEdit()
        self.out_text.setMaximumHeight(
            int(QApplication.desktop().availableGeometry().height() * 0.3))
        self.out_text.setReadOnly(True)

        # Второй поток
        self.threadclass = thread.ThreadClass(self)
        self.threadclass.finishSignal.connect(self.finishSignal_process)

        data_layout.addLayout(self.project_layout)
        data_layout.addLayout(self.tests_layout)
        data_layout.addWidget(self.table)
        left_layout.addLayout(data_layout)
        left_layout.addWidget(self.out_text)
        graph_layout.addWidget(self.originalGraphWidget)
        graph_layout.addWidget(self.changedGraphWidget)
        main_layout.addLayout(left_layout)
        main_layout.addLayout(graph_layout)
        self.central_widget.setLayout(main_layout)

        self.create_menuBar()
        self.update_project_layout()
        self.update_tests_layout()

    def create_menuBar(self):
        menuBar = self.menuBar()

        file_menu = menuBar.addMenu("Файл")
        create_menu = file_menu.addMenu("Создать")
        self.project_action = QAction("Проект", self)
        self.project_action.triggered.connect(self.create_project)
        self.test_action = QAction("Данные испытаний", self)
        self.test_action.setEnabled(False)
        self.test_action.triggered.connect(self.add_test)
        create_menu.addAction(self.project_action)
        create_menu.addAction(self.test_action)
        delete_menu = file_menu.addMenu("Удалить")
        self.delete_prj_action = QAction("Проект", self)
        self.delete_prj_action.triggered.connect(self.delete_prj_folder)
        self.delete_test_action = QAction("Данные испытаний", self)
        self.delete_test_action.triggered.connect(self.delete_test_folder)
        delete_menu.addAction(self.delete_prj_action)
        delete_menu.addAction(self.delete_test_action)

        data_menu = menuBar.addMenu("Данные")
        self.conversion_action = QAction("Конвертировать в .data", self)
        self.conversion_action.setEnabled(False)
        self.conversion_action.triggered.connect(self.convert_data)
        self.set_x_action = QAction("Назначить ось абсцисс", self)
        self.set_x_action.setEnabled(False)
        self.set_x_action.triggered.connect(self.set_x)
        self.graph_action = QAction("Построить график", self)
        self.graph_action.setEnabled(False)
        self.graph_action.triggered.connect(self.get_graph)
        self.copy_action = QAction("Копировать данные", self)
        self.copy_action.setEnabled(False)
        self.copy_action.triggered.connect(self.copy_test)
        data_menu.addAction(self.graph_action)
        data_menu.addAction(self.conversion_action)
        data_menu.addAction(self.set_x_action)
        data_menu.addAction(self.copy_action)
        change_menu = data_menu.addMenu("Изменить")
        self.data_action = QAction("Данные в выбранных ячейках", self)
        self.data_action.setEnabled(False)
        self.data_action.triggered.connect(self.change_data_in_chosen_cells)
        self.column_action = QAction("Порядок столбцов", self)
        self.column_action.setEnabled(False)
        self.column_action.triggered.connect(self.enumerate_col)
        change_menu.addAction(self.data_action)
        change_menu.addAction(self.column_action)
        self.delete_action = QAction("Удалить столбцы", self)
        self.delete_action.setEnabled(False)
        self.delete_action.triggered.connect(self.delete_column)
        data_menu.addAction(self.delete_action)

        graph_menu = menuBar.addMenu("График")
        self.filter_action = QAction("Фильтровать", self)
        self.filter_action.setEnabled(False)
        self.filter_action.triggered.connect(self.filter_data)
        self.add_action = QAction("Изменить диапозон Х", self)
        self.add_action.setEnabled(False)
        self.add_action.triggered.connect(self.add_data)
        graph_menu.addAction(self.filter_action)
        graph_menu.addAction(self.add_action)
        save_menu = graph_menu.addMenu("Сохранить")
        self.original_action = QAction("Исходное изображение", self)
        self.original_action.setEnabled(False)
        self.original_action.triggered.connect(
            lambda state, graphWidget=self.originalGraphWidget: self.
            save_graph(graphWidget))
        self.changed_action = QAction("Изменённое изображение", self)
        self.changed_action.setEnabled(False)
        self.changed_action.triggered.connect(
            lambda state, graphWidget=self.changedGraphWidget: self.save_graph(
                graphWidget))
        save_menu.addAction(self.original_action)
        save_menu.addAction(self.changed_action)

    def init_prj_context_menu(self, name):
        self.current_project = name
        context_menu = QMenu(self)
        add_data = QAction("Добавить данные испытаний", self)
        add_data.triggered.connect(self.add_test)
        delete_project = QAction("Удалить проект", self)
        delete_project.triggered.connect(
            lambda state: self.delete_prj_folder(name))
        context_menu.addAction(add_data)
        context_menu.addAction(delete_project)
        context_menu.exec_(QCursor.pos())

    def init_header_context_menu(self, name):
        context_menu = QMenu(self)
        set = QAction("Сделать осью абсцисс", self)
        #set.triggered.connect(lambda state: self.set_x(name))
        context_menu.addAction(set)
        context_menu.exec_(QCursor.pos())

    def set_x(self):
        items = self.data.columns.to_list()
        item, ok = QInputDialog().getItem(self, "Назначение оси абсцисс",
                                          "Выберите:", items, 0, False)
        if ok and item != '':
            self.x_name = item

    def loading_data(self):
        self.out_text.clear()
        self.out_text.setText("Подождите. Идёт загрузка данных...")

    def update_project_layout(self):
        clear_layout(self.project_layout)
        self.projects = os.listdir(self.path)
        if len(self.projects) == 0:
            empty_lbl = QLabel("Нет созданных проектов")
            empty_lbl.setStyleSheet('font-size: 11pt')
            self.project_layout.addWidget(empty_lbl)
        else:
            box = QGroupBox()
            inner_layout = QVBoxLayout()

            project_lbl = QLabel("Проекты:")
            project_lbl.setStyleSheet('font-size: 11pt')
            self.project_layout.addWidget(project_lbl)

            self.buttons = QButtonGroup()
            self.buttons.buttonClicked[int].connect(self.choose_project)
            for folder in range(len(self.projects)):
                button = QPushButton(self.projects[folder], self)
                button.setSizePolicy(QSizePolicy.Expanding,
                                     QSizePolicy.Expanding)
                button.setStyleSheet(
                    'background: transparent; text-align: left; border: none; font-size: 11pt; '
                    'font-weight: 100')
                button.setContextMenuPolicy(Qt.CustomContextMenu)
                button.customContextMenuRequested.connect(
                    lambda state, name=self.projects[
                        folder]: self.init_prj_context_menu(name))
                self.buttons.addButton(button, folder)
                inner_layout.addWidget(button)

            inner_layout.addStretch(1)
            box.setLayout(inner_layout)
            scroll = QScrollArea()
            scroll.setWidget(box)
            scroll.setWidgetResizable(True)
            self.project_layout.addWidget(scroll)

    def update_tests_layout(self):
        clear_layout(self.tests_layout)

        if self.current_project != '':
            folder_path = os.path.join(self.path, self.current_project)
            tests = os.listdir(folder_path)

            # Добавляем кнопки для всех файлов, лежащих в папке
            # Добавляем ScrollArea, чтобы можно было прокручивать вниз, если файлов очень много
            if len(tests) == 0:
                empty_lbl = QLabel("Нет созданных испытаний")
                empty_lbl.setStyleSheet('font-size: 11pt')
                self.tests_layout.addWidget(empty_lbl)
            else:
                test_lbl = QLabel(self.current_project + ':')
                test_lbl.setStyleSheet('font-size: 11pt')
                self.tests_layout.addWidget(test_lbl)
                self.test_buttons = QButtonGroup()
                self.test_buttons.buttonClicked[int].connect(self.test_pushed)
                box = QGroupBox()  # Необходимо для ScrollArea
                inner_layout = QVBoxLayout()
                for test in range(
                        len(tests)):  # Добавляем каждую внутреннюю директорию
                    button = QPushButton(tests[test], self)
                    button.setSizePolicy(QSizePolicy.Expanding,
                                         QSizePolicy.Expanding)
                    button.setStyleSheet(
                        'background: transparent; text-align: left; border: none; font-size: 11pt; '
                        'font-weight: 100')
                    # В обработчик нажатия передаём путь, чтобы определять, что нужно открыть
                    self.test_buttons.addButton(button, test)
                    inner_layout.addWidget(button)
                    inner_files = os.listdir(
                        os.path.join(folder_path, tests[test]))
                    for file in inner_files:  # Добавляем каждый файл из внутренних директорий
                        button = QPushButton('- ' + file)
                        button.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Expanding)
                        button.setStyleSheet(
                            'background: transparent; text-align: left; border: none; font-size: '
                            '9pt; font-weight: 100; margin-left: 20px')
                        # В обработчик нажатия передаём путь, чтобы определять, что нужно открыть
                        button.clicked.connect(
                            lambda state, file_path=os.path.join(
                                folder_path, tests[test], file
                            ): self.file_pushed(file_path))
                        inner_layout.addWidget(button)
                        if os.path.isdir(
                                os.path.join(folder_path, tests[test], file)):
                            data_files = os.listdir(
                                os.path.join(folder_path, tests[test], file))
                            for df in data_files:
                                button = QPushButton('> ' + df)
                                button.setSizePolicy(QSizePolicy.Expanding,
                                                     QSizePolicy.Expanding)
                                button.setStyleSheet(
                                    'background: transparent; text-align: left; border: none; font-size: '
                                    '7pt; font-weight: 100; margin-left: 40px')
                                button.clicked.connect(
                                    lambda state, file_path=os.path.join(
                                        folder_path, tests[test], file, df
                                    ): self.file_pushed(file_path))
                                inner_layout.addWidget(button)

                box.setLayout(inner_layout)
                scroll = QScrollArea()
                scroll.setWidget(box)
                scroll.setWidgetResizable(True)
                self.tests_layout.addWidget(scroll)

    def choose_project(self, id):
        for button in self.buttons.buttons():
            if self.buttons.id(button) == id:
                self.current_project = button.text()
                button.setStyleSheet(
                    'background: transparent; text-align: left; border: none; font-size: 11pt; font-weight: 700; '
                    'color: yellow')
            else:
                button.setStyleSheet(
                    'background: transparent; text-align: left; border: none; font-size: 11pt; font-weight: 100;'
                )
        self.test_action.setEnabled(True)
        self.copy_action.setEnabled(False)
        self.update_tests_layout()

    def test_pushed(self, id):
        self.incorrect_data = dict.fromkeys(self.data.columns, 0)
        for button in self.test_buttons.buttons():
            if self.test_buttons.id(button) == id:
                self.current_test = button.text()
                button.setStyleSheet(
                    'background: transparent; text-align: left; border: none; font-size: 11pt; font-weight: 700; '
                    'color: yellow')
            else:
                button.setStyleSheet(
                    'background: transparent; text-align: left; border: none; font-size: 11pt; font-weight: 100;'
                )
        self.conversion_action.setEnabled(True)
        self.data_action.setEnabled(True)
        self.column_action.setEnabled(True)
        self.copy_action.setEnabled(True)
        self.delete_action.setEnabled(True)
        self.set_x_action.setEnabled(True)

        # Находим файл с таблицей
        xlsx = os.listdir(
            os.path.join(self.path, self.current_project, self.current_test))
        xlsx = [i for i in xlsx if ('.xlsx' in i) and i != 'out.xlsx']
        self.file_path = os.path.join(self.path, self.current_project,
                                      self.current_test, xlsx[0])

        self.loading_data()
        self.threadclass.start()

    def finishSignal_process(self):
        self.create_table()
        if '.data' in self.file_path:
            self.draw_data_graph()

    def copy_test(self):
        item, ok = QInputDialog.getItem(self, "Выбор проекта", "Проект",
                                        tuple(self.projects), 0, False)
        if ok and item:
            cur_path = os.path.join(self.path, self.current_project,
                                    self.current_test)
            new_path = os.path.join(self.path, item,
                                    self.current_test + "-copy")
            try:
                os.mkdir(new_path)
                paths = [
                    i for i in os.listdir(
                        os.path.join(self.path, self.current_project,
                                     self.current_test))
                    if ('.xlsx' in i) or ('.data' in i)
                ]
                for p in paths:
                    shutil.copy(os.path.join(cur_path, p), new_path)
            except FileExistsError:
                QMessageBox.about(self, "Предупреждение",
                                  "Копия уже была создана")

    def create_project(self):
        name, ok = QInputDialog.getText(self, 'Создание проекта',
                                        'Введите название нового проекта:')
        if ok:
            if name in self.projects:
                QMessageBox.about(self, 'Ошибка',
                                  'Проект с таким именем уже существует.')
            else:
                pat = "[\w-]+"  # Шаблон для названия
                if re.sub(pat, "", name, 1) == "":
                    os.mkdir(os.path.join(self.path, name))
                    self.projects.append(name)
                    self.update_project_layout()
                else:
                    QMessageBox.about(
                        self, 'Ошибка',
                        'Название проекта может состоять из букв, цифр, а также знаков '
                        'тире и нижнего подчёркивания.')

    def add_test(self):
        self.aw = aw.AddWindow(self)
        self.aw.show()

    def enumerate_col(self):
        self.cw = cw.ColumnsWindow(self)
        self.cw.show()

    def create_table(self):
        if self.file_path != "":
            self.x_name = self.data.columns[0]
            self.x = list(self.data[self.x_name])
            self.type_flag = False
            self.table_ready = False
            headers = self.data.columns.to_list()

            self.clear_table()
            self.table.setColumnCount(len(headers))
            self.table.setRowCount(len(self.data))
            self.table.setHorizontalHeaderLabels(headers)
            self.incorrect_data = dict.fromkeys(headers, 0)

            for i in range(len(headers)):
                for j in range(len(self.data)):
                    self.table.setItem(
                        j, i, QTableWidgetItem(str(self.data.iloc[j, i])))

            self.table_ready = True

            self.table.insertRow(0)  # Добавляем ряд с checkbox
            for i in range(0, len(headers)):
                item = QTableWidgetItem()
                item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                item.setCheckState(Qt.Unchecked)
                self.table.setItem(0, i, item)

            # делаем ресайз колонок по содержимому
            self.table.resizeColumnsToContents()

            incorrect_columns = [
                key for key, value in self.incorrect_data.items() if value != 0
            ]
            self.paint_headers(incorrect_columns)
            if len(incorrect_columns) != 0:
                self.conversion_action.setEnabled(False)
                self.graph_action.setEnabled(False)
            else:
                self.conversion_action.setEnabled(True)
                self.graph_action.setEnabled(True)

    def clear_table(self):
        while self.table.rowCount() > 0:
            self.table.removeRow(0)

    def paint_headers(self, columns):
        message = "Некорректные данные в столбцах: \n"
        for i in range(len(self.data.columns)):
            header = self.table.horizontalHeaderItem(i)
            header.setText(header.text().replace('*', ''))

            if self.data.columns[i] in columns:
                message += header.text() + "\n"
                header.setText('*' + header.text())

        if message == "Некорректные данные в столбцах: \n":
            message = "Все данные в верном формате"
        else:
            message += "\nДанные могут быть представлены только в числовом формате.\n" \
                       "Для изменения значений выделите нужные ячейки и нажмите " \
                       "'Данные' - 'Изменить' - 'Данные в выбранных ячейках'."
        self.out_text.clear()
        self.out_text.setText(message)

    def convert_data(self):
        self.get_checked_columns()
        text, ok = QInputDialog.getText(self, 'Конвертация данных',
                                        'Введите название файла:')
        files = os.listdir(
            os.path.join(self.path, self.current_project, self.current_test,
                         "Изменённые_данные"))
        if ok:
            pat = "[\w-]+"  # Шаблон для названия
            if re.sub(pat, "", text, 1) == "":
                if not ((text + '.data') in files):
                    self.data.to_excel(os.path.join(self.path,
                                                    self.current_project,
                                                    self.current_test,
                                                    "Изменённые_данные",
                                                    text + '.xlsx'),
                                       columns=self.y,
                                       index=False)
                    self.data.to_csv(os.path.join(self.path,
                                                  self.current_project,
                                                  self.current_test,
                                                  "Изменённые_данные",
                                                  text + '.data'),
                                     sep=' ',
                                     columns=self.y,
                                     header=True,
                                     index=False)
                    QMessageBox.about(self, "Конвертация",
                                      "Конвертация завершена")
                    self.update_tests_layout()
                else:
                    QMessageBox.about(
                        self, "Ошибка",
                        "Файлы с такими названиями уже существуют")
            else:
                QMessageBox.about(
                    self, 'Ошибка',
                    'Название проекта может состоять из букв, цифр, а также знаков '
                    'тире и нижнего подчёркивания.')

    def get_checked_columns(self):
        self.y.clear()
        for i in range(0, self.table.columnCount()):
            if self.table.item(0, i).checkState() == Qt.Checked:
                self.y.append(self.data.columns[i])  # Add labels of columns

    def get_graph(self):
        self.data = self.data.sort_values(
            by=self.x_name)  # Сортируем данные по возрастанию x
        self.x = list(self.data[self.x_name])

        self.filter_action.setEnabled(True)
        self.add_action.setEnabled(True)
        self.original_action.setEnabled(True)
        self.get_checked_columns()
        self.draw_graph()

    def change_cell(self, row, column):
        if self.table_ready:
            if row != 0:
                t = str(type(self.data.iloc[row - 1, column]))
                self.data.iloc[row - 1,
                               column] = self.table.item(row, column).text()
                try:
                    value = float(self.table.item(row, column).text())
                    self.data.iloc[row - 1, column] = value
                    if not ('float' in t) and not ('int' in t):
                        self.incorrect_data[self.data.columns[column]] -= 1
                except (TypeError, ValueError):
                    if not self.many_cells:
                        QMessageBox.about(self, "Ошибка",
                                          "Введены некорректные данные")
                    self.conversion_action.setEnabled(False)
                    self.graph_action.setEnabled(False)
                    if 'float' in t or 'int' in t:
                        self.incorrect_data[self.data.columns[column]] += 1

                incorrect_columns = [
                    key for key, value in self.incorrect_data.items()
                    if value != 0
                ]
                self.paint_headers(incorrect_columns)
                if len(incorrect_columns) != 0:
                    self.conversion_action.setEnabled(False)
                    self.graph_action.setEnabled(False)
                else:
                    self.conversion_action.setEnabled(True)
                    self.graph_action.setEnabled(True)
        else:
            t = str(type(self.data.iloc[row - 1, column]))
            if not ('float' in t) and not ('int' in t):
                self.incorrect_data[self.data.columns[column]] += 1

    def change_data_in_chosen_cells(self):
        cells = self.table.selectedIndexes()
        if len(cells) == 0:
            QMessageBox.about(self, "Ошибка", "Ни одна ячейка не была выбрана")
        else:
            text, ok = QInputDialog.getText(self, 'Изменение данных',
                                            'Введите число:')
            if ok:
                try:
                    value = float(text)
                except (TypeError, ValueError):
                    QMessageBox.about(self, "Ошибка",
                                      "Введены некорректные данные")
                self.many_cells = True
                for cell in cells:
                    row = cell.row()
                    column = cell.column()
                    item = QTableWidgetItem()
                    item.setText(text)
                    self.table.setItem(row, column, item)
                self.many_cells = False

    # Метод для сохранения картинок графиков
    def save_graph(self, graphWidget):
        exporter = pg.exporters.ImageExporter(graphWidget.plotItem)
        exporter.params.param('width').setValue(
            graphWidget.range.width(), blockSignal=exporter.widthChanged)
        exporter.params.param('height').setValue(
            graphWidget.range.height(), blockSignal=exporter.heightChanged)

        text, ok = QInputDialog.getText(self, 'Сохранение',
                                        'Введите название файла:')
        if ok:
            # save to file
            exporter.export(
                os.path.join(self.path, self.current_project,
                             self.current_test, text + '.png'))

    # Метод для отрисовки графиков в первый раз
    def draw_graph(self):
        self.originalGraphWidget.clear()
        self.changedGraphWidget.clear()
        self.changed_plt.clear()
        self.original_plt.clear()
        for col in self.y:
            if col != self.x_name:
                self.changed_plt.append(
                    plot([0], [0], col, self.changedGraphWidget))
                self.original_plt.append(
                    plot(self.x, list(self.data[col]), col,
                         self.originalGraphWidget))

    # Метод для отрисовки данных по .data
    def draw_data_graph(self):
        self.originalGraphWidget.clear()
        self.changedGraphWidget.clear()
        self.changed_plt.clear()
        self.original_plt.clear()
        for col in self.data.columns:
            if col != self.x_name:
                self.original_plt.append(
                    plot(self.x, list(self.data[col]), col,
                         self.originalGraphWidget))
                self.changed_plt.append(
                    plot([0], [0], col, self.changedGraphWidget))

    # Метод для обновления данных на графиках
    def update_graph(self):
        # plot data: x, y values
        self.changed_flag = False
        for col in range(len(self.y)):
            if self.y[col] != self.x_name:
                flag = False
                for fc in self.y_filtered.keys():
                    if fc == self.y[col]:
                        flag = True
                        break
                if flag:  # Если эти данные были отфильтрованы
                    values = list(self.y_filtered.get(self.y[col]))
                    self.changed_flag = True
                else:
                    values = list(self.data[self.y[col]])
                if self.additional_data_flag:  # Если есть дополнения к графику
                    self.changed_flag = True
                    x = list(enumerate(self.x, 0))
                    min_value = min(x, key=lambda j: j[1])
                    max_value = max(x, key=lambda j: j[1])
                    new_x = []
                    new_y = []
                    for i in range(len(self.x)):
                        if self.x_min <= self.x[i] <= self.x_max:
                            new_x.append(self.x[i])
                            new_y.append(values[i])
                    if min_value[1] > self.x_min:
                        new_x.insert(0, self.x_min)
                        new_y.insert(0, values[min_value[0]])
                    if max_value[1] < self.x_max:
                        new_x.insert(len(new_x), self.x_max)
                        new_y.insert(len(new_x), values[max_value[0]])
                    self.changed_plt[col].setData(new_x, new_y)
                elif self.changed_flag:
                    self.changed_plt[col].setData(self.x, values)
                self.original_plt[col].setData(self.x,
                                               list(self.data[self.y[col]]))

    # Дополнения к графику
    def add_data(self):
        begin, ok = QInputDialog.getText(self, 'Начальное значение',
                                         'Введите начальное значение:')
        if ok:
            try:
                self.x_min = int(begin)
                end, ok = QInputDialog.getText(self, 'Конечное значение',
                                               'Введите конечное значение:')
                if ok:
                    try:
                        self.x_max = int(end)
                        self.additional_data_flag = True
                        self.changed_action.setEnabled(True)
                        self.update_graph()
                    except ValueError:
                        QMessageBox.about(self, "Ошибка",
                                          "Введены некорректные данные")
            except ValueError:
                QMessageBox.about(self, "Ошибка",
                                  "Введены некорректные данные")

    def filter_data(self):
        self.filter_win = fw.FilterWindow(self)
        self.filter_win.show()

    def file_pushed(self, file_path):
        if '.txt' in file_path:
            f = open(file_path)
            self.out_text.setText(f.read())
        elif '.data' in file_path:
            self.file_path = file_path
            self.conversion_action.setEnabled(True)
            self.data_action.setEnabled(True)
            self.column_action.setEnabled(True)
            self.copy_action.setEnabled(True)
            self.delete_action.setEnabled(True)
            self.set_x_action.setEnabled(True)
            f = open(file_path)
            self.out_text.setText(f.read())
            self.loading_data()
            self.threadclass.start()
        elif '.' in file_path:
            subprocess.run(file_path, shell=True)

    def delete_column(self):
        self.get_checked_columns()
        self.data = self.data.drop(columns=self.y)
        self.create_table()

    def delete_prj_folder(self, name=""):
        self.current_project = ""
        if name == "":
            path = os.path.normpath(os.path.join(os.getcwd(), "Projects"))
            prj = QFileDialog.getExistingDirectory(self, "Выберите проект",
                                                   path,
                                                   QFileDialog.ShowDirsOnly)
            if prj != "" and (path in os.path.normpath(prj)):
                shutil.rmtree(prj, ignore_errors=True)
                self.update_project_layout()
                self.update_tests_layout()
        else:
            shutil.rmtree(os.path.join(self.path, name), ignore_errors=True)
            self.update_project_layout()
            self.update_tests_layout()

    def delete_test_folder(self):
        path = os.path.normpath(os.path.join(os.getcwd(), "Projects"))
        prj = QFileDialog.getExistingDirectory(self, "Выберите испытание",
                                               path, QFileDialog.ShowDirsOnly)
        if prj != "":
            h, t = os.path.split(os.path.normpath(prj))
            h, t = os.path.split(h)
            if path == h:
                os.rmdir(prj)
Beispiel #23
0
class SendConfigDialog(QDialog):
    def __init__(self):
        super().__init__()
        self.setMinimumWidth(640)
        self.setWindowTitle("Send configuration to device")
        self.settings = QSettings("tasmotizer.cfg", QSettings.IniFormat)

        self.commands = None
        self.module_mode = 0

        self.createUI()
        self.loadSettings()

    def createUI(self):
        vl = VLayout()
        self.setLayout(vl)

        # Wifi groupbox
        self.gbWifi = QGroupBox("WiFi")
        self.gbWifi.setCheckable(True)
        self.gbWifi.setChecked(False)
        flWifi = QFormLayout()
        self.leAP = QLineEdit()
        self.leAPPwd = QLineEdit()
        self.leAPPwd.setEchoMode(QLineEdit.Password)
        flWifi.addRow("SSID", self.leAP)
        flWifi.addRow("Password", self.leAPPwd)
        self.gbWifi.setLayout(flWifi)

        # Recovery Wifi groupbox
        self.gbRecWifi = QGroupBox("Recovery WiFi")
        self.gbRecWifi.setCheckable(True)
        self.gbRecWifi.setChecked(False)
        flRecWifi = QFormLayout()
        lbRecAP = QLabel("Recovery")
        lbRecAP.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        lbRecAPPwd = QLabel("a1b2c3d4")
        lbRecAPPwd.setAlignment(Qt.AlignVCenter | Qt.AlignRight)

        flRecWifi.addRow("SSID", lbRecAP)
        flRecWifi.addRow("Password", lbRecAPPwd)
        self.gbRecWifi.setLayout(flRecWifi)

        vl_wifis = VLayout(0)
        vl_wifis.addWidgets([self.gbWifi, self.gbRecWifi])

        # MQTT groupbox
        self.gbMQTT = QGroupBox("MQTT")
        self.gbMQTT.setCheckable(True)
        self.gbMQTT.setChecked(False)
        flMQTT = QFormLayout()
        self.leBroker = QLineEdit()
        self.sbPort = SpinBox()
        self.sbPort.setValue(1883)
        self.leTopic = QLineEdit()
        self.leTopic.setText("tasmota")
        self.leFullTopic = QLineEdit()
        self.leFullTopic.setText("%prefix%/%topic%/")
        self.leFriendlyName = QLineEdit()
        self.leMQTTUser = QLineEdit()
        self.leMQTTPass = QLineEdit()
        self.leMQTTPass.setEchoMode(QLineEdit.Password)

        flMQTT.addRow("Host", self.leBroker)
        flMQTT.addRow("Port", self.sbPort)
        flMQTT.addRow("Topic", self.leTopic)
        flMQTT.addRow("FullTopic", self.leFullTopic)
        flMQTT.addRow("FriendlyName", self.leFriendlyName)
        flMQTT.addRow("User [optional]", self.leMQTTUser)
        flMQTT.addRow("Password [optional]", self.leMQTTPass)
        self.gbMQTT.setLayout(flMQTT)

        # Module/template groupbox
        self.gbModule = GroupBoxV("Module/template")
        self.gbModule.setCheckable(True)
        self.gbModule.setChecked(False)

        hl_m_rb = HLayout()
        self.rbModule = QRadioButton("Module")
        self.rbModule.setChecked(True)
        self.rbTemplate = QRadioButton("Template")
        hl_m_rb.addWidgets([self.rbModule, self.rbTemplate])

        self.rbgModule = QButtonGroup(self.gbModule)
        self.rbgModule.addButton(self.rbModule, 0)
        self.rbgModule.addButton(self.rbTemplate, 1)

        self.cbModule = QComboBox()
        for mod_id, mod_name in modules.items():
            self.cbModule.addItem(mod_name, mod_id)

        self.leTemplate = QLineEdit()
        self.leTemplate.setPlaceholderText("Paste template string here")
        self.leTemplate.setVisible(False)

        self.gbModule.addLayout(hl_m_rb)
        self.gbModule.addWidgets([self.cbModule, self.leTemplate])
        self.rbgModule.buttonClicked[int].connect(self.setModuleMode)

        # layout all widgets
        hl_wifis_mqtt = HLayout(0)
        hl_wifis_mqtt.addLayout(vl_wifis)
        hl_wifis_mqtt.addWidget(self.gbMQTT)

        vl.addLayout(hl_wifis_mqtt)
        vl.addWidget(self.gbModule)

        btns = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close)
        btns.accepted.connect(self.accept)
        btns.rejected.connect(self.reject)
        vl.addWidget(btns)

    def loadSettings(self):
        self.gbWifi.setChecked(self.settings.value("gbWifi", False, bool))
        self.leAP.setText(self.settings.value("AP"))

        self.gbRecWifi.setChecked(self.settings.value("gbRecWifi", False,
                                                      bool))

        self.gbMQTT.setChecked(self.settings.value("gbMQTT", False, bool))
        self.leBroker.setText(self.settings.value("Broker"))
        self.sbPort.setValue(self.settings.value("Port", 1883, int))
        self.leTopic.setText(self.settings.value("Topic", "tasmota"))
        self.leFullTopic.setText(
            self.settings.value("FullTopic", "%prefix%/%topic%/"))
        self.leFriendlyName.setText(self.settings.value("FriendlyName"))
        self.leMQTTUser.setText(self.settings.value("MQTTUser"))

        self.gbModule.setChecked(self.settings.value("gbModule", False, bool))

        module_mode = self.settings.value("ModuleMode", 0, int)
        for b in self.rbgModule.buttons():
            if self.rbgModule.id(b) == module_mode:
                b.setChecked(True)
                self.setModuleMode(module_mode)
        self.cbModule.setCurrentText(self.settings.value("Module", "Generic"))
        self.leTemplate.setText(self.settings.value("Template"))

    def setModuleMode(self, radio):
        self.module_mode = radio
        self.cbModule.setVisible(not radio)
        self.leTemplate.setVisible(radio)

    def accept(self):
        ok = True

        if self.gbWifi.isChecked() and (len(self.leAP.text()) == 0
                                        or len(self.leAPPwd.text()) == 0):
            ok = False
            QMessageBox.warning(self, "WiFi details incomplete",
                                "Input WiFi AP and Password")

        if self.gbMQTT.isChecked() and not self.leBroker.text():
            ok = False
            QMessageBox.warning(self, "MQTT details incomplete",
                                "Input broker hostname")

        if self.module_mode == 1 and len(self.leTemplate.text()) == 0:
            ok = False
            QMessageBox.warning(self, "Template string missing",
                                "Input template string")

        if ok:
            backlog = []

            if self.gbWifi.isChecked():
                backlog.extend([
                    "ssid1 {}".format(self.leAP.text()),
                    "password1 {}".format(self.leAPPwd.text())
                ])

            if self.gbRecWifi.isChecked():
                backlog.extend(["ssid2 Recovery", "password2 a1b2c3d4"])

            if self.gbMQTT.isChecked():
                backlog.extend([
                    "mqtthost {}".format(self.leBroker.text()),
                    "mqttport {}".format(self.sbPort.value())
                ])

                topic = self.leTopic.text()
                if topic and topic != "tasmota":
                    backlog.append("topic {}".format(topic))

                fulltopic = self.leFullTopic.text()
                if fulltopic and fulltopic != "%prefix%/%topic%/":
                    backlog.append("fulltopic {}".format(fulltopic))

                fname = self.leFriendlyName.text()
                if fname:
                    backlog.append("friendlyname {}".format(fname))

                mqttuser = self.leMQTTUser.text()
                if mqttuser:
                    backlog.append("mqttuser {}".format(mqttuser))

                    mqttpassword = self.leMQTTPass.text()
                    if mqttpassword:
                        backlog.append("mqttpassword {}".format(mqttpassword))

            if self.gbModule.isChecked():
                if self.module_mode == 0:
                    backlog.append("module {}".format(
                        self.cbModule.currentData()))

                elif self.module_mode == 1:
                    backlog.extend([
                        "template {}".format(self.leTemplate.text()),
                        "module 0"
                    ])

            self.commands = "backlog {}\n".format(";".join(backlog))

            self.done(QDialog.Accepted)
Beispiel #24
0
class VistaListaClienti(QWidget):  # Apre la vista che contiene la lista dei clienti
    def __init__(self):
        super(VistaListaClienti, self).__init__()
        self.controller = ControllerListaClienti()
        # Inserisce in 'lista_clienti' i dati contenuti nel file 'lista_clienti.pickle'.
        # Se la lista è vuota l'utente è notificato con un messaggio di errore.

        self.stylesheet_label = """
            QLabel{
                background-color: white;
                border: 1px solid #dfdfdf;
            }
        """

        self.stylesheet_window = """
            QWidget{
                background-color: #dfdfdf
            }
        """

        self.stylesheet_button_back = """
            QPushButton{
                border-radius: 15px;
                background-color: transparent;
            }

            QPushButton::Pressed{
                background-color: transparent;
            }        
        """

        self.stylesheet_button = """
            QPushButton{
                background-color: #cc3234;
                color: white;
                border-radius: 15px;
            }

            QPushButton::Pressed{
                background-color: grey
            }        
        """

        self.stylesheet_table = """
            QTableWidget{
                background-color: white;
            }
        """

        self.stylesheet_pagamento = """
            QPushButton{
                background-color: transparent;
                border-color: transparent;
            }

            QPushButton::Pressed{
                background-color: grey;
            }
        """

        # Inserimento e impostazioni grafiche dell'immagine dello sfondo della finestra.
        self.imagePath = "Image/foto.png"
        self.image = QImage(self.imagePath)
        self.label = QLabel(self)
        self.label.setPixmap(QPixmap.fromImage(self.image))
        self.label.setScaledContents(True)
        self.label.setGeometry(0, 0, 1670, 750)

        # Inserimento della tabella e intestazione delle colonne.
        self.table = QTableWidget(self)
        self.table.setColumnCount(9)
        self.table.setRowCount(1)
        self.table.setItem(0, 0, QTableWidgetItem("Apri"))
        self.table.setItem(0, 1, QTableWidgetItem("ID"))
        self.table.setItem(0, 2, QTableWidgetItem("Nome"))
        self.table.setItem(0, 3, QTableWidgetItem("Cognome"))
        self.table.setItem(0, 4, QTableWidgetItem("Esame teorico"))
        self.table.setItem(0, 5, QTableWidgetItem("Esame pratico"))
        self.table.setItem(0, 6, QTableWidgetItem("Pagamenti"))
        self.table.setItem(0, 7, QTableWidgetItem("Prenotazione"))
        self.table.setItem(0, 8, QTableWidgetItem("Cancella"))

        self.set_data()  # Inserisce nella tabella i dati contenuti nella lista_clienti.

        # Impostazioni grafiche della tabella.
        self.table.setGeometry(50, 50, 1300, 550)
        self.table.setColumnWidth(0, 90)
        self.table.setColumnWidth(1, 100)
        self.table.setColumnWidth(2, 280)
        self.table.setColumnWidth(3, 280)
        self.table.setColumnWidth(4, 110)
        self.table.setColumnWidth(5, 110)
        self.table.setColumnWidth(6, 110)
        self.table.setColumnWidth(7, 110)
        self.table.setColumnWidth(8, 90)
        self.table.setStyleSheet(self.stylesheet_table)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().hide()
        self.table.horizontalScrollBar().setDisabled(True)
        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table.verticalHeader().hide()
        self.table.setEditTriggers(self.table.NoEditTriggers)
        self.table.setSelectionMode(self.table.NoSelection)
        self.table.setFocusPolicy(Qt.NoFocus)

        # Inserimento e impostazioni grafiche del bottone per tornare alla vista precedente.
        self.button_back = QPushButton(self)
        self.button_back.setIcon(QIcon('Image/back.png'))
        self.button_back.setIconSize(QSize(90, 90))
        self.button_back.setGeometry(60, 630, 90, 90)
        self.button_back.setStyleSheet(self.stylesheet_button_back)
        self.button_back.clicked.connect(self.go_back)

        # Inserimento e impostazioni grafiche del bottone per inserire un nuovo cliente nella lista.
        self.button_new_cliente = QPushButton(self)
        self.button_new_cliente.setText("Nuovo cliente")
        self.font_button = QFont("Times", 11)
        self.button_new_cliente.setFont(self.font_button)
        self.button_new_cliente.setGeometry(1210, 650, 140, 50)
        self.button_new_cliente.setStyleSheet(self.stylesheet_button)
        self.button_new_cliente.clicked.connect(self.go_new_cliente)

        # Impostazioni grafiche generali della finestra del programma.
        self.setWindowTitle("Lista Clienti")
        self.resize(1400, 750)
        self.setFixedSize(self.size())
        self.setStyleSheet(self.stylesheet_window)

    # == set_data ==
    # La funzione si occupa di salvare le informazioni relative al cliente e contenute nel file
    # 'lista_clienti.pickle' nella tabella della VistaListaClienti. Per ogni cliente è disponibile
    # aprire e visualizzare le sue informazioni attraverso un bottone 'Apri' ed è possibile cancellarle
    # attraverso un bottone 'Elimina'.
    def set_data(self):
        self.button_group_apri = QButtonGroup()
        self.button_group_elimina = QButtonGroup()
        self.button_group_pagamenti = QButtonGroup()
        self.icon_no = QIcon("Image/no.png")
        self.icon_si = QIcon("Image/si.png")
        self.icon_sino = QIcon("Image/sino.png")
        self.apri_icon = QIcon("Image/apri_icon.png")
        self.cancella_icon = QIcon("Image/delete.png")
        self.no = QTableWidgetItem()
        self.no.setIcon(self.icon_no)
        self.si = QTableWidgetItem()
        self.si.setIcon(self.icon_si)
        i = 1
        n_righe = len(self.controller.get_lista_clienti())
        self.table.setRowCount(n_righe + 1)
        self.button_group_apri.buttonClicked.connect(self.on_selection_apri)
        self.button_group_elimina.buttonClicked.connect(self.on_selection_elimina)
        self.button_group_pagamenti.buttonClicked.connect(self.on_selection_pagamenti)
        for cliente in self.controller.get_lista_clienti():

            self.sino = QPushButton()
            self.sino.setIcon(self.icon_sino)
            self.sino.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_pagamenti.addButton(self.sino, i)

            self.controller_cliente = ControllerCliente(cliente)
            self.apri = QPushButton()
            self.apri.setIcon(self.apri_icon)
            self.apri.setIconSize(QSize(30, 30))
            self.apri.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_apri.addButton(self.apri, i)
            self.table.setCellWidget(i, 0, self.apri)
            if self.controller_cliente.get_id() == "None":
                self.table.setItem(i, 1, QTableWidgetItem(self.no))
            else:
                self.table.setItem(i, 1, QTableWidgetItem(self.controller_cliente.get_id()))
            self.table.setItem(i, 2, QTableWidgetItem(self.controller_cliente.get_nome()))
            self.table.setItem(i, 3, QTableWidgetItem(self.controller_cliente.get_cognome()))
            if self.controller_cliente.get_esame_teorico() == "None":
                self.table.setItem(i, 4, QTableWidgetItem(self.no))
            else:
                self.table.setItem(i, 4, QTableWidgetItem(self.si))
            if self.controller_cliente.get_esame_pratico() == "None":
                self.table.setItem(i, 5, QTableWidgetItem(self.no))
            else:
                self.table.setItem(i, 5, QTableWidgetItem(self.si))
            if self.controller_cliente.get_pagamento_iniziale() == "None" and \
                    self.controller_cliente.get_pagamento_esame_teorico() == "None" and \
                    self.controller_cliente.get_pagamento_lezioni_guida() == "None" and \
                    self.controller_cliente.get_pagamento_esame_pratico() == "None":
                self.table.setItem(i, 6, QTableWidgetItem(self.no))
            else:
                if self.controller_cliente.get_pagamento_iniziale() != "None" and \
                        self.controller_cliente.get_pagamento_esame_teorico() != "None" and \
                        self.controller_cliente.get_pagamento_lezioni_guida() != "None" and \
                        self.controller_cliente.get_pagamento_esame_pratico() != "None":
                    self.table.setItem(i, 6, QTableWidgetItem(self.si))
                else:
                    self.table.setCellWidget(i, 6, self.sino)
            if self.controller_cliente.get_prenotazione() == "None":
                if self.controller_cliente.get_esame_pratico() == "Effettuato" and \
                        self.controller_cliente.get_esame_teorico() == "Effettuato":
                    self.table.setItem(i, 7, QTableWidgetItem(self.si))
                else:
                    self.table.setItem(i, 7, QTableWidgetItem(self.no))
            else:
                self.table.setItem(i, 7, QTableWidgetItem(self.controller_cliente.get_prenotazione()))
            self.delete = QPushButton()
            self.delete.setIcon(self.cancella_icon)
            self.delete.setIconSize(QSize(35, 35))
            self.delete.setStyleSheet(self.stylesheet_pagamento)
            self.button_group_elimina.addButton(self.delete, i)
            self.table.setCellWidget(i, 8, self.delete)
            i = i + 1

    # == go_new_cliente ==
    # La funzione si occupa di aprire la VistaNuovoCliente.
    def go_new_cliente(self):
        self.vista_nuovo_cliente = VistaNuovoCliente()
        self.vista_nuovo_cliente.show()
        self.close()

    # == go_back ==
    # La funzione si occupa di aprire la finestra precedente.
    def go_back(self):
        self.go_lista_clienti = VistaHomeSegretario.VistaHomeSegretario()
        self.go_lista_clienti.show()
        self.close()

    # == go_pagamenti ==
    # La funzione si occupa di aprire la VistaPagamentiEffettuati.
    def go_pagamenti(self, i):
        pagamento = self.controller.get_lista_clienti()[i-1]
        self.go_vedi_pagamenti = VistaPagamentiEffettuati(pagamento)
        self.go_vedi_pagamenti.show()

    # == go_apri ==
    # La funzione si occupa di aprire la VistaCliente corrispondente al cliente scelto.
    def go_apri(self, i):
        cliente = self.controller.get_lista_clienti()[i - 1]
        self.go_cliente = VistaCliente(cliente, False)
        self.go_cliente.show()
        self.close()

    # == go_elimina ==
    # La funzione, dopo aver chiesto conferma all'utente, cancella le informazioni relative al
    # cliente scelto.
    def go_elimina(self, i):
        conferma = QMessageBox.question(self, "Attenzione", "Sei sicuro di voler eliminare questo cliente?",
                                        QMessageBox.No, QMessageBox.Yes)
        if conferma == QMessageBox.Yes:
            self.controller_pagamenti = ControllerListaPagamenti()
            self.controller_pagamenti.elimina_pagamento_by_cliente(i-1)
            self.controller.rimuovi_cliente_by_index(i-1)
            self.refresh()
        else:
            return

    def refresh(self):
        self.go_lista = VistaListaClienti()
        self.go_lista.show()
        self.close()

    def on_selection_apri(self, selected):
        self.go_apri(self.button_group_apri.id(selected))

    def on_selection_elimina(self, selected):
        self.go_elimina(self.button_group_elimina.id(selected))

    def on_selection_pagamenti(self, selected):
        self.go_pagamenti(self.button_group_pagamenti.id(selected))