This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 25f1d68b97 Add context menu to open file in os file explorer #6564
(#6645)
25f1d68b97 is described below
commit 25f1d68b97d420add23cbf657c6353d7c00eb9d8
Author: Nicolas Adment <[email protected]>
AuthorDate: Thu Feb 26 08:43:40 2026 +0100
Add context menu to open file in os file explorer #6564 (#6645)
---
.../main/java/org/apache/hop/core/vfs/HopVfs.java | 9 ++++++
.../perspective/explorer/ExplorerPerspective.java | 34 ++++++++++++++++++++++
.../org/apache/hop/ui/util/EnvironmentUtils.java | 32 ++++++++++++++++++++
.../explorer/messages/messages_en_US.properties | 3 ++
4 files changed, 78 insertions(+)
diff --git a/core/src/main/java/org/apache/hop/core/vfs/HopVfs.java
b/core/src/main/java/org/apache/hop/core/vfs/HopVfs.java
index f6f85fc44e..a2313dc5f3 100644
--- a/core/src/main/java/org/apache/hop/core/vfs/HopVfs.java
+++ b/core/src/main/java/org/apache/hop/core/vfs/HopVfs.java
@@ -376,6 +376,15 @@ public class HopVfs {
}
}
+ public static boolean isLocalFileSystem(String path) {
+ try {
+ FileObject fileObject = getFileObject(path);
+ return fileObject instanceof LocalFile;
+ } catch (HopFileException e) {
+ return false;
+ }
+ }
+
public static InputStream getInputStream(FileObject fileObject) throws
FileSystemException {
FileContent content = fileObject.getContent();
return content.getInputStream();
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
index 45a3ee9b91..5d23092799 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
@@ -100,6 +100,7 @@ import
org.apache.hop.ui.hopgui.perspective.explorer.file.IExplorerFileTypeHandl
import org.apache.hop.ui.hopgui.perspective.explorer.file.types.FolderFileType;
import
org.apache.hop.ui.hopgui.perspective.explorer.file.types.GenericFileType;
import org.apache.hop.ui.hopgui.shared.CanvasZoomHelper;
+import org.apache.hop.ui.util.EnvironmentUtils;
import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.engine.IWorkflowEngine;
import org.eclipse.swt.SWT;
@@ -179,6 +180,8 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
public static final String CONTEXT_MENU_OPEN =
"ExplorerPerspective-ContextMenu-10100-Open";
public static final String CONTEXT_MENU_OPEN_AS_TEXT =
"ExplorerPerspective-ContextMenu-10101-OpenAsText";
+ public static final String CONTEXT_MENU_OPEN_IN_EXPLORER =
+ "ExplorerPerspective-ContextMenu-10102-OpenInExplorer";
public static final String CONTEXT_MENU_RENAME =
"ExplorerPerspective-ContextMenu-10300-Rename";
public static final String CONTEXT_MENU_COPY_NAME =
"ExplorerPerspective-ContextMenu-10400-CopyName";
@@ -524,6 +527,11 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
if (openAsTextItem != null) {
openAsTextItem.setEnabled(selection.length == 1 && tif != null &&
!tif.folder);
}
+ MenuItem openInExplorerItem =
menuWidgets.findMenuItem(CONTEXT_MENU_OPEN_IN_EXPLORER);
+ if (openInExplorerItem != null) {
+ openInExplorerItem.setEnabled(HopVfs.isLocalFileSystem(tif.path));
+ }
+
menuWidgets.findMenuItem(CONTEXT_MENU_RENAME).setEnabled(selection.length == 1);
// Show the menu
@@ -1614,6 +1622,32 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
openFile(selection[0]);
}
+ @GuiMenuElement(
+ root = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ parentId = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ id = CONTEXT_MENU_OPEN_IN_EXPLORER,
+ label = "i18n::ExplorerPerspective.Menu.OpenInExplorer")
+ public void openFileInExplorer() {
+ TreeItem[] selection = tree.getSelection();
+ if (selection == null || selection.length == 0) {
+ return;
+ }
+
+ TreeItemFolder tif = (TreeItemFolder) selection[0].getData();
+ if (tif != null) {
+ try {
+ EnvironmentUtils.getInstance().openFileExplorer(tif.path);
+ } catch (Throwable e) {
+ new ErrorDialog(
+ getShell(),
+ BaseMessages.getString(PKG,
"ExplorerPerspective.Error.OpenFileInExplorer.Title"),
+ BaseMessages.getString(
+ PKG, "ExplorerPerspective.Error.OpenFileInExplorer.Message",
tif.path),
+ e);
+ }
+ }
+ }
+
@GuiMenuElement(
root = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
parentId = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
diff --git a/ui/src/main/java/org/apache/hop/ui/util/EnvironmentUtils.java
b/ui/src/main/java/org/apache/hop/ui/util/EnvironmentUtils.java
index f33e9d2f10..c53d126fbc 100644
--- a/ui/src/main/java/org/apache/hop/ui/util/EnvironmentUtils.java
+++ b/ui/src/main/java/org/apache/hop/ui/util/EnvironmentUtils.java
@@ -16,7 +16,9 @@
*/
package org.apache.hop.ui.util;
+import java.awt.Desktop;
import java.io.BufferedReader;
+import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
@@ -26,6 +28,7 @@ import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.logging.ILogChannel;
import org.apache.hop.core.logging.LogChannel;
import org.apache.hop.ui.core.PropsUi;
+import org.apache.hop.ui.core.widget.OsHelper;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
@@ -216,6 +219,35 @@ public class EnvironmentUtils {
return System.getProperty("HOP_WEB_THEME");
}
+ /** Open the file explorer based on OS and select the file */
+ public void openFileExplorer(String path) throws HopException {
+
+ if (path == null || path.isBlank()) {
+ return;
+ }
+
+ try {
+ if (OsHelper.isWindows()) {
+ // Open File Explorer on Windows
+ Runtime.getRuntime().exec("explorer.exe /select," + path);
+ } else if (OsHelper.isMac()) {
+ // Open Finder on Mac
+ Runtime.getRuntime().exec("open -R " + path);
+ } else if (Desktop.isDesktopSupported()) {
+ File file = new File(path);
+ if (file.exists()) {
+ // If it is a file, open the parent folder
+ if (file.isFile()) {
+ file = file.getParentFile();
+ }
+ Desktop.getDesktop().open(file);
+ }
+ }
+ } catch (IOException e) {
+ throw new HopException("Error opening file in explorer", e);
+ }
+ }
+
public void openUrl(String url) throws HopException {
if (isWeb()) {
try {
diff --git
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
index f0af81d93a..c94ecf6a0a 100644
---
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
@@ -34,12 +34,15 @@ ExplorerPerspective.Error.RootFolder.Header=Error
ExplorerPerspective.Error.RootFolder.Message=Error getting root folder/name of
explorer perspective
ExplorerPerspective.Error.TreeRefresh.Header=Error
ExplorerPerspective.Error.TreeRefresh.Message=Error refreshing file explorer
tree
+ExplorerPerspective.Error.OpenFileInExplorer.Title=Error
+ExplorerPerspective.Error.OpenFileInExplorer.Message=Error opening file in
explorer:\n''{0}''
ExplorerPerspective.GuiPlugin.Description=A file explorer for your current
project
ExplorerPerspective.Menu.CopyName=Copy name
ExplorerPerspective.Menu.CopyPath=Copy path
ExplorerPerspective.Menu.CreateFolder=Create folder
ExplorerPerspective.Menu.Delete=Delete
ExplorerPerspective.Menu.Open=Open
+ExplorerPerspective.Menu.OpenInExplorer=Open in explorer
ExplorerPerspective.Menu.Rename=Rename
ExplorerPerspective.Menu.ExpandAll=Expand All
ExplorerPerspective.Menu.CollapseAll=Collapse All