Exemple #1
0
 def create_menu(self, position):
     item = self.currentItem()
     if not item:
         return
     menu = QMenu()
     server = item.data(1, Qt.UserRole)
     menu.addAction(_("Use as server"), lambda: self.set_server(server))
     menu.exec_(self.viewport().mapToGlobal(position))
    def __init__(self, parent):
        super(SignAnnounceWidget, self).__init__(parent)
        self.dialog = parent
        self.manager = parent.manager

        # Displays the status of the masternode.
        self.status_edit = QLineEdit()
        self.status_edit.setReadOnly(True)

        self.alias_edit = QLineEdit()
        self.collateral_edit = PrevOutWidget()
        self.delegate_edit = QLineEdit()
        self.delegate_edit.setFont(QFont(util.MONOSPACE_FONT))

        for i in [self.alias_edit, self.collateral_edit, self.delegate_edit]:
            i.setReadOnly(True)

        self.mapper = QDataWidgetMapper()
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setModel(self.dialog.masternodes_widget.proxy_model)

        model = self.dialog.masternodes_widget.model
        self.mapper.addMapping(self.alias_edit, model.ALIAS)
        self.mapper.addMapping(self.collateral_edit, model.VIN, b'string')
        self.mapper.addMapping(self.delegate_edit, model.DELEGATE)

        self.sign_button = QPushButton(_('Activate Masternode'))
        self.sign_button.setEnabled(False)
        self.sign_button.clicked.connect(self.sign_announce)

        status_box = QHBoxLayout()
        status_box.setContentsMargins(0, 0, 0, 0)
        status_box.addWidget(QLabel(_('Status:')))
        status_box.addWidget(self.status_edit, stretch=1)

        vbox = QVBoxLayout()
        vbox.addLayout(status_box)

        form = QFormLayout()
        form.addRow(_('Alias:'), self.alias_edit)
        form.addRow(_('Collateral SPARKS Output:'), self.collateral_edit)
        form.addRow(_('Masternode Private Key:'), self.delegate_edit)
        vbox.addLayout(form)
        vbox.addLayout(util.Buttons(self.sign_button))
        self.setLayout(vbox)
Exemple #3
0
    def calibration_pdf(self, image):
        printer = QPrinter()
        printer.setPaperSize(QSizeF(210, 297), QPrinter.Millimeter)
        printer.setResolution(600)
        printer.setOutputFormat(QPrinter.PdfFormat)
        printer.setOutputFileName(self.base_dir + _('calibration') + '.pdf')
        printer.setPageMargins(0, 0, 0, 0, 6)

        painter = QPainter()
        painter.begin(printer)
        painter.drawImage(553, 533, image)
        font = QFont('Source Sans Pro', 10, QFont.Bold)
        painter.setFont(font)
        painter.drawText(254, 277, _("Calibration sheet"))
        font = QFont('Source Sans Pro', 7, QFont.Bold)
        painter.setFont(font)
        painter.drawText(600, 2077, _("Instructions:"))
        font = QFont('Source Sans Pro', 7, QFont.Normal)
        painter.setFont(font)
        painter.drawText(
            700, 2177,
            _("1. Place this paper on a flat and well iluminated surface."))
        painter.drawText(
            700, 2277,
            _("2. Align your Revealer borderlines to the sparksed lines on the top and left."
              ))
        painter.drawText(
            700, 2377,
            _("3. Press slightly the Revealer against the paper and read the numbers that best "
              "match on the opposite sides. "))
        painter.drawText(700, 2477, _("4. Type the numbers in the software"))
        painter.end()
    def check_device_dialog(self):
        # Set password if fresh device
        if self.password is None and not self.dbb_has_password():
            if not self.setupRunning:
                return False  # A fresh device cannot connect to an existing wallet
            msg = _("An uninitialized Digital Bitbox is detected.") + " " + \
                  _("Enter a new password below.") + "\n\n" + \
                  _("REMEMBER THE PASSWORD!") + "\n\n" + \
                  _("You cannot access your coins or a backup without the password.") + "\n" + \
                  _("A backup is saved automatically when generating a new wallet.")
            if self.password_dialog(msg):
                reply = self.hid_send_plain(b'{"password":"******"}')
            else:
                return False

        # Get password from user if not yet set
        msg = _("Enter your Digital Bitbox password:"******"led":"blink"}')
            if 'error' in reply:
                self.password = None
                if reply['error']['code'] == 109:
                    msg = _("Incorrect password entered.") + "\n\n" + \
                          reply['error']['message'] + "\n\n" + \
                          _("Enter your Digital Bitbox password:"******"Unexpected error occurred.") + "\n\n" + \
                          reply['error']['message'] + "\n\n" + \
                          _("Enter your Digital Bitbox password:"******"device":"info"}')
            if reply['device']['id'] != "":
                self.recover_or_erase_dialog()  # Already seeded
            else:
                self.seed_device_dialog()  # Seed if not initialized
            self.mobile_pairing_dialog()
        return self.isInitialized
