def on_view_blacklist(self, ignored):
        ''' The 'view ban list...' link leads to a modal dialog box where the
        user has the option to clear the entire blacklist. Build that dialog here. '''
        bl = sorted(self.network.blacklisted_servers)
        parent = self.parent()
        if not bl:
            parent.show_error(_("Server ban list is empty!"))
            return
        d = WindowModalDialog(parent.top_level_window(), _("Banned Servers"))
        vbox = QVBoxLayout(d)
        vbox.addWidget(QLabel(_("Banned Servers") + " ({})".format(len(bl))))
        tree = QTreeWidget()
        tree.setHeaderLabels([_('Host'), _('Port')])
        for s in bl:
            host, port, protocol = deserialize_server(s)
            item = QTreeWidgetItem([host, str(port)])
            item.setFlags(Qt.ItemIsEnabled)
            tree.addTopLevelItem(item)
        tree.setIndentation(3)
        h = tree.header()
        h.setStretchLastSection(False)
        h.setSectionResizeMode(0, QHeaderView.Stretch)
        h.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        vbox.addWidget(tree)

        clear_but = QPushButton(_("Clear ban list"))
        weakSelf = Weak.ref(self)
        weakD = Weak.ref(d)
        clear_but.clicked.connect(lambda: weakSelf() and weakSelf().
                                  on_clear_blacklist() and weakD().reject())
        vbox.addLayout(Buttons(clear_but, CloseButton(d)))
        d.exec_()
Exemplo n.º 2
0
 def __init__(self, parent, on_error=None, *, name=None):
     QThread.__init__(self, parent)
     if name is not None:
         self.setObjectName(name)
     self.on_error = on_error
     self.tasks = queue.Queue()
     self.doneSig.connect(self.on_done)
     Weak.finalization_print_error(self)  # track task thread lifecycle in debug log
     self.start()
Exemplo n.º 3
0
 def __init__(self, plugin, window):
     super().__init__()  # top-level QObject, no parent()
     self.server = TimeoutServerProxy('http://%s:%d' % (HOST, PORT),
                                      allow_none=True,
                                      timeout=2.0)
     self.listener = Listener(self)
     self.plugin_ref = Weak.ref(plugin)
     self.window_ref = Weak.ref(window)
     self.cosigner_receive_signal.connect(self.on_receive)
Exemplo n.º 4
0
 def _cache_password(self, wallet, password):
     self._expire_cached_password(wallet)
     if password is None:
         return
     timer = QTimer()  # NB a top-level parentless QObject will get delete by Python when its Python refct goes to 0, which is what we want here. Future programmers: Do not give this timer a parent!
     self._wallet_password_cache[wallet] = (password, timer)
     weakWallet = Weak.ref(wallet)
     weakSelf = Weak.ref(self)
     def timeout():
         slf = weakSelf()
         slf and slf._expire_cached_password(weakWallet)
     timer.setSingleShot(True); timer.timeout.connect(timeout); timer.start(10000)  # 10 sec
Exemplo n.º 5
0
    def __init__(self):
        super().__init__(
        )  # Top-level window. Parent needs to hold a reference to us and clean us up appropriately.
        self.setWindowTitle('Electron Cash - ' + _('Payment Request'))
        self.label = ''
        self.amount = 0
        self.setFocusPolicy(Qt.NoFocus)
        self.setSizePolicy(QSizePolicy.MinimumExpanding,
                           QSizePolicy.MinimumExpanding)

        main_box = QHBoxLayout(self)
        main_box.setContentsMargins(12, 12, 12, 12)
        self.qrw = QRCodeWidget()
        self.qrw.setSizePolicy(QSizePolicy.MinimumExpanding,
                               QSizePolicy.MinimumExpanding)
        main_box.addWidget(self.qrw, 2)

        vbox = QVBoxLayout()
        vbox.setContentsMargins(12, 12, 12, 12)
        main_box.addLayout(vbox, 2)
        main_box.addStretch(1)

        self.address_label = WWLabel()
        self.address_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(self.address_label)

        self.msg_label = WWLabel()
        self.msg_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(self.msg_label)

        self.amount_label = WWLabel()
        self.amount_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(self.amount_label)

        self.op_return_label = WWLabel()
        self.op_return_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
        vbox.addWidget(self.op_return_label)

        vbox.addStretch(2)

        copyBut = QPushButton(_("Copy QR Image"))
        saveBut = QPushButton(_("Save QR Image"))
        vbox.addLayout(Buttons(copyBut, saveBut))

        weakSelf = Weak.ref(
            self
        )  # Qt & Python GC hygeine: don't hold references to self in non-method slots as it appears Qt+Python GC don't like this too much and may leak memory in that case.
        weakQ = Weak.ref(self.qrw)
        weakBut = Weak.ref(copyBut)
        copyBut.clicked.connect(lambda: copy_to_clipboard(weakQ(), weakBut()))
        saveBut.clicked.connect(lambda: save_to_file(weakQ(), weakSelf()))
Exemplo n.º 6
0
    def settings_dialog(self, windowRef):
        window = windowRef(
        )  # NB: window is the internal plugins dialog and not the wallet window
        if not window or not isinstance(window_parent(window), ElectrumWindow):
            return
        wallet = window_parent(window).wallet
        d = WindowModalDialog(window.top_level_window(), _("Label Settings"))
        d.ok_button = OkButton(d)
        dlgRef = Weak.ref(d)
        if wallet in self.wallets:

            class MySigs(QObject):
                ok_button_disable_sig = pyqtSignal(bool)

            d.sigs = MySigs(d)
            d.sigs.ok_button_disable_sig.connect(
                d.ok_button.setDisabled
            )  # disable ok button while the TaskThread runs ..
            hbox = QHBoxLayout()
            hbox.addWidget(QLabel(_("LabelSync options:")))
            upload = ThreadedButton(
                "Force upload",
                partial(Weak(self.do_force_upload), wallet, dlgRef),
                partial(Weak(self.done_processing), dlgRef),
                partial(Weak(self.error_processing), dlgRef))
            download = ThreadedButton(
                "Force download",
                partial(Weak(self.do_force_download), wallet, dlgRef),
                partial(Weak(self.done_processing), dlgRef),
                partial(Weak(self.error_processing), dlgRef))
            d.thread_buts = (upload, download)
            d.finished.connect(partial(Weak(self.on_dlg_finished), dlgRef))
            vbox = QVBoxLayout()
            vbox.addWidget(upload)
            vbox.addWidget(download)
            hbox.addLayout(vbox)
            vbox = QVBoxLayout(d)
            vbox.addLayout(hbox)
        else:
            vbox = QVBoxLayout(d)
            if wallet.network:
                # has network, so the fact that the wallet isn't in the list means it's incompatible
                l = QLabel('<b>' +
                           _("LabelSync not supported for this wallet type") +
                           '</b>')
                l.setAlignment(Qt.AlignCenter)
                vbox.addWidget(l)
                l = QLabel(_("(Only deterministic wallets are supported)"))
                l.setAlignment(Qt.AlignCenter)
                vbox.addWidget(l)
            else:
                # Does not have network, so we won't speak of incompatibility, but instead remind user offline mode means OFFLINE! ;)
                l = QLabel(
                    _("You are using Electron Cash in offline mode; restart Electron Cash if you want to get connected"
                      ))
                l.setWordWrap(True)
                vbox.addWidget(l)
        vbox.addSpacing(20)
        vbox.addLayout(Buttons(d.ok_button))
        return bool(d.exec_())
