소스 검색

Merge branch 'master' of http://192.168.14.36:3000/adc_pilot/modularization

fujiankuan 4 년 전
부모
커밋
8495713be6

+ 4 - 0
src/tool/map_lanetoxodr/adcxodrviewer.pro

@@ -30,6 +30,7 @@ QMAKE_LFLAGS += -no-pie
 
 
 SOURCES += \
+    filedialogextern.cpp \
     ivxodrtool.cpp \
         main.cpp \
     roaddigit.cpp \
@@ -51,11 +52,13 @@ SOURCES += \
     polevl.c \
     const.cpp \
     gnss_coordinate_convert.cpp \
+    simpleCustomEvent.cpp \
     xodrfunc.cpp \
     xodrscenfunc.cpp \
     xvmainwindow.cpp
 
 HEADERS += \
+    filedialogextern.h \
     ivxodrtool.h \
     roaddigit.h \
     myview.h \
@@ -73,6 +76,7 @@ HEADERS += \
     TinyXML/tinystr.h \
     TinyXML/tinyxml.h \
     gnss_coordinate_convert.h \
+    simpleCustomEvent.h \
     xodrfunc.h \
     xodrscenfunc.h \
     xvmainwindow.h

+ 10 - 2
src/tool/map_lanetoxodr/adcxodrviewer_android.pro

@@ -15,7 +15,7 @@ TEMPLATE = app
 
 CONFIG+= c++11
 
-DEFINES += Android
+DEFINES += ANDROID
 
 DEFINES += XODRViewer
 
@@ -34,6 +34,7 @@ QMAKE_LFLAGS += -no-pie
 
 
 SOURCES += \
+    filedialogextern.cpp \
     ivxodrtool.cpp \
         main.cpp \
     roaddigit.cpp \
@@ -55,11 +56,13 @@ SOURCES += \
     polevl.c \
     const.cpp \
     gnss_coordinate_convert.cpp \
+    simpleCustomEvent.cpp \
     xodrfunc.cpp \
     xodrscenfunc.cpp \
     xvmainwindow.cpp
 
 HEADERS += \
+    filedialogextern.h \
     ivxodrtool.h \
     roaddigit.h \
     myview.h \
@@ -77,6 +80,7 @@ HEADERS += \
     TinyXML/tinystr.h \
     TinyXML/tinyxml.h \
     gnss_coordinate_convert.h \
+    simpleCustomEvent.h \
     xodrfunc.h \
     xodrscenfunc.h \
     xvmainwindow.h
@@ -104,7 +108,11 @@ DISTFILES += \ \
     android/gradle/wrapper/gradle-wrapper.properties \
     android/gradlew \
     android/gradlew.bat \
-    android/res/values/libs.xml
+    android/res/values/libs.xml \
+    android/src/an/qt/extendsQtWithJava/ExtendsQtNative.java \
+    android/src/an/qt/extendsQtWithJava/ExtendsQtWithJava.java
+#    android/src/an/qt/ExtendsQtNative.java \
+ #    android/src/an/qt/ExtendsQtWithJava.java
 
 
 unix:INCLUDEPATH += /usr/include/eigen3

+ 91 - 0
src/tool/map_lanetoxodr/android/AndroidManifest.xml

@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<manifest package="adc.iv.xodrviewer" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto">
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
+
+    <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
+         Remove the comment if you do not require these default permissions. -->
+    <!-- %%INSERT_PERMISSIONS -->
+
+    <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
+         Remove the comment if you do not require these default features. -->
+    <!-- %%INSERT_FEATURES -->
+
+    <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
+
+    <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="XODRViewer" android:icon="@drawable/icon">
+        <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="an.qt.extendsQtWithJava.ExtendsQtWithJava" android:label="XODRViewer" android:screenOrientation="unspecified" android:launchMode="singleTop">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+
+            <!-- Application arguments -->
+            <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
+            <!-- Application arguments -->
+
+            <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
+            <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
+            <meta-data android:name="android.app.repository" android:value="default"/>
+            <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
+            <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
+            <!-- Deploy Qt libs as part of package -->
+            <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
+            <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
+            <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
+            <!-- Run with local libs -->
+            <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
+            <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
+            <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
+            <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
+            <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
+            <!-- Used to specify custom system library path to run with local system libs -->
+            <!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> -->
+            <!--  Messages maps -->
+            <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
+            <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
+            <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
+            <meta-data android:value="@string/unsupported_android_version" android:name="android.app.unsupported_android_version"/>
+            <!--  Messages maps -->
+
+            <!-- Splash screen -->
+            <!-- Orientation-specific (portrait/landscape) data is checked first. If not available for current orientation,
+                 then android.app.splash_screen_drawable. For best results, use together with splash_screen_sticky and
+                 use hideSplashScreen() with a fade-out animation from Qt Android Extras to hide the splash screen when you
+                 are done populating your window with content. -->
+            <!-- meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/logo_portrait" / -->
+            <!-- meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/logo_landscape" / -->
+            <!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
+            <!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
+            <!-- Splash screen -->
+
+            <!-- Background running -->
+            <!-- Warning: changing this value to true may cause unexpected crashes if the
+                          application still try to draw after
+                          "applicationStateChanged(Qt::ApplicationSuspended)"
+                          signal is sent! -->
+            <meta-data android:name="android.app.background_running" android:value="false"/>
+            <!-- Background running -->
+
+            <!-- auto screen scale factor -->
+            <meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
+            <!-- auto screen scale factor -->
+
+            <!-- extract android style -->
+            <!-- available android:values :
+                * default - In most cases this will be the same as "full", but it can also be something else if needed, e.g., for compatibility reasons
+                * full - useful QWidget & Quick Controls 1 apps
+                * minimal - useful for Quick Controls 2 apps, it is much faster than "full"
+                * none - useful for apps that don't use any of the above Qt modules
+                -->
+            <meta-data android:name="android.app.extract_android_style" android:value="default"/>
+            <!-- extract android style -->
+    </activity>
+
+    <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
+
+    </application>
+
+<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"/>
+</manifest>