Exemple #5
0
    def setup_dialog(self, window):
        self.update_wallet_name(window.parent().parent().wallet)
        self.user_input = False
        self.noise_seed = False
        self.d = WindowModalDialog(window, "Revealer")
        self.d.setMinimumWidth(420)
        vbox = QVBoxLayout(self.d)
        vbox.addSpacing(21)
        logo = QLabel()
        vbox.addWidget(logo)
        logo.setPixmap(QPixmap(':icons/revealer.png'))
        logo.setAlignment(Qt.AlignCenter)
        vbox.addSpacing(42)

        self.load_noise = ScanQRTextEdit()
        self.load_noise.setTabChangesFocus(True)
        self.load_noise.textChanged.connect(self.on_edit)
        self.load_noise.setMaximumHeight(33)

        vbox.addWidget(
            WWLabel("<b>" + _("Enter your physical revealer code:") + "<b>"))
        vbox.addWidget(self.load_noise)
        vbox.addSpacing(11)

        self.next_button = QPushButton(_("Next"), self.d)
        self.next_button.setDefault(True)
        self.next_button.setEnabled(False)
        vbox.addLayout(Buttons(self.next_button))
        self.next_button.clicked.connect(self.d.close)
        self.next_button.clicked.connect(
            partial(self.cypherseed_dialog, window))
        vbox.addSpacing(21)

        vbox.addWidget(WWLabel(_("or, alternatively: ")))
        bcreate = QPushButton(_("Create a digital Revealer"))

        def mk_digital():
            try:
                self.make_digital(self.d)
            except Exception:
                traceback.print_exc(file=sys.stdout)
            else:
                self.cypherseed_dialog(window)

        bcreate.clicked.connect(mk_digital)

        vbox.addWidget(bcreate)
        vbox.addSpacing(11)
        vbox.addWidget(
            QLabel(''.join([
                "<b>" + _("WARNING") + "</b>:" +
                _("Printing a revealer and encrypted seed"),
                '<br/>',
                _("on the same printer is not trustless towards the printer."),
                '<br/>',
            ])))
        vbox.addSpacing(11)
        vbox.addLayout(Buttons(CloseButton(self.d)))

        return bool(self.d.exec_())