Exemplo n.º 7
0
 def init_qt(self, gui):
     if self.initted: return  # already initted
     self.print_error("Initializing...")
     for window in gui.windows:
         self.on_new_window(window)
     Plugin.Instance_ref = Weak.ref(self)
     self.initted = True
Exemplo n.º 8
0
 def __init__(self, rate, obj, func):
     # note: obj here is really the __class__ of the obj because we prepended the class in our custom invoke() above.
     super().__init__(rate, obj, func)
     self.func_target = func
     self.func = self._call_func_for_all
     self.saved_args = Weak.KeyDictionary(
     )  # we don't use a simple arg tuple, but instead an instance -> args,kwargs dictionary to store collated calls, per instance collated
Exemplo n.º 9
0
 def __init__(self, rate, obj, func):
     self.n = func.__name__
     self.qn = func.__qualname__
     self.rate = rate
     self.obj = Weak.ref(
         obj)  # keep a weak reference to the object to prevent cycles
     self.func = func
Exemplo n.º 10
0
 def update(self):
     # Defer updates if editing
     if self.editor:
         self.pending_update = True
     else:
         # Deferred update mode won't actually update the GUI if it's
         # not on-screen, and will instead update it the next time it is
         # shown.  This has been found to radically speed up large wallets
         # on initial synch or when new TX's arrive.
         if self.should_defer_update_incr():
             return
         self.setUpdatesEnabled(False)
         scroll_pos_val = self.verticalScrollBar().value() # save previous scroll bar position
         self.on_update()
         self.deferred_update_ct = 0
         weakSelf = Weak.ref(self)
         def restoreScrollBar():
             slf = weakSelf()
             if slf:
                 slf.updateGeometry()
                 slf.verticalScrollBar().setValue(scroll_pos_val) # restore scroll bar to previous
                 slf.setUpdatesEnabled(True)
         QTimer.singleShot(0, restoreScrollBar) # need to do this from a timer some time later due to Qt quirks
     if self.current_filter:
         self.filter(self.current_filter)
Exemplo n.º 11
0
 def settings_widget(self, window):
     while window and window_parent(window) and not isinstance(window_parent(window), ElectrumWindow):
         # MacOS fixup -- find window.parent() because we can end up with window.parent() not an ElectrumWindow
         window = window_parent(window)
     windowRef = Weak.ref(window)
     return EnterButton(_('Settings'),
                        partial(self.settings_dialog, windowRef))
Exemplo n.º 12
0
    def __init__(self, parent, tab):
        MyTreeWidget.__init__(self,
                              parent,
                              self.create_menu, [
                                  _('Address'),
                                  _('Amount'),
                              ],
                              stretch_column=0,
                              deferred_updates=True)
        self.tab = Weak.ref(tab)
        self.main_window = parent
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSortingEnabled(False)
        self.sending = None
        self.update_sig.connect(self.update)
        self.monospace_font = QFont(MONOSPACE_FONT)

        self.italic_font = QFont()
        self.italic_font.setItalic(True)
        self.loaded_icon = self._get_loaded_icon()
        self.collected_icon = self._get_collected_icon()
        self.wallet = tab.wallet
        self.balances = dict()
        self.balances_batch = dict()
        self.synch_event = threading.Event()
        lock = threading.Lock()
        self.synch = threading.Thread(target=self.synchronize,
                                      daemon=True,
                                      args=(
                                          self.synch_event,
                                          lock,
                                      ))
        self.synch.start()
Exemplo n.º 13
0
 def transaction_dialog(self, d):
     window, state = self._find_window_and_state_for_wallet(d.wallet)
     if window and state:
         d.cosigner_send_button = b = QPushButton(_("Send to cosigner"))
         b.wallet_ref = Weak.ref(window.wallet)
         b.clicked.connect(lambda: Plugin.do_send_static(d))
         d.buttons.insert(0, b)
         self.transaction_dialog_update(d)
Exemplo n.º 14
0
 def __init__(self, state):
     super().__init__()
     self.daemon = True
     self.state_ref = Weak.ref(state)
     self.received = set()
     self.keyhashes = []
     self.timeoutQ = queue.Queue(
     )  # this queue's sole purpose is to provide an interruptible sleep
Exemplo n.º 15
0
    def initiate_fetch_input_data(self, force):
        weakSelfRef = Weak.ref(self)

        def dl_prog(pct):
            slf = weakSelfRef()
            if slf:
                slf._dl_pct = pct
                slf.throttled_update_sig.emit()

        def dl_done():
            slf = weakSelfRef()
            if slf:
                slf._dl_pct = None
                slf.throttled_update_sig.emit()
                slf.dl_done_sig.emit()

        dl_retries = 0

        def dl_done_mainthread():
            nonlocal dl_retries
            slf = weakSelfRef()
            if slf:
                if slf._closed:
                    return
                dl_retries += 1
                fee = slf.try_calculate_fee()
                if fee is None and dl_retries < 2:
                    if not self.is_fetch_input_data():
                        slf.print_error(
                            "input fetch incomplete; network use is disabled in GUI"
                        )
                        return
                    # retry at most once -- in case a slow server scrwed us up
                    slf.print_error(
                        "input fetch appears incomplete; retrying download once ..."
                    )
                    slf.tx.fetch_input_data(
                        self.wallet,
                        done_callback=dl_done,
                        prog_callback=dl_prog,
                        force=True,
                        use_network=self.is_fetch_input_data(
                        ))  # in this case we reallly do force
                elif fee is not None:
                    slf.print_error("input fetch success")
                else:
                    slf.print_error("input fetch failed")

        try:
            self.dl_done_sig.disconnect()  # disconnect previous
        except TypeError:
            pass
        self.dl_done_sig.connect(dl_done_mainthread, Qt.QueuedConnection)
        self.tx.fetch_input_data(self.wallet,
                                 done_callback=dl_done,
                                 prog_callback=dl_prog,
                                 force=force,
                                 use_network=self.is_fetch_input_data())
 def transfer(self):
     self.show_message(
         _("You should not use either wallet during the transfer. Leave Electron Cash active. "
           "The plugin ceases operation and will have to be re-activated if Electron Cash "
           "is stopped during the operation."))
     self.storage = WalletStorage(self.file)
     self.storage.set_password(self.tmp_pass, encrypt=True)
     self.storage.put('keystore', self.keystore.dump())
     self.recipient_wallet = Standard_Wallet(self.storage)
     self.recipient_wallet.start_threads(self.network)
     # comment the below out if you want to disable auto-clean of temp file
     # otherwise the temp file will be auto-cleaned on app exit or
     # on the recepient_wallet object's destruction (when refct drops to 0)
     Weak.finalize(self.recipient_wallet, self.delete_temp_wallet_file,
                   self.file)
     self.plugin.switch_to(Transfer,
                           self.wallet_name, self.recipient_wallet,
                           float(self.time_e.text()), self.password)