BIN
src/tool/map_lanetoxodr/android/libs/android-support-v4.jar


+ 1 - 0
src/tool/map_lanetoxodr/android/libs/android-support-v4.jar.properties

@@ -0,0 +1 @@
+src = E:\\ProgramFiles\\Tools\\Android\\android-sdk\\extras\\android\\m2repository\\com\\android\\support\\support-v4

+ 12 - 0
src/tool/map_lanetoxodr/android/src/an/qt/extendsQtWithJava/ExtendsQtNative.java

@@ -0,0 +1,12 @@
+package an.qt.extendsQtWithJava;
+import java.lang.String;
+
+public class ExtendsQtNative
+{
+    //public static native String GetQtVersion();
+    //public static native void OnLocationReady(int result, double longitude, double latitude);
+    //public static native void OnImageCaptured(int result, String filePath);
+    //public static native void onFileManager(int result, String fileurl);
+    public static native void onFileManager(int result, String[] fileurls);
+
+}

+ 348 - 0
src/tool/map_lanetoxodr/android/src/an/qt/extendsQtWithJava/ExtendsQtWithJava.java

@@ -0,0 +1,348 @@
+package an.qt.extendsQtWithJava;
+import android.Manifest;
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.ClipData;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.app.PendingIntent;
+import android.widget.Toast;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.location.LocationManager;
+import android.location.Criteria;
+import android.provider.Settings;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationProvider;
+import java.lang.ClassLoader;
+import dalvik.system.DexClassLoader;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import java.io.File;
+
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+
+
+public class ExtendsQtWithJava extends org.qtproject.qt5.android.bindings.QtActivity
+{
+    //private final static int GET_LOCATION_REQUEST_CODE = 1;
+    //private final static int CAPTURE_IMAGE_REQUEST_CODE = 2;
+    private final static int FILE_MANAGER_REQUEST_CODE = 3;
+    final private int REQUEST_CODE_ASK_PERMISSIONS = 123;
+   // private static NotificationManager m_notificationManager;
+    private static ExtendsQtWithJava m_instance;
+    private static Class m_nativeClass = null;
+    private final static String TAG = "extendsQt";
+    public LocationManager m_lm = null;
+
+    public ExtendsQtWithJava(){
+        Log.d(TAG, "ExtendsQtWithJava constructor");
+        m_instance = this;
+    }
+
+    /**
+     * 获得类的成员变量值,包括私有成员
+     * @param instance 被调用的类
+     * @param variableName 成员变量名
+     *
+     */
+    public static Object get(Object instance, String variableName)
+    {
+        Class targetClass = instance.getClass().getSuperclass();
+        org.qtproject.qt5.android.bindings.QtActivity superInst = (org.qtproject.qt5.android.bindings.QtActivity)targetClass.cast(instance);
+        Log.d(TAG, "super class name - " + targetClass.getName() + " super instance -" + superInst);
+        Field field;
+        try {
+            field = targetClass.getDeclaredField(variableName);
+            Log.d(TAG, "field name - " + field.getName());
+            field.setAccessible(true);//访问私有必须调用
+            return field.get(superInst);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static void loadExtendsQtNative(){
+    if(m_nativeClass == null){
+        DexClassLoader loader = (DexClassLoader)get(m_instance, "m_classLoader");
+        Log.d(TAG, "loader - " + loader);
+        if(loader != null){
+            try{
+                m_nativeClass = loader.loadClass("an.qt.extendsQtWithJava.ExtendsQtNative");
+                Log.d(TAG, "load ExtendsQtNative OK!");
+            }catch(ClassNotFoundException e){
+                Log.d(TAG, "load ExtendsQtNative failed");
+            }
+        }
+    }
+    }
+
+    protected  List<Uri> getUris(Intent data){
+        List<Uri> uris = new ArrayList<Uri>();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            ClipData clipData = data.getClipData();
+            if (null != clipData) {
+                for (int i = 0; i < clipData.getItemCount(); i++) {
+                    ClipData.Item item = clipData.getItemAt(i);
+                    uris.add(item.getUri());
+                }
+            } else {
+                uris.add(data.getData());
+            }
+        } else {
+                uris.add(data.getData());
+        }
+        return uris;
+    }
+
+
+    public static void fileManagerActivity(boolean multi){
+        Log.d(TAG, "fileManagerActivity1");
+        //m_instance.startActivity(new Intent(action));
+        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.setType("*/*");//设置类型,我这里是任意类型,任意后缀的可以这样写。
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multi == true);//多选
+        intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+//        intent.putExtra("pointer", 12345678);//无法用putExtra 传递数据在 onActivityResult 中接收,放在下面的it中也不行
+//        Bundle b=new Bundle();
+//        b.putString("listenB", "zp");
+//        intent.putExtras(b);
+
+        //Intent it = Intent.createChooser(intent, "choose file");
+        m_instance.startActivityForResult(intent,FILE_MANAGER_REQUEST_CODE);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data){
+        //super.onActivityResult(requestCode, resultCode, data);
+        Log.d(TAG, "onActivityResult:"+requestCode+";"+resultCode);
+        switch(requestCode){
+        case FILE_MANAGER_REQUEST_CODE:
+        {
+                String arr[] = {};
+            if (resultCode == Activity.RESULT_OK) {
+
+//            data.getIntExtra("pointer", 0);//无法接收数据
+//            Bundle b=data.getExtras();
+
+            //doFileMenageryResult(requestCode,resultCode, data);
+/*            if (resultCode == Activity.RESULT_OK) {//是否选择,没选择就不会继续
+                Uri uri = data.getData();//得到uri,后面就是将uri转化成file的过程。
+                Log.d(TAG, "uri:" + uri);
+                Log.d(TAG, "uri Scheme:" + uri.getScheme());
+                String path = uri.getPath();//= getPath(this, uri);
+
+                if ("file".equalsIgnoreCase(uri.getScheme())){//使用第三方应用打开
+                        Log.d(TAG, "uri:---1");
+                    path = uri.getPath();
+                }else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4+
+                        Log.d(TAG, "uri:---2");
+                    path = getPath(this, uri);
+                }
+                Log.d(TAG, "fpath:" + path);
+
+
+                ExtendsQtNative.onFileManager(resultCode, path);
+
+                */
+                List<Uri> uris = getUris(data);
+               List<String> paths = new ArrayList<String>();
+               for(Uri uri : uris){
+                       String path = "";
+                   if ("file".equalsIgnoreCase(uri.getScheme())){//使用第三方应用打开
+                       Log.d(TAG, "uri:---1");
+                           path = uri.getPath();
+                       }else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4+
+                           Log.d(TAG, "uri:---2");
+                           path = getPath(this, uri);
+                       }
+                                Log.d(TAG, "fpath:" + path);
+                   if(path!=null && !path.isEmpty()){
+                       paths.add(path);
+                   }
+               }
+
+
+               Log.d(TAG, "fpaths:" + paths.toString());
+
+               arr = paths.toArray(new String[paths.size()]);
+               Log.d(TAG, "arr:" + arr.toString());
+
+               ExtendsQtNative.onFileManager(resultCode, arr);
+            }else if(resultCode == Activity.RESULT_CANCELED ){
+                //String arr[] = {};
+                ExtendsQtNative.onFileManager(resultCode,  arr);
+            }
+        }
+
+            break;
+        default:
+            super.onActivityResult(requestCode, resultCode, data);
+        }
+    }
+
+/**
+ * 专为Android4.4设计的从Uri获取文件绝对路径,以前的方法已不好使
+ */
+public String getPath(final Context context, final Uri uri) {
+        Log.d(TAG, "getPath:---1");
+    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+    Log.d(TAG, "getPath:---2-getAuthority:"+uri.getAuthority());
+    // DocumentProvider
+    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+        Log.d(TAG, "getPath:---3");
+        // ExternalStorageProvider
+        if (isExternalStorageDocument(uri)) {
+            final String docId = DocumentsContract.getDocumentId(uri);
+            final String[] split = docId.split(":");
+            final String type = split[0];
+
+            if ("primary".equalsIgnoreCase(type)) {
+                return Environment.getExternalStorageDirectory() + "/" + split[1];
+            }
+        }
+        // DownloadsProvider
+        else if (isDownloadsDocument(uri)) {
+
+            final String id = DocumentsContract.getDocumentId(uri);
+            final Uri contentUri = ContentUris.withAppendedId(
+                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+
+            return getDataColumn(context, contentUri, null, null);
+        }
+        // MediaProvider
+        else if (isMediaDocument(uri)) {
+                Log.d(TAG, "getPath:---4");
+            final String docId = DocumentsContract.getDocumentId(uri);
+            Log.d(TAG, "docId:"+docId);
+            final String[] split = docId.split(":");
+            final String type = split[0];
+            Log.d(TAG, "docId split:"+Arrays.toString(split));
+            Uri contentUri = null;
+            if ("image".equals(type)) {
+                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+            } else if ("video".equals(type)) {
+                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+            } else if ("audio".equals(type)) {
+                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+            }
+
+            final String selection = "_id=?";
+            final String[] selectionArgs = new String[]{split[1]};
+            Log.d(TAG, "contentUri:"+contentUri);
+
+            return getDataColumn(context, contentUri, selection, selectionArgs);
+        }
+    }
+    // MediaStore (and general)
+    else if ("content".equalsIgnoreCase(uri.getScheme())) {
+        return getDataColumn(context, uri, null, null);
+    }
+    // File
+    else if ("file".equalsIgnoreCase(uri.getScheme())) {
+        return uri.getPath();
+    }
+    return null;
+}
+
+/**
+ * Get the value of the data column for this Uri. This is useful for
+ * MediaStore Uris, and other file-based ContentProviders.
+ *
+ * @param context       The context.
+ * @param uri           The Uri to query.
+ * @param selection     (Optional) Filter used in the query.
+ * @param selectionArgs (Optional) Selection arguments used in the query.
+ * @return The value of the _data column, which is typically a file path.
+ */
+public String getDataColumn(Context context, Uri uri, String selection,
+                            String[] selectionArgs) {
+        Log.d(TAG, "getDataColumn:"+uri+";"+selection+";"+Arrays.toString(selectionArgs));
+//content://media/external/images/media;  _id=?;[715746]
+    Cursor cursor = null;
+    final String column = "_data";
+    final String[] projection = {column};
+
+    try {
+/**********权限校验需要 >=sdk23 版本*****************************************/
+        int hasWriteContactsPermisson = ContextCompat.checkSelfPermission(context,
+                        android.Manifest.permission.READ_EXTERNAL_STORAGE);
+        Log.d(TAG, "hasWriteContactsPermisson:"+hasWriteContactsPermisson);
+        if(hasWriteContactsPermisson !=
+            PackageManager.PERMISSION_GRANTED)
+        {
+                ActivityCompat.requestPermissions(m_instance,new String[]
+                {Manifest.permission.WRITE_CONTACTS},
+                REQUEST_CODE_ASK_PERMISSIONS);
+
+            return "";
+        }
+/********************************/
+        Log.d(TAG, "getDataColumn--1");
+        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
+                null);
+        Log.d(TAG, "getDataColumn--2");
+        if (cursor != null && cursor.moveToFirst()) {
+                Log.d(TAG, "getDataColumn--3");
+            final int column_index = cursor.getColumnIndexOrThrow(column);
+            Log.d(TAG, "getDataColumn--4");
+            return cursor.getString(column_index);
+        }
+    } catch(Exception e){
+        Log.d(TAG, "getDataColumn err:"+e.getMessage());
+    }finally {
+        if (cursor != null)
+            cursor.close();
+    }
+    return "null";
+}
+
+
+/**
+ * @param uri The Uri to check.
+ * @return Whether the Uri authority is ExternalStorageProvider.
+ */
+public boolean isExternalStorageDocument(Uri uri) {
+    return "com.android.externalstorage.documents".equals(uri.getAuthority());
+}
+
+/**
+ * @param uri The Uri to check.
+ * @return Whether the Uri authority is DownloadsProvider.
+ */
+public boolean isDownloadsDocument(Uri uri) {
+    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+}
+
+/**
+ * @param uri The Uri to check.
+ * @return Whether the Uri authority is MediaProvider.
+ */
+public boolean isMediaDocument(Uri uri) {
+    return "com.android.providers.media.documents".equals(uri.getAuthority());
+}
+
+
+}
+

+ 136 - 0
src/tool/map_lanetoxodr/filedialogextern.cpp

@@ -0,0 +1,136 @@
+#include "filedialogextern.h"
+#include "simpleCustomEvent.h"
+#include <QEvent>
+#include <QCoreApplication>
+
+#ifdef ANDROID
+#include <QtAndroidExtras/QAndroidJniObject>
+#include <QFile>
+#include<unistd.h>
+//#include <QGuiApplication>
+#include <QAndroidJniEnvironment>
+#else
+#include <QFileDialog>
+#include <QDir>
+#endif
+
+#include <QMessageBox>
+
+#include <QDebug>
+#define DEBUG     qDebug()<<__func__<<__LINE__
+
+static QObject *g_listener = 0;
+
+FileDialogExtern::FileDialogExtern(QObject *parent) : QObject(parent)
+{
+
+}
+
+
+bool FileDialogExtern::event(QEvent *e)
+{
+#ifdef ANDROID
+    if(e->type() == SimpleCustomEvent::eventType())
+    {
+        SimpleCustomEvent *sce = (SimpleCustomEvent*)e;
+        qDebug()<<"FileDialogExtern::event:"<<sce->m_requestCode<<sce->m_resultCode;
+        if(sce->m_requestCode == 3){
+
+
+            if(sce->m_resultCode == -1){
+                QStringList paths = sce->m_msg.toStringList();
+                DEBUG<<paths.count()<<paths;
+                if(paths.isEmpty()) return QObject::event(e);
+                setCurrentFiles(paths);
+                setCurrentFile(paths.at(0));
+//                QMessageBox::information(this,"warn","hello",QMessageBox::YesAll);
+                emit accepted();
+            }else if (sce->m_resultCode == 0) {
+                DEBUG<<"cancel";
+                emit rejected();
+            }
+
+        }/*else
+        {
+            m_captureState->setText("cancel");
+        }*/
+        return true;
+    }
+#endif
+    return QObject::event(e);
+}
+
+
+
+bool FileDialogExtern::open(){
+DEBUG;
+
+#ifdef ANDROID
+
+    //QAndroidJniObject javaAction = QAndroidJniObject::fromString(name);
+    g_listener = this;
+    QAndroidJniObject::callStaticMethod<void>("an/qt/extendsQtWithJava/ExtendsQtWithJava",
+                                       "fileManagerActivity",
+                                       "(Z)V",(m_fileMode == OpenFiles));
+
+
+#else
+
+QString fdir = m_folder.isEmpty()?QDir::currentPath():m_folder;
+QStringList fpaths;
+if(m_fileMode == OpenFile){
+    QString fpath = QFileDialog::getOpenFileName(nullptr,m_title,fdir,"all file(*)");
+    if(!fpath.isEmpty())
+        fpaths.push_back(fpath);
+}else if (m_fileMode == OpenFiles) {
+    fpaths = QFileDialog::getOpenFileNames(nullptr,m_title,fdir,"all file(*)");
+}
+DEBUG<<fpaths.count()<<fpaths;
+if(!fpaths.isEmpty()){
+    setCurrentFiles(fpaths);
+    setCurrentFile(fpaths.at(0));
+    emit accepted();
+}else {
+    emit rejected();
+}
+#endif
+
+    return true;
+}
+
+#ifdef ANDROID
+void onFileManager(JNIEnv *env, jobject thiz,int result, jobjectArray fileUrls)
+{
+    qDebug() << "onFileManager, result - " << result ;
+   int length =  env->GetArrayLength(fileUrls);
+   QStringList paths;
+   int req = 3;
+   int ret = result;
+   if(result == -1){
+       //ret = 3;
+
+       for (int i=0;i<length;i++) {
+           //jstring fileUrl= dynamic_cast<jstring>(env->GetObjectArrayElement(fileUrls,i));
+
+           QString path=QAndroidJniObject::fromLocalRef(env->GetObjectArrayElement(fileUrls,i)).toString();
+
+          // qDebug() << "onFileManager, result - " << result << " fileUrl - " << fileUrl;
+
+           //jboolean copy = false;
+            //const char *nativeString = env->GetStringUTFChars(fileUrl, &copy);
+            //qDebug() << "onFileManager, nativeString - " << nativeString;
+//            QString path = nativeString;
+//            env->ReleaseStringUTFChars(fileUrl, nativeString);
+            if(!path.isEmpty() && QFile::exists(path))
+                paths.push_back(path);
+            qDebug() << "onFileManager, path - " << path;
+       }
+   }else if(result != 0){
+       ret = -3;
+       qDebug() << "could not read the captured file!";
+   }
+DEBUG<<paths;
+    //QGuiApplication::postEvent(g_listener, new SimpleCustomEvent(ret, image));
+    QCoreApplication::postEvent(g_listener, new SimpleCustomEvent(req,ret, paths));
+}
+#endif

+ 56 - 0
src/tool/map_lanetoxodr/filedialogextern.h

@@ -0,0 +1,56 @@
+#ifndef FILEDIALOGEXTERN_H
+#define FILEDIALOGEXTERN_H
+
+#include <QObject>
+
+class FileDialogExtern : public QObject
+{
+    Q_OBJECT
+    Q_ENUMS(FileMode)
+    Q_PROPERTY(NOTIFY accepted)
+    Q_PROPERTY(NOTIFY rejected)
+    Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
+    Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged)
+    Q_PROPERTY(QString currentFile READ currentFile WRITE setCurrentFile NOTIFY currentFileChanged)
+    Q_PROPERTY(QStringList currentFiles READ currentFiles WRITE setCurrentFiles NOTIFY currentFilesChanged)
+    Q_PROPERTY(FileMode fileMode READ fileMode WRITE setFileMode NOTIFY fileModeChanged)
+
+
+public:
+    enum FileMode{OpenFile,OpenFiles,Saveile};
+    explicit FileDialogExtern(QObject *parent = nullptr);
+    bool event(QEvent *);
+
+    Q_INVOKABLE bool open();
+
+    QString title() const{return m_title;}
+    QString folder() const{return m_folder;}
+    QString currentFile() const{return m_currentFile;}
+    QStringList currentFiles() const{return m_currentFiles;}
+    FileMode fileMode() const{return m_fileMode;}
+
+signals:
+    void accepted();
+    void rejected();
+    void titleChanged(QString title);
+    void folderChanged(QString folder);
+    void currentFilesChanged(QStringList currentFiles);
+    void currentFileChanged(QString currentFile);
+    void fileModeChanged(FileMode fileMode);
+
+public slots:
+    void setTitle(const QString &title){m_title = title; emit titleChanged(m_title);}
+    void setFolder(const QString &folder){m_folder = folder; emit folderChanged(m_folder);}
+    void setCurrentFile(const QString &currentFile){m_currentFile = currentFile; emit currentFileChanged(m_currentFile);}
+    void setCurrentFiles(const QStringList &currentFiles){m_currentFiles = currentFiles; emit currentFilesChanged(m_currentFiles);}
+    void setFileMode(const FileMode &fileMode){m_fileMode = fileMode; emit fileModeChanged(m_fileMode);}
+
+private:
+    QString m_title;
+    QString m_folder;
+    QString m_currentFile;
+    QStringList m_currentFiles;
+    FileMode m_fileMode;
+};
+
+#endif // FILEDIALOGEXTERN_H

+ 14 - 3
src/tool/map_lanetoxodr/main.cpp

@@ -8,7 +8,7 @@
 #include <QApplication>
 
 
-#ifdef Android
+#ifdef ANDROID
 #include <QAndroidJniEnvironment>
 #include <QtAndroid>
 //#include <QAndr
@@ -17,10 +17,18 @@
 #endif
 
 
+#ifdef XODRViewer
+#include "filedialogextern.h"
+#endif
+#ifdef ANDROID
+#include "simpleCustomEvent.h"
+#endif
+
 
 
 
-#ifdef Android
+
+#ifdef ANDROID
 
 bool requestPermission() {
    QtAndroid::PermissionResult  r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
@@ -43,10 +51,13 @@ int main(int argc, char *argv[])
 
     QApplication a(argc, argv);
 
-#ifdef Android
+#ifdef ANDROID
 
     requestPermission();
 
+
+    registerNativeMethods();
+
 #endif
 
 #ifdef XODRViewer

+ 71 - 6
src/tool/map_lanetoxodr/myview.cpp

@@ -9,8 +9,15 @@ MyView::MyView(QWidget *parent) :
     beishu(1.00000)
 {
     setDragMode(QGraphicsView::ScrollHandDrag);
+
+//    grabGesture(Qt::PanGesture);
+    grabGesture(Qt::PinchGesture);
+ //   grabGesture(Qt::SwipeGesture);
 }
 
+
+
+
 void MyView::mousePressEvent(QMouseEvent *event)
 {
 //    qDebug("x is %d",event->pos().x());
@@ -19,6 +26,7 @@ void MyView::mousePressEvent(QMouseEvent *event)
 }
 void MyView::mouseMoveEvent(QMouseEvent *event)
 {
+    if(mbInPinch == true)return;
     QGraphicsView::mouseMoveEvent(event);
 
 //    QScrollBar * ps = verticalScrollBar();
@@ -59,12 +67,12 @@ void MyView::zoomIn()
     int centery = (psV->value() + psV->size().height()/2)/beishu;
     int centerx = (psH->value() + psH->size().width()/2)/beishu;
 
-#ifndef Android
+#ifndef ANDROID
     scale(1.1, 1.1);
     beishu *= 1.1;
 #else
-    scale(1.3, 1.3);
-    beishu *= 1.3;
+    scale(1.6, 1.6);
+    beishu *= 1.6;
 #endif
  //   centerOn(450, 700 - (200 / beishu));
 
@@ -98,12 +106,12 @@ void MyView::zoomOut()
     int centery = (psV->value() + psV->size().height()/2)/beishu;
     int centerx = (psH->value() + psH->size().width()/2)/beishu;
 
-#ifndef Android
+#ifndef ANDROID
     scale(1 / 1.1, 1 / 1.1);
     beishu /= 1.1;
 #else
-    scale(1 / 1.3, 1 / 1.3);
-    beishu /= 1.3;
+    scale(1 / 1.6, 1 / 1.6);
+    beishu /= 1.6;
 #endif
 //    centerOn(450, 700 - (200 / beishu));
 
@@ -145,3 +153,60 @@ void MyView::mouseDoubleClickEvent(QMouseEvent *event)
     emit dbclickxy(viewx,viewy);
     qDebug("view x is %d view y is %d ",viewx,viewy);
 }
+
+bool MyView::event(QEvent *event)
+{
+    if (event->type() == QEvent::Gesture)
+    {
+ //       qDebug("gestrue event");
+ //       return true;
+        return gestureEvent(static_cast<QGestureEvent*>(event));
+    }
+
+    return QGraphicsView::event(event);
+}
+
+bool MyView::gestureEvent(QGestureEvent *event)
+{
+    if (QGesture *pinch = event->gesture(Qt::PinchGesture))
+        pinchTriggered(static_cast<QPinchGesture *>(pinch));
+    return true;
+}
+
+void MyView::pinchTriggered(QPinchGesture *gesture)
+{
+
+    static double currentStepScaleFactor = 1;
+    static double oldfactor = 1;
+    QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
+    if (changeFlags & QPinchGesture::ScaleFactorChanged) {
+        currentStepScaleFactor = gesture->totalScaleFactor();
+        mbInPinch = true;
+    }
+    if (gesture->state() == Qt::GestureFinished) {
+//        scaleFactor *= currentStepScaleFactor;
+//        qDebug("scale is %f ",currentStepScaleFactor);
+
+        currentStepScaleFactor = 1;
+        oldfactor = 1;
+        mbInPinch = false;
+    }
+
+    int width,hgt;
+    width = sceneRect().width();
+    hgt = sceneRect().height();
+    QScrollBar * psV = verticalScrollBar();
+    QScrollBar * psH = horizontalScrollBar();
+
+    int centery = (psV->value() + psV->size().height()/2)/beishu;
+    int centerx = (psH->value() + psH->size().width()/2)/beishu;
+
+    double fscale = currentStepScaleFactor/oldfactor;
+    scale(fscale,fscale);
+    beishu *= fscale;
+    oldfactor = currentStepScaleFactor;
+
+    centerOn(centerx,centery);
+
+}
+

+ 11 - 0
src/tool/map_lanetoxodr/myview.h

@@ -11,6 +11,9 @@
 #include <QGraphicsItem>
 #include <QKeyEvent>
 
+#include <QGestureEvent>
+#include <QPinchGesture>
+
 class MyView : public QGraphicsView
 {
     Q_OBJECT
@@ -26,6 +29,8 @@ protected:
     void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
     void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
     void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+
+    bool event(QEvent *event) Q_DECL_OVERRIDE;
 public Q_SLOTS:
     void zoomIn();  // 放大
     void zoomOut();  // 缩小
@@ -36,6 +41,12 @@ signals:
 private:
     bool bottonstatus = false;
     QPoint myview_lastMousePos;
+
+private:
+    bool gestureEvent(QGestureEvent *event);
+    void pinchTriggered(QPinchGesture*);
+
+    bool mbInPinch = false;
 };
 
 #endif // MYVIEW_H

+ 65 - 0
src/tool/map_lanetoxodr/simpleCustomEvent.cpp

@@ -0,0 +1,65 @@
+#include "simpleCustomEvent.h"
+
+#ifdef ANDROID
+#include <QFile>
+#include <QApplication>
+#include <QAndroidJniEnvironment>
+#include <QAndroidJniObject>
+#include <jni.h>
+#include "simpleCustomEvent.h"
+#include <QAndroidJniObject>
+#endif
+
+QEvent::Type SimpleCustomEvent::m_evType = (QEvent::Type)QEvent::None;
+
+SimpleCustomEvent::SimpleCustomEvent(int requestCode , int resultCode, const QVariant &msg)
+    : QEvent(eventType()), m_requestCode(requestCode), m_resultCode(resultCode),m_msg(msg)
+{}
+
+SimpleCustomEvent::~SimpleCustomEvent()
+{
+
+}
+
+QEvent::Type SimpleCustomEvent::eventType()
+{
+    if(m_evType == QEvent::None)
+    {
+        m_evType = (QEvent::Type)registerEventType();
+    }
+    return m_evType;
+}
+
+
+#ifdef ANDROID
+void onFileManager(JNIEnv *env, jobject thiz,int result, jobjectArray fileUrl);
+jclass g_extendsNative = 0;
+bool registerNativeMethods()
+{
+    JNINativeMethod methods[] {
+        {"onFileManager", "(I[Ljava/lang/String;)V", (void*)onFileManager}
+    };
+
+    const char *classname = "an/qt/extendsQtWithJava/ExtendsQtNative";
+    jclass clazz;
+    QAndroidJniEnvironment env;
+
+    QAndroidJniObject javaClass(classname);
+    clazz = env->GetObjectClass(javaClass.object<jobject>());
+    //clazz = env->FindClass(classname);
+    //qDebug() << "find ExtendsQtNative - " << clazz;
+    bool result = false;
+    if(clazz)
+    {
+        //g_extendsNative = static_cast<jclass>(env->NewGlobalRef(clazz));
+        jint ret = env->RegisterNatives(clazz,
+                                        methods,
+                                        sizeof(methods) / sizeof(methods[0]));
+        env->DeleteLocalRef(clazz);
+        //qDebug() << "RegisterNatives return - " << ret;
+        result = ret >= 0;
+    }
+    if(env->ExceptionCheck()) env->ExceptionClear();
+    return result;
+}
+#endif

+ 31 - 0
src/tool/map_lanetoxodr/simpleCustomEvent.h

@@ -0,0 +1,31 @@
+#ifndef SIMPLECUSTOMEVENT_H
+#define SIMPLECUSTOMEVENT_H
+#include <QEvent>
+#include <QString>
+#include <QVariant>
+
+//#include <QAndroidJniEnvironment>
+
+
+
+class SimpleCustomEvent : public QEvent
+{
+public:
+    SimpleCustomEvent(int requestCode = 0, int resultCode = 0, const QVariant &msg = QVariant());
+    ~SimpleCustomEvent();
+
+    static Type eventType();
+
+    int m_requestCode;
+    int m_resultCode;
+    QVariant m_msg;
+
+
+private:
+    static Type m_evType;
+};
+
+//void onFileManager(JNIEnv *env, jobject thiz,int result, jobjectArray fileUrl);
+bool registerNativeMethods();
+
+#endif // SIMPLECUSTOMEVENT_H

+ 24 - 5
src/tool/map_lanetoxodr/xvmainwindow.cpp

@@ -40,6 +40,8 @@ XVMainWindow::XVMainWindow(QWidget *parent) :
 
     myview->setScene(mpscene);
 
+    connect(&mFileDialog,SIGNAL(accepted()),this,SLOT(onFileOpen()));
+
     setWindowTitle("ADC OpenDrive Viewer");
 }
 
@@ -76,17 +78,18 @@ void XVMainWindow::on_actionLoad_triggered()
     }
 
 
-#ifndef Android
+#ifndef ANDROID
     QString strpath = QFileDialog::getOpenFileName(this,"Load XODR",".","*.xodr");
     if(strpath.isEmpty())return;
+    LoadXODR(strpath);
+    UpdateScene();
 #else
 //    QMessageBox::warning(this,"warning","no file dialog.",QMessageBox::YesAll);
-    QString strpath = "/storage/emulated/0/map.xodr";
-
+//    QString strpath = "/storage/emulated/0/map.xodr";
+    mFileDialog.open();
 
 #endif
-    LoadXODR(strpath);
-    UpdateScene();
+
 }
 
 void XVMainWindow::LoadXODR(QString strpath)
@@ -294,3 +297,19 @@ void XVMainWindow::paintEvent(QPaintEvent * event)
         mbRefresh = false;
     }
 }
+
+void XVMainWindow::onFileOpen()
+{
+    QString strpath = mFileDialog.currentFile();
+    if(strpath.isEmpty())return;
+    LoadXODR(strpath);
+    UpdateScene();
+}
+
+void XVMainWindow::on_actionHelp_triggered()
+{
+    QString helpinfo = tr("Load:加载文件(后缀名为.xodr)\nZoom In:放大\nZomm Out:缩小\nZoom One:恢复默认视图\nSet Move:移动显示中心\n"
+                          "Reset Move:恢复默认显示中心\n\ntips: 在屏幕上双击选择道路(查看道路id)或者选择点(用来移动中心点 \n      "
+                          "在屏幕上可以移动查看区域");
+    QMessageBox::information(this,"Help",helpinfo,QMessageBox::Yes);
+}

+ 11 - 0
src/tool/map_lanetoxodr/xvmainwindow.h

@@ -12,6 +12,11 @@
 
 #include "OpenDrive/OpenDriveXmlParser.h"
 
+#include "filedialogextern.h"
+#ifdef ANDROID
+#include "simpleCustomEvent.h"
+#endif
+
 namespace Ui {
 class XVMainWindow;
 }
@@ -39,12 +44,16 @@ private slots:
 
     void on_actionReset_Move_triggered();
 
+    void onFileOpen();
+
 public:
      void resizeEvent(QResizeEvent *event);
 
 private slots:
     virtual void paintEvent(QPaintEvent *);
 
+     void on_actionHelp_triggered();
+
 private:
      void LoadXODR(QString strpath);
      void UpdateScene();
@@ -65,6 +74,8 @@ private:
     double mfsely = 0;
 
     bool mbRefresh = false;
+
+    FileDialogExtern mFileDialog;
 };
 
 #endif // XVMAINWINDOW_H

+ 6 - 0
src/tool/map_lanetoxodr/xvmainwindow.ui

@@ -33,6 +33,7 @@
     <addaction name="actionZoom_One"/>
     <addaction name="actionSet_Move"/>
     <addaction name="actionReset_Move"/>
+    <addaction name="actionHelp"/>
    </widget>
    <addaction name="menuFile"/>
   </widget>
@@ -67,6 +68,11 @@
     <string>Reset Move</string>
    </property>
   </action>
+  <action name="actionHelp">
+   <property name="text">
+    <string>Help</string>
+   </property>
+  </action>
  </widget>
  <resources/>
  <connections/>