summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/corelib/io/qioring/tst_qioring.cpp7
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp14
-rw-r--r--tests/auto/corelib/platform/android/tst_android.cpp10
-rw-r--r--tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST2
-rw-r--r--tests/auto/other/android/deployment_settings/CMakeLists.txt11
-rw-r--r--tests/auto/other/android/deployment_settings/tst_android_deployment_settings.cpp4
-rw-r--r--tests/auto/tools/rcc/data/deduplication/deduplication.expected157
-rw-r--r--tests/auto/tools/rcc/data/deduplication/deduplication.qrc10
-rw-r--r--tests/auto/tools/rcc/data/deduplication/files/a.txt1
-rw-r--r--tests/auto/tools/rcc/data/deduplication/files/b.txt1
-rw-r--r--tests/auto/tools/rcc/data/deduplication/files/c_with_a_content.txt1
-rw-r--r--tests/auto/tools/rcc/tst_rcc.cpp5
-rw-r--r--tests/manual/wasm/localfiles/main.cpp242
13 files changed, 440 insertions, 25 deletions
diff --git a/tests/auto/corelib/io/qioring/tst_qioring.cpp b/tests/auto/corelib/io/qioring/tst_qioring.cpp
index 75d4fe68c55..5d5662cd9b4 100644
--- a/tests/auto/corelib/io/qioring/tst_qioring.cpp
+++ b/tests/auto/corelib/io/qioring/tst_qioring.cpp
@@ -20,6 +20,7 @@ class tst_QIORing : public QObject
Q_OBJECT
private slots:
+ void initTestCase();
void construct();
void sharedInstance();
void open();
@@ -33,6 +34,12 @@ private:
static qintptr openHelper(QIORing *ring, const QString &path, QIODevice::OpenMode flags);
};
+void tst_QIORing::initTestCase()
+{
+ if (QIORing::sharedInstance() == nullptr)
+ QSKIP("QIORing wasn't able to initialize on this platform. Test will be skipped.");
+}
+
void tst_QIORing::closeFile(qintptr fd)
{
#ifdef Q_OS_WIN
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
index d25a6d60cca..cae462c526b 100644
--- a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
+++ b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
@@ -381,8 +381,17 @@ void tst_QEventDispatcher::postEventFromThread()
QAtomicInt hadToQuit = false;
QAtomicInt done = false;
+ int threadCount = 500;
+ const int timeout = (1000
+#if defined(QT_GUI_LIB)
+ // Aggressively posting events may on some platforms rate limit us to
+ // the display's refresh rate, so give us enough time if that happens.
+ + ((1000.0 / qGuiApp->primaryScreen()->refreshRate()) * threadCount)
+#endif
+ );
+
threadPool->start([&]{
- int loop = 1000 / 10; // give it a second
+ int loop = timeout / 10;
while (!done && --loop)
QThread::sleep(std::chrono::milliseconds{10});
if (done)
@@ -399,8 +408,7 @@ void tst_QEventDispatcher::postEventFromThread()
}
} receiver;
- int count = 500;
- while (!hadToQuit && --count) {
+ while (!hadToQuit && --threadCount) {
threadPool->start([&receiver]{
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::User));
});
diff --git a/tests/auto/corelib/platform/android/tst_android.cpp b/tests/auto/corelib/platform/android/tst_android.cpp
index b4bb0323f8a..93d3f1102c9 100644
--- a/tests/auto/corelib/platform/android/tst_android.cpp
+++ b/tests/auto/corelib/platform/android/tst_android.cpp
@@ -251,6 +251,12 @@ void tst_Android::safeAreaWithWindowFlagsAndStates()
QFETCH(Qt::WindowStates, windowStates);
QFETCH(Qt::WindowFlags, windowFlags);
+ if ((QNativeInterface::QAndroidApplication::sdkVersion() > __ANDROID_API_V__) &&
+ qgetenv("QTEST_ENVIRONMENT").split(' ').contains("ci") &
+ (!(windowFlags & Qt::ExpandedClientAreaHint) &&
+ !(windowStates & Qt::WindowFullScreen)))
+ QSKIP("Normal fails on Android 16 (QTBUG-140846).");
+
QWidget widget;
QPalette palette = widget.palette();
palette.setColor(QPalette::Window, Qt::red);
@@ -338,6 +344,10 @@ void tst_Android::safeAreaWithWindowFlagsAndStates()
// QTBUG-107604
void tst_Android::testFullScreenDimensions()
{
+ if ((QNativeInterface::QAndroidApplication::sdkVersion() > __ANDROID_API_V__) &&
+ qgetenv("QTEST_ENVIRONMENT").split(' ').contains("ci") )
+ QSKIP("Keep on failing on Android 16 (QTBUG-141712).");
+
QJniObject activity = QNativeInterface::QAndroidApplication::context();
QVERIFY(activity.isValid());
diff --git a/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
index a8f73d73f4d..e69de29bb2d 100644
--- a/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
+++ b/tests/auto/gui/kernel/qguieventdispatcher/BLACKLIST
@@ -1,2 +0,0 @@
-[postEventFromThread]
-macos-26 developer-build # QTBUG-142185
diff --git a/tests/auto/other/android/deployment_settings/CMakeLists.txt b/tests/auto/other/android/deployment_settings/CMakeLists.txt
index d4546c0ca94..ed373493f97 100644
--- a/tests/auto/other/android/deployment_settings/CMakeLists.txt
+++ b/tests/auto/other/android/deployment_settings/CMakeLists.txt
@@ -33,11 +33,11 @@ set_target_properties(${target} PROPERTIES
my_package_source_dir "path/to/source/dir"
my_libs_property "some/path/to/lib2.so;some/path/to/lib3.so"
my_plugins_property "some/path/to/plugin2.so;some/path/to/plugin3.so"
-
- QT_ANDROID_SDK_BUILD_TOOLS_REVISION "23.0.2"
+ # Below build tools should match to minimum supported OS API level version
+ QT_ANDROID_SDK_BUILD_TOOLS_REVISION "28.0.3"
QT_ANDROID_MIN_SDK_VERSION "1"
QT_ANDROID_TARGET_SDK_VERSION "2"
- QT_ANDROID_COMPILE_SDK_VERSION "35"
+ QT_ANDROID_COMPILE_SDK_VERSION "36"
QT_ANDROID_APP_NAME "Android Deployment Settings Test"
QT_ANDROID_PACKAGE_NAME "org.qtproject.android_deployment_settings_test"
QT_ANDROID_DEPLOYMENT_DEPENDENCIES "dep1.so;dep2.so;dep3.so"
@@ -62,10 +62,11 @@ qt6_policy(SET QTP0002 OLD)
set(target tst_android_deployment_settings_old)
qt6_add_executable(${target} MANUAL_FINALIZATION EXCLUDE_FROM_ALL noop.cpp)
set_target_properties(${target} PROPERTIES
- QT_ANDROID_SDK_BUILD_TOOLS_REVISION "23.0.2"
+ # Below build tools should match to minimum supported OS API level version
+ QT_ANDROID_SDK_BUILD_TOOLS_REVISION "28.0.3"
QT_ANDROID_MIN_SDK_VERSION "1"
QT_ANDROID_TARGET_SDK_VERSION "2"
- QT_ANDROID_COMPILE_SDK_VERSION "35"
+ QT_ANDROID_COMPILE_SDK_VERSION "36"
QT_ANDROID_APP_NAME "Android Deployment Settings Test"
QT_ANDROID_PACKAGE_NAME "org.qtproject.android_deployment_settings_test"
QT_ANDROID_DEPLOYMENT_DEPENDENCIES "dep1.so;dep2.so;dep3.so"
diff --git a/tests/auto/other/android/deployment_settings/tst_android_deployment_settings.cpp b/tests/auto/other/android/deployment_settings/tst_android_deployment_settings.cpp
index 03724b7a225..6eed5506324 100644
--- a/tests/auto/other/android/deployment_settings/tst_android_deployment_settings.cpp
+++ b/tests/auto/other/android/deployment_settings/tst_android_deployment_settings.cpp
@@ -60,7 +60,7 @@ void tst_android_deployment_settings::DeploymentSettings_data()
QTest::addColumn<QString>("value");
QTest::newRow("sdkBuildToolsRevision") << "sdkBuildToolsRevision"
- << "23.0.2";
+ << "28.0.3";
QTest::newRow("deployment-dependencies") << "deployment-dependencies"
<< "dep1.so,dep2.so,dep3.so";
QTest::newRow("android-extra-plugins")
@@ -78,7 +78,7 @@ void tst_android_deployment_settings::DeploymentSettings_data()
QTest::newRow("android-target-sdk-version") << "android-target-sdk-version"
<< "2";
QTest::newRow("android-compile-sdk-version") << "android-compile-sdk-version"
- << "35";
+ << "36";
QTest::newRow("android-package-name") << "android-package-name"
<< "org.qtproject.android_deployment_settings_test";
QTest::newRow("android-app-name") << "android-app-name"
diff --git a/tests/auto/tools/rcc/data/deduplication/deduplication.expected b/tests/auto/tools/rcc/data/deduplication/deduplication.expected
new file mode 100644
index 00000000000..bd873437b46
--- /dev/null
+++ b/tests/auto/tools/rcc/data/deduplication/deduplication.expected
@@ -0,0 +1,157 @@
+/****************************************************************************
+** Resource object code
+**
+IGNORE:** Created by: The Resource Compiler for Qt version 6.9.0
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#ifdef _MSC_VER
+// disable informational message "function ... selected for automatic inline expansion"
+#pragma warning (disable: 4711)
+#endif
+
+static const unsigned char qt_resource_data[] = {
+ // b.txt
+ 0x0,0x0,0x0,0xb,
+ 0x62,
+ 0x20,0x74,0x65,0x73,0x74,0x20,0x66,0x69,0x6c,0x65,
+ // c_with_a_content.txt
+ 0x0,0x0,0x0,0xb,
+ 0x61,
+ 0x20,0x74,0x65,0x73,0x74,0x20,0x66,0x69,0x6c,0x65,
+ // b.txt
+ 0x0,0x0,0x0,0xb,
+ 0x62,
+ 0x20,0x74,0x65,0x73,0x74,0x20,0x66,0x69,0x6c,0x65,
+
+};
+
+static const unsigned char qt_resource_name[] = {
+ // files
+ 0x0,0x5,
+ 0x0,0x6d,0x2,0xc3,
+ 0x0,0x66,
+ 0x0,0x69,0x0,0x6c,0x0,0x65,0x0,0x73,
+ // b.txt
+ 0x0,0x5,
+ 0x0,0x65,0x5b,0xf4,
+ 0x0,0x62,
+ 0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+ // c_with_a_content.txt
+ 0x0,0x14,
+ 0x1,0x61,0x1d,0x34,
+ 0x0,0x63,
+ 0x0,0x5f,0x0,0x77,0x0,0x69,0x0,0x74,0x0,0x68,0x0,0x5f,0x0,0x61,0x0,0x5f,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x74,0x0,0x65,0x0,0x6e,0x0,0x74,0x0,0x2e,
+ 0x0,0x74,0x0,0x78,0x0,0x74,
+ // a.txt
+ 0x0,0x5,
+ 0x0,0x64,0x5b,0xf4,
+ 0x0,0x61,
+ 0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+ // alias_of_b_compress9.txt
+ 0x0,0x18,
+ 0xb,0x26,0xf,0xb4,
+ 0x0,0x61,
+ 0x0,0x6c,0x0,0x69,0x0,0x61,0x0,0x73,0x0,0x5f,0x0,0x6f,0x0,0x66,0x0,0x5f,0x0,0x62,0x0,0x5f,0x0,0x63,0x0,0x6f,0x0,0x6d,0x0,0x70,0x0,0x72,0x0,0x65,
+ 0x0,0x73,0x0,0x73,0x0,0x39,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+ // alias_of_b.txt
+ 0x0,0xe,
+ 0x1,0xa4,0x6d,0x34,
+ 0x0,0x61,
+ 0x0,0x6c,0x0,0x69,0x0,0x61,0x0,0x73,0x0,0x5f,0x0,0x6f,0x0,0x66,0x0,0x5f,0x0,0x62,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+ // alias_of_b_compress9_dupe.txt
+ 0x0,0x1d,
+ 0x9,0x4,0x7a,0x14,
+ 0x0,0x61,
+ 0x0,0x6c,0x0,0x69,0x0,0x61,0x0,0x73,0x0,0x5f,0x0,0x6f,0x0,0x66,0x0,0x5f,0x0,0x62,0x0,0x5f,0x0,0x63,0x0,0x6f,0x0,0x6d,0x0,0x70,0x0,0x72,0x0,0x65,
+ 0x0,0x73,0x0,0x73,0x0,0x39,0x0,0x5f,0x0,0x64,0x0,0x75,0x0,0x70,0x0,0x65,0x0,0x2e,0x0,0x74,0x0,0x78,0x0,0x74,
+
+};
+
+static const unsigned char qt_resource_struct[] = {
+ // :
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/files
+ 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x2,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ // :/files/a.txt
+ 0x0,0x0,0x0,0x4e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xf,
+TIMESTAMP:files/a.txt
+ // :/files/b.txt
+ 0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+TIMESTAMP:files/b.txt
+ // :/files/c_with_a_content.txt
+ 0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xf,
+TIMESTAMP:files/c_with_a_content.txt
+ // :/files/alias_of_b.txt
+ 0x0,0x0,0x0,0x94,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
+TIMESTAMP:files/b.txt
+ // :/files/alias_of_b_compress9_dupe.txt
+ 0x0,0x0,0x0,0xb6,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1e,
+TIMESTAMP:files/b.txt
+ // :/files/alias_of_b_compress9.txt
+ 0x0,0x0,0x0,0x5e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1e,
+TIMESTAMP:files/b.txt
+
+};
+
+#ifdef QT_NAMESPACE
+# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
+# define QT_RCC_MANGLE_NAMESPACE0(x) x
+# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
+# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
+# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
+ QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#else
+# define QT_RCC_PREPEND_NAMESPACE(name) name
+# define QT_RCC_MANGLE_NAMESPACE(name) name
+#endif
+
+#if defined(QT_INLINE_NAMESPACE)
+inline namespace QT_NAMESPACE {
+#elif defined(QT_NAMESPACE)
+namespace QT_NAMESPACE {
+#endif
+
+bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
+
+#ifdef QT_NAMESPACE
+}
+#endif
+
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
+int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
+int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
+{
+ int version = 3;
+ QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
+ (version, qt_resource_struct, qt_resource_name, qt_resource_data);
+ return 1;
+}
+
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wexit-time-destructors"
+#endif
+
+namespace {
+ struct initializer {
+ initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); }
+ ~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); }
+ } dummy;
+}
+
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
diff --git a/tests/auto/tools/rcc/data/deduplication/deduplication.qrc b/tests/auto/tools/rcc/data/deduplication/deduplication.qrc
new file mode 100644
index 00000000000..fd8a776503e
--- /dev/null
+++ b/tests/auto/tools/rcc/data/deduplication/deduplication.qrc
@@ -0,0 +1,10 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>files/a.txt</file>
+ <file>files/b.txt</file>
+ <file alias="files/alias_of_b.txt">files/b.txt</file>
+ <file>files/c_with_a_content.txt</file>
+ <file alias="files/alias_of_b_compress9.txt" compress="9">files/b.txt</file>
+ <file alias="files/alias_of_b_compress9_dupe.txt" compress="9">files/b.txt</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/rcc/data/deduplication/files/a.txt b/tests/auto/tools/rcc/data/deduplication/files/a.txt
new file mode 100644
index 00000000000..abd91bd4652
--- /dev/null
+++ b/tests/auto/tools/rcc/data/deduplication/files/a.txt
@@ -0,0 +1 @@
+a test file \ No newline at end of file
diff --git a/tests/auto/tools/rcc/data/deduplication/files/b.txt b/tests/auto/tools/rcc/data/deduplication/files/b.txt
new file mode 100644
index 00000000000..01e4d76fc57
--- /dev/null
+++ b/tests/auto/tools/rcc/data/deduplication/files/b.txt
@@ -0,0 +1 @@
+b test file \ No newline at end of file
diff --git a/tests/auto/tools/rcc/data/deduplication/files/c_with_a_content.txt b/tests/auto/tools/rcc/data/deduplication/files/c_with_a_content.txt
new file mode 100644
index 00000000000..abd91bd4652
--- /dev/null
+++ b/tests/auto/tools/rcc/data/deduplication/files/c_with_a_content.txt
@@ -0,0 +1 @@
+a test file \ No newline at end of file
diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp
index f5edfbcaa51..ba7e5841185 100644
--- a/tests/auto/tools/rcc/tst_rcc.cpp
+++ b/tests/auto/tools/rcc/tst_rcc.cpp
@@ -152,6 +152,11 @@ void tst_rcc::rcc_data()
QTest::newRow("legal") << m_dataPath + QLatin1StringView("/legal")
<< "legal.qrc" << "rcc_legal.cpp";
+
+ if (sizeof(size_t) == 8) {
+ const QString deduplicationPath = m_dataPath + QLatin1String("/deduplication");
+ QTest::newRow("deduplication") << deduplicationPath << "deduplication.qrc" << "deduplication.expected";
+ }
}
static QStringList readLinesFromFile(const QString &fileName,
diff --git a/tests/manual/wasm/localfiles/main.cpp b/tests/manual/wasm/localfiles/main.cpp
index 862bff50a47..90e8c2e90f6 100644
--- a/tests/manual/wasm/localfiles/main.cpp
+++ b/tests/manual/wasm/localfiles/main.cpp
@@ -5,6 +5,81 @@
#include <emscripten/val.h>
#include <emscripten.h>
+class DropZone : public QLabel
+{
+ Q_OBJECT
+public:
+ explicit DropZone(QWidget *parent = nullptr) : QLabel(parent)
+ {
+ setAcceptDrops(true);
+ setFrameStyle(QFrame::Box | QFrame::Sunken);
+ setAlignment(Qt::AlignCenter);
+ setText("Drop files here\n(will read first file)");
+ setMinimumSize(400, 150);
+ setStyleSheet("QLabel { background-color: #f0f0f0; border: 2px dashed #999; padding: 20px; }");
+ }
+
+Q_SIGNALS:
+ void filesDropped(const QList<QUrl> &urls);
+
+protected:
+ void dragEnterEvent(QDragEnterEvent *event) override
+ {
+ if (event->mimeData()->hasUrls()) {
+ event->acceptProposedAction();
+ setStyleSheet("QLabel { background-color: #e0f0ff; border: 2px dashed #0066cc; padding: 20px; }");
+ }
+ }
+
+ void dragLeaveEvent(QDragLeaveEvent *event) override
+ {
+ Q_UNUSED(event);
+ setStyleSheet("QLabel { background-color: #f0f0f0; border: 2px dashed #999; padding: 20px; }");
+ }
+
+ void dropEvent(QDropEvent *event) override
+ {
+ const QMimeData *mimeData = event->mimeData();
+
+ if (mimeData->hasUrls()) {
+ QList<QUrl> urls = mimeData->urls();
+
+ qDebug() << "=== Files Dropped ===";
+ qDebug() << "Number of files:" << urls.size();
+
+ for (int i = 0; i < urls.size(); ++i) {
+ const QUrl &url = urls.at(i);
+ qDebug() << "\n--- File" << (i + 1) << "---";
+ qDebug() << "URL:" << url;
+ qDebug() << "URL toString:" << url.toString();
+ qDebug() << "URL scheme:" << url.scheme();
+ qDebug() << "URL path:" << url.path();
+ qDebug() << "URL fileName:" << url.fileName();
+ qDebug() << "isLocalFile:" << url.isLocalFile();
+
+ if (url.isLocalFile()) {
+ QString filePath = url.toLocalFile();
+ qDebug() << "Local file path:" << filePath;
+
+ QFileInfo fileInfo(filePath);
+ qDebug() << "File name:" << fileInfo.fileName();
+ qDebug() << "File size:" << fileInfo.size();
+ qDebug() << "File exists:" << fileInfo.exists();
+ qDebug() << "Is readable:" << fileInfo.isReadable();
+ qDebug() << "Absolute path:" << fileInfo.absoluteFilePath();
+ qDebug() << "Last modified:" << fileInfo.lastModified().toString();
+ }
+ }
+ qDebug() << "===================\n";
+
+ event->acceptProposedAction();
+ emit filesDropped(urls);
+ }
+
+ setStyleSheet("QLabel { background-color: #f0f0f0; border: 2px dashed #999; padding: 20px; }");
+ }
+};
+
class AppWindow : public QObject
{
Q_OBJECT
@@ -12,21 +87,39 @@ public:
AppWindow() : m_layout(new QVBoxLayout(&m_loadFileUi)),
m_window(emscripten::val::global("window")),
m_showOpenFilePickerFunction(m_window["showOpenFilePicker"]),
- m_showSaveFilePickerFunction(m_window["showSaveFilePicker"])
+ m_showSaveFilePickerFunction(m_window["showSaveFilePicker"]),
+ m_fileDialog(new QFileDialog(&m_loadFileUi)),
+ m_isLoadOperation(true)
{
- addWidget<QLabel>("Filename filter");
-
const bool localFileApiAvailable =
!m_showOpenFilePickerFunction.isUndefined() && !m_showSaveFilePickerFunction.isUndefined();
m_useLocalFileApisCheckbox = addWidget<QCheckBox>("Use the window.showXFilePicker APIs");
m_useLocalFileApisCheckbox->setEnabled(localFileApiAvailable);
m_useLocalFileApisCheckbox->setChecked(localFileApiAvailable);
+ connect(m_useLocalFileApisCheckbox, &QCheckBox::toggled,
+ std::bind(&AppWindow::onUseLocalFileApisCheckboxToggled, this));
+
+ m_useStandardFileDialogCheckbox = addWidget<QCheckBox>("Use standard QFileDialog API");
+ connect(m_useStandardFileDialogCheckbox, &QCheckBox::toggled,
+ std::bind(&AppWindow::onUseStandardFileDialogCheckboxToggled, this));
+ m_useStandardFileDialogCheckbox->setChecked(true);
+
+ m_useExecModeCheckbox = addWidget<QCheckBox>("Use exec() instead of open()");
+ m_useExecModeCheckbox->setChecked(false);
+
+ addWidget<QLabel>("Filename filter");
- m_filterEdit = addWidget<QLineEdit>("Images (*.png *.jpg);;PDF (*.pdf);;*.txt");
+ m_filterCombo = addWidget<QComboBox>();
+ m_filterCombo->addItem("*");
+ m_filterCombo->addItem("Images (*.png *.jpg);;PDF (*.pdf);;*.txt");
+ m_filterCombo->setCurrentIndex(0); // Make "*" the default
auto* loadFile = addWidget<QPushButton>("Load File");
+ m_dropZone = addWidget<DropZone>();
+ connect(m_dropZone, &DropZone::filesDropped, this, &AppWindow::onFilesDropped);
+
m_fileInfo = addWidget<QLabel>("Opened file:");
m_fileInfo->setTextInteractionFlags(Qt::TextSelectableByMouse);
@@ -43,11 +136,13 @@ public:
m_loadFileUi.setLayout(m_layout);
- QObject::connect(m_useLocalFileApisCheckbox, &QCheckBox::toggled, std::bind(&AppWindow::onUseLocalFileApisCheckboxToggled, this));
QObject::connect(loadFile, &QPushButton::clicked, this, &AppWindow::onLoadClicked);
-
QObject::connect(m_saveFile, &QPushButton::clicked, std::bind(&AppWindow::onSaveClicked, this));
+
+ // Connect to both fileSelected and accepted signals for compatibility
+ QObject::connect(m_fileDialog, &QFileDialog::fileSelected, this, &AppWindow::onFileSelected);
+ QObject::connect(m_fileDialog, &QFileDialog::accepted, this, &AppWindow::onDialogAccepted);
}
void show() {
@@ -67,6 +162,29 @@ private Q_SLOTS:
m_showSaveFilePickerFunction : emscripten::val::undefined());
}
+ void onUseStandardFileDialogCheckboxToggled()
+ {
+ m_useLocalFileApisCheckbox->setChecked(m_useStandardFileDialogCheckbox->isChecked());
+ }
+
+ void onFilesDropped(const QList<QUrl> &urls)
+ {
+ if (urls.isEmpty())
+ return;
+
+ // Load the first dropped file
+ const QUrl &url = urls.first();
+
+ if (url.isLocalFile()) {
+ QString filePath = url.toLocalFile();
+ loadFileWithQFile(filePath);
+ } else {
+ // Try using the URL string directly for non-file:// URLs (like weblocalfile://)
+ QString urlString = url.toString();
+ loadFileWithQFile(urlString);
+ }
+ }
+
void onFileContentReady(const QString &fileName, const QByteArray &fileContents)
{
m_fileContent = fileContents;
@@ -89,16 +207,108 @@ private Q_SLOTS:
void onLoadClicked()
{
- QFileDialog::getOpenFileContent(
- m_filterEdit->text(),
- std::bind(&AppWindow::onFileContentReady, this, std::placeholders::_1, std::placeholders::_2),
- &m_loadFileUi);
+ if (m_useStandardFileDialogCheckbox->isChecked()) {
+ m_isLoadOperation = true;
+ m_fileDialog->setFileMode(QFileDialog::ExistingFile);
+ m_fileDialog->setAcceptMode(QFileDialog::AcceptOpen);
+ m_fileDialog->setNameFilter(m_filterCombo->currentText());
+ m_fileDialog->setWindowTitle("Open File");
+
+ if (m_useExecModeCheckbox->isChecked()) {
+ qDebug() << "Using exec() mode";
+ int result = m_fileDialog->exec();
+ if (result == QDialog::Accepted) {
+ QStringList files = m_fileDialog->selectedFiles();
+ if (!files.isEmpty()) {
+ onFileSelected(files.first());
+ }
+ }
+ } else {
+ qDebug() << "Using open() mode";
+ m_fileDialog->open();
+ }
+ } else {
+ QFileDialog::getOpenFileContent(
+ m_filterCombo->currentText(),
+ std::bind(&AppWindow::onFileContentReady, this, std::placeholders::_1, std::placeholders::_2),
+ &m_loadFileUi);
+ }
}
void onSaveClicked()
{
- m_fileInfo->setText("Saving file... (no result information with current API)");
- QFileDialog::saveFileContent(m_fileContent, m_savedFileNameEdit->text());
+ if (m_useStandardFileDialogCheckbox->isChecked()) {
+ m_isLoadOperation = false;
+ m_fileDialog->setFileMode(QFileDialog::AnyFile);
+ m_fileDialog->setAcceptMode(QFileDialog::AcceptSave);
+ m_fileDialog->setNameFilter(m_filterCombo->currentText());
+ m_fileDialog->setWindowTitle("Save File");
+ m_fileDialog->selectFile(m_savedFileNameEdit->text());
+
+ if (m_useExecModeCheckbox->isChecked()) {
+ qDebug() << "Using exec() mode for save";
+ int result = m_fileDialog->exec();
+ if (result == QDialog::Accepted) {
+ QStringList files = m_fileDialog->selectedFiles();
+ if (!files.isEmpty()) {
+ onFileSelected(files.first());
+ }
+ }
+ } else {
+ qDebug() << "Using open() mode for save";
+ m_fileDialog->open();
+ }
+ } else {
+ m_fileInfo->setText("Saving file... (no result information with current API)");
+ QFileDialog::saveFileContent(m_fileContent, m_savedFileNameEdit->text());
+ }
+ }
+
+ void onDialogAccepted()
+ {
+ QStringList files = m_fileDialog->selectedFiles();
+ if (!files.isEmpty()) {
+ onFileSelected(files.first());
+ }
+ }
+
+ void onFileSelected(const QString &fileName)
+ {
+ qDebug() << "onFileSelected" << fileName;
+
+ if (m_isLoadOperation) {
+ loadFileWithQFile(fileName);
+ } else {
+ saveFileWithQFile(fileName);
+ }
+ }
+
+ void loadFileWithQFile(const QString &fileName)
+ {
+ qDebug() << "loadFileWithQFile" << fileName;
+
+ QFile file(fileName);
+ if (file.open(QIODevice::ReadOnly)) {
+ qDebug() << "loadFileWithQFile" << fileName;
+ QByteArray fileContents = file.readAll();
+ file.close();
+ onFileContentReady(QFileInfo(fileName).fileName(), fileContents);
+ } else {
+ m_fileInfo->setText(QString("Failed to open file: %1").arg(file.errorString()));
+ }
+ }
+
+ void saveFileWithQFile(const QString &fileName)
+ {
+ QFile file(fileName);
+ if (file.open(QIODevice::WriteOnly)) {
+ qint64 bytesWritten = file.write(m_fileContent);
+ file.close();
+ bool success = (bytesWritten == m_fileContent.size());
+ m_fileInfo->setText(QString("File save result: %1").arg(success ? "success" : "failed"));
+ } else {
+ m_fileInfo->setText(QString("Failed to save file: %1").arg(file.errorString()));
+ }
}
private:
@@ -113,7 +323,10 @@ private:
QWidget m_loadFileUi;
QCheckBox* m_useLocalFileApisCheckbox;
- QLineEdit* m_filterEdit;
+ QCheckBox* m_useStandardFileDialogCheckbox;
+ QCheckBox* m_useExecModeCheckbox;
+ DropZone* m_dropZone;
+ QComboBox* m_filterCombo;
QVBoxLayout *m_layout;
QLabel* m_fileInfo;
QLabel* m_fileHash;
@@ -124,6 +337,9 @@ private:
emscripten::val m_showOpenFilePickerFunction;
emscripten::val m_showSaveFilePickerFunction;
+ QFileDialog* m_fileDialog;
+ bool m_isLoadOperation;
+
QByteArray m_fileContent;
};