Browse Source

android file open dialog

Sonnix 6 years ago
parent
commit
e265b567d5
5 changed files with 129 additions and 1 deletions
  1. 9 0
      Qqsp.pro
  2. 60 0
      androidfiledialog.cpp
  3. 36 0
      androidfiledialog.h
  4. 23 0
      mainwindow.cpp
  5. 1 1
      mainwindow.h

+ 9 - 0
Qqsp.pro

@@ -148,6 +148,15 @@ enable-webbox {
   HEADERS += qspwebbox.h
 }
 
+#CONFIG += enable-android
+
+enable-android {
+  DEFINES += _ANDROIDQT
+  QT += androidextras
+  SOURCES += androidfiledialog.cpp
+  HEADERS += androidfiledialog.h
+}
+
 isEmpty(TARGET_EXT) {
     win32 {
         TARGET_CUSTOM_EXT = .exe

+ 60 - 0
androidfiledialog.cpp

@@ -0,0 +1,60 @@
+#include "androidfiledialog.h"
+
+AndroidFileDialog::ResultReceiver::ResultReceiver(AndroidFileDialog *dialog) : _dialog(dialog) {}
+AndroidFileDialog::ResultReceiver::~ResultReceiver() {}
+
+void AndroidFileDialog::ResultReceiver::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data)
+{
+    jint RESULT_OK = QAndroidJniObject::getStaticField<jint>("android/app/Activity", "RESULT_OK");
+    if (receiverRequestCode == EXISTING_FILE_NAME_REQUEST && resultCode == RESULT_OK) {
+        QAndroidJniObject uri = data.callObjectMethod("getData", "()Landroid/net/Uri;");
+        QString path = uriToPath(uri);
+        _dialog->emitExistingFileNameReady(path);
+    } else {
+        _dialog->emitExistingFileNameReady(QString());
+    }
+}
+
+QString AndroidFileDialog::ResultReceiver::uriToPath(QAndroidJniObject uri)
+{
+    if (uri.toString().startsWith("file:", Qt::CaseInsensitive)) {
+        return uri.callObjectMethod("getPath", "()Ljava/lang/String;").toString();
+    } else {
+        QAndroidJniObject contentResolver = QtAndroid::androidActivity().callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;");
+        QAndroidJniObject cursor = contentResolver.callObjectMethod("query", "(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;", uri.object<jobject>(), 0, 0, 0, 0);
+        QAndroidJniObject DATA = QAndroidJniObject::fromString("_data");
+        jint columnIndex = cursor.callMethod<jint>("getColumnIndexOrThrow", "(Ljava/lang/String;)I", DATA.object<jstring>());
+        cursor.callMethod<jboolean>("moveToFirst", "()Z");
+        QAndroidJniObject result = cursor.callObjectMethod("getString", "(I)Ljava/lang/String;", columnIndex);
+        return result.isValid() ? result.toString() : QString();
+    }
+}
+
+AndroidFileDialog::AndroidFileDialog(QObject *parent) : QObject(parent)
+{
+    receiver = new ResultReceiver(this);
+}
+
+AndroidFileDialog::~AndroidFileDialog()
+{
+    delete receiver;
+}
+
+bool AndroidFileDialog::provideExistingFileName()
+{
+    QAndroidJniObject ACTION_GET_CONTENT = QAndroidJniObject::fromString("android.intent.action.GET_CONTENT");
+    QAndroidJniObject intent("android/content/Intent");
+    if (ACTION_GET_CONTENT.isValid() && intent.isValid()) {
+        intent.callObjectMethod("setAction", "(Ljava/lang/String;)Landroid/content/Intent;", ACTION_GET_CONTENT.object<jstring>());
+        intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", QAndroidJniObject::fromString("file/*").object<jstring>());
+        QtAndroid::startActivity(intent.object<jobject>(), EXISTING_FILE_NAME_REQUEST, receiver);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void AndroidFileDialog::emitExistingFileNameReady(QString result)
+{
+    emit existingFileNameReady(result);
+}

+ 36 - 0
androidfiledialog.h

@@ -0,0 +1,36 @@
+#ifndef ANDROIDFILEDIALOG_H
+#define ANDROIDFILEDIALOG_H
+
+#include <QObject>
+#include <QAndroidJniObject>
+#include <QtAndroid>
+#include <QAndroidActivityResultReceiver>
+
+class AndroidFileDialog : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit AndroidFileDialog(QObject *parent = 0);
+    virtual ~AndroidFileDialog();
+    bool provideExistingFileName();
+
+private:
+    class ResultReceiver : public QAndroidActivityResultReceiver {
+        AndroidFileDialog *_dialog;
+    public:
+        ResultReceiver(AndroidFileDialog *dialog);
+        virtual ~ResultReceiver();
+        void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data);
+        QString uriToPath(QAndroidJniObject uri);
+    };
+
+    static const int EXISTING_FILE_NAME_REQUEST = 1;
+    ResultReceiver *receiver;
+    void emitExistingFileNameReady(QString result);
+
+signals:
+    void existingFileNameReady(QString result);
+};
+
+#endif // ANDROIDFILEDIALOG_H

+ 23 - 0
mainwindow.cpp

@@ -19,6 +19,11 @@
 
 #include "optionsdialog.h"
 
+#ifdef _ANDROIDQT
+#include <QStandardPaths>
+#include "androidfiledialog.h"
+#endif
+
 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
 {
     resize(600, 450);
@@ -789,12 +794,30 @@ void MainWindow::ActionsListBoxDoAction(int action)
 
 void MainWindow::OnOpenGame()
 {
+#ifndef _ANDROIDQT
     QString path = QFileDialog::getOpenFileName(this, tr("Select game file"), GetLastPath(), tr("QSP games (*.qsp *.gam)"));
     if (!path.isEmpty())
     {
         SetLastPath(QFileInfo(path).canonicalPath());
         OpenGameFile(path);
     }
+#else
+    QString path = QFileDialog::getOpenFileName(this, tr("Select game file"), QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).at(0), tr("QSP games (*.qsp *.gam)"));
+    if (!path.isEmpty())
+    {
+        SetLastPath(QFileInfo(path).canonicalPath());
+        OpenGameFile(path);
+    }
+    return;
+    AndroidFileDialog fileDialog;
+    connect(&fileDialog, SIGNAL(existingFileNameReady(QString)), this, SLOT(OpenGameFile(QString)));
+    bool success = fileDialog.provideExistingFileName();
+    if (!success) {
+        qDebug() << "Problem with JNI or sth like that...";
+        disconnect(fileDialog, SIGNAL(existingFileNameReady(QString)), this, SLOT(OpenGameFile(QString)));
+        //or just delete fileDialog instead of disconnect
+    }
+#endif
 }
 
 void MainWindow::OnRestartGame()

+ 1 - 1
mainwindow.h

@@ -120,7 +120,6 @@ private:
     void SaveSettings(QString filePath = QString());
     void closeEvent(QCloseEvent *event);
     void keyPressEvent(QKeyEvent *event);
-    void OpenGameFile(const QString& path);
     void ActionsListBoxDoAction(int action);
 
     // Internal methods
@@ -192,6 +191,7 @@ private:
 
 private slots:
     void OnOpenGame();
+    void OpenGameFile(const QString& path);
     void OnRestartGame();
     void OnOpenSavedGame();
     void OnSaveGame(); //TODO: add quick save/load