Exemple #6
0
 def on_filename(filename):
     path = os.path.join(wallet_folder, filename)
     wallet_from_memory = get_wallet_from_daemon(path)
     try:
         if wallet_from_memory:
             self.storage = wallet_from_memory.storage
         else:
             self.storage = WalletStorage(path, manual_upgrades=True)
         self.next_button.setEnabled(True)
     except BaseException:
         traceback.print_exc(file=sys.stderr)
         self.storage = None
         self.next_button.setEnabled(False)
     if self.storage:
         if not self.storage.file_exists():
             msg =_("This file does not exist.") + '\n' \
                   + _("Press 'Next' to create this wallet, or choose another file.")
             pw = False
         elif not wallet_from_memory:
             if self.storage.is_encrypted_with_user_pw():
                 msg = _("This file is encrypted with a password.") + '\n' \
                       + _('Enter your password or choose another file.')
                 pw = True
             elif self.storage.is_encrypted_with_hw_device():
                 msg = _("This file is encrypted using a hardware device.") + '\n' \
                       + _("Press 'Next' to choose device to decrypt.")
                 pw = False
             else:
                 msg = _("Press 'Next' to open this wallet.")
                 pw = False
         else:
             msg = _("This file is already open in memory.") + "\n" \
                 + _("Press 'Next' to create/focus window.")
             pw = False
     else:
         msg = _('Cannot read file')
         pw = False
     self.msg_label.setText(msg)
     if pw:
         self.pw_label.show()
         self.pw_e.show()
         self.pw_e.setFocus()
     else:
         self.pw_label.hide()
         self.pw_e.hide()
Exemple #7
0
 def receive_menu(self, menu, addrs, wallet):
     if len(addrs) != 1:
         return
     for keystore in wallet.get_keystores():
         if type(keystore) == self.keystore_class:
             def show_address(keystore=keystore):
                 keystore.thread.add(partial(self.show_address, wallet, addrs[0], keystore))
             device_name = "{} ({})".format(self.device, keystore.label)
             menu.addAction(_("Show on {}").format(device_name), show_address)
Exemple #8
0
 def get_xpub(self, device_id, derivation, xtype, wizard):
     if xtype not in self.SUPPORTED_XTYPES:
         raise ScriptTypeNotSupported(_('This type of script is not supported with {}.').format(self.device))
     devmgr = self.device_manager()
     client = devmgr.client_by_id(device_id)
     client.handler = self.create_handler(wizard)
     client.checkDevice()
     xpub = client.get_xpub(derivation, xtype)
     return xpub
Exemple #9
0
 def remove_local_tx(self, delete_tx):
     to_delete = {delete_tx}
     to_delete |= self.wallet.get_depending_transactions(delete_tx)
     question = _("Are you sure you want to remove this transaction?")
     if len(to_delete) > 1:
         question = _(
             "Are you sure you want to remove this transaction and {} child transactions?"
             .format(len(to_delete) - 1))
     answer = QMessageBox.question(self.parent, _("Please confirm"),
                                   question, QMessageBox.Yes,
                                   QMessageBox.No)
     if answer == QMessageBox.No:
         return
     for tx in to_delete:
         self.wallet.remove_transaction(tx)
     self.wallet.save_transactions(write=True)
     # need to update at least: history_list, utxo_list, address_list
     self.parent.need_update.set()
 def dbb_has_password(self):
     reply = self.hid_send_plain(b'{"ping":""}')
     if 'ping' not in reply:
         raise Exception(
             _('Device communication error. Please unplug and replug your Digital Bitbox.'
               ))
     if reply['ping'] == 'password':
         return True
     return False
Exemple #11
0
 def update_dlg(self):
     self.modes.setCurrentIndex(self.cfg['mode'])
     self.modebox.setVisible(True)
     self.addPair.setText(
         _("Pair") if not self.cfg['pair'] else _("Re-Pair"))
     self.addPair.setVisible(self.txdata['confirmationType'] > 2)
     self.helpmsg.setText(
         helpTxt[self.cfg['mode'] if self.cfg['mode'] < 2 else 2 if self.
                 cfg['pair'] else 4])
     self.helpmsg.setMinimumHeight(180 if self.txdata['confirmationType'] ==
                                   1 else 100)
     self.pairbox.setVisible(False)
     self.helpmsg.setVisible(True)
     self.pinbox.setVisible(self.cfg['mode'] == 0)
     self.cardbox.setVisible(self.cfg['mode'] == 1)
     self.pintxt.setFocus(
         True) if self.cfg['mode'] == 0 else self.cardtxt.setFocus(True)
     self.setMaximumHeight(400)
Exemple #12
0
 def create_password_layout(self, wallet, is_encrypted, OK_button):
     if not wallet.has_password():
         msg = _('Your wallet is not protected.')
         msg += ' ' + _('Use this dialog to add a password to your wallet.')
     else:
         if not is_encrypted:
             msg = _(
                 'Your Sparks coins are password protected. However, your wallet file is not encrypted.'
             )
         else:
             msg = _('Your wallet is password protected and encrypted.')
         msg += ' ' + _('Use this dialog to change your password.')
     self.playout = PasswordLayout(
         wallet,
         msg,
         PW_CHANGE,
         OK_button,
         force_disable_encrypt_cb=not wallet.can_have_keystore_encryption())
Exemple #13
0
 def checkDevice(self):
     if not self.preflightDone:
         try:
             self.perform_hw1_preflight()
         except BTChipException as e:
             if (e.sw == 0x6d00 or e.sw == 0x6700):
                 raise Exception(_("Device not in Sparks mode")) from e
             raise e
         self.preflightDone = True
    def __init__(self, data, parent=None, title="", show_text=False):
        WindowModalDialog.__init__(self, parent, title)

        vbox = QVBoxLayout()
        qrw = QRCodeWidget(data)
        qscreen = QApplication.primaryScreen()
        vbox.addWidget(qrw, 1)
        if show_text:
            text = QTextEdit()
            text.setText(data)
            text.setReadOnly(True)
            vbox.addWidget(text)
        hbox = QHBoxLayout()
        hbox.addStretch(1)

        config = electrum_sparks.get_config()
        if config:
            filename = os.path.join(config.path, "qrcode.png")

            def print_qr():
                p = qscreen.grabWindow(qrw.winId())
                p.save(filename, 'png')
                self.show_message(_("QR code saved to file") + " " + filename)

            def copy_to_clipboard():
                p = qscreen.grabWindow(qrw.winId())
                QApplication.clipboard().setPixmap(p)
                self.show_message(_("QR code copied to clipboard"))

            b = QPushButton(_("Copy"))
            hbox.addWidget(b)
            b.clicked.connect(copy_to_clipboard)

            b = QPushButton(_("Save"))
            hbox.addWidget(b)
            b.clicked.connect(print_qr)

        b = QPushButton(_("Close"))
        hbox.addWidget(b)
        b.clicked.connect(self.accept)
        b.setDefault(True)

        vbox.addLayout(hbox)
        self.setLayout(vbox)
Exemple #15
0
 def bcrypt(self, dialog):
     self.rawnoise = False
     dialog.show_message(''.join([
         _("{} encrypted for Revealer {}_{} saved as PNG and PDF at:"
           ).format(self.was, self.version, self.code_id), "<br/>", "<b>",
         self.base_dir + self.filename + self.version + "_" + self.code_id,
         "</b>"
     ]),
                         rich_text=True)
     dialog.close()
 def f(b):
     self.is_seed = (lambda x: bool(x)) if b else self.saved_is_seed
     self.is_bip39 = b
     self.on_edit()
     if b:
         msg = ' '.join([
             '<b>' + _('Warning') + ':</b>  ',
             _('BIP39 seeds can be imported in Sparks-Electrum, so that users can access funds locked in other wallets.'
               ),
             _('However, we do not generate BIP39 seeds, because they do not meet our safety standard.'
               ),
             _('BIP39 seeds do not include a version number, which compromises compatibility with future software.'
               ),
             _('We do not guarantee that BIP39 imports will always be supported in Sparks-Electrum.'
               ),
         ])
     else:
         msg = ''
     self.seed_warning.setText(msg)
