Exemplo n.º 1
0
    def __init__(self, parent, text: str, color: QColor, onChange):
        """
            onChange( QColor ) : called when a color is chosen. Receives the new color as argument
        """

        super(ColorButton, self).__init__(parent)

        # reference to the color dialog that is opened
        self.color_dialog = None

        # elements
        button = QPushButton()
        button.setFixedWidth(50)
        label = QLabel(text)

        # reduce the font-weight of the label
        font = label.font()
        font.setWeight(QFont.Thin)
        label.setFont(font)

        layout = QGridLayout()
        layout.setContentsMargins(QMargins(0, 0, 0, 0))

        layout.addWidget(label, 0, 0)
        layout.addWidget(button, 0, 1)

        self.setLayout(layout)
        self.show()

        button.clicked.connect(self.onClick)

        self.button = button
        self.color = color
        self.on_change = onChange

        self.styleButton()
Exemplo n.º 2
0
class AbstractReferenceSelector(QWidget):
    changed = Signal()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.completer = None
        self.p_selected_id = 0

        self.layout = QHBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.name = QLineEdit()
        self.name.setText("")
        self.layout.addWidget(self.name)
        self.details = QLabel()
        self.details.setText("")
        self.details.setVisible(False)
        self.layout.addWidget(self.details)
        self.button = QPushButton("...")
        self.button.setFixedWidth(
            self.button.fontMetrics().horizontalAdvance("XXXX"))
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)

        self.setFocusProxy(self.name)

        self.button.clicked.connect(self.on_button_clicked)

        if self.details_field:
            self.name.setFixedWidth(
                self.name.fontMetrics().horizontalAdvance("X") * 15)
            self.details.setVisible(True)
        self.completer = QCompleter(self.dialog.model.completion_model)
        self.completer.setCompletionColumn(
            self.dialog.model.completion_model.fieldIndex(self.selector_field))
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.name.setCompleter(self.completer)
        self.completer.activated[QModelIndex].connect(self.on_completion)

    def getId(self):
        return self.p_selected_id

    def setId(self, selected_id):
        if self.p_selected_id == selected_id:
            return
        self.p_selected_id = selected_id
        self.name.setText(
            self.dialog.model.getFieldValue(selected_id, self.selector_field))
        if self.details_field:
            self.details.setText(
                self.dialog.model.getFieldValue(selected_id,
                                                self.details_field))

    selected_id = Property(int, getId, setId, notify=changed, user=True)

    def setFilterValue(self, filter_value):
        self.dialog.setFilterValue(filter_value)

    def on_button_clicked(self):
        ref_point = self.mapToGlobal(self.name.geometry().bottomLeft())
        self.dialog.setGeometry(ref_point.x(), ref_point.y(),
                                self.dialog.width(), self.dialog.height())
        res = self.dialog.exec(enable_selection=True,
                               selected=self.selected_id)
        if res:
            self.selected_id = self.dialog.selected_id
            self.changed.emit()

    @Slot(QModelIndex)
    def on_completion(self, index):
        model = index.model()
        self.selected_id = model.data(model.index(index.row(), 0),
                                      Qt.DisplayRole)
        self.changed.emit()

    def isCustom(self):
        return True