Exemplo n.º 17
0
 def __init__(self, config, daemon, plugins):
     super(__class__, self).__init__() # QObject init
     assert __class__.instance is None, "ElectrumGui is a singleton, yet an instance appears to already exist! FIXME!"
     __class__.instance = self
     set_language(config.get('language'))
     # Uncomment this call to verify objects are being properly
     # GC-ed when windows are closed
     #if daemon.network:
     #    from electroncash.util import DebugMem
     #    from electroncash.wallet import Abstract_Wallet
     #    from electroncash.verifier import SPV
     #    from electroncash.synchronizer import Synchronizer
     #    daemon.network.add_jobs([DebugMem([Abstract_Wallet, SPV, Synchronizer,
     #                                       ElectrumWindow], interval=5)])
     QCoreApplication.setAttribute(Qt.AA_X11InitThreads)
     if hasattr(Qt, "AA_ShareOpenGLContexts"):
         QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts)
     if hasattr(QGuiApplication, 'setDesktopFileName'):
         QGuiApplication.setDesktopFileName('electron-cash.desktop')
     self.config = config
     self.daemon = daemon
     self.plugins = plugins
     self.windows = []
     self.app = QApplication(sys.argv)
     self._set_icon()
     self.app.installEventFilter(self)
     self.timer = QTimer(self); self.timer.setSingleShot(False); self.timer.setInterval(500) #msec
     self.gc_timer = QTimer(self); self.gc_timer.setSingleShot(True); self.gc_timer.timeout.connect(ElectrumGui.gc); self.gc_timer.setInterval(500) #msec
     self.nd = None
     # Dark Theme -- ideally set this before any widgets are created.
     self.set_dark_theme_if_needed()
     # /
     # Wallet Password Cache
     # wallet -> (password, QTimer) map for some plugins (like CashShuffle)
     # that need wallet passwords to operate, and we don't want to prompt
     # for pw twice right after the InstallWizard runs (see #106).
     # Entries in this map are deleted after 10 seconds by the QTimer (which
     # also deletes itself)
     self._wallet_password_cache = Weak.KeyDictionary()
     # /
     self.update_checker = UpdateChecker()
     self.update_checker_timer = QTimer(self); self.update_checker_timer.timeout.connect(self.on_auto_update_timeout); self.update_checker_timer.setSingleShot(False)
     self.update_checker.got_new_version.connect(lambda x: self.show_update_checker(parent=None, skip_check=True))
     # init tray
     self.dark_icon = self.config.get("dark_icon", False)
     self.tray = QSystemTrayIcon(self.tray_icon(), self)
     self.tray.setToolTip('Electron Cash')
     self.tray.activated.connect(self.tray_activated)
     self.build_tray_menu()
     self.tray.show()
     self.new_window_signal.connect(self.start_new_window)
     if self.has_auto_update_check():
         self._start_auto_update_timer(first_run = True)
     run_hook('init_qt', self)
     # We did this once already in the set_dark_theme call, but we do this
     # again here just in case some plugin modified the color scheme.
     ColorScheme.update_from_widget(QWidget())
Exemplo n.º 18
0
 def on_focus_change(self, ignored, new_focus_widget):
     ''' Remember the last wallet window that was activated because
     start_new_window uses this information.  We store the ElectrumWindow
     in a weak reference so that we don't interfere with its gc when it is
     closed.'''
     if not new_focus_widget:
         return
     if isinstance(new_focus_widget, QWidget):
         window = QWidget.window(new_focus_widget)  # call base class because some widgets may actually override 'window' with Python attributes.
         if isinstance(window, ElectrumWindow):
             self._last_active_window = Weak.ref(window)
Exemplo n.º 19
0
 def __init__(self, config):
     super().__init__(None) # Top-level Object
     if Exception_Hook._instance: return # This is ok, we will be GC'd later.
     if not _is_enabled(config):
         print_error("[{}] Not installed due to user config.".format(__class__.__qualname__))
         return # self will get auto-gc'd
     Exception_Hook._instance = self # strong reference to self should keep us alive until uninstall() is called
     self.config = config
     sys.excepthook = self.handler # yet another strong reference. We really won't die unless uninstall() is called
     self._report_exception.connect(_show_window)
     print_error("[{}] Installed.".format(__class__.__qualname__))
     Exception_Hook._weak_instances.append(Weak.ref(self, Exception_Hook.finalized))
Exemplo n.º 20
0
 def create_window_for_wallet(self, wallet):
     w = ElectrumWindow(self, wallet)
     self.windows.append(w)
     dname = w.diagnostic_name()
     def onFinalized(wr,dname=dname):
         print_error("[{}] finalized".format(dname))
         self.weak_windows.remove(wr)
     self.weak_windows.append(Weak.ref(w,onFinalized))
     self.build_tray_menu()
     # FIXME: Remove in favour of the load_wallet hook
     run_hook('on_new_window', w)
     return w
Exemplo n.º 21
0
    def __init__(self, parent=None):
        super().__init__(parent, self.create_menu, [], 3, deferred_updates=True)
        self.refresh_headers()
        self.setColumnHidden(1, True)
        self.setSortingEnabled(True)
        self.sortByColumn(0, Qt.AscendingOrder)
        # force attributes to always be defined, even if None, at construction.
        self.wallet = self.parent.wallet

        self.monospaceFont = QFont(MONOSPACE_FONT)
        self.withdrawalBrush = QBrush(QColor("#BC1E1E"))
        self.invoiceIcon = QIcon(":icons/seal")
        self._item_cache = Weak.ValueDictionary()
Exemplo n.º 22
0
    def __init__(self, parent):
        super().__init__(parent, self.create_menu, [], 3, deferred_updates=True)
        self.refresh_headers()
        self.setColumnHidden(1, True)
        # force attributes to always be defined, even if None, at construction.
        self.wallet = self.parent.wallet
        self.cleaned_up = False

        self.monospaceFont = QFont(MONOSPACE_FONT)
        self.withdrawalBrush = QBrush(QColor("#BC1E1E"))
        self.invoiceIcon = QIcon(":icons/seal")
        self._item_cache = Weak.ValueDictionary()
        self.itemChanged.connect(self.item_changed)

        self.has_unknown_balances = False
Exemplo n.º 23
0
 def _setup_do_in_main_thread_handler(self):
     ''' Sets up "do_in_main_thread" handler mechanism for Qt GUI. '''
     self.do_in_main_thread_signal.connect(self._do_in_main_thread_handler_slot)
     orig_handler = Handlers.do_in_main_thread
     weakSelf = Weak.ref(self)
     def my_do_in_main_thread_handler(func, *args, **kwargs):
         strongSelf = weakSelf()
         if strongSelf:
             # We are still alive, emit the signal which will be handled
             # in the main thread.
             strongSelf.do_in_main_thread_signal.emit(func, args, kwargs)
         else:
             # We died. Uninstall this handler, invoke original handler.
             Handlers.do_in_main_thread = orig_handler
             orig_handler(func, *args, **kwargs)
     Handlers.do_in_main_thread = my_do_in_main_thread_handler