Exemple #17
0
    def create_masternode_conf_tab(self):
        """Create the tab used to import masternode.conf files."""

        desc = ' '.join([
            'You can use this form to import your masternode.conf file.',
            'This file is usually located in the same directory that your wallet file is in.',
            'If you just need to import your masternode\'s private key, use the regular process for importing a key.'
        ])
        desc = QLabel(_(desc))
        desc.setWordWrap(True)

        import_filename_edit = QLineEdit()
        import_filename_edit.setPlaceholderText(
            _('Enter the path to your masternode.conf'))
        import_select_file = QPushButton(_('Select File...'))
        hbox = QHBoxLayout()
        hbox.addWidget(import_filename_edit, stretch=1)
        hbox.addWidget(import_select_file)
        import_conf_button = QPushButton(_('Import'))
        vbox = QVBoxLayout()
        vbox.addWidget(desc)
        vbox.addLayout(hbox)
        vbox.addLayout(util.Buttons(import_conf_button))
        vbox.addStretch(1)

        def select_import_file():
            text = QFileDialog.getOpenFileName(None,
                                               _('Select a file to import'),
                                               '', '*.conf')
            if text and len(text) == 2:
                import_filename_edit.setText(text[0])

        import_select_file.clicked.connect(select_import_file)

        def do_import_file():
            path = str(import_filename_edit.text())
            self.import_masternode_conf(path)

        import_conf_button.clicked.connect(do_import_file)

        w = QWidget()
        w.setLayout(vbox)
        return w
Exemple #18
0
 def sign_message(self, sequence, message, password):
     message = message.encode('utf8')
     message_hash = hashlib.sha256(message).hexdigest().upper()
     # prompt for the PIN before displaying the dialog if necessary
     client = self.get_client()
     address_path = self.get_derivation()[2:] + "/%d/%d"%sequence
     self.handler.show_message("Signing message ...\r\nMessage hash: "+message_hash)
     try:
         info = self.get_client().signMessagePrepare(address_path, message)
         pin = ""
         if info['confirmationNeeded']:
             pin = self.handler.get_auth( info ) # does the authenticate dialog and returns pin
             if not pin:
                 raise UserWarning(_('Cancelled by user'))
             pin = str(pin).encode()
         signature = self.get_client().signMessageSign(pin)
     except BTChipException as e:
         if e.sw == 0x6a80:
             self.give_error("Unfortunately, this message cannot be signed by the Ledger wallet. Only alphanumerical messages shorter than 140 characters are supported. Please remove any extra characters (tab, carriage return) and retry.")
         elif e.sw == 0x6985:  # cancelled by user
             return b''
         elif e.sw == 0x6982:
             raise  # pin lock. decorator will catch it
         else:
             self.give_error(e, True)
     except UserWarning:
         self.handler.show_error(_('Cancelled by user'))
         return b''
     except Exception as e:
         self.give_error(e, True)
     finally:
         self.handler.finished()
     # Parse the ASN.1 signature
     rLength = signature[3]
     r = signature[4 : 4 + rLength]
     sLength = signature[4 + rLength + 1]
     s = signature[4 + rLength + 2:]
     if rLength == 33:
         r = r[1:]
     if sLength == 33:
         s = s[1:]
     # And convert it
     return bytes([27 + 4 + (signature[0] & 0x01)]) + r + s
Exemple #19
0
 def toggle_passphrase():
     title = _("Confirm Toggle Passphrase Protection")
     currently_enabled = self.features.passphrase_protection
     if currently_enabled:
         msg = _("After disabling passphrases, you can only pair this "
                 "Sparks-Electrum wallet if it had an empty passphrase.  "
                 "If its passphrase was not empty, you will need to "
                 "create a new wallet with the install wizard.  You "
                 "can use this wallet again at any time by re-enabling "
                 "passphrases and entering its passphrase.")
     else:
         msg = _("Your current Sparks-Electrum wallet can only be used with "
                 "an empty passphrase.  You must create a separate "
                 "wallet with the install wizard for other passphrases "
                 "as each one generates a new set of addresses.")
     msg += "\n\n" + _("Are you sure you want to proceed?")
     if not self.question(msg, title=title):
         return
     invoke_client('toggle_passphrase', unpair_after=currently_enabled)
Exemple #20
0
def filename_field(parent, config, defaultname, select_msg):

    vbox = QVBoxLayout()
    vbox.addWidget(QLabel(_("Format")))
    gb = QGroupBox("format", parent)
    b1 = QRadioButton(gb)
    b1.setText(_("CSV"))
    b1.setChecked(True)
    b2 = QRadioButton(gb)
    b2.setText(_("json"))
    vbox.addWidget(b1)
    vbox.addWidget(b2)

    hbox = QHBoxLayout()

    directory = config.get('io_dir', os.path.expanduser('~'))
    path = os.path.join( directory, defaultname )
    filename_e = QLineEdit()
    filename_e.setText(path)

    def func():
        text = filename_e.text()
        _filter = "*.csv" if text.endswith(".csv") else "*.json" if text.endswith(".json") else None
        p, __ = QFileDialog.getSaveFileName(None, select_msg, text, _filter)
        if p:
            filename_e.setText(p)

    button = QPushButton(_('File'))
    button.clicked.connect(func)
    hbox.addWidget(button)
    hbox.addWidget(filename_e)
    vbox.addLayout(hbox)

    def set_csv(v):
        text = filename_e.text()
        text = text.replace(".json",".csv") if v else text.replace(".csv",".json")
        filename_e.setText(text)

    b1.clicked.connect(lambda: set_csv(True))
    b2.clicked.connect(lambda: set_csv(False))

    return vbox, filename_e, b1
def show_transaction(tx, parent, desc=None, prompt_if_unsaved=False):
    try:
        d = TxDialog(tx, parent, desc, prompt_if_unsaved)
    except SerializationError as e:
        traceback.print_exc(file=sys.stderr)
        parent.show_critical(
            _("Sparks-Electrum was unable to deserialize the transaction:") +
            "\n" + str(e))
    else:
        dialogs.append(d)
        d.show()
Exemple #22
0
 def file_input(self):
     fileName, __ = QFileDialog.getOpenFileName(self, 'select file')
     if not fileName:
         return
     try:
         with open(fileName, "r") as f:
             data = f.read()
     except BaseException as e:
         self.show_error(_('Error opening file') + ':\n' + str(e))
     else:
         self.setText(data)
Exemple #23
0
    def receive_menu(self, menu, addrs, wallet):
        if type(wallet) is not Standard_Wallet:
            return
        keystore = wallet.get_keystore()
        if type(keystore) == self.keystore_class and len(addrs) == 1:

            def show_address():
                keystore.thread.add(
                    partial(self.show_address, wallet, addrs[0]))

            menu.addAction(_("Show on Ledger"), show_address)
Exemple #24
0
 def init_network(self, network):
     message = _("Sparks-Electrum communicates with remote servers to get "
               "information about your transactions and addresses. The "
               "servers all fulfill the same purpose only differing in "
               "hardware. In most cases you simply want to let Sparks-Electrum "
               "pick one at random.  However if you prefer feel free to "
               "select a server manually.")
     choices = [_("Auto connect"), _("Select server manually")]
     title = _("How do you want to connect to a server? ")
     clayout = ChoicesLayout(message, choices)
     self.back_button.setText(_('Cancel'))
     self.exec_layout(clayout.layout(), title)
     r = clayout.selected_index()
     if r == 1:
         nlayout = NetworkChoiceLayout(network, self.config, wizard=True)
         if self.exec_layout(nlayout.layout()):
             nlayout.accept()
     else:
         network.auto_connect = True
         self.config.set_key('auto_connect', True, True)
    def set_mapper_index(self, row):
        """Set the row that the data widget mapper should use."""
        self.valid_outputs_list.clear()
        self.status_edit.clear()
        self.status_edit.setStyleSheet(
            util.ColorScheme.DEFAULT.as_stylesheet())
        self.mapper.setCurrentIndex(row)
        mn = self.dialog.masternodes_widget.masternode_for_row(row)

        status_text = _('Masternode has no collateral payment assigned.')
        can_scan = not mn.announced
        # Disable the scan_outputs button if the masternode already has an assigned output.
        if mn.vin.get('value', 0) == COIN * 1000:
            can_scan = False
            self.valid_outputs_list.add_output(mn.vin)
            status_text = _('Masternode already has a collateral payment.')

        self.status_edit.setText(_(status_text))

        self.scan_outputs_button.setEnabled(can_scan)
