peony/ 0000755 0001750 0001750 00000000000 14205115226 010626 5 ustar feng feng peony/libpeony-qt/ 0000755 0001750 0001750 00000000000 14205115226 013071 5 ustar feng feng peony/libpeony-qt/complementary-style.h 0000644 0001750 0001750 00000004605 14205101223 017254 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef COMPLEMENTARYSTYLE_H
#define COMPLEMENTARYSTYLE_H
#include
#include "peony-core_global.h"
class QMenu;
class QPushButton;
namespace Peony {
/*!
* \brief The ComplementaryStyle class
* \details
* This class provide a fixed style for painting qt's control
* with system theme which qt5-gtk2-platformtheme provided.
*
* If just use the qpa plugin, there were be some incorrect styled
* controls. Such as QToolBarButton's indicator.
*
* \note
* If you are not using gtk-theme as default system theme, you should not use this
* proxy style for painting.
*
* \todo
* add border radius support.
*/
class ComplementaryStyle : public QProxyStyle
{
Q_OBJECT
public:
static PEONYCORESHARED_EXPORT ComplementaryStyle *getStyle();
void polish(QWidget *widget);
int styleHint(QStyle::StyleHint hint,
const QStyleOption *option = nullptr,
const QWidget *widget = nullptr,
QStyleHintReturn *returnData = nullptr) const;
void drawPrimitive(QStyle::PrimitiveElement element,
const QStyleOption *option,
QPainter *painter,
const QWidget *widget = nullptr) const;
void drawComplexControl(QStyle::ComplexControl cc,
const QStyleOptionComplex *opt,
QPainter *p,
const QWidget *widget = nullptr) const;
private:
explicit ComplementaryStyle(QStyle *parent = nullptr);
~ComplementaryStyle();
QMenu *m_styled_menu;
QPushButton *m_styled_button;
};
}
#endif // COMPLEMENTARYSTYLE_H
peony/libpeony-qt/libpeony-qt-header.pri 0000644 0001750 0001750 00000002513 14205101223 017267 0 ustar feng feng INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/file-operation
INCLUDEPATH += $$PWD/file-launcher
INCLUDEPATH += $$PWD/model
INCLUDEPATH += $$PWD/vfs
INCLUDEPATH += $$PWD/convenient-utils
INCLUDEPATH += $$PWD/controls
INCLUDEPATH += $$PWD/windows
INCLUDEPATH += $$PWD/effects
INCLUDEPATH += $$PWD/controls/directory-view
INCLUDEPATH += $$PWD/controls/directory-view/directory-view-factory
INCLUDEPATH += $$PWD/controls/directory-view/delegate
INCLUDEPATH += $$PWD/controls/directory-view/view
INCLUDEPATH += $$PWD/controls/directory-view/view/icon-view
INCLUDEPATH += $$PWD/controls/directory-view/view/list-view
INCLUDEPATH += $$PWD/controls/menu
INCLUDEPATH += $$PWD/controls/menu/directory-view-menu
INCLUDEPATH += $$PWD/controls/menu/side-bar-menu
INCLUDEPATH += $$PWD/controls/navigation-bar
INCLUDEPATH += $$PWD/controls/navigation-bar/location-bar
INCLUDEPATH += $$PWD/controls/navigation-bar/path-bar
INCLUDEPATH += $$PWD/controls/preview-page
INCLUDEPATH += $$PWD/controls/preview-page/default-preview-page
INCLUDEPATH += $$PWD/controls/preview-page/preview-page-factory
INCLUDEPATH += $$PWD/controls/property-page
INCLUDEPATH += $$PWD/controls/side-bar
INCLUDEPATH += $$PWD/controls/status-bar
INCLUDEPATH += $$PWD/controls/tab-page
INCLUDEPATH += $$PWD/controls/tool-bar
INCLUDEPATH += $$PWD/effects
INCLUDEPATH += $$PWD/../plugin-iface/
peony/libpeony-qt/volumeManager.h 0000644 0001750 0001750 00000014375 14205115226 016056 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2021, 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 .
*
* Authors: yanling
*
*/
#ifndef VOLUMEMANAGER_H
#define VOLUMEMANAGER_H
#include
#include
#include
#include
#include
#undef slots
#undef signals
#undef emit
#include
#include
namespace Experimental_Peony{
class Volume;
class Mount;
class Drive;
class Q_DECL_EXPORT VolumeManager : public QObject
{
Q_OBJECT
public:
static VolumeManager* getInstance();
~VolumeManager();
/*静态的获取当前所有有效的设备分区,函数名后期再做更换*/
QList* allVaildVolumes();
void printVolumeList();
private:
explicit VolumeManager(QObject *parent = nullptr);
bool gpartedIsOpening();
void initManagerInfo();
//void initMonitorInfo(); //监控卷分区
QList allMounts();
QList allGMounts();
QList allVolumes();
QList allGVolumes();
QList allGDrives(); /* 获取连接的GDrive集合 */
QList allDrives(); /* 将GDrive转为Drive */
//QString guessContentType(GMount*);
static void volumeAddCallback(GVolumeMonitor*,GVolume*,VolumeManager*);
static void volumeRemoveCallback(GVolumeMonitor*,GVolume*,VolumeManager*);
static void mountAddCallback(GVolumeMonitor*,GMount*,VolumeManager*);
static void mountRemoveCallback(GVolumeMonitor*,GMount*,VolumeManager*);
static void driveConnectCallback(GVolumeMonitor*,GDrive*,VolumeManager*);
static void driveDisconnectCallback(GVolumeMonitor*,GDrive*,VolumeManager*);
static void volumeChangeCallback(GVolumeMonitor*,GVolume*,VolumeManager*);
static void mountChangedCallback(GMount *mount, VolumeManager *pThis);
private:
GVolumeMonitor* m_volumeMonitor = nullptr;
quint64 m_volumeAddHandle;
quint64 m_volumeRemoveHandle;
quint64 m_volumeChangeHandle;
quint64 m_mountAddHandle;
quint64 m_mountRemoveHandle;
quint64 m_driveConnectHandle;
quint64 m_driveDisconnectHandle;
bool m_gpartedIsOpening;
QHash* m_volumeList = nullptr;
//我应该在检测到信号时更新卷设备列表?还是在用到时重新全部get一次?感觉前者好点?
Q_SIGNALS:
void volumeUpdate(const Volume&,QString); //gparted打开与关闭时可能会伴随设备信息的更新
void volumeAdd(const Volume&);
//volumeRemove()对应的槽内需要匹配device或者mountpoint
void volumeRemove(const QString&);//1、设备被真正移除 2、gparetd打开时卸载设备
//void volumeUnmount(const QString& device);
void mountAdd(const Volume&); //重设挂载点信息
void mountRemove(const QString& device);
void signal_unmountFinished(const QString &uri);/* 卸载完成信号 */
void signal_mountFinished();/* 挂载完成信号,目前用于侧边栏设备挂载后路径跳转 */
};
class Q_DECL_EXPORT Drive{
public:
//property
QString name() const;
QString icon() const;
QString device() const;
bool canEject() const;
bool canStop() const;
//bool unmountAble();
GDrive* getGDrive() const;
Drive(GDrive* gdrive);
~Drive();
//method
void eject(GMountUnmountFlags ejectFlag);
void setMountPath(const QString& mountPath);
private:
GDrive* m_drive = nullptr;
bool m_canEject = false ;
bool m_canStop = false;
QString m_name;
QString m_icon;
QString m_device;
QString m_mountPath;
private:
void initDriveInfo();
};
class Q_DECL_EXPORT Mount{
public:
QString name() const;
QString uuid() const;
QString icon() const;
bool canEject() const;
bool canStop() const;
bool canUnmount() const;
QString device() const;
QString mountPoint() const;
GMount* getGMount() const;
Mount(GMount* gmount);
~Mount();
void unmount();
private:
bool m_canEject = false ;
bool m_canStop = false ;
bool m_canUnmount = false ;
GMount* m_mount = nullptr;
QString m_name;
QString m_uuid;
QString m_icon;
QString m_device;
QString m_mountPoint;
GUnixMountEntry * m_entry = nullptr;
private:
void initMountInfo();
void queryDeviceByMountpoint();
};
class Q_DECL_EXPORT Volume{
public:
//property-to-get
QString name() const;
QString icon() const;
QString uuid() const;
QString device() const;
QString mountPoint() const;
GVolume* getGVolume() const;
//property-to-set
void setLabel(const QString& label);
void setFromMount(const Mount& mount);//通过Mount求Volume
void setFromDrive(const Drive& drive);//通过Drive获取Volume
void setMountPoint(QString point);
QString getMountPoint();
Volume* initRootVolume(); //根分区
Volume(GVolume* gvolume);
Volume(const Volume& other);//深拷贝
~Volume();
bool operator==(const Volume& other) const;
bool operator==(const Volume* other) const;
//bool operator==(const QString& deivce) const;
//method
bool canEject() const;
bool canStop() const;
bool canUnmount() const;
bool canMount() const;
void eject(GMountUnmountFlags ejectFlag);
void unmount();
void mount();
void format() const;
private:
bool m_canEject = false ;
bool m_canStop = false;
bool m_canUnmount = false ;
bool m_canMount = false;
GVolume* m_volume = nullptr;
GMount* m_gMount =nullptr;
GDrive* m_gdrive = nullptr;
QString m_name;
QString m_uuid;
QString m_icon;
QString m_device;
QString m_mountPoint;
private:
void initVolumeInfo();
};
}
#endif // VOLUMEMANAGER_H
peony/libpeony-qt/file-enumerator.h 0000644 0001750 0001750 00000020356 14205101223 016336 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef FILEENUMERATOR_H
#define FILEENUMERATOR_H
#include
#include "peony-core_global.h"
#include
#include
#include
#include "custom-error-handler.h"
class QTimer;
namespace Peony {
class FileInfo;
class GErrorWrapper;
/*!
* \brief The FileEnumerator class
*
* FileEnumerator is a file enumeration class with its own exception handling.
* This class provides a unified interface for accessing various uri path subfiles.
* It also supports pre-processing for some uri paths that require special processing
* and provides interaction when needed.
* The essence of this class is a wrapper of GFileEnumerator.
*
*/
class PEONYCORESHARED_EXPORT FileEnumerator : public QObject
{
Q_OBJECT
public:
explicit FileEnumerator(QObject *parent = nullptr);
~FileEnumerator();
void setEnumerateDirectory(QString uri);
void setEnumerateDirectory(GFile *file);
void setEnumerateWithInfoJob(bool query = true);
QString getEnumerateUri();
/*!
* \brief prepare
*
* prepare
* This is an async method that do some pre-handling before
* we really start an enumerating. Ofcourse,
* you can enumerate a file without any preparing, but
* I recommend do something preparing before we enumerate a directory.
* For some special uri, such as drive in computer or remote sftp, we
* can not directly enumerate their children. It is best to wait async
* of prepare done, then we can enumerate the file, or get something
* error messages. we should connect prepared() signal for async.
*
* \see prepared().
*/
void prepare();
/*!
* \brief enumerateSync
*
* Enumerate children of a path, blocking i/o.
*
* \note It might not enum children successfully for some error.
* if you want to
* \see enumerateChildren().
*/
void enumerateSync();
/*!
* \brief getChildren
* \return
*/
const QList> getChildren();
const QStringList getChildrenUris() {
return *m_children_uris;
}
void setAutoDelete(bool autoDelete = true) {
m_auto_delete = true;
}
Q_SIGNALS:
/*!
* \brief prepared
* \param err
* \param targetUri return the real uri should enumerate.
* \param critical if true, show a critical dialog.
*
* We often start an enumerating after prepared signal sended.
* This will reduce the 'risks' of errors.
*
* \see prepare().
*/
void prepared(const std::shared_ptr &err = nullptr, const QString &targetUri = nullptr, bool critical = false);
/*!
* \brief childrenUpdated
* \param uriList, uri list of newly enumerated files.
*
* If we use enumerateAsync(), we might not get all
* the children at once. This signal sends everytime
* there are newly children found asynchronously.
* connect this signal in you classes and update you data.
* or connect finished signal which sends when all
* children were found asynchronously.
*
* \see enumerateAsync(), enumerator_next_files_async_ready_callback();
*/
void childrenUpdated(const QStringList &uriList, bool isEnding = false);
/*!
* \brief enumerateFinished
* \param successed
* \retval true, if enumerate children successed.
* \retval false, if enumerate children failed.
* \note For other class, they might only care whether
* there are children found when enumerating.
* They don't care how enumerator dealing with some error.
* So just tell them the last result with this signal.
*/
void enumerateFinished(bool successed = false);
void cancelled();
public Q_SLOTS:
void enumerateAsync();
/*!
* \brief cancel
*
* Cancel all the work of this eumerator excuting now,
* including mounting, enumerating, etc.
*
*/
void cancel();
protected:
/*!
* \brief handleError
* \param err
*
*/
void handleError(GError *err);
/*!
* \brief enumerateChildren, a sync method enumerate children and cached their GFile handle.
* \param enumerator, handle of enum next file.
*/
void enumerateChildren(GFileEnumerator *enumerator);
/*!
* \brief enumerateTargetFile
* \return target uri which original uri point to.
* \note for some special uri, such as volume in 'computer:///',
* or server in 'network:///', etc, the could not enumerate directly.
* gvfs supplied query their target uri, if they have mounted into local.
* Use this uri rather than the raw one, otherwise we might not enumerate
* their children.
*/
GFile *enumerateTargetFile();
/*!
* \brief prepare_enumerate_callback
* \param file
* \param res
* \param p_this
* \return
* \see prepare(), handleError()
*/
static GAsyncReadyCallback prepare_enumerate_callback(GFile *file,
GAsyncResult *res,
FileEnumerator *p_this);
/*!
* \brief mount_mountable_callback
* \param file
* \param res
* \param p_this
* \return
* \see handleError().
*/
static GAsyncReadyCallback mount_mountable_callback(GFile *file,
GAsyncResult *res,
FileEnumerator *p_this);
/*!
* \brief mount_enclosing_volume_callback
* \param file
* \param res
* \param p_this
* \return
* \see handleError().
*/
static GAsyncReadyCallback mount_enclosing_volume_callback(GFile *file,
GAsyncResult *res,
FileEnumerator *p_this);
/*!
* \brief find_children_async_ready_callback
* \param file
* \param res
* \param p_this
* \return
* \see enumerateAsync().
*/
static GAsyncReadyCallback find_children_async_ready_callback(GFile *file,
GAsyncResult *res,
FileEnumerator *p_this);
/*!
* \brief enumerator_next_files_async_ready_callback
* \param enumerator
* \param res
* \param p_this
* \return
* \see enumerateAsync().
*/
static GAsyncReadyCallback enumerator_next_files_async_ready_callback(GFileEnumerator *enumerator,
GAsyncResult *res,
FileEnumerator *p_this);
private:
QString m_uri;
GFile *m_root_file = nullptr;
GCancellable *m_cancellable = nullptr;
QList *m_children_uris = nullptr;
QStringList *m_cache_uris;
QTimer *m_idle;
bool m_auto_delete = false;
bool m_with_info_job = false;
/*!
* \brief m_cached_infos
* \note
* we could not get this cache directly. insteadly we can use
* FileInfo::fromUri() to get each of them while enumerating finished.
* this cache just hold the strong reference during enumerating.
* once we didn't hold a ref before it deleted, it will unref automaticly.
*
* \see
* setEnumerateWithInfoJob(),
* getChildren()
*/
QList> m_cached_infos;
/*!
* \brief m_is_custom_error_handler_initialized
* \
*/
bool m_is_custom_error_handler_initialized = false;
/*!
* \brief m_custom_error_handlers
* handling custom error occurred in custom vfs.
* \see VFSPluginIface::customErrorHandler().
*/
QMap m_custom_error_handlers;
};
}
#endif // FILEENUMERATOR_H
peony/libpeony-qt/org.ukui.peony.settings.gschema.xml 0000644 0001750 0001750 00000001170 14205115226 021753 0 ustar feng feng
true
show trash dialog
Displays the delete to recycle bin dialog box
false
show hide file
show hide files in peony and peony-desktop
peony/libpeony-qt/mount-operation.h 0000644 0001750 0001750 00000005660 14205101223 016401 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef MOUNTOPERATION_H
#define MOUNTOPERATION_H
#include "peony-core_global.h"
#include
#include
#include
namespace Peony {
class ConnectServerLogin;
class GErrorWrapper;
/*!
* \brief The MountOperation class
*
* This class is a wrapper of GFileMountOperation.
* MountOperation provides a interactive dialog for connecting server.
* In gvfs, all kinds of remote location will use g_file_mount_enclosing_volume()
* for those volumes mounting, many of them need extra infomation, such as user, password, etc.
* This class will help to handle them together.
*
* \note FileEnumerator::prepare() and FileEnumerator::handleError() might use this class instance.
*/
class PEONYCORESHARED_EXPORT MountOperation : public QObject
{
Q_OBJECT
public:
explicit MountOperation(QString uri, QObject *parent = nullptr);
~MountOperation();
void setAutoDelete(bool isAuto = true) {
m_auto_delete = isAuto;
}
Q_SIGNALS:
void finished(const std::shared_ptr &err = nullptr);
void cancelled();
public Q_SLOTS:
void start();
void cancel();
protected:
static GAsyncReadyCallback mount_enclosing_volume_callback(GFile *volume,
GAsyncResult *res,
MountOperation *p_this);
static void
aborted_cb (GMountOperation *op,
MountOperation *p_this);
static void
ask_question_cb (GMountOperation *op,
char *message,
char **choices,
MountOperation *p_this);
static void
ask_password_cb (GMountOperation *op,
const char *message,
const char *default_user,
const char *default_domain,
GAskPasswordFlags flags,
MountOperation *p_this);
private:
bool m_auto_delete = false;
GFile *m_volume = nullptr;
GMountOperation *m_op = nullptr;
GCancellable *m_cancellable = nullptr;
/*!
* \brief m_errs
* \deprecated use GErrorWrapper.
*/
GList *m_errs = nullptr;
ConnectServerLogin *m_dlg = nullptr;
};
}
#endif // MOUNTOPERATION_H
peony/libpeony-qt/peony-core_global.h 0000644 0001750 0001750 00000002067 14205101223 016637 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef PEONYCORE_GLOBAL_H
#define PEONYCORE_GLOBAL_H
#include
#undef signals
#undef slots
#undef emit
#if defined(PEONYCORE_LIBRARY)
# define PEONYCORESHARED_EXPORT Q_DECL_EXPORT
#else
# define PEONYCORESHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // PEONYCORE_GLOBAL_H
peony/libpeony-qt/file-info-manager.h 0000644 0001750 0001750 00000005445 14205115226 016532 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef FILEINFOMANAGER_H
#define FILEINFOMANAGER_H
#include "file-info.h"
#include
namespace Peony {
/*!
* \brief The FileInfoManager class
*
* This is a class used to share FileInfo instances acrossing various members.
* It is a single instance class with a hash table that cached all infos.
* We generally would not operate directly on instance of this class,
* because FileInfo class provides an interface for this class.
* use FileInfo::fromUri(), FileInfo::fromPath() or FileInfo::fromGFile()
* for getting the corresponding shared data.
*
* \note The memory management is based on std smart pointer, but it is not regular.
* Because hash table always hold a use count of shared data. If you want to use
* shared data of this class instance, you should remenmber this point:
* When releasing your info resources, you aslo need to add an additional judgment that whether
* there is no other member but you and manager instance hold this shared data.
* If true, you should aslo remove the element in manager's hash for really releasing resources.
* Otherwise, it might cause an one-time memory leak.
* \see FileInfo, FileInfoJob, FileEnumerator; FileInfo::~FileInfo(), FileInfoJob::~FileInfoJob(),
* FileEnumerator::~FileEnumerator().
* \bug
* Even though I try my best to make share the file info data, it seems that the info is not be shared
* sometimes. Maybe there were some wrong in other classes?
*/
class PEONYCORESHARED_EXPORT FileInfoManager
{
friend class FileInfo;
public:
static FileInfoManager *getInstance();
std::shared_ptr findFileInfoByUri(const QString &uri); //{return global_info_list->value(uri);}
void lock() {
m_mutex.lock();
}
void unlock() {
m_mutex.unlock();
}
void showState();
protected:
std::shared_ptr insertFileInfo(std::shared_ptr info); //{global_info_list->insert(info->uri(), info);}
private:
FileInfoManager();
~FileInfoManager();
QMutex m_mutex;
};
}
#endif // FILEINFOMANAGER_H
peony/libpeony-qt/file-copy.h 0000644 0001750 0001750 00000005071 14205101223 015124 0 ustar feng feng /*
* 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 .
*
* Authors: Ding Jing
*
*/
#ifndef FILECOPY_H
#define FILECOPY_H
#include
#include
#include
namespace Peony
{
/**
* @brief Copy the file to the specified folder.
* @note The source file must be a file, not a folder,
*/
class FileInfo;
class FileCopy : public QObject
{
Q_OBJECT
public:
enum Status
{
INVALID,
PAUSE,
RESTART,
CANCEL,
RUNNING,
RESUME,
FINISHED,
ERROR
};
Q_ENUM(Status)
explicit FileCopy (QString srcUri, QString destUri, GFileCopyFlags flags, GCancellable* cancel, GFileProgressCallback cb, gpointer pcd, GError** error, QObject* obj = nullptr);
~FileCopy();
/**
* @brief 整个复制流程在这里
*/
void run();
public Q_SLOTS:
/**
* @brief pause
*/
void pause();
/**
* @brief resume
*/
void resume();
/**
* @brief cancel
*/
void cancel();
private Q_SLOTS:
private:
void updateProgress () const;
void detailError (GError** error);
void sync(const GFile* destFile);
private:
QMutex mPause;
QString mSrcUri = nullptr;
QString mDestUri = nullptr;
GFileProgressCallback mProgress;
GFileCopyFlags mCopyFlags;
GCancellable* mCancel = nullptr; // temp param
GError** mError = nullptr; // temp param
gpointer mProgressData;
goffset mOffset = 0; // 记录当前进度
goffset mTotalSize = 0; // 记录当前进度
enum Status mStatus = INVALID; // 记录运行状态
};
};
#endif // FILECOPY_H
peony/libpeony-qt/file-meta-info.cpp 0000644 0001750 0001750 00000013442 14205101223 016365 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#include "file-meta-info.h"
#include "file-info-manager.h"
#include
using namespace Peony;
std::shared_ptr FileMetaInfo::fromGFileInfo(const QString &uri, GFileInfo *g_info)
{
return std::make_shared(uri, g_info);
}
std::shared_ptr FileMetaInfo::fromUri(const QString &uri)
{
auto mgr = FileInfoManager::getInstance();
auto info = mgr->findFileInfoByUri(uri);
if (info)
return mgr->findFileInfoByUri(uri)->m_meta_info;
return nullptr;
}
FileMetaInfo::FileMetaInfo(const QString &uri, GFileInfo *g_info)
{
m_uri = uri;
if (g_info) {
char **metainfo_attributes = g_file_info_list_attributes(g_info, "metadata");
if (metainfo_attributes) {
for (int i = 0; metainfo_attributes[i] != nullptr; i++) {
char *string = g_file_info_get_attribute_as_string(g_info, metainfo_attributes[i]);
if (string) {
auto var = QVariant(string);
this->setMetaInfoVariant(metainfo_attributes[i], var, false);
//qDebug()<<"======"<message;
g_error_free(err);
}
}
// g_object_unref(info);
g_object_unref(file);
// m_mutex.unlock();
}
const QVariant FileMetaInfo::getMetaInfoVariant(const QString &key)
{
QString realKey = key;
if (!key.startsWith("metadata::"))
realKey = "metadata::" + key;
if (m_meta_hash.value(realKey).isValid())
return m_meta_hash.value(realKey);
//FIXME: should i use gio query meta here?
return QVariant();
}
const QString FileMetaInfo::getMetaInfoString(const QString &key)
{
return getMetaInfoVariant(key).toString();
}
const QStringList FileMetaInfo::getMetaInfoStringList(const QString &key)
{
return getMetaInfoVariant(key).toString().split('\n');
}
int FileMetaInfo::getMetaInfoInt(const QString &key)
{
return getMetaInfoVariant(key).toString().toInt();
}
void FileMetaInfo::removeMetaInfo(const QString &key)
{
// if (!m_mutex.tryLock(300)) {
// return;
// }
QString realKey = key;
if (!key.startsWith("metadata::"))
realKey = "metadata::" + key;
m_meta_hash.remove(realKey);
GFile *file = g_file_new_for_uri(m_uri.toUtf8().constData());
g_file_set_attribute(file,
realKey.toUtf8().constData(),
G_FILE_ATTRIBUTE_TYPE_INVALID,
nullptr,
G_FILE_QUERY_INFO_NONE,
nullptr,
nullptr);
// GFileInfo *info = g_file_info_new();
// std::string tmp = realKey.toStdString();
// //g_file_info_set_attribute(info, realKey.toUtf8(), G_FILE_ATTRIBUTE_TYPE_INVALID, nullptr);
// g_file_info_remove_attribute(info, realKey.toUtf8());
// //FIXME: should i add callback?
// g_file_set_attributes_async(file,
// info,
// G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
// 0,
// nullptr,
// nullptr,
// nullptr);
// g_object_unref(info);
g_object_unref(file);
// m_mutex.unlock();
}
peony/libpeony-qt/file-watcher.h 0000644 0001750 0001750 00000012036 14205101223 015606 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef FILEWATCHER_H
#define FILEWATCHER_H
#include
#include "peony-core_global.h"
#include
namespace Peony {
/*!
* \brief The FileWatcher class
*
* FileWatcher class is a wrapper of a set of GFileMonitor handles.
* The most obvious difference between it and the ordinary GFileMonitor is that
* it can dynamically track the monitoring directory. For example,
* if your directory move to another path, the watcher will aslo change
* its monitors. If you delete the path (or trash), it will be deleted
* automaticly later.
*
* \bug
* FileWatcher can't monitor some special directory, such as a sftp:// server.
* It will cause the model can not stay in sync with filesystem. This bug is the
* gio's limitations of GFileMonitor.
*/
class PEONYCORESHARED_EXPORT FileWatcher : public QObject
{
Q_OBJECT
public:
explicit FileWatcher(QString uri = nullptr, QObject *parent = nullptr, bool isWatchMovesFlag=false);
~FileWatcher();
/*!
* \brief setMonitorChildrenChange
* \param monitor_children_change
* \details
* For most case, we do not care wether a file internal changed event
* in file manager (for example, the file's content changed).
* Some special files, like files in computer:///, could use this signal
* to monitor the changed event that not created or deleted
* (for volume file handle in computer:///, it might be mount/unmount).
*/
void setMonitorChildrenChange(bool monitor_children_change = true) {
m_montor_children_change = monitor_children_change;
}
void startMonitor();
void stopMonitor();
void forceChangeMonitorDirectory(const QString &uri);
const QString currentUri() {return m_uri;}
/*!
* \brief supportMonitor
* \return
* \details
* Some file or directory doesn't support g_file_monitor* methods.
* We can use this to ensure that if it was truely in monitoring.
* If not, we might take over the handle of file change in our own
* code.
*/
bool supportMonitor() {
return m_support_monitor;
}
void creatorMonitor();
Q_SIGNALS:
void locationChanged(const QString &oldUri, const QString &newUri);
void directoryDeleted(const QString &uri);
void directoryUnmounted(const QString &uri);
void fileCreated(const QString &uri);
void fileDeleted(const QString &uri);
void fileChanged(const QString &uri);
void fileRenamed(const QString &oldUri, const QString &newUri);
/*!
* \brief requestUpdateDirectory
* \note
* only used in directory not support monitor
*/
void requestUpdateDirectory();
void thumbnailUpdated(const QString &uri);
public Q_SLOTS:
void cancel();
protected:
void prepare();
static void file_changed_callback(GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
FileWatcher *p_this);
static void dir_changed_callback(GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
FileWatcher *p_this);
void changeMonitorUri(QString uri);
private:
QString m_uri = nullptr;
QString m_target_uri = nullptr;
GFile *m_file = nullptr;
GFileMonitor *m_monitor = nullptr;
GFileMonitor *m_dir_monitor = nullptr;
bool m_montor_children_change = false;
GCancellable *m_cancellable = nullptr;
/*!
* \brief m_monitor_err
* \deprecated use GErrorWrapper
*/
GError *m_monitor_err = nullptr;
/*!
* \brief m_dir_monitor_err
* \deprecated use GErrorWrapper
*/
GError *m_dir_monitor_err = nullptr;
gulong m_file_handle = 0;
gulong m_dir_handle = 0;
bool m_support_monitor = true;
/* 文件和文件夹重名用先delete再create的方式(即GFileMonitorFlags使用G_FILE_MONITOR_NONE)时该标志值为false,
文件和文件夹重名用rename的方式(即GFileMonitorFlags使用G_FILE_MONITOR_WATCH_MOVES)时该标志值为true */
bool m_isWatchMovesFlag = false;
};
}
#endif // FILEWATCHER_H
peony/libpeony-qt/libpeony-qt.qrc 0000644 0001750 0001750 00000000311 14205115226 016036 0 ustar feng feng
data/libpeony-qt-light.qss
data/libpeony-qt-dark.qss
data/libpeony-qt-styled.qss
peony/libpeony-qt/bookmark-manager.h 0000644 0001750 0001750 00000004160 14205115226 016460 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef BOOKMARKMANAGER_H
#define BOOKMARKMANAGER_H
#include
#include
#include
#include "peony-core_global.h"
namespace Peony {
/*!
* \brief The BookMarkManager class
* \details
* This class is use to manage bookmarks of peony.
* You can add/remove custom bookmark at peony's side bar.
*/
class PEONYCORESHARED_EXPORT BookMarkManager : public QObject
{
Q_OBJECT
public:
static BookMarkManager *getInstance();
const QStringList getCurrentUris() {
return m_uris;
}
bool isLoaded() {
return m_is_loaded;
}
Q_SIGNALS:
void urisLoaded();
void bookMarkAdded(const QString &uri, bool successed);
void bookMarkRemoved(const QString &uri, bool successed);
void bookmarkChanged(const QString oldUri, const QString newUri);
public Q_SLOTS:
void addBookMark(const QString &uri);
void removeBookMark(const QString &uri);
void renameBookmark(const QString oldUri, const QString newUri);
void removeBookMark(const QStringList &uris);
private:
explicit BookMarkManager(QObject *parent = nullptr);
~BookMarkManager();
void addBookMarkPrivate(const QString &uri);
void removeBookMarkPrivate(const QString &uri);
QStringList m_uris;
QSettings *m_book_mark = nullptr;
bool m_is_loaded = false;
QMutex m_mutex;
};
}
#endif // BOOKMARKMANAGER_H
peony/libpeony-qt/copy-headers.sh 0000755 0001750 0001750 00000000202 14205101223 015775 0 ustar feng feng #!/bin/bash
echo "copy header files"
find $(dirname $0) -name "*.h" | xargs -i cp {} $(dirname $0)/development-files/header-files
peony/libpeony-qt/custom-error-handler.h 0000644 0001750 0001750 00000003502 14205101223 017306 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2021, 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 .
*
* Authors: Yue Lan
*
*/
#ifndef CUSTOMERRORHANDLER_H
#define CUSTOMERRORHANDLER_H
#include
#include "peony-core_global.h"
namespace Peony {
class PEONYCORESHARED_EXPORT CustomErrorHandler : public QObject
{
Q_OBJECT
public:
explicit CustomErrorHandler(QObject *parent = nullptr);
/*!
* \brief errorCodeSupportHandling
* \return a list of error code the handler supported.
*/
virtual QList errorCodeSupportHandling();
virtual void handleCustomError(const QString &uri, int errorCode);
Q_SIGNALS:
/*!
* \brief finished
* tell the enumerator error handling finished, and can continue
* do enumeration.
*/
void finished();
/*!
* \brief canceled
* tell the enumerator error handling cancelled, enumerator will go back
* to previous directory.
*/
void cancelled();
/*!
* \brief failed
* \param message
* similar to cancelled(), but providing a error message for show error message.
*/
void failed(const QString &message);
};
}
#endif // CUSTOMERRORHANDLER_H
peony/libpeony-qt/mount-operation.cpp 0000644 0001750 0001750 00000016425 14205101223 016735 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#include "mount-operation.h"
//#include "connect-server-dialog.h"
#include "connect-to-server-dialog.h"
#include "gerror-wrapper.h"
#include
#include
#include
#include
#include
using namespace Peony;
MountOperation::MountOperation(QString uri, QObject *parent) : QObject(parent)
{
m_volume = g_file_new_for_uri(uri.toUtf8().constData());
m_op = g_mount_operation_new();
m_cancellable = g_cancellable_new();
}
MountOperation::~MountOperation()
{
disconnect();
//g_object_disconnect (G_OBJECT (m_op), "any_signal::signal_name", nullptr);
g_signal_handlers_disconnect_by_func(m_op, (void *)G_CALLBACK(ask_password_cb), nullptr);
g_signal_handlers_disconnect_by_func(m_op, (void *)G_CALLBACK(ask_question_cb), nullptr);
g_signal_handlers_disconnect_by_func(m_op, (void *)G_CALLBACK(aborted_cb), nullptr);
g_object_unref(m_volume);
g_object_unref(m_op);
g_object_unref(m_cancellable);
//g_list_free_full(m_errs, GDestroyNotify(g_error_free));
m_dlg->deleteLater();
}
void MountOperation::cancel()
{
g_cancellable_cancel(m_cancellable);
g_object_unref(m_cancellable);
m_cancellable = g_cancellable_new();
Q_EMIT cancelled();
if (m_auto_delete)
deleteLater();
}
void MountOperation::start()
{
gchar* urit = g_file_get_uri(m_volume);
QUrl uri = QUrl(urit);
if (uri.scheme() != "mtp") {
ConnectServerLogin* dlg = new ConnectServerLogin(urit);
m_dlg = dlg;
//block ui
auto code = dlg->exec();
if (code == QDialog::Accepted) {
g_mount_operation_set_username(m_op, dlg->user().toUtf8().constData());
g_mount_operation_set_password(m_op, dlg->password().toUtf8().constData());
g_mount_operation_set_domain(m_op, dlg->domain().toUtf8().constData());
g_mount_operation_set_anonymous(m_op, dlg->anonymous());
//TODO: when FileEnumerator::prepare(), trying mount volume without password dialog first.
g_mount_operation_set_password_save(m_op, dlg->savePassword()? G_PASSWORD_SAVE_FOR_SESSION: G_PASSWORD_SAVE_NEVER);
}
if (code == QDialog::Rejected) {
cancel();
QMessageBox msg;
msg.setText(tr("Operation Cancelled"));
msg.exec();
return;
}
}
g_file_mount_enclosing_volume(m_volume, G_MOUNT_MOUNT_NONE, m_op, m_cancellable, GAsyncReadyCallback(mount_enclosing_volume_callback), this);
g_signal_connect (m_op, "ask-question", G_CALLBACK(ask_question_cb), this);
g_signal_connect (m_op, "ask-password", G_CALLBACK (ask_password_cb), this);
g_signal_connect (m_op, "aborted", G_CALLBACK (aborted_cb), this);
if (nullptr != urit) g_free(urit);
}
#include "global-settings.h"
GAsyncReadyCallback MountOperation::mount_enclosing_volume_callback(GFile *volume,
GAsyncResult *res,
MountOperation *p_this)
{
GError *err = nullptr;
g_file_mount_enclosing_volume_finish (volume, res, &err);
if (err) {
qDebug()<code<message<domain;
auto errWarpper = GErrorWrapper::wrapFrom(err);
p_this->finished(errWarpper);
} else{
QUrl url = QUrl(g_file_get_uri(volume));
p_this->m_dlg->syncRemoteServer(url);
p_this->finished(nullptr);
}
if (p_this->m_auto_delete) {
p_this->disconnect();
p_this->deleteLater();
}
return nullptr;
}
void MountOperation::ask_question_cb(GMountOperation *op,
char *message, char **choices,
MountOperation *p_this)
{
qDebug()<<"ask question cb:"<setText(message);
char **choice = choices;
int i = 0;
while (*choice) {
qDebug()<<*choice;
QPushButton *button = msg_box->addButton(QString(*choice), QMessageBox::ActionRole);
connect(button, &QPushButton::clicked, [=]() {
g_mount_operation_set_choice(op, i);
});
*choice++;
i++;
}
//block ui
msg_box->exec();
msg_box->deleteLater();
qDebug()<<"msg_box done";
g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
}
void MountOperation::ask_password_cb(GMountOperation *op,
const char *message,
const char *default_user,
const char *default_domain,
GAskPasswordFlags flags,
MountOperation *p_this)
{
Q_UNUSED(message);
Q_UNUSED(default_user);
Q_UNUSED(default_domain);
Q_UNUSED(flags);
Q_UNUSED(p_this);
//block ui
if (p_this->m_dlg->anonymous()) {
// try login anonymous once, if not successed, ask password.
p_this->m_dlg->m_usr_btn_usr->click();
g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
return;
} else {
// try get password and login once, if not successed, show message and
// require input password again.
if (!p_this->m_dlg->password().isEmpty()) {
p_this->m_dlg->m_reg_usr_passwd_editor->setText(nullptr);
g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
return;
} else {
QMessageBox::information(0, 0, message);
auto code = p_this->m_dlg->exec();
auto dlg = p_this->m_dlg;
if (code == QDialog::Accepted) {
g_mount_operation_set_username(op, dlg->user().toUtf8().constData());
g_mount_operation_set_password(op, dlg->password().toUtf8().constData());
g_mount_operation_set_domain(op, dlg->domain().toUtf8().constData());
g_mount_operation_set_anonymous(op, dlg->anonymous());
g_mount_operation_set_password_save(op, dlg->savePassword()? G_PASSWORD_SAVE_FOR_SESSION: G_PASSWORD_SAVE_NEVER);
g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
return;
}
if (code == QDialog::Rejected) {
g_mount_operation_reply (op, G_MOUNT_OPERATION_ABORTED);
return;
}
}
}
g_mount_operation_reply (op, G_MOUNT_OPERATION_HANDLED);
}
void MountOperation::aborted_cb(GMountOperation *op,
MountOperation *p_this)
{
g_mount_operation_reply(op, G_MOUNT_OPERATION_ABORTED);
p_this->disconnect();
p_this->deleteLater();
}
peony/libpeony-qt/file-utils.cpp 0000644 0001750 0001750 00000073006 14205115226 015660 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#include "file-utils.h"
#include "file-info.h"
#include "volume-manager.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace Peony;
FileUtils::FileUtils()
{
}
QString FileUtils::getQStringFromCString(char *c_string, bool free)
{
QString value = c_string;
if (free)
g_free(c_string);
return value;
}
QString FileUtils::getFileUri(const GFileWrapperPtr &file)
{
if (!G_IS_FILE (file.get()->get())) {
return nullptr;
}
char *uri = g_file_get_uri(file.get()->get());
QString urlString = QString(uri);
QUrl url = urlString;
g_free(uri);
char *path = g_file_get_path(file.get()->get());
if (path && !url.isLocalFile()) {
QString urlString = QString("file://%1").arg(path);
g_free(path);
return urlString;
}
return urlString;
}
QString FileUtils::getFileBaseName(const GFileWrapperPtr &file)
{
char *basename = g_file_get_basename(file.get()->get());
return getQStringFromCString(basename);
}
QString FileUtils::getUriBaseName(const QString &uri)
{
QUrl url = uri;
return url.fileName();
}
GFileWrapperPtr FileUtils::getFileParent(const GFileWrapperPtr &file)
{
return wrapGFile(g_file_get_parent(file.get()->get()));
}
QString FileUtils::getRelativePath(const GFileWrapperPtr &dir, const GFileWrapperPtr &file)
{
char *relative_path = g_file_get_relative_path(dir.get()->get(), file.get()->get());
return getQStringFromCString(relative_path);
}
GFileWrapperPtr FileUtils::resolveRelativePath(const GFileWrapperPtr &dir, const QString &relativePath)
{
return wrapGFile(g_file_resolve_relative_path(dir.get()->get(),
relativePath.toUtf8().constData()));
}
QString FileUtils::urlEncode(const QString& url)
{
QString decodeUrl = urlDecode(url);
if (!decodeUrl.isEmpty()) {
g_autofree gchar* encodeUrl = g_uri_escape_string (decodeUrl.toUtf8().constData(), ":/", true);
// qDebug() << "encode url from:'" << url <<"' to '" << encodeUrl << "'";
return encodeUrl;
}
g_autofree gchar* encodeUrl = g_uri_escape_string (url.toUtf8().constData(), ":/", true);
// qDebug() << "encode url from:'" << url <<"' to '" << encodeUrl << "'";
return encodeUrl;
}
QString FileUtils::urlDecode(const QString &url)
{
g_autofree gchar* decodeUrl = g_uri_unescape_string(url.toUtf8(), ":/");
if (!decodeUrl) {
// qDebug() << "decode url from:'" << url <<"' to '" << url << "'";
return url;
}
// qDebug() << "decode url from:'" << url <<"' to '" << decodeUrl << "'";
return decodeUrl;
}
QString FileUtils::handleDuplicateName(const QString& uri)
{
QString handledName = nullptr;
QString name = QUrl(uri).toDisplayString().split("/").last();
QRegExp regExpNum("\\(\\d+\\)");
QRegExp regExp (QString("\\ -\\ %1\\(\\d+\\)(\\.[0-9a-zA-Z\\.]+|)$").arg(QObject::tr("duplicate")));
QString dupReg = nullptr;
if (name.contains(regExp)) {
int num = 0;
QString numStr = "";
QString ext = regExp.cap(0);
if (ext.contains(regExpNum)) {
numStr = regExpNum.cap(0);
}
numStr.remove(0, 1);
numStr.chop(1);
num = numStr.toInt();
++num;
handledName = name.replace(regExp, ext.replace(regExpNum, QString("(%1)").arg(num)));
} else {
if (name.contains(".")) {
auto list = name.split(".");
if (list.count() <= 1) {
handledName = name + QString(" - %1(1)").arg(QObject::tr("duplicate"));
} else {
int pos = list.count() - 1;
if (list.last() == "gz"
|| list.last() == "xz"
|| list.last() == "Z"
|| list.last() == "sit"
|| list.last() == "bz"
|| list.last() == "bz2") {
--pos;
}
if (pos < 0) {
pos = 0;
}
auto tmp = list;
QStringList suffixList;
for (int i = 0; i < list.count() - pos; i++) {
suffixList.prepend(tmp.takeLast());
}
auto suffix = suffixList.join(".");
auto basename = tmp.join(".");
name = basename + QString(" - %1(1)").arg(QObject::tr("duplicate")) + "." + suffix;
if (name.endsWith(".")) {
name.chop(1);
}
handledName = name;
}
} else {
handledName = name + QString(" - %1(1)").arg(QObject::tr("duplicate"));
}
}
return handledName;
}
QString FileUtils::handleDesktopFileName(const QString& uri, const QString& displayName)
{
//no need self handle, add return to fix bug#72642
return displayName;
QString name = QUrl(uri).toDisplayString().split("/").last();
QRegExp regExpNum("\\(\\d+\\)");
auto showName = displayName;
if (!name.contains(QObject::tr("duplicate")))
return displayName;
QStringList matchList;
int pos=0;
while((pos=regExpNum.indexIn(name,pos))!=-1)
{
pos+=regExpNum.matchedLength();
QString result=regExpNum.cap(0);
matchList<get(),
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
nullptr);
return type == G_FILE_TYPE_DIRECTORY || type == G_FILE_TYPE_MOUNTABLE;
}
bool FileUtils::getFileIsFolder(const GFileWrapperPtr &file)
{
GFileType type = g_file_query_file_type(file.get()->get(),
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
nullptr);
return type == G_FILE_TYPE_DIRECTORY;
}
bool FileUtils::getFileIsFolder(const QString &uri)
{
auto info = FileInfo::fromUri(uri);
return info.get()->isDir();
}
bool FileUtils::getFileIsSymbolicLink(const QString &uri)
{
auto info = FileInfo::fromUri(uri);
return info.get()->isSymbolLink();
}
QStringList FileUtils::getChildrenUris(const QString &directoryUri)
{
QStringList uris;
GError *err = nullptr;
GFile *top = g_file_new_for_uri(directoryUri.toUtf8().constData());
GFileEnumerator *e = g_file_enumerate_children(top, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
nullptr, &err);
if (err) {
g_error_free(err);
}
g_object_unref(top);
if (!e)
return uris;
auto child_info = g_file_enumerator_next_file(e, nullptr, nullptr);
while (child_info) {
auto child = g_file_enumerator_get_child(e, child_info);
auto uri = g_file_get_uri(child);
QString urlString = FileUtils::urlEncode(uri);
// BUG: 65889
// auto path = g_file_get_path(child);
// QUrl url = urlString;
// if (path && !url.isLocalFile()) {
// urlString = QString("file://%1").arg(path);
// g_free(path);
// } else {
// urlString = uri;
// }
uris<= QT_VERSION_CHECK(5, 10, 0)
QString suffix = suffixedBaseName.chopped(suffixedBaseName.size() - index);
if (suffix == ".gz" || suffix == ".xz" || suffix == ".bz"
|| suffix == ".bz2" || suffix == ".Z" ||
suffix == ".sit") {
int secondIndex = suffixedBaseName.lastIndexOf('.');
suffixedBaseName.chop(suffixedBaseName.size() - secondIndex);
}
#else
suffixedBaseName.chop(suffixedBaseName.size() - index);
#endif
}
return suffixedBaseName;
}
}
QString FileUtils::getFileDisplayName(const QString &uri)
{
auto fileInfo = FileInfo::fromUri(uri);
if (uri == "file:///data")
return QObject::tr("data");
return fileInfo.get()->displayName();
}
QString FileUtils::getFileIconName(const QString &uri, bool checkValid)
{
if (checkValid) {
//FIXME: replace BLOCKING api in ui thread.
auto fileInfo = FileInfo::fromUri(uri);
return fileInfo.get()->iconName();
if (!fileInfo.get()->isEmptyInfo()) {
return fileInfo.get()->iconName();
}
}
auto file = wrapGFile(g_file_new_for_uri(uri.toUtf8().constData()));
auto info = wrapGFileInfo(g_file_query_info(file.get()->get(),
G_FILE_ATTRIBUTE_STANDARD_ICON,
G_FILE_QUERY_INFO_NONE,
nullptr,
nullptr));
if (!G_IS_FILE_INFO (info.get()->get()))
return nullptr;
GIcon *g_icon = g_file_info_get_icon (info.get()->get());
QString icon_name;
//do not unref the GIcon from info.
if (G_IS_ICON(g_icon)) {
const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON (g_icon));
if (icon_names) {
auto p = icon_names;
if (*p)
icon_name = QString (*p);
if (checkValid) {
while (*p) {
QIcon icon = QIcon::fromTheme(*p);
if (!icon.isNull()) {
icon_name = QString (*p);
break;
} else {
p++;
}
}
}
}else {
//if it's a bootable-media,maybe we can get the icon from the mount directory.
char *bootableIcon = g_icon_to_string(g_icon);
if(bootableIcon){
icon_name = QString(bootableIcon);
g_free(bootableIcon);
}
}
}
return icon_name;
}
GErrorWrapperPtr FileUtils::getEnumerateError(const QString &uri)
{
auto file = wrapGFile(g_file_new_for_uri(uri.toUtf8().constData()));
GError *err = nullptr;
auto enumerator = wrapGFileEnumerator(g_file_enumerate_children(file.get()->get(),
G_FILE_ATTRIBUTE_STANDARD_NAME,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
nullptr,
&err));
if (err) {
return GErrorWrapper::wrapFrom(err);
}
return nullptr;
}
QString FileUtils::getTargetUri(const QString &uri)
{
auto fileInfo = FileInfo::fromUri(uri);
return fileInfo.get()->targetUri();
}
QString FileUtils::getEncodedUri(const QString &uri)
{
GFile *file = g_file_new_for_uri(uri.toUtf8().constData());
QString encodedUri = g_file_get_uri(file);
g_object_unref(file);
return encodedUri;
}
QString FileUtils::getSymbolicTarget(const QString &uri)
{
auto fileInfo = FileInfo::fromUri(uri);
return fileInfo.get()->symlinkTarget();
}
bool FileUtils::isMountPoint(const QString &uri)
{
bool flag = false; // The uri is a mount point
GFile* file = g_file_new_for_uri(uri.toUtf8().constData());
GList* mounts = nullptr;
GVolumeMonitor* vm = g_volume_monitor_get();
if (nullptr != vm) {
mounts = g_volume_monitor_get_mounts(vm);
if (nullptr != mounts) {
for (GList* l = mounts; nullptr != l; l = l->next) {
GMount* m = (GMount*)l->data;
GFile* f = g_mount_get_root(m);
if (g_file_equal(file, f)) {
flag = true;
g_object_unref(f);
break;
}
g_object_unref(f);
}
}
}
if (nullptr != vm) {
g_object_unref(vm);
}
if (nullptr != mounts) {
g_list_free_full(mounts, g_object_unref);
}
if (nullptr != file) {
g_object_unref(file);
}
return flag;
}
bool FileUtils::stringStartWithChinese(const QString &string)
{
if (string.isEmpty())
return false;
auto firstStrUnicode = string.at(0).unicode();
return (firstStrUnicode <=0x9FA5 && firstStrUnicode >= 0x4E00);
}
bool FileUtils::stringLesserThan(const QString &left, const QString &right)
{
bool leftStartWithChinese = stringStartWithChinese(left);
bool rightStartWithChinese = stringStartWithChinese(right);
if (!(!leftStartWithChinese && !rightStartWithChinese)) {
return leftStartWithChinese;
}
return left.toLower() < right.toLower();
}
const QString FileUtils::getParentUri(const QString &uri)
{
auto file = wrapGFile(g_file_new_for_uri(uri.toUtf8().constData()));
auto parent = getFileParent(file);
auto parentUri = getFileUri(parent);
return parentUri == uri? nullptr: parentUri;
}
const QString FileUtils::getOriginalUri(const QString &uri)
{
auto file = wrapGFile(g_file_new_for_uri(uri.toUtf8().constData()));
auto originalUri = getFileUri(file);
return originalUri;
}
bool FileUtils::isStandardPath(const QString &uri)
{
QUrl url = uri;
QDir templateDir(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
QString desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString documentPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QString picturePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
QString videoPath= QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
QString downloadPath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
QString musicPath = QStandardPaths::writableLocation(QStandardPaths::MusicLocation);
QStringList mStandardPaths;
//qDebug() << "isStandardPath :" < 1) {
auto last = list.last();
if (last.startsWith(" "))
last.remove(0, 1);
volumeName = last;
} else {
volumeName = displayName;
}
handleVolumeLabelForFat32(volumeName,unixDeviceName);
return true;
}
bool FileUtils::isReadonly(const QString& uri)
{
GFile *file = g_file_new_for_uri(uri.toUtf8().constData());
GFileInfo *info = g_file_query_info(file, "access::*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, nullptr);
g_object_unref(file);
if (info) {
bool read = g_file_info_get_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ);
bool write = g_file_info_get_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
bool execute = g_file_info_get_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE);
if (read && !write && !execute) {
return true;
}
}
return false;
}
bool FileUtils::isFileDirectory(const QString &uri)
{
bool isFolder = false;
GFile *file = g_file_new_for_uri(uri.toUtf8().constData());
isFolder = g_file_query_file_type(file,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
nullptr) == G_FILE_TYPE_DIRECTORY;
g_object_unref(file);
return isFolder;
}
bool FileUtils::isFileUnmountable(const QString &uri)
{
GFile *file = g_file_new_for_uri(uri.toUtf8().constData());
GFileInfo *info = g_file_query_info(file, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, nullptr);
g_object_unref(file);
if (info) {
bool unmountable = g_file_info_get_attribute_boolean(info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT);
g_object_unref(info);
return unmountable;
}
return false;
}
/* @func: convert a ascii string to unicode string. 将一个ascii字符串转换为unicode字符串
* @gbkName a string that needs to be converted from ascii to Unicode. eg:"\\xb8\\xfc\\xd0\\xc2CODE"
*/
QString transcodeForGbkCode(QByteArray gbkName, QString &volumeName)
{
int i;
QByteArray dest,tmp;
QString name;
int len = gbkName.size();
for(i = 0x0; i < len; ++i){
if(92 == gbkName.at(i)){
if(4 == tmp.size())
dest.append(QByteArray::fromHex(tmp));
else{
if(tmp.size() > 4){
dest.append(QByteArray::fromHex(tmp.left(4)));
dest.append(tmp.mid(4));
}else
dest.append(tmp);
}
tmp.clear();
tmp.append(gbkName.at(i));
continue;
}else if(tmp.size() > 0){
tmp.append(gbkName.at(i));
continue;
}else
dest.append(gbkName.at(i));
}
if(4 == tmp.size())
dest.append(QByteArray::fromHex(tmp));
else{
if(tmp.size() > 4){
dest.append(QByteArray::fromHex(tmp.left(4)));
dest.append(tmp.mid(4));
}else
dest.append(tmp);
}
/*
* gio的api获取的卷名和/dev/disk/by-label先的名字不一致,有可能是卷名
* 中含有特殊字符,导致/dev/disk/label下的卷名含有转义字符,导致二者的名字不一致
* 而不是编码格式的不一致导致的,比如卷名:“数据光盘(2020-08-22)”,在/dev/disk/by-label
* 写的名字:"数据光盘\x282020-08-22\x29",经过上述处理之后可以去除转义字符,在判断一次
* 是否相等。比较完美的解决方案是找到能够判断字符串的编码格式,目前还没有找到实现方式,需要进一步完善
*/
name = QString(dest);
if (name == volumeName){
return name;
}
name = QTextCodec::codecForName("GBK")->toUnicode(dest);
//name = QTextCodec::codecForLocale()->toUnicode(dest);
return name;
}
/* @func: determines whether the @volumeName needs to be transcoded. 判断字符串是否需要转码.
* @volumeName a string that needs to be converted from ascii to Unicode. eg:"\\xb8\\xfc\\xd0\\xc2CODE"
* @unixDeviceName a device name. eg: /dev/sdb
*/
void FileUtils::handleVolumeLabelForFat32(QString &volumeName,const QString &unixDeviceName){
if (unixDeviceName.isEmpty())
return;
GVolumeMonitor *vm = g_volume_monitor_get();
GList *volumes = g_volume_monitor_get_volumes(vm);
GList *l = volumes;
while (l) {
GVolume *volume = static_cast(l->data);
g_autofree char *volume_unix_dev = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
if (unixDeviceName == volume_unix_dev) {
g_autofree char *volume_name = g_volume_get_name(volume);
volumeName = volume_name;
break;
}
l = l->next;
}
g_list_free_full(volumes, g_object_unref);
g_object_unref(vm);
return;
QFileInfoList diskList;
QFileInfo diskLabel;
QDir diskDir;
QString partitionName,linkTarget;
QString tmpName,finalName;
int i;
QRegExp rx("[^\u4e00-\u9fa5]"); //non-chinese characters
diskDir.setPath("/dev/disk/by-label");
if(!diskDir.exists()) //this means: volume has no name.
return; // or there no mobile devices.
diskList = diskDir.entryInfoList(); //all file from dir.
/* eg: unixDeviceName == "/dev/sdb4"
* partitionName == "sdb4"
*/
partitionName = unixDeviceName.mid(unixDeviceName.lastIndexOf('/')+1);
for(i = 0; i < diskList.size(); ++i){
diskLabel = diskList.at(i);
linkTarget = diskLabel.symLinkTarget();
linkTarget = linkTarget.mid(linkTarget.lastIndexOf('/')+1);
if(linkTarget == partitionName)
break;
linkTarget.clear();
}
if(!linkTarget.isEmpty())
tmpName = diskLabel.fileName();//可能带有乱码的名字
if(!tmpName.isEmpty()){
if(tmpName == volumeName || !tmpName.contains(rx)){ //ntfs、exfat格式或者非纯中文名的fat32设备,这个设备的名字不需要转码
volumeName = tmpName;
return;
} else {
finalName = transcodeForGbkCode(tmpName.toLocal8Bit(), volumeName);
if(!finalName.isEmpty())
volumeName = finalName;
}
}
}
/* @Func: return abstract device path
* @uri : such as "computer:///xxx.drive"
* @return: nullptr or such as "/dev/sdb1"
*/
QString FileUtils::getUnixDevice(const QString &uri)
{
GFile* file;
GFileInfo* fileInfo;
GCancellable* cancel;
QString devicePath,targetUri;
const char *tmpPath;
char *mountPoint;
if(uri.isEmpty())
return nullptr;
cancel = g_cancellable_new();
file = g_file_new_for_uri(uri.toUtf8().data());
if(!file ||!cancel)
return nullptr;
//query device path by "mountable::unix-device-file"
fileInfo = g_file_query_info(file,"*",G_FILE_QUERY_INFO_NONE,cancel,NULL);
tmpPath = g_file_info_get_attribute_as_string(fileInfo,G_FILE_ATTRIBUTE_MOUNTABLE_UNIX_DEVICE_FILE);
devicePath = tmpPath;
if(!devicePath.isEmpty()){
g_object_unref(fileInfo);
g_cancellable_cancel(cancel);
g_object_unref(cancel);
g_object_unref(file);
return devicePath;
}
//query device path by "standard::target-uri"
targetUri = getTargetUri(uri);
if(targetUri.isEmpty())
return nullptr;
mountPoint = g_filename_from_uri(targetUri.toUtf8().data(),NULL,NULL);
if(mountPoint)
tmpPath = Peony::VolumeManager::getUnixDeviceFileFromMountPoint(mountPoint);
devicePath = tmpPath;
g_free(mountPoint);
g_object_unref(fileInfo);
g_cancellable_cancel(cancel);
g_object_unref(cancel);
g_object_unref(file);
return devicePath;
}
double FileUtils::getDeviceSize(const gchar * device_name)
{
struct stat statbuf;
const gchar *crypto_backing_device;
UDisksObject *object, *crypto_backing_object;
UDisksBlock *block;
UDisksClient *client =udisks_client_new_sync (NULL,NULL);
object = NULL;
if (stat (device_name, &statbuf) != 0)
{
return -1;
}
block = udisks_client_get_block_for_dev (client, statbuf.st_rdev);
if (block == NULL)
{
return -1;
}
object = UDISKS_OBJECT (g_dbus_interface_dup_object (G_DBUS_INTERFACE (block)));
g_object_unref (block);
crypto_backing_device = udisks_block_get_crypto_backing_device ((udisks_object_peek_block (object)));
crypto_backing_object = udisks_client_get_object (client, crypto_backing_device);
if (crypto_backing_object != NULL)
{
g_object_unref (object);
object = crypto_backing_object;
}
block = udisks_object_get_block (object);
guint64 size = udisks_block_get_size(block);
double volume_size =(double)size/1024/1024/1024;
g_clear_object(&client);
g_object_unref(object);
g_object_unref(block);
return volume_size;
}
quint64 FileUtils::getFileSystemSize(QString uri)
{
QString unixDevice,dbusPath;
quint64 total = 0;
unixDevice = FileUtils::getUnixDevice(uri);
if (unixDevice.isEmpty()) {
return total;
}
dbusPath = "/org/freedesktop/UDisks2/block_devices/" + unixDevice.split("/").last();
if (! QDBusConnection::systemBus().isConnected())
return total;
QDBusInterface blockInterface("org.freedesktop.UDisks2",
dbusPath,
"org.freedesktop.UDisks2.Filesystem",
QDBusConnection::systemBus());
if(blockInterface.isValid())
total = blockInterface.property("Size").toULongLong();
return total;
}
QString FileUtils::getFileSystemType(QString uri)
{
QString unixDevice,dbusPath;
QString fsType = "";
unixDevice = getUnixDevice(uri);
if (unixDevice.isEmpty()) {
return fsType;
}
dbusPath = "/org/freedesktop/UDisks2/block_devices/" + unixDevice.split("/").last();
if (! QDBusConnection::systemBus().isConnected())
return fsType;
QDBusInterface blockInterface("org.freedesktop.UDisks2",
dbusPath,
"org.freedesktop.UDisks2.Block",
QDBusConnection::systemBus());
if(blockInterface.isValid())
fsType = blockInterface.property("IdType").toString();
//if need diff FAT16 and FAT32, should use IdVersion
// if(fsType == "" && blockInterface.isValid())
// fsType = blockInterface.property("IdVersion").toString();
return fsType;
}
peony/libpeony-qt/complementary-style.cpp 0000644 0001750 0001750 00000022756 14205101223 017616 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#include "complementary-style.h"
#include "tool-bar.h"
#include "location-bar.h"
#include
#include
#include
#include
#include
using namespace Peony;
static ComplementaryStyle *global_instance = nullptr;
ComplementaryStyle::ComplementaryStyle(QStyle *parent) : QProxyStyle(parent)
{
m_styled_menu = new QMenu;
m_styled_button = new QPushButton;
}
ComplementaryStyle::~ComplementaryStyle()
{
m_styled_menu->deleteLater();
m_styled_button->deleteLater();
}
ComplementaryStyle *ComplementaryStyle::getStyle()
{
if (!global_instance)
global_instance = new ComplementaryStyle;
return global_instance;
}
void ComplementaryStyle::polish(QWidget *widget)
{
QProxyStyle::polish(widget);
if (auto button = qobject_cast(widget)) {
//fix push button use as icon caused color issues
if (! button->property("isIcon").toBool())
{
button->setProperty("useIconHighlightEffect", true);
button->setProperty("iconHighlightEffectMode", 1);
button->setProperty("fillIconSymbolicColor", true);
}
return;
}
if (auto menu = qobject_cast(widget)) {
menu->setProperty("useIconHighlightEffect", true);
menu->setProperty("iconHighlightEffectMode", 1);
menu->setProperty("fillIconSymbolicColor", true);
return;
}
}
int ComplementaryStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
{
switch (hint) {
case QStyle::SH_Menu_Scrollable: {
return 1;
}
default:
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
}
void ComplementaryStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
if (widget && widget->inherits("QMenu")) {
return QProxyStyle::drawPrimitive(element, option, painter, widget);
}
switch (element) {
case QStyle::PE_FrameFocusRect:
case QStyle::PE_IndicatorToolBarSeparator: {
//do not draw toolbar separator and focus rect
return;
}
case PE_IndicatorArrowDown: {
ToolBar *toolBar = qobject_cast(widget->parentWidget());
LocationBar *locationBar = qobject_cast(widget->parentWidget());
if (toolBar) {
auto rect = option->rect;
rect.setY((rect.top()+rect.bottom())/2 - 8);
rect.setWidth(16);
rect.setHeight(16);
if (option->state & State_Sunken) {
rect.adjust(1, 1, 1, 1);
}
QIcon arrowDown = QIcon::fromTheme("ukui-down-symbolic", QIcon(":/icons/ukui-down-symbolic"));
arrowDown.paint(painter, rect.adjusted(-3, 0, -3, 0));
return;
} else if (locationBar) {
auto rect = option->rect;
rect.setY((rect.top()+rect.bottom())/2 - 8);
rect.setX((rect.left()+rect.right())/2 - 8);
rect.setWidth(16);
rect.setHeight(16);
if (option->state & State_Sunken) {
QIcon arrowDown = QIcon::fromTheme("ukui-down-symbolic", QIcon(":/icons/ukui-down-symbolic"));
arrowDown.paint(painter, rect.adjusted(1, 1, 1, 1));
} else {
QIcon arrowDown = QIcon::fromTheme("ukui-end-symbolic", QIcon(":/icons/ukui-end-symbolic"));
arrowDown.paint(painter, rect.adjusted(1, 1, 1, 1));
}
return;
}
break;
}
default:
break;
}
return QProxyStyle::drawPrimitive(element, option, painter, widget);
}
void ComplementaryStyle::drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const
{
switch (cc) {
case QStyle::CC_ToolButton: {
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast(opt)) {
//Peony::ToolBar has different style with other toolbar.
ToolBar *parentWidget = qobject_cast(widget->parentWidget());
QRect button, menuarea;
button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~State_Sunken;
if (bflags & State_AutoRaise) {
if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) {
bflags &= ~State_Raised;
}
}
State mflags = bflags;
if (toolbutton->state & State_Sunken) {
if (toolbutton->activeSubControls & SC_ToolButton)
bflags |= State_Sunken;
mflags |= State_Sunken;
}
QStyleOption tool = *toolbutton;
if (toolbutton->subControls & SC_ToolButton) {
if (bflags & (State_Sunken | State_On | State_Raised)) {
tool.rect = button;
tool.state = bflags;
if (parentWidget) {
if (toolbutton->features.testFlag(QStyleOptionToolButton::Menu)) {
tool.rect = QRect(button.topLeft(), QSize(button.width() + menuarea.width(), button.height()));
}
proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
} else {
proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
}
} else {
if (parentWidget) {
tool.rect = button;
tool.state = bflags;
if (toolbutton->features.testFlag(QStyleOptionToolButton::HasMenu)) {
tool.rect = QRect(button.topLeft(), QSize(button.width() + menuarea.width(), button.height()));
}
qDrawShadePanel(p,
tool.rect.adjusted(1, 1, -1, -1),
m_styled_menu->palette().button().color(),
false,
0,
&m_styled_menu->palette().brush(QPalette::Normal, QPalette::Button));
}
}
}
if (toolbutton->state & State_HasFocus) {
QStyleOptionFocusRect fr;
fr.QStyleOption::operator=(*toolbutton);
fr.rect.adjust(3, 3, -3, -3);
if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
toolbutton, widget), 0);
proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
}
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
label.rect = button.adjusted(fw, fw, -fw, -fw);
label.palette.setColor(QPalette::Window, m_styled_menu->palette().window().color());
proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;//.adjusted(1, 1, -1, -1);
tool.state = mflags;
tool.palette.setColor(QPalette::Button, m_styled_button->palette().highlight().color());
//FIXME: paint indicator button background correctly.
if (mflags & (State_Sunken | State_On | State_Raised)) {
if (parentWidget) {
//do nothing
} else {
proxy()->drawPrimitive(PE_PanelButtonCommand, &tool, p, widget);
}
}
drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6, mbi - 6);
newBtn.rect = visualRect(toolbutton->direction, button, newBtn.rect);
drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
}
default:
return QProxyStyle::drawComplexControl(cc, opt, p, widget);
}
}
peony/libpeony-qt/file-watcher.cpp 0000644 0001750 0001750 00000024105 14205115226 016151 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#include "file-watcher.h"
#include "gerror-wrapper.h"
#include "file-label-model.h"
#include
#include "file-utils.h"
#include "file-operation-manager.h"
#include "file-info.h"
#include "volume-manager.h"
#include "volumeManager.h"
#include
using namespace Peony;
FileWatcher::FileWatcher(QString uri, QObject *parent, bool isWatchMovesFlag)
: QObject(parent), m_isWatchMovesFlag(isWatchMovesFlag)
{
if (uri.startsWith("thumbnail://"))
return;
m_uri = uri;
m_target_uri = uri;
m_file = g_file_new_for_uri(uri.toUtf8().constData());
m_cancellable = g_cancellable_new();
//monitor target file if existed.
prepare();
creatorMonitor();
FileOperationManager::getInstance()->registerFileWatcher(this);
}
FileWatcher::~FileWatcher()
{
FileOperationManager::getInstance()->unregisterFileWatcher(this);
disconnect();
//qDebug()<<"~FileWatcher"<
* If file handle has target uri, we need monitor file that target uri point to.
* FileWatcher::prepare() just query if there is a target uri of current file handle,
* and it asumed that everything is no problem. If you want to use
* a file watcher instance, I recommend you call a file enumerator class instance
* with FileEnumerator::prepare() and wait it finished first.
*
* \see FileEnumerator::prepare().
*/
void FileWatcher::prepare()
{
auto fileInfo = FileInfo::fromGFile(m_file);
auto targetUri = fileInfo.get()->targetUri();
if (!targetUri.isNull()) {
g_object_unref(m_file);
m_file = g_file_new_for_uri(targetUri.toUtf8().constData());
m_target_uri = targetUri;
}
return;
}
void FileWatcher::cancel()
{
if (!m_cancellable)
return;
g_cancellable_cancel(m_cancellable);
g_object_unref(m_cancellable);
m_cancellable = g_cancellable_new();
}
void FileWatcher::startMonitor()
{
//make sure only connect once in a watcher.
stopMonitor();
m_file_handle = g_signal_connect(m_monitor, "changed", G_CALLBACK(file_changed_callback), this);
m_dir_handle = g_signal_connect(m_dir_monitor, "changed", G_CALLBACK(dir_changed_callback), this);
connect(FileLabelModel::getGlobalModel(), &FileLabelModel::fileLabelChanged, this, [=](const QString &uri) {
auto parentUri = FileUtils::getParentUri(uri);
QUrl parentUrl = parentUri;
if (parentUri == m_uri || parentUri == m_target_uri || parentUrl.toDisplayString() == m_uri || parentUrl.toDisplayString() == m_target_uri) {
Q_EMIT fileChanged(uri);
qDebug()<<"file label changed"< 0) {
g_signal_handler_disconnect(m_monitor, m_file_handle);
m_file_handle = 0;
}
if (m_dir_handle > 0) {
g_signal_handler_disconnect(m_dir_monitor, m_dir_handle);
m_dir_handle = 0;
}
}
void FileWatcher::forceChangeMonitorDirectory(const QString &uri)
{
changeMonitorUri(uri);
}
void FileWatcher::creatorMonitor()
{
GError *err1 = nullptr;
m_monitor = g_file_monitor_file(m_file,
G_FILE_MONITOR_WATCH_MOVES,
m_cancellable,
&err1);
if (err1) {
qDebug()<code<message;
g_error_free(err1);
m_support_monitor = false;
}
GError *err2 = nullptr;
GFileMonitorFlags flag = m_isWatchMovesFlag?G_FILE_MONITOR_WATCH_MOVES:G_FILE_MONITOR_NONE;
m_dir_monitor = g_file_monitor_directory(m_file,
flag,
m_cancellable,
&err2);
if (err2) {
qDebug()<code<message;
g_error_free(err2);
m_support_monitor = false;
}
}
void FileWatcher::changeMonitorUri(QString uri)
{
QString oldUri = m_uri;
stopMonitor();
cancel();
m_uri = uri;
m_target_uri = uri;
if (m_file)
g_object_unref(m_file);
if (m_monitor)
g_object_unref(m_monitor);
if (m_dir_monitor)
g_object_unref(m_dir_monitor);
m_file = g_file_new_for_uri(uri.toUtf8().constData());
prepare();
creatorMonitor();
startMonitor();
Q_EMIT locationChanged(oldUri, m_uri);
}
void FileWatcher::file_changed_callback(GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
FileWatcher *p_this)
{
//qDebug()<<"file_changed_callback"<changeMonitorUri(uri);
break;
}
case G_FILE_MONITOR_EVENT_DELETED: {
auto uri = g_file_get_uri(file);
bool shouldSendSignal = p_this->m_target_uri == uri;
if (uri)
g_free(uri);
if (!shouldSendSignal)
return;
p_this->stopMonitor();
p_this->cancel();
//qDebug()<m_target_uri;
Q_EMIT p_this->directoryDeleted(p_this->m_target_uri);
break;
}
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: {
char *uri = g_file_get_uri(file);
qDebug()<fileChanged(uri);
g_free(uri);
break;
}
default:
break;
}
}
void FileWatcher::dir_changed_callback(GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
FileWatcher *p_this)
{
//qDebug()<<"dir_changed_callback";
Q_UNUSED(monitor);
Q_UNUSED(other_file);
switch (event_type) {
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: {
if (p_this->m_montor_children_change) {
char *uri = g_file_get_uri(file);
QString changedFileUri = uri;
//qDebug()<fileChanged(changedFileUri);
}
break;
}
case G_FILE_MONITOR_EVENT_CREATED:
case G_FILE_MONITOR_EVENT_MOVED_IN: {
char *uri = g_file_get_uri(file);
QString createdFileUri = uri;
//qDebug()<<"***create uri***"<fileCreated(createdFileUri);
break;
}
case G_FILE_MONITOR_EVENT_DELETED:
case G_FILE_MONITOR_EVENT_MOVED_OUT: {
char *uri = g_file_get_uri(file);
QString deletedFileUri = uri;
//qDebug()<<"***delete uri***"<fileDeleted(deletedFileUri);
break;
}
case G_FILE_MONITOR_EVENT_RENAMED: {
char *old_uri = g_file_get_uri (file);
char *new_uri = g_file_get_uri(other_file);
Q_EMIT p_this->fileRenamed(old_uri,new_uri);
qDebug()<<"***oldUri***newUri***"<directoryUnmounted(deletedFileUri);
break;
}
default:
break;
}
}
peony/libpeony-qt/file-copy.cpp 0000644 0001750 0001750 00000033145 14205115226 015472 0 ustar feng feng /*
* 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 .
*
* Authors: Ding Jing
*
*/
#include "file-copy.h"
#include "file-utils.h"
#include
#include
#include
#include
#include
#include "file-info.h"
#include "file-info-job.h"
#define BUF_SIZE 1024000
#define SYNC_INTERVAL 10
using namespace Peony;
static gchar* get_fs_type (char* path);
FileCopy::FileCopy (QString srcUri, QString destUri, GFileCopyFlags flags, GCancellable* cancel, GFileProgressCallback cb, gpointer pcd, GError** error, QObject* obj) : QObject (obj)
{
mSrcUri = FileUtils::urlEncode(srcUri);
mDestUri = FileUtils::urlEncode(destUri);
QString destUrit = nullptr;
mCopyFlags = flags;
mCancel = cancel;
mProgress = cb;
mProgressData = pcd;
mError = error;
}
FileCopy::~FileCopy()
{
}
void FileCopy::pause ()
{
mStatus = PAUSE;
mPause.tryLock();
}
void FileCopy::resume ()
{
mStatus = RESUME;
mPause.unlock();
}
void FileCopy::cancel()
{
if (mCancel) {
g_cancellable_cancel (mCancel);
}
mPause.unlock();
}
void FileCopy::detailError (GError** error)
{
if (nullptr == error || nullptr == *error || nullptr == mError) {
return;
}
g_set_error(mError, (*error)->domain, (*error)->code, "%s", (*error)->message);
g_error_free(*error);
*error = nullptr;
}
void FileCopy::sync(const GFile* destFile)
{
g_autofree char* uri = g_file_get_uri(const_cast(destFile));
g_autofree char* path = g_file_get_path(const_cast(destFile));
// it's not possible
g_return_if_fail(uri && path);
// uri is start with "file://"
QString gvfsPath = QString("/run/user/%1/gvfs/").arg(getuid());
if (0 != g_ascii_strncasecmp(uri, "file:///", 8) || g_strstr_len(uri, strlen(uri), gvfsPath.toUtf8().constData())) {
return;
}
// execute sync
QProcess p;
p.setProgram("sync");
p.setArguments(QStringList() << "-f" << path);
p.start();
p.waitForFinished(-1);
}
void FileCopy::updateProgress () const
{
if (nullptr == mProgress) {
return;
}
mProgress(mOffset, mTotalSize, mProgressData);
}
void FileCopy::run ()
{
int syncTim = 0;
GError* error = nullptr;
gssize readSize = 0;
gssize writeSize = 0;
GFileInputStream* readIO = nullptr;
GFileOutputStream* writeIO = nullptr;
GFile* srcFile = nullptr;
GFile* destFile = nullptr;
GFileInfo* srcFileInfo = nullptr;
GFileInfo* destFileInfo = nullptr;
GFileType srcFileType = G_FILE_TYPE_UNKNOWN;
GFileType destFileType = G_FILE_TYPE_UNKNOWN;
g_autofree gchar* buf = (char*)g_malloc0(sizeof (char) * BUF_SIZE);
g_autoptr (GFile) destDir = NULL;
srcFile = g_file_new_for_uri(FileUtils::urlEncode(mSrcUri).toUtf8());
destFile = g_file_new_for_uri(FileUtils::urlEncode(mDestUri).toUtf8());
// it's impossible
if (nullptr == srcFile || nullptr == destFile) {
error = g_error_new (1, G_IO_ERROR_INVALID_ARGUMENT,"%s", tr("Error in source or destination file path!").toUtf8().constData());
detailError(&error);
goto out;
}
// impossible
srcFileType = g_file_query_file_type(srcFile, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr);
if (G_FILE_TYPE_DIRECTORY == srcFileType) {
error = g_error_new (1, G_IO_ERROR_INVALID_ARGUMENT,"%s", tr("Error in source or destination file path!").toUtf8().constData());
detailError(&error);
goto out;
}
destFileType = g_file_query_file_type(destFile, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr);
if (G_FILE_TYPE_DIRECTORY == destFileType) {
mDestUri = mDestUri + "/" + mSrcUri.split("/").last();
g_object_unref(destFile);
destFile = g_file_new_for_uri(FileUtils::urlEncode(mDestUri).toUtf8());
if (nullptr == destFile) {
error = g_error_new (1, G_IO_ERROR_INVALID_ARGUMENT,"%s", tr("Error in source or destination file path!").toUtf8().constData());
detailError(&error);
goto out;
}
}
// check file status
if (FileUtils::isFileExsit(mDestUri)) {
if (mCopyFlags & G_FILE_COPY_OVERWRITE) {
g_file_delete(destFile, nullptr, &error);
if (nullptr != error) {
detailError(&error);
goto out;
}
} else if (mCopyFlags & G_FILE_COPY_BACKUP) {
do {
QStringList newUrl = mDestUri.split("/");
newUrl.pop_back();
newUrl.append(FileUtils::handleDuplicateName(FileUtils::urlDecode(mDestUri)));
mDestUri = newUrl.join("/");
} while (FileUtils::isFileExsit(mDestUri));
if (nullptr != destFile) {
g_object_unref(destFile);
}
destFile = g_file_new_for_uri(FileUtils::urlEncode(mDestUri).toUtf8());
} else {
error = g_error_new (1, G_IO_ERROR_EXISTS, "%s", QString(tr("The dest file \"%1\" has existed!")).arg(mDestUri).toUtf8().constData());
detailError(&error);
goto out;
}
}
srcFileInfo = g_file_query_info(srcFile, "standard::*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, mCancel ? mCancel : nullptr, &error);
if (nullptr != error) {
mTotalSize = 0;
qDebug() << "srcFile: " << mSrcUri << " querry info error: " << error->message;
detailError(&error);
} else {
mTotalSize = g_file_info_get_size(srcFileInfo);
}
qDebug() << "copy - src: " << mSrcUri << " to: " << mDestUri;
// check dest filesystem
destDir = g_file_get_parent (destFile);
if (destDir) {
g_autoptr (GMount) destMount = g_file_find_enclosing_mount (destDir, NULL, NULL);
if (destMount) {
g_autoptr (GFile) destMountFile = g_mount_get_default_location (destMount);
if (destMountFile) {
g_autofree gchar* mountPath = g_file_get_path (destMountFile);
if (mountPath) {
g_autofree gchar* fstype = get_fs_type (mountPath);
if (!g_strcmp0 (fstype, "vfat") || !g_strcmp0 (fstype, "fat32")) {
if (mTotalSize >= 4294967296) {
error = g_error_new (1, G_IO_ERROR_NOT_SUPPORTED, "%s", QString(tr("Vfat/FAT32 file systems do not support a single file that occupies more than 4 GB space!")).toUtf8 ().constData ());
detailError(&error);
goto out;
}
}
}
}
}
}
// read io stream
readIO = g_file_read(srcFile, mCancel ? mCancel : nullptr, &error);
if (nullptr != error) {
detailError(&error);
goto out;
}
// write io stream
writeIO = g_file_create(destFile, G_FILE_CREATE_REPLACE_DESTINATION, mCancel ? mCancel : nullptr, &error);
if (nullptr != error) {
// it's impossible for 'buf' is null
if (!buf || G_IO_ERROR_NOT_SUPPORTED == error->code) {
qWarning() << "g_file_copy " << error->code << " -- " << error->message;
g_error_free(error);
error = nullptr;
g_file_copy(srcFile, destFile, mCopyFlags, mCancel, mProgress, mProgressData, &error);
if (error) {
qWarning() << "g_file_copy error:" << error->code << " -- " << error->message;
detailError(&error);
mStatus = ERROR;
} else {
mStatus = FINISHED;
}
} else {
detailError(&error);
qDebug() << "create dest file error!" << mDestUri << " == " << g_file_get_uri(destFile);
}
goto out;
}
if (!readIO || !writeIO) {
error = g_error_new (1, G_IO_ERROR_FAILED,"%s", tr("Error opening source or destination file!").toUtf8().constData());
detailError(&error);
goto out;
}
while (true) {
if (RUNNING == mStatus) {
if (nullptr != mCancel && g_cancellable_is_cancelled(mCancel)) {
mStatus = CANCEL;
continue;
}
memset(buf, 0, BUF_SIZE);
if (++syncTim > SYNC_INTERVAL) {
syncTim = 0;
sync(destFile);
}
mPause.lock();
// read data
readSize = g_input_stream_read(G_INPUT_STREAM(readIO), buf, BUF_SIZE - 1, mCancel ? mCancel : nullptr, &error);
if (0 == readSize && nullptr == error) {
mStatus = FINISHED;
mPause.unlock();
continue;
} else if (nullptr != error) {
detailError(&error);
mStatus = ERROR;
mPause.unlock();
continue;
}
mPause.unlock();
// write data
writeSize = g_output_stream_write(G_OUTPUT_STREAM(writeIO), buf, readSize, mCancel ? mCancel : nullptr, &error);
if (nullptr != error) {
qDebug() << "write destfile: " << mDestUri << " error: " << error->message;
detailError(&error);
mStatus = ERROR;
continue;
}
if (readSize != writeSize) {
// it's impossible
qDebug() << "read file: " << mSrcUri << " --- write file: " << mDestUri << " size not inconsistent";
error = g_error_new (1, G_IO_ERROR_FAILED,"%s", tr("Please confirm that the device controls are insufficient!").toUtf8().constData());
detailError(&error);
mStatus = ERROR;
continue;
}
if (mOffset <= mTotalSize) {
mOffset += writeSize;
}
updateProgress ();
} else if (CANCEL == mStatus) {
error = g_error_new(1, G_IO_ERROR_CANCELLED, "%s", tr("operation cancel").toUtf8().constData());
detailError(&error);
g_file_delete (destFile, nullptr, nullptr);
break;
} else if (ERROR == mStatus) {
g_file_delete (destFile, nullptr, nullptr);
break;
} else if (FINISHED == mStatus) {
qDebug() << "copy file finish!";
break;
} else if (PAUSE == mStatus) {
if (mPause.tryLock(3000)) {
if (RESUME == mStatus) {
mPause.unlock();
}
mStatus = RUNNING;
}
} else {
mStatus = RUNNING;
}
}
out:
// if copy sucessed, flush all data
if (FINISHED == mStatus && g_file_query_exists(destFile, nullptr)) {
// copy file attribute
// It is possible that some file systems do not support file attributes
g_file_copy_attributes(srcFile, destFile, G_FILE_COPY_ALL_METADATA, nullptr, &error);
if (nullptr != error) {
qWarning() << "copy attribute error:" << error->code << " --- " << error->message;
g_error_free(error);
error = nullptr;
}
sync(destFile);
} else {
// some special detail for mtp
if (mSrcUri.startsWith("mtp:///") || mDestUri.startsWith("mtp:///")) {
if (mError) {
g_error_free(*mError);
*mError = nullptr;
g_set_error(mError, 1, G_IO_ERROR_NOT_SUPPORTED, "%s", tr("File opening failure").toUtf8().constData());
}
}
}
if (nullptr != readIO) {
g_input_stream_close (G_INPUT_STREAM(readIO), nullptr, nullptr);
g_object_unref(readIO);
}
if (nullptr != writeIO) {
g_output_stream_close (G_OUTPUT_STREAM(writeIO), nullptr, nullptr);
g_object_unref(writeIO);
}
if (nullptr != error) {
g_error_free(error);
}
if (nullptr != srcFile) {
g_object_unref(srcFile);
}
if (nullptr != destFile) {
g_object_unref(destFile);
}
if (nullptr != srcFileInfo) {
g_object_unref(srcFileInfo);
}
if (nullptr != destFileInfo) {
g_object_unref(destFileInfo);
}
}
/**
* @note
* 同步了 glib 针对vfat/fat32 单文件大于4g,提前提醒用户的补丁,
* 由于 gio 获取文件系统类型不准确(据康哥反馈会把某些设备vfat/fat32、ntfs文件系统都识别为msdos),
* 所以使用linux接口获取。
*/
static gchar* get_fs_type (char* path)
{
char* fstype = NULL;
struct mntent* m = NULL;
FILE* f = NULL;
f = setmntent ("/etc/mtab", "r");
if (!f) {
qDebug() << "get filesystem type error";
}
while ((m = getmntent(f))) {
if (!path) continue;
if (!m->mnt_dir) continue;
if (!strcmp (path, m->mnt_dir)) {
fstype = g_strdup_printf("%s", m->mnt_type);
break;
}
}
endmntent (f);
return fstype;
}
peony/libpeony-qt/effects/ 0000755 0001750 0001750 00000000000 14205101223 014500 5 ustar feng feng peony/libpeony-qt/effects/border-shadow-effect.h 0000644 0001750 0001750 00000005317 14205101223 020651 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, Tianjin KYLIN Information Technology 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 .
*
* Authors: Yue Lan
*
*/
#ifndef BORDERSHADOWEFFECT_H
#define BORDERSHADOWEFFECT_H
#include
#include
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include
#endif
/*!
* \brief The BorderShadowEffect class
* \details
* This class is used to decorate a frameless window.
* It provides a border shadow which can be adjusted.
*
* The effect is similar to QGraphicsDropShadowEffects,
* but it doesn't blur allow the window. It just render
* a border for toplevel window, whatever if the window
* is transparent and whatever element on the window.
*
* \note
* To let the effect works,
* You have to use it on toplevel window, and let the
* window has an invisible contents margins.
*
* If your window has a border radius, use setBorderRadius()
* for matching your window border rendering.
*/
class PEONYCORESHARED_EXPORT BorderShadowEffect : public QGraphicsEffect
{
Q_OBJECT
public:
explicit BorderShadowEffect(QObject *parent = nullptr);
void setBorderRadius(int radius);
void setBorderRadius(int xradius, int yradius);
void setBlurRadius(int radius);
void setPadding(int padding);
void setShadowColor(const QColor &color);
void setWindowBackground(const QColor &color);
void setTransParentPath(const QPainterPath &path);
void setTransParentAreaBg(const QColor &transparentBg);
void drawWindowShadowManually(QPainter *painter, const QRect &windowRect, bool fakeShadow = false);
protected:
void draw(QPainter *painter) override;
private:
int m_x_border_radius = 0;
int m_y_border_radius = 0;
int m_blur_radius = 0;
int m_padding = 0;
QColor m_shadow_color = QColor(63, 63, 63, 180); // dark gray
QColor m_window_bg = Qt::transparent;
QImage m_cache_shadow;
bool m_force_update_cache = false;
QPainterPath m_transparent_path;
QColor m_transparent_bg = QColor(255, 255, 255, 127);
};
#endif // BORDERSHADOWEFFECT_H
peony/libpeony-qt/effects/effects.pri 0000644 0001750 0001750 00000000165 14205101223 016635 0 ustar feng feng INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/border-shadow-effect.h
SOURCES += \
$$PWD/border-shadow-effect.cpp
peony/libpeony-qt/effects/border-shadow-effect.cpp 0000644 0001750 0001750 00000013461 14205101223 021203 0 ustar feng feng /*
* Peony-Qt's Library
*
* Copyright (C) 2020, Tianjin KYLIN Information Technology 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 .
*
* Authors: Yue Lan
*
*/
#include "border-shadow-effect.h"
#include
#include
#include
//qt's global function
extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
BorderShadowEffect::BorderShadowEffect(QObject *parent) : QGraphicsEffect(parent)
{
}
void BorderShadowEffect::setBorderRadius(int radius)
{
m_x_border_radius = 0;
m_y_border_radius = 0;
//m_x_border_radius = radius;
//m_y_border_radius = radius;
}
void BorderShadowEffect::setBorderRadius(int xradius, int yradius)
{
m_x_border_radius = 0;
m_y_border_radius = 0;
//m_x_border_radius = xradius;
//m_y_border_radius = yradius;
}
void BorderShadowEffect::setBlurRadius(int radius)
{
m_blur_radius = 0;
//m_blur_radius = radius;
}
void BorderShadowEffect::setPadding(int padding)
{
m_padding = 0;
//m_padding = padding;
}
void BorderShadowEffect::setShadowColor(const QColor &color)
{
if (color != m_shadow_color) {
m_force_update_cache = true;
}
m_shadow_color = color;
}
void BorderShadowEffect::setWindowBackground(const QColor &color)
{
m_window_bg = color;
}
void BorderShadowEffect::setTransParentPath(const QPainterPath &path)
{
m_transparent_path = path;
}
void BorderShadowEffect::setTransParentAreaBg(const QColor &transparentBg)
{
m_transparent_bg = transparentBg;
}
void BorderShadowEffect::drawWindowShadowManually(QPainter *painter, const QRect &windowRect, bool fakeShadow)
{
//draw window bg;
QRect sourceRect = windowRect;
auto contentRect = sourceRect.adjusted(m_padding, m_padding, -m_padding, -m_padding);
//qDebug()<fillPath(bgPath, m_window_bg);
painter->fillPath(m_transparent_path, m_transparent_bg);
return;
if (fakeShadow) {
painter->save();
auto color = m_shadow_color;
color.setAlphaF(0.1);
painter->setPen(color);
painter->setBrush(Qt::transparent);
painter->drawPath(contentPath);
painter->restore();
return;
}
//qDebug()<boundingRect()< 0) {
if (m_cache_shadow.size() == windowRect.size() && !m_force_update_cache) {
//use cache pixmap draw shadow.
painter->save();
painter->setClipPath(sourcePath - contentPath);
painter->drawImage(QPoint(), m_cache_shadow);
painter->restore();
} else {
//draw shadow and cache shadow pixmap
QPixmap pixmap(sourceRect.size().width(), sourceRect.height());
pixmap.fill(Qt::transparent);
QPainter p(&pixmap);
p.fillPath(contentPath, m_shadow_color);
p.end();
QImage img = pixmap.toImage();
qt_blurImage(img, m_blur_radius, false, false);
pixmap.convertFromImage(img);
m_cache_shadow = img;
painter->save();
painter->setClipPath(sourcePath - contentPath);
painter->drawImage(QPoint(), img);
painter->restore();
m_force_update_cache = false;
}
}
}
void BorderShadowEffect::draw(QPainter *painter)
{
//draw window bg;
auto sourceRect = boundingRect();
auto contentRect = boundingRect().adjusted(m_padding, m_padding, -m_padding, -m_padding);
//qDebug()<fillPath(contentPath, m_window_bg);
QPoint offset;
if (sourceIsPixmap()) {
// No point in drawing in device coordinates (pixmap will be scaled anyways).
const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, QGraphicsEffect::PadToTransparentBorder);
painter->drawPixmap(offset, pixmap);
} else {
// Draw pixmap in device coordinates to avoid pixmap scaling;
const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, QGraphicsEffect::PadToTransparentBorder);
painter->setWorldTransform(QTransform());
painter->drawPixmap(offset, pixmap);
}
//qDebug()<boundingRect()< 0) {
//draw shadow
QPixmap pixmap(sourceRect.size().width(), sourceRect.height());
pixmap.fill(Qt::transparent);
QPainter p(&pixmap);
p.fillPath(contentPath, m_shadow_color);
p.end();
QImage img = pixmap.toImage();
qt_blurImage(img, m_blur_radius, false, false);
pixmap.convertFromImage(img);
painter->save();
painter->setClipPath(sourcePath - contentPath);
painter->drawImage(QPoint(), img);
painter->restore();
}
}
peony/libpeony-qt/vfs/ 0000755 0001750 0001750 00000000000 14205115226 013667 5 ustar feng feng peony/libpeony-qt/vfs/favorite-vfs-file-enumerator.h 0000644 0001750 0001750 00000003075 14205101223 021544 0 ustar feng feng /*
* 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 .
*
* Authors: Ding Jing
*
*/
#ifndef FAVORITEVFSFILEENUMERATOR_H
#define FAVORITEVFSFILEENUMERATOR_H
#include
#include
G_BEGIN_DECLS
#define VFS_TYPE_FAVORITES_FILE_ENUMERATOR vfs_favorites_file_enumerator_get_type()
G_DECLARE_FINAL_TYPE(FavoritesVFSFileEnumerator, vfs_favorites_file_enumerator, VFS, FAVORITES_FILE_ENUMERATOR, GFileEnumerator)
FavoritesVFSFileEnumerator* vfs_favorites_file_enumerator_new(void);
typedef struct _FavoritesVFSFileEnumeratorPrivate FavoritesVFSFileEnumeratorPrivate;
struct _FavoritesVFSFileEnumeratorPrivate
{
QQueue* enumerate_queue;
};
struct _FavoritesVFSFileEnumerator
{
GFileEnumerator parent_instance;
FavoritesVFSFileEnumeratorPrivate* priv;
};
G_END_DECLS
#endif // FAVORITEVFSFILEENUMERATOR_H
peony/libpeony-qt/vfs/search-vfs-uri-parser.h 0000644 0001750 0001750 00000002653 14205101223 020166 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef SEARCHVFSURIPARSER_H
#define SEARCHVFSURIPARSER_H
#include
#include
namespace Peony {
class PEONYCORESHARED_EXPORT SearchVFSUriParser
{
public:
const static QString parseSearchKey(const QString &uri, const QString &key, const bool &search_file_name=true,
const bool &search_content=false, const QString &extend_key="", const bool &recursive = true);
const static QString getSearchUriNameRegexp(const QString &searchUri);
const static QString getSearchUriTargetDirectory(const QString &searchUri);
private:
SearchVFSUriParser();
};
}
#endif // SEARCHVFSURIPARSER_H
peony/libpeony-qt/vfs/favorite-vfs-file.cpp 0000644 0001750 0001750 00000057625 14205115226 017742 0 ustar feng feng /*
* 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 .
*
* Authors: Ding Jing
*
*/
#include "file-utils.h"
#include "favorite-vfs-file.h"
#include "favorite-vfs-file-monitor.h"
#include "favorite-vfs-file-enumerator.h"
#include
#include
#include
#include
static char* vfs_favorite_file_get_target_file (GFile* file);
static void vfs_favorite_file_g_file_iface_init(GFileIface *iface);
GFile* vfs_favorite_file_dup(GFile *file);
char* vfs_favorite_file_get_uri(GFile *file);
char* vfs_favorite_file_get_path(GFile *file);
gboolean vfs_favorite_file_is_native(GFile *file);
GFile* vfs_favorite_file_get_parent(GFile *file);
char* vfs_favorite_file_get_schema (GFile* file);
void vfs_favorite_file_dispose(GObject *object);
char* vfs_favorite_file_get_basename (GFile* file);
GFile* vfs_favorite_file_new_for_uri(const char *uri);
gboolean vfs_favorite_file_is_equal(GFile *file1, GFile *file2);
char* vfs_favorite_file_get_relative_path (GFile* parent, GFile* descendant);
GFile* vfs_favorite_file_resolve_relative_path(GFile *file, const char *relative_path);
GFileInputStream* vfs_favorite_file_read_fn(GFile* file, GCancellable* cancellable, GError** error);
gboolean vfs_favorite_file_delete (GFile* file, GCancellable* cancellable, GError** error);
GFileIOStream * vfs_favorite_file_open_readwrite(GFile* file, GCancellable* cancellable, GError** error);
gboolean vfs_favorite_file_make_directory(GFile* file, GCancellable* cancellable, GError** error);
GMount * vfs_favorite_file_find_enclosing_mount(GFile* file, GCancellable* cancellable, GError** error);
GFileOutputStream* vfs_favorite_file_create(GFile* file, GFileCreateFlags flags, GCancellable* cancellable, GError** error);
gboolean vfs_favorite_file_make_symbolic_link(GFile* file, const char* svalue, GCancellable* cancellable, GError** error);
GFileMonitor* vfs_favorite_file_monitor_directory (GFile* file, GFileMonitorFlags flags, GCancellable* cancellable, GError** error);
GFile* vfs_favorite_file_set_display_name (GFile* file, const gchar* display_name, GCancellable* cancellable, GError** error);
GFileInfo* vfs_favorite_file_query_filesystem_info(GFile* file, const char* attributes, GCancellable* cancellable, GError** error);
GFileInfo* vfs_favorite_file_query_info(GFile *file, const char *attributes, GFileQueryInfoFlags flags, GCancellable *cancellable, GError **error);
GFileEnumerator* vfs_favorite_file_enumerate_children(GFile *file, const char *attribute, GFileQueryInfoFlags flags, GCancellable *cancellable, GError **error);
GFileOutputStream* vfs_favorite_file_replace(GFile* file, const char* etag, gboolean make_backup, GFileCreateFlags flags, GCancellable* cancellable, GError** error);
GFileEnumerator* vfs_favorite_file_enumerate_children_internal(GFile *file, const char *attribute, GFileQueryInfoFlags flags, GCancellable *cancellable, GError **error);
gboolean vfs_favorite_file_copy(GFile* source, GFile* destination, GFileCopyFlags flags, GCancellable* cancellable, GFileProgressCallback pcallback, gpointer pcallbackdata, GError** error);
gboolean vfs_favorite_file_move(GFile* source, GFile* destination, GFileCopyFlags flags, GCancellable* cancellable, GFileProgressCallback progress_callback, gpointer progress, GError** error);
G_DEFINE_TYPE_EXTENDED(FavoriteVFSFile, vfs_favorite_file, G_TYPE_OBJECT, 0, G_ADD_PRIVATE(FavoriteVFSFile) G_IMPLEMENT_INTERFACE(G_TYPE_FILE, vfs_favorite_file_g_file_iface_init));
static void vfs_favorite_file_init(FavoriteVFSFile* self)
{
g_return_if_fail(VFS_IS_FAVORITES_FILE(self));
FavoriteVFSFilePrivate *priv = (FavoriteVFSFilePrivate*)vfs_favorite_file_get_instance_private(self);
self->priv = priv;
self->priv->uri = nullptr;
}
static void vfs_favorite_file_class_init (FavoriteVFSFileClass* kclass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS (kclass);
gobject_class->dispose = vfs_favorite_file_dispose;
}
void vfs_favorite_file_dispose(GObject *object)
{
g_return_if_fail(VFS_IS_FAVORITES_FILE(object));
auto vfsfile = VFS_FAVORITES_FILE (object);
if (G_IS_FILE_MONITOR(vfsfile->priv->fileMonitor)) {
g_file_monitor_cancel (vfsfile->priv->fileMonitor);
vfsfile->priv->fileMonitor = nullptr;
}
if (vfsfile->priv->uri) {
g_free(vfsfile->priv->uri);
vfsfile->priv->uri = nullptr;
}
}
static void vfs_favorite_file_g_file_iface_init(GFileIface *iface)
{
iface->dup = vfs_favorite_file_dup;
iface->move = vfs_favorite_file_move;
iface->copy = vfs_favorite_file_copy;
iface->trash = vfs_favorite_file_delete;
iface->read_fn = vfs_favorite_file_read_fn;
iface->equal = vfs_favorite_file_is_equal;
iface->create = vfs_favorite_file_create;
iface->get_uri = vfs_favorite_file_get_uri;
iface->get_path = vfs_favorite_file_get_path;
iface->is_native = vfs_favorite_file_is_native;
iface->get_parent = vfs_favorite_file_get_parent;
iface->query_info = vfs_favorite_file_query_info;
iface->delete_file = vfs_favorite_file_delete;
iface->get_uri_scheme = vfs_favorite_file_get_schema;
iface->get_basename = vfs_favorite_file_get_basename;
iface->open_readwrite = vfs_favorite_file_open_readwrite;
iface->make_directory = vfs_favorite_file_make_directory;
iface->set_display_name = vfs_favorite_file_set_display_name;
iface->get_relative_path = vfs_favorite_file_get_relative_path;
iface->monitor_dir = vfs_favorite_file_monitor_directory;
iface->make_symbolic_link = vfs_favorite_file_make_symbolic_link;
iface->enumerate_children = vfs_favorite_file_enumerate_children;
iface->find_enclosing_mount = vfs_favorite_file_find_enclosing_mount;
iface->query_filesystem_info = vfs_favorite_file_query_filesystem_info;
iface->resolve_relative_path = vfs_favorite_file_resolve_relative_path;
}
char* vfs_favorite_file_get_uri(GFile *file)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), g_strdup("favorite:///"));
auto vfsfile = VFS_FAVORITES_FILE (file);
return g_strdup(Peony::FileUtils::urlDecode(vfsfile->priv->uri).toUtf8().constData());
}
gboolean vfs_favorite_file_is_native(GFile *file)
{
Q_UNUSED(file);
return FALSE;
}
GFile* vfs_favorite_file_dup (GFile *file)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), g_file_new_for_uri("favorite:///"));
auto vfs_file = VFS_FAVORITES_FILE(file);
auto dup = VFS_FAVORITES_FILE(g_object_new(VFS_TYPE_FAVORITE_FILE, nullptr));
dup->priv->uri = g_strdup(vfs_file->priv->uri);
return G_FILE(dup);
}
GFileEnumerator* vfs_favorite_file_enumerate_children_internal(GFile *file, const char *attribute, GFileQueryInfoFlags flags, GCancellable *cancellable, GError **error)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), nullptr);
Q_UNUSED(flags)
Q_UNUSED(error)
Q_UNUSED(attribute)
Q_UNUSED(cancellable)
QString uri = g_file_get_uri(file);
if ("favorite:///" == uri) {
return G_FILE_ENUMERATOR(g_object_new(VFS_TYPE_FAVORITES_FILE_ENUMERATOR, "container", file, nullptr));
}
return nullptr;
}
GFile* vfs_favorite_file_new_for_uri(const char* turi)
{
auto vfsfile = VFS_FAVORITES_FILE(g_object_new(VFS_TYPE_FAVORITE_FILE, nullptr));
QString quri;
QString uri = Peony::FileUtils::urlDecode(turi);
QString urii1 = uri.replace("favorite://", "");
QStringList path1 = urii1.split("/");
QStringList path2;
QString path3;
QString schemaInfo;
for (auto i : path1) {
if ("" != i) {
if (!i.contains("?schema=")) {
path2 << i;
continue;
}
QStringList tmp = i.split("?schema=");
if (tmp.size() >= 2 && "favorite" != tmp[1]) {
path2 << tmp[0];
schemaInfo = "?schema=" + tmp[1];
}
}
}
path3 = path2.join("/") + schemaInfo;
if ("?schema=" == schemaInfo || "" == path3) {
quri = "favorite:///";
} else {
quri = "favorite:///" + path2.join("/") + schemaInfo;
}
vfsfile->priv->uri = g_strdup(Peony::FileUtils::urlEncode(quri).toUtf8().constData());
return G_FILE(vfsfile);
}
char* vfs_favorite_file_get_path(GFile *file)
{
return nullptr;
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), nullptr);
QUrl url = QString(vfs_favorite_file_get_uri (file));
return g_strdup (url.path().toUtf8().constData());
}
GFile* vfs_favorite_file_resolve_relative_path(GFile *file, const char *relativepath)
{
QString tmp = relativepath;
if (tmp.contains('/')) {
if (relativepath) {
return g_file_new_for_uri(relativepath);
}
} else if (!tmp.isEmpty()) {
QString uri = "favorite:///" + tmp;
return vfs_favorite_file_new_for_uri(uri.toUtf8().constData());
}
return g_file_new_for_uri("favorite:///");;
}
GFileInfo* vfs_favorite_file_query_info(GFile *file, const char *attributes, GFileQueryInfoFlags flags, GCancellable *cancellable, GError **error)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), nullptr);
auto vfsfile = VFS_FAVORITES_FILE(file);
GFileInfo* info = nullptr;
QString trueUri = nullptr;
QUrl url(vfs_favorite_file_get_uri(file));
if ("favorite:///" != url.toString()) {
QStringList querys = url.query().split("&");
for (int i = 0; i < querys.count(); ++i) {
if (querys.at(i).contains("schema=")) {
QString scheam = querys.at(i).split("=").last();
if ("favorite" == scheam) {
trueUri = QString("%1://%2").arg("file").arg(url.path());
} else {
trueUri = QString("%1://%2").arg(scheam).arg(url.path());
}
break;
}
}
}
if (nullptr != trueUri) {
GFile* file = g_file_new_for_uri (trueUri.toUtf8().constData());
if (nullptr != file) {
info = g_file_query_info(file, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, nullptr);
if (!info)
info = g_file_info_new();
g_file_info_set_attribute_string(info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, trueUri.toUtf8().constData());
} else {
info = g_file_info_new();
}
g_object_unref(file);
} else {
info = g_file_info_new ();
QString name = QObject::tr("favorite");
auto icon = g_themed_icon_new("favorite");
g_file_info_set_icon(info, icon);
g_object_unref(icon);
g_file_info_set_size(info, 0);
g_file_info_set_is_hidden(info, FALSE);
g_file_info_set_is_symlink(info, FALSE);
g_file_info_set_file_type(info, G_FILE_TYPE_DIRECTORY);
g_file_info_set_display_name(info, name.toUtf8().constData());
}
g_file_info_set_name (info, vfsfile->priv->uri);
if (url.path() == "/data/usershare") {
g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
g_file_info_set_attribute_string(info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, QObject::tr("Share Data").toUtf8());
}
g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, TRUE);
g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
Q_UNUSED(flags)
Q_UNUSED(error)
Q_UNUSED(attributes)
Q_UNUSED(cancellable)
return info;
}
GFileEnumerator* vfs_favorite_file_enumerate_children(GFile *file, const char *attribute, GFileQueryInfoFlags flags, GCancellable *cancellable, GError **error)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), nullptr);
return vfs_favorite_file_enumerate_children_internal(file, attribute, flags, cancellable, error);
}
GFileMonitor* vfs_favorite_file_monitor_directory (GFile* file, GFileMonitorFlags flags, GCancellable* cancellable, GError** error)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), nullptr);
FavoriteVFSFilePrivate* priv = VFS_FAVORITE_FILE((FavoriteVFSFile*)file)->priv;
priv->fileMonitor = (GFileMonitor*) g_object_new (VFS_TYPE_FAVORITE_FILE_MONITOR, nullptr);
vfs_favorite_file_monitor_dir (VFS_FAVORITE_FILE_MONITOR(priv->fileMonitor));
Q_UNUSED(file)
Q_UNUSED(flags)
Q_UNUSED(error)
Q_UNUSED(cancellable)
return priv->fileMonitor;
}
gboolean vfs_favorite_file_delete (GFile* file, GCancellable* cancellable, GError** error)
{
QString uri = nullptr;
GFileIface *iface = nullptr;
g_return_val_if_fail (VFS_IS_FAVORITES_FILE(file), FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
return FALSE;
}
iface = G_FILE_GET_IFACE (file);
uri = g_file_get_uri (file);
QString errorStr = QObject::tr("Operation not supported");
if (iface->delete_file == NULL) {
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, errorStr.toUtf8().constData());
return FALSE;
}
Peony::BookMarkManager::getInstance()->removeBookMark(uri);
return TRUE;
}
char* vfs_favorite_file_get_schema (GFile* file)
{
Q_UNUSED(file);
return g_strdup("favorite");
}
GFile* vfs_favorite_file_get_parent (GFile* file)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), nullptr);
Q_UNUSED(file);
QString uri = g_file_get_uri(file);
if ("favorite:///" == uri) {
return nullptr;
}
return g_file_new_for_uri("favorite:///");
}
char* vfs_favorite_file_get_basename (GFile* file)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file), nullptr);
char* uri = vfs_favorite_file_get_uri (file);
QString baseName = nullptr;
if (0 == strcmp("favorite:///", uri)) {
return g_strdup("favorite:///");
} else {
QString url = uri;
QString baseNamet = url.split("/").takeLast();
if (baseNamet.contains("?schema=") && baseNamet.split("?schema=").size() >= 2) {
baseName = baseNamet.split("?schema=").first();
}
}
if (nullptr != uri) g_free(uri);
return g_strdup (baseName.toUtf8().constData());
}
gboolean vfs_favorite_file_is_equal(GFile *file1, GFile* file2)
{
g_return_val_if_fail(VFS_IS_FAVORITES_FILE(file1) || VFS_IS_FAVORITES_FILE(file2), false);
char* f1 = g_file_get_uri(file1);
char* f2 = g_file_get_uri(file2);
int ret = g_strcmp0(f1, f2);
if (nullptr != f1) {
g_free(f1);
}
if (nullptr != f2) {
g_free(f2);
}
return ret == 0;
}
GFileOutputStream* vfs_favorite_file_create(GFile* file, GFileCreateFlags flags, GCancellable* cancellable, GError** error)
{
Q_UNUSED(file);
Q_UNUSED(flags);
Q_UNUSED(error);
Q_UNUSED(cancellable);
// fixme:// Do not implement
QString str = QObject::tr("Virtual file directories do not support move and copy operations");
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return FALSE;
}
gboolean vfs_favorite_file_make_directory(GFile* file, GCancellable* cancellable, GError** error)
{
Q_UNUSED(file);
Q_UNUSED(error);
Q_UNUSED(cancellable);
QString str = QObject::tr("The virtual file system does not support folder creation");
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return FALSE;
}
gboolean vfs_favorite_file_make_symbolic_link(GFile* file, const char* svalue, GCancellable* cancellable, GError** error)
{
Q_UNUSED(file);
Q_UNUSED(error);
Q_UNUSED(svalue);
Q_UNUSED(cancellable);
// fixme:// Do not implement
QString str = QObject::tr("Virtual file directories do not support move and copy operations");
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return FALSE;
}
gboolean vfs_favorite_file_move(GFile* source, GFile* destination, GFileCopyFlags flags, GCancellable* cancellable, GFileProgressCallback progress_callback, gpointer progress, GError** error)
{
Q_UNUSED(flags);
Q_UNUSED(progress);
Q_UNUSED(cancellable);
Q_UNUSED(progress_callback);
// fixme:// Do not implement
QString str = QObject::tr("Virtual file directories do not support move and copy operations");
char *src_uri = g_file_get_uri(source);
char *dest_uri = g_file_get_uri(destination);
char *src_scheme = g_file_get_uri_scheme(source);
char *dest_scheme = g_file_get_uri_scheme(destination);
QString srcUri = src_uri;
QString destUri = dest_uri;
// we have constructed a error dest uri in FileMoveOperation::run(),
// at here we should chop the relative path and add it here manually.
destUri.chop(destUri.length() - destUri.lastIndexOf('/'));
QString srcScheme = src_scheme;
QString destScheme = dest_scheme;
if (src_uri) {
g_free(src_uri);
}
if (dest_uri) {
g_free(dest_uri);
}
if (src_scheme) {
g_free(src_scheme);
}
if (dest_scheme) {
g_free(dest_scheme);
}
if (srcScheme == destScheme) {
// dnd from favorite:/// to favorite:///, do nothing
return true;
}
if (srcUri.startsWith("filesafe:///")){
return true;
}
if (srcScheme == "favorite" && destScheme == "file") {
// dnd from favorite:/// to file:///xxx
// find file favorite file point to, and create a symbolic link.
auto file_info = g_file_query_info(source, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, nullptr);
auto target_uri = g_file_info_get_attribute_as_string(file_info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
QString targetUri = target_uri;
if (target_uri) {
g_free(target_uri);
}
g_object_unref(file_info);
if (!targetUri.startsWith("file:///")) {
*error = g_error_new_literal(G_IO_ERROR, G_IO_ERROR_FAILED, QObject::tr("Can not create a symbolic file for vfs location").toUtf8().constData());
return false;
}
auto real_src_file = g_file_new_for_uri(targetUri.toUtf8().constData());
auto real_src_path = g_file_get_path(real_src_file);
auto base_name = g_file_get_basename(real_src_file);
g_object_unref(real_src_file);
QString destLinkUri = destUri + "/" + QObject::tr("Symbolic Link") + " - " + base_name;
auto symbolic_file = g_file_new_for_uri(destLinkUri.toUtf8().constData());
GError *error2 = nullptr;
bool success = g_file_make_symbolic_link(symbolic_file, real_src_path, nullptr, &error2);
if (base_name) {
g_free(base_name);
}
if (real_src_path) {
g_free(real_src_path);
}
g_object_unref(symbolic_file);
if (!success) {
*error = g_error_new_literal(G_IO_ERROR, G_IO_ERROR_FAILED, QObject::tr("Can not create symbolic file here, %1").arg(error2->message).toUtf8().constData());
g_error_free(error2);
}
return success;
}
if (srcScheme == "file" && destScheme == "favorite") {
// add src file to favorite:///
Peony::BookMarkManager::getInstance()->addBookMark(srcUri);
return true;
}
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return FALSE;
}
gboolean vfs_favorite_file_copy(GFile* source, GFile* destination, GFileCopyFlags flags, GCancellable* cancellable, GFileProgressCallback pcallback, gpointer pcallbackdata, GError** error)
{
// fixme:// Do not implement
QString str = QObject::tr("Virtual file directories do not support move and copy operations");
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return FALSE;
}
GFile* vfs_favorite_file_set_display_name (GFile* file, const gchar* display_name, GCancellable* cancellable, GError** error)
{
Q_UNUSED(error);
Q_UNUSED(cancellable);
Q_UNUSED(display_name);
return file;
}
GFileOutputStream* vfs_favorite_file_replace(GFile* file, const char* etag, gboolean make_backup, GFileCreateFlags flags, GCancellable* cancellable, GError** error)
{
QString str = QObject::tr("Virtual file directories do not support move and copy operations");
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return FALSE;
}
GFileInfo* vfs_favorite_file_query_filesystem_info(GFile* file, const char* attributes, GCancellable* cancellable, GError** error)
{
return vfs_favorite_file_query_info(file, attributes, G_FILE_QUERY_INFO_NONE, cancellable, error);
}
GMount* vfs_favorite_file_find_enclosing_mount(GFile* file, GCancellable* cancellable, GError** error)
{
return nullptr;
}
char* vfs_favorite_file_get_relative_path (GFile* parent, GFile* descendant)
{
return nullptr;
}
GFileInputStream* vfs_favorite_file_read_fn(GFile* file, GCancellable* cancellable, GError** error)
{
QString str = QObject::tr("The virtual file system cannot be opened");
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return nullptr;
}
GFileIOStream* vfs_favorite_file_open_readwrite(GFile* file, GCancellable* cancellable, GError** error)
{
QString str = QObject::tr("The virtual file system cannot be opened");
*error = g_error_new(G_FILE_ERROR_FAILED, G_IO_ERROR_NOT_SUPPORTED, "%s\n", str.toUtf8().constData());
return nullptr;
}
gboolean vfs_favorite_file_is_exist(const char *uri)
{
gboolean ret = FALSE;
GFile* file = g_file_new_for_uri(uri);
GFileInfo* fileInfo = nullptr;
if (nullptr != file) {
fileInfo = g_file_query_info(file, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, nullptr);
if (nullptr != fileInfo) {
gchar* targetUri = g_file_info_get_attribute_as_string(fileInfo, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
ret = Peony::FileUtils::isFileExsit(targetUri);
g_free(targetUri);
g_object_unref(fileInfo);
}
g_object_unref(file);
}
return ret;
}
static char* vfs_favorite_file_get_target_file (GFile* file)
{
if (nullptr == file) {
return nullptr;
}
gchar* uri = nullptr;
GFileInfo* fileInfo = nullptr;
gchar* targetUri = nullptr;
uri = g_file_get_uri(file);
if (nullptr != uri && 0 != strncmp("favorite://", uri, 11)) {
return uri;
}
if (nullptr != uri) g_free(uri);
fileInfo = g_file_query_info(file, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, nullptr);
if (nullptr != fileInfo) {
targetUri = g_file_info_get_attribute_as_string(fileInfo, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
g_object_unref(fileInfo);
}
return targetUri;
}
peony/libpeony-qt/vfs/vfs-plugin-manager.h 0000644 0001750 0001750 00000003250 14205101223 017532 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
*
*/
#ifndef VFSPLUGINMANAGER_H
#define VFSPLUGINMANAGER_H
#include "vfs-plugin-iface.h"
#include
#include
namespace Peony {
class PEONYCORESHARED_EXPORT VFSPluginManager : public QObject
{
Q_OBJECT
public:
static VFSPluginManager *getInstance();
void registerPlugin(VFSPluginIface *plugin);
QList registeredPlugins();
/*!
* \brief supportExtraSchemes
* \return the registered plugins schemes, like "search://".
*/
const QStringList supportExtraSchemes();
/*!
* \brief newVFSFile
* construct a vfs file implemented by plugin.
* \param uri
* \return
* \see supportExtraSchemes
*/
GFile *newVFSFile(const QString &uri);
private:
explicit VFSPluginManager(QObject *parent = nullptr);
QList m_plugins;
QStringList m_support_schemes;
};
}
#endif // VFSPLUGINMANAGER_H
peony/libpeony-qt/vfs/search-vfs-uri-parser.cpp 0000644 0001750 0001750 00000007200 14205113763 020526 0 ustar feng feng /*
* 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 .
*
* Authors: Yue Lan
* Authors: Meihong He
*
*/
#include "search-vfs-uri-parser.h"
#include "file-utils.h"
#include
#include
using namespace Peony;
SearchVFSUriParser::SearchVFSUriParser()
{
}
const QString SearchVFSUriParser:: parseSearchKey(const QString &uri, const QString &key, const bool &search_file_name,
const bool &search_content, const QString &extend_key, const bool &recursive)
{
QString search_str = "search:///search_uris="+uri;
if (search_file_name)
search_str += "&name_regexp="+key;
if (search_content)
search_str += "&content_regexp="+key;
//multiple name key search
if (extend_key != "")
search_str += "&extend_regexp="+extend_key;
else if (! search_file_name && ! search_content && extend_key=="")
{
qWarning()<<"Search content or file name at least one be true!";
//use default search file name
search_str += "&name_regexp="+key;
}
if (recursive)
return QString(search_str+"&recursive=1");
return QString(search_str+"&recursive=0");
}
const QString SearchVFSUriParser::getSearchUriNameRegexp(const QString &searchUri)
{
auto string = searchUri;
string.remove("search:///");
auto list = string.split("&");
qDebug() << "list length:" <