<commit_before>import os

from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject

from electrum.i18n import _
from electrum.logging import get_logger
from electrum.util import WalletFileException, standardize_path
from electrum.wallet import Abstract_Wallet
from electrum.plugin import run_hook
from electrum.lnchannel import ChannelState

from .auth import AuthMixin, auth_protect
from .qefx import QEFX
from .qewallet import QEWallet
from .qewalletdb import QEWalletDB
from .qewizard import QENewWalletWizard, QEServerConnectWizard

# wallet list model. supports both wallet basenames (wallet file basenames)
# and whole Wallet instances (loaded wallets)
class QEWalletListModel(QAbstractListModel):
    _logger = get_logger(__name__)

    # define listmodel rolemap
    _ROLE_NAMES= ('name','path','active')
    _ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
    _ROLE_MAP  = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))

    def __init__(self, daemon, parent=None):
        QAbstractListModel.__init__(self, parent)
        self.daemon = daemon
        self.wallets = []
        self.reload()

    def rowCount(self, index):
        return len(self.wallets)

    def roleNames(self):
        return self._ROLE_MAP

    def data(self, index, role):
        (wallet_name, wallet_path) = self.wallets[index.row()]
        role_index = role - Qt.UserRole
        role_name = self._ROLE_NAMES[role_index]
        if role_name == 'name':
            return wallet_name
        if role_name == 'path':
            return wallet_path
        if role_name == 'active':
            return self.daemon.get_wallet(wallet_path) is not None

    @pyqtSlot()
    def reload(self):
        self._logger.debug('enumerating available wallets')
        if len(self.wallets) > 0:
            self.beginRemoveRows(QModelIndex(), 0, len(self.wallets) - 1)
            self.wallets = []
            self.endRemoveRows()

        available = []
        wallet_folder = os.path.dirname(self.daemon.config.get_wallet_path())
        with os.scandir(wallet_folder) as it:
            for i in it:
                if i.is_file() and not i.name.startswith('.'):
                    available.append(i.path)
        for path in sorted(available):
            wallet = self.daemon.get_wallet(path)
            self.add_wallet(wallet_path = path)

    def add_wallet(self, wallet_path):
        self.beginInsertRows(QModelIndex(), len(self.wallets), len(self.wallets))
        wallet_name = os.path.basename(wallet_path)
        wallet_path = standardize_path(wallet_path)
        item = (wallet_name, wallet_path)
        self.wallets.append(item)
        self.endInsertRows()

    def remove_wallet(self, path):
        i = 0
        wallets = []
        remove = -1
        for wallet_name, wallet_path in self.wallets:
            if wallet_path == path:
                remove = i
            else:
                self._logger.debug('HM, %s is not %s', wallet_path, path)
                wallets.append((wallet_name, wallet_path))
            i += 1

        if remove >= 0:
            self.beginRemoveRows(QModelIndex(), i, i)
            self.wallets = wallets
            self.endRemoveRows()

    def wallet_name_exists(self, name):
        for wallet_name, wallet_path in self.wallets:
            if name == wallet_name:
                return True
        return False

class QEDaemon(AuthMixin, QObject):
    def __init__(self, daemon, parent=None):
        super().__init__(parent)
        self.daemon = daemon
        self.qefx = QEFX(daemon.fx, daemon.config)
        self._walletdb = QEWalletDB()
        self._walletdb.validPasswordChanged.connect(self.passwordValidityCheck)

    _logger = get_logger(__name__)
    _available_wallets = None
    _current_wallet = None
    _new_wallet_wizard = None
    _server_connect_wizard = None
    _path = None
    _use_single_password = False
    _password = None

    availableWalletsChanged = pyqtSignal()
    fxChanged = pyqtSignal()
    newWalletWizardChanged = pyqtSignal()
    serverConnectWizardChanged = pyqtSignal()

    walletLoaded = pyqtSignal()
    walletRequiresPassword = pyqtSignal()
    walletOpenError = pyqtSignal([str], arguments=["error"])
    walletDeleteError = pyqtSignal([str,str], arguments=['code', 'message'])

    @pyqtSlot()
    def passwordValidityCheck(self):
        if not self._walletdb._validPassword:
            self.walletRequiresPassword.emit()

    @pyqtSlot()
    @pyqtSlot(str)
    @pyqtSlot(str, str)
    def load_wallet(self, path=None, password=None):
        if path is None:
            self._path = self.daemon.config.get('wallet_path') # command line -w option
            if self._path is None:
                self._path = self.daemon.config.get('gui_last_wallet')
        else:
            self._path = path
        if self._path is None:
            return

        self._path = standardize_path(self._path)
        self._logger.debug('load wallet ' + str(self._path))

        if not password:
            password = self._password

        wallet_already_open = self._path in self.daemon._wallets

        if not wallet_already_open:
            # pre-checks, let walletdb trigger any necessary user interactions
            self._walletdb.path = self._path
            self._walletdb.password = password
            self._walletdb.verify()
            if not self._walletdb.ready:
                return

        try:
            wallet = self.daemon.load_wallet(self._path, password)
            if wallet is not None:
                self._current_wallet = QEWallet.getInstanceFor(wallet)
                if not wallet_already_open:
                    self._current_wallet.password = password
                self.walletLoaded.emit()<commit_msg>qml: let WalletListModel update the wallet state when a wallet is loaded<commit_after>import os

from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject

from electrum.i18n import _
from electrum.logging import get_logger
from electrum.util import WalletFileException, standardize_path
from electrum.wallet import Abstract_Wallet
from electrum.plugin import run_hook
from electrum.lnchannel import ChannelState

from .auth import AuthMixin, auth_protect
from .qefx import QEFX
from .qewallet import QEWallet
from .qewalletdb import QEWalletDB
from .qewizard import QENewWalletWizard, QEServerConnectWizard

# wallet list model. supports both wallet basenames (wallet file basenames)
# and whole Wallet instances (loaded wallets)
class QEWalletListModel(QAbstractListModel):
    _logger = get_logger(__name__)

    # define listmodel rolemap
    _ROLE_NAMES= ('name','path','active')
    _ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
    _ROLE_MAP  = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))

    def __init__(self, daemon, parent=None):
        QAbstractListModel.__init__(self, parent)
        self.daemon = daemon
        self.reload()

    def rowCount(self, index):
        return len(self.wallets)

    def roleNames(self):
        return self._ROLE_MAP

    def data(self, index, role):
        (wallet_name, wallet_path) = self.wallets[index.row()]
        role_index = role - Qt.UserRole
        role_name = self._ROLE_NAMES[role_index]
        if role_name == 'name':
            return wallet_name
        if role_name == 'path':
            return wallet_path
        if role_name == 'active':
            return self.daemon.get_wallet(wallet_path) is not None

    @pyqtSlot()
    def reload(self):
        self._logger.debug('enumerating available wallets')
        self.beginResetModel()
        self.wallets = []
        self.endResetModel()

        available = []
        wallet_folder = os.path.dirname(self.daemon.config.get_wallet_path())
        with os.scandir(wallet_folder) as it:
            for i in it:
                if i.is_file() and not i.name.startswith('.'):
                    available.append(i.path)
        for path in sorted(available):
            wallet = self.daemon.get_wallet(path)
            self.add_wallet(wallet_path = path)

    def add_wallet(self, wallet_path):
        self.beginInsertRows(QModelIndex(), len(self.wallets), len(self.wallets))
        wallet_name = os.path.basename(wallet_path)
        wallet_path = standardize_path(wallet_path)
        item = (wallet_name, wallet_path)
        self.wallets.append(item)
        self.endInsertRows()

    def remove_wallet(self, path):
        i = 0
        wallets = []
        remove = -1
        for wallet_name, wallet_path in self.wallets:
            if wallet_path == path:
                remove = i
            else:
                self._logger.debug('HM, %s is not %s', wallet_path, path)
                wallets.append((wallet_name, wallet_path))
            i += 1

        if remove >= 0:
            self.beginRemoveRows(QModelIndex(), i, i)
            self.wallets = wallets
            self.endRemoveRows()

    def wallet_name_exists(self, name):
        for wallet_name, wallet_path in self.wallets:
            if name == wallet_name:
                return True
        return False

    @pyqtSlot(str)
    def updateWallet(self, path):
        i = 0
        for wallet_name, wallet_path in self.wallets:
            if wallet_path == path:
                mi = self.createIndex(i, i)
                self.dataChanged.emit(mi, mi, self._ROLE_KEYS)
                return
            i += 1

class QEDaemon(AuthMixin, QObject):
    def __init__(self, daemon, parent=None):
        super().__init__(parent)
        self.daemon = daemon
        self.qefx = QEFX(daemon.fx, daemon.config)
        self._walletdb = QEWalletDB()
        self._walletdb.validPasswordChanged.connect(self.passwordValidityCheck)

    _logger = get_logger(__name__)
    _available_wallets = None
    _current_wallet = None
    _new_wallet_wizard = None
    _server_connect_wizard = None
    _path = None
    _use_single_password = False
    _password = None

    availableWalletsChanged = pyqtSignal()
    fxChanged = pyqtSignal()
    newWalletWizardChanged = pyqtSignal()
    serverConnectWizardChanged = pyqtSignal()

    walletLoaded = pyqtSignal()
    walletRequiresPassword = pyqtSignal()
    walletOpenError = pyqtSignal([str], arguments=["error"])
    walletDeleteError = pyqtSignal([str,str], arguments=['code', 'message'])

    @pyqtSlot()
    def passwordValidityCheck(self):
        if not self._walletdb._validPassword:
            self.walletRequiresPassword.emit()

    @pyqtSlot()
    @pyqtSlot(str)
    @pyqtSlot(str, str)
    def load_wallet(self, path=None, password=None):
        if path is None:
            self._path = self.daemon.config.get('wallet_path') # command line -w option
            if self._path is None:
                self._path = self.daemon.config.get('gui_last_wallet')
        else:
            self._path = path
        if self._path is None:
            return

        self._path = standardize_path(self._path)
        self._logger.debug('load wallet ' + str(self._path))

        if not password:
            password = self._password

        wallet_already_open = self._path in self.daemon._wallets

        if not wallet_already_open:
            # pre-checks, let walletdb trigger any necessary user interactions
            self._walletdb.path = self._path
            self._walletdb.password = password
            self._walletdb.verify()
            if not self._walletdb.ready:
                return

        try:
            wallet = self.daemon.load_wallet(self._path, password)
            if wallet is not None:
                self._current_wallet = QEWallet.getInstanceFor(wallet)
                if not wallet_already_open:
                    self.availableWallets.updateWallet(self._path)
                    self._current_wallet.password = password
                self.walletLoaded.emit()
{'fraction_non_alphanumeric': 0.0892233494096125, 'fraction_numerical': 0.0017462165308498253, 'mean_word_length': 2.4461318051575933, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3281398', 'n_tokens_mistral': 3586, 'n_tokens_neox': 3595, 'n_words': 819}