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 @@ ...@@ -27,7 +27,7 @@
@interface DocumentPickerController : UIViewController @interface DocumentPickerController : UIViewController
- (void)openImportDocumentPicker; - (void)openImportDocumentPicker:(NSArray<NSString*>*)allowedUtis;
- (void)openExportDocumentPicker:(NSArray<NSURL*>*)exportUrls; - (void)openExportDocumentPicker:(NSArray<NSURL*>*)exportUrls;
@end @end
...@@ -40,22 +40,22 @@ ...@@ -40,22 +40,22 @@
- (void)openExportDocumentPicker:(NSArray<NSURL *> *)exportUrls { - (void)openExportDocumentPicker:(NSArray<NSURL *> *)exportUrls {
//NSLog(@"EXPORT FILE URLs: %@", exportUrls);
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithURLs:exportUrls inMode:UIDocumentPickerModeExportToService]; UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithURLs:exportUrls inMode:UIDocumentPickerModeExportToService];
documentPicker.delegate = self; documentPicker.delegate = self;
documentPicker.modalPresentationStyle = UIModalPresentationFormSheet; documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:documentPicker animated:YES completion:nil]; [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; 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; 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 { - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
...@@ -80,6 +80,9 @@ ...@@ -80,6 +80,9 @@
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller { - (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
Q_UNUSED(controller); Q_UNUSED(controller);
if (Q_NULLPTR != GlobInstcs::iOSHelperPtr) {
GlobInstcs::iOSHelperPtr->importFilesToAppInbox(QList<QUrl>());
}
} }
@end @end
...@@ -70,13 +70,22 @@ public: ...@@ -70,13 +70,22 @@ public:
const QString &destFilePath); 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). * @param[in] exportFilesPath File paths for export (can be empty).
* @return True if document picker controller is created and opened. * @return True if document picker controller is created and opened.
*/ */
static 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. * @brief Move file from app temporary inbox to local app sandbox.
......
...@@ -80,7 +80,7 @@ ICloudIo::ICloudResult ICloudIo::moveFileToCloud( ...@@ -80,7 +80,7 @@ ICloudIo::ICloudResult ICloudIo::moveFileToCloud(
} }
} }
bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath) bool ICloudIo::openDocumentPickerControllerForImport(const QStringList &allowedUtis)
{ {
static DocumentPickerController *dpc = nil; static DocumentPickerController *dpc = nil;
if (dpc != nil) { if (dpc != nil) {
...@@ -93,25 +93,17 @@ bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath) ...@@ -93,25 +93,17 @@ bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath)
if (rootv != nil) { if (rootv != nil) {
dpc = [[DocumentPickerController alloc] init]; dpc = [[DocumentPickerController alloc] init];
[rootv addChildViewController:dpc]; [rootv addChildViewController:dpc];
if (exportFilesPath.isEmpty()) { if (allowedUtis.isEmpty()) {
// exportFilesPath is empty so import Document Picker will open [dpc openImportDocumentPicker:@[@"public.data"]];
[dpc openImportDocumentPicker];
} else { } else {
// exportFilesPath is not empty so export Document Picker will open // 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 // covert export file paths to array of nsurl
for (int i = 0; i < exportFilesPath.count(); ++i) { for (int i = 0; i < allowedUtis.count(); ++i) {
QUrl url(QUrl::fromLocalFile(exportFilesPath.at(i))); [nsUITs addObject:allowedUtis.at(i).toNSString()];
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) { if ([nsUITs count] > 0) {
[dpc openExportDocumentPicker:exportUrls]; [dpc openImportDocumentPicker:nsUITs];
} }
} }
return true; return true;
...@@ -120,6 +112,41 @@ bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath) ...@@ -120,6 +112,41 @@ bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath)
return false; 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, QUrl ICloudIo::moveFile(const QUrl &sourceFileUrl,
const QString &newFilePath) const QString &newFilePath)
{ {
......
...@@ -25,6 +25,7 @@ import QtQuick 2.7 ...@@ -25,6 +25,7 @@ import QtQuick 2.7
import QtQuick.Controls 2.1 import QtQuick.Controls 2.1
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import cz.nic.mobileDatovka 1.0 import cz.nic.mobileDatovka 1.0
import cz.nic.mobileDatovka.iOsHelper 1.0
Component { Component {
id: importMessage id: importMessage
...@@ -38,6 +39,8 @@ Component { ...@@ -38,6 +39,8 @@ Component {
property string userName property string userName
property var accountModel: null property var accountModel: null
property bool iOS: false
/* Clear import info and import results */ /* Clear import info and import results */
function clearInfo() { function clearInfo() {
infoText.text = "" infoText.text = ""
...@@ -45,11 +48,15 @@ Component { ...@@ -45,11 +48,15 @@ Component {
} }
Component.onCompleted: { Component.onCompleted: {
iOS = iOSHelper.isIos()
clearInfo() clearInfo()
} }
Component.onDestruction: { Component.onDestruction: {
accounts.updateAccountCounters(accountModel) accounts.updateAccountCounters(accountModel)
if (iOS) {
iOSHelper.clearSendAndTmpDirs()
}
statusBar.visible = false statusBar.visible = false
} }
...@@ -75,19 +82,40 @@ Component { ...@@ -75,19 +82,40 @@ Component {
pageView.pop(StackView.Immediate) pageView.pop(StackView.Immediate)
} }
} }
/* Object (associative array) holding functions. */ /* Object (associative array) holding functions. */
property var funcs: { property var funcs: {
"zfoFile": function callZfoFile() { "zfoFile": function callZfoFile() {
clearInfo() 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() { "zfoDir": function callZfoDir() {
clearInfo() 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 { ListModel {
id: importMenuListModel id: importMenuListModel
ListElement { ListElement {
...@@ -152,7 +180,7 @@ Component { ...@@ -152,7 +180,7 @@ Component {
spacing: 1 spacing: 1
opacity: 1 opacity: 1
funcArr: funcs funcArr: funcs
model: importMenuListModel model: (iOS) ? importMenuListModeliOS : importMenuListModel
} }
Text { Text {
text: " " text: " "
...@@ -191,5 +219,12 @@ Component { ...@@ -191,5 +219,12 @@ Component {
progressText.text = progressText.text + "<br/>" + txt 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 ...@@ -27,6 +27,7 @@ import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import cz.nic.mobileDatovka 1.0 import cz.nic.mobileDatovka 1.0
import cz.nic.mobileDatovka.files 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.messages 1.0
import cz.nic.mobileDatovka.models 1.0 import cz.nic.mobileDatovka.models 1.0
...@@ -504,10 +505,10 @@ Item { ...@@ -504,10 +505,10 @@ Item {
Item { Item {
id: tabAttachments id: tabAttachments
Connections { Connections {
target: iOSHelper target: iOSHelper
onFileSelectedSig: { onSendFilesSelectedSig: {
if (filePath !== "") { for (var j = 0; j < sendFilePaths.length; ++j) {
appendFileToSendModel(filePath) appendFileToSendModel(sendFilePaths[j])
} }
} }
} }
...@@ -518,7 +519,7 @@ Item { ...@@ -518,7 +519,7 @@ Item {
font.pointSize: defaultTextFont.font.pointSize font.pointSize: defaultTextFont.font.pointSize
text: qsTr("Add file") text: qsTr("Add file")
onClicked: { onClicked: {
iOS ? iOSHelper.openDocumentPickerController() : fileDialogue.raise(qsTr("Select files"), ["*.*"], true, "") iOS ? iOSHelper.openDocumentPickerControllerForImport(IosImportAction.IMPORT_SEND,[]) : fileDialogue.raise(qsTr("Select files"), ["*.*"], true, "")
} }
} }
Component { Component {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QMessageBox> #include <QMessageBox>
#include <QQmlEngine>
#include "src/auxiliaries/ios_helper.h" #include "src/auxiliaries/ios_helper.h"
#include "src/io/filesystem.h" #include "src/io/filesystem.h"
...@@ -35,8 +36,15 @@ ...@@ -35,8 +36,15 @@
#define SEND_FILE_PATH_PREFIX "Documents/Datovka" #define SEND_FILE_PATH_PREFIX "Documents/Datovka"
#endif /* Q_OS_IOS */ #endif /* Q_OS_IOS */
void IosHelper::declareQML(void)
{
qmlRegisterType<IosHelper>("cz.nic.mobileDatovka.iOsHelper", 1, 0, "IosImportAction");
qRegisterMetaType<IosHelper::IosImportAction>();
}
IosHelper::IosHelper(QObject *parent) IosHelper::IosHelper(QObject *parent)
: QObject(parent) : QObject(parent),
m_importAction(IosImportAction::IMPORT_NONE)
{ {
} }
...@@ -147,22 +155,71 @@ void IosHelper::clearSendAndTmpDirs(void) ...@@ -147,22 +155,71 @@ void IosHelper::clearSendAndTmpDirs(void)
dir.removeRecursively(); dir.removeRecursively();
} }
void IosHelper::openDocumentPickerController(void) void IosHelper::openDocumentPickerControllerForImport(enum IosImportAction action,
const QStringList &allowedUtis)
{ {
debugFuncCall(); debugFuncCall();
#ifdef Q_OS_IOS #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 */ #endif /* Q_OS_IOS */
} }
void IosHelper::importFilesToAppInbox(const QList<QUrl> &selectedFileUrls) void IosHelper::importFilesToAppInbox(const QList<QUrl> &selectedFileUrls)
{ {
foreach (const QUrl &fileUrl, selectedFileUrls) { if (selectedFileUrls.isEmpty()) {
moveFileToSendDir(fileUrl); 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) void IosHelper::storeFilesToDeviceStorage(const QStringList &srcFilePaths)
...@@ -175,7 +232,7 @@ void IosHelper::storeFilesToDeviceStorage(const QStringList &srcFilePaths) ...@@ -175,7 +232,7 @@ void IosHelper::storeFilesToDeviceStorage(const QStringList &srcFilePaths)
return; return;
} }
ICloudIo::openDocumentPickerController(srcFilePaths); ICloudIo::openDocumentPickerControllerForExport(srcFilePaths);
#else /* !Q_OS_IOS */ #else /* !Q_OS_IOS */
Q_UNUSED(srcFilePaths); Q_UNUSED(srcFilePaths);
...@@ -191,20 +248,25 @@ bool IosHelper::isIos(void) ...@@ -191,20 +248,25 @@ bool IosHelper::isIos(void)
#endif #endif
} }
void IosHelper::moveFileToSendDir(const QUrl &sourceFileUrl) QString IosHelper::moveFileToTargetPath(const QUrl &sourceFileUrl,
const QString &targetPath)
{ {
#ifdef Q_OS_IOS #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()) { if (targetFileUrl.isValid()) {
targetFileUrl.setScheme(QString()); targetFileUrl.setScheme(QString());
emit fileSelectedSig(targetFileUrl.toString()); return targetFileUrl.toString();
} }
#else /* !Q_OS_IOS */ #else /* !Q_OS_IOS */
Q_UNUSED(sourceFileUrl); Q_UNUSED(sourceFileUrl);
Q_UNUSED(targetPath);
#endif #endif
return QString();
} }
...@@ -35,6 +35,23 @@ class IosHelper : public QObject { ...@@ -35,6 +35,23 @@ class IosHelper : public QObject {
Q_OBJECT Q_OBJECT
public: 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. * @brief Constructor.
* *
...@@ -68,10 +85,14 @@ public: ...@@ -68,10 +85,14 @@ public:
void clearSendAndTmpDirs(void); 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 Q_INVOKABLE
void openDocumentPickerController(void); void openDocumentPickerControllerForImport(enum IosImportAction action,
const QStringList &allowedUtis);
/*! /*!
* @brief Is activated when files have been selected with iOS file picker. * @brief Is activated when files have been selected with iOS file picker.
...@@ -100,15 +121,37 @@ signals: ...@@ -100,15 +121,37 @@ signals:
/*! /*!
* @brief Is activated when a file has been chosen with document picker. * @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: 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] 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[]) ...@@ -507,6 +507,7 @@ int main(int argc, char *argv[])
GovFormListModel::declareQML(); GovFormListModel::declareQML();
GovServiceListModel::declareQML(); GovServiceListModel::declareQML();
InteractionFilesystem::declareQML(); InteractionFilesystem::declareQML();
IosHelper::declareQML();
ListSortFilterProxyModel::declareQML(); ListSortFilterProxyModel::declareQML();
MessageListModel::declareQML(); MessageListModel::declareQML();
Messages::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