parent
03320d44ae
commit
88d19f7ee1
@ -1,18 +0,0 @@
|
||||
Description: Add integration for LXQt Archiver
|
||||
Author: "Hong Jen Yee (PCMan)" <pcman.tw@gmail.com>
|
||||
Origin: upstream
|
||||
Applied-Upstream: commit:9a3bf23
|
||||
Last-Update: 2018-07-14
|
||||
--- a/data/archivers.list
|
||||
+++ b/data/archivers.list
|
||||
@@ -1,3 +1,10 @@
|
||||
+[lxqt-archiver]
|
||||
+create=lxqt-archiver --add %U
|
||||
+extract=lxqt-archiver --extract %U
|
||||
+extract_to=lxqt-archiver --extract-to %d %U
|
||||
+mime_types=application/x-7z-compressed;application/x-7z-compressed-tar;application/x-ace;application/x-alz;application/x-ar;application/x-arj;application/x-bzip;application/x-bzip-compressed-tar;application/x-bzip1;application/x-bzip1-compressed-tar;application/x-cabinet;application/x-cbr;application/x-cbz;application/x-cd-image;application/x-compress;application/x-compressed-tar;application/x-cpio;application/x-deb;application/x-ear;application/x-ms-dos-executable;application/x-gtar;application/x-gzip;application/x-gzpostscript;application/x-java-archive;application/x-lha;application/x-lhz;application/x-lzip;application/x-lzip-compressed-tar;application/x-lzma;application/x-lzma-compressed-tar;application/x-lzop;application/x-lzop-compressed-tar;application/x-rar;application/x-rar-compressed;application/vnd.rar;application/x-rpm;application/x-rzip;application/x-tar;application/x-tarz;application/x-stuffit;application/x-war;application/x-xz;application/x-xz-compressed-tar;application/x-zip;application/x-zip-compressed;application/x-zoo;application/zip;multipart/x-zip;
|
||||
+supports_uris=true
|
||||
+
|
||||
[file-roller]
|
||||
create=file-roller --add %U
|
||||
extract=file-roller --extract %U
|
@ -1,166 +0,0 @@
|
||||
Description: Support adding metadata for trusting executables.
|
||||
Author: Tsu Jan <tsujan2000@gmail.com>
|
||||
Applied-Upstream: https://github.com/lxqt/libfm-qt/pull/242/commits/9c2f00c2e22b8054bcaedad89ef74f0432b9f7fe
|
||||
Last-Update: 2018-10-15
|
||||
--- a/src/core/basicfilelauncher.cpp
|
||||
+++ b/src/core/basicfilelauncher.cpp
|
||||
@@ -176,7 +176,7 @@ bool BasicFileLauncher::launchDesktopEnt
|
||||
const char* desktopEntryName = nullptr;
|
||||
FilePathList shortcutTargetPaths;
|
||||
if(fileInfo->isExecutableType()) {
|
||||
- auto act = quickExec_ ? ExecAction::DIRECT_EXEC : askExecFile(fileInfo);
|
||||
+ auto act = (quickExec_ || fileInfo->isTrustable()) ? ExecAction::DIRECT_EXEC : askExecFile(fileInfo);
|
||||
switch(act) {
|
||||
case ExecAction::EXEC_IN_TERMINAL:
|
||||
case ExecAction::DIRECT_EXEC: {
|
||||
@@ -275,7 +275,7 @@ bool BasicFileLauncher::launchExecutable
|
||||
auto filename = fileInfo->path().localPath();
|
||||
/* FIXME: we need to use eaccess/euidaccess here. */
|
||||
if(g_file_test(filename.get(), G_FILE_TEST_IS_EXECUTABLE)) {
|
||||
- auto act = quickExec_ ? ExecAction::DIRECT_EXEC : askExecFile(fileInfo);
|
||||
+ auto act = (quickExec_ || fileInfo->isTrustable()) ? ExecAction::DIRECT_EXEC : askExecFile(fileInfo);
|
||||
int flags = G_APP_INFO_CREATE_NONE;
|
||||
switch(act) {
|
||||
case ExecAction::EXEC_IN_TERMINAL:
|
||||
--- a/src/core/fileinfo.cpp
|
||||
+++ b/src/core/fileinfo.cpp
|
||||
@@ -9,7 +9,8 @@ const char defaultGFileInfoQueryAttribs[
|
||||
"time::*,"
|
||||
"access::*,"
|
||||
"id::filesystem,"
|
||||
- "metadata::emblems";
|
||||
+ "metadata::emblems,"
|
||||
+ "metadata::trusted";
|
||||
|
||||
FileInfo::FileInfo() {
|
||||
// FIXME: initialize numeric data members
|
||||
@@ -23,6 +24,7 @@ FileInfo::~FileInfo() {
|
||||
}
|
||||
|
||||
void FileInfo::setFromGFileInfo(const GObjectPtr<GFileInfo>& inf, const FilePath& parentDirPath) {
|
||||
+ inf_ = inf;
|
||||
dirPath_ = parentDirPath;
|
||||
const char* tmp, *uri;
|
||||
GIcon* gicon;
|
||||
@@ -377,6 +379,37 @@ bool FileInfo::isExecutableType() const
|
||||
return mimeType_->canBeExecutable();
|
||||
}
|
||||
|
||||
+bool FileInfo::isTrustable() const {
|
||||
+ if(isExecutableType()) {
|
||||
+ /* to avoid GIO assertion warning: */
|
||||
+ if(g_file_info_get_attribute_type(inf_.get(), "metadata::trusted") == G_FILE_ATTRIBUTE_TYPE_STRING) {
|
||||
+ if(const auto data = g_file_info_get_attribute_string(inf_.get(), "metadata::trusted")) {
|
||||
+ return (strcmp(data, "true") == 0);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+void FileInfo::setTrustable(bool trust) const {
|
||||
+ if(!isExecutableType()) {
|
||||
+ return; // "metadata::trusted" is only for executables
|
||||
+ }
|
||||
+ GObjectPtr<GFileInfo> info {g_file_info_new()}; // used to set only this attribute
|
||||
+ if(trust) {
|
||||
+ g_file_info_set_attribute_string(info.get(), "metadata::trusted", "true");
|
||||
+ g_file_info_set_attribute_string(inf_.get(), "metadata::trusted", "true");
|
||||
+ }
|
||||
+ else {
|
||||
+ g_file_info_set_attribute(info.get(), "metadata::trusted", G_FILE_ATTRIBUTE_TYPE_INVALID, nullptr);
|
||||
+ g_file_info_set_attribute(inf_.get(), "metadata::trusted", G_FILE_ATTRIBUTE_TYPE_INVALID, nullptr);
|
||||
+ }
|
||||
+ g_file_set_attributes_from_info(path().gfile().get(),
|
||||
+ info.get(),
|
||||
+ G_FILE_QUERY_INFO_NONE,
|
||||
+ nullptr, nullptr);
|
||||
+}
|
||||
+
|
||||
|
||||
bool FileInfoList::isSameType() const {
|
||||
if(!empty()) {
|
||||
--- a/src/core/fileinfo.h
|
||||
+++ b/src/core/fileinfo.h
|
||||
@@ -214,7 +214,12 @@ public:
|
||||
return emblems_;
|
||||
}
|
||||
|
||||
+ bool isTrustable() const;
|
||||
+
|
||||
+ void setTrustable(bool trust) const;
|
||||
+
|
||||
private:
|
||||
+ GObjectPtr<GFileInfo> inf_;
|
||||
std::string name_;
|
||||
QString dispName_;
|
||||
|
||||
--- a/src/filemenu.cpp
|
||||
+++ b/src/filemenu.cpp
|
||||
@@ -245,6 +245,18 @@ FileMenu::FileMenu(Fm::FileInfoList file
|
||||
FileMenu::~FileMenu() {
|
||||
}
|
||||
|
||||
+void FileMenu::addTrustAction() {
|
||||
+ if(info_->isExecutableType() && (!fileLauncher_ || !fileLauncher_->quickExec())) {
|
||||
+ QAction* trustAction = new QAction(files_.size() > 1
|
||||
+ ? tr("Trust selected executables")
|
||||
+ : tr("Trust this executable"),
|
||||
+ this);
|
||||
+ trustAction->setCheckable(true);
|
||||
+ trustAction->setChecked(info_->isTrustable());
|
||||
+ connect(trustAction, &QAction::toggled, this, &FileMenu::onTrustToggled);
|
||||
+ insertAction(propertiesAction_, trustAction);
|
||||
+ }
|
||||
+}
|
||||
|
||||
void FileMenu::addCustomActionItem(QMenu* menu, std::shared_ptr<const FileActionItem> item) {
|
||||
if(!item) { // separator
|
||||
@@ -329,6 +341,12 @@ void FileMenu::onCustomActionTrigerred()
|
||||
}
|
||||
}
|
||||
|
||||
+void FileMenu::onTrustToggled(bool checked) {
|
||||
+ for(auto& file: files_) {
|
||||
+ file->setTrustable(checked);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void FileMenu::onFilePropertiesTriggered() {
|
||||
FilePropsDialog::showForFiles(files_);
|
||||
}
|
||||
--- a/src/filemenu.h
|
||||
+++ b/src/filemenu.h
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
explicit FileMenu(Fm::FileInfoList files, std::shared_ptr<const Fm::FileInfo> info, Fm::FilePath cwd, bool isWritableDir = true, const QString& title = QString(), QWidget* parent = nullptr);
|
||||
~FileMenu();
|
||||
|
||||
+ void addTrustAction();
|
||||
+
|
||||
bool useTrash() {
|
||||
return useTrash_;
|
||||
}
|
||||
@@ -162,6 +164,7 @@ protected:
|
||||
protected Q_SLOTS:
|
||||
void onOpenTriggered();
|
||||
void onOpenWithTriggered();
|
||||
+ void onTrustToggled(bool checked);
|
||||
void onFilePropertiesTriggered();
|
||||
void onApplicationTriggered();
|
||||
void onCustomActionTrigerred();
|
||||
--- a/src/folderview.cpp
|
||||
+++ b/src/folderview.cpp
|
||||
@@ -1318,11 +1318,11 @@ void FolderView::onFileClicked(int type,
|
||||
// show context menu
|
||||
auto files = selectedFiles();
|
||||
if(!files.empty()) {
|
||||
- QModelIndexList selIndexes = mode == DetailedListMode ? selectedRows() : selectedIndexes();
|
||||
- Fm::FileMenu* fileMenu = (view && selIndexes.size() == 1)
|
||||
+ Fm::FileMenu* fileMenu = (view && files.size() == 1)
|
||||
? new Fm::FileMenu(files, fileInfo, folderPath, isWritableDir, QString(), view)
|
||||
: new Fm::FileMenu(files, fileInfo, folderPath, isWritableDir);
|
||||
fileMenu->setFileLauncher(fileLauncher_);
|
||||
+ fileMenu->addTrustAction();
|
||||
prepareFileMenu(fileMenu);
|
||||
menu = fileMenu;
|
||||
}
|
@ -1,251 +0,0 @@
|
||||
Description: Fix failure to open smb:// caused by incorrect file info handling
|
||||
Author: "Hong Jen Yee (PCMan)" <pcman.tw@gmail.com>
|
||||
Origin: upstream
|
||||
Applied-Upstream: commit:1a6fa26
|
||||
Last-Update: 2018-07-14
|
||||
--- a/src/core/basicfilelauncher.cpp
|
||||
+++ b/src/core/basicfilelauncher.cpp
|
||||
@@ -27,11 +27,13 @@ bool BasicFileLauncher::launchFiles(cons
|
||||
FilePathList pathsToLaunch;
|
||||
// classify files according to different mimetypes
|
||||
for(auto& fileInfo : fileInfos) {
|
||||
- // qDebug("path: %s, target: %s", fileInfo->path().toString().get(), fileInfo->target().c_str());
|
||||
- if(fileInfo->isDir()) {
|
||||
- folderInfos.emplace_back(fileInfo);
|
||||
- }
|
||||
- else if(fileInfo->isMountable()) {
|
||||
+ /*
|
||||
+ qDebug("path: %s, type: %s, target: %s, isDir: %i, isDesktopEntry: %i",
|
||||
+ fileInfo->path().toString().get(), fileInfo->mimeType()->name(), fileInfo->target().c_str(),
|
||||
+ fileInfo->isDir(), fileInfo->isDesktopEntry());
|
||||
+ */
|
||||
+
|
||||
+ if(fileInfo->isMountable()) {
|
||||
if(fileInfo->target().empty()) {
|
||||
// the mountable is not yet mounted so we have no target URI.
|
||||
GErrorPtr err{G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED,
|
||||
@@ -65,6 +67,9 @@ bool BasicFileLauncher::launchFiles(cons
|
||||
pathsToLaunch.emplace_back(path);
|
||||
}
|
||||
}
|
||||
+ else if(fileInfo->isDir()) {
|
||||
+ folderInfos.emplace_back(fileInfo);
|
||||
+ }
|
||||
else {
|
||||
auto& mimeType = fileInfo->mimeType();
|
||||
mimeTypeToFiles[mimeType->name()].emplace_back(fileInfo);
|
||||
@@ -101,16 +106,27 @@ bool BasicFileLauncher::launchFiles(cons
|
||||
bool BasicFileLauncher::launchPaths(FilePathList paths, GAppLaunchContext* ctx) {
|
||||
// FIXME: blocking with an event loop is not a good design :-(
|
||||
QEventLoop eventLoop;
|
||||
-
|
||||
auto job = new FileInfoJob{paths};
|
||||
job->setAutoDelete(false); // do not automatically delete the job since we want its results later.
|
||||
|
||||
GObjectPtr<GAppLaunchContext> ctxPtr{ctx};
|
||||
+
|
||||
+ // error handling (for example: handle path not mounted error)
|
||||
+ QObject::connect(job, &FileInfoJob::error,
|
||||
+ &eventLoop, [this, job, ctx](const GErrorPtr & err, Job::ErrorSeverity /* severity */ , Job::ErrorAction &act) {
|
||||
+ auto path = job->currentPath();
|
||||
+ if(showError(ctx, err, path, nullptr)) {
|
||||
+ // the user handled the error and ask for retry
|
||||
+ act = Job::ErrorAction::RETRY;
|
||||
+ }
|
||||
+ }, Qt::BlockingQueuedConnection); // BlockingQueuedConnection is required here to pause the job and wait for user response
|
||||
+
|
||||
QObject::connect(job, &FileInfoJob::finished,
|
||||
[&eventLoop]() {
|
||||
// exit the event loop when the job is done
|
||||
eventLoop.exit();
|
||||
});
|
||||
+
|
||||
// run the job in another thread to not block the UI
|
||||
job->runAsync();
|
||||
|
||||
@@ -143,7 +159,7 @@ BasicFileLauncher::ExecAction BasicFileL
|
||||
return ExecAction::DIRECT_EXEC;
|
||||
}
|
||||
|
||||
-bool BasicFileLauncher::showError(GAppLaunchContext* /* ctx */, GErrorPtr& /* err */, const FilePath& /* path */, const FileInfoPtr& /* info */) {
|
||||
+bool BasicFileLauncher::showError(GAppLaunchContext* /* ctx */, const GErrorPtr & /* err */, const FilePath& /* path */, const FileInfoPtr& /* info */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -247,13 +263,21 @@ bool BasicFileLauncher::launchDesktopEnt
|
||||
|
||||
FilePath BasicFileLauncher::handleShortcut(const FileInfoPtr& fileInfo, GAppLaunchContext* ctx) {
|
||||
auto target = fileInfo->target();
|
||||
+
|
||||
+ // if we know the target is a dir, we are not going to open it using other apps
|
||||
+ // for example: `network:///smb-root' is a shortcut targeting `smb:///' and it's also a dir
|
||||
+ if(fileInfo->isDir()) {
|
||||
+ return FilePath::fromPathStr(target.c_str());
|
||||
+ }
|
||||
+
|
||||
auto scheme = CStrPtr{g_uri_parse_scheme(target.c_str())};
|
||||
if(scheme) {
|
||||
// collect the uri schemes we support
|
||||
if(strcmp(scheme.get(), "file") == 0
|
||||
|| strcmp(scheme.get(), "trash") == 0
|
||||
|| strcmp(scheme.get(), "network") == 0
|
||||
- || strcmp(scheme.get(), "computer") == 0) {
|
||||
+ || strcmp(scheme.get(), "computer") == 0
|
||||
+ || strcmp(scheme.get(), "menu") == 0) {
|
||||
return FilePath::fromUri(fileInfo->target().c_str());
|
||||
}
|
||||
else {
|
||||
--- a/src/core/basicfilelauncher.h
|
||||
+++ b/src/core/basicfilelauncher.h
|
||||
@@ -53,7 +53,7 @@ protected:
|
||||
|
||||
virtual bool openFolder(GAppLaunchContext* ctx, const FileInfoList& folderInfos, GErrorPtr& err);
|
||||
|
||||
- virtual bool showError(GAppLaunchContext* ctx, GErrorPtr& err, const FilePath& path = FilePath{}, const FileInfoPtr& info = FileInfoPtr{});
|
||||
+ virtual bool showError(GAppLaunchContext* ctx, const GErrorPtr& err, const FilePath& path = FilePath{}, const FileInfoPtr& info = FileInfoPtr{});
|
||||
|
||||
virtual ExecAction askExecFile(const FileInfoPtr& file);
|
||||
|
||||
--- a/src/core/fileinfo.cpp
|
||||
+++ b/src/core/fileinfo.cpp
|
||||
@@ -36,10 +36,9 @@ void FileInfo::setFromGFileInfo(const GO
|
||||
size_ = g_file_info_get_size(inf.get());
|
||||
|
||||
tmp = g_file_info_get_content_type(inf.get());
|
||||
- if(!tmp) {
|
||||
- tmp = "application/octet-stream";
|
||||
+ if(tmp) {
|
||||
+ mimeType_ = MimeType::fromName(tmp);
|
||||
}
|
||||
- mimeType_ = MimeType::fromName(tmp);
|
||||
|
||||
mode_ = g_file_info_get_attribute_uint32(inf.get(), G_FILE_ATTRIBUTE_UNIX_MODE);
|
||||
|
||||
@@ -196,6 +195,10 @@ _file_is_symlink:
|
||||
}
|
||||
}
|
||||
|
||||
+ if(!mimeType_) {
|
||||
+ mimeType_ = MimeType::fromName("application/octet-stream");
|
||||
+ }
|
||||
+
|
||||
/* if there is a custom folder icon, use it */
|
||||
if(isNative() && type == G_FILE_TYPE_DIRECTORY) {
|
||||
auto local_path = path().localPath();
|
||||
--- a/src/core/fileinfojob.cpp
|
||||
+++ b/src/core/fileinfojob.cpp
|
||||
@@ -13,31 +13,41 @@ FileInfoJob::FileInfoJob(FilePathList pa
|
||||
|
||||
void FileInfoJob::exec() {
|
||||
for(const auto& path: paths_) {
|
||||
- if(!isCancelled()) {
|
||||
+ if(isCancelled()) {
|
||||
+ break;
|
||||
+ }
|
||||
+ currentPath_ = path;
|
||||
+
|
||||
+ bool retry;
|
||||
+ do {
|
||||
+ retry = false;
|
||||
GErrorPtr err;
|
||||
GFileInfoPtr inf{
|
||||
g_file_query_info(path.gfile().get(), defaultGFileInfoQueryAttribs,
|
||||
G_FILE_QUERY_INFO_NONE, cancellable().get(), &err),
|
||||
false
|
||||
};
|
||||
- if(!inf) {
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- // Reuse the same dirPath object when the path remains the same (optimize for files in the same dir)
|
||||
- auto dirPath = commonDirPath_.isValid() ? commonDirPath_ : path.parent();
|
||||
- FileInfo fileInfo(inf, dirPath);
|
||||
+ if(inf) {
|
||||
+ // Reuse the same dirPath object when the path remains the same (optimize for files in the same dir)
|
||||
+ auto dirPath = commonDirPath_.isValid() ? commonDirPath_ : path.parent();
|
||||
+ auto fileInfoPtr = std::make_shared<FileInfo>(inf, dirPath);
|
||||
+
|
||||
+ // FIXME: this is not elegant
|
||||
+ if(cutFilesHashSet_
|
||||
+ && cutFilesHashSet_->count(path.hash())) {
|
||||
+ fileInfoPtr->bindCutFiles(cutFilesHashSet_);
|
||||
+ }
|
||||
|
||||
- if(cutFilesHashSet_
|
||||
- && cutFilesHashSet_->count(fileInfo.path().hash())) {
|
||||
- fileInfo.bindCutFiles(cutFilesHashSet_);
|
||||
+ results_.push_back(fileInfoPtr);
|
||||
+ Q_EMIT gotInfo(path, results_.back());
|
||||
}
|
||||
-
|
||||
- auto fileInfoPtr = std::make_shared<const FileInfo>(fileInfo);
|
||||
-
|
||||
- results_.push_back(fileInfoPtr);
|
||||
- Q_EMIT gotInfo(path, fileInfoPtr);
|
||||
- }
|
||||
+ else {
|
||||
+ auto act = emitError(err);
|
||||
+ if(act == Job::ErrorAction::RETRY) {
|
||||
+ retry = true;
|
||||
+ }
|
||||
+ }
|
||||
+ } while(retry && !isCancelled());
|
||||
}
|
||||
}
|
||||
|
||||
--- a/src/core/fileinfojob.h
|
||||
+++ b/src/core/fileinfojob.h
|
||||
@@ -27,6 +27,10 @@ public:
|
||||
return results_;
|
||||
}
|
||||
|
||||
+ const FilePath& currentPath() const {
|
||||
+ return currentPath_;
|
||||
+ }
|
||||
+
|
||||
Q_SIGNALS:
|
||||
void gotInfo(const FilePath& path, std::shared_ptr<const FileInfo>& info);
|
||||
|
||||
@@ -39,6 +43,7 @@ private:
|
||||
FileInfoList results_;
|
||||
FilePath commonDirPath_;
|
||||
const std::shared_ptr<const HashSet> cutFilesHashSet_;
|
||||
+ FilePath currentPath_;
|
||||
};
|
||||
|
||||
} // namespace Fm
|
||||
--- a/src/core/gioptrs.h
|
||||
+++ b/src/core/gioptrs.h
|
||||
@@ -112,6 +112,10 @@ public:
|
||||
return err_;
|
||||
}
|
||||
|
||||
+ const GError* operator->() const {
|
||||
+ return err_;
|
||||
+ }
|
||||
+
|
||||
bool operator == (const GErrorPtr& other) const {
|
||||
return err_ == other.err_;
|
||||
}
|
||||
--- a/src/filelauncher.cpp
|
||||
+++ b/src/filelauncher.cpp
|
||||
@@ -76,7 +76,7 @@ bool FileLauncher::openFolder(GAppLaunch
|
||||
return BasicFileLauncher::openFolder(ctx, folderInfos, err);
|
||||
}
|
||||
|
||||
-bool FileLauncher::showError(GAppLaunchContext* /*ctx*/, GErrorPtr &err, const FilePath &path, const FileInfoPtr &info) {
|
||||
+bool FileLauncher::showError(GAppLaunchContext* /*ctx*/, const GErrorPtr &err, const FilePath &path, const FileInfoPtr &info) {
|
||||
/* ask for mount if trying to launch unmounted path */
|
||||
if(err->domain == G_IO_ERROR) {
|
||||
if(path && err->code == G_IO_ERROR_NOT_MOUNTED) {
|
||||
--- a/src/filelauncher.h
|
||||
+++ b/src/filelauncher.h
|
||||
@@ -43,7 +43,7 @@ protected:
|
||||
|
||||
bool openFolder(GAppLaunchContext* ctx, const FileInfoList& folderInfos, GErrorPtr& err) override;
|
||||
|
||||
- bool showError(GAppLaunchContext* ctx, GErrorPtr& err, const FilePath& path = FilePath{}, const FileInfoPtr& info = FileInfoPtr{}) override;
|
||||
+ bool showError(GAppLaunchContext* ctx, const GErrorPtr &err, const FilePath& path = FilePath{}, const FileInfoPtr& info = FileInfoPtr{}) override;
|
||||
|
||||
ExecAction askExecFile(const FileInfoPtr& file) override;
|
||||
|
@ -1,68 +0,0 @@
|
||||
Description: Correctly handle mountable types
|
||||
Author: "Hong Jen Yee (PCMan)" <pcman.tw@gmail.com>
|
||||
Origin: upstream
|
||||
Applied-Upstream: commit:dc7a575
|
||||
Last-Update: 2018-07-14
|
||||
--- a/src/core/basicfilelauncher.cpp
|
||||
+++ b/src/core/basicfilelauncher.cpp
|
||||
@@ -28,11 +28,10 @@ bool BasicFileLauncher::launchFiles(cons
|
||||
// classify files according to different mimetypes
|
||||
for(auto& fileInfo : fileInfos) {
|
||||
/*
|
||||
- qDebug("path: %s, type: %s, target: %s, isDir: %i, isDesktopEntry: %i",
|
||||
+ qDebug("path: %s, type: %s, target: %s, isDir: %i, isShortcut: %i, isMountable: %i, isDesktopEntry: %i",
|
||||
fileInfo->path().toString().get(), fileInfo->mimeType()->name(), fileInfo->target().c_str(),
|
||||
- fileInfo->isDir(), fileInfo->isDesktopEntry());
|
||||
+ fileInfo->isDir(), fileInfo->isShortcut(), fileInfo->isMountable(), fileInfo->isDesktopEntry());
|
||||
*/
|
||||
-
|
||||
if(fileInfo->isMountable()) {
|
||||
if(fileInfo->target().empty()) {
|
||||
// the mountable is not yet mounted so we have no target URI.
|
||||
@@ -267,6 +266,7 @@ FilePath BasicFileLauncher::handleShortc
|
||||
// if we know the target is a dir, we are not going to open it using other apps
|
||||
// for example: `network:///smb-root' is a shortcut targeting `smb:///' and it's also a dir
|
||||
if(fileInfo->isDir()) {
|
||||
+ qDebug("shortcut is dir: %s", target.c_str());
|
||||
return FilePath::fromPathStr(target.c_str());
|
||||
}
|
||||
|
||||
--- a/src/core/fileinfo.cpp
|
||||
+++ b/src/core/fileinfo.cpp
|
||||
@@ -118,7 +118,8 @@ void FileInfo::setFromGFileInfo(const GO
|
||||
isDeletable_ = true;
|
||||
}
|
||||
|
||||
- isShortcut_ = false;
|
||||
+ isShortcut_ = (type == G_FILE_TYPE_SHORTCUT);
|
||||
+ isMountable_ = (type == G_FILE_TYPE_MOUNTABLE);
|
||||
|
||||
/* special handling for symlinks */
|
||||
if(g_file_info_get_is_symlink(inf.get())) {
|
||||
@@ -129,7 +130,6 @@ void FileInfo::setFromGFileInfo(const GO
|
||||
|
||||
switch(type) {
|
||||
case G_FILE_TYPE_SHORTCUT:
|
||||
- isShortcut_ = true;
|
||||
/* Falls through. */
|
||||
case G_FILE_TYPE_MOUNTABLE:
|
||||
uri = g_file_info_get_attribute_string(inf.get(), G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
|
||||
--- a/src/core/fileinfo.h
|
||||
+++ b/src/core/fileinfo.h
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
}
|
||||
|
||||
bool isMountable() const {
|
||||
- return mimeType_->isMountable();
|
||||
+ return isMountable_;
|
||||
}
|
||||
|
||||
bool isShortcut() const {
|
||||
@@ -239,6 +239,7 @@ private:
|
||||
std::string target_; /* target of shortcut or mountable. */
|
||||
|
||||
bool isShortcut_ : 1; /* TRUE if file is shortcut type */
|
||||
+ bool isMountable_ : 1; /* TRUE if file is mountable type */
|
||||
bool isAccessible_ : 1; /* TRUE if can be read by user */
|
||||
bool isWritable_ : 1; /* TRUE if can be written to by user */
|
||||
bool isDeletable_ : 1; /* TRUE if can be deleted by user */
|
@ -1,29 +0,0 @@
|
||||
Description: Fix launching desktop files
|
||||
Author: Tsu Jan <tsujan2000@gmail.com>
|
||||
Applied-Upstream: https://github.com/lxqt/libfm-qt/commit/9af480812bdef4a7cca7db7416b24d96b179ebf1
|
||||
Last-Update: 2018-11-21
|
||||
--- a/src/core/basicfilelauncher.cpp
|
||||
+++ b/src/core/basicfilelauncher.cpp
|
||||
@@ -250,7 +250,21 @@ bool BasicFileLauncher::launchDesktopEnt
|
||||
it cannot be launched in fact */
|
||||
|
||||
if(app) {
|
||||
- return launchWithApp(app, paths, ctx);
|
||||
+ // don't call launchWithApp() because it calls g_app_info_launch_uris(),
|
||||
+ // which uses the hard-coded terminal list of GLib -> gdesktopappinfo.c
|
||||
+ GList* uris = nullptr;
|
||||
+ for(auto& path : paths) {
|
||||
+ auto uri = path.uri();
|
||||
+ uris = g_list_prepend(uris, uri.release());
|
||||
+ }
|
||||
+ GErrorPtr err;
|
||||
+ ret = bool(fm_app_info_launch(app, uris, ctx, &err));
|
||||
+ g_list_foreach(uris, reinterpret_cast<GFunc>(g_free), nullptr);
|
||||
+ g_list_free(uris);
|
||||
+ if(!ret) {
|
||||
+ // FIXME: show error for all files
|
||||
+ showError(ctx, err, paths[0]);
|
||||
+ }
|
||||
}
|
||||
else {
|
||||
QString msg = QObject::tr("Invalid desktop entry file: '%1'").arg(desktopEntryName);
|
@ -1,52 +0,0 @@
|
||||
Description: Use window text color for places view
|
||||
Author: tsujan <tsujan2000@gmail.com>
|
||||
Origin: upstream
|
||||
Bug: https://github.com/lxqt/pcmanfm-qt/issues/696
|
||||
Applied-Upstream: commit:87df010
|
||||
Last-Update: 2018-07-14
|
||||
--- a/src/folderitemdelegate.cpp
|
||||
+++ b/src/folderitemdelegate.cpp
|
||||
@@ -361,7 +361,8 @@ QWidget* FolderItemDelegate::createEdito
|
||||
// ensure that its background isn't transparent (on the side-pane)
|
||||
QWidget* editor = QStyledItemDelegate::createEditor(parent, option, index);
|
||||
QPalette p = editor->palette();
|
||||
- p.setColor(QPalette::Base, QApplication::palette().color(QPalette::Base));
|
||||
+ p.setColor(QPalette::Text, qApp->palette().text().color());
|
||||
+ p.setColor(QPalette::Base, qApp->palette().color(QPalette::Base));
|
||||
editor->setPalette(p);
|
||||
return editor;
|
||||
}
|
||||
--- a/src/placesview.cpp
|
||||
+++ b/src/placesview.cpp
|
||||
@@ -131,13 +131,6 @@ PlacesView::PlacesView(QWidget* parent):
|
||||
setHeaderHidden(true);
|
||||
setIndentation(12);
|
||||
|
||||
- /* merge with the surroundings */
|
||||
- setFrameShape(QFrame::NoFrame);
|
||||
- QPalette p = palette();
|
||||
- p.setColor(QPalette::Base, QColor(Qt::transparent));
|
||||
- setPalette(p);
|
||||
- viewport()->setAutoFillBackground(false);
|
||||
-
|
||||
connect(this, &QTreeView::clicked, this, &PlacesView::onClicked);
|
||||
connect(this, &QTreeView::pressed, this, &PlacesView::onPressed);
|
||||
|
||||
--- a/src/sidepane.cpp
|
||||
+++ b/src/sidepane.cpp
|
||||
@@ -158,6 +158,15 @@ void SidePane::setMode(Mode mode) {
|
||||
switch(mode) {
|
||||
case ModePlaces: {
|
||||
PlacesView* placesView = new Fm::PlacesView(this);
|
||||
+
|
||||
+ // visually merge it with its surroundings
|
||||
+ placesView->setFrameShape(QFrame::NoFrame);
|
||||
+ QPalette p = placesView->palette();
|
||||
+ p.setColor(QPalette::Base, QColor(Qt::transparent));
|
||||
+ p.setColor(QPalette::Text, p.color(QPalette::WindowText));
|
||||
+ placesView->setPalette(p);
|
||||
+ placesView->viewport()->setAutoFillBackground(false);
|
||||
+
|
||||
view_ = placesView;
|
||||
placesView->restoreHiddenItems(restorableHiddenPlaces_);
|
||||
placesView->setIconSize(iconSize_);
|
@ -1,373 +0,0 @@
|
||||
Description: Move the Qt file dialog helper into libfm-qt.
|
||||
Author: Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
Origin: upstream
|
||||
Applied-Upstream: commit:cc63bc7
|
||||
Last-Update: 2018-07-30
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -83,6 +83,7 @@ set(libfm_SRCS
|
||||
filedialog.cpp
|
||||
fm-search.c # might be moved to libfm later
|
||||
xdndworkaround.cpp
|
||||
+ filedialoghelper.cpp
|
||||
)
|
||||
|
||||
set(libfm_UIS
|
||||
--- /dev/null
|
||||
+++ b/src/filedialoghelper.cpp
|
||||
@@ -0,0 +1,290 @@
|
||||
+#include "filedialoghelper.h"
|
||||
+
|
||||
+#include "libfmqt.h"
|
||||
+#include "filedialog.h"
|
||||
+
|
||||
+#include <QWindow>
|
||||
+#include <QDebug>
|
||||
+#include <QTimer>
|
||||
+#include <QSettings>
|
||||
+#include <QtGlobal>
|
||||
+
|
||||
+#include <memory>
|
||||
+
|
||||
+namespace Fm {
|
||||
+
|
||||
+inline static const QString viewModeToString(Fm::FolderView::ViewMode value);
|
||||
+inline static Fm::FolderView::ViewMode viewModeFromString(const QString& str);
|
||||
+
|
||||
+FileDialogHelper::FileDialogHelper() {
|
||||
+ // can only be used after libfm-qt initialization
|
||||
+ dlg_ = std::unique_ptr<Fm::FileDialog>(new Fm::FileDialog());
|
||||
+ connect(dlg_.get(), &Fm::FileDialog::accepted, [this]() {
|
||||
+ saveSettings();
|
||||
+ accept();
|
||||
+ });
|
||||
+ connect(dlg_.get(), &Fm::FileDialog::rejected, [this]() {
|
||||
+ saveSettings();
|
||||
+ reject();
|
||||
+ });
|
||||
+
|
||||
+ connect(dlg_.get(), &Fm::FileDialog::fileSelected, this, &FileDialogHelper::fileSelected);
|
||||
+ connect(dlg_.get(), &Fm::FileDialog::filesSelected, this, &FileDialogHelper::filesSelected);
|
||||
+ connect(dlg_.get(), &Fm::FileDialog::currentChanged, this, &FileDialogHelper::currentChanged);
|
||||
+ connect(dlg_.get(), &Fm::FileDialog::directoryEntered, this, &FileDialogHelper::directoryEntered);
|
||||
+ connect(dlg_.get(), &Fm::FileDialog::filterSelected, this, &FileDialogHelper::filterSelected);
|
||||
+}
|
||||
+
|
||||
+FileDialogHelper::~FileDialogHelper() {
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::exec() {
|
||||
+ dlg_->exec();
|
||||
+}
|
||||
+
|
||||
+bool FileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow* parent) {
|
||||
+ dlg_->setAttribute(Qt::WA_NativeWindow, true); // without this, sometimes windowHandle() will return nullptr
|
||||
+
|
||||
+ dlg_->setWindowFlags(windowFlags);
|
||||
+ dlg_->setWindowModality(windowModality);
|
||||
+
|
||||
+ // Reference: KDE implementation
|
||||
+ // https://github.com/KDE/plasma-integration/blob/master/src/platformtheme/kdeplatformfiledialoghelper.cpp
|
||||
+ dlg_->windowHandle()->setTransientParent(parent);
|
||||
+
|
||||
+ applyOptions();
|
||||
+
|
||||
+ loadSettings();
|
||||
+ // central positioning with respect to the parent window
|
||||
+ if(parent && parent->isVisible()) {
|
||||
+ dlg_->move(parent->x() + (parent->width() - dlg_->width()) / 2,
|
||||
+ parent->y() + (parent->height() - dlg_->height()) / 2);
|
||||
+ }
|
||||
+
|
||||
+ // NOTE: the timer here is required as a workaround borrowed from KDE. Without this, the dialog UI will be blocked.
|
||||
+ // QFileDialog calls our platform plugin to show our own native file dialog instead of showing its widget.
|
||||
+ // However, it still creates a hidden dialog internally, and then make it modal.
|
||||
+ // So user input from all other windows that are not the children of the QFileDialog widget will be blocked.
|
||||
+ // This includes our own dialog. After the return of this show() method, QFileDialog creates its own window and
|
||||
+ // then make it modal, which blocks our UI. The timer schedule a delayed popup of our file dialog, so we can
|
||||
+ // show again after QFileDialog and override the modal state. Then our UI can be unblocked.
|
||||
+ QTimer::singleShot(0, dlg_.get(), &QDialog::show);
|
||||
+ dlg_->setFocus();
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::hide() {
|
||||
+ dlg_->hide();
|
||||
+}
|
||||
+
|
||||
+bool FileDialogHelper::defaultNameFilterDisables() const {
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::setDirectory(const QUrl& directory) {
|
||||
+ dlg_->setDirectory(directory);
|
||||
+}
|
||||
+
|
||||
+QUrl FileDialogHelper::directory() const {
|
||||
+ return dlg_->directory();
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::selectFile(const QUrl& filename) {
|
||||
+ dlg_->selectFile(filename);
|
||||
+}
|
||||
+
|
||||
+QList<QUrl> FileDialogHelper::selectedFiles() const {
|
||||
+ return dlg_->selectedFiles();
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::setFilter() {
|
||||
+ // FIXME: what's this?
|
||||
+ // The gtk+ 3 file dialog helper in Qt5 update options in this method.
|
||||
+ applyOptions();
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::selectNameFilter(const QString& filter) {
|
||||
+ dlg_->selectNameFilter(filter);
|
||||
+}
|
||||
+
|
||||
+#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||
+QString FileDialogHelper::selectedMimeTypeFilter() const {
|
||||
+ return dlg_->selectedMimeTypeFilter();
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::selectMimeTypeFilter(const QString& filter) {
|
||||
+ dlg_->selectMimeTypeFilter(filter);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+QString FileDialogHelper::selectedNameFilter() const {
|
||||
+ return dlg_->selectedNameFilter();
|
||||
+}
|
||||
+
|
||||
+bool FileDialogHelper::isSupportedUrl(const QUrl& url) const {
|
||||
+ return dlg_->isSupportedUrl(url);
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::applyOptions() {
|
||||
+ auto& opt = options();
|
||||
+
|
||||
+ // set title
|
||||
+ if(opt->windowTitle().isEmpty()) {
|
||||
+ dlg_->setWindowTitle(opt->acceptMode() == QFileDialogOptions::AcceptOpen ? tr("Open File")
|
||||
+ : tr("Save File"));
|
||||
+ }
|
||||
+ else {
|
||||
+ dlg_->setWindowTitle(opt->windowTitle());
|
||||
+ }
|
||||
+
|
||||
+ dlg_->setFilter(opt->filter());
|
||||
+ dlg_->setFileMode(QFileDialog::FileMode(opt->fileMode()));
|
||||
+ dlg_->setAcceptMode(QFileDialog::AcceptMode(opt->acceptMode())); // also sets a default label for accept button
|
||||
+ // bool useDefaultNameFilters() const;
|
||||
+ dlg_->setNameFilters(opt->nameFilters());
|
||||
+ if(!opt->mimeTypeFilters().empty()) {
|
||||
+ dlg_->setMimeTypeFilters(opt->mimeTypeFilters());
|
||||
+ }
|
||||
+
|
||||
+ dlg_->setDefaultSuffix(opt->defaultSuffix());
|
||||
+ // QStringList history() const;
|
||||
+
|
||||
+ // explicitly set labels
|
||||
+ for(int i = 0; i < QFileDialogOptions::DialogLabelCount; ++i) {
|
||||
+ auto label = static_cast<QFileDialogOptions::DialogLabel>(i);
|
||||
+ if(opt->isLabelExplicitlySet(label)) {
|
||||
+ dlg_->setLabelText(static_cast<QFileDialog::DialogLabel>(label), opt->labelText(label));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ auto url = opt->initialDirectory();
|
||||
+ if(url.isValid()) {
|
||||
+ dlg_->setDirectory(url);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||
+ auto filter = opt->initiallySelectedMimeTypeFilter();
|
||||
+ if(!filter.isEmpty()) {
|
||||
+ selectMimeTypeFilter(filter);
|
||||
+ }
|
||||
+ else {
|
||||
+ filter = opt->initiallySelectedNameFilter();
|
||||
+ if(!filter.isEmpty()) {
|
||||
+ selectNameFilter(opt->initiallySelectedNameFilter());
|
||||
+ }
|
||||
+ }
|
||||
+#else
|
||||
+ auto filter = opt->initiallySelectedNameFilter();
|
||||
+ if(!filter.isEmpty()) {
|
||||
+ selectNameFilter(filter);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ auto selectedFiles = opt->initiallySelectedFiles();
|
||||
+ for(const auto& selectedFile: selectedFiles) {
|
||||
+ selectFile(selectedFile);
|
||||
+ }
|
||||
+ // QStringList supportedSchemes() const;
|
||||
+}
|
||||
+
|
||||
+static const QString viewModeToString(Fm::FolderView::ViewMode value) {
|
||||
+ QString ret;
|
||||
+ switch(value) {
|
||||
+ case Fm::FolderView::DetailedListMode:
|
||||
+ default:
|
||||
+ ret = QLatin1String("Detailed");
|
||||
+ break;
|
||||
+ case Fm::FolderView::CompactMode:
|
||||
+ ret = QLatin1String("Compact");
|
||||
+ break;
|
||||
+ case Fm::FolderView::IconMode:
|
||||
+ ret = QLatin1String("Icon");
|
||||
+ break;
|
||||
+ case Fm::FolderView::ThumbnailMode:
|
||||
+ ret = QLatin1String("Thumbnail");
|
||||
+ break;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+Fm::FolderView::ViewMode viewModeFromString(const QString& str) {
|
||||
+ Fm::FolderView::ViewMode ret;
|
||||
+ if(str == QLatin1String("Detailed")) {
|
||||
+ ret = Fm::FolderView::DetailedListMode;
|
||||
+ }
|
||||
+ else if(str == QLatin1String("Compact")) {
|
||||
+ ret = Fm::FolderView::CompactMode;
|
||||
+ }
|
||||
+ else if(str == QLatin1String("Icon")) {
|
||||
+ ret = Fm::FolderView::IconMode;
|
||||
+ }
|
||||
+ else if(str == QLatin1String("Thumbnail")) {
|
||||
+ ret = Fm::FolderView::ThumbnailMode;
|
||||
+ }
|
||||
+ else {
|
||||
+ ret = Fm::FolderView::DetailedListMode;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::loadSettings() {
|
||||
+ QSettings settings(QSettings::UserScope, "lxqt", "filedialog");
|
||||
+ settings.beginGroup ("Sizes");
|
||||
+ dlg_->resize(settings.value("WindowSize", QSize(700, 500)).toSize());
|
||||
+ dlg_->setSplitterPos(settings.value("SplitterPos", 200).toInt());
|
||||
+ settings.endGroup();
|
||||
+
|
||||
+ settings.beginGroup ("View");
|
||||
+ dlg_->setViewMode(viewModeFromString(settings.value("Mode", "Detailed").toString()));
|
||||
+ settings.endGroup();
|
||||
+}
|
||||
+
|
||||
+void FileDialogHelper::saveSettings() {
|
||||
+ QSettings settings(QSettings::UserScope, "lxqt", "filedialog");
|
||||
+ settings.beginGroup ("Sizes");
|
||||
+ QSize windowSize = dlg_->size();
|
||||
+ if(settings.value("WindowSize") != windowSize) { // no redundant write
|
||||
+ settings.setValue("WindowSize", windowSize);
|
||||
+ }
|
||||
+ int splitterPos = dlg_->splitterPos();
|
||||
+ if(settings.value("SplitterPos") != splitterPos) {
|
||||
+ settings.setValue("SplitterPos", splitterPos);
|
||||
+ }
|
||||
+ settings.endGroup();
|
||||
+
|
||||
+ settings.beginGroup ("View");
|
||||
+ QString mode = viewModeToString(dlg_->viewMode());
|
||||
+ if(settings.value("Mode") != mode) {
|
||||
+ settings.setValue("Mode", mode);
|
||||
+ }
|
||||
+ settings.endGroup();
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+FileDialogPlugin::FileDialogPlugin() {
|
||||
+
|
||||
+}
|
||||
+
|
||||
+QPlatformFileDialogHelper *FileDialogPlugin::createHelper() {
|
||||
+ return new FileDialogHelper();
|
||||
+}
|
||||
+*/
|
||||
+
|
||||
+} // namespace Fm
|
||||
+
|
||||
+
|
||||
+QPlatformFileDialogHelper *createFileDialogHelper() {
|
||||
+ // When a process has this environment set, that means glib event loop integration is disabled.
|
||||
+ // In this case, libfm just won't work. So let's disable the file dialog helper and return nullptr.
|
||||
+ if(qgetenv("QT_NO_GLIB") == "1") {
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+
|
||||
+ static std::unique_ptr<Fm::LibFmQt> libfmQtContext_;
|
||||
+ if(!libfmQtContext_) {
|
||||
+ // initialize libfm-qt only once
|
||||
+ libfmQtContext_ = std::unique_ptr<Fm::LibFmQt>{new Fm::LibFmQt()};
|
||||
+ }
|
||||
+ return new Fm::FileDialogHelper{};
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/src/filedialoghelper.h
|
||||
@@ -0,0 +1,62 @@
|
||||
+#ifndef FILEDIALOGHELPER_H
|
||||
+#define FILEDIALOGHELPER_H
|
||||
+
|
||||
+#include "libfmqtglobals.h"
|
||||
+#include <qpa/qplatformdialoghelper.h> // this private header is subject to changes
|
||||
+#include <memory>
|
||||
+
|
||||
+namespace Fm {
|
||||
+
|
||||
+class FileDialog;
|
||||
+
|
||||
+class LIBFM_QT_API FileDialogHelper : public QPlatformFileDialogHelper {
|
||||
+ Q_OBJECT
|
||||
+
|
||||
+public:
|
||||
+ FileDialogHelper();
|
||||
+
|
||||
+ virtual ~FileDialogHelper();
|
||||
+
|
||||
+ // QPlatformDialogHelper
|
||||
+ void exec() override;
|
||||
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
|
||||
+ void hide() override;
|
||||
+
|
||||
+ // QPlatformFileDialogHelper
|
||||
+ bool defaultNameFilterDisables() const override;
|
||||
+ void setDirectory(const QUrl &directory) override;
|
||||
+ QUrl directory() const override;
|
||||
+ void selectFile(const QUrl &filename) override;
|
||||
+ QList<QUrl> selectedFiles() const override;
|
||||
+ void setFilter() override;
|
||||
+ void selectNameFilter(const QString &filter) override;
|
||||
+#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||
+ QString selectedMimeTypeFilter() const override;
|
||||
+ void selectMimeTypeFilter(const QString &filter) override;
|
||||
+#endif
|
||||
+ QString selectedNameFilter() const override;
|
||||
+
|
||||
+ bool isSupportedUrl(const QUrl &url) const override;
|
||||
+
|
||||
+private:
|
||||
+ void applyOptions();
|
||||
+ void loadSettings();
|
||||
+ void saveSettings();
|
||||
+
|
||||
+private:
|
||||
+ std::unique_ptr<Fm::FileDialog> dlg_;
|
||||
+};
|
||||
+
|
||||
+} // namespace Fm
|
||||
+
|
||||
+// export a C API without C++ name mangling so others can dynamically load libfm-qt at runtime
|
||||
+// to call this API and get a new QPlatformFileDialogHelper object.
|
||||
+
|
||||
+extern "C" {
|
||||
+
|
||||
+// if the process calling this API fail to load libfm-qt, nullptr will be returned instead.
|
||||
+LIBFM_QT_API QPlatformFileDialogHelper* createFileDialogHelper();
|
||||
+
|
||||
+}
|
||||
+
|
||||
+#endif // FILEDIALOGHELPER_H
|
@ -1,7 +0,0 @@
|
||||
add-lxqt-archiver-integration.patch
|
||||
fix-incorrect-file-info-handling-1.patch
|
||||
fix-incorrect-file-info-handling-2.patch
|
||||
fix-places-font-color.patch
|
||||
move-in-file-dialog.patch
|
||||
add-metadata-for-trusting-executables.patch
|
||||
fix-launching-desktop-files.patch
|
Loading…
Reference in new issue