Exemple #26
0
 def show_address(self, wallet, address, keystore=None):
     if keystore is None:
         keystore = wallet.get_keystore()
     if not self.show_address_helper(wallet, address, keystore):
         return
     if type(wallet) is not Standard_Wallet:
         keystore.handler.show_error(_('This function is only available for standard wallets when using {}.').format(self.device))
         return
     sequence = wallet.get_address_index(address)
     txin_type = wallet.get_txin_type(address)
     keystore.show_address(sequence, txin_type)
Exemple #27
0
    def add_show_address_on_hw_device_button_for_receive_addr(
            self, wallet, keystore, main_window):
        plugin = keystore.plugin
        receive_address_e = main_window.receive_address_e

        def show_address():
            addr = receive_address_e.text()
            keystore.thread.add(
                partial(plugin.show_address, wallet, addr, keystore))

        receive_address_e.addButton(":icons/eye1.png", show_address,
                                    _("Show on {}").format(plugin.device))
Exemple #28
0
 def __init__(self, parent, message, task, on_success=None, on_error=None):
     assert parent
     if isinstance(parent, MessageBoxMixin):
         parent = parent.top_level_window()
     WindowModalDialog.__init__(self, parent, _("Please wait"))
     vbox = QVBoxLayout(self)
     vbox.addWidget(QLabel(message))
     self.accepted.connect(self.on_accepted)
     self.show()
     self.thread = TaskThread(self)
     self.thread.finished.connect(self.deleteLater)  # see #3956
     self.thread.add(task, on_success, self.accept, on_error)
Exemple #29
0
 def create_menu(self, position):
     menu = QMenu()
     item = self.itemAt(position)
     if not item:
         return
     key = item.data(0, Qt.UserRole)
     column = self.currentColumn()
     column_title = self.headerItem().text(column)
     column_data = item.text(column)
     pr = self.parent.invoices.get(key)
     status = self.parent.invoices.get_status(key)
     if column_data:
         menu.addAction(
             _("Copy {}").format(column_title),
             lambda: self.parent.app.clipboard().setText(column_data))
     menu.addAction(_("Details"), lambda: self.parent.show_invoice(key))
     if status == PR_UNPAID:
         menu.addAction(_("Pay Now"),
                        lambda: self.parent.do_pay_invoice(key))
     menu.addAction(_("Delete"), lambda: self.parent.delete_invoice(key))
     menu.exec_(self.viewport().mapToGlobal(position))
Exemple #30
0
 def calibration(self):
     img = QImage(self.size[0], self.size[1], QImage.Format_Mono)
     bitmap = QBitmap.fromImage(img, Qt.MonoOnly)
     bitmap.fill(Qt.black)
     self.make_calnoise()
     img = self.overlay_marks(
         self.calnoise.scaledToHeight(self.f_size.height()), False, True)
     self.calibration_pdf(img)
     QDesktopServices.openUrl(
         QUrl.fromLocalFile(
             os.path.abspath(self.base_dir + _('calibration') + '.pdf')))
     return img