Exemplo n.º 24
0
 def _setup_save_sort_mechanism(self):
     if (self._save_sort_settings
             and isinstance(getattr(self.parent, 'wallet', None), Abstract_Wallet)):
         storage = self.parent.wallet.storage
         key = f'mytreewidget_default_sort_{type(self).__name__}'
         default = (storage and storage.get(key, None)) or self.default_sort
         if default and isinstance(default, (tuple, list)) and len(default) >= 2 and all(isinstance(i, int) for i in default):
             self.setSortingEnabled(True)
             self.sortByColumn(default[0], default[1])
         if storage:
             # Paranoia; hold a weak reference just in case subclass code
             # does unusual things.
             weakStorage = Weak.ref(storage)
             def save_sort(column, qt_sort_order):
                 storage = weakStorage()
                 if storage:
                     storage.put(key, [column, qt_sort_order])
             self.header().sortIndicatorChanged.connect(save_sort)
     elif self.default_sort:
         self.setSortingEnabled(True)
         self.sortByColumn(self.default_sort[0], self.default_sort[1])
 def __init__(self, parent, tab):
     MyTreeWidget.__init__(self,
                           parent,
                           self.create_menu, [
                               _('Address'),
                               _('Amount'),
                               _('Time'),
                               _('When'),
                               _('Status'),
                           ],
                           stretch_column=3,
                           deferred_updates=True)
     self.tab = Weak.ref(tab)
     self.t0 = time.time()
     self.t0_last = None
     self._recalc_times(tab.times)
     self.print_error("transferring utxo")
     self.utxos = list(tab.utxos)
     self.main_window = parent
     self.setSelectionMode(QAbstractItemView.NoSelection)
     self.setSortingEnabled(False)
     self.sent_utxos = dict()
     self.failed_utxos = dict()
     self.sending = None
     self.check_icon = self._get_check_icon()
     self.fail_icon = self._get_fail_icon()
     self.update_sig.connect(self.update)
     self.monospace_font = QFont(MONOSPACE_FONT)
     self.italic_font = QFont()
     self.italic_font.setItalic(True)
     self.timer = QTimer(self)
     self.timer.setSingleShot(False)
     self.timer.timeout.connect(self.update_sig)
     self.timer.start(
         2000
     )  # update every 2 seconds since the granularity of our "When" column is ~5 seconds
     self.wallet = tab.recipient_wallet
Exemplo n.º 26
0
    def __init__(self, parent, plugin, wallet_name, password=None):
        QDialog.__init__(self, parent)
        self.main_window = parent
        self.password = password
        self.wallet = parent.wallet
        self.plugin = plugin
        self.network = parent.network
        self.wallet_name = wallet_name
        self.batch_label = "BitcoinBiletoj1"
        self.template_file = ''
        self.working_directory = self.wallet.storage.get("bileto_path")
        if self.working_directory:
            if not os.path.exists(self.working_directory):
                self.working_directory = None
        self.number = 0
        self.times = 1
        self.public_key = ''
        for x in range(10):
            name = 'tmp_wo_wallet' + ''.join(
                random.choices(string.ascii_letters + string.digits, k=10))
            self.file = os.path.join(tempfile.gettempdir(), name)
            if not os.path.exists(self.file):
                break
        else:
            raise RuntimeError(
                'Could not find a unique temp file in tmp directory',
                tempfile.gettempdir())
        self.tmp_pass = ''.join(
            random.choices(string.ascii_uppercase + string.digits, k=10))

        from electroncash import mnemonic
        seed = mnemonic.Mnemonic('en').make_seed('standard')
        self.keystore = keystore.from_seed(seed, self.tmp_pass, False)
        self.storage = WalletStorage(self.file)
        self.storage.set_password(self.tmp_pass, encrypt=True)
        self.storage.put('keystore', self.keystore.dump())
        self.recipient_wallet = Standard_Wallet(self.storage)
        self.recipient_wallet.start_threads(self.network)
        Weak.finalize(self.recipient_wallet, self.delete_temp_wallet_file,
                      self.file)
        vbox = QVBoxLayout()
        self.setLayout(vbox)
        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        l = QLabel("<b>%s</b>" % (_("Bitcoin Bileto")))
        hbox.addStretch(1)
        hbox.addWidget(l)
        hbox.addStretch(1)
        vbox.addWidget(QLabel("Working directory:"))
        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        self.wd_label = QLabel(self.working_directory)
        hbox.addWidget(self.wd_label)
        b = QPushButton("Set")
        b.clicked.connect(lambda: self.plugin.settings_dialog(
            self, self.settings_updated_signal))
        self.settings_updated_signal.connect(self.on_settings_updated)
        hbox.addWidget(b)
        data = "prywatny klucz do portfela"
        self.qrw_priv = QRCodeWidget(data)
        self.qrw_add = QRCodeWidget(data)

        self.batch_label_wid = QLineEdit()
        self.batch_label_wid.setPlaceholderText(
            _("Bitcoin biletoj batch label"))
        self.batch_label_wid.textEdited.connect(self.batch_info_changed)
        vbox.addWidget(self.batch_label_wid)

        grid = QGridLayout()
        vbox.addLayout(grid)
        self.number_wid = QLineEdit()
        self.number_wid.setPlaceholderText(_("Number of biletoj"))
        self.number_wid.textEdited.connect(self.batch_info_changed)
        self.times_wid = QLineEdit()
        self.times_wid.textEdited.connect(self.batch_info_changed)
        self.times_wid.setText("1")
        hbox = QHBoxLayout()
        vbox.addLayout(hbox)
        hbox.addWidget(self.number_wid)
        #hbox.addWidget(QLabel("x"))
        #hbox.addWidget(self.times_wid)
        hbox.addStretch(1)
        self.times_wid.setMaximumWidth(120)
        self.number_wid.setMaximumWidth(140)
        self.only_qrcodes_checkbox = QCheckBox("Only make QR codes.")
        self.only_qrcodes_checkbox.stateChanged.connect(
            self.batch_info_changed)
        self.encrypt_checkbox = QCheckBox("Encrypt Batch.")
        vbox.addWidget(self.encrypt_checkbox)
        vbox.addWidget(self.only_qrcodes_checkbox)
        #b = QPushButton(_("Load .tex template"))
        #b.clicked.connect(self.load_template)
        #b.setMaximumWidth(130)
        #grid.addWidget(b, 0, 0)
        #self.template_path_label_wid = QLabel('set path')
        #grid.addWidget(self.template_path_label_wid, 0, 1)
        self.public_key_wid = QLineEdit()
        self.public_key_wid.setPlaceholderText(
            _("Public Key") + _(" for encryption"))
        self.public_key_wid.textEdited.connect(self.batch_info_changed)
        #vbox.addWidget(self.public_key_wid)
        self.b = QPushButton(_("Generate biletoj"))
        self.b.clicked.connect(self.generate_biletoj)
        self.prog_bar = QProgressBar()
        self.prog_bar.setVisible(False)
        vbox.addWidget(self.b)
        vbox.addWidget(self.prog_bar)
        self.b.setDisabled(True)
        vbox.addStretch(1)
