12 changed files with 514 additions and 21 deletions
			
			
		@ -1,5 +1,44 @@ | 
				
			|||||
import QtQuick 2.0 | 
					import QtQuick 2.10 | 
				
			||||
 | 
					import de.skycoder42.QtMvvm.Core 1.0 | 
				
			||||
 | 
					import de.skycoder42.QtMvvm.Quick 1.0 | 
				
			||||
 | 
					
 | 
				
			||||
Item { | 
					FileChooser { | 
				
			||||
 | 
						id: _fileChooser | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						property var msgConfig | 
				
			||||
 | 
						property MessageResult msgResult | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						signal closed() | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						title: msgConfig.title | 
				
			||||
 | 
						folderUrl: msgConfig.defaultValue | 
				
			||||
 | 
						type: { | 
				
			||||
 | 
							if(msgConfig.subType == "open") | 
				
			||||
 | 
								return FileChooser.OpenDocument; | 
				
			||||
 | 
							else if(msgConfig.subType == "files") | 
				
			||||
 | 
								return FileChooser.OpenMultipleDocuments; | 
				
			||||
 | 
							else if(msgConfig.subType == "save") | 
				
			||||
 | 
								return FileChooser.CreateDocument; | 
				
			||||
 | 
							else if(msgConfig.subType == "get") //special value for android only | 
				
			||||
 | 
								return FileChooser.GetContent; | 
				
			||||
 | 
							else { | 
				
			||||
 | 
								return FileChooser.OpenDocument; | 
				
			||||
 | 
							} | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						onAccepted: { | 
				
			||||
 | 
							if(msgResult) { | 
				
			||||
 | 
								msgResult.complete(MessageConfig.Ok, result); | 
				
			||||
 | 
								msgResult = null; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							closed(); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						onRejected: { | 
				
			||||
 | 
							if(msgResult) { | 
				
			||||
 | 
								msgResult.complete(MessageConfig.Cancel); | 
				
			||||
 | 
								msgResult = null; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							closed(); | 
				
			||||
 | 
						} | 
				
			||||
} | 
					} | 
				
			||||
 | 
				
			|||||
@ -1,5 +1,32 @@ | 
				
			|||||
import QtQuick 2.0 | 
					import QtQuick 2.10 | 
				
			||||
 | 
					import de.skycoder42.QtMvvm.Core 1.0 | 
				
			||||
 | 
					import de.skycoder42.QtMvvm.Quick 1.0 | 
				
			||||
 | 
					
 | 
				
			||||
Item { | 
					FileChooser { | 
				
			||||
 | 
						id: _folderChooser | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						property var msgConfig | 
				
			||||
 | 
						property MessageResult msgResult | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						signal closed() | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						title: msgConfig.title | 
				
			||||
 | 
						folderUrl: msgConfig.defaultValue | 
				
			||||
 | 
						type: FileChooser.OpenDocumentTree | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						onAccepted: { | 
				
			||||
 | 
							if(msgResult) { | 
				
			||||
 | 
								msgResult.complete(MessageConfig.Ok, result); | 
				
			||||
 | 
								msgResult = null; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							closed(); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						onRejected: { | 
				
			||||
 | 
							if(msgResult) { | 
				
			||||
 | 
								msgResult.complete(MessageConfig.Cancel); | 
				
			||||
 | 
								msgResult = null; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							closed(); | 
				
			||||
 | 
						} | 
				
			||||
} | 
					} | 
				
			||||
 | 
				
			|||||
@ -0,0 +1,304 @@ | 
				
			|||||
 | 
					#include "androidfilechooser.h" | 
				
			||||
 | 
					#include <QtAndroidExtras/QtAndroid> | 
				
			||||
 | 
					#include <QtAndroidExtras/QAndroidJniEnvironment> | 
				
			||||
 | 
					using namespace QtMvvm; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					AndroidFileChooser::AndroidFileChooser(QObject *parent) : | 
				
			||||
 | 
						QObject(parent), | 
				
			||||
 | 
						_title(), | 
				
			||||
 | 
						_folderUrl(), | 
				
			||||
 | 
						_type(OpenDocument), | 
				
			||||
 | 
						_mimeTypes(QStringLiteral("*/*")), | 
				
			||||
 | 
						_flags(OpenableFlag | AlwaysGrantWriteFlag), | 
				
			||||
 | 
						_active(false), | 
				
			||||
 | 
						_result() | 
				
			||||
 | 
					{} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					AndroidFileChooser::~AndroidFileChooser() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						qt_noop(); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QString AndroidFileChooser::title() const | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						return _title; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QUrl AndroidFileChooser::folderUrl() const | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						return _folderUrl; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					AndroidFileChooser::ChooserType AndroidFileChooser::type() const | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						return _type; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QStringList AndroidFileChooser::mimeTypes() const | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						return _mimeTypes; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					AndroidFileChooser::ChooserFlags AndroidFileChooser::chooserFlags() const | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						return _flags; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QVariant AndroidFileChooser::result() const | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						return _result; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::open() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						if(_active) | 
				
			||||
 | 
							return; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QAndroidJniObject intent; | 
				
			||||
 | 
						switch (_type) { | 
				
			||||
 | 
						case GetContent: | 
				
			||||
 | 
							intent = createGetIntent(); | 
				
			||||
 | 
							break; | 
				
			||||
 | 
						case OpenDocument: | 
				
			||||
 | 
							intent = createOpenIntent(); | 
				
			||||
 | 
							break; | 
				
			||||
 | 
						case OpenMultipleDocuments: | 
				
			||||
 | 
							intent = createOpenMultipleIntent(); | 
				
			||||
 | 
							break; | 
				
			||||
 | 
						case CreateDocument: | 
				
			||||
 | 
							intent = createSaveIntent(); | 
				
			||||
 | 
							break; | 
				
			||||
 | 
						case OpenDocumentTree: | 
				
			||||
 | 
							intent = createOpenTreeIntent(); | 
				
			||||
 | 
							break; | 
				
			||||
 | 
						default: | 
				
			||||
 | 
							Q_UNREACHABLE(); | 
				
			||||
 | 
							break; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						auto chooserIntent = QAndroidJniObject::callStaticObjectMethod("android/content/Intent", "createChooser", | 
				
			||||
 | 
																					   "(Landroid/content/Intent;Ljava/lang/CharSequence;)Landroid/content/Intent;", | 
				
			||||
 | 
																					   intent.object(), | 
				
			||||
 | 
																					   QAndroidJniObject::fromString(_title).object()); | 
				
			||||
 | 
						_active = true; | 
				
			||||
 | 
						QtAndroid::startActivity(chooserIntent, | 
				
			||||
 | 
												 _flags.testFlag(PersistPermissionsFlag) ? RequestCodePersist : RequestCodeNormal, | 
				
			||||
 | 
												 this); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::setTitle(const QString &title) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						if (_title == title) | 
				
			||||
 | 
							return; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						_title = title; | 
				
			||||
 | 
						emit titleChanged(title); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::setFolderUrl(const QUrl &contentUrl) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						if (_folderUrl == contentUrl) | 
				
			||||
 | 
							return; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						_folderUrl = contentUrl; | 
				
			||||
 | 
						emit folderUrlChanged(contentUrl); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::setType(AndroidFileChooser::ChooserType type) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						if (_type == type) | 
				
			||||
 | 
							return; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						_type = type; | 
				
			||||
 | 
						emit typeChanged(type); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::setMimeTypes(const QStringList &mimeType) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						if (_mimeTypes == mimeType) | 
				
			||||
 | 
							return; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						_mimeTypes = mimeType; | 
				
			||||
 | 
						emit mimeTypesChanged(mimeType); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::setChooserFlags(ChooserFlags chooserFlags) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						if (_flags == chooserFlags) | 
				
			||||
 | 
							return; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						_flags = chooserFlags; | 
				
			||||
 | 
						emit chooserFlagsChanged(chooserFlags); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						if(receiverRequestCode == RequestCodeNormal || receiverRequestCode == RequestCodePersist) { | 
				
			||||
 | 
							static const auto RESULT_OK = QAndroidJniObject::getStaticField<jint>("android/app/Activity", "RESULT_OK"); | 
				
			||||
 | 
							static const auto FLAG_GRANT_READ_URI_PERMISSION = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_GRANT_READ_URI_PERMISSION"); | 
				
			||||
 | 
							static const auto FLAG_GRANT_WRITE_URI_PERMISSION = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_GRANT_WRITE_URI_PERMISSION"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							if(resultCode == RESULT_OK) { | 
				
			||||
 | 
								if(receiverRequestCode == RequestCodePersist) { | 
				
			||||
 | 
									auto flags = data.callMethod<jint>("getFlags"); | 
				
			||||
 | 
									flags &= (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
									auto resolver = QtAndroid::androidContext().callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;"); | 
				
			||||
 | 
									resolver.callMethod<void>("takePersistableUriPermission", "(Landroid/net/Uri;I)V", | 
				
			||||
 | 
															  data.callObjectMethod("getData", "()Landroid/net/Uri;").object(), | 
				
			||||
 | 
															  flags); | 
				
			||||
 | 
								} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								_result.clear(); | 
				
			||||
 | 
								if(_type == OpenMultipleDocuments) { | 
				
			||||
 | 
									auto clipData = data.callObjectMethod("getClipData", "()Landroid/content/ClipData;"); | 
				
			||||
 | 
									if(clipData.isValid()) { | 
				
			||||
 | 
										QList<QUrl> urls; | 
				
			||||
 | 
										const auto cnt = clipData.callMethod<jint>("getItemCount"); | 
				
			||||
 | 
										for(auto i = 0; i < cnt; i++) { | 
				
			||||
 | 
											auto item = clipData.callObjectMethod("getItemAt", "(I)Landroid/content/ClipData$Item;", i); | 
				
			||||
 | 
											urls.append(item.callObjectMethod("getUri", "()Landroid/net/Uri;").toString()); | 
				
			||||
 | 
										} | 
				
			||||
 | 
										_result = QVariant::fromValue(urls); | 
				
			||||
 | 
									} | 
				
			||||
 | 
								} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								if(!_result.isValid()) | 
				
			||||
 | 
									_result = QUrl(data.callObjectMethod("getDataString", "()Ljava/lang/String;").toString()); | 
				
			||||
 | 
								emit resultChanged(_result); | 
				
			||||
 | 
								_active = false; | 
				
			||||
 | 
								emit accepted(); | 
				
			||||
 | 
							} else { | 
				
			||||
 | 
								_active = false; | 
				
			||||
 | 
								emit rejected(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
						} | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QAndroidJniObject AndroidFileChooser::createGetIntent() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						static const auto ACTION_GET_CONTENT = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_GET_CONTENT"); | 
				
			||||
 | 
						static const auto EXTRA_LOCAL_ONLY = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "EXTRA_LOCAL_ONLY"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", | 
				
			||||
 | 
												 ACTION_GET_CONTENT.object()); | 
				
			||||
 | 
						setupBasic(intent); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						if(_flags.testFlag(LocalOnlyFlag)) { | 
				
			||||
 | 
							intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;", | 
				
			||||
 | 
													EXTRA_LOCAL_ONLY.object(), true); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						return intent; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QAndroidJniObject AndroidFileChooser::createOpenIntent() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						static const auto ACTION_OPEN_DOCUMENT = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_OPEN_DOCUMENT"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", | 
				
			||||
 | 
												 ACTION_OPEN_DOCUMENT.object()); | 
				
			||||
 | 
						setupBasic(intent); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						return intent; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QAndroidJniObject AndroidFileChooser::createOpenMultipleIntent() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						static const auto EXTRA_ALLOW_MULTIPLE = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "EXTRA_ALLOW_MULTIPLE"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						auto intent = createOpenIntent(); | 
				
			||||
 | 
						intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;", | 
				
			||||
 | 
												EXTRA_ALLOW_MULTIPLE.object(), true); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						return intent; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QAndroidJniObject AndroidFileChooser::createSaveIntent() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						static const auto ACTION_CREATE_DOCUMENT = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_CREATE_DOCUMENT"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", | 
				
			||||
 | 
												 ACTION_CREATE_DOCUMENT.object()); | 
				
			||||
 | 
						setupBasic(intent); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						return intent; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					QAndroidJniObject AndroidFileChooser::createOpenTreeIntent() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						static const auto ACTION_OPEN_DOCUMENT_TREE = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_OPEN_DOCUMENT_TREE"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", | 
				
			||||
 | 
												 ACTION_OPEN_DOCUMENT_TREE.object()); | 
				
			||||
 | 
						setupBasic(intent, true); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						return intent; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void AndroidFileChooser::setupBasic(QAndroidJniObject &intent, bool asTree) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						static const auto CATEGORY_OPENABLE = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "CATEGORY_OPENABLE"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						static const auto FLAG_GRANT_PERSISTABLE_URI_PERMISSION = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_GRANT_PERSISTABLE_URI_PERMISSION"); | 
				
			||||
 | 
						static const auto FLAG_GRANT_READ_URI_PERMISSION = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_GRANT_READ_URI_PERMISSION"); | 
				
			||||
 | 
						static const auto FLAG_GRANT_WRITE_URI_PERMISSION = QAndroidJniObject::getStaticField<jint>("android/content/Intent", "FLAG_GRANT_WRITE_URI_PERMISSION"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						static const auto EXTRA_MIME_TYPES = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "EXTRA_MIME_TYPES"); | 
				
			||||
 | 
						static const auto EXTRA_INITIAL_URI = [](){ | 
				
			||||
 | 
							if(QtAndroid::androidSdkVersion() >= 26) //Android Oreo
 | 
				
			||||
 | 
								return QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "EXTRA_INITIAL_URI"); | 
				
			||||
 | 
							else | 
				
			||||
 | 
								return QAndroidJniObject(); | 
				
			||||
 | 
						}(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						//set the acceptable mimetypes
 | 
				
			||||
 | 
						if(!asTree) { | 
				
			||||
 | 
							if(_mimeTypes.size() == 1) { | 
				
			||||
 | 
								intent.callObjectMethod("setTypeAndNormalize", "(Ljava/lang/String;)Landroid/content/Intent;", | 
				
			||||
 | 
														QAndroidJniObject::fromString(_mimeTypes.first()).object()); | 
				
			||||
 | 
							} else { | 
				
			||||
 | 
								intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", | 
				
			||||
 | 
														QAndroidJniObject::fromString(QStringLiteral("*/*")).object()); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								if(!_mimeTypes.isEmpty()) { | 
				
			||||
 | 
									QAndroidJniEnvironment env; | 
				
			||||
 | 
									auto strClass = env->FindClass("java/lang/String"); | 
				
			||||
 | 
									QAndroidJniObject strArray(env->NewObjectArray(_mimeTypes.size(), strClass, nullptr)); | 
				
			||||
 | 
									for(auto i = 0; i < _mimeTypes.size(); i++) { | 
				
			||||
 | 
										auto mimeStr = QAndroidJniObject::callStaticObjectMethod("android/content/Intent", "normalizeMimeType", | 
				
			||||
 | 
																								 "(Ljava/lang/String;)Ljava/lang/String;", | 
				
			||||
 | 
																								 QAndroidJniObject::fromString(_mimeTypes[i]).object()); | 
				
			||||
 | 
										env->SetObjectArrayElement(strArray.object<jobjectArray>(), i, mimeStr.object()); | 
				
			||||
 | 
									} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
									intent.callObjectMethod("putExtra", "(Ljava/lang/String;[Ljava/lang/String;)Landroid/content/Intent;", | 
				
			||||
 | 
															EXTRA_MIME_TYPES.object(), strArray.object()); | 
				
			||||
 | 
								} | 
				
			||||
 | 
							} | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						//Set the intent flags
 | 
				
			||||
 | 
						auto aFlags = FLAG_GRANT_READ_URI_PERMISSION; | 
				
			||||
 | 
						if(_type != GetContent) | 
				
			||||
 | 
							aFlags |= FLAG_GRANT_PERSISTABLE_URI_PERMISSION; | 
				
			||||
 | 
						if(_type == CreateDocument || _flags.testFlag(AlwaysGrantWriteFlag)) | 
				
			||||
 | 
							aFlags |= FLAG_GRANT_WRITE_URI_PERMISSION; | 
				
			||||
 | 
						intent.callObjectMethod("addFlags", "(I)Landroid/content/Intent;", | 
				
			||||
 | 
												aFlags); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						//set openable
 | 
				
			||||
 | 
						if(_flags.testFlag(OpenableFlag) && !asTree) { | 
				
			||||
 | 
							intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", | 
				
			||||
 | 
													CATEGORY_OPENABLE.object()); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						if(EXTRA_INITIAL_URI.isValid()) { | 
				
			||||
 | 
							auto uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", | 
				
			||||
 | 
																				 "(Ljava/lang/String;)Landroid/net/Uri;", | 
				
			||||
 | 
																				 QAndroidJniObject::fromString(_folderUrl.toString()).object()); | 
				
			||||
 | 
							intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;", | 
				
			||||
 | 
													EXTRA_INITIAL_URI.object(), uri.object()); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,106 @@ | 
				
			|||||
 | 
					#ifndef QTMVVM_ANDROIDFILECHOOSER_H | 
				
			||||
 | 
					#define QTMVVM_ANDROIDFILECHOOSER_H | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <QtCore/QObject> | 
				
			||||
 | 
					#include <QtCore/QUrl> | 
				
			||||
 | 
					#include <QtCore/QVariant> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <QtAndroidExtras/QAndroidActivityResultReceiver> | 
				
			||||
 | 
					#include <QtAndroidExtras/QAndroidJniObject> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace QtMvvm { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class AndroidFileChooser : public QObject, public QAndroidActivityResultReceiver | 
				
			||||
 | 
					{ | 
				
			||||
 | 
						Q_OBJECT | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						Q_PROPERTY(QUrl folderUrl READ folderUrl WRITE setFolderUrl NOTIFY folderUrlChanged) | 
				
			||||
 | 
						Q_PROPERTY(ChooserType type READ type WRITE setType NOTIFY typeChanged) | 
				
			||||
 | 
						Q_PROPERTY(QStringList mimeTypes READ mimeTypes WRITE setMimeTypes NOTIFY mimeTypesChanged) | 
				
			||||
 | 
						Q_PROPERTY(ChooserFlags chooserFlags READ chooserFlags WRITE setChooserFlags NOTIFY chooserFlagsChanged) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						Q_PROPERTY(QVariant result READ result NOTIFY resultChanged) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					public: | 
				
			||||
 | 
						enum ChooserType { | 
				
			||||
 | 
							GetContent = 0, | 
				
			||||
 | 
							OpenDocument = 1, | 
				
			||||
 | 
							OpenMultipleDocuments = 2, | 
				
			||||
 | 
							CreateDocument = 3, | 
				
			||||
 | 
							OpenDocumentTree = 4 | 
				
			||||
 | 
						}; | 
				
			||||
 | 
						Q_ENUM(ChooserType) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						enum ChooserFlag { | 
				
			||||
 | 
							OpenableFlag = 0x01, | 
				
			||||
 | 
							LocalOnlyFlag = 0x02, | 
				
			||||
 | 
							AlwaysGrantWriteFlag = 0x04, | 
				
			||||
 | 
							PersistPermissionsFlag = 0x08 | 
				
			||||
 | 
						}; | 
				
			||||
 | 
						Q_DECLARE_FLAGS(ChooserFlags, ChooserFlag) | 
				
			||||
 | 
						Q_FLAG(ChooserFlags) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						explicit AndroidFileChooser(QObject *parent = nullptr); | 
				
			||||
 | 
						~AndroidFileChooser(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QString title() const; | 
				
			||||
 | 
						QUrl folderUrl() const; | 
				
			||||
 | 
						ChooserType type() const; | 
				
			||||
 | 
						QStringList mimeTypes() const; | 
				
			||||
 | 
						ChooserFlags chooserFlags() const; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QVariant result() const; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					public Q_SLOTS: | 
				
			||||
 | 
						void open(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						void setTitle(const QString &title); | 
				
			||||
 | 
						void setFolderUrl(const QUrl &folderUrl); | 
				
			||||
 | 
						void setType(ChooserType type); | 
				
			||||
 | 
						void setMimeTypes(const QStringList &mimeTypes); | 
				
			||||
 | 
						void setChooserFlags(ChooserFlags chooserFlags); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Q_SIGNALS: | 
				
			||||
 | 
						void accepted(); | 
				
			||||
 | 
						void rejected(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						void titleChanged(const QString &title); | 
				
			||||
 | 
						void folderUrlChanged(const QUrl &folderUrl); | 
				
			||||
 | 
						void typeChanged(ChooserType type); | 
				
			||||
 | 
						void mimeTypesChanged(const QStringList &mimeTypes); | 
				
			||||
 | 
						void chooserFlagsChanged(ChooserFlags chooserFlags); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						void resultChanged(QVariant result); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					protected: | 
				
			||||
 | 
						void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data) override; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					private: | 
				
			||||
 | 
						const static int RequestCodeNormal = 0x1091c657; | 
				
			||||
 | 
						const static int RequestCodePersist = 0x1091c658; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QString _title; | 
				
			||||
 | 
						QUrl _folderUrl; | 
				
			||||
 | 
						ChooserType _type; | 
				
			||||
 | 
						QStringList _mimeTypes; | 
				
			||||
 | 
						ChooserFlags _flags; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						bool _active; | 
				
			||||
 | 
						QVariant _result; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						QAndroidJniObject createGetIntent(); | 
				
			||||
 | 
						QAndroidJniObject createOpenIntent(); | 
				
			||||
 | 
						QAndroidJniObject createOpenMultipleIntent(); | 
				
			||||
 | 
						QAndroidJniObject createSaveIntent(); | 
				
			||||
 | 
						QAndroidJniObject createOpenTreeIntent(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						void setupBasic(QAndroidJniObject &intent, bool asTree = false); | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Q_DECLARE_OPERATORS_FOR_FLAGS(QtMvvm::AndroidFileChooser::ChooserFlags) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#endif // QTMVVM_ANDROIDFILECHOOSER_H
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue