diff --git a/main.cpp b/main.cpp index e74dada3..1fb190d5 100644 --- a/main.cpp +++ b/main.cpp @@ -64,6 +64,7 @@ #include "qt/ipc.h" #include "qt/utils.h" #include "qt/mime.h" +#include "src/qt/KeysFiles.h" // IOS exclusions #ifndef Q_OS_IOS @@ -116,6 +117,19 @@ int main(int argc, char *argv[]) // qDebug() << "High DPI auto scaling - enabled"; //#endif + QString moneroAccountsDir; + #if defined(Q_OS_WIN) || defined(Q_OS_IOS) + QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + #else + QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); + #endif + if (!moneroAccountsRootDir.empty()) { + moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero/wallets"; + } else { + qCritical() << "Error: accounts root directory could not be set"; + return 1; + } + MainApp app(argc, argv); app.setApplicationName("monero-core"); @@ -145,9 +159,6 @@ int main(int argc, char *argv[]) Monero::Wallet::init(argv[0], "monero-wallet-gui", logPath.toStdString().c_str(), true); qInstallMessageHandler(messageHandler); - // Get default account name - QString accountName = getAccountName(); - // loglevel is configured in main.qml. Anything lower than // qWarning is not shown here unless MONERO_LOG_LEVEL env var is set bool logLevelOk; @@ -223,7 +234,8 @@ int main(int argc, char *argv[]) qmlRegisterUncreatableType("moneroComponents.TranslationManager", 1, 0, "TranslationManager", "TranslationManager can't be instantiated directly"); - + qmlRegisterUncreatableType("moneroComponents.walletKeysFilesModel", 1, 0, "WalletKeysFilesModel", + "walletKeysFilesModel can't be instantiated directly"); qmlRegisterUncreatableType("moneroComponents.TransactionHistoryModel", 1, 0, "TransactionHistoryModel", "TransactionHistoryModel can't be instantiated directly"); @@ -278,7 +290,11 @@ int main(int argc, char *argv[]) engine.addImportPath(":/fonts"); - engine.rootContext()->setContextProperty("walletManager", WalletManager::instance()); + engine.rootContext()->setContextProperty("moneroAccountsDir", moneroAccountsDir); + + WalletManager *walletManager = WalletManager::instance(); + + engine.rootContext()->setContextProperty("walletManager", walletManager); engine.rootContext()->setContextProperty("translationManager", TranslationManager::instance()); @@ -299,17 +315,6 @@ int main(int argc, char *argv[]) engine.rootContext()->setContextProperty("daemonManager", daemonManager); #endif -// export to QML monero accounts root directory -// wizard is talking about where -// to save the wallet file (.keys, .bin), they have to be user-accessible for -// backups - I reckon we save that in My Documents\Monero Accounts\ on -// Windows, ~/Monero Accounts/ on nix / osx -#if defined(Q_OS_WIN) || defined(Q_OS_IOS) - QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); -#else - QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); -#endif - engine.rootContext()->setContextProperty("isWindows", isWindows); engine.rootContext()->setContextProperty("isIOS", isIOS); engine.rootContext()->setContextProperty("isAndroid", isAndroid); @@ -325,11 +330,17 @@ int main(int argc, char *argv[]) engine.rootContext()->setContextProperty("desktopFolder", desktopFolder); #endif - if (!moneroAccountsRootDir.empty()) - { - QString moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero/wallets"; - engine.rootContext()->setContextProperty("moneroAccountsDir", moneroAccountsDir); - } + // Wallet .keys files model (wizard -> open wallet) + WalletKeysFilesModel walletKeysFilesModel(walletManager); + engine.rootContext()->setContextProperty("walletKeysFilesModel", &walletKeysFilesModel); + engine.rootContext()->setContextProperty("walletKeysFilesModelProxy", &walletKeysFilesModel.proxyModel()); + + // Get default account name + QString accountName = qgetenv("USER"); // mac/linux + if (accountName.isEmpty()) + accountName = qgetenv("USERNAME"); // Windows + if (accountName.isEmpty()) + accountName = "My monero Account"; engine.rootContext()->setContextProperty("defaultAccountName", accountName); engine.rootContext()->setContextProperty("applicationDirectory", QApplication::applicationDirPath()); diff --git a/monero-wallet-gui.pro b/monero-wallet-gui.pro index 5deb5964..a1227408 100644 --- a/monero-wallet-gui.pro +++ b/monero-wallet-gui.pro @@ -64,6 +64,7 @@ HEADERS += \ MainApp.h \ src/qt/ipc.h \ src/qt/mime.h \ + src/qt/KeysFiles.h \ src/qt/utils.h SOURCES += main.cpp \ @@ -95,6 +96,7 @@ SOURCES += main.cpp \ MainApp.cpp \ src/qt/ipc.cpp \ src/qt/mime.cpp \ + src/qt/KeysFiles.cpp \ src/qt/utils.cpp CONFIG(DISABLE_PASS_STRENGTH_METER) { diff --git a/src/qt/KeysFiles.cpp b/src/qt/KeysFiles.cpp new file mode 100644 index 00000000..29b0c442 --- /dev/null +++ b/src/qt/KeysFiles.cpp @@ -0,0 +1,183 @@ +// Copyright (c) 2014-2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "src/libwalletqt/WalletManager.h" +#include "src/NetworkType.h" +#include "src/qt/utils.h" + +#include "KeysFiles.h" + + +WalletKeysFiles::WalletKeysFiles(const qint64 &modified, const qint64 &created, const QString &path, const quint8 &networkType, const QString &address) + : m_modified(modified), m_created(created), m_path(path), m_networkType(networkType), m_address(address) +{ +} + +qint64 WalletKeysFiles::modified() const +{ + return m_modified; +} + +QString WalletKeysFiles::address() const +{ + return m_address; +} + +qint64 WalletKeysFiles::created() const +{ + return m_created; +} + +QString WalletKeysFiles::path() const +{ + return m_path; +} + +quint8 WalletKeysFiles::networkType() const +{ + return m_networkType; +} + + +WalletKeysFilesModel::WalletKeysFilesModel(WalletManager *walletManager, QObject *parent) + : QAbstractListModel(parent) +{ + this->m_walletManager = walletManager; + this->m_walletKeysFilesItemModel = qobject_cast(this); + + this->m_walletKeysFilesModelProxy.setSourceModel(this->m_walletKeysFilesItemModel); + this->m_walletKeysFilesModelProxy.setSortRole(WalletKeysFilesModel::ModifiedRole); + this->m_walletKeysFilesModelProxy.setDynamicSortFilter(true); + this->m_walletKeysFilesModelProxy.sort(0, Qt::DescendingOrder); +} + +QSortFilterProxyModel &WalletKeysFilesModel::proxyModel() +{ + return m_walletKeysFilesModelProxy; +} + +void WalletKeysFilesModel::clear() +{ + beginResetModel(); + m_walletKeyFiles.clear(); + endResetModel(); +} + +void WalletKeysFilesModel::refresh(const QString &moneroAccountsDir) +{ + this->clear(); + this->findWallets(moneroAccountsDir); +} + +void WalletKeysFilesModel::findWallets(const QString &moneroAccountsDir) +{ + QStringList walletDir = this->m_walletManager->findWallets(moneroAccountsDir); + foreach(QString wallet, walletDir){ + if(!fileExists(wallet + ".keys")) + continue; + + quint8 networkType = NetworkType::MAINNET; + QString address = QString(""); + + // attempt to retreive wallet address + if(fileExists(wallet + ".address.txt")){ + QFile file(wallet + ".address.txt"); + file.open(QFile::ReadOnly | QFile::Text); + QString _address = QTextCodec::codecForMib(106)->toUnicode(file.readAll()); + + if(!_address.isEmpty()){ + address = _address; + if(address.startsWith("5") || address.startsWith("7")){ + networkType = NetworkType::STAGENET; + } else if(address.startsWith("9") || address.startsWith("B")){ + networkType = NetworkType::TESTNET; + } + } + + file.close(); + } + + const QFileInfo info(wallet); + const QDateTime modifiedAt = info.lastModified(); + const QDateTime createdAt = info.created(); // @TODO: QFileInfo::birthTime() >= Qt 5.10 + + this->addWalletKeysFile(WalletKeysFiles(modifiedAt.toSecsSinceEpoch(), + createdAt.toSecsSinceEpoch(), + wallet, networkType, address)); + } +} + +void WalletKeysFilesModel::addWalletKeysFile(const WalletKeysFiles &walletKeysFile) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_walletKeyFiles << walletKeysFile; + endInsertRows(); +} + +int WalletKeysFilesModel::rowCount(const QModelIndex & parent) const { + Q_UNUSED(parent); + return m_walletKeyFiles.count(); +} + +QVariant WalletKeysFilesModel::data(const QModelIndex & index, int role) const { + if (index.row() < 0 || index.row() >= m_walletKeyFiles.count()) + return QVariant(); + + const WalletKeysFiles &walletKeyFile = m_walletKeyFiles[index.row()]; + if (role == ModifiedRole) + return walletKeyFile.modified(); + else if (role == PathRole) + return walletKeyFile.path(); + else if (role == NetworkTypeRole) + return walletKeyFile.networkType(); + else if (role == AddressRole) + return walletKeyFile.address(); + else if (role == CreatedRole) + return walletKeyFile.created(); + return QVariant(); +} + +QHash WalletKeysFilesModel::roleNames() const { + QHash roles; + roles[ModifiedRole] = "modified"; + roles[PathRole] = "path"; + roles[NetworkTypeRole] = "networktype"; + roles[AddressRole] = "address"; + roles[CreatedRole] = "created"; + return roles; +} diff --git a/src/qt/KeysFiles.h b/src/qt/KeysFiles.h new file mode 100644 index 00000000..78348b2d --- /dev/null +++ b/src/qt/KeysFiles.h @@ -0,0 +1,91 @@ +// Copyright (c) 2014-2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef KEYSFILES_H +#define KEYSFILES_H + +#include +#include "src/libwalletqt/WalletManager.h" +#include "src/NetworkType.h" +#include + +class WalletKeysFiles +{ +public: + WalletKeysFiles(const qint64 &modified, const qint64 &created, const QString &path, const quint8 &networkType, const QString &address); + + qint64 modified() const; + qint64 created() const; + QString path() const; + quint8 networkType() const; + QString address() const; + +private: + qint64 m_modified; + qint64 m_created; + QString m_path; + quint8 m_networkType; + QString m_address; +}; + +class WalletKeysFilesModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum KeysFilesRoles { + ModifiedRole = Qt::UserRole + 1, + PathRole, + NetworkTypeRole, + AddressRole, + CreatedRole + }; + + WalletKeysFilesModel(WalletManager *walletManager, QObject *parent = 0); + + Q_INVOKABLE void refresh(const QString &moneroAccountsDir); + Q_INVOKABLE void clear(); + + void findWallets(const QString &moneroAccountsDir); + void addWalletKeysFile(const WalletKeysFiles &walletKeysFile); + int rowCount(const QModelIndex & parent = QModelIndex()) const; + + QSortFilterProxyModel &proxyModel(); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QHash roleNames() const; + +protected: + +private: + QList m_walletKeyFiles; + WalletManager *m_walletManager; + + QAbstractItemModel *m_walletKeysFilesItemModel; + QSortFilterProxyModel m_walletKeysFilesModelProxy; +}; + +#endif // KEYSFILES_H diff --git a/wizard/WizardOpenWallet1.qml b/wizard/WizardOpenWallet1.qml index 93c38837..50823a37 100644 --- a/wizard/WizardOpenWallet1.qml +++ b/wizard/WizardOpenWallet1.qml @@ -30,29 +30,21 @@ import QtQuick 2.9 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.0 +import QtGraphicalEffects 1.0 import Qt.labs.folderlistmodel 2.1 +import moneroComponents.NetworkType 1.0 import "../js/Wizard.js" as Wizard import "../components" import "../components" as MoneroComponents +import "../components/effects/" as MoneroEffects Rectangle { id: wizardOpenWallet1 color: "transparent" property string viewName: "wizardOpenWallet1" - - FolderListModel { - // @TODO: Current implementation only lists the folders in `/home/foo/Monero/wallets`, better - // solution is to actually scan for .keys files. - id: folderModel - nameFilters: ["*"] - folder: "file:" + moneroAccountsDir + "/" - - showFiles: false - showHidden: false - sortField: FolderListModel.Time - } + property int walletCount: walletKeysFilesModel.rowCount() ColumnLayout { Layout.alignment: Qt.AlignHCenter; @@ -67,37 +59,25 @@ Rectangle { Layout.topMargin: wizardController.wizardSubViewTopMargin Layout.maximumWidth: wizardController.wizardSubViewWidth Layout.alignment: Qt.AlignHCenter - spacing: 20 + spacing: 10 WizardHeader { title: qsTr("Open a wallet from file") + translationManager.emptyString subtitle: qsTr("Import an existing .keys wallet file from your computer.") + translationManager.emptyString } - MoneroComponents.StandardButton { - Layout.topMargin: 20 - id: btnNext - small: true - text: qsTr("Browse filesystem") + translationManager.emptyString - - onClicked: { - wizardController.openWallet(); - } - } - GridLayout { - visible: folderModel.count > 0 - Layout.topMargin: 30 + visible: walletKeysFilesModel.rowCount() > 0 + Layout.topMargin: 10 Layout.fillWidth: true columnSpacing: 20 columns: 2 MoneroComponents.TextPlain { - text: qsTr("Most recent wallets") + translationManager.emptyString + Layout.fillWidth: true + text: qsTr("Recently opened") + ":" + translationManager.emptyString font.family: MoneroComponents.Style.fontLight.name font.pixelSize: 16 - color: MoneroComponents.Style.defaultFontColor - Layout.fillWidth: true } Item { @@ -105,61 +85,154 @@ Rectangle { } } - GridLayout { - visible: folderModel.count > 0 + Flow { + id: flow + visible: wizardOpenWallet1.walletCount > 0 + spacing: 0 + clip: true + + property int _height: 0 + property int itemHeight: 50 + property int maxRows: 6 + Layout.topMargin: 10 Layout.fillWidth: true - columnSpacing: 20 - columns: 2 + Layout.preferredHeight: _height - ListView { + function calcHeight(){ + var itemsHeight = Math.ceil(wizardOpenWallet1.walletCount / 3) * itemHeight; + if(itemsHeight >= (flow.itemHeight * flow.maxRows)) + return flow.itemHeight * flow.maxRows; + else + return itemsHeight; + } + + Repeater { id: recentList - property int itemHeight: 42 - property int maxItems: 7 - clip: true + model: walletKeysFilesModelProxy Layout.fillWidth: true - Layout.preferredHeight: recentList.itemHeight * folderModel.count - Layout.maximumHeight: recentList.itemHeight * recentList.maxItems - interactive: false // disable scrolling + Layout.minimumWidth: flow.itemHeight + Layout.preferredHeight: parent.height delegate: Rectangle { - height: recentList.itemHeight - width: 200 - property string activeColor: "#26FFFFFF" + // inherited roles from walletKeysFilesModel: + // index, modified, accessed, path, networktype, address + id: item + height: flow.itemHeight + width: { + if(wizardController.layoutScale <= 1) + return parent.width / 2 + return parent.width / 3 + } + property string networkType: { + if(networktype === 0) return qsTr("Mainnet"); + else if(networktype === 1) return qsTr("Testnet"); + else if(networktype === 2) return qsTr("Stagenet"); + return ""; + } + property string fileName: { + var spl = path.split("/"); + return spl[spl.length - 1].replace(".keys", ""); + } + property string filePath: { return path } color: "transparent" - RowLayout { - height: recentList.itemHeight + Rectangle { + height: 1 width: parent.width - spacing: 10 + anchors.top: parent.top + color: MoneroComponents.Style.appWindowBorderColor + visible: index <= 2 // top row + + MoneroEffects.ColorTransition { + targetObj: parent + blackColor: MoneroComponents.Style._b_appWindowBorderColor + whiteColor: MoneroComponents.Style._w_appWindowBorderColor + } + } + + RowLayout { + height: flow.itemHeight + width: parent.width + spacing: 6 Rectangle { - Layout.preferredWidth: recentList.itemHeight - Layout.preferredHeight: recentList.itemHeight + Layout.preferredWidth: 48 + Layout.preferredHeight: flow.itemHeight color: "transparent" Image { - height: recentList.itemHeight - width: recentList.itemHeight - anchors.horizontalCenter: parent.horizontalCenter + id: icon + height: 48 + width: 48 + anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter fillMode: Image.PreserveAspectFit source: "qrc:///images/open-wallet-from-file.png" + visible: { + if(!isOpenGL) return true; + if(MoneroComponents.Style.blackTheme) return true; + return false; + } + } + + Colorize { + visible: isOpenGL && !MoneroComponents.Style.blackTheme + anchors.fill: icon + source: icon + lightness: 0.65 // +65% + saturation: 0.0 } } - Rectangle { + ColumnLayout { Layout.fillWidth: true - Layout.preferredHeight: recentList.itemHeight - color: "transparent" + Layout.preferredHeight: flow.itemHeight + spacing: 0 + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } TextArea { - text: fileName - anchors.verticalCenter: parent.verticalCenter + text: { + // truncate on window width + var maxLength = wizardController.layoutScale <= 1 ? 12 : 16 + if(item.fileName.length > maxLength) + return item.fileName.substring(0, maxLength) + "..."; + return item.fileName; + } + + Layout.preferredHeight: 26 + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.fillWidth: true font.family: MoneroComponents.Style.fontRegular.name color: MoneroComponents.Style.defaultFontColor - font.pixelSize: 18 + font.pixelSize: 16 + + selectionColor: MoneroComponents.Style.dimmedFontColor + selectedTextColor: MoneroComponents.Style.defaultFontColor + + selectByMouse: false + wrapMode: Text.WordWrap + textMargin: 0 + leftPadding: 0 + topPadding: networktype !== -1 ? 8 : 4 + bottomPadding: 0 + readOnly: true + } + + TextArea { + visible: networktype !== -1 + Layout.preferredHeight: 24 + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.fillWidth: true + text: item.networkType + font.family: MoneroComponents.Style.fontRegular.name + color: MoneroComponents.Style.dimmedFontColor + font.pixelSize: 14 selectionColor: MoneroComponents.Style.textSelectionColor selectedTextColor: MoneroComponents.Style.textSelectedColor @@ -171,13 +244,25 @@ Rectangle { topPadding: 0 bottomPadding: 0 readOnly: true - - // @TODO: Legacy. Remove after Qt 5.8. - MouseArea { - anchors.fill: parent - enabled: false - } } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } + + Rectangle { + height: 1 + width: parent.width + color: MoneroComponents.Style.appWindowBorderColor + anchors.bottom: parent.bottom + + MoneroEffects.ColorTransition { + targetObj: parent + blackColor: MoneroComponents.Style._b_appWindowBorderColor + whiteColor: MoneroComponents.Style._w_appWindowBorderColor } } @@ -187,28 +272,27 @@ Rectangle { cursorShape: Qt.PointingHandCursor onEntered: { - parent.color = parent.activeColor; + parent.color = MoneroComponents.Style.titleBarButtonHoverColor; } onExited: { parent.color = "transparent"; } onClicked: { - // open wallet + persistentSettings.nettype = parseInt(networktype) + if(appWindow.walletMode === 0 || appWindow.walletMode === 1){ wizardController.fetchRemoteNodes(function(){ - wizardController.openWalletFile(moneroAccountsDir + "/" + fileName + "/" + fileName + ".keys"); + wizardController.openWalletFile(item.filePath); }, function(){ appWindow.showStatusMessage(qsTr("Failed to fetch remote nodes from third-party server."), 5); - wizardController.openWalletFile(moneroAccountsDir + "/" + fileName + "/" + fileName + ".keys"); + wizardController.openWalletFile(item.filePath); }); } else { - wizardController.openWalletFile(moneroAccountsDir + "/" + fileName + "/" + fileName + ".keys"); + wizardController.openWalletFile(item.filePath); } } } } - - model: folderModel } Item { @@ -217,20 +301,26 @@ Rectangle { } WizardNav { - Layout.topMargin: { - if(folderModel.count > 0){ - return 40; - } else { - return 20; - } - } + Layout.topMargin: 0 progressEnabled: false btnPrev.text: qsTr("Back to menu") + translationManager.emptyString - btnNext.visible: false + btnNext.text: qsTr("Browse filesystem") + translationManager.emptyString + btnNext.visible: true onPrevClicked: { wizardStateView.state = "wizardHome"; } + onNextClicked: { + wizardController.openWallet(); + } } } } + + function onPageCompleted(previousView){ + if(previousView.viewName == "wizardHome"){ + walletKeysFilesModel.refresh(moneroAccountsDir); + wizardOpenWallet1.walletCount = walletKeysFilesModel.rowCount(); + flow._height = flow.calcHeight(); + } + } }