Commit a209d4ad authored by Martin Straka's avatar Martin Straka

Allow to export files to local storage of device

parent 685dabd5
/*
* Copyright (C) 2014-2018 CZ.NIC
* Copyright (C) 2014-2019 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -26,6 +26,6 @@
@interface DocumentPickerController : UIViewController
- (void)openImportDocumentPicker;
- (void)openExportDocumentPicker:(NSArray<NSURL*>*)exportUrls;
@end
/*
* Copyright (C) 2014-2018 CZ.NIC
* Copyright (C) 2014-2019 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -21,13 +21,14 @@
* the two.
*/
#include <QString>
#include <QList>
#include <QUrl>
#import "ios/src/doc_picker_controller.h"
// External globals for transporting of async result back to C++ and QML.
QString selectedFilePath;
bool isControllerOpen;
QList<QUrl> selectedFileUrls; // Url list of selected files
bool isControllerOpen; // holds information if DocumentPickerController is active.
@interface DocumentPickerController () <UIDocumentPickerDelegate>
......@@ -39,21 +40,45 @@ bool isControllerOpen;
[super viewDidLoad];
}
- (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 {
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.data"] 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.allowsMultipleSelection = YES;
documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:documentPicker animated:YES completion:nil];
}
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
if (controller.documentPickerMode == UIDocumentPickerModeImport) {
selectedFilePath = QString::fromNSString(url.absoluteString);
isControllerOpen = false;
NSLog(@"SELECTED FILE URLs: %@", urls);
QList<QUrl> qurls;
for (NSURL *url in urls) {
QUrl tmpUrl = QUrl::fromNSURL(url);
qurls.append(tmpUrl);
}
selectedFileUrls = qurls;
} else if (controller.documentPickerMode == UIDocumentPickerModeExportToService) {
NSLog(@"STORAGE FILE URLs: %@", urls);
}
isControllerOpen = false;
}
- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
......
/*
* Copyright (C) 2014-2018 CZ.NIC
* Copyright (C) 2014-2019 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -26,6 +26,7 @@
#include <QObject>
#include <QString>
#include <QStringList>
#include <QUrl>
/*!
* @brief Provides objective-C IO methods for interaction with iCLoud.
......@@ -113,18 +114,19 @@ public:
/*!
* @brief Create and open document picker controller.
*
* @param[in] exportFilesPath File paths for export (can be empty).
* @return True if document picker controller is created and opened.
*/
static
bool openDocumentPickerController(void);
bool openDocumentPickerController(const QStringList &exportFilesPath);
/*!
* @brief Move file from app temporary inbox to local app sandbox.
*
* @param[in] oldFilePath Source file path from inbox.
* @param[in] sourceFileUrl Source file url from inbox.
* @param[in] newFilePath Target path to local app sandbox.
* @return Full path where file was moved.
*/
static
QString moveFile(const QString &oldFilePath, const QString &newFilePath);
QUrl moveFile(const QUrl &sourceFileUrl, const QString &newFilePath);
};
/*
* Copyright (C) 2014-2018 CZ.NIC
* Copyright (C) 2014-2019 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -221,7 +221,7 @@ bool ICloudIo::isDownloadedFromCloud(const QString &cloudFilePath)
return false;
}
bool ICloudIo::openDocumentPickerController(void)
bool ICloudIo::openDocumentPickerController(const QStringList &exportFilesPath)
{
static DocumentPickerController* dpc = nil;
if (dpc != nil) {
......@@ -234,18 +234,38 @@ bool ICloudIo::openDocumentPickerController(void)
if (rootv != nil) {
dpc = [[DocumentPickerController alloc] init];
[rootv addChildViewController:dpc];
[dpc openImportDocumentPicker];
if (exportFilesPath.isEmpty()) {
// exportFilesPath is empty so import Document Picker will open
[dpc openImportDocumentPicker];
} else {
// exportFilesPath is not empty so export Document Picker will open
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;
}
QString ICloudIo::moveFile(const QString &oldFilePath,
QUrl ICloudIo::moveFile(const QUrl &sourceFileUrl,
const QString &newFilePath)
{
// Convert string path to URL
NSURL *ofp = [NSURL URLWithString:oldFilePath.toNSString()];
NSURL *ofp = sourceFileUrl.toNSURL();
NSURL *np = [NSURL fileURLWithPath:newFilePath.toNSString()];
NSString *fileName = [ofp lastPathComponent];
......@@ -254,7 +274,7 @@ QString ICloudIo::moveFile(const QString &oldFilePath,
if (![[NSFileManager defaultManager] createDirectoryAtURL:np
withIntermediateDirectories:YES attributes:nil error:&error]) {
NSLog(@"Local storage: Create message subdirectories error: %@", error);
return QString();
return QUrl();
}
NSURL *nfp = [np URLByAppendingPathComponent:fileName];
......@@ -267,13 +287,13 @@ QString ICloudIo::moveFile(const QString &oldFilePath,
if ([[NSFileManager defaultManager] moveItemAtURL:ofp toURL:nfp error:&error]) {
NSLog(@"Local storage: File has moved to target path.");
return QString::fromNSString(nfp.absoluteString);
return QUrl::fromNSURL(nfp);
} else {
if (error.code == NSFileWriteFileExistsError) {
NSLog(@"Local storage: File with the same name already exists in the target path.");
} else {
NSLog(@"Local storage: Error code: %zd %@", error.code, error);
}
return QString();
return QUrl();
}
}
/*
* Copyright (C) 2014-2018 CZ.NIC
* Copyright (C) 2014-2019 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -21,11 +21,9 @@
* the two.
*/
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QMessageBox>
#include <QUrl>
#include "src/auxiliaries/icloud_helper.h"
#include "src/io/filesystem.h"
......@@ -51,12 +49,6 @@ ICloudHelper::ICloudHelper(QObject *parent)
{
}
/* TODO - removed this tmp function if all will done. */
QStringList testCloudPathList(void)
{
return QStringList() << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/Send/" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/pokus/" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/Send/app_delegate.mm" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/6765996/priloha.txt" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/6766050/" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/6765996/" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/pokus/dmg_background.png" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/pokus/datovka.svg" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/4i2xd7/623345688/DZ_623345688.zfo" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/Send/datovka.png" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/6766050/dokument.odt" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/4i2xd7/623345688/5000FC241550444E8BE9C217BF5247EA.pdf" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/6766050/notification.mp3" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/6766050/dokument.pdf" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/wh5ef3/6766050/obrazek.png" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/4i2xd7/" << "file:///private/var/mobile/Library/Mobile%20Documents/iCloud~cz~nic~mobile-datovka/Documents/4i2xd7/623345688/";
}
void ICloudHelper::createCloudConteiner(void)
{
debugFuncCall();
......@@ -304,6 +296,11 @@ void ICloudHelper::clearSendDir(void)
QDir dir(appSendDirPath());
dir.removeRecursively();
/*
// TODO - used for experiments and testing only
QDir dir2(dfltAttachSavingLoc());
dir2.removeRecursively();
*/
}
void ICloudHelper::receivedCloudHierarchy(void)
......@@ -332,8 +329,8 @@ void ICloudHelper::openDocumentPickerController(void)
return;
}
selectedFilePath.clear();
isControllerOpen = ICloudIo::openDocumentPickerController();
selectedFileUrls.clear();
isControllerOpen = ICloudIo::openDocumentPickerController(QStringList());
if (isControllerOpen) {
connect(m_dpcTimer, SIGNAL(timeout()),
this, SLOT(receivedSelectedFilePath()));
......@@ -345,34 +342,57 @@ void ICloudHelper::openDocumentPickerController(void)
void ICloudHelper::receivedSelectedFilePath(void)
{
#ifdef Q_OS_IOS
if (!isControllerOpen) {
m_dpcTimer->stop();
disconnect(m_dpcTimer, SIGNAL(timeout()),
this, SLOT(receivedSelectedFilePath()));
if (!selectedFilePath.isEmpty()) {
moveFileToSendDir(selectedFilePath);
selectedFilePath.clear();
if (!selectedFileUrls.isEmpty()) {
foreach (const QUrl &fileUrl, selectedFileUrls) {
moveFileToSendDir(fileUrl);
}
selectedFileUrls.clear();
}
}
#endif
}
void ICloudHelper::moveFileToSendDir(const QString &filePath)
void ICloudHelper::moveFileToSendDir(const QUrl &sourceFileUrl)
{
#ifdef Q_OS_IOS
if (filePath.isEmpty()) {
if (Q_UNLIKELY(!sourceFileUrl.isValid())) {
return;
}
QString lfPath = ICloudIo::moveFile(filePath, appSendDirPath());
if (!lfPath.isEmpty()) {
lfPath = QUrl::fromPercentEncoding(lfPath.toUtf8());
lfPath = lfPath.replace("file://", "");
emit fileSelectedSig(lfPath);
QUrl targetFileUrl = ICloudIo::moveFile(sourceFileUrl, appSendDirPath());
if (targetFileUrl.isValid()) {
targetFileUrl.setScheme(QString());
emit fileSelectedSig(targetFileUrl.toString());
}
#endif
}
void ICloudHelper::storeFilesToDeviceStorage(const QStringList &srcFilePaths)
{
debugFuncCall();
#ifdef Q_OS_IOS
if (Q_UNLIKELY(srcFilePaths.isEmpty())) {
return;
}
ICloudIo::openDocumentPickerController(srcFilePaths);
#else /* !Q_OS_IOS */
Q_UNUSED(srcFilePaths);
#endif /* Q_OS_IOS */
}
/*
* Copyright (C) 2014-2018 CZ.NIC
* Copyright (C) 2014-2019 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -27,6 +27,7 @@
#include <QString>
#include <QStringList>
#include <QTimer>
#include <QUrl>
/*
* External global variables. These are using for transporting of async results
......@@ -35,7 +36,7 @@
*/
extern QStringList iCloudFileList;
extern bool isSearchRunning;
extern QString selectedFilePath;
extern QList<QUrl> selectedFileUrls;
extern bool isControllerOpen;
/*!
......@@ -80,6 +81,14 @@ public:
void storeFilesToCloud(const QStringList &srcFilePaths,
const QString &targetPath);
/*!
* @brief Store files to device local storage.
*
* @param[in] srcFilePaths List of file paths to be saved into storage.
*/
Q_INVOKABLE
void storeFilesToDeviceStorage(const QStringList &srcFilePaths);
/*!
* @brief Download file from iCloud if not exists in the local storage.
*
......@@ -171,9 +180,9 @@ private:
/*!
* @brief Move file from app temporary inbox to send path.
*
* @param[in] filePath Source file path from inbox.
* @param[in] sourceFileUrl Source file url from inbox.
*/
void moveFileToSendDir(const QString &filePath);
void moveFileToSendDir(const QUrl &sourceFileUrl);
/* Detect moment when async search response with iCloud hierarchy finished. */
QTimer *m_icloudTimer;
......
......@@ -24,6 +24,7 @@
#include <QDesktopServices>
#include <QDir>
#include <QFileInfo>
#include <QMessageBox>
#include <QQmlEngine>
#include <QStringBuilder>
......@@ -639,6 +640,27 @@ void Files::sendAttachmentEmailZfo(const QVariant &attachModelVariant,
QString::number(msgId));
}
#ifdef Q_OS_IOS
static
void exportFilesiOS(const QStringList &destFilePaths,
const QString &targetDir)
{
QMessageBox msgBox;
msgBox.setText(QObject::tr("You can export files into iCloud or into device local storage."));
msgBox.setDetailedText(QObject::tr("Do you want to export files to Datovka iCloud container?"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::No);
int ret = msgBox.exec();
if (ret == QMessageBox::Yes) {
ICloudHelper::storeFilesToCloud(destFilePaths, targetDir);
} else if (ret == QMessageBox::No) {
ICloudHelper ich;
ich.storeFilesToDeviceStorage(destFilePaths);
}
}
#endif
void Files::saveMsgFilesToDisk(const QString &userName,
const QString &msgIdStr, MsgAttachFlags attachFlags)
{
......@@ -723,8 +745,7 @@ void Files::saveMsgFilesToDisk(const QString &userName,
#else
ICloudHelper::storeFilesToCloud(destFilePaths, joinDirs(userName,
msgIdStr));
exportFilesiOS(destFilePaths, joinDirs(userName, msgIdStr));
#endif
}
......@@ -763,7 +784,7 @@ void Files::saveAttachmentsToDiskZfo(const QVariant &attachModelVariant,
#else
ICloudHelper::storeFilesToCloud(destFilePaths, msgIdStr);
exportFilesiOS(destFilePaths, msgIdStr);
#endif
}
......
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