Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FileBrowser: "Open containing folder" automatically selects file in the OS's file manager #7700

Open
wants to merge 91 commits into
base: master
Choose a base branch
from

Conversation

AW1534
Copy link
Contributor

@AW1534 AW1534 commented Feb 10, 2025

Introduces a new helper class FileManagerServices to manage file selection across different platforms (Windows, macOS, Linux, and other *nix operating systems with xdg). Includes methods to open and select files or directories using the default file manager on the respective platform.

User-Facing Changes:

  • Replace "open containing folder" in the file context menu with "Show in [Explorer/Finder/file manager]" respectively for different Operating Systems. This not only opens the containing folder, but highlights the file if supported by the File Manager.
  • Adds "Open in [Explorer/Finder/file manager]" option to Folder context menu.

Other Changes:

  • Added FileManagerServices.h and FileManagerServices.cpp to define and implement the file selecting functionality.
  • Modified FileBrowser.cpp to integrate FileManagerServices for opening containing folders and directories.
  • FileManagerServices::canSelect method to check if file selection is possible.
  • FileManagerServices::select method to select files or directories using platform-specific commands.
  • Handling of different file managers on Linux by checking support for the --select option.

@AW1534
Copy link
Contributor Author

AW1534 commented Feb 10, 2025

Turns out my code was fine, its just that without LV2 support, item->isTrack() returns the wrong value. This causes the context menu to always display the options for presets (send to instrument track).

Example

image

Works fine with the CI Built binaries. I'll be removing some debug code and opening this PR up for review.

@AW1534 AW1534 marked this pull request as ready for review February 10, 2025 02:48
@AW1534 AW1534 marked this pull request as draft February 10, 2025 20:01
@AW1534 AW1534 marked this pull request as ready for review February 10, 2025 20:49
src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
@sakertooth
Copy link
Contributor

Sticking to saying "Open containing folder" regardless of OS and opening it using the native file manager (if any) is probably the way to go IMO. It's a lot simpler that way at the cost of little.

Also, I'm confused on what this has to do with highlighting files in the FileBrowser? It seems like if anything, the goal is to highlight files in the file manager on the OS once "Open containing folder" is pressed (which IMO isn't a requirement if it means not having to deal with all the OS-specific file managers)

Additionally, I think we should be using something like QDesktopServices::openUrl and not worrying about all the OS-specific file managers and whatnot.

@AW1534
Copy link
Contributor Author

AW1534 commented Feb 14, 2025

Sticking to saying "Open containing folder" regardless of OS and opening it using the native file manager (if any) is probably the way to go IMO. It's a lot simpler that way at the cost of little.

Unless you have other concerns, the only downside is maintainability but that should've been fixed in the latest commit.

Also, I'm confused on what this has to do with highlighting files in the FileBrowser? It seems like if anything, the goal is to highlight files in the file manager on the OS once "Open containing folder" is pressed (which IMO isn't a requirement if it means not having to deal with all the OS-specific file managers)

You're right, this PR is badly titled.

Additionally, I think we should be using something like QDesktopServices::openUrl and not worrying about all the OS-specific file managers and whatnot.

I really do dislike using openUrl. It was really slow for me (like ~5 second wait time) when I was on linux, But almost instant with my PR.

@AW1534 AW1534 changed the title Highlight files in FileBrowser highlight files in the file manager on the OS Feb 14, 2025
@tresf
Copy link
Member

tresf commented Feb 14, 2025

Sticking to saying "Open containing folder" regardless of OS and opening it using the native file manager (if any) is probably the way to go IMO. It's a lot simpler that way at the cost of little.

@sakertooth Many applications have shims that do as the OP is suggesting. I've noticed that this trend has become an unofficial standard over the years for polished software. For example, my IDEs tend to do this same thing and when reading the source code, the techniques are often identical to the OP's. The larger the folder contents, the more useful this feature can become as the file manager will navigate directly to the file that was requested. This is a very well received feature IMO.

@tresf
Copy link
Member

tresf commented Feb 14, 2025

Additionally, I think we should be using something like QDesktopServices::openUrl and not worrying about all the OS-specific file managers and whatnot.

I really do dislike using openUrl. It was really slow for me (like ~5 second wait time) when I was on linux, But almost instant with my PR.