Exemplo n.º 27
0
class Plugin(LabelsPlugin):

    def __init__(self, *args):
        LabelsPlugin.__init__(self, *args)
        self.obj = LabelsSignalObject()
        self.wallet_windows = {}
        self.initted = False

    def requires_settings(self):
        return True

    def settings_widget(self, window):
        while window and window_parent(window) and not isinstance(window_parent(window), ElectrumWindow):
            # MacOS fixup -- find window.parent() because we can end up with window.parent() not an ElectrumWindow
            window = window_parent(window)
        windowRef = Weak.ref(window)
        return EnterButton(_('Settings'),
                           partial(self.settings_dialog, windowRef))

    def settings_dialog(self, windowRef):
        window = windowRef() # NB: window is the internal plugins dialog and not the wallet window
        if not window or not isinstance(window_parent(window), ElectrumWindow): return
        wallet = window_parent(window).wallet
        d = WindowModalDialog(window.top_level_window(), _("Label Settings"))
        d.ok_button = OkButton(d)
        dlgRef = Weak.ref(d)
        if wallet in self.wallets:
            class MySigs(QObject):
                ok_button_disable_sig = pyqtSignal(bool)
            d.sigs = MySigs(d)
            d.sigs.ok_button_disable_sig.connect(d.ok_button.setDisabled) # disable ok button while the TaskThread runs ..
            hbox = QtWidgets.QHBoxLayout()
            hbox.addWidget(QtWidgets.QLabel(_("LabelSync options:")))
            upload = ThreadedButton(_("Force upload"),
                                    partial(Weak(self.do_force_upload), wallet, dlgRef),
                                    partial(Weak(self.done_processing), dlgRef),
                                    partial(Weak(self.error_processing), dlgRef))
            download = ThreadedButton(_("Force download"),
                                      partial(Weak(self.do_force_download), wallet, dlgRef),
                                      partial(Weak(self.done_processing), dlgRef),
                                      partial(Weak(self.error_processing), dlgRef))
            d.thread_buts = (upload, download)
            d.finished.connect(partial(Weak(self.on_dlg_finished), dlgRef))
            vbox = QtWidgets.QVBoxLayout()
            vbox.addWidget(upload)
            vbox.addWidget(download)
            hbox.addLayout(vbox)
            vbox = QtWidgets.QVBoxLayout(d)
            vbox.addLayout(hbox)
        else:
            vbox = QtWidgets.QVBoxLayout(d)
            if wallet.network:
                # has network, so the fact that the wallet isn't in the list means it's incompatible
                l = QtWidgets.QLabel('<b>' + _("LabelSync not supported for this wallet type") + '</b>')
                l.setAlignment(Qt.AlignCenter)
                vbox.addWidget(l)
                l = QtWidgets.QLabel(_("(Only deterministic wallets are supported)"))
                l.setAlignment(Qt.AlignCenter)
                vbox.addWidget(l)
            else:
                # Does not have network, so we won't speak of incompatibility, but instead remind user offline mode means OFFLINE! ;)
                l = QtWidgets.QLabel(_(f"You are using {PROJECT_NAME} in offline mode;"
                             f" restart Electron Cash if you want to get "
                             f"connected"))
                l.setWordWrap(True)
                vbox.addWidget(l)
        vbox.addSpacing(20)
        vbox.addLayout(Buttons(d.ok_button))
        return bool(d.exec_())

    def on_dlg_finished(self, dlgRef, result_code):
        ''' Wait for any threaded buttons that may be still extant so we don't get a crash '''
        #self.print_error("Dialog finished with code", result_code)
        dlg = dlgRef()
        if dlg:
            upload, download = dlg.thread_buts
            if upload.thread and upload.thread.isRunning():
                upload.thread.stop(); upload.thread.wait()
            if download.thread and download.thread.isRunning():
                download.thread.stop(); download.thread.wait()

    def do_force_upload(self, wallet, dlgRef):
        # this runs in a NON-GUI thread
        dlg = dlgRef()
        if dlg: dlg.sigs.ok_button_disable_sig.emit(True) # block window closing prematurely which can cause a temporary hang until thread completes
        self.push_thread(wallet)

    def do_force_download(self, wallet, dlgRef):
        # this runs in a NON-GUI thread
        dlg = dlgRef()
        if dlg: dlg.sigs.ok_button_disable_sig.emit(True) # block window closing prematurely which can cause a temporary hang until thread completes
        self.pull_thread(wallet, True)

    def done_processing(self, dlgRef, result):
        # this runs in the GUI thread
        dlg = dlgRef()
        if dlg:
            dlg.ok_button.setEnabled(True)
            self._ok_synched(dlg)

    def _ok_synched(self, window):
        if window.isVisible():
            window.show_message(_("Your labels have been synchronised."))

    def error_processing(self, dlgRef, exc_info):
        dlg = dlgRef()
        if dlg:
            dlg.ok_button.setEnabled(True)
            self._notok_synch(dlg, exc_info)

    _warn_dlg_flg = Weak.KeyDictionary()
    def _notok_synch(self, window, exc_info):
        # Runs in main thread
        cls = __class__
        if window.isVisible() and not cls._warn_dlg_flg.get(window, False):
            # Guard against duplicate error dialogs (without this we may get error window spam when importing labels)
            cls._warn_dlg_flg[window] = True
            window.show_warning(_("LabelSync error:") + "\n\n" + str(exc_info[1]), rich_text=False)
            cls._warn_dlg_flg.pop(window, None)

    def on_request_exception(self, wallet, exc_info):
        # not main thread
        self.obj.request_exception_signal.emit(wallet, exc_info)

    def request_exception_slot(self, wallet, exc_info):
        # main thread
        window = self.wallet_windows.get(wallet, None)
        if window: self._notok_synch(window, exc_info)

    def start_wallet(self, wallet, window=None):
        ret = super().start_wallet(wallet)
        if ret and window:
            self.wallet_windows[wallet] = window
        return ret

    def stop_wallet(self, wallet):
        ret = super().stop_wallet(wallet)
        window = self.wallet_windows.pop(wallet, None)
        return ret

    def on_pulled(self, wallet):
        # not main thread
        super().on_pulled(wallet) # super just logs to print_error
        self.obj.labels_changed_signal.emit(wallet)

    def on_labels_changed(self, wallet):
        # main thread
        window = self.wallet_windows.get(wallet, None)
        if window:
            #self.print_error("On labels changed", wallet.basename())
            window.update_labels()

    def on_wallet_not_synched(self, wallet):
        # not main thread
        self.obj.wallet_not_synched_signal.emit(wallet)

    def wallet_not_synched_slot(self, wallet):
        # main thread
        window = self.wallet_windows.get(wallet, None)
        if window:
            if window.question(_("LabelSync detected that this wallet is not synched with the label server.")
                               + "\n\n" + _("Synchronize now?")):
                WaitingDialog(window, _("Synchronizing..."),
                              partial(self.pull_thread, wallet, True),
                              lambda *args: self._ok_synched(window),
                              lambda exc: self._notok_synch(window, exc))

    def on_close(self):
        if not self.initted:
            return
        try: self.obj.labels_changed_signal.disconnect(self.on_labels_changed)
        except TypeError: pass # not connected
        try: self.obj.wallet_not_synched_signal.disconnect(self.wallet_not_synched_slot)
        except TypeError: pass # not connected
        try: self.obj.request_exception_signal.disconnect(self.request_exception_slot)
        except TypeError: pass # not connected
        super().on_close()
        assert 0==len(self.wallet_windows), "LabelSync still had extant wallet_windows!"
        self.initted = False

    @hook
    def on_new_window(self, window):
        return self.start_wallet(window.wallet, window)

    @hook
    def on_close_window(self, window):
        return self.stop_wallet(window.wallet)

    @hook
    def init_qt(self, gui):
        if self.initted:
            return
        self.on_init()
        # connect signals. this needs to happen first as below on_new_window depends on these being active
        self.obj.labels_changed_signal.connect(self.on_labels_changed)
        self.obj.wallet_not_synched_signal.connect(self.wallet_not_synched_slot)
        self.obj.request_exception_signal.connect(self.request_exception_slot)

        ct, ct2 = 0, 0
        for window in gui.windows:
            if self.on_new_window(window):
                ct2 += 1
            ct += 1

        self.initted = True
        self.print_error("Initialized (had {} extant windows, added {}).".format(ct,ct2))
Exemplo n.º 28
0
    def __init__(self, tx, parent, desc, prompt_if_unsaved):
        '''Transactions in the wallet will show their description.
        Pass desc to give a description for txs not yet in the wallet.
        '''
        # We want to be a top-level window
        QDialog.__init__(self, parent=None)
        # Take a copy; it might get updated in the main window by
        # e.g. the FX plugin.  If this happens during or after a long
        # sign operation the signatures are lost.
        self.tx = copy.deepcopy(tx)
        self.tx.deserialize()
        self.main_window = parent
        self.wallet = parent.wallet
        self.prompt_if_unsaved = prompt_if_unsaved
        self.saved = False
        self.desc = desc
        self.cashaddr_signal_slots = []
        self._dl_pct = None
        self._closed = False
        self.tx_height = None

        self.setMinimumWidth(750)
        self.setWindowTitle(_("Transaction"))

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        vbox.addWidget(QLabel(_("Transaction ID:")))
        self.tx_hash_e = ButtonsLineEdit()
        self.tx_hash_e.addCopyButton()
        weakSelfRef = Weak.ref(self)
        qr_show = lambda: weakSelfRef() and weakSelfRef(
        ).main_window.show_qrcode(str(weakSelfRef().tx_hash_e.text()),
                                  'Transaction ID',
                                  parent=weakSelfRef())
        icon = ":icons/qrcode_white.svg" if ColorScheme.dark_scheme else ":icons/qrcode.svg"
        self.tx_hash_e.addButton(icon, qr_show, _("Show as QR code"))
        self.tx_hash_e.setReadOnly(True)
        vbox.addWidget(self.tx_hash_e)
        self.tx_desc = QLabel()
        vbox.addWidget(self.tx_desc)
        self.status_label = QLabel()
        vbox.addWidget(self.status_label)
        self.date_label = QLabel()
        vbox.addWidget(self.date_label)
        self.amount_label = QLabel()
        vbox.addWidget(self.amount_label)
        self.size_label = QLabel()
        vbox.addWidget(self.size_label)
        self.fee_label = QLabel()
        vbox.addWidget(self.fee_label)

        for l in (self.tx_desc, self.status_label, self.date_label,
                  self.amount_label, self.size_label, self.fee_label):
            # make these labels selectable by mouse in case user wants to copy-paste things in tx dialog
            l.setTextInteractionFlags(l.textInteractionFlags()
                                      | Qt.TextSelectableByMouse)

        def open_be_url(link):
            if link:
                try:
                    kind, thing = link.split(':')
                    url = web.BE_URL(self.main_window.config, kind, thing)
                except:
                    url = None
                if url:
                    webopen(url)
                else:
                    self.show_error(
                        _('Unable to open in block explorer. Please be sure your block explorer is configured correctly in preferences.'
                          ))

        self.status_label.linkActivated.connect(open_be_url)

        self.add_io(vbox)

        self.sign_button = b = QPushButton(_("Sign"))
        b.clicked.connect(self.sign)

        self.broadcast_button = b = QPushButton(_("Broadcast"))
        b.clicked.connect(self.do_broadcast)

        self.save_button = b = QPushButton(_("Save"))
        b.clicked.connect(self.save)

        self.cancel_button = b = QPushButton(_("Close"))
        b.clicked.connect(self.close)
        b.setDefault(True)

        self.qr_button = b = QPushButton()
        b.setIcon(QIcon(icon))
        b.clicked.connect(self.show_qr)

        self.copy_button = CopyButton(
            lambda: str(weakSelfRef() and weakSelfRef().tx),
            callback=lambda: weakSelfRef() and weakSelfRef().show_message(
                _("Transaction raw hex copied to clipboard.")))

        # Action buttons
        self.buttons = [
            self.sign_button, self.broadcast_button, self.cancel_button
        ]
        # Transaction sharing buttons
        self.sharing_buttons = [
            self.copy_button, self.qr_button, self.save_button
        ]

        run_hook('transaction_dialog', self)

        hbox = QHBoxLayout()
        hbox.addLayout(Buttons(*self.sharing_buttons))
        hbox.addStretch(1)
        hbox.addLayout(Buttons(*self.buttons))
        vbox.addLayout(hbox)

        self.throttled_update_sig.connect(self.throttled_update,
                                          Qt.QueuedConnection)
        self.initiate_fetch_input_data(True)

        self.update()

        # connect slots so we update in realtime as blocks come in, etc
        parent.history_updated_signal.connect(self.update_tx_if_in_wallet)
        parent.labels_updated_signal.connect(self.update_tx_if_in_wallet)
        parent.network_signal.connect(self.got_verified_tx)
Exemplo n.º 29
0
    def __init__(self, parent, network, config, wizard=False):
        super().__init__(parent)
        self.network = network
        self.config = config
        self.protocol = None
        self.tor_proxy = None

        # tor detector
        self.td = TorDetector(self)
        self.td.found_proxy.connect(self.suggest_proxy)

        self.tabs = tabs = QTabWidget()
        server_tab = QWidget()
        weakTd = Weak.ref(self.td)

        class ProxyTab(QWidget):
            def showEvent(slf, e):
                super().showEvent(e)
                td = weakTd()
                if e.isAccepted() and td:
                    td.start(
                    )  # starts the tor detector when proxy_tab appears

            def hideEvent(slf, e):
                super().hideEvent(e)
                td = weakTd()
                if e.isAccepted() and td:
                    td.stop(
                    )  # stops the tor detector when proxy_tab disappears

        proxy_tab = ProxyTab()
        blockchain_tab = QWidget()
        slp_tab = QWidget()
        tabs.addTab(blockchain_tab, _('Overview'))
        tabs.addTab(server_tab, _('Server'))
        tabs.addTab(proxy_tab, _('Proxy'))
        tabs.addTab(slp_tab, _('Tokens'))

        if wizard:
            tabs.setCurrentIndex(1)

        # server tab
        grid = QGridLayout(server_tab)
        grid.setSpacing(8)

        self.server_host = QLineEdit()
        self.server_host.setFixedWidth(200)
        self.server_port = QLineEdit()
        self.server_port.setFixedWidth(60)
        self.ssl_cb = QCheckBox(_('Use SSL'))
        self.autoconnect_cb = QCheckBox(_('Select server automatically'))
        self.autoconnect_cb.setEnabled(
            self.config.is_modifiable('auto_connect'))

        weakSelf = Weak.ref(
            self
        )  # Qt/Python GC hygeine: avoid strong references to self in lambda slots.
        self.server_host.editingFinished.connect(
            lambda: weakSelf() and weakSelf().set_server(onion_hack=True))
        self.server_port.editingFinished.connect(
            lambda: weakSelf() and weakSelf().set_server(onion_hack=True))
        self.ssl_cb.clicked.connect(self.change_protocol)
        self.autoconnect_cb.clicked.connect(self.set_server)
        self.autoconnect_cb.clicked.connect(self.update)

        msg = ' '.join([
            _("If auto-connect is enabled, Electron Cash will always use a server that is on the longest blockchain."
              ),
            _("If it is disabled, you have to choose a server you want to use. Electron Cash will warn you if your server is lagging."
              )
        ])
        grid.addWidget(self.autoconnect_cb, 0, 0, 1, 3)
        grid.addWidget(HelpButton(msg), 0, 4)

        self.preferred_only_cb = QCheckBox(
            _("Connect only to preferred servers"))
        self.preferred_only_cb.setEnabled(
            self.config.is_modifiable('whitelist_servers_only'))
        self.preferred_only_cb.setToolTip(
            _("If enabled, restricts Electron Cash to connecting to servers only marked as 'preferred'."
              ))

        self.preferred_only_cb.clicked.connect(
            self.set_whitelisted_only
        )  # re-set the config key and notify network.py

        msg = '\n\n'.join([
            _("If 'Connect only to preferred servers' is enabled, Electron Cash will only connect to servers marked as 'preferred' servers ({})."
              ).format(ServerFlag.Symbol[ServerFlag.Preferred]),
            _("This feature was added in response to the potential for a malicious actor to deny service via launching many servers (aka a sybil attack)."
              ),
            _("If unsure, most of the time it's safe to leave this option disabled. However leaving it enabled is safer (if a little bit discouraging to new server operators wanting to populate their servers)."
              )
        ])
        grid.addWidget(self.preferred_only_cb, 1, 0, 1, 3)
        grid.addWidget(HelpButton(msg), 1, 4)

        grid.addWidget(self.ssl_cb, 2, 0, 1, 3)
        self.ssl_help = HelpButton(
            _('SSL is used to authenticate and encrypt your connections with the blockchain servers.'
              ) + "\n\n" +
            _('Due to potential security risks, you may only disable SSL when using a Tor Proxy.'
              ))
        grid.addWidget(self.ssl_help, 2, 4)

        grid.addWidget(QLabel(_('Server') + ':'), 3, 0)
        grid.addWidget(self.server_host, 3, 1, 1, 2)
        grid.addWidget(self.server_port, 3, 3)

        self.server_list_label = label = QLabel(
            '')  # will get set by self.update()
        grid.addWidget(label, 4, 0, 1, 5)
        self.servers_list = ServerListWidget(self)
        grid.addWidget(self.servers_list, 5, 0, 1, 5)
        self.legend_label = label = WWLabel(
            '')  # will get populated with the legend by self.update()
        label.setTextInteractionFlags(label.textInteractionFlags() & (
            ~Qt.TextSelectableByMouse))  # disable text selection by mouse here
        self.legend_label.linkActivated.connect(self.on_view_blacklist)
        grid.addWidget(label, 6, 0, 1, 4)
        msg = ' '.join([
            _("Preferred servers ({}) are servers you have designated as reliable and/or trustworthy."
              ).format(ServerFlag.Symbol[ServerFlag.Preferred]),
            _("Initially, the preferred list is the hard-coded list of known-good servers vetted by the Electron Cash developers."
              ),
            _("You can add or remove any server from this list and optionally elect to only connect to preferred servers."
              ), "\n\n" +
            _("Banned servers ({}) are servers deemed unreliable and/or untrustworthy, and so they will never be connected-to by Electron Cash."
              ).format(ServerFlag.Symbol[ServerFlag.Banned])
        ])
        grid.addWidget(HelpButton(msg), 6, 4)

        # Proxy tab
        grid = QGridLayout(proxy_tab)
        grid.setSpacing(8)

        # proxy setting
        self.proxy_cb = QCheckBox(_('Use proxy'))
        self.proxy_cb.clicked.connect(self.check_disable_proxy)
        self.proxy_cb.clicked.connect(self.set_proxy)

        self.proxy_mode = QComboBox()
        self.proxy_mode.addItems(['SOCKS4', 'SOCKS5', 'HTTP'])
        self.proxy_host = QLineEdit()
        self.proxy_host.setFixedWidth(200)
        self.proxy_port = QLineEdit()
        self.proxy_port.setFixedWidth(60)
        self.proxy_user = QLineEdit()
        self.proxy_user.setPlaceholderText(_("Proxy user"))
        self.proxy_password = QLineEdit()
        self.proxy_password.setPlaceholderText(_("Password"))
        self.proxy_password.setEchoMode(QLineEdit.Password)
        self.proxy_password.setFixedWidth(60)

        self.proxy_mode.currentIndexChanged.connect(self.set_proxy)
        self.proxy_host.editingFinished.connect(self.set_proxy)
        self.proxy_port.editingFinished.connect(self.set_proxy)
        self.proxy_user.editingFinished.connect(self.set_proxy)
        self.proxy_password.editingFinished.connect(self.set_proxy)

        self.proxy_mode.currentIndexChanged.connect(
            self.proxy_settings_changed)
        self.proxy_host.textEdited.connect(self.proxy_settings_changed)
        self.proxy_port.textEdited.connect(self.proxy_settings_changed)
        self.proxy_user.textEdited.connect(self.proxy_settings_changed)
        self.proxy_password.textEdited.connect(self.proxy_settings_changed)

        self.tor_cb = QCheckBox(_("Use Tor Proxy"))
        self.tor_cb.setIcon(QIcon(":icons/tor_logo.svg"))
        self.tor_cb.setEnabled(False)
        self.tor_cb.clicked.connect(self.use_tor_proxy)

        grid.addWidget(self.tor_cb, 1, 0, 1, 3)
        grid.addWidget(self.proxy_cb, 2, 0, 1, 3)
        grid.addWidget(
            HelpButton(
                _('Proxy settings apply to all connections: with Electron Cash servers, but also with third-party services.'
                  )), 2, 4)
        grid.addWidget(self.proxy_mode, 4, 1)
        grid.addWidget(self.proxy_host, 4, 2)
        grid.addWidget(self.proxy_port, 4, 3)
        grid.addWidget(self.proxy_user, 5, 2)
        grid.addWidget(self.proxy_password, 5, 3)
        grid.setRowStretch(7, 1)

        # SLP Validation Tab
        grid = QGridLayout(slp_tab)
        self.slpdb_cb = QCheckBox(
            _('Use SLPDB Graph Search to speed up validation'))
        self.slpdb_cb.clicked.connect(self.use_slpdb)
        self.slpdb_cb.setChecked(
            config.get('slp_validator_graphsearch_enabled', False))
        grid.addWidget(self.slpdb_cb, 0, 0, 1, 3)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel(_('Server') + ':'))
        self.slp_server_host = QLineEdit()
        self.slp_server_host.setFixedWidth(250)
        self.slp_server_host.editingFinished.connect(
            lambda: weakSelf() and weakSelf().set_slp_server())
        hbox.addWidget(self.slp_server_host)
        hbox.addStretch(1)
        grid.addLayout(hbox, 1, 0)

        self.slpdb_list_widget = SlpServeListWidget(self)
        grid.addWidget(self.slpdb_list_widget, 2, 0, 1, 5)
        grid.addWidget(QLabel(_("Current Graph Search Jobs:")), 3, 0)
        self.slp_search_job_list_widget = SlpSearchJobListWidget(self)
        grid.addWidget(self.slp_search_job_list_widget, 4, 0, 1, 5)

        # Blockchain Tab
        grid = QGridLayout(blockchain_tab)
        msg = ' '.join([
            _("Electron Cash connects to several nodes in order to download block headers and find out the longest blockchain."
              ),
            _("This blockchain is used to verify the transactions sent by your transaction server."
              )
        ])
        self.status_label = QLabel('')
        self.status_label.setTextInteractionFlags(
            self.status_label.textInteractionFlags()
            | Qt.TextSelectableByMouse)
        grid.addWidget(QLabel(_('Status') + ':'), 0, 0)
        grid.addWidget(self.status_label, 0, 1, 1, 3)
        grid.addWidget(HelpButton(msg), 0, 4)

        self.server_label = QLabel('')
        self.server_label.setTextInteractionFlags(
            self.server_label.textInteractionFlags()
            | Qt.TextSelectableByMouse)
        msg = _(
            "Electron Cash sends your wallet addresses to a single server, in order to receive your transaction history."
        )
        grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
        grid.addWidget(self.server_label, 1, 1, 1, 3)
        grid.addWidget(HelpButton(msg), 1, 4)

        self.height_label = QLabel('')
        self.height_label.setTextInteractionFlags(
            self.height_label.textInteractionFlags()
            | Qt.TextSelectableByMouse)
        msg = _('This is the height of your local copy of the blockchain.')
        grid.addWidget(QLabel(_('Blockchain') + ':'), 2, 0)
        grid.addWidget(self.height_label, 2, 1)
        grid.addWidget(HelpButton(msg), 2, 4)

        self.split_label = QLabel('')
        self.split_label.setTextInteractionFlags(
            self.split_label.textInteractionFlags() | Qt.TextSelectableByMouse)
        grid.addWidget(self.split_label, 3, 0, 1, 3)

        self.nodes_list_widget = NodesListWidget(self)
        grid.addWidget(self.nodes_list_widget, 5, 0, 1, 5)

        vbox = QVBoxLayout()
        vbox.addWidget(tabs)
        self.layout_ = vbox

        self.fill_in_proxy_settings()
        self.update()
Exemplo n.º 30
0
    def __init__(self, parent, network, config, wizard=False):
        super().__init__(parent)
        self.network = network
        self.config = config
        self.protocol = None
        self.tor_proxy = None

        # tor detector
        self.td = TorDetector(self)
        self.td.found_proxy.connect(self.suggest_proxy)

        self.tabs = tabs = QTabWidget()
        server_tab = QWidget()
        weakTd = Weak.ref(self.td)

        class ProxyTab(QWidget):
            def showEvent(slf, e):
                super().showEvent(e)
                td = weakTd()
                if e.isAccepted() and td:
                    td.start(
                    )  # starts the tor detector when proxy_tab appears

            def hideEvent(slf, e):
                super().hideEvent(e)
                td = weakTd()
                if e.isAccepted() and td:
                    td.stop(
                    )  # stops the tor detector when proxy_tab disappears

        proxy_tab = ProxyTab()
        blockchain_tab = QWidget()
        tabs.addTab(blockchain_tab, _('Overview'))
        tabs.addTab(server_tab, _('Server'))
        tabs.addTab(proxy_tab, _('Proxy'))

        if wizard:
            tabs.setCurrentIndex(1)

        # server tab
        grid = QGridLayout(server_tab)
        grid.setSpacing(8)

        self.server_host = QLineEdit()
        self.server_host.setFixedWidth(200)
        self.server_port = QLineEdit()
        self.server_port.setFixedWidth(60)
        self.autoconnect_cb = QCheckBox(_('Select server automatically'))
        self.autoconnect_cb.setEnabled(
            self.config.is_modifiable('auto_connect'))

        self.server_host.editingFinished.connect(self.set_server)
        self.server_port.editingFinished.connect(self.set_server)
        self.autoconnect_cb.clicked.connect(self.set_server)
        self.autoconnect_cb.clicked.connect(self.update)

        msg = ' '.join([
            _("If auto-connect is enabled, Electron Cash will always use a server that is on the longest blockchain."
              ),
            _("If it is disabled, you have to choose a server you want to use. Electron Cash will warn you if your server is lagging."
              )
        ])
        grid.addWidget(self.autoconnect_cb, 0, 0, 1, 3)
        grid.addWidget(HelpButton(msg), 0, 4)

        grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
        grid.addWidget(self.server_host, 1, 1, 1, 2)
        grid.addWidget(self.server_port, 1, 3)

        label = _('Server peers') if network.is_connected() else _(
            'Default Servers')
        grid.addWidget(QLabel(label), 2, 0, 1, 5)
        self.servers_list = ServerListWidget(self)
        grid.addWidget(self.servers_list, 3, 0, 1, 5)

        # Proxy tab
        grid = QGridLayout(proxy_tab)
        grid.setSpacing(8)

        # proxy setting
        self.proxy_cb = QCheckBox(_('Use proxy'))
        self.proxy_cb.clicked.connect(self.check_disable_proxy)
        self.proxy_cb.clicked.connect(self.set_proxy)

        self.proxy_mode = QComboBox()
        self.proxy_mode.addItems(['SOCKS4', 'SOCKS5', 'HTTP'])
        self.proxy_host = QLineEdit()
        self.proxy_host.setFixedWidth(200)
        self.proxy_port = QLineEdit()
        self.proxy_port.setFixedWidth(60)
        self.proxy_user = QLineEdit()
        self.proxy_user.setPlaceholderText(_("Proxy user"))
        self.proxy_password = QLineEdit()
        self.proxy_password.setPlaceholderText(_("Password"))
        self.proxy_password.setEchoMode(QLineEdit.Password)
        self.proxy_password.setFixedWidth(60)

        self.proxy_mode.currentIndexChanged.connect(self.set_proxy)
        self.proxy_host.editingFinished.connect(self.set_proxy)
        self.proxy_port.editingFinished.connect(self.set_proxy)
        self.proxy_user.editingFinished.connect(self.set_proxy)
        self.proxy_password.editingFinished.connect(self.set_proxy)

        self.proxy_mode.currentIndexChanged.connect(
            self.proxy_settings_changed)
        self.proxy_host.textEdited.connect(self.proxy_settings_changed)
        self.proxy_port.textEdited.connect(self.proxy_settings_changed)
        self.proxy_user.textEdited.connect(self.proxy_settings_changed)
        self.proxy_password.textEdited.connect(self.proxy_settings_changed)

        self.tor_cb = QCheckBox(_("Use Tor Proxy"))
        self.tor_cb.setIcon(QIcon(":icons/tor_logo.png"))
        self.tor_cb.hide()
        self.tor_cb.clicked.connect(self.use_tor_proxy)

        grid.addWidget(self.tor_cb, 1, 0, 1, 3)
        grid.addWidget(self.proxy_cb, 2, 0, 1, 3)
        grid.addWidget(
            HelpButton(
                _('Proxy settings apply to all connections: with Electron Cash servers, but also with third-party services.'
                  )), 2, 4)
        grid.addWidget(self.proxy_mode, 4, 1)
        grid.addWidget(self.proxy_host, 4, 2)
        grid.addWidget(self.proxy_port, 4, 3)
        grid.addWidget(self.proxy_user, 5, 2)
        grid.addWidget(self.proxy_password, 5, 3)
        grid.setRowStretch(7, 1)

        # Blockchain Tab
        grid = QGridLayout(blockchain_tab)
        msg = ' '.join([
            _("Electron Cash connects to several nodes in order to download block headers and find out the longest blockchain."
              ),
            _("This blockchain is used to verify the transactions sent by your transaction server."
              )
        ])
        self.status_label = QLabel('')
        grid.addWidget(QLabel(_('Status') + ':'), 0, 0)
        grid.addWidget(self.status_label, 0, 1, 1, 3)
        grid.addWidget(HelpButton(msg), 0, 4)

        self.server_label = QLabel('')
        msg = _(
            "Electron Cash sends your wallet addresses to a single server, in order to receive your transaction history."
        )
        grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
        grid.addWidget(self.server_label, 1, 1, 1, 3)
        grid.addWidget(HelpButton(msg), 1, 4)

        self.height_label = QLabel('')
        msg = _('This is the height of your local copy of the blockchain.')
        grid.addWidget(QLabel(_('Blockchain') + ':'), 2, 0)
        grid.addWidget(self.height_label, 2, 1)
        grid.addWidget(HelpButton(msg), 2, 4)

        self.split_label = QLabel('')
        grid.addWidget(self.split_label, 3, 0, 1, 3)

        self.nodes_list_widget = NodesListWidget(self)
        grid.addWidget(self.nodes_list_widget, 5, 0, 1, 5)

        vbox = QVBoxLayout()
        vbox.addWidget(tabs)
        self.layout_ = vbox

        self.fill_in_proxy_settings()
        self.update()