Commit 9559fcea authored by Karel Slaný's avatar Karel Slaný

Merge branch 'ios-zfo-import' into 'develop'

Use iOS file picker controller for ZFOs import

Closes #143

See merge request !148
parents 9d76ad39 fe58afb0
......@@ -27,7 +27,7 @@
@interface DocumentPickerController : UIViewController
- (void)openImportDocumentPicker;
- (void)openImportDocumentPicker:(NSArray<NSString*>*)allowedUtis;
- (void)openExportDocumentPicker:(NSArray<NSURL*>*)exportUrls;
@end
......@@ -40,22 +40,22 @@
- (void)openExportDocumentPicker:(NSArray<NSURL *> *)exportUrls {
//NSLog(@"EXPORT FILE URLs: %@", exportUrls);
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithURLs:exportUrls inMode:UIDocumentPickerModeExportToService];
documentPicker.delegate = self;
documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:documentPicker animated:YES completion:nil];
}
- (void)openImportDocumentPicker {
- (void)openImportDocumentPicker:(NSArray<NSString *> *)allowedUtis {
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.data"] inMode:UIDocumentPickerModeImport];
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:allowedUtis inMode:UIDocumentPickerModeImport];
documentPicker.delegate = self;
// Next property does not work with iOS < 11.
// Apple bug: Selected files are not picked if multiple select is on.
documentPicker.allowsMultipleSelection = YES;
documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:documentPicker animated:YES completion:nil];
[self presentViewController:documentPicker animated:NO completion:^{
if (@available(iOS 11.0, *)) {
documentPicker.allowsMultipleSelection = YES;
}
}];
}
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
......@@ -80,6 +80,9 @@
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
Q_UNUSED(controller);
if (Q_NULLPTR != GlobInstcs::iOSHelperPtr) {
GlobInstcs::iOSHelperPtr->importFilesToAppInbox(QList<QUrl>());
}
}
@end
......@@ -70,13 +70,22 @@ public:
const QString &destFilePath);
/*!
* @brief Create and open document picker controller.
* @brief Create and open document picker controller for export.
*
* @param[in] exportFilesPath File paths for export (can be empty).
* @return True if document picker controller is created and opened.
*/
static
bool openDocumentPickerController(const QStringList &exportFilesPath);
bool openDocumentPickerControllerForExport(const QStringList &exportFilesPath);
/*!
* @brief Create and open document picker controller for import.
*
* @param[in] allowedUtis Allowed iOS mime extensions (can be empty).
* @return True if document picker controller is created and opened.
*/
static
bool openDocumentPickerControllerForImport(const QStringList &allowedUtis);
/*!
* @brief Move file from app temporary inbox to local app sandbox.
......
......@@ -80,7 +80,7 @@ ICloudIo::ICloudResult ICloudIo::moveFileToCloud(
}
}
bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath)
bool ICloudIo::openDocumentPickerControllerForImport(const QStringList &allowedUtis)
{
static DocumentPickerController *dpc = nil;
if (dpc != nil) {
......@@ -93,25 +93,17 @@ bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath)
if (rootv != nil) {
dpc = [[DocumentPickerController alloc] init];
[rootv addChildViewController:dpc];
if (exportFilesPath.isEmpty()) {
// exportFilesPath is empty so import Document Picker will open
[dpc openImportDocumentPicker];
if (allowedUtis.isEmpty()) {
[dpc openImportDocumentPicker:@[@"public.data"]];
} else {
// exportFilesPath is not empty so export Document Picker will open
NSMutableArray<NSURL*> *exportUrls = [NSMutableArray array];
NSMutableArray<NSString*> *nsUITs = [NSMutableArray array];
// covert export file paths to array of nsurl
for (int i = 0; i < exportFilesPath.count(); ++i) {
QUrl url(QUrl::fromLocalFile(exportFilesPath.at(i)));
if (url.isValid()) {
NSURL *fileUrl = url.toNSURL();
[exportUrls addObject:fileUrl];
//NSLog(@"ADD FILE URL to list: %@", fileUrl);
} else {
NSLog(@"ERROR FILE URL: %@", url.toNSURL());
}
for (int i = 0; i < allowedUtis.count(); ++i) {
[nsUITs addObject:allowedUtis.at(i).toNSString()];
}
if ([exportUrls count] > 0) {
[dpc openExportDocumentPicker:exportUrls];
if ([nsUITs count] > 0) {
[dpc openImportDocumentPicker:nsUITs];
}
}
return true;
......@@ -120,6 +112,41 @@ bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath)
return false;
}
bool ICloudIo::openDocumentPickerControllerForExport(const QStringList &exportFilesPath)
{
static DocumentPickerController *dpc = nil;
if (dpc != nil) {
[dpc removeFromParentViewController];
[dpc release];
}
UIViewController *rootv = [[[[UIApplication sharedApplication]windows] firstObject]rootViewController];
if (rootv != nil) {
dpc = [[DocumentPickerController alloc] init];
[rootv addChildViewController:dpc];
NSMutableArray<NSURL*> *exportUrls = [NSMutableArray array];
// covert export file paths to array of nsurl
for (int i = 0; i < exportFilesPath.count(); ++i) {
QUrl url(QUrl::fromLocalFile(exportFilesPath.at(i)));
if (url.isValid()) {
NSURL *fileUrl = url.toNSURL();
[exportUrls addObject:fileUrl];
//NSLog(@"ADD FILE URL to list: %@", fileUrl);
} else {
NSLog(@"ERROR FILE URL: %@", url.toNSURL());
}
}
if ([exportUrls count] > 0) {
[dpc openExportDocumentPicker:exportUrls];
}
return true;
}
return false;
}
QUrl ICloudIo::moveFile(const QUrl &sourceFileUrl,
const QString &newFilePath)
{
......
......@@ -25,6 +25,7 @@ import QtQuick 2.7
import QtQuick.Controls 2.1
import QtGraphicalEffects 1.0
import cz.nic.mobileDatovka 1.0
import cz.nic.mobileDatovka.iOsHelper 1.0
Component {
id: importMessage
......@@ -38,6 +39,8 @@ Component {
property string userName
property var accountModel: null
property bool iOS: false
/* Clear import info and import results */
function clearInfo() {
infoText.text = ""
......@@ -45,11 +48,15 @@ Component {
}
Component.onCompleted: {
iOS = iOSHelper.isIos()
clearInfo()
}
Component.onDestruction: {
accounts.updateAccountCounters(accountModel)
if (iOS) {
iOSHelper.clearSendAndTmpDirs()
}
statusBar.visible = false
}
......@@ -75,19 +82,40 @@ Component {
pageView.pop(StackView.Immediate)
}
}
/* Object (associative array) holding functions. */
property var funcs: {
"zfoFile": function callZfoFile() {
clearInfo()
fileDialogue.raise(qsTr("Select ZFO files"), ["*.zfo"], true, "")
if (iOS) {
iOSHelper.openDocumentPickerControllerForImport(IosImportAction.IMPORT_ZFOS, ["cz.nic.mobile-datovka.zfo"])
} else {
fileDialogue.raise(qsTr("Select ZFO files"), ["*.zfo"], true, "")
}
},
"zfoDir": function callZfoDir() {
clearInfo()
fileDialogue.raise(qsTr("Select import directory"), ["*.*"], false, "")
if (iOS) {
/* Import ZFOs from selected directory on iOS is not used now because the UIDocumentPickerViewController still has not support for this. */
iOSHelper.openDocumentPickerControllerForImport(IosImportAction.IMPORT_ZFO_DIR, ["public.directory","public.folder"])
} else {
fileDialogue.raise(qsTr("Select import directory"), ["*.*"], false, "")
}
}
}
/* Import ZFO list model for iOS only. Import ZFOs from selected directory on iOS is not allowed now. */
ListModel {
id: importMenuListModeliOS
ListElement {
image: "qrc:/ui/datovka-file-zfo.svg"
showEntry: true
showNext: true
name: qsTr("Import selected ZFO files")
funcName: "zfoFile"
}
}
/* Import ZFO list model for other platforms. */
ListModel {
id: importMenuListModel
ListElement {
......@@ -152,7 +180,7 @@ Component {
spacing: 1
opacity: 1
funcArr: funcs
model: importMenuListModel
model: (iOS) ? importMenuListModeliOS : importMenuListModel
}
Text {
text: " "
......@@ -191,5 +219,12 @@ Component {
progressText.text = progressText.text + "<br/>" + txt
}
}
Connections {
target: iOSHelper
onZfoFilesSelectedSig: {
clearInfo()
infoText.text = isds.importZfoMessages(userName, zfoFilePaths, verifyMessage.checked)
}
}
}
}
......@@ -27,6 +27,7 @@ import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import cz.nic.mobileDatovka 1.0
import cz.nic.mobileDatovka.files 1.0
import cz.nic.mobileDatovka.iOsHelper 1.0
import cz.nic.mobileDatovka.messages 1.0
import cz.nic.mobileDatovka.models 1.0
......@@ -504,10 +505,10 @@ Item {
Item {
id: tabAttachments
Connections {
target: iOSHelper
onFileSelectedSig: {
if (filePath !== "") {
appendFileToSendModel(filePath)
target: iOSHelper
onSendFilesSelectedSig: {
for (var j = 0; j < sendFilePaths.length; ++j) {
appendFileToSendModel(sendFilePaths[j])
}
}
}
......@@ -518,7 +519,7 @@ Item {
font.pointSize: defaultTextFont.font.pointSize
text: qsTr("Add file")
onClicked: {
iOS ? iOSHelper.openDocumentPickerController() : fileDialogue.raise(qsTr("Select files"), ["*.*"], true, "")
iOS ? iOSHelper.openDocumentPickerControllerForImport(IosImportAction.IMPORT_SEND,[]) : fileDialogue.raise(qsTr("Select files"), ["*.*"], true, "")
}
}
Component {
......
......@@ -24,6 +24,7 @@
#include <QDir>
#include <QFileInfo>
#include <QMessageBox>
#include <QQmlEngine>
#include "src/auxiliaries/ios_helper.h"
#include "src/io/filesystem.h"
......@@ -35,8 +36,15 @@
#define SEND_FILE_PATH_PREFIX "Documents/Datovka"
#endif /* Q_OS_IOS */
void IosHelper::declareQML(void)
{
qmlRegisterType<IosHelper>("cz.nic.mobileDatovka.iOsHelper", 1, 0, "IosImportAction");
qRegisterMetaType<IosHelper::IosImportAction>();
}
IosHelper::IosHelper(QObject *parent)
: QObject(parent)
: QObject(parent),
m_importAction(IosImportAction::IMPORT_NONE)
{
}
......@@ -147,22 +155,71 @@ void IosHelper::clearSendAndTmpDirs(void)
dir.removeRecursively();
}
void IosHelper::openDocumentPickerController(void)
void IosHelper::openDocumentPickerControllerForImport(enum IosImportAction action,
const QStringList &allowedUtis)
{
debugFuncCall();
#ifdef Q_OS_IOS
ICloudIo::openDocumentPickerController(QStringList());
if (IosImportAction::IMPORT_NONE != m_importAction) {
// Another document picker import acitvity is running.
return;
}
m_importAction = action;
if (!ICloudIo::openDocumentPickerControllerForImport(allowedUtis)) {
m_importAction = IosImportAction::IMPORT_NONE;
}
#else /* !Q_OS_IOS */
Q_UNUSED(action);
Q_UNUSED(allowedUtis);
#endif /* Q_OS_IOS */
}
void IosHelper::importFilesToAppInbox(const QList<QUrl> &selectedFileUrls)
{
foreach (const QUrl &fileUrl, selectedFileUrls) {
moveFileToSendDir(fileUrl);
if (selectedFileUrls.isEmpty()) {
m_importAction = IosImportAction::IMPORT_NONE;
return;
}
QStringList filePaths;
switch (m_importAction) {
case IosImportAction::IMPORT_SEND:
foreach (const QUrl &fileUrl, selectedFileUrls) {
filePaths.append(moveFileToTargetPath(fileUrl,
appSendDirPath()));
}
emit sendFilesSelectedSig(filePaths);
break;
case IosImportAction::IMPORT_ZFOS:
foreach (const QUrl &fileUrl, selectedFileUrls) {
filePaths.append(moveFileToTargetPath(fileUrl,
appTmpDirPath()));
}
emit zfoFilesSelectedSig(filePaths);
break;
case IosImportAction::IMPORT_CERT:
foreach (const QUrl &fileUrl, selectedFileUrls) {
filePaths.append(moveFileToTargetPath(fileUrl,
appCertDirPath()));
}
emit certFilesSelectedSig(filePaths);
break;
case IosImportAction::IMPORT_ZFO_DIR:
/*
* TODO - Import ZFOs from selected directory on iOS is not used
* now because the UIDocumentPickerViewController still has not
* support for this.
*/
break;
default: break;
}
m_importAction = IosImportAction::IMPORT_NONE;
}
void IosHelper::storeFilesToDeviceStorage(const QStringList &srcFilePaths)
......@@ -175,7 +232,7 @@ void IosHelper::storeFilesToDeviceStorage(const QStringList &srcFilePaths)
return;
}
ICloudIo::openDocumentPickerController(srcFilePaths);
ICloudIo::openDocumentPickerControllerForExport(srcFilePaths);
#else /* !Q_OS_IOS */
Q_UNUSED(srcFilePaths);
......@@ -191,20 +248,25 @@ bool IosHelper::isIos(void)
#endif
}
void IosHelper::moveFileToSendDir(const QUrl &sourceFileUrl)
QString IosHelper::moveFileToTargetPath(const QUrl &sourceFileUrl,
const QString &targetPath)
{
#ifdef Q_OS_IOS
if (Q_UNLIKELY(!sourceFileUrl.isValid())) {
return;
if (Q_UNLIKELY(!sourceFileUrl.isValid() || targetPath.isEmpty())) {
return QString();
}
QUrl targetFileUrl(ICloudIo::moveFile(sourceFileUrl, appSendDirPath()));
QUrl targetFileUrl(ICloudIo::moveFile(sourceFileUrl, targetPath));
if (targetFileUrl.isValid()) {
targetFileUrl.setScheme(QString());
emit fileSelectedSig(targetFileUrl.toString());
return targetFileUrl.toString();
}
#else /* !Q_OS_IOS */
Q_UNUSED(sourceFileUrl);
Q_UNUSED(targetPath);
#endif
return QString();
}
......@@ -35,6 +35,23 @@ class IosHelper : public QObject {
Q_OBJECT
public:
/* Defines import action for iOS File Picker */
enum IosImportAction {
IMPORT_NONE = 0,
IMPORT_SEND,
IMPORT_ZFOS,
IMPORT_ZFO_DIR,
IMPORT_CERT
};
Q_ENUM(IosImportAction)
/*!
* @brief Declare various properties to the QML system.
*/
static
void declareQML(void);
/*!
* @brief Constructor.
*
......@@ -68,10 +85,14 @@ public:
void clearSendAndTmpDirs(void);
/*!
* @brief Create and open document picker controller.
* @brief Create and open document picker controller for import.
*
* @param[in] action Import action.
* @param[in] allowedUtis Allowed iOS mime extensions (can be empty).
*/
Q_INVOKABLE static
void openDocumentPickerController(void);
Q_INVOKABLE
void openDocumentPickerControllerForImport(enum IosImportAction action,
const QStringList &allowedUtis);
/*!
* @brief Is activated when files have been selected with iOS file picker.
......@@ -100,15 +121,37 @@ signals:
/*!
* @brief Is activated when a file has been chosen with document picker.
*
* @param[in] filePath Path file for QML.
* @param[in] sendFilePaths Path file list for QML.
*/
void sendFilesSelectedSig(QStringList sendFilePaths);
/*!
* @brief Is activated when a file has been chosen with document picker.
*
* @param[in] zfoFilePaths Path file list for QML.
*/
void zfoFilesSelectedSig(QStringList zfoFilePaths);
/*!
* @brief Is activated when a file has been chosen with document picker.
*
* @param[in] certFilePaths Path file list for QML.
*/
void fileSelectedSig(QString filePath);
void certFilesSelectedSig(QStringList certFilePaths);
private:
/*!
* @brief Move file from app temporary inbox to send path.
* @brief Move file from app temporary inbox to target path.
*
* @param[in] sourceFileUrl Source file url from inbox.
* @param[in] targePath Target file path.
* @return Full path where file was moved.
*/
void moveFileToSendDir(const QUrl &sourceFileUrl);
QString moveFileToTargetPath(const QUrl &sourceFileUrl,
const QString &targePath);
enum IosImportAction m_importAction; /*!< Holds import action type. */
};
/* Declare IosImportAction to QML. */
Q_DECLARE_METATYPE(IosHelper::IosImportAction)
......@@ -507,6 +507,7 @@ int main(int argc, char *argv[])
GovFormListModel::declareQML();
GovServiceListModel::declareQML();
InteractionFilesystem::declareQML();
IosHelper::declareQML();
ListSortFilterProxyModel::declareQML();
MessageListModel::declareQML();
Messages::declareQML();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment