Merge pull request #10573 from f321x/qml_wallet_rename
qml: allow renaming wallets
This commit is contained in:
@@ -585,6 +585,17 @@ class Daemon(Logger):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def rename_wallet_file(self, old_path: str, new_path: str):
|
||||||
|
old_path = standardize_path(old_path)
|
||||||
|
new_path = standardize_path(new_path)
|
||||||
|
if os.path.exists(new_path):
|
||||||
|
raise ValueError("Wallet file already exists")
|
||||||
|
os.rename(old_path, new_path)
|
||||||
|
self.logger.debug(f'renamed wallet: {old_path} -> {new_path}')
|
||||||
|
self.update_recently_opened_wallets(old_path, remove=True)
|
||||||
|
if self.config.CURRENT_WALLET == old_path:
|
||||||
|
self.config.CURRENT_WALLET = new_path
|
||||||
|
|
||||||
def stop_wallet(self, path: str) -> bool:
|
def stop_wallet(self, path: str) -> bool:
|
||||||
"""Returns True iff a wallet was found."""
|
"""Returns True iff a wallet was found."""
|
||||||
assert util.get_running_loop() != util.get_asyncio_loop(), 'must not be called from asyncio thread'
|
assert util.get_running_loop() != util.get_asyncio_loop(), 'must not be called from asyncio thread'
|
||||||
|
|||||||
@@ -130,6 +130,64 @@ Pane {
|
|||||||
visible: Daemon.currentWallet
|
visible: Daemon.currentWallet
|
||||||
columns: 2
|
columns: 2
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
Layout.topMargin: constants.paddingSmall
|
||||||
|
text: qsTr('Name')
|
||||||
|
color: Material.accentColor
|
||||||
|
}
|
||||||
|
|
||||||
|
TextHighlightPane {
|
||||||
|
id: walletNameContent
|
||||||
|
property bool editmode: false
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
width: parent.width
|
||||||
|
Label {
|
||||||
|
visible: !walletNameContent.editmode
|
||||||
|
text: Daemon.currentWallet.name
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: constants.fontSizeLarge
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
visible: !walletNameContent.editmode
|
||||||
|
icon.source: '../../icons/pen.png'
|
||||||
|
icon.color: 'transparent'
|
||||||
|
onClicked: {
|
||||||
|
walletNameEdit.text = Daemon.currentWallet.name
|
||||||
|
walletNameContent.editmode = true
|
||||||
|
walletNameEdit.focus = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: walletNameEdit
|
||||||
|
visible: walletNameContent.editmode
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: constants.fontSizeLarge
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
visible: walletNameContent.editmode
|
||||||
|
icon.source: '../../icons/confirmed.png'
|
||||||
|
icon.color: enabled ? 'transparent' : constants.mutedForeground
|
||||||
|
enabled: walletNameEdit.text !== Daemon.currentWallet.name
|
||||||
|
&& Daemon.isValidWalletName(walletNameEdit.text)
|
||||||
|
onClicked: {
|
||||||
|
walletNameContent.editmode = false
|
||||||
|
Daemon.renameWallet(walletNameEdit.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
visible: walletNameContent.editmode
|
||||||
|
icon.source: '../../icons/closebutton.png'
|
||||||
|
icon.color: 'transparent'
|
||||||
|
onClicked: walletNameContent.editmode = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.columnSpan: 2
|
Layout.columnSpan: 2
|
||||||
Layout.topMargin: constants.paddingSmall
|
Layout.topMargin: constants.paddingSmall
|
||||||
@@ -526,6 +584,14 @@ Pane {
|
|||||||
dialog.open()
|
dialog.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function onWalletRenameError(message) {
|
||||||
|
var dialog = app.messageDialog.createObject(app, {
|
||||||
|
title: qsTr('Error'),
|
||||||
|
iconSource: Qt.resolvedUrl('../../icons/warning.png'),
|
||||||
|
text: message
|
||||||
|
})
|
||||||
|
dialog.open()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ class QEDaemon(AuthMixin, QObject):
|
|||||||
walletRequiresPassword = pyqtSignal([str, str], arguments=['name', 'path'])
|
walletRequiresPassword = pyqtSignal([str, str], arguments=['name', 'path'])
|
||||||
walletOpenError = pyqtSignal([str], arguments=["error"])
|
walletOpenError = pyqtSignal([str], arguments=["error"])
|
||||||
walletDeleteError = pyqtSignal([str, str], arguments=['code', 'message'])
|
walletDeleteError = pyqtSignal([str, str], arguments=['code', 'message'])
|
||||||
|
walletRenameError = pyqtSignal([str], arguments=['message'])
|
||||||
|
|
||||||
def __init__(self, daemon: 'Daemon', plugins: 'Plugins', parent=None):
|
def __init__(self, daemon: 'Daemon', plugins: 'Plugins', parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@@ -310,6 +311,34 @@ class QEDaemon(AuthMixin, QObject):
|
|||||||
|
|
||||||
self.availableWallets.remove_wallet(path)
|
self.availableWallets.remove_wallet(path)
|
||||||
|
|
||||||
|
@pyqtSlot(str, result=bool)
|
||||||
|
def isValidWalletName(self, wallet_name: str) -> bool:
|
||||||
|
if not wallet_name:
|
||||||
|
return False
|
||||||
|
if self.availableWallets.wallet_name_exists(wallet_name):
|
||||||
|
return False
|
||||||
|
# ensure wallet_name is not interpreted as path
|
||||||
|
if os.path.basename(wallet_name) != wallet_name: # '/foo/bar/' returns 'bar'
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def renameWallet(self, new_name: str):
|
||||||
|
wallet = self._current_wallet
|
||||||
|
assert wallet, "name change without wallet?"
|
||||||
|
old_path = standardize_path(wallet.wallet.storage.path)
|
||||||
|
wallet_dir = os.path.dirname(old_path)
|
||||||
|
new_path = standardize_path(os.path.join(wallet_dir, new_name))
|
||||||
|
if old_path == new_path:
|
||||||
|
return
|
||||||
|
self._current_wallet = None
|
||||||
|
self.daemon.stop_wallet(old_path)
|
||||||
|
try:
|
||||||
|
self.daemon.rename_wallet_file(old_path, new_path)
|
||||||
|
except Exception as e:
|
||||||
|
self.walletRenameError.emit(_('Error renaming wallet:\n') + str(e))
|
||||||
|
self.walletLoaded.emit(None, None)
|
||||||
|
|
||||||
@pyqtProperty(bool, notify=loadingChanged)
|
@pyqtProperty(bool, notify=loadingChanged)
|
||||||
def loading(self):
|
def loading(self):
|
||||||
return self._loading
|
return self._loading
|
||||||
|
|||||||
Reference in New Issue
Block a user