peony/libpeony-qt/file-operation/create-template-operation.cpp

218 lines
7.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Peony-Qt's Library
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: Yue Lan <lanyue@kylinos.cn>
*
*/
#include "create-template-operation.h"
#include "file-operation-manager.h"
#include "file-operation-utils.h"
#include "global-settings.h"
#include <gio/gio.h>
#include <utime.h>
#include <QMessageBox>
#include <QProcess>
#include <file-utils.h>
using namespace Peony;
#define TEMPLATE_DIR "file://" + GlobalSettings::getInstance()->getValue(TEMPLATES_DIR).toString()
void CreateTemplateOperation::handleDuplicate(const QString &uri)
{
m_target_uri = m_dest_dir_uri + "/" + FileUtils::handleDuplicateName(uri);
}
CreateTemplateOperation::CreateTemplateOperation(const QString &destDirUri, Type type, const QString &templateName, QObject *parent) : FileOperation(parent)
{
m_target_uri = destDirUri + "/" + templateName;
QStringList srcUris;
m_src_uri = TEMPLATE_DIR + templateName;
srcUris << m_src_uri;
m_dest_dir_uri = destDirUri;
m_type = type;
m_info = std::make_shared<FileOperationInfo>(srcUris, destDirUri, FileOperationInfo::Type::Copy);
}
void CreateTemplateOperation::run()
{
Q_EMIT operationStarted();
Q_EMIT operationPrepared();
switch (m_type) {
case EmptyFile: {
m_target_uri = m_dest_dir_uri + "/" + tr("NewFile") + ".txt";
retry_create_empty_file:
GError *err = nullptr;
GFileOutputStream *newFile = g_file_create(wrapGFile(g_file_new_for_uri(FileUtils::urlEncode(m_target_uri).toUtf8())).get()->get(), G_FILE_CREATE_NONE, nullptr, &err);
if (err) {
FileOperationError except;
if (err->code == G_IO_ERROR_EXISTS) {
g_error_free(err);
handleDuplicate(m_target_uri);
goto retry_create_empty_file;
} else {
except.srcUri = m_src_uri;
except.dlgType = ED_WARNING;
except.destDirUri = m_dest_dir_uri;
except.isCritical = true;
except.op = FileOpCreateTemp;
except.title = tr("Create file");
except.errorCode = err->code;
except.errorStr = err->message;
except.errorType = ET_GIO;
Q_EMIT errored(except);
}
}
//fix bug 35145, function occupy udisk issue
g_object_unref(newFile);
break;
}
case EmptyFolder: {
m_target_uri = m_dest_dir_uri + "/" + tr("NewFolder");
retry_create_empty_folder:
GError *err = nullptr;
g_file_make_directory(wrapGFile(g_file_new_for_uri(FileUtils::urlEncode(m_target_uri).toUtf8())).get()->get(),
nullptr,
&err);
if (err) {
// todo: Allow user naming
if (err->code == G_IO_ERROR_EXISTS) {
g_error_free(err);
handleDuplicate(m_target_uri);
goto retry_create_empty_folder;
} else {
FileOperationError except;
except.srcUri = m_src_uri;
except.dlgType = ED_WARNING;
except.destDirUri = m_dest_dir_uri;
except.isCritical = true;
except.op = FileOpCreateTemp;
except.title = tr("Create file error");
except.errorCode = err->code;
except.errorStr = err->message;
except.errorType = ET_GIO;
Q_EMIT errored(except);
}
}
break;
}
case Template: {
retry_create_template:
qDebug() << "create tmp";
GError *err = nullptr;
g_file_copy(wrapGFile(g_file_new_for_uri(FileUtils::urlEncode(m_src_uri).toUtf8())).get()->get(),
wrapGFile(g_file_new_for_uri(m_target_uri.toUtf8())).get()->get(),
GFileCopyFlags(G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_NOFOLLOW_SYMLINKS),
nullptr,
nullptr,
nullptr,
&err);
if (err) {
setHasError(true);
if (err->code == G_IO_ERROR_EXISTS) {
g_error_free(err);
handleDuplicate(m_target_uri);
goto retry_create_template;
} else {
FileOperationError except;
except.srcUri = m_src_uri;
except.dlgType = ED_WARNING;
except.destDirUri = m_dest_dir_uri;
except.isCritical = true;
except.op = FileOpCreateTemp;
except.title = tr("Create file error");
except.errorCode = err->code;
except.errorStr = err->message;
except.errorType = ET_GIO;
Q_EMIT errored(except);
}
} else {
setHasError(false);
}
// change file's modify time and access time after copy templete file;
time_t now_time = time(NULL);
g_file_set_attribute_uint64(wrapGFile(g_file_new_for_uri(m_target_uri.toUtf8())).get()->get(),
G_FILE_ATTRIBUTE_TIME_MODIFIED,
(guint64)now_time,
G_FILE_QUERY_INFO_NONE, nullptr, &err);
//需要设置一下访问时间属性修复前场反馈的在U盘创建wps文件访问时间异常问题时分秒为000000
g_file_set_attribute_uint64(wrapGFile(g_file_new_for_uri(m_target_uri.toUtf8())).get()->get(),
G_FILE_ATTRIBUTE_TIME_ACCESS,
(guint64)now_time,
G_FILE_QUERY_INFO_NONE, nullptr, &err);
break;
}
}
FileUtils::saveCreateTime (m_target_uri);
// judge if the operation should sync.
bool needSync = false;
GFile *src_first_file = g_file_new_for_uri(FileUtils::urlEncode(m_src_uri).toUtf8().constData());
GMount *src_first_mount = g_file_find_enclosing_mount(src_first_file, nullptr, nullptr);
if (src_first_mount) {
needSync = g_mount_can_unmount(src_first_mount);
g_object_unref(src_first_mount);
} else {
// maybe a vfs file.
needSync = true;
}
g_object_unref(src_first_file);
GFile *dest_dir_file = g_file_new_for_uri(FileUtils::urlEncode(m_dest_dir_uri).toUtf8().constData());
GMount *dest_dir_mount = g_file_find_enclosing_mount(dest_dir_file, nullptr, nullptr);
//fix create folder not sync issue, bug#128665, 132326
if (m_type == EmptyFolder) {
dest_dir_file = g_file_new_for_uri(FileUtils::urlEncode(m_target_uri).toUtf8().constData());
}
if (src_first_mount) {
needSync = g_mount_can_unmount(dest_dir_mount);
g_object_unref(dest_dir_mount);
} else {
needSync = true;
}
//needSync = true;
if (needSync) {
auto path = g_file_get_path(dest_dir_file);
if (path) {
operationStartSnyc();
QProcess p;
p.start(QString("/usr/bin/sync -f '%1'").arg(path));
p.waitForFinished(-1);
g_free(path);
}
}
g_object_unref(dest_dir_file);
// as target()
m_info.get()->m_dest_dir_uri = m_target_uri;
m_info.get()->m_dest_uris.clear();
m_info.get()->m_dest_uris<<m_target_uri;
Q_EMIT operationFinished();
notifyFileWatcherOperationFinished();
}