diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 2d56708716..95a9017c18 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -163,6 +163,12 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ if test -d "$qt_plugin_path/../qml/QtQuick/Controls"; then QT_LIBS="$QT_LIBS -L$qt_plugin_path/../qml/QtQuick/Controls" fi + if test -d "$qt_plugin_path/../qml/QtQuick/Dialogs"; then + QT_LIBS="$QT_LIBS -L$qt_plugin_path/../qml/QtQuick/Dialogs -L$qt_plugin_path/../qml/QtQuick/Dialogs/Private" + fi + if test -d "$qt_plugin_path/../qml/Qt/labs/folderlistmodel"; then + QT_LIBS="$QT_LIBS -L$qt_plugin_path/../qml/Qt/labs/folderlistmodel" + fi if test -d "$qt_plugin_path/../qml/Qt/labs/settings"; then QT_LIBS="$QT_LIBS -L$qt_plugin_path/../qml/Qt/labs/settings" fi @@ -214,6 +220,9 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuickLayoutsPlugin], [-lqquicklayoutsplugin]) dnl qtquickcontrols module plugins _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuickControls1Plugin], [-lqtquickcontrolsplugin]) + _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuick2DialogsPlugin], [-ldialogplugin]) + _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuick2DialogsPrivatePlugin], [-ldialogsprivateplugin]) + _BITCOIN_QT_CHECK_STATIC_PLUGIN([QmlFolderListModelPlugin], [-lqmlfolderlistmodelplugin]) _BITCOIN_QT_CHECK_STATIC_PLUGIN([QmlSettingsPlugin], [-lqmlsettingsplugin]) dnl qtquickcontrols2 module plugins _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuickControls2Plugin], [-lqtquickcontrols2plugin]) @@ -227,6 +236,9 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuickLayoutsPlugin], [-lqml_QtQuick_Layouts_qquicklayoutsplugin]) dnl qtquickcontrols module plugins _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuickControls1Plugin], [-lqml_QtQuick_Controls_qtquickcontrolsplugin]) + _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuick2DialogsPlugin], [-lqml_QtQuick_Dialogs_dialogplugin]) + _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuick2DialogsPrivatePlugin], [-lqml_QtQuick_Dialogs_Private_dialogsprivateplugin]) + _BITCOIN_QT_CHECK_STATIC_PLUGIN([QmlFolderListModelPlugin], [-lqml_Qt_labs_folderlistmodel_qmlfolderlistmodelplugin]) _BITCOIN_QT_CHECK_STATIC_PLUGIN([QmlSettingsPlugin], [-lqml_Qt_labs_settings_qmlsettingsplugin]) dnl qtquickcontrols2 module plugins _BITCOIN_QT_CHECK_STATIC_PLUGIN([QtQuickControls2Plugin], [-lqml_QtQuick_Controls_2_qtquickcontrols2plugin]) diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index dd30a60559..2afa47fece 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -24,6 +24,7 @@ $(package)_patches += fast_fixed_dtoa_no_optimize.patch $(package)_patches += guix_cross_lib_path.patch $(package)_patches += fix_android_plugin_names.patch $(package)_patches += fix_riscv_atomic.patch +$(package)_patches += fix_android_controls_file_location.patch $(package)_qtdeclarative_file_name = qtdeclarative-$($(package)_suffix) $(package)_qtdeclarative_sha256_hash = 5cc169d91efb15a1ee7f484862f872c3eaba592dacf3c0fbcb55c0f3c208254a @@ -300,6 +301,7 @@ define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/guix_cross_lib_path.patch && \ patch -p1 -i $($(package)_patch_dir)/fix_android_plugin_names.patch && \ patch -p1 -i $($(package)_patch_dir)/fix_riscv_atomic.patch && \ + patch -p1 -i $($(package)_patch_dir)/fix_android_controls_file_location.patch && \ mkdir -p qtbase/mkspecs/macx-clang-linux &&\ cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\ cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \ diff --git a/depends/patches/qt/fix_android_controls_file_location.patch b/depends/patches/qt/fix_android_controls_file_location.patch new file mode 100644 index 0000000000..cefbed9962 --- /dev/null +++ b/depends/patches/qt/fix_android_controls_file_location.patch @@ -0,0 +1,13 @@ +diff --git a/qtquickcontrols/src/controls/plugin.cpp b/src/controls/plugin.cpp +index 446357aa..a08957cd 100644 +--- a/qtquickcontrols/src/controls/plugin.cpp ++++ b/qtquickcontrols/src/controls/plugin.cpp +@@ -240,7 +240,7 @@ void QtQuickControls1Plugin::initializeEngine(QQmlEngine *engine, const char *ur + QString QtQuickControls1Plugin::fileLocation() const + { + #ifdef Q_OS_ANDROID +- return "qrc:/android_rcc_bundle/qml/QtQuick/Controls"; ++ return "qrc:/qt-project.org/imports/QtQuick/Controls"; + #else + #ifndef QT_STATIC + if (isLoadedFromResource()) diff --git a/src/qml/README.md b/src/qml/README.md index d9b4798984..63971447f2 100644 --- a/src/qml/README.md +++ b/src/qml/README.md @@ -70,7 +70,7 @@ The following runtime dependencies are also required for dynamic builds; they are not needed for static builds: ``` -sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 qml-module-qt-labs-settings +sudo apt install qml-module-qtquick2 qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qtquick-layouts qml-module-qtquick-window2 qml-module-qt-labs-settings ``` ##### Important: diff --git a/src/qml/bitcoin.cpp b/src/qml/bitcoin.cpp index d87386cbd5..520382447a 100644 --- a/src/qml/bitcoin.cpp +++ b/src/qml/bitcoin.cpp @@ -57,9 +57,12 @@ QT_END_NAMESPACE #include Q_IMPORT_PLUGIN(QtQmlPlugin) Q_IMPORT_PLUGIN(QtQmlModelsPlugin) +Q_IMPORT_PLUGIN(QtQuick2DialogsPlugin) +Q_IMPORT_PLUGIN(QtQuick2DialogsPrivatePlugin) Q_IMPORT_PLUGIN(QtQuick2Plugin) Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) Q_IMPORT_PLUGIN(QtQuickControls1Plugin) +Q_IMPORT_PLUGIN(QmlFolderListModelPlugin) Q_IMPORT_PLUGIN(QmlSettingsPlugin) Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin) Q_IMPORT_PLUGIN(QtQuickControls2Plugin) diff --git a/src/qml/components/StorageLocations.qml b/src/qml/components/StorageLocations.qml index 241477e775..b5fac4aa4d 100644 --- a/src/qml/components/StorageLocations.qml +++ b/src/qml/components/StorageLocations.qml @@ -5,6 +5,10 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 +import QtQuick.Dialogs 1.3 + +import org.bitcoincore.qt 1.0 + import "../controls" ColumnLayout { @@ -25,5 +29,21 @@ ColumnLayout { ButtonGroup.group: group text: qsTr("Custom") description: qsTr("Choose the directory and storage device.") + onClicked: fileDialog.open() + } + FileDialog { + id: fileDialog + selectFolder: true + folder: optionsModel.getDefaultDataDirectory + onAccepted: { + optionsModel.setCustomDataDirString(fileDialog.fileUrls[0].toString()) + var customDataDir = fileDialog.fileUrl.toString(); + if (customDataDir !== "") { + optionsModel.setCustomDataDirArgs(customDataDir); + } + } + onRejected: { + console.log("Custom datadir selection canceled") + } } } diff --git a/src/qml/models/options_model.cpp b/src/qml/models/options_model.cpp index 61459dbf6c..082ed06513 100644 --- a/src/qml/models/options_model.cpp +++ b/src/qml/models/options_model.cpp @@ -9,13 +9,20 @@ #include #include #include +#include #include #include #include +#include +#include #include #include +#include +#include +#include + OptionsQmlModel::OptionsQmlModel(interfaces::Node& node) : m_node{node} { @@ -105,3 +112,28 @@ common::SettingsValue OptionsQmlModel::pruneSetting() const assert(!m_prune || m_prune_size_gb >= 1); return m_prune ? PruneGBtoMiB(m_prune_size_gb) : 0; } + +QString PathToQString(const fs::path &path) +{ + return QString::fromStdString(path.u8string()); +} + +QString OptionsQmlModel::getDefaultDataDirString() +{ + return PathToQString(GetDefaultDataDir()); +} + + +QUrl OptionsQmlModel::getDefaultDataDirectory() +{ + QString path = getDefaultDataDirString(); + return QUrl::fromLocalFile(path); +} + +void OptionsQmlModel::setCustomDataDirArgs(QString path) +{ + if (!path.isEmpty()) { + // TODO: add actual custom data wiring + qDebug() << "PlaceHolder: Created data directory: " << path; + } +} \ No newline at end of file diff --git a/src/qml/models/options_model.h b/src/qml/models/options_model.h index b67aa8c76c..86bdacd8f8 100644 --- a/src/qml/models/options_model.h +++ b/src/qml/models/options_model.h @@ -11,6 +11,8 @@ #include #include +#include +#include namespace interfaces { class Node; @@ -32,6 +34,8 @@ class OptionsQmlModel : public QObject Q_PROPERTY(int scriptThreads READ scriptThreads WRITE setScriptThreads NOTIFY scriptThreadsChanged) Q_PROPERTY(bool server READ server WRITE setServer NOTIFY serverChanged) Q_PROPERTY(bool upnp READ upnp WRITE setUpnp NOTIFY upnpChanged) + Q_PROPERTY(QString getDefaultDataDirString READ getDefaultDataDirString CONSTANT) + Q_PROPERTY(QUrl getDefaultDataDirectory READ getDefaultDataDirectory CONSTANT) public: explicit OptionsQmlModel(interfaces::Node& node); @@ -56,6 +60,15 @@ class OptionsQmlModel : public QObject void setServer(bool new_server); bool upnp() const { return m_upnp; } void setUpnp(bool new_upnp); + QString getDefaultDataDirString(); + QUrl getDefaultDataDirectory(); + Q_INVOKABLE void setCustomDataDirArgs(QString path); + +public Q_SLOTS: + void setCustomDataDirString(const QString &new_custom_datadir_string) { + m_custom_datadir_string = new_custom_datadir_string; + m_signalReceived = true; + } Q_SIGNALS: void dbcacheSizeMiBChanged(int new_dbcache_size_mib); @@ -66,6 +79,7 @@ class OptionsQmlModel : public QObject void scriptThreadsChanged(int new_script_threads); void serverChanged(bool new_server); void upnpChanged(bool new_upnp); + void customDataDirStringChanged(QString new_custom_datadir_string); private: interfaces::Node& m_node; @@ -83,6 +97,8 @@ class OptionsQmlModel : public QObject int m_script_threads; bool m_server; bool m_upnp; + QString m_custom_datadir_string; + bool m_signalReceived = false; common::SettingsValue pruneSetting() const; };