I haven't benchmarked openUrl, but I wholeheartedly agree. A pragmatic solution would leverage the underlying C++ APIs, but Linux lacks a consistently shared framework to leverage something like this and Windows + macOS have the support build into the CLI of their file managers, so this really is the simplest approach for 99% of users. For those 1% of users (e.g. Haiku) we'll need to simply fallback to Qt's inferior handling.

@tresf
Copy link
Member

tresf commented Feb 14, 2025

@sakertooth @AW1534 how much sense would it be to subclass QDesktopServices into our own implementation and take this logic right out of FileBrowser? This would allow us to eventually leverage the same logic in other/future areas of the codebase and help keep FileBrowser clean of our own implementation.

The code also reads more portable anyway since it uses non-LMMS precompiler definitions and focuses on standard ones (e.g. _WIN32, __APPLE__) which smells a lot like a general good utility class that other projects can copy/pasta.

Copy link
Contributor

@sakertooth sakertooth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless you have other concerns, the only downside is maintainability but that should've been fixed in the latest commit.

Just took another peek at the code and it's a lot better. In particular, we aren't making so many references to platform-specific applications like Thunar, Nautilus, Dolphin, etc. The use of xdg-mime and xdg-open is a nice solution.

Code-wise, I think we can apply some formatting to the new changes, and I think some simplifications can be made. I can help out a bit if you will allow it.

@sakertooth
Copy link
Contributor

sakertooth commented Feb 14, 2025

@sakertooth @AW1534 how much sense would it be to subclass QDesktopServices into our own implementation and take this logic right out of FileBrowser? This would allow us to eventually leverage the same logic in other/future areas of the codebase and help keep FileBrowser clean of our own implementation.

The code also reads more portable anyway since it uses non-LMMS precompiler definitions and focuses on standard ones (e.g. _WIN32, APPLE) which smells a lot like a general good utility class that other projects can copy/pasta.

It seems like we merely fallback to using QDesktopServices, so there shouldn't be a need to extend from it. However, I do like the idea of putting all of the implementation specific code in one tidy place, which then FileBrowser can reference.

src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
@AW1534
Copy link
Contributor Author

AW1534 commented Feb 14, 2025

@sakertooth @AW1534 how much sense would it be to subclass QDesktopServices into our own implementation and take this logic right out of FileBrowser? This would allow us to eventually leverage the same logic in other/future areas of the codebase and help keep FileBrowser clean of our own implementation.

The code also reads more portable anyway since it uses non-LMMS precompiler definitions and focuses on standard ones (e.g. _WIN32, __APPLE__) which smells a lot like a general good utility class that other projects can copy/pasta.

This is a great idea which i'm willing to do, but as @sakertooth said, it probably doesnt need to extend from QDesktopServices

Co-authored-by: Tres Finocchiaro <[email protected]>

#if !defined(_WIN32) && !defined(__APPLE__)

bool supportsSelectOption(const QString &fileManager) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be refactored to run once on construction only. It should not need to be run each time a file is opened.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point. I'll do this after i move the code out of the FileBrowser class though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I may have to rethink this logic, since it has a blocking operation in it... I might need some help from @sakertooth on how to refactor this properly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this resolved? since it's all cached anyway

@AW1534
Copy link
Contributor Author

AW1534 commented Feb 14, 2025

Code-wise, I think we can apply some formatting to the new changes, and I think some simplifications can be made. I can help out a bit if you will allow it.

absolutely, I'll apply any suggestions you give me

src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
@AW1534
Copy link
Contributor Author

AW1534 commented Feb 18, 2025

done

src/gui/FileRevealer.cpp Outdated Show resolved Hide resolved
Co-authored-by: Tres Finocchiaro <[email protected]>
@tresf tresf self-requested a review February 18, 2025 01:56
src/gui/FileRevealer.cpp Outdated Show resolved Hide resolved
[=, this]{ openContainingFolder(file); }
);
contextMenu.addAction(QIcon(embed::getIconPixmap("folder")), tr("Show in %1").arg(fileManager),
[=, this] { FileRevealer::reveal(fileName); });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[=, this] { FileRevealer::reveal(fileName); });
[=] { FileRevealer::reveal(fileName); });

case TypeDirectoryItem: {
auto dir = dynamic_cast<Directory*>(item);
QString dirname = dir->fullName();
contextMenu.addAction(QIcon(embed::getIconPixmap("folder")), tr("Open in %1").arg(fileManager), [=, this] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
contextMenu.addAction(QIcon(embed::getIconPixmap("folder")), tr("Open in %1").arg(fileManager), [=, this] {
contextMenu.addAction(QIcon(embed::getIconPixmap("folder")), tr("Open in %1").arg(fileManager), [=] {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@tresf tresf Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clang (macOS) will error (-Werror) if they're left for areas that they're unused. The only unused this that must be removed are the Actions that no longer call a FileBrowser function now, which are the calls to openDir and reveal.

If still gcc complains with only the two removals, we can leave it in. Clang is set to not treat warnings as errors in our CI so this is fine.

@regulus79
Copy link
Contributor

Testing on Arch Linux with GNOME.
My default file manager is Nautilus.

Overall it seems to work pretty well.

I noticed that when opening factory folders (which do not have a corresponding user folder) by rightclicking and selecting "Open in file manager", Nautilus shows an error:

image
However, when selecting "Show in file manager", it works fine. Or if you show one of the files within that folder, it works and opens the right folder.

Also, I noticed that when opening files in a different folder than a previous file opened, a new file manager window opens. That actually kinda makes sense, so maybe that's intentional?

Minor but I noticed the terminal output gets spammed with

** Message: 19:56:43.537: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:56:51.049: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:57:06.018: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:57:18.318: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:57:20.134: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:57:46.400: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:57:51.381: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:57:54.024: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:57:57.205: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:58:03.053: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:59:36.335: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 19:59:51.021: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:09.595: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:15.518: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:19.555: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:26.788: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:35.608: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:37.341: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:39.241: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:41.224: Connecting to org.freedesktop.Tracker3.Miner.Files
** Message: 20:02:43.578: Connecting to org.freedesktop.Tracker3.Miner.Files

@tresf
Copy link
Member

tresf commented Feb 18, 2025

However, when selecting "Show in file manager", it works fine. Or if you show one of the files within that folder, it works and opens the right folder.

@regulus79 thanks for the testing! The stock folders are broken because of this:

No application knows how to open URL data:/projects/demos/

It's a pretty quick fix. @AW1534 There appears to be an implicit conversion of QString -> QFileInfo for reveal(), but not for openDir(). Let's please match that function signature and add item.canonicalFilePath() similar to reveal(). I've tested this locally and it should fix the problem.

Minor but I noticed the terminal output gets spammed with
** Message: 19:56:43.537: Connecting to org.freedesktop.Tracker3.Miner.Files

This is going to be a bit harder to fix. We can suppress all errors with something like https://doc.qt.io/qt-5/qprocess.html#setStandardErrorFile, but this may make it harder for situation like finding the above error. It's sad how noisy Linux GUI apps are.

Also, I noticed that when opening files in a different folder than a previous file opened, a new file manager window opens. That actually kinda makes sense, so maybe that's intentional?

macOS will re-use an existing window, but I believe this functionality is unique to macOS (macOS tracks open applications for this reason).. (Edit: No, macOS does the same thing as Linux) I do not believe there's a way around this easily. Notice nautilus has an --new-window flag, but we do not use it, but it still behaves this way. I don't think we have can easily change this.

@AW1534
Copy link
Contributor Author

AW1534 commented Feb 18, 2025

should be good now

src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
src/gui/FileBrowser.cpp Outdated Show resolved Hide resolved
@tresf tresf requested a review from bratpeki February 18, 2025 17:18
@bratpeki bratpeki self-assigned this Feb 18, 2025
@bratpeki
Copy link
Member

Downloading the MSVC and MinGW builds now!

@bratpeki
Copy link
Member

Everything works on both MinGW and MSVC Windows builds! 🎉

The right click doesn't work for "--- Factory files ---", as expected, great job.
Speaking of which, why do we need that "file"?

@AW1534
Copy link
Contributor Author

AW1534 commented Feb 18, 2025

Speaking of which, why do we need that "file"?

Yeah, it seems quite pointless. If we want to indicate which files are factory I think changing the color of factory files is a better option

@bratpeki
Copy link
Member

It's cool, I keep track of LMMS issues, I'll add this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement gui needs code review A functional code review is currently required for this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants