瀏覽代碼

[launcher][iOS] select directory to copy oh3 files using objc/uikit

Andrey Filipenkov 1 年之前
父節點
當前提交
e019997bee
共有 4 個文件被更改,包括 109 次插入2 次删除
  1. 6 0
      launcher/CMakeLists.txt
  2. 11 2
      launcher/firstLaunch/firstlaunch_moc.cpp
  3. 20 0
      launcher/ios/selectdirectory.h
  4. 72 0
      launcher/ios/selectdirectory.mm

+ 6 - 0
launcher/CMakeLists.txt

@@ -26,6 +26,8 @@ set(launcher_SRCS
 if(APPLE_IOS)
 	list(APPEND launcher_SRCS
 		ios/launchGame.m
+		ios/selectdirectory.h
+		ios/selectdirectory.mm
 	)
 endif()
 
@@ -212,6 +214,10 @@ if(ENABLE_INNOEXTRACT)
 endif()
 
 if(APPLE_IOS)
+	target_link_libraries(vcmilauncher
+		"-framework UniformTypeIdentifiers"
+	)
+
 	# TODO: remove after switching prebuilt deps to a newer Conan's Qt recipe
 	if(XCODE_VERSION VERSION_GREATER_EQUAL 14.0)
 		target_link_libraries(vcmilauncher "-framework IOKit")

+ 11 - 2
launcher/firstLaunch/firstlaunch_moc.cpp

@@ -26,7 +26,9 @@
 #include "cli/extract.hpp"
 #endif
 
-#ifdef VCMI_ANDROID
+#ifdef VCMI_IOS
+#include "ios/selectdirectory.h"
+#elif defined(VCMI_ANDROID)
 #include <QAndroidJniObject>
 #include <QtAndroid>
 
@@ -384,9 +386,16 @@ void FirstLaunchView::extractGogData()
 void FirstLaunchView::copyHeroesData(const QString & path, bool move)
 {
 	QDir sourceRoot{path};
-	
+
+#ifdef VCMI_IOS
+	// TODO: Qt 6.5 can select directories https://codereview.qt-project.org/c/qt/qtbase/+/446449
+	SelectDirectory iosDirectorySelector;
+	if(path.isEmpty())
+		sourceRoot.setPath(iosDirectorySelector.getExistingDirectory());
+#else
 	if(path.isEmpty())
 		sourceRoot.setPath(QFileDialog::getExistingDirectory(this, {}, {}, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks));
+#endif
 
 	if(!sourceRoot.exists())
 		return;

+ 20 - 0
launcher/ios/selectdirectory.h

@@ -0,0 +1,20 @@
+/*
+ * selectdirectory.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#pragma once
+
+#include <QString>
+
+class SelectDirectory final
+{
+public:
+	~SelectDirectory();
+
+	QString getExistingDirectory();
+};

+ 72 - 0
launcher/ios/selectdirectory.mm

@@ -0,0 +1,72 @@
+/*
+ * selectdirectory.mm, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "selectdirectory.h"
+
+#include <QEventLoop>
+
+#import <UIKit/UIKit.h>
+#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
+#import <MobileCoreServices/MobileCoreServices.h>
+
+
+@interface ObjcDocumentPickerDelegate : NSObject <UIDocumentPickerDelegate>
+@property (nonatomic, assign, readonly) QEventLoop & eventLoop;
+@property (nonatomic, copy, nullable) NSURL * selectedDirectoryURL;
+@end
+
+@implementation ObjcDocumentPickerDelegate
+{
+	QEventLoop _eventLoop;
+}
+
+- (QEventLoop &)eventLoop { return _eventLoop; }
+
+- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls
+{
+	self.selectedDirectoryURL = urls.firstObject;
+	_eventLoop.exit();
+}
+
+- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller
+{
+	_eventLoop.exit();
+}
+
+@end
+
+static ObjcDocumentPickerDelegate * documentPickerDelegate;
+
+
+SelectDirectory::~SelectDirectory()
+{
+	[documentPickerDelegate.selectedDirectoryURL stopAccessingSecurityScopedResource];
+	documentPickerDelegate = nil;
+}
+
+QString SelectDirectory::getExistingDirectory()
+{
+	documentPickerDelegate = [ObjcDocumentPickerDelegate new];
+
+	UIDocumentPickerViewController * documentPickerVc;
+	if(@available(iOS 14.0, *))
+		documentPickerVc = [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:@[UTTypeFolder]];
+	else
+		documentPickerVc = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[(__bridge NSString *)kUTTypeFolder] inMode:UIDocumentPickerModeOpen];
+	documentPickerVc.allowsMultipleSelection = NO;
+	documentPickerVc.delegate = documentPickerDelegate;
+	[UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:documentPickerVc animated:YES completion:nil];
+
+	documentPickerDelegate.eventLoop.exec(QEventLoop::DialogExec);
+	if(!documentPickerDelegate.selectedDirectoryURL)
+		return {};
+
+	[documentPickerDelegate.selectedDirectoryURL startAccessingSecurityScopedResource];
+	return QString::fromNSString(documentPickerDelegate.selectedDirectoryURL.path);
+}