peony/libpeony-qt/file-info.cpp

315 lines
8.5 KiB
C++

/*
* 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 <gio/gunixmounts.h>
#include "file-info.h"
#include "file-info-manager.h"
#include "file-info-job.h"
#include "file-meta-info.h"
#include "file-utils.h"
#include "thumbnail-manager.h"
#include "emblem-provider.h"
#include <QUrl>
#include <QDir>
#include <QDebug>
using namespace Peony;
FileInfo::FileInfo(QObject *parent) : QObject (parent)
{
m_cancellable = g_cancellable_new();
}
FileInfo::FileInfo(const QString &uri, QObject *parent) : QObject (parent)
{
m_cancellable = g_cancellable_new();
/*!
* \note
* In qt program we alwas handle file's uri format as unicode,
* but in glib/gio it might be not.
* I want to keep the uri strings format in peony-qt,
* this would help me avoid some problem, such as the uri path completion
* bug in PathBarModel enumeration.
*/
m_uri = uri;
m_file = g_file_new_for_uri(uri.toUtf8().constData());
m_parent = g_file_get_parent(m_file);
m_is_remote = !g_file_is_native(m_file);
m_is_dir = false;
m_is_volume = false;
m_meta_info = FileMetaInfo::fromGFileInfo(uri, nullptr);
GFileType type = g_file_query_file_type(m_file, G_FILE_QUERY_INFO_NONE, nullptr);
switch (type) {
case G_FILE_TYPE_DIRECTORY:
//qDebug()<<"dir";
m_is_dir = true;
break;
case G_FILE_TYPE_MOUNTABLE:
//qDebug()<<"mountable";
m_is_volume = true;
break;
default:
break;
}
}
FileInfo::~FileInfo()
{
ThumbnailManager::getInstance()->releaseThumbnail(m_uri);
EmblemProviderManager::getInstance()->cancelQuery(m_uri);
//qDebug()<<"~FileInfo"<<m_uri;
disconnect();
g_object_unref(m_cancellable);
g_object_unref(m_file);
if (m_parent)
g_object_unref(m_parent);
m_uri = nullptr;
}
std::shared_ptr<FileInfo> FileInfo::fromUri(QString uri)
{
FileInfoManager *info_manager = FileInfoManager::getInstance();
// avoid using binding mount original uri. link to: #48982.
if (info_manager->isAutoParted()) {
if (uri.contains("file:///data/home")) {
uri.replace("file:///data/home", "file:///home");
}
}
info_manager->lock();
std::shared_ptr<FileInfo> info = info_manager->findFileInfoByUri(uri);
if (info != nullptr) {
info_manager->unlock();
return info;
} else {
std::shared_ptr<FileInfo> newly_info = std::make_shared<FileInfo>();
newly_info->m_uri = uri;
newly_info->m_file = g_file_new_for_uri(uri.toUtf8().constData());
newly_info->m_parent = g_file_get_parent(newly_info->m_file);
newly_info->m_is_remote = ! g_file_is_native(newly_info->m_file);
newly_info->m_is_dir = false;
newly_info->m_is_volume = false;
newly_info->m_meta_info = FileMetaInfo::fromGFileInfo(uri, nullptr);
if (! newly_info->m_is_remote && false) {
GFileType type = g_file_query_file_type(newly_info->m_file, G_FILE_QUERY_INFO_NONE, nullptr);
switch (type) {
case G_FILE_TYPE_DIRECTORY:
//qDebug()<<"dir";
newly_info->m_is_dir = true;
break;
case G_FILE_TYPE_MOUNTABLE:
//qDebug()<<"mountable";
newly_info->m_is_volume = true;
break;
default:
break;
}
}
newly_info = info_manager->insertFileInfo(newly_info);
info_manager->unlock();
return newly_info;
}
}
std::shared_ptr<FileInfo> FileInfo::fromPath(QString path)
{
QString uri = "file://" + path;
return fromUri(uri);
}
std::shared_ptr<FileInfo> FileInfo::fromGFile(GFile *file)
{
char *uri_str = g_file_get_uri(file);
QString uri = uri_str;
g_free(uri_str);
return fromUri(uri);
}
/*******
函数功能:判断文件是否是视频文件
一般的视频文件都是 video/*,但是有些视频文件比较特殊
比如:
asf : application/vnd.ms-asf
rmvb: application/vnd.rn-realmedia
swf : application/vnd.adobe.flash.movie
ts : text/vnd.trolltech.linguist
h264: application/octet-stream
目前上面这些是已经测试到的视频文件类型,如果有没有覆盖到的情况后面再补充
**/
bool FileInfo::isVideoFile()
{
if (nullptr != m_mime_type_string)
{
if (m_mime_type_string.startsWith("video")
|| m_mime_type_string.endsWith("vnd.trolltech.linguist")
|| m_mime_type_string.endsWith("vnd.adobe.flash.movie")
|| m_mime_type_string.endsWith("vnd.rn-realmedia")
|| m_mime_type_string.endsWith("vnd.ms-asf")
|| m_mime_type_string.endsWith("octet-stream"))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
bool FileInfo::isOfficeFile()
{
int idx = 0;
QString mtype = nullptr;
for (idx = 0; office_mime_types[idx] != "end"; idx++)
{
mtype = office_mime_types[idx];
if (m_mime_type_string.contains(mtype))
{
return true;
}
}
return false;
}
const QString FileInfo::targetUri()
{
return m_target_uri;
}
const QString FileInfo::symlinkTarget()
{
if (m_symlink_target == ".")
return "";
//fix soft link use relative path issue, link to bug#73529
if (! m_symlink_target.startsWith("/"))
{
QString parentUri = FileUtils::getParentUri(m_uri);
m_symlink_target = QUrl(parentUri).path() + "/" + m_symlink_target;
}
return m_symlink_target;
}
const QString FileInfo::customIcon()
{
if (!m_meta_info)
return nullptr;
return m_meta_info.get()->getMetaInfoString("custom-icon");
}
quint64 FileInfo::getDeletionDateUInt64()
{
return m_deletion_date_uint64;
}
const QString FileInfo::unixDeviceFile()
{
GFile* file;
const char *path;
bool isMountPoint;
GUnixMountEntry* entry;
char* device = nullptr;
QString unixDevice = nullptr;
isMountPoint = FileUtils::isMountPoint(m_uri);
//return from here if @m_uri is like "computer:///xxx"
if(!isMountPoint)
return m_unix_device_file;
//query device path if @m_uri is like "file:///media/user/xxx"
file = g_file_new_for_uri(m_uri.toUtf8().constData());
if(!file)
return unixDevice;
path = g_file_peek_path(file);
if(path){
entry = g_unix_mount_at(path,NULL);
if(!entry)
entry = g_unix_mount_for(path,NULL);
if(entry){
device = g_strescape(g_unix_mount_get_device_path(entry),NULL);
g_unix_mount_free(entry);
}
}
unixDevice = device;
g_object_unref(file);
if(device)
g_free(device);
return unixDevice;
}
const QString FileInfo::displayName()
{
if (isEmptyInfo())
return nullptr;
bool isMountPoint;
QString unixDevice,deviceName;
unixDevice = unixDeviceFile();
isMountPoint = FileUtils::isMountPoint(m_uri);
QString targetUri = FileUtils::getTargetUri(m_uri);
if(m_uri == "file:///DATA"
|| m_uri == "file:///data"
|| targetUri == "file:///data")
{
return tr("data");
}
if((nullptr != m_display_name)
&& (!isMountPoint
|| unixDevice.isEmpty() /*@m_uri is like "computer:///xxx"*/
|| !unixDevice.contains("/dev") /*audio-cd*/
|| unixDevice.contains("/dev/sr"))) { /*blank-cd or blank-dvd*/
return m_display_name;
}
if (m_uri.endsWith("/")) {
QString uri = m_uri;
if (!m_uri.endsWith(":///") && !m_uri.endsWith("://")) {
uri.chop(1);
}
return uri.split("/").last();
}
//@deviceName transcoding
deviceName = m_display_name;
FileUtils::handleVolumeLabelForFat32(deviceName,unixDevice);
return deviceName;
}