Exemplo n.º 3
0
class TransferWidget(AbstractOperationDetails):
    def __init__(self, parent=None):
        AbstractOperationDetails.__init__(self, parent)
        self.name = "Transfer"
        self.operation_type = LedgerTransaction.Transfer

        self.from_date_label = QLabel(self)
        self.from_account_label = QLabel(self)
        self.from_amount_label = QLabel(self)
        self.to_date_label = QLabel(self)
        self.to_account_label = QLabel(self)
        self.to_amount_label = QLabel(self)
        self.fee_account_label = QLabel(self)
        self.fee_amount_label = QLabel(self)
        self.comment_label = QLabel(self)
        self.arrow_account = QLabel(self)
        self.copy_date_btn = QPushButton(self)
        self.copy_amount_btn = QPushButton(self)

        self.main_label.setText(self.tr("Transfer"))
        self.from_date_label.setText(self.tr("Date/Time"))
        self.from_account_label.setText(self.tr("From"))
        self.from_amount_label.setText(self.tr("Amount"))
        self.to_date_label.setText(self.tr("Date/Time"))
        self.to_account_label.setText(self.tr("To"))
        self.to_amount_label.setText(self.tr("Amount"))
        self.fee_account_label.setText(self.tr("Fee from"))
        self.fee_amount_label.setText(self.tr("Fee amount"))
        self.comment_label.setText(self.tr("Note"))
        self.arrow_account.setText(" ➜ ")
        self.copy_date_btn.setText("➜")
        self.copy_date_btn.setFixedWidth(
            self.copy_date_btn.fontMetrics().horizontalAdvance("XXXX"))
        self.copy_amount_btn.setText("➜")
        self.copy_amount_btn.setFixedWidth(
            self.copy_amount_btn.fontMetrics().horizontalAdvance("XXXX"))

        self.withdrawal_timestamp = QDateTimeEdit(self)
        self.withdrawal_timestamp.setCalendarPopup(True)
        self.withdrawal_timestamp.setTimeSpec(Qt.UTC)
        self.withdrawal_timestamp.setFixedWidth(
            self.withdrawal_timestamp.fontMetrics().horizontalAdvance(
                "00/00/0000 00:00:00") * 1.25)
        self.withdrawal_timestamp.setDisplayFormat("dd/MM/yyyy hh:mm:ss")
        self.deposit_timestamp = QDateTimeEdit(self)
        self.deposit_timestamp.setCalendarPopup(True)
        self.deposit_timestamp.setTimeSpec(Qt.UTC)
        self.deposit_timestamp.setFixedWidth(
            self.deposit_timestamp.fontMetrics().horizontalAdvance(
                "00/00/0000 00:00:00") * 1.25)
        self.deposit_timestamp.setDisplayFormat("dd/MM/yyyy hh:mm:ss")
        self.from_account_widget = AccountSelector(self)
        self.to_account_widget = AccountSelector(self)
        self.fee_account_widget = AccountSelector(self)
        self.withdrawal = QLineEdit(self)
        self.withdrawal.setAlignment(Qt.AlignRight)
        self.deposit = QLineEdit(self)
        self.deposit.setAlignment(Qt.AlignRight)
        self.fee = QLineEdit(self)
        self.fee.setAlignment(Qt.AlignRight)
        self.comment = QLineEdit(self)

        self.layout.addWidget(self.from_date_label, 1, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.from_account_label, 2, 0, 1, 1,
                              Qt.AlignLeft)
        self.layout.addWidget(self.from_amount_label, 3, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.comment_label, 5, 0, 1, 1, Qt.AlignLeft)

        self.layout.addWidget(self.withdrawal_timestamp, 1, 1, 1, 1,
                              Qt.AlignLeft)
        self.layout.addWidget(self.from_account_widget, 2, 1, 1, 1,
                              Qt.AlignLeft)
        self.layout.addWidget(self.withdrawal, 3, 1, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.comment, 5, 1, 1, 4)

        self.layout.addWidget(self.copy_date_btn, 1, 2, 1, 1)
        self.layout.addWidget(self.arrow_account, 2, 2, 1, 1, Qt.AlignCenter)
        self.layout.addWidget(self.copy_amount_btn, 3, 2, 1, 1)

        self.layout.addWidget(self.to_date_label, 1, 3, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.to_account_label, 2, 3, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.to_amount_label, 3, 3, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.fee_account_label, 4, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.fee_amount_label, 4, 3, 1, 1, Qt.AlignLeft)

        self.layout.addWidget(self.deposit_timestamp, 1, 4, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.to_account_widget, 2, 4, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.deposit, 3, 4, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.fee_account_widget, 4, 1, 1, 1,
                              Qt.AlignLeft)
        self.layout.addWidget(self.fee, 4, 4, 1, 1, Qt.AlignLeft)

        self.layout.addWidget(self.commit_button, 0, 6, 1, 1)
        self.layout.addWidget(self.revert_button, 0, 7, 1, 1)

        self.layout.addItem(self.verticalSpacer, 6, 0, 1, 1)
        self.layout.addItem(self.horizontalSpacer, 1, 5, 1, 1)

        self.copy_date_btn.clicked.connect(self.onCopyDate)
        self.copy_amount_btn.clicked.connect(self.onCopyAmount)

        super()._init_db("transfers")
        self.mapper.setItemDelegate(TransferWidgetDelegate(self.mapper))

        self.from_account_widget.changed.connect(self.mapper.submit)
        self.to_account_widget.changed.connect(self.mapper.submit)
        self.fee_account_widget.changed.connect(self.mapper.submit)

        self.mapper.addMapping(self.withdrawal_timestamp,
                               self.model.fieldIndex("withdrawal_timestamp"))
        self.mapper.addMapping(self.from_account_widget,
                               self.model.fieldIndex("withdrawal_account"))
        self.mapper.addMapping(self.withdrawal,
                               self.model.fieldIndex("withdrawal"))
        self.mapper.addMapping(self.deposit_timestamp,
                               self.model.fieldIndex("deposit_timestamp"))
        self.mapper.addMapping(self.to_account_widget,
                               self.model.fieldIndex("deposit_account"))
        self.mapper.addMapping(self.deposit, self.model.fieldIndex("deposit"))
        self.mapper.addMapping(self.fee_account_widget,
                               self.model.fieldIndex("fee_account"))
        self.mapper.addMapping(self.fee, self.model.fieldIndex("fee"))
        self.mapper.addMapping(self.comment, self.model.fieldIndex("note"))

        self.model.select()

    @Slot()
    def saveChanges(self):
        record = self.model.record(0)
        # Set related fields NULL if we don't have fee. This is required for correct transfer processing
        fee_amount = record.value(self.model.fieldIndex("fee"))
        if not fee_amount:
            fee_amount = 0
        if abs(float(fee_amount)) < Setup.CALC_TOLERANCE:
            self.model.setData(
                self.model.index(0, self.model.fieldIndex("fee_account")),
                None)
            self.model.setData(
                self.model.index(0, self.model.fieldIndex("fee")), None)
        super().saveChanges()

    def prepareNew(self, account_id):
        new_record = super().prepareNew(account_id)
        new_record.setValue(
            "withdrawal_timestamp",
            int(datetime.now().replace(tzinfo=tz.tzutc()).timestamp()))
        new_record.setValue("withdrawal_account", account_id)
        new_record.setValue("withdrawal", 0)
        new_record.setValue(
            "deposit_timestamp",
            int(datetime.now().replace(tzinfo=tz.tzutc()).timestamp()))
        new_record.setValue("deposit_account", 0)
        new_record.setValue("deposit", 0)
        new_record.setValue("fee_account", 0)
        new_record.setValue("fee", 0)
        new_record.setValue("asset", None)
        new_record.setValue("note", None)
        return new_record

    def copyToNew(self, row):
        new_record = self.model.record(row)
        new_record.setNull("id")
        new_record.setValue(
            "withdrawal_timestamp",
            int(datetime.now().replace(tzinfo=tz.tzutc()).timestamp()))
        new_record.setValue(
            "deposit_timestamp",
            int(datetime.now().replace(tzinfo=tz.tzutc()).timestamp()))
        return new_record

    @Slot()
    def onCopyDate(self):
        self.deposit_timestamp.setDateTime(
            self.withdrawal_timestamp.dateTime())
        # mapper.submit() isn't needed here as 'changed' signal of 'deposit_timestamp' is linked with it

    @Slot()
    def onCopyAmount(self):
        self.deposit.setText(self.withdrawal.text())
        self.mapper.submit()
Exemplo n.º 4
0
class LogViewer(QPlainTextEdit, logging.Handler):
    def __init__(self, parent=None):
        QPlainTextEdit.__init__(self, parent)
        logging.Handler.__init__(self)
        self.app = QApplication.instance()
        self.setReadOnly(True)
        self.status_bar = None  # Status bar where notifications and control are located
        self.expandButton = None  # Button that shows/hides log window
        self.notification = None  # Here is QLabel element to display LOG update status
        self.clear_color = None  # Variable to store initial "clear" background color
        self.collapsed_text = self.tr("▶ logs")
        self.expanded_text = self.tr("▲ logs")

    def emit(self, record, **kwargs):
        predefinded_colors = {
            logging.DEBUG: CustomColor.Grey,
            logging.INFO: self.clear_color,
            logging.WARNING: CustomColor.LightRed,
            logging.ERROR: CustomColor.LightRed,
            logging.CRITICAL: CustomColor.LightRed
        }
        try:
            msg_color = predefinded_colors[record.levelno]
        except KeyError:
            self.appendPlainText(
                self.tr("Unknown logging level provided: ") +
                f"{record.levelno}")
            msg_color = CustomColor.LightRed

        # Store message in log window
        msg = self.format(record)
        tf = self.currentCharFormat()
        tf.setForeground(QBrush(msg_color))
        self.setCurrentCharFormat(tf)
        self.appendPlainText(msg)

        # Show in status bar
        if self.notification:
            palette = self.notification.palette()
            palette.setColor(self.notification.foregroundRole(), msg_color)
            self.notification.setPalette(palette)
            msg = msg.replace('\n',
                              "; ")  # Get rid of new lines in error message
            elided_text = self.notification.fontMetrics().elidedText(
                msg, Qt.ElideRight, self.get_available_width())
            self.notification.setText(elided_text)
        # Set button color
        if self.expandButton:
            palette = self.expandButton.palette()
            palette.setColor(self.expandButton.foregroundRole(), msg_color)

        self.app.processEvents()

    def showEvent(self, event):
        self.cleanNotification()
        super().showEvent(event)

    def setStatusBar(self, status_bar):
        self.setVisible(False)
        self.status_bar = status_bar

        self.expandButton = QPushButton(self.collapsed_text, parent=self)
        self.expandButton.setFixedWidth(
            self.expandButton.fontMetrics().horizontalAdvance(
                self.collapsed_text) * 1.25)
        self.expandButton.setCheckable(True)
        self.expandButton.clicked.connect(self.showLogs)
        self.status_bar.addWidget(self.expandButton)

        self.notification = QLabel(self)
        self.status_bar.addWidget(self.notification)
        self.notification.setAutoFillBackground(True)
        self.clear_color = self.expandButton.palette().color(
            self.notification.foregroundRole())
        self.setFormatter(
            logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))

    def removeStatusBar(self):
        self.cleanNotification()
        self.notification = None

    def cleanNotification(self):
        palette = self.notification.palette()
        palette.setColor(self.notification.foregroundRole(), self.clear_color)
        self.notification.setPalette(palette)
        self.notification.setText("")

    @Slot()
    def showLogs(self):
        self.setVisible(self.expandButton.isChecked())
        text = self.expanded_text if self.expandButton.isChecked(
        ) else self.collapsed_text
        self.expandButton.setText(text)

    # Calculates maximum width that is free on status bar
    def get_available_width(self):
        width = self.status_bar.width()
        for child in self.status_bar.children():
            if hasattr(child, "width") and child != self.notification:
                width -= child.width()
        return width - 8  # return calculated width reduced by small safety gap
Exemplo n.º 5
0
class AddSteamWidget(TritonWidget):

    def __init__(self, base, *args, **kwargs):
        TritonWidget.__init__(self, base, *args, **kwargs)
        self.sharedSecret = None
        self.identitySecret = None
        self.steamId = None
        self.type = Globals.SteamAuth

        self.setWindowTitle('Add Steam')
        self.setBackgroundColor(self, Qt.white)

        self.boxLayout = QVBoxLayout(self)
        self.boxLayout.setContentsMargins(20, 20, 20, 20)

        self.nameWidget = TextboxWidget(base, 'Name:')
        self.steamIdWidget = TextboxWidget(base, 'Steam ID:')
        self.sharedWidget = TextboxWidget(base, 'Shared Secret:')
        self.identityWidget = TextboxWidget(base, 'Identity Secret:')

        self.verifyLabel = QLabel()
        self.verifyLabel.setText('Click the Verify button to check the first code.')
        self.verifyLabel.setFont(QFont('Helvetica', 10))

        self.verifyBox = QLineEdit()
        self.verifyBox.setFixedWidth(150)
        self.verifyBox.setFont(QFont('Helvetica', 10))
        self.verifyBox.setEnabled(False)

        palette = QPalette()
        palette.setColor(QPalette.Text, Qt.black)
        self.verifyBox.setPalette(palette)
        self.verifyBox.setAlignment(Qt.AlignCenter)

        self.verifyButton = QPushButton('Verify')
        self.verifyButton.clicked.connect(self.checkVerify)
        self.verifyButton.setFixedWidth(150)

        self.addButton = QPushButton('OK')
        self.addButton.clicked.connect(self.add)

        self.boxLayout.addWidget(self.nameWidget)
        self.boxLayout.addWidget(self.steamIdWidget)
        self.boxLayout.addWidget(self.sharedWidget)
        self.boxLayout.addWidget(self.identityWidget)
        self.boxLayout.addSpacing(10)
        self.boxLayout.addWidget(self.verifyLabel)
        self.boxLayout.addWidget(self.verifyBox, 0, Qt.AlignCenter)
        self.boxLayout.addWidget(self.verifyButton, 0, Qt.AlignCenter)
        self.boxLayout.addSpacing(10)
        self.boxLayout.addWidget(self.addButton, 0, Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.center()
        self.show()

    def getName(self):
        return self.nameWidget.box.text()

    def getAccount(self):
        return {'name': self.getName(), 'type': self.type, 'sharedSecret': self.sharedSecret, 'identitySecret': self.identitySecret, 'steamId': self.steamId, 'icon': 'icons/SteamIcon.png'}

    def invalidateSecret(self, text=''):
        self.sharedSecret = None
        self.identitySecret = None
        self.steamId = None
        self.verifyBox.setText(text)

    def checkVerify(self):
        self.sharedSecret = self.sharedWidget.box.text()
        self.identitySecret = self.identityWidget.box.text()
        self.steamId = self.steamIdWidget.box.text()

        if not self.sharedSecret or not self.identitySecret or not self.steamId:
            self.invalidateSecret('Invalid')
            return

        try:
            self.verifyBox.setText(self.base.getAuthCode(self.getAccount()))
        except:
            self.invalidateSecret('Invalid')

    def add(self):
        if not self.sharedSecret or not self.getName():
            return

        self.base.addAccount(self.getAccount())
        self.close()
Exemplo n.º 6
0
class AddOTPWidget(TritonWidget):
    def __init__(self, base, *args, **kwargs):
        TritonWidget.__init__(self, base, *args, **kwargs)
        self.key = None
        self.type = Globals.OTPAuth

        self.setWindowTitle('Add Authenticator')
        self.setBackgroundColor(self, Qt.white)

        self.boxLayout = QVBoxLayout(self)
        self.boxLayout.setContentsMargins(20, 20, 20, 20)

        self.nameWidget = TextboxWidget(base, 'Name:')

        self.secretLabel = QLabel()
        self.secretLabel.setText(
            'Enter the Secret Code. If you have a QR code,\nyou can paste the URL of the image instead.'
        )
        self.secretLabel.setFont(QFont('Helvetica', 10))

        self.secretBox = QLineEdit()
        self.secretBox.setFixedWidth(300)
        self.secretBox.setFont(QFont('Helvetica', 10))
        self.secretBox.textChanged.connect(
            lambda text: self.invalidateSecret())

        self.verifyLabel = QLabel()
        self.verifyLabel.setText(
            'Click the Verify button to check the first code.')
        self.verifyLabel.setFont(QFont('Helvetica', 10))

        self.verifyBox = QLineEdit()
        self.verifyBox.setFixedWidth(150)
        self.verifyBox.setFont(QFont('Helvetica', 10))
        self.verifyBox.setEnabled(False)

        palette = QPalette()
        palette.setColor(QPalette.Text, Qt.black)
        self.verifyBox.setPalette(palette)
        self.verifyBox.setAlignment(Qt.AlignCenter)

        self.verifyButton = QPushButton('Verify')
        self.verifyButton.clicked.connect(self.checkVerify)
        self.verifyButton.setFixedWidth(150)

        self.addButton = QPushButton('OK')
        self.addButton.clicked.connect(self.add)

        self.boxLayout.addWidget(self.nameWidget)
        self.boxLayout.addSpacing(10)
        self.boxLayout.addWidget(self.secretLabel)
        self.boxLayout.addWidget(self.secretBox)
        self.boxLayout.addSpacing(10)
        self.boxLayout.addWidget(self.verifyLabel)
        self.boxLayout.addWidget(self.verifyBox, 0, Qt.AlignCenter)
        self.boxLayout.addWidget(self.verifyButton, 0, Qt.AlignCenter)
        self.boxLayout.addSpacing(10)
        self.boxLayout.addWidget(self.addButton, 0, Qt.AlignRight)

        self.setFixedSize(self.sizeHint())
        self.center()
        self.show()

    def getName(self):
        return self.nameWidget.box.text()

    def getAccount(self):
        return {
            'name': self.getName(),
            'type': self.type,
            'key': self.key,
            'icon': 'icons/WinAuthIcon.png'
        }

    def invalidateSecret(self, value=''):
        self.key = None
        self.verifyBox.setText(value)

    def checkVerify(self):
        self.key = self.secretBox.text()

        if not self.key:
            self.invalidateSecret('Invalid')
            return

        self.key = self.base.readQRLink(self.key) or self.key
        self.key = self.key.upper().replace(' ', '')

        try:
            self.verifyBox.setText(self.base.getAuthCode(self.getAccount()))
        except:
            self.invalidateSecret('Invalid')

    def add(self):
        if not self.key or not self.getName():
            return

        self.base.addAccount(self.getAccount())
        self.close()