From 2849d58339c6ebd639061cf908b0842a4bf4fdd7 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Thu, 27 Nov 2025 22:46:14 +0100 Subject: [PATCH 01/33] Change logging --- sql12/core/doc/changes.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 3cac6986f..304dc96b3 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,7 +6,8 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: -Security: Introduced option to use a key password for encrypting Alias passwords. +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/73 + Security: Introduced option to use a key password for encrypting Alias passwords. When a key password is used SQuirreL can decrypt Alias-passwords only after the key password was entered. SQuirreL stores the key password in memory only. As a consequence the key password must be entered after SQuirreL was started and before an Alias, that uses password encryption, can be connected to. From 423d9b066e7d1629e170959f1d876e9e231a6d10 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Fri, 28 Nov 2025 18:01:00 +0100 Subject: [PATCH 02/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/74 Multiple selected Aliases can be selected and connected to. --- sql12/core/doc/changes.txt | 3 ++ .../client/gui/db/AliasesList.java | 21 ++++++---- .../squirrel_sql/client/gui/db/BaseList.java | 40 ++++++++++--------- .../client/gui/db/BaseListInternalFrame.java | 18 +++------ .../client/gui/db/DriversList.java | 13 +++--- .../client/gui/db/IAliasesList.java | 3 ++ .../client/gui/db/JListAliasesListImpl.java | 26 +++++++----- .../client/gui/db/JTreeAliasesListImpl.java | 12 +++++- .../action/ConnectToAliasAction.java | 14 +++---- 9 files changed, 86 insertions(+), 64 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 304dc96b3..7f9c795b5 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,9 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/74 + Multiple selected Aliases can be selected and connected to. + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/73 Security: Introduced option to use a key password for encrypting Alias passwords. When a key password is used SQuirreL can decrypt Alias-passwords only after the key password was entered. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesList.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesList.java index c85b06298..7d282aa24 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesList.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesList.java @@ -1,5 +1,13 @@ package net.sourceforge.squirrel_sql.client.gui.db; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JComponent; +import javax.swing.JPanel; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.WindowManager; @@ -7,13 +15,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; import net.sourceforge.squirrel_sql.fw.util.StringUtilities; -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.ArrayList; -import java.util.List; - /* * Copyright (C) 2001-2004 Colin Bell * colbell@users.sourceforge.net @@ -165,6 +166,12 @@ public SQLAlias getSelectedAlias(MouseEvent evt) return getCurrentImpl().getSelectedAlias(evt); } + @Override + public List getAllSelectedAliases() + { + return getCurrentImpl().getAllSelectedAliases(); + } + @Override public SQLAlias getLeadSelectionValue() { diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseList.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseList.java index 107ebdee1..f9d518742 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseList.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseList.java @@ -1,16 +1,18 @@ package net.sourceforge.squirrel_sql.client.gui.db; -import net.sourceforge.squirrel_sql.fw.gui.SortedListModel; -import net.sourceforge.squirrel_sql.client.ApplicationListener; -import net.sourceforge.squirrel_sql.client.IApplication; - -import javax.swing.*; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; -import java.awt.*; -import java.awt.event.MouseListener; +import java.awt.Dimension; +import java.awt.Point; import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; import java.util.ArrayList; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.fw.gui.SortedListModel; import net.sourceforge.squirrel_sql.fw.props.Props; public abstract class BaseList implements IBaseList @@ -27,10 +29,17 @@ public String getToolTipText(MouseEvent event) private JScrollPane _comp = new JScrollPane(_list); - public BaseList(SortedListModel sortedListModel, IApplication app) + public BaseList(SortedListModel sortedListModel, boolean allowMultipleSelection) { _list.setModel(sortedListModel); - getList().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + if(allowMultipleSelection) + { + getList().getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + } + else + { + getList().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } // Add listener to listen for items added/removed from list. _list.getModel().addListDataListener(new ListDataListener() @@ -51,14 +60,7 @@ public void contentsChanged(ListDataEvent evt) _comp.setPreferredSize(new Dimension(100, 100)); - app.addApplicationListener(new ApplicationListener() - { - public void saveApplicationState() - { - onSaveApplicationState(); - } - }); - + Main.getApplication().addApplicationListener(() -> onSaveApplicationState()); setSelIxFromPrefs(); } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseListInternalFrame.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseListInternalFrame.java index 6b4eb126c..2e841a12c 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseListInternalFrame.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/BaseListInternalFrame.java @@ -18,6 +18,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DockWidget; import net.sourceforge.squirrel_sql.fw.gui.BasePopupMenu; @@ -27,11 +33,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - abstract class BaseListInternalFrame extends DockWidget { private static final ILogger s_log = LoggerController.createLogger(BaseListInternalFrame.class); @@ -89,13 +90,6 @@ private void onMousePress(MouseEvent evt) { if (evt.isPopupTrigger()) { - - // If the user wants to select for Right mouse clicks then change the selection before popup appears - if (Main.getApplication().getSquirrelPreferences().getSelectOnRightMouseClick()) - { - _uiFactory.getList().selectListEntryAtPoint(evt.getPoint()); - } - if (_popupMenu == null) { _popupMenu = _uiFactory.getPopupMenu(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/DriversList.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/DriversList.java index dfb632538..04f72afdc 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/DriversList.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/DriversList.java @@ -18,18 +18,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.ToolTipManager; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences; import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; import net.sourceforge.squirrel_sql.fw.sql.ISQLDriver; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; /** * This is a JList that dispays all the ISQLDriver * objects. @@ -61,7 +60,7 @@ public class DriversList extends BaseList implements IDriversList */ public DriversList(IApplication app) throws IllegalArgumentException { - super(new DriversListModel(), app); + super(new DriversListModel(), false); _app = app; _model = (DriversListModel) getList().getModel(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/IAliasesList.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/IAliasesList.java index bcaccd95c..e46c96273 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/IAliasesList.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/IAliasesList.java @@ -1,6 +1,7 @@ package net.sourceforge.squirrel_sql.client.gui.db; import java.awt.event.MouseEvent; +import java.util.List; /* * Copyright (C) 2004 Colin Bell @@ -29,6 +30,8 @@ public interface IAliasesList extends IBaseList */ SQLAlias getSelectedAlias(MouseEvent evt); + List getAllSelectedAliases(); + void sortAliases(); void requestFocus(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JListAliasesListImpl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JListAliasesListImpl.java index a64ea2df0..190920ed5 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JListAliasesListImpl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JListAliasesListImpl.java @@ -1,5 +1,14 @@ package net.sourceforge.squirrel_sql.client.gui.db; +import java.awt.BorderLayout; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.List; +import javax.swing.JList; +import javax.swing.SwingUtilities; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.db.aliascolor.ListAliasColorSelectionHandler; @@ -7,15 +16,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import javax.swing.JList; -import javax.swing.SwingUtilities; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; -import java.awt.BorderLayout; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; - /* * Copyright (C) 2001-2004 Colin Bell * colbell@users.sourceforge.net @@ -53,7 +53,7 @@ public class JListAliasesListImpl extends BaseList implements IAliasesList public JListAliasesListImpl(IApplication app, AliasesListModel aliasesListModel, AliasListSelectionListener selectionListener) { - super(aliasesListModel, app); + super(aliasesListModel, true); _model = aliasesListModel; getList().setLayout(new BorderLayout()); @@ -160,6 +160,12 @@ public SQLAlias getSelectedAlias(MouseEvent evt) return (SQLAlias)getList().getSelectedValue(); } + @Override + public List getAllSelectedAliases() + { + return getList().getSelectedValuesList(); + } + public void sortAliases() { final SQLAlias selectedAlias = getSelectedAlias(null); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JTreeAliasesListImpl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JTreeAliasesListImpl.java index 21f2e3915..abb2a28d0 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JTreeAliasesListImpl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/JTreeAliasesListImpl.java @@ -12,6 +12,7 @@ import java.awt.event.MouseListener; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import javax.activation.DataHandler; @@ -29,7 +30,6 @@ import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; - import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.db.aliascolor.TreeAliasColorSelectionHandler; @@ -544,6 +544,16 @@ else if(selNode.getUserObject() instanceof AliasFolder) _tree.setSelectionPath(new TreePath(treeModel.getPathToRoot(newNode))); } + public List getAllSelectedAliases() + { + return + Arrays.stream(_tree.getSelectionPaths()) + .map(p -> p.getLastPathComponent()) + .filter(n -> n instanceof DefaultMutableTreeNode dmt && dmt.getUserObject() instanceof SQLAlias) + .map(n -> (SQLAlias)((DefaultMutableTreeNode) n).getUserObject()) + .toList(); + } + public SQLAlias getSelectedAlias(MouseEvent evt) { TreePath path = _tree.getSelectionPath(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/mainframe/action/ConnectToAliasAction.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/mainframe/action/ConnectToAliasAction.java index 6ea21a214..056cd83e5 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/mainframe/action/ConnectToAliasAction.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/mainframe/action/ConnectToAliasAction.java @@ -18,12 +18,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.event.ActionEvent; +import java.util.List; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.gui.db.IAliasesList; import net.sourceforge.squirrel_sql.client.gui.db.SQLAlias; -import java.awt.event.ActionEvent; - public class ConnectToAliasAction extends AliasAction { /** @@ -51,11 +51,9 @@ public ConnectToAliasAction(IApplication app, IAliasesList list) */ public void actionPerformed(ActionEvent evt) { - moveToFrontAndSelectAliasFrame(); - final SQLAlias alias = _aliases.getSelectedAlias(null); - if (alias != null) - { - new ConnectToAliasCommand(alias).executeConnect(); - } + moveToFrontAndSelectAliasFrame(); + List selectedAliases = _aliases.getAllSelectedAliases(); + + selectedAliases.forEach(a -> new ConnectToAliasCommand(a).executeConnect()); } } From 320080ab217f330eb92de9e8e2b84e1a6b5c18de Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Fri, 28 Nov 2025 21:53:01 +0100 Subject: [PATCH 03/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 New function to execute a SQL in multiple Sessions: The new Session toolbar button "Run SQL in all open Sessions" (ctrl+alt+shift+ENTER) executes the current SQL in all open Sessions. The feature can be switched off at menu File --> Global Preferences --> tab SQL --> checkbox "Allow to run a SQL in all open Sessions" --- sql12/core/doc/changes.txt | 7 +++ .../client/action/ActionRegistry.java | 3 ++ .../gui/mainframe/MainFrameMenuBar.java | 6 +-- .../gui/session/SQLInternalFrameToolBar.java | 2 + .../gui/session/SessionPanelToolBar.java | 2 + .../client/preferences/I18NStrings.properties | 1 + .../preferences/SQLPreferencesController.java | 13 ++--- .../preferences/SQLPreferencesPanel.java | 43 +++++++++-------- .../preferences/SquirrelPreferences.java | 44 ++++++++++++----- .../SquirrelPreferencesBeanInfo.java | 4 +- .../resources/images/multiSessionExec.png | Bin 0 -> 605 bytes .../client/resources/squirrel.properties | 9 +++- .../client/session/ISQLPanelAPI.java | 12 ++--- .../client/session/SQLPanelAPI.java | 19 +++++--- .../action/ExecuteSqlInAllSessionsAction.java | 45 ++++++++++++++++++ .../sqlparam/SQLParamExecutionListener.java | 17 ++++--- .../SQLReplaceExecutionListener.java | 15 +++--- 17 files changed, 168 insertions(+), 74 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/multiSessionExec.png create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/session/action/ExecuteSqlInAllSessionsAction.java diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 7f9c795b5..cde325bf0 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,13 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 + New function to execute a SQL in multiple Sessions: + The new Session toolbar button "Run SQL in all open Sessions" (ctrl+alt+shift+ENTER) + executes the current SQL in all open Sessions. + The feature can be switched off at menu File --> Global Preferences --> tab SQL + --> checkbox "Allow to run a SQL in all open Sessions" + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/74 Multiple selected Aliases can be selected and connected to. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/action/ActionRegistry.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/action/ActionRegistry.java index 1f0ea21b3..1ceb0bb4a 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/action/ActionRegistry.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/action/ActionRegistry.java @@ -50,6 +50,7 @@ import net.sourceforge.squirrel_sql.client.session.action.EscapeDateAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteAllSqlsAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlAction; +import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlInAllSessionsAction; import net.sourceforge.squirrel_sql.client.session.action.FilterObjectsAction; import net.sourceforge.squirrel_sql.client.session.action.FindColumnsAction; import net.sourceforge.squirrel_sql.client.session.action.FindColumnsInObjectTreeNodesAction; @@ -184,6 +185,7 @@ public void registerToolsPopupActions(ActionCollection ac, ToolsPopupController toolsPopupController.addAction("redo", sqlPanel.getRedoAction()); toolsPopupController.addAction("runsql", ac.get(ExecuteSqlAction.class)); toolsPopupController.addAction("runallsqls", ac.get(ExecuteAllSqlsAction.class)); + toolsPopupController.addAction("runsqlinallsession", ac.get(ExecuteSqlInAllSessionsAction.class)); toolsPopupController.addAction("filenew", ac.get(FileNewAction.class)); toolsPopupController.addAction("filedetach", ac.get(FileDetachAction.class)); toolsPopupController.addAction("fileopen", ac.get(FileOpenAction.class)); @@ -325,6 +327,7 @@ public void preloadActions(ActionCollection actionCollection) actionCollection.add(new DumpSessionAction(app)); actionCollection.add(new ExecuteSqlAction(app)); actionCollection.add(new ExecuteAllSqlsAction(app)); + actionCollection.add(new ExecuteSqlInAllSessionsAction()); actionCollection.add(new ExitAction(app)); actionCollection.add(new FileNewAction(app)); actionCollection.add(new FileDetachAction(app)); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/mainframe/MainFrameMenuBar.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/mainframe/MainFrameMenuBar.java index e3d41a85b..b73862ab4 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/mainframe/MainFrameMenuBar.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/mainframe/MainFrameMenuBar.java @@ -105,6 +105,7 @@ import net.sourceforge.squirrel_sql.client.session.action.EscapeDateAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteAllSqlsAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlAction; +import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlInAllSessionsAction; import net.sourceforge.squirrel_sql.client.session.action.FindColumnsAction; import net.sourceforge.squirrel_sql.client.session.action.FormatSQLAction; import net.sourceforge.squirrel_sql.client.session.action.GoToAliasSessionAction; @@ -428,14 +429,12 @@ private JMenu createSessionMenu(Resources rsrc) addToMenu(rsrc, FindColumnsAction.class, menu); addToMenu(rsrc, ExecuteSqlAction.class, menu); addToMenu(rsrc, ExecuteAllSqlsAction.class, menu); + addToMenu(rsrc, ExecuteSqlInAllSessionsAction.class, menu); menu.add(createTransactionMenu(rsrc)); addToMenu(rsrc, SQLFilterAction.class, menu); menu.addSeparator(); addToMenu(rsrc, ViewObjectAtCursorInObjectTreeAction.class, menu); - menu.addSeparator(); menu.add(createSessionWindowFileMenu(rsrc)); - addToMenu(rsrc, ChangeTrackAction.class, menu); - menu.addSeparator(); menu.add(createSavedSessionMenu(rsrc)); menu.addSeparator(); addToMenu(rsrc, ShowNativeSQLAction.class, menu); @@ -655,6 +654,7 @@ private JMenu createSessionWindowFileMenu(Resources rsrc) addToMenu(rsrc, FileAppendAction.class, menu); addToMenu(rsrc, FilePrintAction.class, menu); addToMenu(rsrc, FileReloadAction.class, menu); + addToMenu(rsrc, ChangeTrackAction.class, menu); return menu; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SQLInternalFrameToolBar.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SQLInternalFrameToolBar.java index 7791e5367..dd0cfddd7 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SQLInternalFrameToolBar.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SQLInternalFrameToolBar.java @@ -6,6 +6,7 @@ import net.sourceforge.squirrel_sql.client.session.action.ChangeTrackAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteAllSqlsAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlAction; +import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlInAllSessionsAction; import net.sourceforge.squirrel_sql.client.session.action.GoToLastEditLocationAction; import net.sourceforge.squirrel_sql.client.session.action.NextSqlAction; import net.sourceforge.squirrel_sql.client.session.action.PreviousSqlAction; @@ -45,6 +46,7 @@ private void createGUI(ISession session, ISQLPanelAPI panel) add(actions.get(ExecuteSqlAction.class)); addSeparator(); add(actions.get(ExecuteAllSqlsAction.class)); + add(actions.get(ExecuteSqlInAllSessionsAction.class)); addSeparator(); add(actions.get(FileNewAction.class)); add(actions.get(FileDetachAction.class)); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SessionPanelToolBar.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SessionPanelToolBar.java index 6a21f3a9a..7a6013ee4 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SessionPanelToolBar.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/session/SessionPanelToolBar.java @@ -6,6 +6,7 @@ import net.sourceforge.squirrel_sql.client.session.action.ChangeTrackAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteAllSqlsAction; import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlAction; +import net.sourceforge.squirrel_sql.client.session.action.ExecuteSqlInAllSessionsAction; import net.sourceforge.squirrel_sql.client.session.action.FindColumnsAction; import net.sourceforge.squirrel_sql.client.session.action.GoToLastEditLocationAction; import net.sourceforge.squirrel_sql.client.session.action.NextSqlAction; @@ -76,6 +77,7 @@ private void createGUI(ISession session) add(actions.get(ExecuteSqlAction.class)); addSeparator(); add(actions.get(ExecuteAllSqlsAction.class)); + add(actions.get(ExecuteSqlInAllSessionsAction.class)); addSeparator(); // actions.get(ExecuteSqlAction.class).setEnabled(false); add(actions.get(SQLFilterAction.class)); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/I18NStrings.properties index d5ab22254..efaf97d4f 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/I18NStrings.properties @@ -82,6 +82,7 @@ SQLPreferencesPanel.largeScriptStmtCount.note=Note: If the number of statements SQLPreferencesPanel.copy.quoted.sql.to.clip=In quotes functions should copy quoted SQLs to clipboard SQLPreferencesPanel.allow.run.all.sqls.in.editor=Allow to run all SQLs in editor +SQLPreferencesPanel.allow.run.sql.in.all.sessions=Allow to run a SQL in all open Sessions SQLPreferencesPanel.title=SQL diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesController.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesController.java index 70fd9a269..5c91214f6 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesController.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesController.java @@ -18,6 +18,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.Color; +import java.awt.Component; +import javax.swing.JColorChooser; +import javax.swing.JFileChooser; +import javax.swing.JScrollPane; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.session.mainpanel.changetrack.ChangeTrackPrefsPanelController; @@ -28,12 +33,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import javax.swing.JColorChooser; -import javax.swing.JFileChooser; -import javax.swing.JScrollPane; -import java.awt.Color; -import java.awt.Component; - /** * This preferences panel allows maintenance of SQL preferences. * @author Colin Bell @@ -78,6 +77,7 @@ void loadData() _panel.queryTimeout.setInt(prefs.getQueryTimeout()); _panel.chkCopyQuotedSqlsToClip.setSelected(prefs.getCopyQuotedSqlsToClip()); _panel.chkAllowRunAllSQLsInEditor.setSelected(prefs.getAllowRunAllSQLsInEditor()); + _panel.chkAllowRunSqlInAllSessions.setSelected(prefs.getAllowRunSqlInAllSessions()); _panel.chkMarkCurrentSql.setSelected(prefs.isMarkCurrentSql()); _panel.getCurrentSqlMarkColorIcon().setColor(new Color(prefs.getCurrentSqlMarkColorRGB())); @@ -113,6 +113,7 @@ public void applyChanges() prefs.setCopyQuotedSqlsToClip(_panel.chkCopyQuotedSqlsToClip.isSelected()); prefs.setAllowRunAllSQLsInEditor(_panel.chkAllowRunAllSQLsInEditor.isSelected()); + prefs.setAllowRunSqlInAllSessions(_panel.chkAllowRunSqlInAllSessions.isSelected()); prefs.setMarkCurrentSql(_panel.chkMarkCurrentSql.isSelected()); prefs.setCurrentSqlMarkColorRGB((_panel.getCurrentSqlMarkColorIcon()).getColor().getRGB()); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesPanel.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesPanel.java index 238480d60..e0ead4737 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesPanel.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SQLPreferencesPanel.java @@ -1,14 +1,10 @@ package net.sourceforge.squirrel_sql.client.preferences; -import net.sourceforge.squirrel_sql.client.session.mainpanel.changetrack.ChangeTrackPrefsPanel; -import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabheader.ResultTabHeaderPrefsPanel; -import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetViewer; -import net.sourceforge.squirrel_sql.fw.gui.IntegerField; -import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; -import net.sourceforge.squirrel_sql.fw.gui.OutputLabel; -import net.sourceforge.squirrel_sql.fw.util.StringManager; -import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; - +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; @@ -18,11 +14,14 @@ import javax.swing.JRadioButton; import javax.swing.JTextField; import javax.swing.SwingConstants; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; +import net.sourceforge.squirrel_sql.client.session.mainpanel.changetrack.ChangeTrackPrefsPanel; +import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabheader.ResultTabHeaderPrefsPanel; +import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetViewer; +import net.sourceforge.squirrel_sql.fw.gui.IntegerField; +import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; +import net.sourceforge.squirrel_sql.fw.gui.OutputLabel; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; public final class SQLPreferencesPanel extends JPanel { @@ -39,6 +38,7 @@ public final class SQLPreferencesPanel extends JPanel IntegerField queryTimeout = new IntegerField(); JCheckBox chkCopyQuotedSqlsToClip = new JCheckBox(s_stringMgr.getString("SQLPreferencesPanel.copy.quoted.sql.to.clip")); JCheckBox chkAllowRunAllSQLsInEditor = new JCheckBox(s_stringMgr.getString("SQLPreferencesPanel.allow.run.all.sqls.in.editor")); + JCheckBox chkAllowRunSqlInAllSessions = new JCheckBox(s_stringMgr.getString("SQLPreferencesPanel.allow.run.sql.in.all.sessions")); JCheckBox chkMarkCurrentSql = new JCheckBox(s_stringMgr.getString("SQLPreferencesPanel.mark.current.sql")); JButton btnCurrentSqlMarkColorRGB = new JButton(); @@ -149,35 +149,40 @@ private JPanel createGeneralPanel(ResultTabHeaderPrefsPanel resultTabHeaderPrefs gbc.gridx = 0; gbc.gridy = 5; gbc.gridwidth = GridBagConstraints.REMAINDER; + pnl.add(chkAllowRunSqlInAllSessions, gbc); + + gbc.gridx = 0; + gbc.gridy = 6; + gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.NONE; pnl.add(createCurrentSqlMarkPanel(), gbc); gbc.gridx = 0; - gbc.gridy = 6; + gbc.gridy = 7; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.NONE; pnl.add(chkUseStatementSeparatorAsSqlToExecuteBounds, gbc); gbc.gridx = 0; - gbc.gridy = 7; + gbc.gridy = 8; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.HORIZONTAL; pnl.add(resultTabHeaderPrefsPanel , gbc); gbc.gridx = 0; - gbc.gridy = 8; + gbc.gridy = 9; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.HORIZONTAL; pnl.add(createReloadSQLContentsPanel(), gbc); gbc.gridx = 0; - gbc.gridy = 9; + gbc.gridy = 10; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.NONE; pnl.add(createMaxTextOutputColumnWidthPanel(), gbc); gbc.gridx = 0; - gbc.gridy = 10; + gbc.gridy = 11; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.NONE; pnl.add(chkNotifyExternalFileChanges, gbc); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java index ff537a2ae..e610e00f7 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java @@ -20,6 +20,15 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.Color; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.Serializable; +import java.sql.DriverManager; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; import net.sourceforge.squirrel_sql.client.action.ActionKeys; import net.sourceforge.squirrel_sql.client.gui.db.mainframetitle.PositionInMainFrameTitle; import net.sourceforge.squirrel_sql.client.gui.mainframe.MainFrameWindowState; @@ -36,16 +45,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; import net.sourceforge.squirrel_sql.fw.xml.XMLBeanReader; import net.sourceforge.squirrel_sql.fw.xml.XMLBeanWriter; - -import java.awt.Color; -import java.beans.PropertyChangeListener; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.Serializable; -import java.sql.DriverManager; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; /** * This class represents the application preferences. * @@ -63,6 +62,7 @@ public interface IPropertyNames String LARGE_SCRIPT_STMT_COUNT = "largeScriptStmtCount"; String COPY_QUOTED_SQLS_TO_CLIP = "copyQuotedSqlsToClip"; String ALLOW_RUN_ALL_SQLS_IN_EDITOR = "allowRunAllSQLsInEditor"; + String ALLOW_RUN_SQLS_IN_ALL_OPEN_SESSIONS = "allowRunSqlInAllSessions"; String MARK_CURRENT_SQL = "markCurrentSql"; String CURRENT_SQL_MARK_COLOR_RGB = "currentSqlMarkColorRGB"; @@ -215,7 +215,9 @@ public interface IJdbcDebugTypes private boolean _allowRunAllSQLsInEditor = true; - /** Show tooltips for controls. */ + private boolean _allowRunSqlInAllSessions = true; + + /** Show tooltips for controls. */ private boolean _showToolTips = true; /** Use scrollable tabbed panes. JDK 1.4 and above only. */ @@ -1331,7 +1333,7 @@ public void setCopyQuotedSqlsToClip(boolean copyQuotedSqlsToClip) public boolean getAllowRunAllSQLsInEditor() { - return _allowRunAllSQLsInEditor; + return isAllowRunAllSQLsInEditor(); } public boolean isAllowRunAllSQLsInEditor() @@ -1344,7 +1346,23 @@ public void setAllowRunAllSQLsInEditor(boolean allowRunAllSQLsInEditor) _allowRunAllSQLsInEditor = allowRunAllSQLsInEditor; } - public boolean isMarkCurrentSql() + public boolean getAllowRunSqlInAllSessions() + { + return isAllowRunSqlInAllSessions(); + } + + public boolean isAllowRunSqlInAllSessions() + { + return _allowRunSqlInAllSessions; + } + + public void setAllowRunSqlInAllSessions(boolean allowRunSqlInAllSessions) + { + _allowRunSqlInAllSessions = allowRunSqlInAllSessions; + } + + + public boolean isMarkCurrentSql() { return _markCurrentSql; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferencesBeanInfo.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferencesBeanInfo.java index 135a7412c..5f5db1ab2 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferencesBeanInfo.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferencesBeanInfo.java @@ -19,12 +19,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.fw.util.Utilities; - import java.beans.IndexedPropertyDescriptor; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.beans.SimpleBeanInfo; +import net.sourceforge.squirrel_sql.fw.util.Utilities; /** * This is the BeanInfo class for SquirrelPreferences. @@ -57,6 +56,7 @@ public PropertyDescriptor[] getPropertyDescriptors() prop(LARGE_SCRIPT_STMT_COUNT, SquirrelPreferences.class, "getLargeScriptStmtCount", "setLargeScriptStmtCount"), prop(ALLOW_RUN_ALL_SQLS_IN_EDITOR, SquirrelPreferences.class, "isAllowRunAllSQLsInEditor", "setAllowRunAllSQLsInEditor"), + prop(ALLOW_RUN_SQLS_IN_ALL_OPEN_SESSIONS, SquirrelPreferences.class, "isAllowRunSqlInAllSessions", "setAllowRunSqlInAllSessions"), prop(MARK_CURRENT_SQL, SquirrelPreferences.class, "isMarkCurrentSql", "setMarkCurrentSql"), prop(CURRENT_SQL_MARK_COLOR_RGB, SquirrelPreferences.class, "getCurrentSqlMarkColorRGB", "setCurrentSqlMarkColorRGB"), diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/multiSessionExec.png b/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/multiSessionExec.png new file mode 100644 index 0000000000000000000000000000000000000000..31ddc1e8f418b4c4c217be2438a7ff7eb9269b34 GIT binary patch literal 605 zcmV-j0;2tiP)plzGU zT-TZFTYHLj$Hn(TTmN*5K6P1F?s)Ycknoc8HqYxK(^q&M~9j6!-WC+oIRdodU zMjM#9>N>GY9d)O$#PS?iP>nC?VZ^UtSG_$o9fH=+wf(vw)N^aC02tZZUkCa`q>d3^L~1JKmZ?;}v=X>3 z%X r#{k^4+BS( new SelectWidgetCommand(_sqlPanelAPI.getSession().getActiveSessionWindow()).execute()); + + // Was removed because it messed with the feature https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 + //GUIUtils.processOnSwingEventThread(() -> new SelectWidgetCommand(_sqlPanelAPI.getSession().getActiveSessionWindow()).execute()); // log.info("SQL passing to execute: " + buffer.toString()); ////////////////////////////////////////////////////////////////// diff --git a/sql12/plugins/sqlreplace/src/net/sourceforge/squirrel_sql/plugins/sqlreplace/SQLReplaceExecutionListener.java b/sql12/plugins/sqlreplace/src/net/sourceforge/squirrel_sql/plugins/sqlreplace/SQLReplaceExecutionListener.java index b99d4fa8b..9f1fcd101 100644 --- a/sql12/plugins/sqlreplace/src/net/sourceforge/squirrel_sql/plugins/sqlreplace/SQLReplaceExecutionListener.java +++ b/sql12/plugins/sqlreplace/src/net/sourceforge/squirrel_sql/plugins/sqlreplace/SQLReplaceExecutionListener.java @@ -18,10 +18,8 @@ */ package net.sourceforge.squirrel_sql.plugins.sqlreplace; -import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.SelectWidgetCommand; import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.event.SQLExecutionAdapter; -import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.sql.querytokenizer.QueryHolder; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; @@ -79,12 +77,13 @@ public String statementExecuting(String sql) { if (log.isDebugEnabled()) { log.debug("statementExecuting: replacedStmnt = "+replacedStmnt); } - - GUIUtils.processOnSwingEventThread(new Runnable() { - public void run() { - new SelectWidgetCommand(session.getActiveSessionWindow()).execute(); - } - }); + + // Was removed because it messed with the feature https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 + //GUIUtils.processOnSwingEventThread(new Runnable() { + // public void run() { + // new SelectWidgetCommand(session.getActiveSessionWindow()).execute(); + // } + //}); return replacedStmnt; } From 98a690145820bd1306c16597de2e9835496c98c9 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sun, 30 Nov 2025 21:38:48 +0100 Subject: [PATCH 04/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/76 Cell data popup and cell detail display now offer right mouse menus to Base64/Base32/Hex-decode selected text. The decoded text is written to the message panel. --- sql12/core/doc/changes.txt | 4 + .../celldatapopup/DecodeSelection.java | 92 +++++++++++++++++++ .../celldatapopup/I18NStrings.properties | 11 ++- .../celldatapopup/PopupEditableIOPanel.java | 56 +++++------ 4 files changed, 134 insertions(+), 29 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/DecodeSelection.java diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index cde325bf0..6c49ea34b 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,10 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/76 + Cell data popup and cell detail display now offer right mouse menus to + Base64/Base32/Hex-decode selected text. The decoded text is written to the message panel. + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 New function to execute a SQL in multiple Sessions: The new Session toolbar button "Run SQL in all open Sessions" (ctrl+alt+shift+ENTER) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/DecodeSelection.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/DecodeSelection.java new file mode 100644 index 000000000..154c55dcb --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/DecodeSelection.java @@ -0,0 +1,92 @@ +package net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup; + +import java.nio.charset.StandardCharsets; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.RestorableRSyntaxTextArea; +import net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice.Base64DecodeHelper; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; +import net.sourceforge.squirrel_sql.fw.util.Utilities; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base32; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.lang3.StringUtils; + +public class DecodeSelection +{ + private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(DecodeSelection.class); + + public static JMenu getParentMenu(RestorableRSyntaxTextArea textArea) + { + JMenu ret = new JMenu(s_stringMgr.getString("DecodeSelection.menu")); + ret.setToolTipText(s_stringMgr.getString("DecodeSelection.menu.tooltip")); + + JMenuItem menuItem; + + menuItem = new JMenuItem(s_stringMgr.getString("DecodeSelection.menu.item.decode.base64")); + menuItem.addActionListener(e -> decodeBase64(textArea)); + ret.add(menuItem); + + menuItem = new JMenuItem(s_stringMgr.getString("DecodeSelection.menu.item.decode.base32")); + menuItem.addActionListener(e -> decodeBase32(textArea)); + ret.add(menuItem); + + menuItem = new JMenuItem(s_stringMgr.getString("DecodeSelection.menu.item.decode.hex")); + menuItem.addActionListener(e -> decodeHex(textArea)); + ret.add(menuItem); + + return ret; + } + + private static void decodeHex(RestorableRSyntaxTextArea textArea) + { + try + { + String selectedText = textArea.getSelectedText(); + + if(StringUtils.isBlank(selectedText)) + { + Main.getApplication().getMessageHandler().showWarningMessage(s_stringMgr.getString("DecodeSelection.no.text.selected.to.decode")); + return; + } + + Main.getApplication().getMessageHandler().showMessage(new String(Hex.decodeHex(selectedText), StandardCharsets.UTF_8)); + } + catch(DecoderException e) + { + throw Utilities.wrapRuntime(e); + } + } + + private static void decodeBase32(RestorableRSyntaxTextArea textArea) + { + String selectedText = textArea.getSelectedText(); + + if(StringUtils.isBlank(selectedText)) + { + Main.getApplication().getMessageHandler().showWarningMessage(s_stringMgr.getString("DecodeSelection.no.text.selected.to.decode")); + return; + } + + Main.getApplication().getMessageHandler().showMessage(new String(new Base32().decode(selectedText), StandardCharsets.UTF_8)); + } + + private static void decodeBase64(RestorableRSyntaxTextArea textArea) + { + String selectedText = textArea.getSelectedText(); + + if(StringUtils.isBlank(selectedText)) + { + Main.getApplication().getMessageHandler().showWarningMessage(s_stringMgr.getString("DecodeSelection.no.text.selected.to.decode")); + return; + } + + Main.getApplication().getMessageHandler().showMessage( + new String(Base64DecodeHelper.decodeBase64OmittingInvalidBase64Chars(selectedText), StandardCharsets.UTF_8)); + + } + + +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/I18NStrings.properties index 2ad796874..7373c9dae 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/I18NStrings.properties @@ -75,4 +75,13 @@ popupEditableIoPanel.clipboard.vs.cell.data=Clipboard vs cell data PopupEditableIOPanel.no.word.wrap.without.line.wrap=Word wrap is -popupEditableIoPanel.cannot.update.binary.display.while.reformatted=Cannot update binary display while display is reformatted. \ No newline at end of file +popupEditableIoPanel.cannot.update.binary.display.while.reformatted=Cannot update binary display while display is reformatted. + +DecodeSelection.menu=Decode selection +DecodeSelection.menu.tooltip=Decode selected text to message panel + +DecodeSelection.menu.item.decode.base64=Decode Base64 to message panel +DecodeSelection.menu.item.decode.base32=Decode Base32 to message panel +DecodeSelection.menu.item.decode.hex=Decode HEX to message panel + +DecodeSelection.no.text.selected.to.decode=No text selected to decode diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/PopupEditableIOPanel.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/PopupEditableIOPanel.java index dc63bf3f9..b6950aecb 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/PopupEditableIOPanel.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/PopupEditableIOPanel.java @@ -18,6 +18,33 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Path; +import java.sql.Types; +import java.util.Objects; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JToggleButton; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; import net.sourceforge.squirrel_sql.client.session.action.dbdiff.DBDIffService; @@ -44,34 +71,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JToggleButton; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.file.Path; -import java.sql.Types; -import java.util.Objects; - /** * @author gwg * @@ -231,6 +230,7 @@ public PopupEditableIOPanel(ColumnDisplayDefinition colDef, Object value, boolea _popupMenu.add(_chkMnuWordWrap); _popupMenu.add(new XMLJsonReformatAction()); + _popupMenu.add(DecodeSelection.getParentMenu(_textArea)); _popupMenu.add(new CompareToClipAction()).setToolTipText(s_stringMgr.getString("popupEditableIoPanel.compare.to.clip.tooltip")); _popupMenu.setTextComponent(_textArea); From 58e667ad44345f31d37937e9e72b049ed1f96d22 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sun, 14 Dec 2025 21:03:35 +0100 Subject: [PATCH 05/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/79 MS Excel file export: The MS Excel section of the file export dialog offers two new options: 1. Option to define the name of the Excel sheet tab that is created inside the Excel file. 2. Option to replace Excel sheet tabs in existing Excel files. Note that those two (as several other) options will apply to automated exports, too. To learn about automated exports see the link at the bottom of the file export dialog. --- sql12/core/doc/changes.txt | 7 ++ .../fileexport/DataExportExcelWriter.java | 35 +++++--- .../fileexport/ExcelSQLStatementSheet.java | 28 ++++-- .../fileexport/ExcelSheetReplaceUtil.java | 83 ++++++++++++++++++ .../action/fileexport/ExportController.java | 47 +++++++--- .../gui/action/fileexport/ExportDataInfo.java | 24 ++---- .../fw/gui/action/fileexport/ExportDlg.java | 86 +++++++++++++------ .../action/fileexport/I18NStrings.properties | 12 ++- .../fileexport/TableExportPreferences.java | 22 +++++ .../fileexport/TableExportPreferencesDAO.java | 6 ++ .../squirrel_sql/fw/util/StringUtilities.java | 11 ++- 11 files changed, 285 insertions(+), 76 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSheetReplaceUtil.java diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 6c49ea34b..0ea08f534 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,13 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/79 + MS Excel file export: The MS Excel section of the file export dialog offers two new options: + 1. Option to define the name of the Excel sheet tab that is created inside the Excel file. + 2. Option to replace Excel sheet tabs in existing Excel files. + Note that those two (as several other) options will apply to automated exports, too. + To learn about automated exports see the link at the bottom of the file export dialog. + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/76 Cell data popup and cell detail display now offer right mouse menus to Base64/Base32/Hex-decode selected text. The decoded text is written to the message panel. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/DataExportExcelWriter.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/DataExportExcelWriter.java index d09de721a..0bfec0b37 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/DataExportExcelWriter.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/DataExportExcelWriter.java @@ -18,6 +18,14 @@ */ package net.sourceforge.squirrel_sql.fw.gui.action.fileexport; +import java.io.File; +import java.io.FileOutputStream; +import java.sql.Types; +import java.text.NumberFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.CellComponentFactory; import net.sourceforge.squirrel_sql.fw.sql.ProgressAbortCallback; @@ -34,15 +42,6 @@ import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import java.io.File; -import java.io.FileOutputStream; -import java.sql.Types; -import java.text.NumberFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; - /** * Exports {@link IExportData} to a Excel file. * Note: This class is the result of a refactoring task. The code was @@ -80,7 +79,7 @@ public long write(ExportDataInfoList exportDataInfoList, TableExportPreferences for (ExportDataInfo exportDataInfo : exportDataInfoList.getExportDataInfos()) { - _sheet = _workbook.createSheet(exportDataInfo.getExcelSheetTabName()); + _sheet = ExcelSheetReplaceUtil.getOrCreateSheet(_workbook, exportDataInfo.getExcelSheetTabName(prefs), prefs); rowsCount += _writeExcelTab(exportDataInfo.getExportData()); @@ -96,7 +95,7 @@ public long write(ExportDataInfoList exportDataInfoList, TableExportPreferences if(prefs.isExcelExportSQLStatementInAdditionalSheet()) { - ExcelSQLStatementSheet.createSqlStatementSheet(exportDataInfo, _workbook); + ExcelSQLStatementSheet.createSqlStatementSheet(exportDataInfo, _workbook, prefs); } } _fileExportService.progress(s_stringMgr.getString("DataExportExcelWriter.finishedLoading", NumberFormat.getInstance().format(rowsCount))); @@ -280,20 +279,28 @@ private String getDataXLSAsString(Object cellObj) private void beforeWorking() { + _workbook = ExcelSheetReplaceUtil.getExistingWorkBookOrNull(_fileExportService); + + if(null != _workbook) + { + return; + } + + if (_fileExportService.getPrefs().isFormatXLSOld()) { - this._workbook = new HSSFWorkbook(); // See https://gist.github.com/madan712/3912272 + _workbook = new HSSFWorkbook(); // See https://gist.github.com/madan712/3912272 } else { if(_fileExportService.getPrefs().isUseColoring()) { // See class ExcelCellColorer on how this will take care the Excel gets colored. - this._workbook = new XSSFWorkbook(); + _workbook = new XSSFWorkbook(); } else { - this._workbook = new SXSSFWorkbook(100); // keep 100 rows in memory, exceeding rows will be flushed to disk + _workbook = new SXSSFWorkbook(100); // keep 100 rows in memory, exceeding rows will be flushed to disk } } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSQLStatementSheet.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSQLStatementSheet.java index d2a3c0b42..89d83c1c9 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSQLStatementSheet.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSQLStatementSheet.java @@ -12,16 +12,14 @@ public class ExcelSQLStatementSheet { - public static void createSqlStatementSheet(ExportDataInfo exportDataInfo, Workbook workbook) + public static void createSqlStatementSheet(ExportDataInfo exportDataInfo, Workbook workbook, TableExportPreferences prefs) { if(StringUtilities.isEmpty(exportDataInfo.getSqlToWriteToFile(), true)) { return; } - String sqlStatementTabName = getUniqueSqlSheetName(workbook, exportDataInfo.getExcelSheetTabName(), 0); - - Sheet sheet = workbook.createSheet(sqlStatementTabName); + Sheet sheet = getOrCreateSqlStatementSheet(exportDataInfo, workbook, prefs); Row row = sheet.createRow(0); // Does not work @@ -40,9 +38,24 @@ public static void createSqlStatementSheet(ExportDataInfo exportDataInfo, Workbo cell.setCellStyle(cellStyle); } + private static Sheet getOrCreateSqlStatementSheet(ExportDataInfo exportDataInfo, Workbook workbook, TableExportPreferences prefs) + { + if(ExcelSheetReplaceUtil.isReplaceExcelSheets(prefs)) + { + String sqlStatementTabName = getInitialCandidateSqlSheetName(exportDataInfo.getExcelSheetTabName(prefs)); + return ExcelSheetReplaceUtil.getOrCreateSheet(workbook, sqlStatementTabName, prefs); + } + else + { + String sqlStatementTabName = getUniqueSqlSheetName(workbook, exportDataInfo.getExcelSheetTabName(prefs), 0); + Sheet sheet = workbook.createSheet(sqlStatementTabName); + return sheet; + } + } + private static String getUniqueSqlSheetName(Workbook workbook, String excelSheetTabName, int numberToCheck) { - String candidate = excelSheetTabName + "_SQL"; + String candidate = getInitialCandidateSqlSheetName(excelSheetTabName); if(numberToCheck > 0) { @@ -60,4 +73,9 @@ private static String getUniqueSqlSheetName(Workbook workbook, String excelSheet return candidate; } + + private static String getInitialCandidateSqlSheetName(String excelSheetTabName) + { + return excelSheetTabName + "_SQL"; + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSheetReplaceUtil.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSheetReplaceUtil.java new file mode 100644 index 000000000..7c121dc78 --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExcelSheetReplaceUtil.java @@ -0,0 +1,83 @@ +package net.sourceforge.squirrel_sql.fw.gui.action.fileexport; + +import java.io.FileInputStream; +import java.io.IOException; +import net.sourceforge.squirrel_sql.fw.util.log.ILogger; +import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; + +public class ExcelSheetReplaceUtil +{ + private static final ILogger s_log = LoggerController.createLogger(ExcelSheetReplaceUtil.class); + + + public static Sheet getOrCreateSheet(Workbook workbook, String excelSheetTabName, TableExportPreferences prefs) + { + if(false == isReplaceExcelSheets(prefs)) + { + return workbook.createSheet(excelSheetTabName); + } + + Sheet sheet = workbook.getSheet(excelSheetTabName); + if(null == sheet) + { + return workbook.createSheet(excelSheetTabName); + } + + // AI: Clear existing contents + for(int rowIndex = sheet.getLastRowNum(); rowIndex >= 0; rowIndex--) + { + Row row = sheet.getRow(rowIndex); + if(row != null) + { + sheet.removeRow(row); + } + } + + return sheet; + + } + + + public static boolean isReplaceExcelSheets(TableExportPreferences prefs) + { + return prefs.isExcelReplaceSheets(); + } + + public static Workbook getExistingWorkBookOrNull(FileExportService fileExportService) + { + if(false == isReplaceExcelSheets(fileExportService.getPrefs())) + { + return null; + } + + + if(!hasExcelExtension(fileExportService.getFile().getAbsolutePath())) + { + return null; // Quick check by extension + } + + try(FileInputStream fis = new FileInputStream(fileExportService.getFile())) + { + Workbook workbook = WorkbookFactory.create(fis); // Will throw exception if not valid + return workbook; + } + catch(IOException e) + { + s_log.warn("File to replace sheet(s) in is not an MSExcelFile", e); + return null; + } + } + + /** + * AI: Method to check by extension + */ + public static boolean hasExcelExtension(String filePath) + { + return StringUtils.endsWithIgnoreCase(filePath,".xls") || StringUtils.endsWithIgnoreCase(filePath,".xlsx"); + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportController.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportController.java index 7a4601209..eec4b0d89 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportController.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportController.java @@ -1,5 +1,16 @@ package net.sourceforge.squirrel_sql.fw.gui.action.fileexport; +import java.awt.Font; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import net.sourceforge.squirrel_sql.fw.gui.EditableComboBoxHandler; import net.sourceforge.squirrel_sql.fw.gui.FontChooser; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; @@ -8,18 +19,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringUtilities; import org.apache.commons.lang3.StringUtils; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.Font; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.io.File; - public class ExportController { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ExportController.class); @@ -190,8 +189,11 @@ private void onFormat(boolean replaceEnding) _dlg.btnChooseExcelFont.setEnabled(false); _dlg.btnChooseExcelHeaderFont.setEnabled(false); _dlg.lblExcelFontName.setEnabled(false); + _dlg.lblExcelSheetName.setEnabled(false); + _dlg.txtExcelSheetName.setEnabled(false); _dlg.lblExcelHeaderFontName.setEnabled(false); _dlg.chkExcelExportSQLStatementInAdditionalSheet.setEnabled(false); + _dlg.chkExcelReplaceSheets.setEnabled(false); if(_dlg.chkSeparatorTab.isSelected()) @@ -231,7 +233,10 @@ else if (_dlg.radFormatXLSX.isSelected() || _dlg.radFormatXLS.isSelected()) _dlg.btnChooseExcelHeaderFont.setEnabled(true); _dlg.lblExcelFontName.setEnabled(true); _dlg.lblExcelHeaderFontName.setEnabled(true); + _dlg.lblExcelSheetName.setEnabled(true); + _dlg.txtExcelSheetName.setEnabled(true); _dlg.chkExcelExportSQLStatementInAdditionalSheet.setEnabled(true); + _dlg.chkExcelReplaceSheets.setEnabled(true); if(replaceEnding) { @@ -258,7 +263,10 @@ else if (_dlg.radFormatXML.isSelected() || _dlg.radFormatJSON.isSelected()) _dlg.btnChooseExcelHeaderFont.setEnabled(false); _dlg.lblExcelFontName.setEnabled(false); _dlg.lblExcelHeaderFontName.setEnabled(false); + _dlg.lblExcelSheetName.setEnabled(false); + _dlg.txtExcelSheetName.setEnabled(false); _dlg.chkExcelExportSQLStatementInAdditionalSheet.setEnabled(false); + _dlg.chkExcelReplaceSheets.setEnabled(false); if(replaceEnding) @@ -444,8 +452,12 @@ private void onOK() && false == isExportingMultipleFiles() // For now in case of multiple export files these files will be replaced silently. ) { - // i18n[TableExportCsvController.replaceFile=The export file already exisits. Would you like to replace it?] String msg = s_stringMgr.getString("TableExportCsvController.replaceFile"); + if(isExcelWithReplaceSheets()) + { + msg = s_stringMgr.getString("TableExportCsvController.add.or.replace.excel.sheet"); + } + if(JOptionPane.OK_OPTION != JOptionPane.showConfirmDialog(_dlg, msg)) { return; @@ -460,6 +472,11 @@ private void onOK() closeDlg(); } + private boolean isExcelWithReplaceSheets() + { + return (_dlg.radFormatXLSX.isSelected() || _dlg.radFormatXLS.isSelected()) && _dlg.chkExcelReplaceSheets.isSelected(); + } + private boolean isExportingMultipleFiles() { return _exportSelectionPanelController.isExportMultipleSQLResults() @@ -503,7 +520,9 @@ private void writeControlsToPrefs(TableExportPreferences prefs) prefs.setExcelFirstRowFrozen(_dlg.chkExcelFirstRowFrozen.isSelected()); prefs.setExcelFirstRowCentered(_dlg.chkExcelFirstRowCentered.isSelected()); prefs.setExcelFirstRowBold(_dlg.chkExcelFirstRowBold.isSelected()); + prefs.setExcelSheetNameFileNormalized(StringUtilities.fileNameNormalize(StringUtilities.emptyToNull(_dlg.txtExcelSheetName.getText()), true)); prefs.setExcelExportSQLStatementInAdditionalSheet(_dlg.chkExcelExportSQLStatementInAdditionalSheet.isSelected()); + prefs.setExcelReplaceSheets(_dlg.chkExcelReplaceSheets.isSelected()); _excelFontCtrl.writeToPrefs(prefs); @@ -545,7 +564,9 @@ private void initData() _dlg.chkExcelFirstRowFrozen.setSelected(prefs.isExcelFirstRowFrozen()); _dlg.chkExcelFirstRowCentered.setSelected(prefs.isExcelFirstRowCentered()); _dlg.chkExcelFirstRowBold.setSelected(prefs.isExcelFirstRowBold()); + _dlg.txtExcelSheetName.setText(prefs.getExcelSheetNameFileNormalized()); _dlg.chkExcelExportSQLStatementInAdditionalSheet.setSelected(prefs.isExcelExportSQLStatementInAdditionalSheet()); + _dlg.chkExcelReplaceSheets.setSelected(prefs.isExcelReplaceSheets()); _dlg.cboCharsets.setSelectedItem(prefs.getEncoding()); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDataInfo.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDataInfo.java index de3930577..34aa62e5c 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDataInfo.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDataInfo.java @@ -1,8 +1,7 @@ package net.sourceforge.squirrel_sql.fw.gui.action.fileexport; -import net.sourceforge.squirrel_sql.fw.util.StringUtilities; - import java.io.File; +import net.sourceforge.squirrel_sql.fw.util.StringUtilities; public class ExportDataInfo { @@ -50,27 +49,20 @@ public File getFile(TableExportPreferences prefs) } } - public String getExcelSheetTabName() + public String getExcelSheetTabName(TableExportPreferences prefs) { - if(StringUtilities.isEmpty(_exportNameFileNormalized, true)) + if(false == StringUtilities.isEmpty(_exportNameFileNormalized, true)) { - return DataExportExcelWriter.DEFAULT_EXCEL_EXPORT_SHEET_NAME; + return _exportNameFileNormalized; } - else + else if(false == StringUtilities.isEmpty(prefs.getExcelSheetNameFileNormalized())) { - return _exportNameFileNormalized; + return prefs.getExcelSheetNameFileNormalized(); } - - } - - public ResultSetExportData getResultSetExportData() - { - if(_exportData instanceof ResultSetExportData ret) + else { - return ret; + return DataExportExcelWriter.DEFAULT_EXCEL_EXPORT_SHEET_NAME; } - - return null; } public String getSqlToWriteToFile() diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDlg.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDlg.java index dce04b336..8561c2801 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDlg.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/ExportDlg.java @@ -1,14 +1,16 @@ package net.sourceforge.squirrel_sql.fw.gui.action.fileexport; -import net.sourceforge.squirrel_sql.client.Main; -import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; -import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; -import net.sourceforge.squirrel_sql.fw.gui.buttontabcomponent.SmallToolTipInfoButton; -import net.sourceforge.squirrel_sql.fw.resources.LibraryResources; -import net.sourceforge.squirrel_sql.fw.util.StringManager; -import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; - +import java.awt.Component; +import java.awt.Cursor; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.nio.charset.Charset; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; @@ -21,17 +23,13 @@ import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ScrollPaneConstants; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Insets; -import java.awt.Window; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.nio.charset.Charset; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; +import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; +import net.sourceforge.squirrel_sql.fw.gui.buttontabcomponent.SmallToolTipInfoButton; +import net.sourceforge.squirrel_sql.fw.resources.LibraryResources; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; public class ExportDlg extends JDialog { @@ -57,7 +55,11 @@ public class ExportDlg extends JDialog JButton btnChooseExcelHeaderFont; MultipleLineLabel lblExcelHeaderFontName; + JLabel lblExcelSheetName; + JTextField txtExcelSheetName; + JCheckBox chkExcelExportSQLStatementInAdditionalSheet; + JCheckBox chkExcelReplaceSheets; JRadioButton radFormatXML; JRadioButton radFormatJSON; @@ -245,21 +247,53 @@ private JPanel createExcelOptionsPanel() gbc = new GridBagConstraints(0, 1, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 3, 3, 0), 0, 0); ret.add(createFontPanel(), gbc); - gbc = new GridBagConstraints(0, 2, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 3, 3, 0), 0, 0); - ret.add(createSQLStatementInAdditionalSheetPanel(), gbc); + gbc = new GridBagConstraints(0, 2, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 3, 3, 0), 0, 0); + ret.add(createSheetNamePanel(), gbc); + + gbc = new GridBagConstraints(0, 3, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 3, 3, 0), 0, 0); + ret.add(createExcelSectionLowerCheckboxes(), gbc); + + return ret; + } + + private JPanel createSheetNamePanel() + { + JPanel ret = new JPanel(new GridBagLayout()); + + GridBagConstraints gbc; + + gbc = new GridBagConstraints(0,0,1,1,0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); + lblExcelSheetName = new JLabel(s_stringMgr.getString("TableExportCsvDlg.lbl.sheet.name")); + ret.add(lblExcelSheetName, gbc); + + gbc = new GridBagConstraints(1,0,1,1,1,0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0,5,0,60), 0,0); + txtExcelSheetName = new JTextField(); + ret.add(txtExcelSheetName, gbc); return ret; } - private JPanel createSQLStatementInAdditionalSheetPanel() + private JPanel createExcelSectionLowerCheckboxes() { - JPanel ret = new JPanel(new BorderLayout()); + JPanel ret = new JPanel(new GridBagLayout()); + + GridBagConstraints gbc; + gbc = new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); chkExcelExportSQLStatementInAdditionalSheet = new JCheckBox(s_stringMgr.getString("TableExportCsvDlg.excel.SQL.in.extra.sheet")); - ret.add(chkExcelExportSQLStatementInAdditionalSheet, BorderLayout.CENTER); + ret.add(chkExcelExportSQLStatementInAdditionalSheet, gbc); + + gbc = new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); + SmallToolTipInfoButton btnInfoSql = new SmallToolTipInfoButton(s_stringMgr.getString("TableExportCsvDlg.excel.SQL.in.extra.sheet.infoButton")); + ret.add(btnInfoSql.getButton(), gbc); + + gbc = new GridBagConstraints(2,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,20,0,0), 0,0); + chkExcelReplaceSheets = new JCheckBox(s_stringMgr.getString("TableExportCsvDlg.excel.replace.sheets")); + ret.add(chkExcelReplaceSheets, gbc); - SmallToolTipInfoButton btnInfo = new SmallToolTipInfoButton(s_stringMgr.getString("TableExportCsvDlg.excel.SQL.in.extra.sheet.infoButton")); - ret.add(btnInfo.getButton(), BorderLayout.EAST); + gbc = new GridBagConstraints(3,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); + SmallToolTipInfoButton btnInfoReplace = new SmallToolTipInfoButton(s_stringMgr.getString("TableExportCsvDlg.excel.replace.sheets.infoButton")); + ret.add(btnInfoReplace.getButton(), gbc); return ret; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/I18NStrings.properties index b62157613..5bc116db0 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/I18NStrings.properties @@ -39,6 +39,7 @@ TableExportCsvController.noFile=You must provide an export file name. TableExportCsvController.noCommand=You must provide a command string or uncheck "Execute command". TableExportCsvController.invalidSeparator=You must provide a single separator character or check "Use tab" to use the tab character. TableExportCsvController.replaceFile=The export file already exists. Would you like to replace it? +TableExportCsvController.add.or.replace.excel.sheet=The Excel file to export to already exists. Would you like to add or replace sheets in the file? TableExportCsvController.fileChooserTilte=Choose export file TableExportCsvCommand.failedToWriteFile=Failed to write file\n{0}\nError message:\n{1}\nSee last log entry for details. TableExportCsvCommand.failedToExecuteCommand=Failed to execute\n{0}\nError message:\n{1}\nSee last log entry for details. @@ -202,4 +203,13 @@ TableExportCsvDlg.excel.SQL.in.extra.sheet.infoButton=Applies to MS Excel data may be incomplete or changed as compared to the SQL result.

\ On direct SQL exports: To do direct SQL exports you may right mouse click an SQL statement or hit Ctrl+T --> sql2file
\ or check the multiple sheet export explained in the "About Exporting" link at the bottom of the export dialog.\ - \ No newline at end of file + + + +TableExportCsvDlg.excel.replace.sheets=Update existing Excel file +TableExportCsvDlg.excel.replace.sheets.infoButton=When the Excel file to export to already exists then this option, instead of replacing the complete Excel file,
\ + will add or update sheet(s) in the existing file. + +TableExportCsvDlg.lbl.sheet.name=Sheet name + + diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferences.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferences.java index 8394ea288..841044122 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferences.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferences.java @@ -77,6 +77,8 @@ public class TableExportPreferences private boolean _excelHeaderFontBold; private boolean _excelHeaderFontItalic; private boolean _excelExportSQLStatementInAdditionalSheet; + private String _excelSheetNameFileNormalized; + private boolean _excelReplaceSheets; public boolean isFormatXLS() { @@ -426,4 +428,24 @@ public void setExcelExportSQLStatementInAdditionalSheet(boolean excelExportSQLSt { _excelExportSQLStatementInAdditionalSheet = excelExportSQLStatementInAdditionalSheet; } + + public void setExcelSheetNameFileNormalized(String excelSheetNameFileNormalized) + { + _excelSheetNameFileNormalized = excelSheetNameFileNormalized; + } + + public String getExcelSheetNameFileNormalized() + { + return _excelSheetNameFileNormalized; + } + + public void setExcelReplaceSheets(boolean excelReplaceSheets) + { + _excelReplaceSheets = excelReplaceSheets; + } + + public boolean isExcelReplaceSheets() + { + return _excelReplaceSheets; + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferencesDAO.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferencesDAO.java index 3f0978827..6de58f0f8 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferencesDAO.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/fileexport/TableExportPreferencesDAO.java @@ -37,6 +37,8 @@ public class TableExportPreferencesDAO private static final String PREF_KEY_EXCEL_HEADER_FONT_BOLD = "SQuirrelSQL.csvexport.excelHeaderFontBold"; private static final String PREF_KEY_EXCEL_HEADER_FONT_ITALIC = "SQuirrelSQL.csvexport.excelHeaderFontItalic"; private static final String PREF_KEY_EXCEL_SQL_STATEMENT_IN_ADDITIONAL_SHEET = "SQuirrelSQL.csvexport.excelExportSQLStatementInAdditionalSheet"; + private static final String PREF_KEY_EXCEL_SHEET_NAME_FILE_NORMALIZED = "SQuirrelSQL.csvexport.excelSheetNameFileNormalized"; + private static final String PREF_KEY_EXCEL_REPLACE_SHEETS = "SQuirrelSQL.csvexport.excelReplaceSheets"; private static final String PREF_KEY_FORMAT_XML = "SquirrelSQL.csvexport.formatXML"; private static final String PREF_KEY_FORMAT_JSON = "SquirrelSQL.csvexport.formatJSON"; @@ -71,6 +73,8 @@ public static TableExportPreferences loadPreferences() ret.setExcelFirstRowBold(Props.getBoolean(PREF_KEY_EXCEL_FIRST_ROW_BOLD, ret.isExcelFirstRowBold())); ret.setExcelFirstRowCentered(Props.getBoolean(PREF_KEY_EXCEL_FIRST_ROW_CENTERED, ret.isExcelFirstRowCentered())); ret.setExcelExportSQLStatementInAdditionalSheet(Props.getBoolean(PREF_KEY_EXCEL_SQL_STATEMENT_IN_ADDITIONAL_SHEET, ret.isExcelExportSQLStatementInAdditionalSheet())); + ret.setExcelSheetNameFileNormalized(Props.getString(PREF_KEY_EXCEL_SHEET_NAME_FILE_NORMALIZED, ret.getExcelSheetNameFileNormalized())); + ret.setExcelReplaceSheets(Props.getBoolean(PREF_KEY_EXCEL_REPLACE_SHEETS, ret.isExcelReplaceSheets())); ret.setExcelFontNoSelection(Props.getBoolean(PREF_KEY_EXCEL_FONT_NO_SELECTION, ret.isExcelFontNoSelection())); ret.setExcelFontFamily(Props.getString(PREF_KEY_EXCEL_FONT_FAMILY, ret.getExcelFontFamily())); @@ -127,6 +131,8 @@ public static void savePreferences(TableExportPreferences prefs) Props.putBoolean(PREF_KEY_EXCEL_HEADER_FONT_BOLD, prefs.isExcelHeaderFontBold()); Props.putBoolean(PREF_KEY_EXCEL_HEADER_FONT_ITALIC, prefs.isExcelHeaderFontItalic()); Props.putBoolean(PREF_KEY_EXCEL_SQL_STATEMENT_IN_ADDITIONAL_SHEET, prefs.isExcelExportSQLStatementInAdditionalSheet()); + Props.putString(PREF_KEY_EXCEL_SHEET_NAME_FILE_NORMALIZED, prefs.getExcelSheetNameFileNormalized()); + Props.putBoolean(PREF_KEY_EXCEL_REPLACE_SHEETS, prefs.isExcelReplaceSheets()); Props.putBoolean(PREF_KEY_FORMAT_XML, prefs.isFormatXML()); Props.putBoolean(PREF_KEY_FORMAT_JSON, prefs.isFormatJSON()); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/StringUtilities.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/StringUtilities.java index babe4c2b2..af7fdd61b 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/StringUtilities.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/StringUtilities.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; - import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; import org.apache.commons.lang3.StringUtils; @@ -326,6 +325,16 @@ else if(false == ensureJavaStart && Character.isLetterOrDigit(text.charAt(0)) ) public static String fileNameNormalize(String text) { + return fileNameNormalize(text, false); + } + + public static String fileNameNormalize(String text, boolean respectNull) + { + if(respectNull && null == text) + { + return null; + } + StringBuilder buf = new StringBuilder(text.length()); for(int i=0; i < text.length(); ++i) From 23ab454b1eeb85ca4a1f86847ea8ee275b33107d Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sun, 14 Dec 2025 21:48:12 +0100 Subject: [PATCH 06/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 The options "Allow to run all SQLs in editor" and "Allow to run a SQL in all open Sessions" are now switched off by default. See menu File --> Global Preferences tab SQL. Note: This change applies only to SQuirreL user directories that did not already contain these options in their prefs.xml file. The path to SQuirreL's user directory is displayed in SQuirrel's window title. --- sql12/core/doc/changes.txt | 7 +++++++ .../client/preferences/SquirrelPreferences.java | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 0ea08f534..65c2f3580 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,13 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 + The options "Allow to run all SQLs in editor" and "Allow to run a SQL in all open Sessions" + are now switched off by default. See menu File --> Global Preferences tab SQL. + Note: This change applies only to SQuirreL user directories that did not already + contain these options in their prefs.xml file. The path to SQuirreL's user directory is displayed + in SQuirrel's window title. + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/79 MS Excel file export: The MS Excel section of the file export dialog offers two new options: 1. Option to define the name of the Excel sheet tab that is created inside the Excel file. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java index e610e00f7..bf19877be 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/SquirrelPreferences.java @@ -213,9 +213,9 @@ public interface IJdbcDebugTypes private boolean _copyQuotedSqlsToClip; - private boolean _allowRunAllSQLsInEditor = true; + private boolean _allowRunAllSQLsInEditor = false; - private boolean _allowRunSqlInAllSessions = true; + private boolean _allowRunSqlInAllSessions = false; /** Show tooltips for controls. */ private boolean _showToolTips = true; From f142b2f89d5fcf58ca8845c59972a983b04c8f3f Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Fri, 19 Dec 2025 01:07:54 +0100 Subject: [PATCH 07/33] Refactoring, removed unused code --- .../squirrel_sql/client/Application.java | 9 +- .../squirrel_sql/fw/util/IOUtilities.java | 93 +----- .../squirrel_sql/fw/util/IOUtilitiesImpl.java | 273 +----------------- .../squirrel_sql/fw/util/ProxyHandler.java | 8 +- 4 files changed, 7 insertions(+), 376 deletions(-) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/Application.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/Application.java index dc98aa17d..51e095408 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/Application.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/Application.java @@ -23,7 +23,6 @@ */ import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -267,13 +266,7 @@ public void startup() _desktopStyle = new DesktopStyle(_globalPreferences); preferencesHaveChanged(null); - _globalPreferences.addPropertyChangeListener(new PropertyChangeListener() - { - public void propertyChange(PropertyChangeEvent evt) - { - preferencesHaveChanged(evt); - } - }); + _globalPreferences.addPropertyChangeListener(evt -> preferencesHaveChanged(evt)); SquirrelSplashScreen splash = null; if (args.getShowSplashScreen()) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilities.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilities.java index e19147af1..0b38a7a92 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilities.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilities.java @@ -18,26 +18,14 @@ */ package net.sourceforge.squirrel_sql.fw.util; -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; public interface IOUtilities { - - public static String NEW_LINE = System.getProperty("line.separator"); - - String HTTP_PROTOCOL_PREFIX = "http"; - - void closeInputStream(InputStream is); - void closeOutputStream(OutputStream os); /** @@ -63,43 +51,6 @@ public interface IOUtilities * the Writer to flush. */ void flushWriter(Writer writer); - - /** - * Reads from the specified InputStream and copies bytes read to the specified OuputStream. - * - * @param is - * the InputStream to read from - * @param os - * the OutputStream to write to - * @throws IOException - * in an exception occurs while reading/writing - */ - void copyBytes(InputStream is, OutputStream os) throws IOException; - - /** - * Reads from the specified FileWrapper(from) and copies bytes read to the specified FileWrapper(to). - * - * @param from - * @param to - * @throws IOException - */ - void copyFile(FileWrapper from, FileWrapper to) throws IOException; - - /** - * Computes the CRC32 checksum for the specified file. This doesn't appear to be compatible with cksum. - * - * @param f - * the file to compute a checksum for. - * @return the checksum value for the file specified - */ - long getCheckSum(File f) throws IOException; - - /** - * @param f - * @return - * @throws IOException - */ - long getCheckSum(FileWrapper f) throws IOException; /** * Copies bytes from the specified InputStream to the specified output file. This will create the file if @@ -112,49 +63,7 @@ public interface IOUtilities * @return the number of bytes that were read and written to the file. * @throws IOException */ - public int copyBytesToFile(InputStream is, FileWrapper outputFile) throws IOException; - - /** - * Downloads a file using HTTP. - * - * @param url - * the URL of the file to be retrieved - * @param destFile - * the file to download the URL file into - * @param proxySettings - * the ProxySettings to use - * @return the number of bytes that were read and written to the file. - * @throws Exception - */ - int downloadHttpFile(final URL url, FileWrapper destFile, IProxySettings proxySettings) throws IOException; - - URL constructHttpUrl(final String host, final int port, final String fileToGet) - throws MalformedURLException; - - /** - * Reads the file specified by filename and builds a list of lines, applying the line fixers specified. - * - * @param filename - * the name of the file to read lines from. - * @param lineFixers - * a list of fixers to apply to each line. This can be null if no line manipulation is required. - * @return a list of lines - * @throws IOException - * if an I/O error occurs. - */ - List getLinesFromFile(String filename, List lineFixers) throws IOException; - - /** - * Writes the specified list of line to the specified filename. This will overrite the current contents of - * the file. - * - * @param filename - * the file to overwrite - * @param lines - * the lines to write to the file. - * @throws FileNotFoundException - */ - void writeLinesToFile(String filename, List lines) throws FileNotFoundException; + int copyBytesToFile(InputStream is, FileWrapper outputFile) throws IOException; } \ No newline at end of file diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilitiesImpl.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilitiesImpl.java index 0716d0ece..5ccc35fd4 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilitiesImpl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/IOUtilitiesImpl.java @@ -18,34 +18,15 @@ */ package net.sourceforge.squirrel_sql.fw.util; -import net.sourceforge.squirrel_sql.fw.util.log.ILogger; -import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import org.apache.commons.httpclient.Credentials; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.UsernamePasswordCredentials; -import org.apache.commons.httpclient.auth.AuthScope; -import org.apache.commons.httpclient.methods.GetMethod; - -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.PrintWriter; import java.io.Reader; import java.io.Writer; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.zip.CRC32; +import net.sourceforge.squirrel_sql.fw.util.log.ILogger; +import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; public class IOUtilitiesImpl implements IOUtilities { @@ -56,24 +37,6 @@ public class IOUtilitiesImpl implements IOUtilities /** Logger for this class. */ private final ILogger s_log = LoggerController.createLogger(IOUtilitiesImpl.class); - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities#closeInputStream(java.io.InputStream) - */ - public void closeInputStream(InputStream is) - { - if (is != null) - { - try - { - is.close(); - } - catch (Exception e) - { - s_log.error("closeInputStream: Unable to close InputStream - " + e.getMessage(), e); - } - } - } - /** * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities#closeOutputStream(java.io.OutputStream) */ @@ -146,21 +109,7 @@ public void flushWriter(Writer writer) } } } - - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities# copyBytes(java.io.InputStream, - * java.io.OutputStream) - */ - public void copyBytes(InputStream is, OutputStream os) throws IOException - { - byte[] buffer = new byte[DISK_DATA_BUFFER_SIZE]; - int length; - while ((length = is.read(buffer)) > 0) - { - os.write(buffer, 0, length); - } - } + /** * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities# copyBytesToFile(java.io.InputStream, @@ -192,220 +141,4 @@ public int copyBytesToFile(InputStream is, FileWrapper outputFile) throws IOExce } return totalLength; } - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities#getCheckSum(java.io.File) - */ - public long getCheckSum(File f) throws IOException - { - CRC32 result = new CRC32(); - FileInputStream fis = null; - try - { - fis = new FileInputStream(f); - int len = 0; - byte[] buffer = new byte[DISK_DATA_BUFFER_SIZE]; - while ((len = fis.read(buffer)) != -1) - { - result.update(buffer, 0, len); - } - } - finally - { - closeInputStream(fis); - } - return result.getValue(); - } - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities# - * getCheckSum(net.sourceforge.squirrel_sql.fw.util.FileWrapper) - */ - public long getCheckSum(FileWrapper f) throws IOException - { - return getCheckSum(new File(f.getAbsolutePath())); - } - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities# - * copyFile(net.sourceforge.squirrel_sql.fw.util.FileWrapper, - * net.sourceforge.squirrel_sql.fw.util.FileWrapper) - */ - public void copyFile(FileWrapper from, FileWrapper to) throws IOException - { - FileInputStream in = null; - FileOutputStream out = null; - try - { - in = new FileInputStream(from.getAbsolutePath()); - out = new FileOutputStream(to.getAbsolutePath()); - byte[] buffer = new byte[8192]; - int len; - while ((len = in.read(buffer)) != -1) - { - out.write(buffer, 0, len); - } - } - finally - { - closeInputStream(in); - closeOutputStream(out); - } - } - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities# constructHttpUrl(java.lang.String, int, - * java.lang.String) - */ - public URL constructHttpUrl(final String host, final int port, final String fileToGet) - throws MalformedURLException - { - URL url = null; - String server = host; - if (server.startsWith(HTTP_PROTOCOL_PREFIX)) - { - int beginIdx = server.indexOf("://") + 3; - server = server.substring(beginIdx, host.length()); - } - if (port == 80) - { - url = new URL(HTTP_PROTOCOL_PREFIX, server, fileToGet); - } - else - { - url = new URL(HTTP_PROTOCOL_PREFIX, server, port, fileToGet); - } - return url; - } - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities# downloadHttpFile(java.lang.String, int, - * java.lang.String, net.sourceforge.squirrel_sql.fw.util.FileWrapper) - */ - public int downloadHttpFile(URL url, FileWrapper destFile, IProxySettings proxySettings) - throws IOException - { - BufferedInputStream is = null; - HttpMethod method = null; - int resultCode = -1; - int result = -1; - try - { - if (s_log.isDebugEnabled()) - { - s_log.debug("downloadHttpFile: downloading file (" + destFile.getName() + ") from url: " + url); - } - HttpClient client = new HttpClient(); - setupProxy(proxySettings, client, url); - - method = new GetMethod(url.toString()); - method.setFollowRedirects(true); - - resultCode = client.executeMethod(method); - if (s_log.isDebugEnabled()) - { - s_log.debug("downloadHttpFile: response code was: " + resultCode); - } - - if (resultCode != 200) { throw new FileNotFoundException("Failed to download file from url (" + url - + "): HTTP Response Code=" + resultCode); } - InputStream mis = method.getResponseBodyAsStream(); - - is = new BufferedInputStream(mis); - - if (s_log.isDebugEnabled()) - { - s_log.debug("downloadHttpFile: writing http response body to file: " + destFile.getAbsolutePath()); - } - - result = copyBytesToFile(mis, destFile); - } - catch (IOException e) - { - s_log.error("downloadHttpFile: Unexpected exception while " - + "attempting to open an HTTP connection to url (" + url + ") to download a file (" - + destFile.getAbsolutePath() + "): " + e.getMessage(), e); - throw e; - } - finally - { - closeInputStream(is); - method.releaseConnection(); - } - return result; - } - - /** - * Setup proxy configuration specified in proxySettings. This setup is skipped if: 1) proxySettings is - * null. 2) proxySettings.getHttpUseProxy() is false (HttpClient doesn't support SOCKS proxy) 3) The url's - * host component is in the "non-proxy" host list - * - * @param proxySettings - * the ProxySettings to use - * @param client - * the instance of HttpClient to configure - * @param url - * the URL of the file to be retrieved - */ - private void setupProxy(IProxySettings proxySettings, HttpClient client, URL url) - { - if (proxySettings == null) { return; } - if (!proxySettings.getHttpUseProxy()) { return; } - if (proxySettings.getHttpNonProxyHosts() != null - && proxySettings.getHttpNonProxyHosts().contains(url.getHost())) { return; } - - String proxyHost = proxySettings.getHttpProxyServer(); - int proxyPort = Integer.parseInt(proxySettings.getHttpProxyPort()); - String proxyUsername = proxySettings.getHttpProxyUser(); - String proxyPassword = proxySettings.getHttpProxyPassword(); - - client.getHostConfiguration().setProxy(proxyHost, proxyPort); - if (proxyUsername != null && !"".equals(proxyUsername)) - { - Credentials credentials = new UsernamePasswordCredentials(proxyUsername, proxyPassword); - client.getState().setProxyCredentials(AuthScope.ANY, credentials); - } - } - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities#getLinesFromFile(java.lang.String, java.util.List) - */ - @Override - public List getLinesFromFile(String filename, List lineFixers) throws IOException - { - ArrayList lines = new ArrayList(); - - BufferedReader reader = new BufferedReader(new FileReader(filename)); - String line = null; - - while ((line = reader.readLine()) != null) - { - if (lineFixers != null) - { - for (ScriptLineFixer fixer : lineFixers) - { - line = fixer.fixLine(filename, line); - } - } - lines.add(line); - } - reader.close(); - return lines; - } - - /** - * @see net.sourceforge.squirrel_sql.fw.util.IOUtilities#writeLinesToFile(java.lang.String, java.util.List) - */ - @Override - public void writeLinesToFile(String filename, List lines) throws FileNotFoundException - { - PrintWriter out = new PrintWriter(new File(filename)); - for (String outline : lines) - { - out.write(outline); - out.write(NEW_LINE); - } - out.close(); - } - } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java index 9cf96f1fc..07943c4a1 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java @@ -17,10 +17,10 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + import java.net.Authenticator; import java.net.PasswordAuthentication; import java.util.Properties; - import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; /** @@ -42,11 +42,7 @@ public ProxyHandler() public void apply(IProxySettings proxy) { - apply(proxy, System.getProperties()); - } - - public void apply(IProxySettings proxy, Properties props) - { + Properties props = System.getProperties(); if (proxy == null) { throw new IllegalArgumentException("ProxySettings == null"); From fe354c9bead52fc4965e5d8eb01ca11cdf0a6fbf Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Fri, 19 Dec 2025 01:09:49 +0100 Subject: [PATCH 08/33] Refactoring, removed unused code --- .../net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java index 07943c4a1..eac0ec1af 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/util/ProxyHandler.java @@ -43,10 +43,6 @@ public ProxyHandler() public void apply(IProxySettings proxy) { Properties props = System.getProperties(); - if (proxy == null) - { - throw new IllegalArgumentException("ProxySettings == null"); - } final boolean http = proxy.getHttpUseProxy(); if (http) From db067bc9ed261c3e29839a5b4ad48707d9ff07c5 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Thu, 25 Dec 2025 22:50:10 +0100 Subject: [PATCH 09/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 Bookmarks Plugin: A bookmark's statement can be run from within the SQL editor use @runbookmark --- sql12/core/doc/changes.txt | 3 + .../fw/sql/querytokenizer/QueryTokenizer.java | 17 +- .../sqlbookmark/I18NStrings.properties | 7 + .../sqlbookmark/RunBookmarkTagHandler.java | 53 +++++ .../sqlbookmark/SQLBookmarkPlugin.java | 197 ++++++++---------- .../SQLBookmarkPreferencesPanel.java | 7 +- 6 files changed, 160 insertions(+), 124 deletions(-) create mode 100644 sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/RunBookmarkTagHandler.java diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 65c2f3580..33920ea01 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,9 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 + Bookmarks Plugin: A bookmark's statement can be run from within the SQL editor use @runbookmark + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 The options "Allow to run all SQLs in editor" and "Allow to run a SQL in all open Sessions" are now switched off by default. See menu File --> Global Preferences tab SQL. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/querytokenizer/QueryTokenizer.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/querytokenizer/QueryTokenizer.java index 65bee0c86..57be6f61b 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/querytokenizer/QueryTokenizer.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/querytokenizer/QueryTokenizer.java @@ -18,6 +18,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.session.action.sqlscript.SQLScriptServices; import net.sourceforge.squirrel_sql.fw.preferences.IQueryTokenizerPreferenceBean; @@ -29,13 +35,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - public class QueryTokenizer implements IQueryTokenizer { private final static ILogger s_log = LoggerController.createLogger(QueryTokenizer.class); @@ -166,8 +165,8 @@ public void setScriptToTokenize(String script, QueryTokenizePurpose queryTokeniz script = script.replace('\r', ' '); - StringBuffer curQuery = new StringBuffer(); - StringBuffer curOriginalQuery = new StringBuffer(); + StringBuilder curQuery = new StringBuilder(); + StringBuilder curOriginalQuery = new StringBuilder(); SQLCommentAndLiteralHandler commentAndLiteralHandler = new SQLCommentAndLiteralHandler(script, _lineCommentBegin, _removeMultiLineComment, _removeLineComment); ChangeStatementSeparatorSupport changeStatementSeparatorSupport = new ChangeStatementSeparatorSupport(queryTokenizePurpose, script, _lineCommentBegin); diff --git a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/I18NStrings.properties b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/I18NStrings.properties index 82178fb6b..680264f89 100644 --- a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/I18NStrings.properties +++ b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/I18NStrings.properties @@ -48,3 +48,10 @@ BookmarkEditController.duplicate.bookmark.name=A bookmark named "{0}" already ex SQLBookmarkPreferencesPanel.show.as.tree=Show user bookmarks in tree using SQLBookmarkPreferencesPanel.show.as.tree.as.path.separator=as path separator char + +RunBookmarkTagHandler.noBookmarkBeginMarker=@runbookmark tag found without bookmark to run. Bookmark name must be given after the tag in single quotes. +RunBookmarkTagHandler.noBookmarkEndMarker=@runbookmark tag found without bookmark to run. Bookmark name must be given after the tag in single quotes. +RunBookmarkTagHandler.bookmarkDoesNotExist=Bookmark named {0} does not exits. + +sqlbookmark.note.runbookmark=Note: To directly execute a bookmark's statement use @runbookmark +sqlbookmark.note.runbookmark.tooltipp=Note: To directly execute a bookmark's statement from within the SQL editor use @runbookmark \ No newline at end of file diff --git a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/RunBookmarkTagHandler.java b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/RunBookmarkTagHandler.java new file mode 100644 index 000000000..9b70f20d0 --- /dev/null +++ b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/RunBookmarkTagHandler.java @@ -0,0 +1,53 @@ +package net.sourceforge.squirrel_sql.plugins.sqlbookmark; + +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; +import org.apache.commons.lang3.StringUtils; + +public class RunBookmarkTagHandler +{ + private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(RunBookmarkTagHandler.class); + + private static final String RUN_BOOKMARK_TAG = "@runbookmark"; + + public static boolean requiresToRunBookmark(String sql) + { + return StringUtils.startsWith(StringUtils.trim(sql), RUN_BOOKMARK_TAG); + } + + public static String toBookmarkSql(String sql, BookmarkManager bookmarkManager) + { + String sqlWithBookmarkPrefix = sql; + + int bookmarkBeginMarkerPos = sqlWithBookmarkPrefix.indexOf('\''); + if(-1 == bookmarkBeginMarkerPos) + { + Main.getApplication().getMessageHandler().showErrorMessage(s_stringMgr.getString("RunBookmarkTagHandler.noBookmarkBeginMarker")); + throw new IllegalStateException("@runbookmark tag found without bookmark to run. Bookmark name must be given after the tag in single quotes."); + } + + int fileEndMarkerPos = sqlWithBookmarkPrefix.indexOf('\'', bookmarkBeginMarkerPos + 1); + if(-1 == fileEndMarkerPos) + { + Main.getApplication().getMessageHandler().showErrorMessage(s_stringMgr.getString("RunBookmarkTagHandler.noBookmarkEndMarker")); + throw new IllegalStateException("@runbookmark tag found without bookmark to run. Bookmark name must be given after the tag in single quotes."); + } + + String bookmarkName = sqlWithBookmarkPrefix.substring(bookmarkBeginMarkerPos + 1, fileEndMarkerPos).trim(); + Bookmark bookmark = bookmarkManager.get(bookmarkName); + + if(null == bookmark) + { + Main.getApplication().getMessageHandler().showErrorMessage(s_stringMgr.getString("RunBookmarkTagHandler.bookmarkDoesNotExist", bookmarkName)); + throw new IllegalStateException("Bookmark named %s does not exist".formatted(bookmarkName)); + } + + return bookmark.getSql(); + } + + public static boolean scriptContainsRunBookmarkTag(String script) + { + return StringUtils.contains(script, RUN_BOOKMARK_TAG); + } +} diff --git a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java index a63edc7d8..9d0898967 100644 --- a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java +++ b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java @@ -43,13 +43,19 @@ import net.sourceforge.squirrel_sql.client.preferences.IGlobalPreferencesPanel; import net.sourceforge.squirrel_sql.client.session.ISQLPanelAPI; import net.sourceforge.squirrel_sql.client.session.ISession; +import net.sourceforge.squirrel_sql.client.session.event.SQLExecutionAdapter; import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.ObjectTreePanel; import net.sourceforge.squirrel_sql.client.session.mainpanel.sqltab.AdditionalSQLTab; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.resources.IResources; +import net.sourceforge.squirrel_sql.fw.sql.querytokenizer.IQueryTokenizer; +import net.sourceforge.squirrel_sql.fw.sql.querytokenizer.QueryHolder; import net.sourceforge.squirrel_sql.fw.util.FileWrapper; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; +import org.apache.commons.lang3.StringUtils; /** * Main entry into the SQL Bookmark plugin. @@ -63,64 +69,40 @@ public class SQLBookmarkPlugin extends DefaultSessionPlugin { private final static ILogger s_log = LoggerController.createLogger(SQLBookmarkPlugin.class); + private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(SQLBookmarkPlugin.class); - private ArrayList _sqlPanelAPIsListeningForBookmarks = new ArrayList<>(); private static final String BOOKMARKS_PROPS_FILE = "bookmarks.properties"; static final String BOOKMARK_PROP_DEFAULT_MARKS_IN_POPUP = "squirrelMarksInPopup"; static final String BOOKMARK_PROP_USE_CONTAINS_TO_FILTER_BOOKMARKS = "useContainsToFilterBookmarks"; - private Properties _boomarkProps; - private interface IMenuResourceKeys { String BOOKMARKS = "bookmarks"; } - public static final String RESOURCE_PATH = - "net.sourceforge.squirrel_sql.plugins.sqlbookmark.sqlbookmark"; + public static final String RESOURCE_PATH = "net.sourceforge.squirrel_sql.plugins.sqlbookmark.sqlbookmark"; - private static ILogger logger = - LoggerController.createLogger(SQLBookmarkPlugin.class); + private Properties _bookmarkProps; private IResources _resources; - private IPluginResourcesFactory _resourcesFactory = new PluginResourcesFactory(); - /** - * @param resourcesFactory the resourcesFactory to set - */ - public void setResourcesFactory(IPluginResourcesFactory resourcesFactory) - { - _resourcesFactory = resourcesFactory; - } + private ArrayList _sqlPanelAPIsListeningForBookmarks = new ArrayList<>(); - /** - * The bookmark menu - */ - private JMenu menu; + private IPluginResourcesFactory _resourcesFactory = new PluginResourcesFactory(); + + private JMenu _menu; + + private BookmarkManager _bookmarkManager; - /** - * All the current bookmarkManager - */ - private BookmarkManager bookmarkManager; - /** - * Returns the plugin version. - * - * @return the plugin version. - */ public String getVersion() { return "2.0.1"; } - /** - * Returns the authors name. - * - * @return the authors name. - */ public String getAuthor() { return "Joseph Mocker"; @@ -131,99 +113,44 @@ public String getContributors() return "Gerd Wagner"; } - - /** - * Return the internal name of this plugin. - * - * @return the internal name of this plugin. - */ public String getInternalName() { return "sqlbookmark"; } - /** - * Return the descriptive name of this plugin. - * - * @return the descriptive name of this plugin. - */ public String getDescriptiveName() { return "SQL Bookmark Plugin"; } - /** - * Returns the name of the Help file for the plugin. - * - * @return the help file name. - */ public String getHelpFileName() { return "doc/readme.html"; } - /** - * Returns the name of the Help file for the plugin. - * - * @return the license file name. - */ public String getLicenceFileName() { return "licence.txt"; } - /** - * Returns the name of the change log for the plugin. This should - * be a text or HTML file residing in the getPluginAppSettingsFolder - * directory. - * - * @return the changelog file name or null if plugin doesn't have - * a change log. - */ public String getChangeLogFileName() { return "changes.txt"; } - /** - * Return the plugin resources. Used by other classes. - * - * @return plugin resources. - */ - protected IResources getResources() + IResources getResources() { return _resources; } - /** - * Get and return a string from the plugin resources. - * - * @param name name of the resource string to return. - * @return resource string. - */ - protected String getResourceString(String name) + String getResourceString(String name) { return _resources.getString(name); } - /** - * Returns a handle to the current bookmark manager. - * - * @return the bookmark manager. - */ BookmarkManager getBookmarkManager() { - return bookmarkManager; - } - - /** - * Set the bookmark manager. - * - * @param bookmarks new manager to register. - */ - protected void setBookmarkManager(BookmarkManager bookmarks) - { - this.bookmarkManager = bookmarks; + return _bookmarkManager; } @@ -232,9 +159,6 @@ public Object getExternalService() return new BookmarksExternalServiceImpl(this); } - /** - * Initialize this plugin. - */ public synchronized void initialize() throws PluginException { super.initialize(); @@ -244,17 +168,17 @@ public synchronized void initialize() throws PluginException // Load resources such as menu items, etc... _resources = _resourcesFactory.createResource(RESOURCE_PATH, this); - bookmarkManager = new BookmarkManager(this); + _bookmarkManager = new BookmarkManager(this); // Load plugin preferences. try { - bookmarkManager.load(); + _bookmarkManager.load(); } catch (IOException e) { if (!(e instanceof FileNotFoundException)) { - logger.error("Problem loading bookmarkManager", e); + s_log.error("Problem loading bookmarkManager", e); } } @@ -330,6 +254,55 @@ private void initSqlPanel(ISQLPanelAPI sqlPanelAPI) sqlPanelAPI.addToToolsPopUp("bookmarkadd", coll.get(AddBookmarkAction.class)); sqlPanelAPI.addToToolsPopUp("bookmarkedit", coll.get(EditBookmarksAction.class)); sqlPanelAPI.addToToolsPopUp("bookmarkselect", registerBookmarkSelectKeyStroke(sqlPanelAPI)); + + sqlPanelAPI.addSQLExecutionListener(new SQLExecutionAdapter(){ + @Override + public String statementExecuting(String sql) + { + return onStatementExecuting(sql, sqlPanelAPI.getSession()); + } + }); + } + + private String onStatementExecuting(String sql, ISession session) + { + if(false == RunBookmarkTagHandler.scriptContainsRunBookmarkTag(sql)) + { + return sql; + } + + IQueryTokenizer tokenizer = session.getNewQueryTokenizer(); + + tokenizer.setScriptToTokenize(sql); + + StringBuilder sb = new StringBuilder(); + + boolean changed = false; + while(tokenizer.hasQuery()) + { + QueryHolder query = tokenizer.nextQuery(); + String trimmedSql = StringUtils.trim(query.getQuery()); + + if(RunBookmarkTagHandler.requiresToRunBookmark(trimmedSql)) + { + sb.append(RunBookmarkTagHandler.toBookmarkSql(trimmedSql, _bookmarkManager)).append(tokenizer.getSQLStatementSeparator()); + changed = true; + } + else + { + sb.append(query.getOriginalQuery()).append(tokenizer.getSQLStatementSeparator()); + } + } + + + if(changed) + { + return sb.toString(); + } + else + { + return sql; + } } private CompleteBookmarkAction registerBookmarkSelectKeyStroke(ISQLPanelAPI sqlPaneAPI) @@ -350,12 +323,12 @@ protected void rebuildMenu() { ActionCollection coll = getApplication().getActionCollection(); - menu.removeAll(); - _resources.addToMenu(coll.get(AddBookmarkAction.class), menu); - _resources.addToMenu(coll.get(EditBookmarksAction.class), menu); - menu.add(new JSeparator()); + _menu.removeAll(); + _resources.addToMenu(coll.get(AddBookmarkAction.class), _menu); + _resources.addToMenu(coll.get(EditBookmarksAction.class), _menu); + _menu.add(new JSeparator()); - for (Iterator i = bookmarkManager.iterator(); i.hasNext();) + for (Iterator i = _bookmarkManager.iterator(); i.hasNext();) { Object o = i.next(); Bookmark bookmark = (Bookmark) o; @@ -388,9 +361,9 @@ private void createMenu() { IApplication app = getApplication(); - menu = _resources.createMenu(IMenuResourceKeys.BOOKMARKS); + _menu = _resources.createMenu(IMenuResourceKeys.BOOKMARKS); - app.addToMenu(IApplication.IMenuIDs.SESSION_MENU, menu); + app.addToMenu(IApplication.IMenuIDs.SESSION_MENU, _menu); } /** @@ -406,7 +379,7 @@ protected void addBookmarkItem(Bookmark bookmark) JMenuItem item = new JMenuItem(coll.get(RunBookmarkAction.class)); item.setText(bookmark.getName()); - menu.add(item); + _menu.add(item); } /** @@ -450,23 +423,23 @@ Properties getBookmarkProperties() FileInputStream fis = null; try { - if(null == _boomarkProps) + if(null == _bookmarkProps) { FileWrapper usf = getPluginUserSettingsFolder(); FileWrapper bookmarkPropsFile = fileWrapperFactory.create(usf, BOOKMARKS_PROPS_FILE); if(false == bookmarkPropsFile.exists()) { - _boomarkProps = new Properties(); + _bookmarkProps = new Properties(); } else { fis = bookmarkPropsFile.getFileInputStream(); - _boomarkProps = new Properties(); - _boomarkProps.load(fis); + _bookmarkProps = new Properties(); + _bookmarkProps.load(fis); } } - return _boomarkProps; + return _bookmarkProps; } catch (IOException e) { @@ -488,7 +461,7 @@ void saveBookmarkProperties() FileOutputStream fos = null; try { - if(null == _boomarkProps) + if(null == _bookmarkProps) { return; } @@ -496,7 +469,7 @@ void saveBookmarkProperties() FileWrapper usf = getPluginUserSettingsFolder(); FileWrapper boomarkPropsFile = fileWrapperFactory.create(usf, BOOKMARKS_PROPS_FILE); fos = boomarkPropsFile.getFileOutputStream(); - _boomarkProps.store(fos, "Bookmark properties"); + _bookmarkProps.store(fos, "Bookmark properties"); } catch (IOException e) { throw new RuntimeException(e); } finally { diff --git a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPreferencesPanel.java b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPreferencesPanel.java index 3759d4270..294b99dae 100644 --- a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPreferencesPanel.java +++ b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPreferencesPanel.java @@ -80,9 +80,10 @@ private JPanel createSouthPane(SQLBookmarkPlugin plugin) gbc = new GridBagConstraints(0,3,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0,5,5,5), 0,0); pnlSouth.add(createViewAsTreePanel(), gbc); - gbc = new GridBagConstraints(1,0,1,3,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0); - pnlSouth.add(new JPanel(), gbc); - + gbc = new GridBagConstraints(0,4,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0,5,5,5), 0,0); + JLabel lblRunBookmark = new JLabel(s_stringMgr.getString("sqlbookmark.note.runbookmark")); + lblRunBookmark.setToolTipText(s_stringMgr.getString("sqlbookmark.note.runbookmark.tooltipp")); + pnlSouth.add(lblRunBookmark, gbc); return pnlSouth; } From e5adb1becec48edd6919431ec95880e6602a1a5f Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sun, 28 Dec 2025 21:45:32 +0100 Subject: [PATCH 10/33] Rerun timer repeated --> Initial commit --- .../client/resources/SquirrelResources.java | 2 + .../client/resources/images/runTimer.png | Bin 0 -> 552 bytes .../client/resources/squirrel.properties | 2 + .../client/session/mainpanel/IResultTab.java | 14 +-- .../RerunWithTimerRepeatsManager.java | 54 +++++++++++ .../client/session/mainpanel/ResultTab.java | 84 +++++++++++------- .../session/mainpanel/ResultTabFactory.java | 6 +- .../session/mainpanel/ResultTabListener.java | 2 +- .../SQLResultExecuterPanelFacade.java | 2 +- .../mainpanel/SQLResultExecutorPanel.java | 45 ++++------ .../client/session/mainpanel/TabButton.java | 9 +- .../resulttabactions/I18NStrings.properties | 2 + .../resulttabactions/ReRunChooserCtrl.java | 80 +++++++++++++++++ .../RerunCurrentSQLResultTabAction.java | 63 +++++++++++-- .../resulttabactions/RerunResultTabMode.java | 21 +++++ .../RerunWithTimerRepeatsCtrl.java | 21 +++++ .../resulttabactions/ResultTabProvider.java | 26 ++++-- 17 files changed, 347 insertions(+), 86 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/runTimer.png create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/RerunWithTimerRepeatsManager.java create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunResultTabMode.java create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java index dfc6c220f..226aa6e75 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java @@ -231,6 +231,8 @@ public interface IImageNames String BOOKMARK_SINGLE = "bookmark_single"; String PASSWORD_12X12 = "password12x12"; + + String RUN_TIMER = "runTimer"; } public SquirrelResources(String rsrcBundleBaseName) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/runTimer.png b/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/runTimer.png new file mode 100644 index 0000000000000000000000000000000000000000..5f36b5520afff85b50244d8ece9f123fda98a727 GIT binary patch literal 552 zcmV+@0@wYCP)3FCj}4MgLn{W)}S6d)GrV}Ad)l+O|5Anq-wL{As=koYz78i z-kEu3o@WMzm}OaF7^aw}DZ}!7%`i*>x<1hKVF2lL5-CGvULjEw&^-R`pgZQ$7Ya3n#M*DO%7c&}@@jkXZ zf8*jTwRWjK^-N#C!`g41bB4yjafMffHKe1&a@FO2;0! zcT1#BM47vsK!BI;T{bs6cVJnTC`ubkM9AmAQT-F($e}jc@sm;NwSPQW_<^n~oWGRd zbV>t2?}|2X49^7^nHV2G)cN)EZ(ojHEEaK`+%_sRbMuYm6$yF&)B%M3G+_2#{lVL> zt=S71jj7HCDy1d>2POgld@8y4ZeeF6e03~B^HILVm$KU{^cF7^TK*FNm=9~ypUYBM qT_>=AOkrZ5f=K(2zOM?g2+jXIwYzQzShQ*Y0000 onTimerTriggered()); + _timer.setRepeats(true); + _timer.start(); + onTimerTriggered(); + + //reRunChooserCtrl.showStopButton(); + } + + private void onTimerTriggered() + { + // If the ResultTabData aren't new the rerun previously triggered is still running. + if(_newResultTabData) + { + _newResultTabData = false; + _currentResultTabData.resultTab.reRunSQLIntern(); + } + } + + void resultWasTabReplaced(ResultTab newResultTab, ReRunChooserCtrl newReRunChooserCtrl) + { + if(null == _timer || false == _timer.isRunning()) + { + return; + } + + initNewResultTabData(newResultTab, newReRunChooserCtrl); + } + + private void initNewResultTabData(ResultTab resultTab, ReRunChooserCtrl reRunChooserCtrl) + { + _currentResultTabData = new ResultTabData(resultTab, reRunChooserCtrl); + _currentResultTabData.reRunChooserCtrl.setResultTab(resultTab); + _newResultTabData = true; + } + +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java index 1ab21186a..0d4b2d9cf 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java @@ -23,6 +23,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.builders.UIFactory; import net.sourceforge.squirrel_sql.client.session.DataModelImplementationDetails; @@ -35,7 +50,7 @@ import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.CreateResultTabFrameAction; import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.FindInResultAction; import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.FindResultColumnAction; -import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.RerunCurrentSQLResultTabAction; +import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.ReRunChooserCtrl; import net.sourceforge.squirrel_sql.client.session.mainpanel.rowcolandsum.RowColAndSumController; import net.sourceforge.squirrel_sql.client.session.properties.SessionProperties; import net.sourceforge.squirrel_sql.fw.datasetviewer.BaseDataSetViewerDestination; @@ -65,22 +80,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.JComponent; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTabbedPane; -import javax.swing.SwingUtilities; -import java.awt.BorderLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.List; - public class ResultTab extends JPanel implements IHasIdentifier, IResultTab { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ResultTab.class); @@ -139,6 +138,10 @@ public class ResultTab extends JPanel implements IHasIdentifier, IResultTab private List _resultTabCloseListenerList = new ArrayList<>(); + private ReRunChooserCtrl _reRunChooserCtrl; + + private RerunWithTimerRepeatsManager _rerunWithTimerRepeatsManager; + /** * Ctor. * @@ -158,6 +161,8 @@ public ResultTab(ISession session, SQLResultExecuterPanelFacade sqlResultExecute { _resultTabListener = resultTabListener; _session = session; + _reRunChooserCtrl = new ReRunChooserCtrl(session); + _rerunWithTimerRepeatsManager = new RerunWithTimerRepeatsManager(); _queryInfoPanel = new QueryInfoPanel(_session); _sqlResultExecuterPanelFacade = sqlResultExecuterPanelFacade; @@ -381,6 +386,12 @@ public void addResultTabCloseListener(ResultTabCloseListener l) _resultTabCloseListenerList.add(l); } + @Override + public void removeResultTabCloseListener(ResultTabCloseListener l) + { + _resultTabCloseListenerList.remove(l); + } + public void disposeTab() { if (_metaDataDataSetViewerFindHandler != null) @@ -438,10 +449,22 @@ public JComponent getCompleteResultTab() */ public void reRunSQL() { - _resultTabListener.rerunSQL(_exInfo.getQueryHolder().getOriginalQuery(), ResultTab.this); + reRunSQLIntern(); } - - /** + + @Override + public void reRunSqlWithTimerRepeats(int repeatSeconds) + { + _rerunWithTimerRepeatsManager.startTimerRepeats(repeatSeconds, this, _reRunChooserCtrl); + } + + void reRunSQLIntern() + { + _resultTabListener.rerunSQL(_exInfo.getQueryHolder().getOriginalQuery(), this); + } + + + /** * Session properties have changed so update GUI if required. * * @param propertyName Name of property that has changed. @@ -600,7 +623,7 @@ private JPanel createTopRightButtonsPanel() ret.add(_readMoreResultsHandler.getLoadingLabel(),gbc); gbc = new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(2,10,0,0), 0,0); - ret.add(new TabButton(getRerunCurrentSQLResultTabAction()), gbc); + ret.add(_reRunChooserCtrl.getComponent(), gbc); _showCellDetailCtrl = new ShowCellDetailCtrl(this); gbc = new GridBagConstraints(2,0,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(2,2,0,0), 0,0); @@ -632,16 +655,6 @@ private JPanel createTopRightButtonsPanel() return ret; } - private RerunCurrentSQLResultTabAction getRerunCurrentSQLResultTabAction() - { - RerunCurrentSQLResultTabAction rtn = new RerunCurrentSQLResultTabAction(this); - - rtn.setSQLPanel( _session.getSQLPanelAPIOfActiveSessionWindow() ); - - return rtn; - } - - @Override public void toggleShowFindPanel() { @@ -667,8 +680,6 @@ public GlobalFindRemoteControl getDataSetViewerFindRemoteControlOfSQLQueryResult return _resultDataSetViewerFindHandler.getDataSetViewerFindRemoteControlOrNull(); } - - @Override public void findColumn() { @@ -812,4 +823,11 @@ protected void finalize() } } + + @Override + public void wasReplacedBy(ResultTab newResultTab) + { + newResultTab._rerunWithTimerRepeatsManager = _rerunWithTimerRepeatsManager; + _rerunWithTimerRepeatsManager.resultWasTabReplaced(newResultTab, newResultTab._reRunChooserCtrl); + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabFactory.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabFactory.java index 95b1ef62f..a8bf1861f 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabFactory.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabFactory.java @@ -1,5 +1,6 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel; +import java.util.ArrayList; import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.SQLExecutionInfo; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException; @@ -8,8 +9,6 @@ import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetMetaDataDataSet; import net.sourceforge.squirrel_sql.fw.id.IntegerIdentifierFactory; -import java.util.ArrayList; - public class ResultTabFactory { private IntegerIdentifierFactory _idFactory = new IntegerIdentifierFactory(); @@ -24,8 +23,7 @@ public ResultTabFactory(ISession session, SQLResultExecuterPanelFacade sqlResult public ResultTab createResultTab(SQLExecutionInfo exInfo, IDataSetUpdateableTableModel dataSetUpdateableTableModel, ResultSetDataSet rsds, ResultSetMetaDataDataSet mdds) throws DataSetException { - final ResultTabListener resultTabListener = (sql, resultTab) -> _sqlResultExecuterPanelFacade.rerunSQL(sql, resultTab); - + final ResultTabListener resultTabListener = (sql, resultTabToReplace) -> _sqlResultExecuterPanelFacade.rerunSQL(sql, resultTabToReplace); ResultTab tab = new ResultTab(_session, _sqlResultExecuterPanelFacade, _idFactory.createIdentifier(), exInfo, dataSetUpdateableTableModel, resultTabListener); tab.showResults(rsds, mdds); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabListener.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabListener.java index f32d5f05e..330bb08c2 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabListener.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTabListener.java @@ -2,5 +2,5 @@ public interface ResultTabListener { - void rerunSQL(String sql, IResultTab resultTab); + void rerunSQL(String sql, IResultTab resultTabToReplace); } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanelFacade.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanelFacade.java index d239eb1b6..759b19c03 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanelFacade.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanelFacade.java @@ -8,7 +8,7 @@ public interface SQLResultExecuterPanelFacade void createSQLResultFrame(IResultTab resultTab); - void rerunSQL(String sql, IResultTab resultTab); + void rerunSQL(String sql, IResultTab resultTabToReplace); void removeErrorPanel(ErrorPanel errorPanel); } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java index ddc1bfe2e..6f761f154 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java @@ -18,6 +18,22 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JTabbedPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.builders.UIFactory; import net.sourceforge.squirrel_sql.client.session.ISQLEntryPanel; @@ -49,23 +65,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JTabbedPane; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import java.awt.BorderLayout; -import java.awt.Component; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - /** * This is the panel where SQL scripts are executed and results presented. * @@ -144,9 +143,9 @@ public void createSQLResultFrame(IResultTab resultTab) } @Override - public void rerunSQL(String sql, IResultTab resultTab) + public void rerunSQL(String sql, IResultTab resultTabToReplace) { - SQLResultExecutorPanel.this.rerunSQL(sql, resultTab); + SQLResultExecutorPanel.this.rerunSQL(sql, resultTabToReplace); } @Override @@ -786,13 +785,7 @@ else if (null != resultTabToReplace) _resultTabClosing.closeTabAt(indexToReplace); _tabAdder.insert(getTabHeaderTitle(tab), tabIcon, tab, tab.getViewableSqlString(), indexToReplace); - - //final JLabel tabComponent = new JLabel(getTabHeaderTitle(tab)); - //_tabbedExecutionsPanel.setTabComponentAt(_tabbedExecutionsPanel.indexOfComponent(tab), tabComponent); - //if(null != tabIcon) - //{ - // _tabAdder.setIconAt(indexToReplace, tabIcon); - //} + resultTabToReplace.wasReplacedBy(tab); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TabButton.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TabButton.java index 39660aa1c..d6a3d72ee 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TabButton.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TabButton.java @@ -1,18 +1,19 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel; +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JButton; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; -import javax.swing.*; - public class TabButton extends JButton { - TabButton(Action action) + public TabButton(Action action) { super(action); GUIUtils.styleAsTabButton(this); } - TabButton() + public TabButton() { this((Action) null); } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties new file mode 100644 index 000000000..f1785192a --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties @@ -0,0 +1,2 @@ + +ReRunChooserCtrl.rerun.timered=Rerun the current tab''s SQL Query with timer ({0}) \ No newline at end of file diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java new file mode 100644 index 000000000..962dc8efe --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java @@ -0,0 +1,80 @@ +package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; + +import javax.swing.Action; +import javax.swing.JComponent; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; +import net.sourceforge.squirrel_sql.client.session.ISession; +import net.sourceforge.squirrel_sql.client.session.mainpanel.ResultTab; +import net.sourceforge.squirrel_sql.client.session.mainpanel.TabButton; +import net.sourceforge.squirrel_sql.client.shortcut.ShortcutUtil; +import net.sourceforge.squirrel_sql.fw.gui.buttonchooser.ButtonChooser; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; + +public class ReRunChooserCtrl +{ + private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ReRunChooserCtrl.class); + + private final ISession _session; + private final RerunCurrentSQLResultTabAction _actionDefault; + private final RerunCurrentSQLResultTabAction _actionTimerRepeats; + private ButtonChooser _btnChooser; + + + public ReRunChooserCtrl(ISession session) + { + _btnChooser = new ButtonChooser(); + _session = session; + _actionDefault = createDefaultReRunAction(); + _actionTimerRepeats = createTimerRepeatsReRunAction(); + + TabButton btnDefault = new TabButton(_actionDefault); + TabButton btnTimerRepeats = new TabButton(_actionTimerRepeats); + + _btnChooser.addButton(btnDefault); + _btnChooser.addButton(btnTimerRepeats); + + if(RerunResultTabMode.getCurrentMode() == RerunResultTabMode.DEFAULT) + { + _btnChooser.setSelectedButton(btnDefault); + } + else + { + _btnChooser.setSelectedButton(btnTimerRepeats); + } + + _btnChooser.setButtonSelectedListener( + (btnNew, btnOld) -> RerunResultTabMode.setCurrentMode(btnNew == btnDefault ? RerunResultTabMode.DEFAULT : RerunResultTabMode.TIMER_REPEATS)); + } + + private RerunCurrentSQLResultTabAction createTimerRepeatsReRunAction() + { + RerunCurrentSQLResultTabAction ret = createDefaultReRunAction(); + + ret.putValue(Action.SMALL_ICON, Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.RUN_TIMER)); + String description = s_stringMgr.getString("ReRunChooserCtrl.rerun.timered", ShortcutUtil.getKeystrokeString(ret.getKeyStroke())); + ret.putValue(Action.SHORT_DESCRIPTION, description); + ret.putValue(Action.LONG_DESCRIPTION, description); + + return ret; + } + + private RerunCurrentSQLResultTabAction createDefaultReRunAction() + { + RerunCurrentSQLResultTabAction ret = new RerunCurrentSQLResultTabAction(); + ret.setSQLPanel(_session.getSQLPanelAPIOfActiveSessionWindow()); + return ret; + } + + public JComponent getComponent() + { + return _btnChooser.getComponent(); + } + + public void setResultTab(ResultTab resultTab) + { + _actionDefault.setResultTab(resultTab); + _actionTimerRepeats.setResultTab(resultTab); + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java index 0869ebacd..9171893e0 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java @@ -1,18 +1,19 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; +import java.awt.Frame; +import java.awt.event.ActionEvent; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.action.SquirrelAction; import net.sourceforge.squirrel_sql.client.session.ISQLPanelAPI; import net.sourceforge.squirrel_sql.client.session.action.ISQLPanelAction; +import net.sourceforge.squirrel_sql.client.session.mainpanel.IResultTab; import net.sourceforge.squirrel_sql.client.session.mainpanel.ResultTab; -import java.awt.event.ActionEvent; - public class RerunCurrentSQLResultTabAction extends SquirrelAction implements ISQLPanelAction { private ResultTabProvider _resultTabProvider; - public RerunCurrentSQLResultTabAction(ResultTab resultTab) + public RerunCurrentSQLResultTabAction(ResultTab resultTab) { super(Main.getApplication()); _resultTabProvider = new ResultTabProvider(resultTab); @@ -28,12 +29,62 @@ public void setSQLPanel(ISQLPanelAPI panel) setEnabled(_resultTabProvider.setSQLPanelAPI(panel)); } - public synchronized void actionPerformed(ActionEvent evt) + public void actionPerformed(ActionEvent evt) { - if (_resultTabProvider.hasResultTab()) + if (false == _resultTabProvider.hasResultTab()) + { + return; + } + + switch(RerunResultTabMode.getCurrentMode()) + { + case DEFAULT -> _resultTabProvider.getResultTab().reRunSQL(); + case TIMER_REPEATS -> rerunWithTimerRepeats(); + } + } + + private void rerunWithTimerRepeats() + { + IResultTab resultTab = _resultTabProvider.getResultTab(); + if(null == resultTab) + { + return; + } + + Frame parentWindow; + + ISQLPanelAPI sqlPanelApi = _resultTabProvider.getSqlPanelApiOrNull(); + if(null == sqlPanelApi) { - _resultTabProvider.getResultTab().reRunSQL(); + parentWindow = Main.getApplication().getMainFrame(); } + else + { + parentWindow = sqlPanelApi.getOwningFrame(); + } + + RerunWithTimerRepeatsCtrl rerunWithTimerRepeatsCtrl = new RerunWithTimerRepeatsCtrl(parentWindow); + + if(false == rerunWithTimerRepeatsCtrl.isOk()) + { + return; + } + + int repeatSeconds = rerunWithTimerRepeatsCtrl.getRepeatSeconds(); + + if(0 == repeatSeconds) + { + resultTab.reRunSQL(); + } + else + { + resultTab.reRunSqlWithTimerRepeats(repeatSeconds); + } + } + + public void setResultTab(ResultTab resultTab) + { + _resultTabProvider.setResultTab(resultTab); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunResultTabMode.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunResultTabMode.java new file mode 100644 index 000000000..0bf2c6f9e --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunResultTabMode.java @@ -0,0 +1,21 @@ +package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; + +import net.sourceforge.squirrel_sql.fw.props.Props; + +public enum RerunResultTabMode +{ + DEFAULT, + TIMER_REPEATS; + + private static final String PREF_RERUN_RESULT_TAB_MODE = "RerunResultTabMode.rerun.result.tab.mode"; + + static RerunResultTabMode getCurrentMode() + { + return RerunResultTabMode.valueOf(Props.getString(PREF_RERUN_RESULT_TAB_MODE, RerunResultTabMode.DEFAULT.name())); + } + + static void setCurrentMode(RerunResultTabMode mode) + { + Props.putString(PREF_RERUN_RESULT_TAB_MODE, mode.name()); + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java new file mode 100644 index 000000000..c5ee9e20a --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java @@ -0,0 +1,21 @@ +package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; + +import java.awt.Frame; + +public class RerunWithTimerRepeatsCtrl +{ + public RerunWithTimerRepeatsCtrl(Frame parentWindow) + { + + } + + public boolean isOk() + { + return true; + } + + public int getRepeatSeconds() + { + return 1; + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ResultTabProvider.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ResultTabProvider.java index 25068ecb3..68f79e5d2 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ResultTabProvider.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ResultTabProvider.java @@ -3,20 +3,18 @@ import net.sourceforge.squirrel_sql.client.session.ISQLPanelAPI; import net.sourceforge.squirrel_sql.client.session.mainpanel.IResultTab; import net.sourceforge.squirrel_sql.client.session.mainpanel.ISQLResultExecutor; +import net.sourceforge.squirrel_sql.client.session.mainpanel.ResultTabCloseListener; public class ResultTabProvider { + private final ResultTabCloseListener _resultTabCloseListener = () -> _resultTab = null; + private ISQLPanelAPI _panel; private IResultTab _resultTab; public ResultTabProvider(IResultTab resultTab) { - _resultTab = resultTab; - - if(null != _resultTab) - { - _resultTab.addResultTabCloseListener(() -> _resultTab = null); - } + setResultTab(resultTab); } public boolean setSQLPanelAPI(ISQLPanelAPI panel) @@ -57,4 +55,20 @@ public ISQLPanelAPI getSqlPanelApiOrNull() { return _panel; } + + public void setResultTab(IResultTab resultTab) + { + if(null != _resultTab) + { + _resultTab.removeResultTabCloseListener(_resultTabCloseListener); + } + + _resultTab = resultTab; + + if(null != _resultTab) + { + _resultTab.addResultTabCloseListener(_resultTabCloseListener); + } + + } } From e93a4cfbfe7af208b957c81061c24f258e6db0da Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sun, 28 Dec 2025 22:42:10 +0100 Subject: [PATCH 11/33] Rerun timer repeated --> Stopping repeats --- .../client/resources/SquirrelResources.java | 1 + .../client/resources/images/runTimerStop.png | Bin 0 -> 327 bytes .../client/resources/squirrel.properties | 1 + .../RerunWithTimerRepeatsManager.java | 8 +++- .../resulttabactions/I18NStrings.properties | 4 +- .../resulttabactions/ReRunChooserCtrl.java | 42 +++++++++++++++--- .../fw/gui/buttonchooser/ButtonChooser.java | 33 +++++++++----- 7 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/runTimerStop.png diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java index 226aa6e75..c759804f1 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/SquirrelResources.java @@ -233,6 +233,7 @@ public interface IImageNames String PASSWORD_12X12 = "password12x12"; String RUN_TIMER = "runTimer"; + String RUN_TIMER_STOP = "runTimerStop"; } public SquirrelResources(String rsrcBundleBaseName) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/runTimerStop.png b/sql12/core/src/net/sourceforge/squirrel_sql/client/resources/images/runTimerStop.png new file mode 100644 index 0000000000000000000000000000000000000000..6ffaaf3ca9b9add1878896f4b38cd5bbb0ff95e4 GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5M?jcysy3fAQ1GXx zi(`mI@6<_-S%(b-T<7=bPn=uR`KIfFXNkyJ-zL9D8Q~nP>vsn(oGn(=ep0EdBRewJ zo`W;(+4=v*O>9X$uVO9;G;RA-_An+O!7}uVF4KE<1%?U5S>?ile=inp|GjzXJIe{h zPA(R6{YxU)?$dwOIUhp=K{lHQ^6uSf4yp&;`f68g~w*h46&SV z-|#!^*}6Rc)crhb)%HKDbPn)Re7 _timer.stop()); _newResultTabData = true; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties index f1785192a..3f917dc19 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties @@ -1,2 +1,4 @@ -ReRunChooserCtrl.rerun.timered=Rerun the current tab''s SQL Query with timer ({0}) \ No newline at end of file +ReRunChooserCtrl.rerun.timered=Rerun the current tab''s SQL Query with timer ({0}) + +ReRunChooserCtrl.rerun.timered.stop=Stop rerunning the current tab''s SQL Query \ No newline at end of file diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java index 962dc8efe..fb5271311 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java @@ -1,5 +1,9 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.stream.Stream; import javax.swing.Action; import javax.swing.JComponent; import net.sourceforge.squirrel_sql.client.Main; @@ -19,6 +23,9 @@ public class ReRunChooserCtrl private final ISession _session; private final RerunCurrentSQLResultTabAction _actionDefault; private final RerunCurrentSQLResultTabAction _actionTimerRepeats; + private final TabButton _btnReRunDefault; + private final TabButton _btnReRunTimerRepeats; + private final TabButton _btnReRunTimerRepeatsStop; private ButtonChooser _btnChooser; @@ -29,23 +36,24 @@ public ReRunChooserCtrl(ISession session) _actionDefault = createDefaultReRunAction(); _actionTimerRepeats = createTimerRepeatsReRunAction(); - TabButton btnDefault = new TabButton(_actionDefault); - TabButton btnTimerRepeats = new TabButton(_actionTimerRepeats); + _btnReRunDefault = new TabButton(_actionDefault); + _btnReRunTimerRepeats = new TabButton(_actionTimerRepeats); + _btnReRunTimerRepeatsStop = new TabButton(Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.RUN_TIMER_STOP)); - _btnChooser.addButton(btnDefault); - _btnChooser.addButton(btnTimerRepeats); + _btnChooser.addButton(_btnReRunDefault); + _btnChooser.addButton(_btnReRunTimerRepeats); if(RerunResultTabMode.getCurrentMode() == RerunResultTabMode.DEFAULT) { - _btnChooser.setSelectedButton(btnDefault); + _btnChooser.setSelectedButton(_btnReRunDefault); } else { - _btnChooser.setSelectedButton(btnTimerRepeats); + _btnChooser.setSelectedButton(_btnReRunTimerRepeats); } _btnChooser.setButtonSelectedListener( - (btnNew, btnOld) -> RerunResultTabMode.setCurrentMode(btnNew == btnDefault ? RerunResultTabMode.DEFAULT : RerunResultTabMode.TIMER_REPEATS)); + (btnNew, btnOld) -> RerunResultTabMode.setCurrentMode(btnNew == _btnReRunDefault ? RerunResultTabMode.DEFAULT : RerunResultTabMode.TIMER_REPEATS)); } private RerunCurrentSQLResultTabAction createTimerRepeatsReRunAction() @@ -77,4 +85,24 @@ public void setResultTab(ResultTab resultTab) _actionDefault.setResultTab(resultTab); _actionTimerRepeats.setResultTab(resultTab); } + + public void switchToStopButton(ActionListener stopListener) + { + cleanUp(); + _btnReRunTimerRepeatsStop.addActionListener(e -> onStopRepeats(stopListener, e)); + _btnReRunTimerRepeatsStop.setToolTipText(s_stringMgr.getString("ReRunChooserCtrl.rerun.timered.stop")); + _btnChooser.replaceButtonsBy(List.of(_btnReRunTimerRepeatsStop)); + } + + private void onStopRepeats(ActionListener stopListener, ActionEvent e) + { + stopListener.actionPerformed(e); + cleanUp(); + _btnChooser.replaceButtonsBy(List.of(_btnReRunDefault, _btnReRunTimerRepeats)); + } + + public void cleanUp() + { + Stream.of(_btnReRunTimerRepeatsStop.getActionListeners()).forEach(al -> _btnReRunTimerRepeatsStop.removeActionListener(al)); + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/buttonchooser/ButtonChooser.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/buttonchooser/ButtonChooser.java index 5ce03c8b8..14b5cf1b1 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/buttonchooser/ButtonChooser.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/buttonchooser/ButtonChooser.java @@ -1,9 +1,12 @@ package net.sourceforge.squirrel_sql.fw.gui.buttonchooser; -import net.sourceforge.squirrel_sql.client.Main; -import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; -import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; - +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.ImageIcon; @@ -13,13 +16,9 @@ import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JToolBar; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; /** * Behaves like a ComboBox with buttons in it. @@ -277,4 +276,16 @@ public void setPreferredHeight(int height) { GUIUtils.setPreferredHeight(_container, height); } + + public void replaceButtonsBy(List newButtons) + { + if(newButtons.isEmpty()) + { + throw new IllegalStateException("newButtons cannot be empty"); + } + + _buttons.clear(); + newButtons.forEach(b -> addButton(b)); + setSelectedButton(newButtons.get(newButtons.size() - 1)); + } } From a321ea063d7f255ec91eec9d94ad62c2a1e741f4 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sun, 28 Dec 2025 23:27:28 +0100 Subject: [PATCH 12/33] Rerun timer repeated --> Rerun interval dialog --- .../resulttabactions/I18NStrings.properties | 7 +- .../RerunWithTimerRepeatsCtrl.java | 35 +++++++++- .../RerunWithTimerRepeatsDlg.java | 65 +++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsDlg.java diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties index 3f917dc19..0c87740bc 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/I18NStrings.properties @@ -1,4 +1,9 @@ ReRunChooserCtrl.rerun.timered=Rerun the current tab''s SQL Query with timer ({0}) -ReRunChooserCtrl.rerun.timered.stop=Stop rerunning the current tab''s SQL Query \ No newline at end of file +ReRunChooserCtrl.rerun.timered.stop=Stop rerunning the current tab''s SQL Query + +RerunWithTimerRepeatsDlg.title=Rerun interval +RerunWithTimerRepeatsDlg.enter.repeat.interval.in.seconds=Enter rerun interval in seconds (0 means don't repeat) +RerunWithTimerRepeatsDlg.ok=Ok +RerunWithTimerRepeatsDlg.cancel=Cancel \ No newline at end of file diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java index c5ee9e20a..17d5ff8e8 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsCtrl.java @@ -1,21 +1,52 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; import java.awt.Frame; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; +import net.sourceforge.squirrel_sql.fw.props.Props; public class RerunWithTimerRepeatsCtrl { + private static final String PREFS_KEY_REPEAT_INTERVAL = "RerunWithTimerRepeatsCtrl.repeat.interval"; + + private final RerunWithTimerRepeatsDlg _dlg; + private boolean _ok; + public RerunWithTimerRepeatsCtrl(Frame parentWindow) { + _dlg = new RerunWithTimerRepeatsDlg(parentWindow); + + _dlg.txtSeconds.setInt(Props.getInt(PREFS_KEY_REPEAT_INTERVAL, 5)); + _dlg.btnOK.addActionListener(e -> onOk()); + _dlg.btnCancel.addActionListener(e -> close()); + + GUIUtils.initLocation(_dlg, 400, 130); + GUIUtils.enableCloseByEscape(_dlg); + + GUIUtils.forceFocus(_dlg.txtSeconds); + _dlg.setVisible(true); + } + + private void onOk() + { + _ok = true; + close(); + } + + private void close() + { + Props.putInt(PREFS_KEY_REPEAT_INTERVAL, _dlg.txtSeconds.getInt()); + _dlg.setVisible(true); + _dlg.dispose(); } public boolean isOk() { - return true; + return _ok; } public int getRepeatSeconds() { - return 1; + return _dlg.txtSeconds.getInt(); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsDlg.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsDlg.java new file mode 100644 index 000000000..a0ca24e9b --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunWithTimerRepeatsDlg.java @@ -0,0 +1,65 @@ +package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; + +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; +import net.sourceforge.squirrel_sql.fw.gui.IntegerField; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; + +public class RerunWithTimerRepeatsDlg extends JDialog +{ + private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(RerunWithTimerRepeatsDlg.class); + + IntegerField txtSeconds; + JButton btnOK; + JButton btnCancel; + + public RerunWithTimerRepeatsDlg(Frame parentWindow) + { + super(parentWindow, s_stringMgr.getString("RerunWithTimerRepeatsDlg.title"), true); + getContentPane().setLayout(new GridBagLayout()); + + GridBagConstraints gbc; + + gbc = new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,0,5), 0,0); + getContentPane().add(new JLabel(s_stringMgr.getString("RerunWithTimerRepeatsDlg.enter.repeat.interval.in.seconds")), gbc); + + gbc = new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,0,5), 0,0); + txtSeconds = new IntegerField(5, 0); + GUIUtils.setPreferredWidth(txtSeconds, 100); + GUIUtils.setMinimumWidth(txtSeconds, 100); + getContentPane().add(txtSeconds, gbc); + + gbc = new GridBagConstraints(0,2,2,1,0,0,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10,5,0,5), 0,0); + getContentPane().add(createButtonPanel(), gbc); + + gbc = new GridBagConstraints(0,3,2,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0); + getContentPane().add(new JPanel(), gbc); + + getRootPane().setDefaultButton(btnOK); + } + + private JPanel createButtonPanel() + { + JPanel ret = new JPanel(new GridBagLayout()); + + GridBagConstraints gbc; + + gbc = new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); + btnOK = new JButton(s_stringMgr.getString("RerunWithTimerRepeatsDlg.ok")); + ret.add(btnOK, gbc); + + gbc = new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0,5,0,0), 0,0); + btnCancel = new JButton(s_stringMgr.getString("RerunWithTimerRepeatsDlg.cancel")); + ret.add(btnCancel, gbc); + + return ret; + } +} From b5a53f398e7bd3fa20d044e330a2dea1f6f2bdce Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Mon, 29 Dec 2025 22:05:25 +0100 Subject: [PATCH 13/33] Rerun timer repeated --> Clean ups and change logging --- sql12/core/doc/changes.txt | 4 ++ .../client/session/mainpanel/IResultTab.java | 7 ++- .../RerunWithTimerRepeatsManager.java | 23 ++++++++- .../client/session/mainpanel/ResultTab.java | 17 +++++-- .../client/session/mainpanel/SQLPanel.java | 47 ++++++++++--------- .../mainpanel/SQLResultExecutorPanel.java | 3 +- .../CreateResultTabFrameAction.java | 4 +- .../ShowCellDetailCtrl.java | 20 ++++++-- 8 files changed, 86 insertions(+), 39 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 33920ea01..76452811a 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,10 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/80 + SQL results can be rerun automatically after a configurable number of seconds. + To give access to this function the SQL result's rerun button was made switchable. + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 Bookmarks Plugin: A bookmark's statement can be run from within the SQL editor use @runbookmark diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java index 631f83ad6..66c9e1e30 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java @@ -109,5 +109,10 @@ public interface IResultTab GlobalFindRemoteControl getDataSetViewerFindRemoteControlOfSQLQueryResultTabOrNull(); - void wasReplacedBy(ResultTab tab); + /** + * Is called before the {@link ResultTabCloseListener] of the previous {@link ResultTab} is fired. + */ + void aboutToBeReplacedBy(ResultTab tab); + + void prepareBeingMovedToResultFrame(); } \ No newline at end of file diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/RerunWithTimerRepeatsManager.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/RerunWithTimerRepeatsManager.java index a7fc3fd1b..afdfaedb9 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/RerunWithTimerRepeatsManager.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/RerunWithTimerRepeatsManager.java @@ -1,11 +1,13 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel; +import java.util.List; import javax.swing.Timer; import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.ReRunChooserCtrl; public class RerunWithTimerRepeatsManager { private Timer _timer; + private ResultTabCloseListener _resultTabCloseListener = () -> disposeTimer(); private record ResultTabData(ResultTab resultTab, ReRunChooserCtrl reRunChooserCtrl){} @@ -16,6 +18,7 @@ void startTimerRepeats(int repeatSeconds, ResultTab resultTab, ReRunChooserCtrl { initNewResultTabData(resultTab, reRunChooserCtrl); + disposeTimer(); _timer = new Timer(1000 * repeatSeconds, e -> onTimerTriggered()); _timer.setRepeats(true); _timer.start(); @@ -32,7 +35,7 @@ private void onTimerTriggered() } } - void resultWasTabReplaced(ResultTab newResultTab, ReRunChooserCtrl newReRunChooserCtrl) + void aboutToBeReplacedBy(ResultTab newResultTab, ReRunChooserCtrl newReRunChooserCtrl) { if(null == _timer || false == _timer.isRunning()) { @@ -42,16 +45,32 @@ void resultWasTabReplaced(ResultTab newResultTab, ReRunChooserCtrl newReRunChoos initNewResultTabData(newResultTab, newReRunChooserCtrl); } + public void disposeTimer() + { + if(null == _timer) + { + return; + } + _timer.stop(); + List.of(_timer.getActionListeners()).forEach(l -> _timer.removeActionListener(l)); + } + + private void initNewResultTabData(ResultTab resultTab, ReRunChooserCtrl reRunChooserCtrl) { if(null != _currentResultTabData) { _currentResultTabData.reRunChooserCtrl.cleanUp(); + + // Note: When this method is called by aboutToBeReplacedBy() this method will be called before the ResultTabCloseListener is fired. + // The following command makes sure that disposeTimer() isn't called when the ResultTab is replaced + _currentResultTabData.resultTab.removeResultTabCloseListener(_resultTabCloseListener); } _currentResultTabData = new ResultTabData(resultTab, reRunChooserCtrl); _currentResultTabData.reRunChooserCtrl.setResultTab(resultTab); - _currentResultTabData.reRunChooserCtrl.switchToStopButton(e -> _timer.stop()); + _currentResultTabData.reRunChooserCtrl.switchToStopButton(e -> disposeTimer()); + _currentResultTabData.resultTab.addResultTabCloseListener(_resultTabCloseListener); _newResultTabData = true; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java index 0d4b2d9cf..5d0b0b59b 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java @@ -139,8 +139,7 @@ public class ResultTab extends JPanel implements IHasIdentifier, IResultTab private List _resultTabCloseListenerList = new ArrayList<>(); private ReRunChooserCtrl _reRunChooserCtrl; - - private RerunWithTimerRepeatsManager _rerunWithTimerRepeatsManager; + private RerunWithTimerRepeatsManager _rerunWithTimerRepeatsManager = new RerunWithTimerRepeatsManager(); /** * Ctor. @@ -162,7 +161,6 @@ public ResultTab(ISession session, SQLResultExecuterPanelFacade sqlResultExecute _resultTabListener = resultTabListener; _session = session; _reRunChooserCtrl = new ReRunChooserCtrl(session); - _rerunWithTimerRepeatsManager = new RerunWithTimerRepeatsManager(); _queryInfoPanel = new QueryInfoPanel(_session); _sqlResultExecuterPanelFacade = sqlResultExecuterPanelFacade; @@ -824,10 +822,19 @@ protected void finalize() } } + /** + * Is called before the {@link ResultTabCloseListener] of the previous {@link ResultTab} is fired. + */ @Override - public void wasReplacedBy(ResultTab newResultTab) + public void aboutToBeReplacedBy(ResultTab newResultTab) { newResultTab._rerunWithTimerRepeatsManager = _rerunWithTimerRepeatsManager; - _rerunWithTimerRepeatsManager.resultWasTabReplaced(newResultTab, newResultTab._reRunChooserCtrl); + _rerunWithTimerRepeatsManager.aboutToBeReplacedBy(newResultTab, newResultTab._reRunChooserCtrl); + } + + @Override + public void prepareBeingMovedToResultFrame() + { + _rerunWithTimerRepeatsManager.disposeTimer(); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLPanel.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLPanel.java index 771847dc6..3b51f1ec5 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLPanel.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLPanel.java @@ -23,6 +23,28 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import javax.swing.Action; +import javax.swing.Box; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.builders.UIFactory; @@ -49,29 +71,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringUtilities; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; - -import javax.swing.Action; -import javax.swing.Box; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JSplitPane; -import javax.swing.JTabbedPane; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; /** * This is the panel where SQL scripts can be entered and executed. * @@ -397,6 +396,8 @@ public void sessionWorksheetOrTabClosing() _resultTabMatchingCurrentSqlHandler.close(); _sqlPanelListenerManager.fireSQLPanelParentClosing(); + + _panelAPI.closeAllSQLResultTabs(); } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java index 6f761f154..f5f84b73e 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java @@ -782,10 +782,11 @@ else if (null != resultTabToReplace) } else { + // We need to make sure this is fired before the ResultTabCloseListener of resultTabToReplace is fired. + resultTabToReplace.aboutToBeReplacedBy(tab); _resultTabClosing.closeTabAt(indexToReplace); _tabAdder.insert(getTabHeaderTitle(tab), tabIcon, tab, tab.getViewableSqlString(), indexToReplace); - resultTabToReplace.wasReplacedBy(tab); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/CreateResultTabFrameAction.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/CreateResultTabFrameAction.java index 02a7a1471..08529d19d 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/CreateResultTabFrameAction.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/CreateResultTabFrameAction.java @@ -1,13 +1,12 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; +import java.awt.event.ActionEvent; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.action.SquirrelAction; import net.sourceforge.squirrel_sql.client.session.ISQLPanelAPI; import net.sourceforge.squirrel_sql.client.session.action.ISQLPanelAction; import net.sourceforge.squirrel_sql.client.session.mainpanel.ResultTab; -import java.awt.event.ActionEvent; - public class CreateResultTabFrameAction extends SquirrelAction implements ISQLPanelAction { private ResultTabProvider _resultTabProvider; @@ -36,6 +35,7 @@ public void actionPerformed(ActionEvent evt) { if(_resultTabProvider.hasResultTab()) { + _resultTabProvider.getResultTab().prepareBeingMovedToResultFrame(); _resultTabProvider.getResultTab().getSQLResultExecuterPanelFacade().createSQLResultFrame(_resultTabProvider.getResultTab()); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ShowCellDetailCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ShowCellDetailCtrl.java index e1eb7cbd9..22a3409f9 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ShowCellDetailCtrl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ShowCellDetailCtrl.java @@ -1,15 +1,15 @@ package net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice; +import javax.swing.JToggleButton; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; +import net.sourceforge.squirrel_sql.client.session.mainpanel.IResultTab; import net.sourceforge.squirrel_sql.client.session.mainpanel.ResultTab; import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.ResultTabProvider; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import javax.swing.JToggleButton; - public class ShowCellDetailCtrl { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ShowCellDetailCtrl.class); @@ -60,11 +60,21 @@ else if(false == selectedTabsDisplayHandler.getCellDetailDisplayAvailableInfo(). public void finishedCreatingResultTab() { - ResultDataSetAndCellDetailDisplayHandler selectedTabsDisplayHandler = _resultTabProvider.getResultTab().getSelectedResultTabsDisplayHandler(); - if(null != selectedTabsDisplayHandler) + IResultTab resultTab = _resultTabProvider.getResultTab(); + + if(null == resultTab) { - selectedTabsDisplayHandler.setCloseListener(() -> onClosedByPanelButton()); + return; } + + ResultDataSetAndCellDetailDisplayHandler selectedResultTabsDisplayHandler = resultTab.getSelectedResultTabsDisplayHandler(); + + if(null == selectedResultTabsDisplayHandler) + { + return; + } + + selectedResultTabsDisplayHandler.setCloseListener(() -> onClosedByPanelButton()); } private void onClosedByPanelButton() From 14081fb9962cb7b9078019ca9f363fe844cfcb07 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 17 Jan 2026 18:58:00 +0100 Subject: [PATCH 14/33] SQL result displayed in new window: Improved UI behavior --- .../client/session/mainpanel/IResultTab.java | 1 + .../client/session/mainpanel/ResultFrame.java | 63 ++++++----- .../client/session/mainpanel/ResultTab.java | 1 + .../MarkDuplicatesToggleAction.java | 16 ++- .../MarkDuplicatesChooserController.java | 58 ++++------ .../MarkDuplicatesStateHandler.java | 103 +++++++++++++++++ .../squirrel_sql/fw/gui/GUIUtils.java | 107 +++++++++++------- 7 files changed, 246 insertions(+), 103 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java index 66c9e1e30..97a2b4fed 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java @@ -74,6 +74,7 @@ public interface IResultTab void reRunSqlWithTimerRepeats(int repeatSeconds); TableState getResultSortableTableState(); + void applyResultSortableTableState(TableState tableState); void toggleShowFindPanel(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java index 242d17a47..ba9b48546 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java @@ -20,6 +20,20 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Insets; +import java.util.ArrayList; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DialogWidget; @@ -33,16 +47,14 @@ import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetUpdateableTableModel; import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet; import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetMetaDataDataSet; +import net.sourceforge.squirrel_sql.fw.datasetviewer.TableState; import net.sourceforge.squirrel_sql.fw.datasetviewer.coloring.markduplicates.MarkDuplicatesChooserController; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; - /** * JASON: Rename to ResultInternalFrame * Torn off frame that contains SQL results. @@ -69,22 +81,6 @@ public class ResultFrame extends SessionDialogWidget private JPanel _centerPanel; private RowColAndSumController _rowColAndSumController = new RowColAndSumController(); - /** - * Ctor. - * - * - * - * - * - * @param session Current session. - * @param resultTab SQL results tab. - * - * @param resultTabFactory - * @param resultFrameListener - *@param isOnRerun @throws IllegalArgumentException - * If a null ISession or - * ResultTab passed. - */ public ResultFrame(final ISession session, IResultTab resultTab, ResultTabFactory resultTabFactory, ResultFrameListener resultFrameListener, boolean checkStayOnTop, boolean isOnRerun) { super(getFrameTitle(session, resultTab), true, true, true, true, session); @@ -189,7 +185,7 @@ private void onSetCancelPanel(final CancelPanelCtrl cancelPanelCtrl) public void run() { _centerPanel.removeAll(); - _centerPanel.add(cancelPanelCtrl.getPanel(), BorderLayout.CENTER); + _centerPanel.add(cancelPanelCtrl.getPanel()); } }); } @@ -211,13 +207,26 @@ private void showRerunResultsInNewFrame(SQLExecutionInfo info, IDataSetUpdateabl try { _centerPanel.removeAll(); - ResultTab tab = _resultTabFactory.createResultTab(info, creator, rsds, rsmdds); - ResultFrame frame = new ResultFrame(_session, tab, _resultTabFactory, _resultFrameListener, _chkOnTop.isSelected(), true); - showFrame(frame, true); - setVisible(false); - dispose(); - _resultFrameListener.frameReplaced(ResultFrame.this, frame); + TableState tableState = null; + + if(null != _resultTab) + { + tableState = _resultTab.getResultSortableTableState(); + } + + _resultTab = _resultTabFactory.createResultTab(info, creator, rsds, rsmdds); + JTabbedPane tabbedPaneOfResultTabs = _resultTab.getTabbedPaneOfResultTabs(); + GUIUtils.unconventionallyAddToParentWithRepaint(_centerPanel, tabbedPaneOfResultTabs); + _markDuplicatesChooserController.init(_resultTab); + + if(null != tableState) + { + _resultTab.applyResultSortableTableState(tableState); + } + + _btnReturnToTab.setEnabled(true); + _btnReRun.setEnabled(true); } catch (Throwable t) { diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java index 5d0b0b59b..1ca9cf0d1 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java @@ -731,6 +731,7 @@ public TableState getResultSortableTableState() return _resultDataSetViewerFindHandler.getDataSetViewer().getResultSortableTableState(); } + @Override public void applyResultSortableTableState(TableState sortableTableState) { _resultDataSetViewerFindHandler.getDataSetViewer().applyResultSortableTableState(sortableTableState); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/MarkDuplicatesToggleAction.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/MarkDuplicatesToggleAction.java index cf2efbfba..ec13fea5f 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/MarkDuplicatesToggleAction.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/MarkDuplicatesToggleAction.java @@ -1,13 +1,12 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions; +import java.awt.event.ActionEvent; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.action.SquirrelAction; import net.sourceforge.squirrel_sql.client.session.ISQLPanelAPI; import net.sourceforge.squirrel_sql.client.session.action.ISQLPanelAction; import net.sourceforge.squirrel_sql.client.session.mainpanel.IResultTab; -import java.awt.event.ActionEvent; - public class MarkDuplicatesToggleAction extends SquirrelAction implements ISQLPanelAction { private ResultTabProvider _resultTabProvider; @@ -31,6 +30,18 @@ public MarkDuplicatesToggleAction() public void setSQLPanel(ISQLPanelAPI panel) { _resultTabProvider.setSQLPanelAPI(panel); + doEnable(); + } + + public void setResultTab(IResultTab resultTab) + { + _resultTabProvider.setResultTab(resultTab); + doEnable(); + } + + private void doEnable() + { + setEnabled(_resultTabProvider.hasResultTab()); } public void actionPerformed(ActionEvent evt) @@ -39,6 +50,5 @@ public void actionPerformed(ActionEvent evt) { _resultTabProvider.getResultTab().markDuplicates(evt); } - } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesChooserController.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesChooserController.java index 3f69398bd..41b7d71af 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesChooserController.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesChooserController.java @@ -1,30 +1,27 @@ package net.sourceforge.squirrel_sql.fw.datasetviewer.coloring.markduplicates; +import java.awt.event.ActionEvent; +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import javax.swing.JToggleButton; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.session.mainpanel.IResultTab; -import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.MarkDuplicatesToggleAction; -import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTablePanel; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetViewer; import net.sourceforge.squirrel_sql.fw.gui.buttonchooser.ButtonChooser; -import net.sourceforge.squirrel_sql.fw.gui.table.SortableTableModel; import net.sourceforge.squirrel_sql.fw.props.Props; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.JToggleButton; -import java.awt.event.ActionEvent; - public class MarkDuplicatesChooserController { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(MarkDuplicatesChooserController.class); - private final IDataSetViewer _sqlResultDataSetViewer; private ButtonChooser _toggleBtnChooser; private static final String PREF_MARK_DUPLICATES_MODE_LAST_MODE = "MarkDuplicatesMode.last.mode"; + private MarkDuplicatesStateHandler _markDuplicatesStateHandler = null; + private boolean _dontReactToEvents = false; @@ -40,23 +37,17 @@ public MarkDuplicatesChooserController(IResultTab resultTab) private MarkDuplicatesChooserController(IDataSetViewer dataSetViewer, IResultTab resultTab) { - _sqlResultDataSetViewer = dataSetViewer; _toggleBtnChooser = new ButtonChooser(); + _markDuplicatesStateHandler = new MarkDuplicatesStateHandler(e -> actionWasFired(e), + tableSortingAdmin -> onTableSorted(), + () -> onColumnMoved()); + + _markDuplicatesStateHandler.init(dataSetViewer, resultTab); + for (MarkDuplicatesMode mode : MarkDuplicatesMode.values()) { - JToggleButton btn; - if(null != resultTab) - { - // MarkDuplicatesToggleAction results in call of actionWasFired(...) - btn = new JToggleButton(new MarkDuplicatesToggleAction(resultTab)); - } - else - { - btn = new JToggleButton(); - btn.addActionListener(e -> actionWasFired(e)); - } - + JToggleButton btn = new JToggleButton(_markDuplicatesStateHandler.getAction()); btn.setIcon(mode.getIcon()); btn.setText(mode.getText()); btn.setToolTipText(mode.getToolTipText()); @@ -67,17 +58,6 @@ private MarkDuplicatesChooserController(IDataSetViewer dataSetViewer, IResultTab _toggleBtnChooser.setSelectedButton(getLastMode().findButton(_toggleBtnChooser)); _toggleBtnChooser.setButtonSelectedListener((newSelectedButton, formerSelectedButton) -> onButtonSelected((JToggleButton)newSelectedButton, (JToggleButton)formerSelectedButton)); - - if(_sqlResultDataSetViewer instanceof DataSetViewerTablePanel) - { - SortableTableModel sortableTableModel = ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getSortableTableModel(); - sortableTableModel.addSortingListener(tableSortingAdmin -> onTableSorted()); - } - - if(_sqlResultDataSetViewer instanceof DataSetViewerTablePanel) - { - ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getButtonTableHeader().setDraggedColumnListener(() -> onColumnMoved()); - } } private void onColumnMoved() @@ -190,7 +170,7 @@ public boolean actionWasFired(ActionEvent e) private void doMarkDuplicates() { - if(false == _sqlResultDataSetViewer instanceof DataSetViewerTablePanel) + if(false == _markDuplicatesStateHandler.hasDatasetViewerTablePanel()) { Main.getApplication().getMessageHandler().showWarningMessage(s_stringMgr.getString("MarkDuplicatesChooserController.mark.duplicates.for.table.output.only")); return; @@ -205,7 +185,7 @@ private void doMarkDuplicates() mode = MarkDuplicatesMode.getModeByButton(_toggleBtnChooser.getSelectedButton()); } - ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getColoringService().getMarkDuplicatesHandler().markDuplicates(mode); + _markDuplicatesStateHandler.markDuplicates(mode); } public void copyStateFrom(MarkDuplicatesChooserController controllerToCopyFrom) @@ -234,4 +214,12 @@ public void copyStateFrom(MarkDuplicatesChooserController controllerToCopyFrom) } } + public void init(IResultTab resultTab) + { + init(resultTab.getSQLResultDataSetViewer(), resultTab); + } + public void init(IDataSetViewer dataSetViewer, IResultTab resultTab) + { + _markDuplicatesStateHandler.init(dataSetViewer, resultTab); + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java new file mode 100644 index 000000000..6b319fc97 --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java @@ -0,0 +1,103 @@ +package net.sourceforge.squirrel_sql.fw.datasetviewer.coloring.markduplicates; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.AbstractAction; +import javax.swing.Action; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.client.session.mainpanel.IResultTab; +import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.MarkDuplicatesToggleAction; +import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTablePanel; +import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetViewer; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; +import net.sourceforge.squirrel_sql.fw.gui.table.ButtonTableHeaderDraggedColumnListener; +import net.sourceforge.squirrel_sql.fw.gui.table.SortableTableModel; +import net.sourceforge.squirrel_sql.fw.gui.table.SortingListener; + +public class MarkDuplicatesStateHandler +{ + private final ActionListener _noResultTabFallBackActionListener; + private final SortingListener _tableSortingListener; + private final ButtonTableHeaderDraggedColumnListener _buttonTableHeaderDraggedColumnListener; + private Action _actionProxy; + + private IDataSetViewer _sqlResultDataSetViewer; + private IResultTab _resultTab; + private MarkDuplicatesToggleAction _proxyDelegate; + + public MarkDuplicatesStateHandler(ActionListener noResultTabFallBackActionListener, + SortingListener tableSortingListener, + ButtonTableHeaderDraggedColumnListener buttonTableHeaderDraggedColumnListener) + { + _noResultTabFallBackActionListener = noResultTabFallBackActionListener; + _tableSortingListener = tableSortingListener; + _buttonTableHeaderDraggedColumnListener = buttonTableHeaderDraggedColumnListener; + + _actionProxy = new AbstractAction() + { + @Override + public void actionPerformed(ActionEvent e) + { + if(null == _proxyDelegate) + { + _noResultTabFallBackActionListener.actionPerformed(e); + } + else + { + _proxyDelegate.actionPerformed(e); + } + } + }; + + GUIUtils.copyAllActionProperties(Main.getApplication().getActionCollection().get(MarkDuplicatesToggleAction.class), _actionProxy); + } + + public Action getAction() + { + return _actionProxy; + } + + public void init(IDataSetViewer dataSetViewer, IResultTab resultTab) + { + _sqlResultDataSetViewer = dataSetViewer; + _resultTab = resultTab; + + _proxyDelegate = null; + if(null != _resultTab) + { + _proxyDelegate = new MarkDuplicatesToggleAction(_resultTab); + } + + if(null != _resultTab) + { + _sqlResultDataSetViewer = _resultTab.getSQLResultDataSetViewer(); + } + + if(_sqlResultDataSetViewer instanceof DataSetViewerTablePanel) + { + SortableTableModel sortableTableModel = ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getSortableTableModel(); + sortableTableModel.addSortingListener(_tableSortingListener); + } + + if(_sqlResultDataSetViewer instanceof DataSetViewerTablePanel) + { + ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getButtonTableHeader().setDraggedColumnListener(_buttonTableHeaderDraggedColumnListener); + } + } + + public boolean hasDatasetViewerTablePanel() + { + return _sqlResultDataSetViewer instanceof DataSetViewerTablePanel; + } + + /** + * Maybe should be moved to {@link MarkDuplicatesChooserController} + */ + public void markDuplicates(MarkDuplicatesMode mode) + { + if(hasDatasetViewerTablePanel()) + { + ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getColoringService().getMarkDuplicatesHandler().markDuplicates(mode); + } + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/GUIUtils.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/GUIUtils.java index 8e0df75ad..b0e8fd000 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/GUIUtils.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/GUIUtils.java @@ -18,44 +18,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DialogWidget; -import net.sourceforge.squirrel_sql.fw.props.Props; -import net.sourceforge.squirrel_sql.fw.util.StringManager; -import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import net.sourceforge.squirrel_sql.fw.util.Utilities; -import net.sourceforge.squirrel_sql.fw.util.log.ILogger; -import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import org.apache.commons.lang3.StringUtils; - -import javax.swing.AbstractAction; -import javax.swing.AbstractButton; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JInternalFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.JToggleButton; -import javax.swing.JTree; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.ToolTipManager; -import javax.swing.plaf.TextUI; -import javax.swing.text.BadLocationException; -import javax.swing.text.Position; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -96,6 +58,45 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.ToolTipManager; +import javax.swing.plaf.TextUI; +import javax.swing.text.BadLocationException; +import javax.swing.text.Position; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DialogWidget; +import net.sourceforge.squirrel_sql.fw.props.Props; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; +import net.sourceforge.squirrel_sql.fw.util.Utilities; +import net.sourceforge.squirrel_sql.fw.util.log.ILogger; +import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; +import org.apache.commons.lang3.StringUtils; /** * Common GUI utilities accessed via static methods. @@ -1385,4 +1386,34 @@ public static BufferedImage scaleImage(BufferedImage originalImage, int newWidth return scaledImage; } + + public static void unconventionallyAddToParentWithRepaint(JPanel parent, JComponent child) + { + JFrame f = new JFrame(); + f.getContentPane().setLayout(new GridLayout(1,1)); + f.getContentPane().add(child); + f.setSize(5,5); + //f.setVisible(true); + + SwingUtilities.invokeLater(() -> + { + f.setVisible(false); + f.getContentPane().remove(child); + f.dispose(); + parent.add(child); + parent.doLayout(); + }); + } + + public static void copyAllActionProperties(Action from, Action to) + { + to.putValue(Action.NAME, from.getValue(Action.NAME)); + to.putValue(Action.ACTION_COMMAND_KEY, from.getValue(Action.ACTION_COMMAND_KEY)); + to.putValue(Action.SMALL_ICON, from.getValue(Action.SMALL_ICON)); + to.putValue(Action.LARGE_ICON_KEY, from.getValue(Action.LARGE_ICON_KEY)); + to.putValue(Action.MNEMONIC_KEY, from.getValue(Action.MNEMONIC_KEY)); + to.putValue(Action.ACCELERATOR_KEY, from.getValue(Action.ACCELERATOR_KEY)); + to.putValue(Action.SHORT_DESCRIPTION, from.getValue(Action.SHORT_DESCRIPTION)); + to.putValue(Action.LONG_DESCRIPTION, from.getValue(Action.LONG_DESCRIPTION)); + } } From f40c01f26dfb4b3f9276377e4b82046d450bc13a Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 17 Jan 2026 22:12:27 +0100 Subject: [PATCH 15/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/80 SQL results displayed in their own window can be rerun automatically, too. The UI behavior of SQL results displayed in their own window was improved. --- sql12/core/doc/changes.txt | 4 ++ .../client/session/mainpanel/IResultTab.java | 11 ++++ .../client/session/mainpanel/ResultFrame.java | 50 ++++++++----------- .../client/session/mainpanel/ResultTab.java | 24 ++++++++- .../resulttabactions/ReRunChooserCtrl.java | 18 +++---- .../RerunCurrentSQLResultTabAction.java | 9 +++- 6 files changed, 75 insertions(+), 41 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 76452811a..f72c2d535 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,10 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/80 + SQL results displayed in their own window can be rerun automatically, too. + The UI behavior of SQL results displayed in their own window was improved. + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/80 SQL results can be rerun automatically after a configurable number of seconds. To give access to this function the SQL result's rerun button was made switchable. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java index 97a2b4fed..046cc25d0 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/IResultTab.java @@ -22,6 +22,7 @@ import java.awt.event.ActionEvent; import javax.swing.JComponent; import javax.swing.JTabbedPane; +import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.ReRunChooserCtrl; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetViewer; import net.sourceforge.squirrel_sql.fw.datasetviewer.TableState; import net.sourceforge.squirrel_sql.fw.datasetviewer.coloring.markduplicates.MarkDuplicatesChooserController; @@ -115,5 +116,15 @@ public interface IResultTab */ void aboutToBeReplacedBy(ResultTab tab); + /** + * Is called before the {@link ResultTabCloseListener] of the previous {@link ResultTab} is fired. + */ + void aboutToBeReplacedBy(ResultTab newResultTab, ReRunChooserCtrl reRunChooserCtrl); + void prepareBeingMovedToResultFrame(); + + /** + * @return The previous {@link ResultTabListener} + */ + ResultTabListener replaceResultTabListener(ResultTabListener resultTabListener); } \ No newline at end of file diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java index ba9b48546..08161f764 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultFrame.java @@ -43,6 +43,7 @@ import net.sourceforge.squirrel_sql.client.session.SQLExecutionInfo; import net.sourceforge.squirrel_sql.client.session.action.ReturnResultTabAction; import net.sourceforge.squirrel_sql.client.session.event.ISQLExecutionListener; +import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabactions.ReRunChooserCtrl; import net.sourceforge.squirrel_sql.client.session.mainpanel.rowcolandsum.RowColAndSumController; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetUpdateableTableModel; import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet; @@ -77,17 +78,21 @@ public class ResultFrame extends SessionDialogWidget private TabButton _btnFindColumn; private MarkDuplicatesChooserController _markDuplicatesChooserController; private JCheckBox _chkOnTop; - private TabButton _btnReRun; private JPanel _centerPanel; private RowColAndSumController _rowColAndSumController = new RowColAndSumController(); + private final ResultTabListener _originalResultTabListener; + + private ReRunChooserCtrl _reRunChooserCtrl; public ResultFrame(final ISession session, IResultTab resultTab, ResultTabFactory resultTabFactory, ResultFrameListener resultFrameListener, boolean checkStayOnTop, boolean isOnRerun) { super(getFrameTitle(session, resultTab), true, true, true, true, session); _session = session; _resultTab = resultTab; + _originalResultTabListener = _resultTab.replaceResultTabListener((sql, resultTabToReplace) -> onRerun()); _resultTabFactory = resultTabFactory; _resultFrameListener = resultFrameListener; + _reRunChooserCtrl = new ReRunChooserCtrl(_resultTab); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); @@ -103,8 +108,6 @@ public ResultFrame(final ISession session, IResultTab resultTab, ResultTabFactor _chkOnTop.addActionListener(e -> onStayOnTopChanged()); - _btnReRun.addActionListener(e -> onRerun()); - _btnToggleFind.addActionListener(e -> onFind()); _btnFindColumn.addActionListener(e -> onFindColumn()); @@ -128,7 +131,7 @@ private void onFindColumn() private void onRerun() { _btnReturnToTab.setEnabled(false); - _btnReRun.setEnabled(false); + //_reRunChooserCtrl.setEnabled(false); _centerPanel.removeAll(); new SQLExecutionHandler(_resultTab, _session, _resultTab.getSqlString(), createSQLExecutionHandlerListener(), new ISQLExecutionListener[0]); } @@ -173,7 +176,7 @@ public void run() ErrorPanel errorPanel = _resultTabFactory.createErrorPanel(sqlExecErrorMsgs, lastExecutedStatement); errorPanel.hideCloseButton(); _centerPanel.add(errorPanel); - _btnReRun.setEnabled(true); + //_reRunChooserCtrl.setEnabled(true); } }); } @@ -199,10 +202,10 @@ private void onRemoveCancelPanel(final CancelPanelCtrl cancelPanelCtrl, IResultT private void onAddResultsTab(final SQLExecutionInfo info, final ResultSetDataSet rsds, final ResultSetMetaDataDataSet rsmdds, final IDataSetUpdateableTableModel creator, IResultTab resultTabToReplace) { // We start a new frame here because reusing the current one for the new result led to repaint problems - SwingUtilities.invokeLater(() -> showRerunResultsInNewFrame(info, creator, rsds, rsmdds)); + SwingUtilities.invokeLater(() -> showRerunResult(info, creator, rsds, rsmdds)); } - private void showRerunResultsInNewFrame(SQLExecutionInfo info, IDataSetUpdateableTableModel creator, ResultSetDataSet rsds, ResultSetMetaDataDataSet rsmdds) + private void showRerunResult(SQLExecutionInfo info, IDataSetUpdateableTableModel creator, ResultSetDataSet rsds, ResultSetMetaDataDataSet rsmdds) { try { @@ -215,10 +218,16 @@ private void showRerunResultsInNewFrame(SQLExecutionInfo info, IDataSetUpdateabl tableState = _resultTab.getResultSortableTableState(); } - _resultTab = _resultTabFactory.createResultTab(info, creator, rsds, rsmdds); + ResultTab newResultTab = _resultTabFactory.createResultTab(info, creator, rsds, rsmdds); + _resultTab.aboutToBeReplacedBy(newResultTab, _reRunChooserCtrl); + + _resultTab = newResultTab; + _resultTab.replaceResultTabListener((sql, resultTabToReplace) -> onRerun()); + JTabbedPane tabbedPaneOfResultTabs = _resultTab.getTabbedPaneOfResultTabs(); GUIUtils.unconventionallyAddToParentWithRepaint(_centerPanel, tabbedPaneOfResultTabs); _markDuplicatesChooserController.init(_resultTab); + _reRunChooserCtrl.setResultTab((ResultTab) _resultTab); if(null != tableState) { @@ -226,17 +235,17 @@ private void showRerunResultsInNewFrame(SQLExecutionInfo info, IDataSetUpdateabl } _btnReturnToTab.setEnabled(true); - _btnReRun.setEnabled(true); + //_reRunChooserCtrl.setEnabled(true); } catch (Throwable t) { - _session.showErrorMessage(t); + Main.getApplication().getMessageHandler().showErrorMessage(t); } } private void showFrame(ResultFrame frame, boolean isOnRerun) { - _session.getApplication().getMainFrame().addWidget(frame); + Main.getApplication().getMainFrame().addWidget(frame); if (isOnRerun) { frame.setBounds(getBounds()); @@ -274,7 +283,6 @@ private JPanel createLeftButtonsPanel(ISession session, IApplication app, boolea gbc = new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0,5,0,5), 0,0); pnlButtons.add(_btnReturnToTab, gbc); - // i18n[resultFrame.stayOnTop=Stay on top] _chkOnTop = new JCheckBox(s_stringMgr.getString("resultFrame.stayOnTop")); gbc = new GridBagConstraints(1,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,5,0,5), 0,0); pnlButtons.add(_chkOnTop, gbc); @@ -302,44 +310,29 @@ private JPanel createRightUpperPanel() public void updateRightUpperPanelLayout(JPanel panel) { - //_panel.invalidate(); - //SwingUtilities.invokeLater( () -> {_panel.revalidate(); _panel.getParent().revalidate(); _panel.getParent().getParent().revalidate();}); - //SwingUtilities.invokeLater( () -> _panel.repaint()); panel.revalidate(); - //panel.getParent().revalidate(); if (null != panel.getParent()) { panel.getParent().revalidate(); } - - //_panel.setBorder(BorderFactory.createLineBorder(Color.RED)); } private JPanel createRightButtonsPanel() { JPanel ret = new JPanel(new GridLayout(1,4)); - - ImageIcon iconReRun = Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.RERUN); - _btnReRun = new TabButton(iconReRun); - _btnReRun.setToolTipText(s_stringMgr.getString("ResultFrame.rerun")); - //gbc = new GridBagConstraints(3,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); - ret.add(_btnReRun); - + ret.add(_reRunChooserCtrl.getComponent()); _markDuplicatesChooserController = new MarkDuplicatesChooserController(_resultTab); _markDuplicatesChooserController.copyStateFrom(_resultTab.getMarkDuplicatesChooserController()); - //gbc = new GridBagConstraints(4,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); ret.add(_markDuplicatesChooserController.getComponent()); ImageIcon iconFindColumn = Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.FIND_COLUMN); _btnFindColumn = new TabButton(iconFindColumn); - //gbc = new GridBagConstraints(5,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0,0); ret.add(_btnFindColumn); ImageIcon iconFind = Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.FIND); _btnToggleFind = new TabButton(iconFind); - //gbc = new GridBagConstraints(6,0,1,1,0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,5), 0,0); ret.add(_btnToggleFind); return ret; @@ -380,6 +373,7 @@ public void returnToTabbedPane() { s_log.debug("ResultFrame.returnToTabbedPane()"); getContentPane().remove(_resultTab.getTabbedPaneOfResultTabs()); + _resultTab.replaceResultTabListener(_originalResultTabListener); _resultTab.returnToTabbedPane(); _resultTab = null; dispose(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java index 1ca9cf0d1..9cccf8637 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/ResultTab.java @@ -160,7 +160,7 @@ public ResultTab(ISession session, SQLResultExecuterPanelFacade sqlResultExecute { _resultTabListener = resultTabListener; _session = session; - _reRunChooserCtrl = new ReRunChooserCtrl(session); + _reRunChooserCtrl = new ReRunChooserCtrl(this); _queryInfoPanel = new QueryInfoPanel(_session); _sqlResultExecuterPanelFacade = sqlResultExecuterPanelFacade; @@ -828,9 +828,18 @@ protected void finalize() */ @Override public void aboutToBeReplacedBy(ResultTab newResultTab) + { + aboutToBeReplacedBy(newResultTab, newResultTab._reRunChooserCtrl); + } + + /** + * Is called before the {@link ResultTabCloseListener] of the previous {@link ResultTab} is fired. + */ + @Override + public void aboutToBeReplacedBy(ResultTab newResultTab, ReRunChooserCtrl reRunChooserCtrl) { newResultTab._rerunWithTimerRepeatsManager = _rerunWithTimerRepeatsManager; - _rerunWithTimerRepeatsManager.aboutToBeReplacedBy(newResultTab, newResultTab._reRunChooserCtrl); + _rerunWithTimerRepeatsManager.aboutToBeReplacedBy(newResultTab, reRunChooserCtrl); } @Override @@ -838,4 +847,15 @@ public void prepareBeingMovedToResultFrame() { _rerunWithTimerRepeatsManager.disposeTimer(); } + + /** + * @return The previous {@link ResultTabListener} + */ + @Override + public ResultTabListener replaceResultTabListener(ResultTabListener resultTabListener) + { + ResultTabListener previous = _resultTabListener; + _resultTabListener = resultTabListener; + return previous; + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java index fb5271311..7d2318934 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/ReRunChooserCtrl.java @@ -8,7 +8,7 @@ import javax.swing.JComponent; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; -import net.sourceforge.squirrel_sql.client.session.ISession; +import net.sourceforge.squirrel_sql.client.session.mainpanel.IResultTab; import net.sourceforge.squirrel_sql.client.session.mainpanel.ResultTab; import net.sourceforge.squirrel_sql.client.session.mainpanel.TabButton; import net.sourceforge.squirrel_sql.client.shortcut.ShortcutUtil; @@ -20,7 +20,6 @@ public class ReRunChooserCtrl { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ReRunChooserCtrl.class); - private final ISession _session; private final RerunCurrentSQLResultTabAction _actionDefault; private final RerunCurrentSQLResultTabAction _actionTimerRepeats; private final TabButton _btnReRunDefault; @@ -29,12 +28,11 @@ public class ReRunChooserCtrl private ButtonChooser _btnChooser; - public ReRunChooserCtrl(ISession session) + public ReRunChooserCtrl(IResultTab resultTab) { _btnChooser = new ButtonChooser(); - _session = session; - _actionDefault = createDefaultReRunAction(); - _actionTimerRepeats = createTimerRepeatsReRunAction(); + _actionDefault = createDefaultReRunAction(resultTab); + _actionTimerRepeats = createTimerRepeatsReRunAction(resultTab); _btnReRunDefault = new TabButton(_actionDefault); _btnReRunTimerRepeats = new TabButton(_actionTimerRepeats); @@ -56,9 +54,9 @@ public ReRunChooserCtrl(ISession session) (btnNew, btnOld) -> RerunResultTabMode.setCurrentMode(btnNew == _btnReRunDefault ? RerunResultTabMode.DEFAULT : RerunResultTabMode.TIMER_REPEATS)); } - private RerunCurrentSQLResultTabAction createTimerRepeatsReRunAction() + private static RerunCurrentSQLResultTabAction createTimerRepeatsReRunAction(IResultTab resultTab) { - RerunCurrentSQLResultTabAction ret = createDefaultReRunAction(); + RerunCurrentSQLResultTabAction ret = createDefaultReRunAction(resultTab); ret.putValue(Action.SMALL_ICON, Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.RUN_TIMER)); String description = s_stringMgr.getString("ReRunChooserCtrl.rerun.timered", ShortcutUtil.getKeystrokeString(ret.getKeyStroke())); @@ -68,10 +66,10 @@ private RerunCurrentSQLResultTabAction createTimerRepeatsReRunAction() return ret; } - private RerunCurrentSQLResultTabAction createDefaultReRunAction() + private static RerunCurrentSQLResultTabAction createDefaultReRunAction(IResultTab resultTab) { RerunCurrentSQLResultTabAction ret = new RerunCurrentSQLResultTabAction(); - ret.setSQLPanel(_session.getSQLPanelAPIOfActiveSessionWindow()); + ret.setResultTab((ResultTab) resultTab); return ret; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java index 9171893e0..01c09ff10 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/resulttabactions/RerunCurrentSQLResultTabAction.java @@ -26,9 +26,15 @@ public RerunCurrentSQLResultTabAction() public void setSQLPanel(ISQLPanelAPI panel) { - setEnabled(_resultTabProvider.setSQLPanelAPI(panel)); + _resultTabProvider.setSQLPanelAPI(panel); + doEnable(); } + private void doEnable() + { + setEnabled(_resultTabProvider.hasResultTab()); + } + public void actionPerformed(ActionEvent evt) { if (false == _resultTabProvider.hasResultTab()) @@ -85,6 +91,7 @@ private void rerunWithTimerRepeats() public void setResultTab(ResultTab resultTab) { _resultTabProvider.setResultTab(resultTab); + doEnable(); } } From b07d113079fa583b7ade9737b75d9fd5b17aad4b Mon Sep 17 00:00:00 2001 From: GWA Date: Thu, 22 Jan 2026 10:06:28 +0100 Subject: [PATCH 16/33] Bug fix: Deleting or editing SQL table results or Object tree "Content"-tables rose NullPointerException when a table had one or more columns of type LONGVARCHAR and LONGVARCHAR types were chosen to be left out of generated WHERE clauses. See menu File --> Global Preferences --> tab "Data type controls" --> section "CHAR, VARCHAR, LONGVARCHAR" --- sql12/core/doc/changes.txt | 4 + .../DataSetUpdateableTableModelImpl.java | 40 +++++---- .../cellcomponent/DataTypeString.java | 89 ++++++++++--------- 3 files changed, 75 insertions(+), 58 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index f72c2d535..1a28a2e9e 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -74,6 +74,10 @@ DB2 Plugin: The table details in the Object tree has a new tab Bug fixes: +Deleting or editing SQL table results or Object tree "Content"-tables rose NullPointerException when + a table had one or more columns of type LONGVARCHAR and LONGVARCHAR types were chosen to be left out of generated WHERE clauses. + See menu File --> Global Preferences --> tab "Data type controls" --> section "CHAR, VARCHAR, LONGVARCHAR" + Alias find dialog (ctrl+alt+shift+g or ctrl+alt+shift+f): Modifying an Alias folder raised NullPointerException. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/DataSetUpdateableTableModelImpl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/DataSetUpdateableTableModelImpl.java index fc2701f77..d39e35a1c 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/DataSetUpdateableTableModelImpl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/DataSetUpdateableTableModelImpl.java @@ -1,5 +1,14 @@ package net.sourceforge.squirrel_sql.client.session; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Vector; +import javax.swing.JOptionPane; + import net.sourceforge.squirrel_sql.client.session.mainpanel.sqltypecheck.ReadOnlySessionCheck; import net.sourceforge.squirrel_sql.client.session.properties.EditWhereCols; import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; @@ -22,15 +31,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.JOptionPane; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Vector; - public class DataSetUpdateableTableModelImpl implements IDataSetUpdateableTableModel { @@ -646,29 +646,37 @@ private List getWhereClause( // the user has restricted the set of columns to use. // If this name is NOT in the list, then skip it; otherwise we fall through // and use the column in the WHERE clause - if (colNames.get(colDefs[i].getColumnName()) == null) + if( colNames.get(colDefs[i].getColumnName()) == null ) + { continue; // go on to the next item + } } // for the column that is being changed, use the value // passed in by the caller (which may be either the // current value or the new replacement value) Object value = values[i]; - if (i == col) + if( i == col ) + { value = colValue; + } - // convert user representation of null into an actual null - if (value != null && value.toString().equals(StringUtilities.NULL_AS_STRING)) + if( value != null && value.toString().equals(StringUtilities.NULL_AS_STRING) ) + { + // convert user representation of null into an actual null value = null; + } // do different things depending on data type ISQLDatabaseMetaData md = _session.getMetaData(); IWhereClausePart clausePart = CellComponentFactory.getWhereClauseValue(colDefs[i], value, md); - if (clausePart.shouldBeUsed()) - // Now we know that the part should not we ignoredshould + if( null != clausePart && clausePart.shouldBeUsed() ) + { + // Now we know that the part should not be ignored clauseParts.add(clausePart); + } } return clauseParts; @@ -676,7 +684,7 @@ private List getWhereClause( } catch (Exception e) { - throw new RuntimeException(e); + throw Utilities.wrapRuntime(e); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/DataTypeString.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/DataTypeString.java index 3332a93b4..abec087ee 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/DataTypeString.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/DataTypeString.java @@ -18,32 +18,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; -import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.EmptyWhereClausePart; -import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.IWhereClausePart; -import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.IsNullWhereClausePart; -import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.ParameterWhereClausePart; -import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataDialogHandler; -import net.sourceforge.squirrel_sql.fw.gui.IntegerField; -import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; -import net.sourceforge.squirrel_sql.fw.gui.OkJPanel; -import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData; -import net.sourceforge.squirrel_sql.fw.util.StringManager; -import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import net.sourceforge.squirrel_sql.fw.util.StringUtilities; -import net.sourceforge.squirrel_sql.fw.util.Utilities; - -import javax.swing.BorderFactory; -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.text.JTextComponent; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; @@ -60,6 +34,32 @@ import java.sql.ResultSet; import java.sql.Types; import java.util.Iterator; +import javax.swing.BorderFactory; +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.text.JTextComponent; + +import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; +import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.EmptyWhereClausePart; +import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.IWhereClausePart; +import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.IsNullWhereClausePart; +import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.whereClause.ParameterWhereClausePart; +import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataDialogHandler; +import net.sourceforge.squirrel_sql.fw.gui.IntegerField; +import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; +import net.sourceforge.squirrel_sql.fw.gui.OkJPanel; +import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; +import net.sourceforge.squirrel_sql.fw.util.StringUtilities; +import net.sourceforge.squirrel_sql.fw.util.Utilities; /** @@ -123,7 +123,7 @@ public class DataTypeString extends BaseDataTypeComponent * otherwise do not include it. * Oracle does not allow that type to be used in a WHERE clause */ - private static boolean _useLongInWhere = true; + private static boolean _useLongVarcharInWhere = true; /** @@ -163,10 +163,10 @@ private static void loadProperties() { if (makeNewlinesVisibleString != null && makeNewlinesVisibleString.equals("false")) _makeNewlinesVisibleInCell = false; - _useLongInWhere = true; // set to the default + _useLongVarcharInWhere = true; // set to the default String useLongInWhereString = DataTypeProps.getProperty(DataTypeString.class.getName(), "useLongInWhere"); if (useLongInWhereString != null && useLongInWhereString.equals("false")) - _useLongInWhere = false; + _useLongVarcharInWhere = false; LimitReadLengthFeatureUnstable._limitRead = false; // set to default String limitReadString = DataTypeProps.getProperty(DataTypeString.class.getName(), "limitRead"); @@ -542,27 +542,32 @@ public Object readResultSet(ResultSet rs, int index, boolean limitDataRead) * or whatever is appropriate for this column in the database. */ @Override - public IWhereClausePart getWhereClauseValue(Object value, ISQLDatabaseMetaData md) { + public IWhereClausePart getWhereClauseValue(Object value, ISQLDatabaseMetaData md) + { // first do special check to see if we should use LONGVARCHAR // in the WHERE clause. // (Oracle does not allow this.) - if (_colDef.getSqlType() == Types.LONGVARCHAR && - _useLongInWhere == false) - return null; // this column cannot be used in a WHERE clause + if( _colDef.getSqlType() == Types.LONGVARCHAR && _useLongVarcharInWhere == false ) + { + return null; // this column cannot be used in a WHERE clause + } - if (value == null || value.toString() == null ) + if( value == null || value.toString() == null ) + { return new IsNullWhereClausePart(_colDef); - else { + } + else + { // We cannot use this data in the WHERE clause if it has been truncated. // Since being truncated is the same as needing to re-read, // only use this in the WHERE clause if we do not need to re-read - if ( ! needToReRead(value)) + if( !needToReRead(value) ) { return new ParameterWhereClausePart(_colDef, value, this); } - else - { - return new EmptyWhereClausePart(); // value is truncated, so do not use in WHERE clause + else + { + return new EmptyWhereClausePart(); // value is truncated, so do not use in WHERE clause } } } @@ -842,7 +847,7 @@ public DataTypeStringPanel() { _makeNewlinesVisibleInCellChk.setSelected(_makeNewlinesVisibleInCell); // checkbox for using LONG in WHERE clause - _useLongInWhereChk.setSelected(_useLongInWhere); + _useLongInWhereChk.setSelected(_useLongVarcharInWhere); // checkbox for limit/no-limit on data read during initial table load _limitReadChk.setSelected(LimitReadLengthFeatureUnstable._limitRead); @@ -979,8 +984,8 @@ public void ok() { _makeNewlinesVisibleInCell = _makeNewlinesVisibleInCellChk.isSelected(); DataTypeProps.putDataTypeProperty(DataTypeString.class.getName(), "makeNewlinesVisibleInCell", Boolean.valueOf(_makeNewlinesVisibleInCell).toString()); - _useLongInWhere = _useLongInWhereChk.isSelected(); - DataTypeProps.putDataTypeProperty(DataTypeString.class.getName(), "useLongInWhere", Boolean.valueOf(_useLongInWhere).toString()); + _useLongVarcharInWhere = _useLongInWhereChk.isSelected(); + DataTypeProps.putDataTypeProperty(DataTypeString.class.getName(), "useLongInWhere", Boolean.valueOf(_useLongVarcharInWhere).toString()); LimitReadLengthFeatureUnstable._limitRead = _limitReadChk.isSelected(); DataTypeProps.putDataTypeProperty(DataTypeString.class.getName(), "limitRead", Boolean.valueOf(LimitReadLengthFeatureUnstable._limitRead).toString()); From 64ea61dd370c8c57979ad0b6aaa6992b70f6ddb7 Mon Sep 17 00:00:00 2001 From: GWA Date: Fri, 23 Jan 2026 08:38:20 +0100 Subject: [PATCH 17/33] Adjusted copyright to new year --- .../src/net/sourceforge/squirrel_sql/client/Version.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/Version.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/Version.java index 2203e371b..3f5575693 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/Version.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/Version.java @@ -18,11 +18,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; - import java.io.IOException; import java.io.InputStream; import java.util.Properties; + +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; /** * Application version information. * @@ -35,7 +35,7 @@ public class Version * No I18n/StringManager here. This class is used to early. The right Locale may not have been set yet. */ private static final String APP_NAME = "SQuirreL SQL Client"; - private static final String COPYRIGHT = "Copyright (c) 2001-2025\nColin Bell, Gerd Wagner, Rob Manning and others"; + private static final String COPYRIGHT = "Copyright (c) 2001-2026\nColin Bell, Gerd Wagner, Rob Manning and others"; private static final String WEB_SITE = "http://www.squirrelsql.org"; private static final String WEB_SITE2 = "https://squirrelsql.org"; From 7c9a29b83c4002cf839efd812b87bdab27ce2d28 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 24 Jan 2026 22:38:19 +0100 Subject: [PATCH 18/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 Session Scripts Plugin: Session startup scripts now support running bookmarks by @runbookmark the same way the SQL editor does. Feature: Session Scripts Plugin: Aliases combo box of the Session startup scripts frame now sorts Aliases alphabetically and puts the ones on top which have Session startup scripts defined. See menu Plugins --> Session Scripts ... --- sql12/core/doc/changes.txt | 10 +- .../gui/db/AliasesAndDriversManager.java | 27 +++--- .../client/plugin/DefaultSessionPlugin.java | 9 +- .../client/plugin/ISessionPlugin.java | 9 +- .../client/plugin/PluginManager.java | 91 +++++++++---------- .../sessionscript/SQLALiasesCombo.java | 42 +++++---- .../plugins/sessionscript/ScriptsSheet.java | 31 +++---- .../sessionscript/SessionScriptPlugin.java | 27 +++--- .../ViewSessionScriptsPanel.java | 31 +++---- sql12/plugins/sqlbookmark/doc/readme.html | 13 ++- .../sqlbookmark/SQLBookmarkPlugin.java | 2 +- 11 files changed, 158 insertions(+), 134 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 1a28a2e9e..8c26c78c9 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,14 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 + Session Scripts Plugin: Session startup scripts now support running bookmarks + by @runbookmark the same way the SQL editor does. + +Session Scripts Plugin: Aliases combo box of the Session startup scripts frame now + sorts Aliases alphabetically and puts the ones on top which have Session startup scripts defined. + See menu Plugins --> Session Scripts ... + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/80 SQL results displayed in their own window can be rerun automatically, too. The UI behavior of SQL results displayed in their own window was improved. @@ -15,7 +23,7 @@ https://github.com/squirrel-sql-client/squirrel-sql-code/issues/80 To give access to this function the SQL result's rerun button was made switchable. https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 - Bookmarks Plugin: A bookmark's statement can be run from within the SQL editor use @runbookmark + Bookmarks Plugin: A bookmark's statement can be run from within the SQL editor use @runbookmark https://github.com/squirrel-sql-client/squirrel-sql-code/issues/75 The options "Allow to run all SQLs in editor" and "Allow to run a SQL in all open Sessions" diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesAndDriversManager.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesAndDriversManager.java index 22bba25d2..2a2543a36 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesAndDriversManager.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/db/AliasesAndDriversManager.java @@ -18,6 +18,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.db.listholder.AliasListHolder; import net.sourceforge.squirrel_sql.client.gui.db.listholder.DriverListHolder; @@ -28,20 +36,15 @@ import net.sourceforge.squirrel_sql.fw.sql.ISQLDriver; import net.sourceforge.squirrel_sql.fw.sql.SQLDriver; import net.sourceforge.squirrel_sql.fw.sql.SQLDriverManager; -import net.sourceforge.squirrel_sql.fw.util.*; +import net.sourceforge.squirrel_sql.fw.util.IMessageHandler; +import net.sourceforge.squirrel_sql.fw.util.IObjectCacheChangeListener; +import net.sourceforge.squirrel_sql.fw.util.NullMessageHandler; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; import net.sourceforge.squirrel_sql.fw.xml.XMLException; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - public class AliasesAndDriversManager { private final static StringManager s_stringMgr = StringManagerFactory.getStringManager(AliasesAndDriversManager.class); @@ -248,12 +251,12 @@ public SQLAlias getAlias(IIdentifier id) return _aliasListHolder.get(id); } - public Iterator aliases() + public Iterator aliases() { return _aliasListHolder.getAll().iterator(); } - public List getAliasList() + public List getAliasList() { return _aliasListHolder.getAll(); } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/DefaultSessionPlugin.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/DefaultSessionPlugin.java index 6b5047668..7bcc03073 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/DefaultSessionPlugin.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/DefaultSessionPlugin.java @@ -20,14 +20,13 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import javax.swing.JMenu; +import javax.swing.JMenu; import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.event.SessionAdapter; import net.sourceforge.squirrel_sql.client.session.event.SessionEvent; import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.INodeExpander; import net.sourceforge.squirrel_sql.client.session.properties.ISessionPropertiesPanel; -import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; @@ -59,6 +58,12 @@ public boolean allowsSessionStartedInBackground() return false; } + @Override + public int getSessionStartedCallRank() + { + return 0; + } + /** * Called when a session shutdown. * diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/ISessionPlugin.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/ISessionPlugin.java index 86d19d7fa..b40572f72 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/ISessionPlugin.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/ISessionPlugin.java @@ -19,11 +19,11 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType; import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.INodeExpander; import net.sourceforge.squirrel_sql.client.session.properties.ISessionPropertiesPanel; +import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType; /** * Base interface for all plugins associated with a session. */ @@ -61,6 +61,13 @@ public interface ISessionPlugin extends IPlugin */ PluginSessionCallback sessionStarted(ISession session); + /** + * Allows to influence the order in which {@link #sessionStarted(ISession)} is called with respect to other SessionPlugins. + * Safely influencing the order is possible only when {@link #allowsSessionStartedInBackground()} returns false. + */ + int getSessionStartedCallRank(); + + /** * Called when a session shutdown. */ diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginManager.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginManager.java index c26d6a4aa..9228587ff 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginManager.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginManager.java @@ -21,6 +21,20 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import net.sourceforge.squirrel_sql.client.ApplicationArguments; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.gui.db.SQLAlias; @@ -45,21 +59,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - /** * Manages plugins for the application. * @@ -178,42 +177,47 @@ public synchronized void sessionStarted(final ISession session) final List plugins = new ArrayList(); _activeSessions.put(session.getIdentifier(), plugins); - ArrayList startInFG = new ArrayList(); - final ArrayList startInBG = new ArrayList(); + ArrayList startInFG = new ArrayList<>(); + final ArrayList startInBG = new ArrayList<>(); for (Iterator it = _sessionPlugins.iterator(); it.hasNext();) { SessionPluginInfo spi = it.next(); - if (spi.getSessionPlugin().allowsSessionStartedInBackground()) + if(spi.getSessionPlugin().allowsSessionStartedInBackground()) { startInBG.add(spi); - } else + } + else { startInFG.add(spi); } - } session.setPluginsfinishedLoading(true); - for (Iterator it = startInFG.iterator(); it.hasNext();) - { - SessionPluginInfo spi = it.next(); - sendSessionStarted(session, spi, plugins); - } + + startInFG.sort((spi1, spi2) -> compareBySessionStartedCallRank(spi1, spi2)); + for(SessionPluginInfo spi : startInFG) + { + sendSessionStarted(session, spi, plugins); + } session.getApplication().getThreadPool().addTask(new Runnable() { public void run() { - for (Iterator it = startInBG.iterator(); it.hasNext();) - { - SessionPluginInfo spi = it.next(); - sendSessionStarted(session, spi, plugins); - } + for(SessionPluginInfo spi : startInBG) + { + sendSessionStarted(session, spi, plugins); + } session.setPluginsfinishedLoading(true); } }); } + private int compareBySessionStartedCallRank(SessionPluginInfo spi1, SessionPluginInfo spi2) + { + return Integer.compare(spi1.getSessionPlugin().getSessionStartedCallRank(), spi2.getSessionPlugin().getSessionStartedCallRank()); + } + private void sendSessionStarted(ISession session, SessionPluginInfo spi, List plugins) { try @@ -222,30 +226,17 @@ private void sendSessionStarted(ISession session, SessionPluginInfo spi, List list = - _pluginSessionCallbacksBySessionID.get(session.getIdentifier()); - if (null == list) - { - list = new ArrayList(); - _pluginSessionCallbacksBySessionID.put(session.getIdentifier(), list); - } - list.add(pluginSessionCallback); - + List list = _pluginSessionCallbacksBySessionID.computeIfAbsent(session.getIdentifier(), k -> new ArrayList<>()); + list.add(pluginSessionCallback); plugins.add(spi); } - } catch (final Throwable th) + } + catch(final Throwable th) { - final String msg = - s_stringMgr.getString("PluginManager.error.sessionstarted", spi.getPlugin().getDescriptiveName()); - s_log.error(msg, th); - GUIUtils.processOnSwingEventThread(new Runnable() - { - public void run() - { - _app.showErrorDialog(msg, th); - } - }); + final String msg =s_stringMgr.getString("PluginManager.error.sessionstarted", spi.getPlugin().getDescriptiveName()); + s_log.error(msg, th); + GUIUtils.processOnSwingEventThread(() -> _app.showErrorDialog(msg, th)); } } diff --git a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SQLALiasesCombo.java b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SQLALiasesCombo.java index 06b70a300..eba8d9561 100644 --- a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SQLALiasesCombo.java +++ b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SQLALiasesCombo.java @@ -18,11 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.client.IApplication; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JComboBox; +import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.db.SQLAlias; +import org.apache.commons.lang3.StringUtils; -import javax.swing.*; -import java.util.Iterator; /** * This JComboBox will display all aliases. * @@ -46,22 +48,30 @@ public SQLAlias getSelectedSQLAlias() /** * Load control with all the aliases in the system. - * - * @param conn app Application API. - * - * @throws IllegalArgumentException - * Thrown if a null IApplication passed. - * - * @throws BaseSQLException - * Thrown if an SQL exception occurs. */ - public void load(IApplication app) + public void load(AliasScriptCache scriptsCache) { removeAllItems(); - for (Iterator it = app.getAliasesAndDriversManager().aliases(); it.hasNext();) + + List aliasListClone= new ArrayList<>(Main.getApplication().getAliasesAndDriversManager().getAliasList()); + + aliasListClone.sort((a1, a2) -> compareAliases(scriptsCache, a1, a2)); + + aliasListClone.forEach(a -> addItem(a)); + } + + private int compareAliases(AliasScriptCache scriptsCache, SQLAlias a1, SQLAlias a2) + { + if(false == StringUtils.isBlank(scriptsCache.get(a1).getSQL()) && StringUtils.isBlank(scriptsCache.get(a2).getSQL())) { - SQLAlias alias = it.next(); - addItem(alias); + return -1; } - } + else if(StringUtils.isBlank(scriptsCache.get(a1).getSQL()) && false == StringUtils.isBlank(scriptsCache.get(a2).getSQL())) + { + return 1; + } + + return StringUtils.compareIgnoreCase(a1.getName(), a2.getName()); + + } } diff --git a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ScriptsSheet.java b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ScriptsSheet.java index 1b82ad442..002e6bf91 100644 --- a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ScriptsSheet.java +++ b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ScriptsSheet.java @@ -18,44 +18,34 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import javax.swing.WindowConstants; import net.sourceforge.squirrel_sql.client.IApplication; +import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DialogWidget; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import net.sourceforge.squirrel_sql.fw.util.log.ILogger; -import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; - -import javax.swing.*; -import java.awt.*; class ScriptsSheet extends DialogWidget { - private static final StringManager s_stringMgr = - StringManagerFactory.getStringManager(ScriptsSheet.class); + private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ScriptsSheet.class); - - /** Logger for this class. */ - private static ILogger s_log = - LoggerController.createLogger(ScriptsSheet.class); - /** Singleton instance of this class. */ private static ScriptsSheet s_instance; - /** Plugin. */ private SessionScriptPlugin _plugin; - /** Application API. */ - private IApplication _app; /** Main panel. */ private ViewSessionScriptsPanel _mainPnl; - private ScriptsSheet(SessionScriptPlugin plugin, IApplication app) + private ScriptsSheet(SessionScriptPlugin plugin) { // i18n[sessionscript.startupScripts=Startup Scripts] - super(s_stringMgr.getString("sessionscript.startupScripts"), true, true, true, true); + super(s_stringMgr.getString("sessionscript.startupScripts"), true, true, true, true, Main.getApplication().getMainFrame()); _plugin = plugin; - _app = app; createUserInterface(); } @@ -74,9 +64,10 @@ public static synchronized void showSheet(SessionScriptPlugin plugin, { if (s_instance == null) { - s_instance = new ScriptsSheet(plugin, app); + s_instance = new ScriptsSheet(plugin); app.getMainFrame().addWidget(s_instance); } + DialogWidget.centerWithinDesktop(s_instance); s_instance.setVisible(true); } @@ -94,7 +85,7 @@ private void createUserInterface() makeToolWindow(true); - _mainPnl = new ViewSessionScriptsPanel(_plugin, _app); + _mainPnl = new ViewSessionScriptsPanel(_plugin); Container content = getContentPane(); content.setLayout(new BorderLayout()); diff --git a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SessionScriptPlugin.java b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SessionScriptPlugin.java index dac5fa698..6ec7267ea 100755 --- a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SessionScriptPlugin.java +++ b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/SessionScriptPlugin.java @@ -18,8 +18,9 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import java.io.IOException; +import java.io.IOException; +import javax.swing.SwingUtilities; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.action.ActionCollection; import net.sourceforge.squirrel_sql.client.plugin.DefaultSessionPlugin; @@ -32,8 +33,7 @@ import net.sourceforge.squirrel_sql.fw.util.FileWrapper; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; - -import javax.swing.*; +import org.apache.commons.lang3.StringUtils; /** * The plugin class. @@ -169,7 +169,8 @@ public synchronized void initialize() throws PluginException try { _cache = new AliasScriptCache(this); - } catch (IOException ex) + } + catch(IOException ex) { throw new PluginException(ex); } @@ -189,17 +190,22 @@ public void unload() super.unload(); } - public PluginSessionCallback sessionStarted(final ISession session) + @Override + public int getSessionStartedCallRank() { - boolean rc = false; + // Call this Plugin's sessionStarted method last. + return Integer.MAX_VALUE; + } + @Override + public PluginSessionCallback sessionStarted(final ISession session) + { AliasScript script = _cache.get(session.getAlias()); if (script != null) { final String sql = script.getSQL(); - if (sql != null && sql.length() > 0) + if (false == StringUtils.isBlank(sql)) { - rc = true; final ISQLPanelAPI api = session.getSessionInternalFrame().getMainSQLPanelAPI(); SwingUtilities.invokeLater(new Runnable() @@ -212,11 +218,6 @@ public void run() }); } } - - if (false == rc) - { - return null; - } return new PluginSessionCallbackAdaptor(); } diff --git a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ViewSessionScriptsPanel.java b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ViewSessionScriptsPanel.java index 7d7cacb52..2a3ff4950 100644 --- a/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ViewSessionScriptsPanel.java +++ b/sql12/plugins/sessionscript/src/net/sourceforge/squirrel_sql/plugins/sessionscript/ViewSessionScriptsPanel.java @@ -18,18 +18,22 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.client.IApplication; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import net.sourceforge.squirrel_sql.client.gui.db.SQLAlias; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - public class ViewSessionScriptsPanel extends JPanel { private static final StringManager s_stringMgr = @@ -37,25 +41,18 @@ public class ViewSessionScriptsPanel extends JPanel private SessionScriptPlugin _plugin; - private IApplication _app; private SQLALiasesCombo _aliasesCmb = new SQLALiasesCombo(); private JTextArea _sqlEntry = new JTextArea(); private JButton _saveBtn; - ViewSessionScriptsPanel(SessionScriptPlugin plugin, IApplication app) + ViewSessionScriptsPanel(SessionScriptPlugin plugin) { - super(); if (plugin == null) { throw new IllegalArgumentException("SessionScriptPlugin == null"); } - if (app == null) - { - throw new IllegalArgumentException("IApplication == null"); - } _plugin = plugin; - _app = app; createUserInterface(); refreshScript(); @@ -86,7 +83,7 @@ private void createUserInterface() { setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); - _aliasesCmb.load(_app); + _aliasesCmb.load(_plugin.getScriptsCache()); _aliasesCmb.addActionListener(new AliasesComboListener(this)); _sqlEntry.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); diff --git a/sql12/plugins/sqlbookmark/doc/readme.html b/sql12/plugins/sqlbookmark/doc/readme.html index 23625ab81..cb0bce817 100644 --- a/sql12/plugins/sqlbookmark/doc/readme.html +++ b/sql12/plugins/sqlbookmark/doc/readme.html @@ -9,7 +9,7 @@ -

SQLBookmark 1.0 - Joe Mocker, Gerd Wagner

+

SQLBookmark 2.0.1 - Joe Mocker, Gerd Wagner

SQLBookmark allows you to "bookmark" commonly used SQL code for easy point and click reuse. Whatever you type in the SQL editor can be easily bookmarked by opening SQuirreL's tools popup via @@ -99,5 +99,16 @@

The Global Preferences window can be opened using the “Edit Bookmarks” toolbar button of a Session window.

+

+



+

+

Executing Bookmarks scriptlike:

+Bookmarks can be called from within the SQL editor using the following syntax: + + + @runbookmark <bookmarkNameInSingleQuotes> + + + \ No newline at end of file diff --git a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java index 9d0898967..106aa6119 100644 --- a/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java +++ b/sql12/plugins/sqlbookmark/src/net/sourceforge/squirrel_sql/plugins/sqlbookmark/SQLBookmarkPlugin.java @@ -193,7 +193,7 @@ public synchronized void initialize() throws PluginException public boolean allowsSessionStartedInBackground() { - return true; + return false; } public PluginSessionCallback sessionStarted(final ISession session) From adc4a87990149cbfc4f6f165a99fb6f2f23239f5 Mon Sep 17 00:00:00 2001 From: GWA Date: Wed, 28 Jan 2026 08:43:36 +0100 Subject: [PATCH 19/33] Bug: Fixed "java.beans.IntrospectionException: Method not found" when creating an application dump. See menu File --> Dump Application --- sql12/core/doc/changes.txt | 3 +++ .../client/plugin/PluginInfo.java | 1 - .../client/plugin/PluginInfoBeanInfo.java | 27 +++++++++---------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 8c26c78c9..11f8c38c2 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -82,6 +82,9 @@ DB2 Plugin: The table details in the Object tree has a new tab Bug fixes: +Fixed "java.beans.IntrospectionException: Method not found" when creating an application dump. + See menu File --> Dump Application + Deleting or editing SQL table results or Object tree "Content"-tables rose NullPointerException when a table had one or more columns of type LONGVARCHAR and LONGVARCHAR types were chosen to be left out of generated WHERE clauses. See menu File --> Global Preferences --> tab "Data type controls" --> section "CHAR, VARCHAR, LONGVARCHAR" diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfo.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfo.java index 99bcfaee7..8b0d16307 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfo.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfo.java @@ -34,7 +34,6 @@ public interface IPropertyNames String IS_LOADED = "isLoaded"; String PLUGIN_CLASS_NAME = "pluginClassName"; String VERSION = "version"; - String WEB_SITE = "webSite"; } private String _pluginClassName; diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfoBeanInfo.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfoBeanInfo.java index 27ffe71d4..0587fba22 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfoBeanInfo.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/plugin/PluginInfoBeanInfo.java @@ -21,6 +21,8 @@ import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.beans.SimpleBeanInfo; +import java.util.ArrayList; +import java.util.List; /** * This is the BeanInfo class for PluginInfo. @@ -32,7 +34,7 @@ public final class PluginInfoBeanInfo extends SimpleBeanInfo private interface IPropNames extends PluginInfo.IPropertyNames { - // Empty body, purely to shorten the interface name for convienience. + // Empty body, purely to shorten the interface name for convenience. } /** @@ -46,22 +48,17 @@ public PropertyDescriptor[] getPropertyDescriptors() { try { - PropertyDescriptor[] s_descr = new PropertyDescriptor[8]; + List s_descr = new ArrayList<>(); - s_descr[0] = - new PropertyDescriptor(IPropNames.PLUGIN_CLASS_NAME, PluginInfo.class, "getPluginClassName", null); - s_descr[1] = new PropertyDescriptor(IPropNames.IS_LOADED, PluginInfo.class, "isLoaded", null); - s_descr[2] = - new PropertyDescriptor(IPropNames.INTERNAL_NAME, PluginInfo.class, "getInternalName", null); - s_descr[3] = - new PropertyDescriptor(IPropNames.DESCRIPTIVE_NAME, PluginInfo.class, "getDescriptiveName", null); - s_descr[4] = new PropertyDescriptor(IPropNames.AUTHOR, PluginInfo.class, "getAuthor", null); - s_descr[5] = - new PropertyDescriptor(IPropNames.CONTRIBUTORS, PluginInfo.class, "getContributors", null); - s_descr[6] = new PropertyDescriptor(IPropNames.WEB_SITE, PluginInfo.class, "getWebSite", null); - s_descr[7] = new PropertyDescriptor(IPropNames.VERSION, PluginInfo.class, "getVersion", null); + s_descr.add(new PropertyDescriptor(IPropNames.PLUGIN_CLASS_NAME, PluginInfo.class, "getPluginClassName", null)); + s_descr.add(new PropertyDescriptor(IPropNames.IS_LOADED, PluginInfo.class, "isLoaded", null)); + s_descr.add(new PropertyDescriptor(IPropNames.INTERNAL_NAME, PluginInfo.class, "getInternalName", null)); + s_descr.add(new PropertyDescriptor(IPropNames.DESCRIPTIVE_NAME, PluginInfo.class, "getDescriptiveName", null)); + s_descr.add(new PropertyDescriptor(IPropNames.AUTHOR, PluginInfo.class, "getAuthor", null)); + s_descr.add(new PropertyDescriptor(IPropNames.CONTRIBUTORS, PluginInfo.class, "getContributors", null)); + s_descr.add(new PropertyDescriptor(IPropNames.VERSION, PluginInfo.class, "getVersion", null)); - return s_descr; + return s_descr.toArray(new PropertyDescriptor[0]); } catch (IntrospectionException e) { From 9e07e52de5b4f30e3bf30534cc8ebb58a31704a9 Mon Sep 17 00:00:00 2001 From: GWA Date: Thu, 29 Jan 2026 15:49:13 +0100 Subject: [PATCH 20/33] Feature: The UI table's "Copy separated by ..." right mouse menu function now allows to concatenate cell values without separator. --- sql12/core/doc/changes.txt | 3 + .../copyseparatedby/CopySeparatedByCtrl.java | 103 ++++++++++-------- .../copyseparatedby/CopySeparatedByDlg.java | 75 ++++++++----- .../copyseparatedby/I18NStrings.properties | 6 +- .../TableCopySeparatedByCommand.java | 41 ++++++- 5 files changed, 147 insertions(+), 81 deletions(-) diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 11f8c38c2..dbbe0a625 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,9 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +The UI table's "Copy separated by ..." right mouse menu function now allows + to concatenate cell values without separator. + https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 Session Scripts Plugin: Session startup scripts now support running bookmarks by @runbookmark the same way the SQL editor does. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java index 5dbe57abd..b3790f781 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java @@ -1,27 +1,32 @@ package net.sourceforge.squirrel_sql.fw.gui.action.copyseparatedby; +import javax.swing.JOptionPane; + import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTable; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.props.Props; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; - -import javax.swing.JOptionPane; +import org.apache.commons.lang3.StringUtils; public class CopySeparatedByCtrl { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(CopySeparatedByCtrl.class); + public static final String DEFAULT_CELL_SEPARATOR = ","; + private static final String PREF_KEY_COPYSEPARATEDBYCTRL_CELL_SEPARATOR = "Squirrel.copyseparatedbyctrl.cell.separator"; + private static final String PREF_KEY_JUST_CONCAT_CELLS = "Squirrel.copyseparatedbyctrl.just.concat.cells"; private static final String PREF_KEY_COPYSEPARATEDBYCTRL_CELL_DELIMITER = "Squirrel.copyseparatedbyctrl.cell.delimiter"; private static final String PREF_KEY_COPYSEPARATEDBYCTRL_INCLUDE_HEADERS = "Squirrel.copyseparatedbyctrl.include.headers"; private static final String PREF_KEY_COPYSEPARATEDBYCTRL_ROW_SEPARATOR = "Squirrel.copyseparatedbyctrl.row.separator"; private static final String PREF_KEY_COPYSEPARATEDBYCTRL_ROW_PREFERED_LINE_LEN = "Squirrel.copyseparatedbyctrl.prefered.line.len"; - private CopySeparatedByDlg _copySeparatedByDlg; + private CopySeparatedByDlg _dlg; private boolean _enableRowSeparator; private String _cellSeparator = ""; + private boolean _justConcatCells; private String _cellDelimiter = ""; private boolean _includeHeaders; private String _rowSeparator = ""; @@ -30,97 +35,103 @@ public class CopySeparatedByCtrl public CopySeparatedByCtrl(DataSetViewerTable table, boolean enableRowSeparator) { - _copySeparatedByDlg = new CopySeparatedByDlg(GUIUtils.getOwningFrame(table)); + _dlg = new CopySeparatedByDlg(GUIUtils.getOwningFrame(table)); _enableRowSeparator = enableRowSeparator; - _copySeparatedByDlg.txtCellSeparator.setText(Props.getString(PREF_KEY_COPYSEPARATEDBYCTRL_CELL_SEPARATOR, ",")); - _copySeparatedByDlg.txtCellDelimiter.setText(Props.getString(PREF_KEY_COPYSEPARATEDBYCTRL_CELL_DELIMITER, "")); + _dlg.txtCellSeparator.setText(Props.getString(PREF_KEY_COPYSEPARATEDBYCTRL_CELL_SEPARATOR, DEFAULT_CELL_SEPARATOR)); + _dlg.txtCellDelimiter.setText(Props.getString(PREF_KEY_COPYSEPARATEDBYCTRL_CELL_DELIMITER, "")); + + _dlg.txtLineLength.setInt(Props.getInt(PREF_KEY_COPYSEPARATEDBYCTRL_ROW_PREFERED_LINE_LEN, 100)); + _dlg.txtRowSeparator.setText(Props.getString(PREF_KEY_COPYSEPARATEDBYCTRL_ROW_SEPARATOR, "\\n")); - _copySeparatedByDlg.txtLineLength.setInt(Props.getInt(PREF_KEY_COPYSEPARATEDBYCTRL_ROW_PREFERED_LINE_LEN, 100)); - _copySeparatedByDlg.txtRowSeparator.setText(Props.getString(PREF_KEY_COPYSEPARATEDBYCTRL_ROW_SEPARATOR, "\\n")); + _dlg.chkIncludeHeaders.setSelected(Props.getBoolean(PREF_KEY_COPYSEPARATEDBYCTRL_INCLUDE_HEADERS, false)); + _dlg.chkIncludeHeaders.addActionListener(e -> updateEnabled()); - _copySeparatedByDlg.chkIncludeHeaders.setSelected(Props.getBoolean(PREF_KEY_COPYSEPARATEDBYCTRL_INCLUDE_HEADERS, false)); + _dlg.chkJustConcatCells.setSelected(Props.getBoolean(PREF_KEY_JUST_CONCAT_CELLS, false)); + _dlg.chkJustConcatCells.addActionListener(e -> updateEnabled()); - _copySeparatedByDlg.chkIncludeHeaders.addActionListener(e -> updateEnabled()); updateEnabled(); - _copySeparatedByDlg.btnOk.addActionListener(e -> onOk()); - _copySeparatedByDlg.btnCancel.addActionListener(e -> onCancel()); + _dlg.btnOk.addActionListener(e -> onOk()); + _dlg.btnCancel.addActionListener(e -> onCancel()); - GUIUtils.forceFocus(_copySeparatedByDlg.txtCellSeparator); + GUIUtils.forceFocus(_dlg.txtCellSeparator); - _copySeparatedByDlg.setVisible(true); + _dlg.setVisible(true); } private void updateEnabled() { - _copySeparatedByDlg.txtRowSeparator.setEnabled(true); - _copySeparatedByDlg._lblRowSeparator.setEnabled(true); + _dlg.txtCellSeparator.setEnabled(!_dlg.chkJustConcatCells.isSelected()); + _dlg.lblCellSeparator.setEnabled(!_dlg.chkJustConcatCells.isSelected()); - _copySeparatedByDlg.txtLineLength.setEnabled(true); - _copySeparatedByDlg.lblPreferredLineLength.setEnabled(true); + _dlg.txtRowSeparator.setEnabled(true); + _dlg.lblRowSeparator.setEnabled(true); + _dlg.txtLineLength.setEnabled(true); + _dlg.lblPreferredLineLength.setEnabled(true); - if(false == _enableRowSeparator || _copySeparatedByDlg.chkIncludeHeaders.isSelected()) + + if(false == _enableRowSeparator || _dlg.chkIncludeHeaders.isSelected()) { - _copySeparatedByDlg.txtRowSeparator.setEnabled(false); - _copySeparatedByDlg._lblRowSeparator.setEnabled(false); + _dlg.txtRowSeparator.setEnabled(false); + _dlg.lblRowSeparator.setEnabled(false); //_copySeparatedByDlg.txtRowSeparator.setText(null); } - if(_copySeparatedByDlg.chkIncludeHeaders.isSelected()) + if( _dlg.chkIncludeHeaders.isSelected()) { - _copySeparatedByDlg.txtLineLength.setEnabled(false); - _copySeparatedByDlg.lblPreferredLineLength.setEnabled(false); + _dlg.txtLineLength.setEnabled(false); + _dlg.lblPreferredLineLength.setEnabled(false); } } private void onCancel() { - _copySeparatedByDlg.setVisible(false); - _copySeparatedByDlg.dispose(); + _dlg.setVisible(false); + _dlg.dispose(); } private void onOk() { - if(0 >= _copySeparatedByDlg.txtLineLength.getInt()) + if( 0 > _dlg.txtLineLength.getInt()) { - JOptionPane.showConfirmDialog(_copySeparatedByDlg, s_stringMgr.getString("CopySeparatedByCtrl.invalid.line.length")); + JOptionPane.showConfirmDialog(_dlg, s_stringMgr.getString("CopySeparatedByCtrl.invalid.line.length")); return; } - - String text = ""; - if (null != _copySeparatedByDlg.txtCellSeparator.getText()) + String text = DEFAULT_CELL_SEPARATOR; + if ( null != _dlg.txtCellSeparator.getText()) { - text = _copySeparatedByDlg.txtCellSeparator.getText(); + text = _dlg.txtCellSeparator.getText(); } Props.putString(PREF_KEY_COPYSEPARATEDBYCTRL_CELL_SEPARATOR, text); _cellSeparator = doReplacements(text); + Props.putBoolean(PREF_KEY_JUST_CONCAT_CELLS, _dlg.chkJustConcatCells.isSelected()); + _justConcatCells = _dlg.chkJustConcatCells.isSelected(); String cellDelim = ""; - if (null != _copySeparatedByDlg.txtCellDelimiter.getText()) + if(false == StringUtils.isBlank(_dlg.txtCellDelimiter.getText())) { - cellDelim = _copySeparatedByDlg.txtCellDelimiter.getText(); + cellDelim = _dlg.txtCellDelimiter.getText(); } Props.putString(PREF_KEY_COPYSEPARATEDBYCTRL_CELL_DELIMITER, cellDelim); _cellDelimiter = cellDelim; + Props.putBoolean(PREF_KEY_COPYSEPARATEDBYCTRL_INCLUDE_HEADERS, _dlg.chkIncludeHeaders.isSelected()); + _includeHeaders = _dlg.chkIncludeHeaders.isSelected(); - Props.putBoolean(PREF_KEY_COPYSEPARATEDBYCTRL_INCLUDE_HEADERS, _copySeparatedByDlg.chkIncludeHeaders.isSelected()); - _includeHeaders = _copySeparatedByDlg.chkIncludeHeaders.isSelected(); - - Props.putInt(PREF_KEY_COPYSEPARATEDBYCTRL_ROW_PREFERED_LINE_LEN, _copySeparatedByDlg.txtLineLength.getInt()); - _preferredLineLength = _copySeparatedByDlg.txtLineLength.getInt(); + Props.putInt(PREF_KEY_COPYSEPARATEDBYCTRL_ROW_PREFERED_LINE_LEN, _dlg.txtLineLength.getInt()); + _preferredLineLength = _dlg.txtLineLength.getInt(); - if(_enableRowSeparator && null != _copySeparatedByDlg.txtRowSeparator.getText()) + if(_enableRowSeparator && null != _dlg.txtRowSeparator.getText()) { text = "\\n"; - if (null != _copySeparatedByDlg.txtRowSeparator.getText()) + if ( null != _dlg.txtRowSeparator.getText()) { - text = _copySeparatedByDlg.txtRowSeparator.getText(); + text = _dlg.txtRowSeparator.getText(); } Props.putString(PREF_KEY_COPYSEPARATEDBYCTRL_ROW_SEPARATOR, text); @@ -130,8 +141,8 @@ private void onOk() _isOk = true; - _copySeparatedByDlg.setVisible(false); - _copySeparatedByDlg.dispose(); + _dlg.setVisible(false); + _dlg.dispose(); } private String doReplacements(String text) @@ -145,6 +156,10 @@ public String getCellSeparator() return _cellSeparator; } + public boolean isJustConcatCells() + { + return _justConcatCells; + } public String getRowSeparator() { diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java index 2b586fe1b..818271100 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java @@ -1,39 +1,42 @@ package net.sourceforge.squirrel_sql.fw.gui.action.copyseparatedby; -import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; -import net.sourceforge.squirrel_sql.fw.gui.IntegerField; -import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; -import net.sourceforge.squirrel_sql.fw.gui.buttontabcomponent.SmallToolTipInfoButton; -import net.sourceforge.squirrel_sql.fw.util.StringManager; -import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; +import net.sourceforge.squirrel_sql.fw.gui.IntegerField; +import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; +import net.sourceforge.squirrel_sql.fw.gui.buttontabcomponent.SmallToolTipInfoButton; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; public class CopySeparatedByDlg extends JDialog { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(CopySeparatedByDlg.class); + JLabel lblCellSeparator = new JLabel(s_stringMgr.getString("CopySeparatedByDlg.cell.separator")); JTextField txtCellSeparator = new JTextField(); + JCheckBox chkJustConcatCells = new JCheckBox(s_stringMgr.getString("CopySeparatedByDlg.justConcat.cells")); + JTextField txtCellDelimiter = new JTextField(); JCheckBox chkIncludeHeaders = new JCheckBox(s_stringMgr.getString("CopySeparatedByDlg.include.column.headers")); - JLabel _lblRowSeparator = new JLabel(s_stringMgr.getString("CopySeparatedByDlg.row.separator")); + JLabel lblRowSeparator = new JLabel(s_stringMgr.getString("CopySeparatedByDlg.row.separator")); JTextField txtRowSeparator = new JTextField(); JLabel lblPreferredLineLength = new JLabel(s_stringMgr.getString("CopySeparatedByDlg.prefered.line.length")); - IntegerField txtLineLength = new IntegerField(6); + IntegerField txtLineLength = new IntegerField(8); JButton btnOk = new JButton(s_stringMgr.getString("CopySeparatedByDlg.cell.ok")); JButton btnCancel = new JButton(s_stringMgr.getString("CopySeparatedByDlg.cell.cancel")); @@ -87,40 +90,44 @@ private JPanel createControlsPanel() GridBagConstraints gbc; - gbc = new GridBagConstraints(0, 0 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0); - ret.add(new JLabel(s_stringMgr.getString("CopySeparatedByDlg.cell.separator")), gbc); + gbc = new GridBagConstraints(0, 0 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,0,0), 0,0); + ret.add(lblCellSeparator, gbc); - gbc = new GridBagConstraints(1, 0 , 1, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0); - //txtCellSeparator.setPreferredSize(new Dimension(70, txtCellSeparator.getPreferredSize().height)); + gbc = new GridBagConstraints(1, 0 , 1, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,0,5), 0,0); ret.add(txtCellSeparator, gbc); - gbc = new GridBagConstraints(0, 1 , 1, 1, 0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0); + gbc = new GridBagConstraints(0, 1 , 2, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0,20,0,0), 0,0); + ret.add(chkJustConcatCells, gbc); + + + gbc = new GridBagConstraints(0, 2 , 1, 1, 0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(15,5,0,5), 0,0); ret.add(createCellDelimiterLabelPanel(), gbc); - gbc = new GridBagConstraints(1, 1 , 1, 1, 1,0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0); + gbc = new GridBagConstraints(1, 2 , 1, 1, 1,0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(15,5,0,5), 0,0); ret.add(txtCellDelimiter, gbc); - gbc = new GridBagConstraints(0, 2 , 2, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(15,5,0,5), 0,0); + + gbc = new GridBagConstraints(0, 3 , 2, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(15,5,0,5), 0,0); ret.add(GUIUtils.createHorizontalSeparatorPanel(), gbc); - gbc = new GridBagConstraints(0, 3 , 2, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0); + gbc = new GridBagConstraints(0, 4 , 2, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,0,5), 0,0); ret.add(chkIncludeHeaders, gbc); - gbc = new GridBagConstraints(0, 4 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0); - ret.add(_lblRowSeparator, gbc); + gbc = new GridBagConstraints(0, 5 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,0,0), 0,0); + ret.add(lblRowSeparator, gbc); - gbc = new GridBagConstraints(1, 4 , 1, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0,0); + gbc = new GridBagConstraints(1, 5 , 1, 1, 1,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,0,5), 0,0); //txtRowSeparator.setPreferredSize(new Dimension(70, txtRowSeparator.getPreferredSize().height)); ret.add(txtRowSeparator, gbc); - gbc = new GridBagConstraints(0, 5 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0); - ret.add(lblPreferredLineLength, gbc); + gbc = new GridBagConstraints(0, 6 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,0,0), 0,0); + ret.add(createPreferredLineLengthLabelPanel(), gbc); - gbc = new GridBagConstraints(1, 5 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0); - txtLineLength.setPreferredSize(new Dimension(70, txtLineLength.getPreferredSize().height)); + gbc = new GridBagConstraints(1, 6 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,0,5), 0,0); + txtLineLength.setPreferredSize(new Dimension(100, txtLineLength.getPreferredSize().height)); ret.add(txtLineLength, gbc); @@ -141,4 +148,12 @@ private JPanel createCellDelimiterLabelPanel() return ret; } + + private JPanel createPreferredLineLengthLabelPanel() + { + JPanel ret = new JPanel(new BorderLayout()); + ret.add(lblPreferredLineLength, BorderLayout.CENTER); + ret.add(new SmallToolTipInfoButton(s_stringMgr.getString("CopySeparatedByDlg.preferred.line.length.info")).getButton(), BorderLayout.EAST); + return ret; + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties index ba75cdacb..a970f77b4 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties @@ -18,4 +18,8 @@ CopySeparatedByDlg.description=Configure separators for cells and rows. If the s CopySeparatedByDlg.prefered.line.length=Preferred line length -CopySeparatedByCtrl.invalid.line.length=Please enter a valid line length. \ No newline at end of file +CopySeparatedByCtrl.invalid.line.length=Please enter a valid line length. +CopySeparatedByDlg.preferred.line.length.info=0 means no line length limit. + +CopySeparatedByDlg.justConcat.cells=Just concatenate cell values + diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java index 6ad71e117..e648a6dd1 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java @@ -32,6 +32,11 @@ public void execute() String cellSeparator = copySeparatedByCtrl.getCellSeparator(); + if(copySeparatedByCtrl.isJustConcatCells()) + { + cellSeparator = ""; + } + String rowSeparator = "\n"; if(false == copySeparatedByCtrl.isIncludeHeaders()) @@ -47,8 +52,6 @@ public void execute() int preferredLineLength = copySeparatedByCtrl.getPreferredLineLength(); - - int nbrSelRows = _table.getSelectedRowCount(); int[] selRows = _table.getSelectedRows(); int[] selCols = _table.getSelectedColumns(); @@ -93,7 +96,9 @@ public void execute() { sb.append(cellSeparator); - if(false == copySeparatedByCtrl.isIncludeHeaders() && preferredLineLength < getDistToLastNewLine(sb)) + if( false == copySeparatedByCtrl.isIncludeHeaders() + && 0 < preferredLineLength + && preferredLineLength < getDistToLastNewLine(sb)) { sb.append("\n"); } @@ -107,10 +112,13 @@ public void execute() } } - if(cellObj instanceof String && -1 < ((String)cellObj).indexOf('\n')) + if( false == copySeparatedByCtrl.isJustConcatCells() + && cellObj instanceof String cellStr + && -1 < indexOfFirstLineBreakChar(cellStr) ) { - int lineBreakPos = ((String)cellObj).indexOf('\n'); - sb.append(wrapCellDelimiter(cellObj, copySeparatedByCtrl.getCellDelimiter()), 0, lineBreakPos); + int lineBreakPos = indexOfFirstLineBreakChar(cellStr); + cellStr = cellStr.substring(0, lineBreakPos); + sb.append(wrapCellDelimiter(cellStr, copySeparatedByCtrl.getCellDelimiter())); } else if(null == cellObj) { @@ -126,6 +134,27 @@ else if(null == cellObj) ClipboardUtil.copyToClip(sb); } + private static int indexOfFirstLineBreakChar(String cellStr) + { + int indexOfNewLine = cellStr.indexOf('\n'); + int indexOfCarriageReturn = cellStr.indexOf('\r'); + + if(-1 == indexOfNewLine && -1 == indexOfCarriageReturn) + { + return -1; + } + else if(-1 == indexOfNewLine) + { + return indexOfCarriageReturn; + } + else if(-1 == indexOfCarriageReturn) + { + return indexOfNewLine; + } + + return Math.min(indexOfCarriageReturn, indexOfNewLine); + } + private String wrapCellDelimiter(Object cellContent, String cellDelimiter) { if(StringUtilities.isEmpty(cellDelimiter, true)) From b6a0828e5ccf4b43f227e135b01910517a6bcbf8 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 7 Feb 2026 22:07:56 +0100 Subject: [PATCH 21/33] Feature: The UI-table's "Copy separated by ..." right mouse menu function now allows to display the copy result in a cell data dialog. --- sql12/core/doc/changes.txt | 5 +- .../celldatapopup/CellDataDialog.java | 67 +++++------------ .../CellDataDialogEditableState.java | 34 +++++++++ .../celldatapopup/CellDataDialogHandler.java | 65 ++++++++++------ .../celldatapopup/CellDataDialogState.java | 75 +++++++++++++++++++ .../celldatapopup/CellDataUpdateInfo.java | 30 ++++---- ...ultDataSetAndCellDetailDisplayHandler.java | 29 ++++--- .../ResultImageDisplayPanel.java | 31 ++++---- .../copyseparatedby/CopySeparatedByCtrl.java | 20 ++++- .../copyseparatedby/CopySeparatedByDlg.java | 17 +++-- .../copyseparatedby/I18NStrings.properties | 3 + .../TableCopySeparatedByCommand.java | 15 +++- 12 files changed, 267 insertions(+), 124 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogEditableState.java create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogState.java diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index dbbe0a625..26268de7d 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,7 +6,10 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: -The UI table's "Copy separated by ..." right mouse menu function now allows +The UI-table's "Copy separated by ..." right mouse menu function now allows + to display the copy result in a cell data dialog. + +The UI-table's "Copy separated by ..." right mouse menu function now allows to concatenate cell values without separator. https://github.com/squirrel-sql-client/squirrel-sql-code/issues/81 diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialog.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialog.java index 5c255150b..49067b59d 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialog.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialog.java @@ -1,22 +1,17 @@ package net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup; import java.awt.GridLayout; +import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JDialog; -import javax.swing.JTable; -import javax.swing.SwingUtilities; - import net.sourceforge.squirrel_sql.client.Main; -import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; -import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTable; import net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice.CellDisplayPanel; import net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice.CellDisplayPanelContent; import net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice.DisplayMode; import net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice.DisplayPanelListener; import net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice.ResultImageDisplayPanel; import net.sourceforge.squirrel_sql.fw.datasetviewer.tablefind.GlobalFindRemoteControl; -import net.sourceforge.squirrel_sql.fw.gui.CloseByEscapeListener; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; @@ -27,27 +22,14 @@ public class CellDataDialog extends JDialog private CellDisplayPanel _cellDisplayPanel; - public CellDataDialog(JTable parentTable, - String columnName, - int rowIx, - int colIx, - ColumnDisplayDefinition colDef, - Object objectToDisplay, - boolean isModelEditable) + public CellDataDialog(CellDataDialogState cellDataDialogState, Window parentWindow) { - super(SwingUtilities.windowForComponent(parentTable)); + super(parentWindow); getContentPane().setLayout(new GridLayout(1,1)); - initCellDisplayPanel(parentTable, columnName, rowIx, colIx, colDef, objectToDisplay, isModelEditable,false); + initCellDisplayPanel(cellDataDialogState); - GUIUtils.enableCloseByEscape(this, new CloseByEscapeListener() - { - @Override - public void willCloseByEscape(JDialog dialog) - { - cleanUp(); - } - }); + GUIUtils.enableCloseByEscape(this, dialog -> cleanUp()); addWindowListener(new WindowAdapter() { @@ -70,15 +52,10 @@ private void cleanUp() _cellDisplayPanel.cleanUp(); } - public void initCellDisplayPanel(JTable table, - String columnName, - int rowIx, - int colIx, - ColumnDisplayDefinition colDef, - Object value, - boolean isModelEditable, - boolean pinned) + public void initCellDisplayPanel(CellDataDialogState cellDataDialogState) { + + if(null != _cellDisplayPanel) { getContentPane().remove(_cellDisplayPanel); @@ -86,14 +63,14 @@ public void initCellDisplayPanel(JTable table, _cellDisplayPanel = null; } - setTitle(s_stringMgr.getString("cellDataPopup.valueofColumn", columnName)); + setTitle(s_stringMgr.getString("cellDataPopup.valueofColumn", cellDataDialogState.getCellName())); DisplayPanelListener displayPanelListener = new DisplayPanelListener() { @Override public void displayModeChanged() { - onDisplayModeChanged(colDef, value, rowIx, colIx, isModelEditable, table); + onDisplayModeChanged(cellDataDialogState); } @Override @@ -103,12 +80,12 @@ public void scaleImageToPanelSize() } }; - _cellDisplayPanel =new CellDisplayPanel(displayPanelListener,sticky -> onToggleSticky(sticky), pinned); + _cellDisplayPanel =new CellDisplayPanel(displayPanelListener,sticky -> onToggleSticky(sticky), cellDataDialogState.isPinned()); - _cellDisplayPanel.setCurrentColumnDisplayDefinition(colDef); + _cellDisplayPanel.setCurrentColumnDisplayDefinition(cellDataDialogState.getColDispDef()); getContentPane().add(_cellDisplayPanel); - onDisplayModeChanged(colDef, value, rowIx, colIx, isModelEditable, table); + onDisplayModeChanged(cellDataDialogState); } private void onScaleImageToPanelSize() @@ -132,28 +109,24 @@ private void onToggleSticky(boolean sticky) } } - private void onDisplayModeChanged(ColumnDisplayDefinition colDef, Object value, int row, int col, boolean isModelEditable, JTable table) + private void onDisplayModeChanged(CellDataDialogState cellDataDialogState) { CellDisplayPanelContent pnlToDisplay; if(DisplayMode.IMAGE == _cellDisplayPanel.getDisplayMode()) { - pnlToDisplay = new ResultImageDisplayPanel(colDef, - value, - isModelEditable, - row, - col, - () -> _cellDisplayPanel.getContentComponent().castToComponent().getSize(), - (DataSetViewerTable) table); + pnlToDisplay = new ResultImageDisplayPanel(cellDataDialogState, + () -> _cellDisplayPanel.getContentComponent().castToComponent().getSize() + ); } else { - CellDataColumnDataPanel cellDataPanel = new CellDataColumnDataPanel(value, colDef, isModelEditable); - cellDataPanel.setCellDataUpdateInfo(new CellDataUpdateInfo(row, col, table, this)); + CellDataColumnDataPanel cellDataPanel = new CellDataColumnDataPanel(cellDataDialogState.getValueToDisplay(), cellDataDialogState.getColDispDef(), cellDataDialogState.isEditable()); + cellDataPanel.setCellDataUpdateInfo(new CellDataUpdateInfo(cellDataDialogState, this)); pnlToDisplay = cellDataPanel; } - _cellDisplayPanel.setCurrentColumnDisplayDefinition(colDef); + _cellDisplayPanel.setCurrentColumnDisplayDefinition(cellDataDialogState.getColDispDef()); _cellDisplayPanel.setContentComponent(pnlToDisplay); _cellDisplayPanel.revalidate(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogEditableState.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogEditableState.java new file mode 100644 index 000000000..5064c3f69 --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogEditableState.java @@ -0,0 +1,34 @@ +package net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup; + +import javax.swing.JTable; +import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTable; + +public class CellDataDialogEditableState +{ + private final JTable _table; + private final int _rowIx; + private final int _colIx; + + public CellDataDialogEditableState(JTable table, int rowIx, int colIx) + { + _table = table; + _rowIx = rowIx; + _colIx = colIx; + } + + + public int getRowIx() + { + return _rowIx; + } + + public int getColIx() + { + return _colIx; + } + + public DataSetViewerTable getDatasetViewerTable() + { + return (DataSetViewerTable) _table; + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogHandler.java index d7817ca61..22d8d66bb 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogHandler.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogHandler.java @@ -18,18 +18,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.client.Main; -import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; -import net.sourceforge.squirrel_sql.fw.datasetviewer.ExtTableColumn; -import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; -import net.sourceforge.squirrel_sql.fw.props.Props; -import net.sourceforge.squirrel_sql.fw.util.StringManager; -import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; - -import javax.swing.CellEditor; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.table.TableColumn; import java.awt.Component; import java.awt.Dimension; import java.awt.Point; @@ -38,6 +26,17 @@ import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import javax.swing.CellEditor; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.TableColumn; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; +import net.sourceforge.squirrel_sql.fw.datasetviewer.ExtTableColumn; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; +import net.sourceforge.squirrel_sql.fw.props.Props; +import net.sourceforge.squirrel_sql.fw.util.StringManager; +import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; /** * Generate a popup window to display and manipulate the @@ -116,7 +115,10 @@ public static void showSelectedValueInPinnedCellDataDialog(JTable table, boolean Object obj = table.getValueAt(selectedRow, selectedColumn); ColumnDisplayDefinition colDef = ((ExtTableColumn) column).getColumnDisplayDefinition(); - pinnedCellDataDialog.initCellDisplayPanel(table, table.getColumnName(selectedColumn), selectedRow, selectedColumn, colDef, obj, isModelEditable, true); + CellDataDialogState cellDataDialogState = + new CellDataDialogState(table.getColumnName(selectedColumn), colDef, obj, true, isModelEditable, table, selectedRow, selectedColumn); + + pinnedCellDataDialog.initCellDisplayPanel(cellDataDialogState); } @@ -130,7 +132,21 @@ private static void createAndShowCellDataDialog(JTable parentTable, boolean isModelEditable, MouseEvent evt) { - CellDataDialog cellDataDialog = new CellDataDialog(parentTable, columnName, rowIx, colIx, colDef, objectToDisplay, isModelEditable); + CellDataDialogState cellDataDialogState = + new CellDataDialogState(columnName, colDef, objectToDisplay, false, isModelEditable, parentTable, rowIx, colIx); + + createAndShowCellDataDialog(cellDataDialogState, SwingUtilities.windowForComponent(parentTable), evt); + } + + public static void createAndShowCellDataDialog(CellDataDialogState cellDataDialogState, Window parentWindow) + { + createAndShowCellDataDialog(cellDataDialogState, parentWindow, null); + } + + + public static void createAndShowCellDataDialog(CellDataDialogState cellDataDialogState, Window parentWindow, MouseEvent mouseEvent) + { + CellDataDialog cellDataDialog = new CellDataDialog(cellDataDialogState, parentWindow); cellDataDialog.pack(); @@ -162,16 +178,21 @@ private static void createAndShowCellDataDialog(JTable parentTable, } } - Window parentWindow = SwingUtilities.windowForComponent(parentTable); - Point dialogPos = parentWindow.getLocation(); - - dialogPos.x += SwingUtilities.convertPoint((Component) evt.getSource(), evt.getPoint(), parentWindow).x; - dialogPos.y += SwingUtilities.convertPoint((Component) evt.getSource(), evt.getPoint(), parentWindow).y; - - Rectangle dialogRect = GUIUtils.ensureBoundsOnOneScreen(new Rectangle(dialogPos.x, dialogPos.y, dim.width, dim.height)); + if(null != mouseEvent) + { + Point dialogPos = parentWindow.getLocation(); + dialogPos.x += SwingUtilities.convertPoint((Component) mouseEvent.getSource(), mouseEvent.getPoint(), parentWindow).x; + dialogPos.y += SwingUtilities.convertPoint((Component) mouseEvent.getSource(), mouseEvent.getPoint(), parentWindow).y; + Rectangle dialogRect = GUIUtils.ensureBoundsOnOneScreen(new Rectangle(dialogPos.x, dialogPos.y, dim.width, dim.height)); - cellDataDialog.setBounds(dialogRect); + cellDataDialog.setBounds(dialogRect); + } + else + { + cellDataDialog.setSize(dim); + GUIUtils.centerWithinParent(cellDataDialog); + } cellDataDialog.addWindowListener(new WindowAdapter() { diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogState.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogState.java new file mode 100644 index 000000000..f46c93743 --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataDialogState.java @@ -0,0 +1,75 @@ +package net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup; + +import java.sql.Types; +import javax.swing.JTable; +import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; + +public class CellDataDialogState +{ + private final String _columnName; + private final ColumnDisplayDefinition _colDef; + private final Object _valueToDisplay; + private final boolean _isModelEditable; + private final boolean _pinned; + private final CellDataDialogEditableState _cellDataDialogEditableState; + + public CellDataDialogState(String columnName, ColumnDisplayDefinition colDef, Object value, boolean pinned, boolean isModelEditable, JTable table, int rowIx, int colIx) + { + _columnName = columnName; + _colDef = colDef; + _valueToDisplay = value; + _isModelEditable = isModelEditable; + _pinned = pinned; + + _cellDataDialogEditableState = new CellDataDialogEditableState(table, rowIx, colIx); + } + + public CellDataDialogState(String dialogTitlePostfix, String value) + { + _columnName = dialogTitlePostfix; + _valueToDisplay = value; + + _colDef = new ColumnDisplayDefinition(100, dialogTitlePostfix); + _colDef.setSqlType(Types.VARCHAR); + _colDef.setSqlTypeName("VARCHAR"); + + _isModelEditable = false; + _pinned = false; + _cellDataDialogEditableState = null; + } + + public String getCellName() + { + return _columnName; + } + + public boolean isEditable() + { + return _isModelEditable; + } + + public ColumnDisplayDefinition getColDispDef() + { + return _colDef; + } + + public Object getValueToDisplay() + { + return _valueToDisplay; + } + + public boolean isPinned() + { + return _pinned; + } + + public CellDataDialogEditableState getEditableState() + { + if(false == isEditable()) + { + throw new IllegalStateException("Only to be called when updateable"); + } + + return _cellDataDialogEditableState; + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataUpdateInfo.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataUpdateInfo.java index 31ac5fa77..a5ff3b245 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataUpdateInfo.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/celldatapopup/CellDataUpdateInfo.java @@ -4,48 +4,44 @@ public class CellDataUpdateInfo { - private final int _row; - private final int _col; - private JTable _table; - private CellDataDialog _parentDialog; + private CellDataDialogState _cellDataDialogState; + private CellDataDialog _parentCellDataDialog; - public CellDataUpdateInfo(int row, int col, JTable table, CellDataDialog parentDialog) + public CellDataUpdateInfo(CellDataDialogState cellDataDialogState, CellDataDialog parentCellDataDialog) { - _row = row; - _col = col; - _table = table; - _parentDialog = parentDialog; + _cellDataDialogState = cellDataDialogState; + _parentCellDataDialog = parentCellDataDialog; } public int getRow() { - return _row; + return _cellDataDialogState.getEditableState().getRowIx(); } public int getCol() { - return _col; + return _cellDataDialogState.getEditableState().getColIx(); } public JTable getTable() { - return _table; + return _cellDataDialogState.getEditableState().getDatasetViewerTable(); } public void closeParentDialog() { - if(null == _parentDialog) + if(null == _parentCellDataDialog) { return; } - _parentDialog.setVisible(false); - _parentDialog.dispose(); + _parentCellDataDialog.setVisible(false); + _parentCellDataDialog.dispose(); } public void cleanUp() { - _parentDialog = null; - _table = null; + _parentCellDataDialog = null; + _cellDataDialogState = null; } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultDataSetAndCellDetailDisplayHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultDataSetAndCellDetailDisplayHandler.java index 0ce27352c..a7df7d59f 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultDataSetAndCellDetailDisplayHandler.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultDataSetAndCellDetailDisplayHandler.java @@ -1,9 +1,16 @@ package net.sourceforge.squirrel_sql.fw.datasetviewer.columndisplaychoice; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.beans.PropertyChangeEvent; +import javax.swing.BorderFactory; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTablePanel; import net.sourceforge.squirrel_sql.fw.datasetviewer.ExtTableColumn; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetViewer; import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataColumnDataPanel; +import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataDialogState; import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataUpdateInfo; import net.sourceforge.squirrel_sql.fw.datasetviewer.tablefind.GlobalFindRemoteControl; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; @@ -11,13 +18,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import javax.swing.BorderFactory; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.beans.PropertyChangeEvent; - public class ResultDataSetAndCellDetailDisplayHandler { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ResultDataSetAndCellDetailDisplayHandler.class); @@ -137,20 +137,19 @@ private void onRowColSelectionChanged(DataSetViewerTablePanel dataSetViewer, boo _rightCellDisplayPanel.setCurrentColumnDisplayDefinition(column.getColumnDisplayDefinition()); CellDisplayPanelContent pnlToDisplay; + + CellDataDialogState cellDataDialogState = new CellDataDialogState(column.getColumnDisplayDefinition().getColumnName(), column.getColumnDisplayDefinition(), value, false, dataSetViewer.isTableEditable(), dataSetViewer.getTable(), + rowLeadSelectionIndex, + colLeadSelectionIndex + ); if(DisplayMode.IMAGE == _rightCellDisplayPanel.getDisplayMode()) { - pnlToDisplay = new ResultImageDisplayPanel(column.getColumnDisplayDefinition(), - value, - dataSetViewer.isTableEditable(), - rowLeadSelectionIndex, - colLeadSelectionIndex, - () -> _rightCellDisplayPanel.getContentComponent().castToComponent().getSize(), - dataSetViewer.getTable()); + pnlToDisplay = new ResultImageDisplayPanel(cellDataDialogState, () -> _rightCellDisplayPanel.getContentComponent().castToComponent().getSize()); } else { CellDataColumnDataPanel panel = new CellDataColumnDataPanel(value, column.getColumnDisplayDefinition(), dataSetViewer.isTableEditable()); - panel.setCellDataUpdateInfo(new CellDataUpdateInfo(rowLeadSelectionIndex, colLeadSelectionIndex, dataSetViewer.getTable(), null)); + panel.setCellDataUpdateInfo(new CellDataUpdateInfo(cellDataDialogState, null)); pnlToDisplay = panel; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultImageDisplayPanel.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultImageDisplayPanel.java index 81d7a53bb..6251968aa 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultImageDisplayPanel.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/columndisplaychoice/ResultImageDisplayPanel.java @@ -23,7 +23,6 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingConstants; - import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.dnd.DropedFileExtractor; import net.sourceforge.squirrel_sql.client.resources.SquirrelResources; @@ -33,6 +32,7 @@ import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.ClobDescriptor; import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.DataTypeBlobProperties; import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.DataTypeClobProperties; +import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataDialogState; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; import net.sourceforge.squirrel_sql.fw.util.StringManager; @@ -52,23 +52,17 @@ public class ResultImageDisplayPanel extends JPanel implements CellDisplayPanelC private BufferedImage _image; - public ResultImageDisplayPanel(ColumnDisplayDefinition cdd, - Object valueToDisplay, - boolean tableEditable, - int selRow, - int selCol, - ImageContainerSizeProvider imageContainerSizeProvider, - DataSetViewerTable table) + public ResultImageDisplayPanel(CellDataDialogState cellDataDialogState, ImageContainerSizeProvider imageContainerSizeProvider) { _imageContainerSizeProvider = imageContainerSizeProvider; setLayout(new BorderLayout(3,3)); add(_scrImage, BorderLayout.CENTER); - updateImageDisplay(cdd, valueToDisplay); + updateImageDisplay(cellDataDialogState.getColDispDef(), cellDataDialogState.getValueToDisplay()); - if(tableEditable) + if(cellDataDialogState.isEditable()) { - add(createUpdatePanel(selRow, selCol, table, cdd), BorderLayout.SOUTH); + add(createUpdatePanel(cellDataDialogState), BorderLayout.SOUTH); } } @@ -77,7 +71,7 @@ private void updateImageDisplay(ColumnDisplayDefinition cdd, Object valueToDispl _scrImage.setViewportView(getDisplayComponent(cdd, valueToDisplay)); } - private JPanel createUpdatePanel(int selRow, int selCol, DataSetViewerTable table, ColumnDisplayDefinition cdd) + private JPanel createUpdatePanel(CellDataDialogState state) { JPanel ret = new JPanel(new BorderLayout(0,3)); @@ -89,7 +83,11 @@ private JPanel createUpdatePanel(int selRow, int selCol, DataSetViewerTable tabl @Override public void drop(DropTargetDropEvent dtde) { - onDrop(dtde, selRow, selCol, table, cdd); + onDrop(dtde, + state.getEditableState().getRowIx(), + state.getEditableState().getColIx(), + state.getEditableState().getDatasetViewerTable(), + state.getColDispDef()); } }); @@ -103,7 +101,12 @@ public void drop(DropTargetDropEvent dtde) JButton btnDel = new JButton(Main.getApplication().getResources().getIcon(SquirrelResources.IImageNames.DELETE)); btnDel.setToolTipText(s_stringMgr.getString("ResultImageDisplayPanel.delete.image.from.database.tooltip")); - btnDel.addActionListener(e -> onDelete(selRow, selCol, table, cdd)); + + btnDel.addActionListener(e -> onDelete(state.getEditableState().getRowIx(), + state.getEditableState().getColIx(), + state.getEditableState().getDatasetViewerTable(), + state.getColDispDef())); + ret.add(GUIUtils.styleAsToolbarButton(btnDel), BorderLayout.EAST); return ret; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java index b3790f781..861758cb3 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByCtrl.java @@ -1,7 +1,6 @@ package net.sourceforge.squirrel_sql.fw.gui.action.copyseparatedby; import javax.swing.JOptionPane; - import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTable; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.props.Props; @@ -32,6 +31,7 @@ public class CopySeparatedByCtrl private String _rowSeparator = ""; private int _preferredLineLength; private boolean _isOk; + private boolean _inCellDataPopup; public CopySeparatedByCtrl(DataSetViewerTable table, boolean enableRowSeparator) { @@ -54,6 +54,7 @@ public CopySeparatedByCtrl(DataSetViewerTable table, boolean enableRowSeparator) _dlg.btnOk.addActionListener(e -> onOk()); _dlg.btnCancel.addActionListener(e -> onCancel()); + _dlg.btnInCellDataPopup.addActionListener(e -> onInCellDataPopup()); GUIUtils.forceFocus(_dlg.txtCellSeparator); @@ -93,6 +94,18 @@ private void onCancel() _dlg.dispose(); } + private void onInCellDataPopup() + { + onOk(); + + if(_isOk) + { + _inCellDataPopup = true; + } + } + + + private void onOk() { if( 0 > _dlg.txtLineLength.getInt()) @@ -185,4 +198,9 @@ public boolean isOk() { return _isOk; } + + public boolean isInCellDataPopup() + { + return _inCellDataPopup; + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java index 818271100..57cea64e0 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/CopySeparatedByDlg.java @@ -1,7 +1,6 @@ package net.sourceforge.squirrel_sql.fw.gui.action.copyseparatedby; import java.awt.BorderLayout; -import java.awt.Dimension; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; @@ -12,7 +11,6 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; - import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.gui.IntegerField; import net.sourceforge.squirrel_sql.fw.gui.MultipleLineLabel; @@ -40,6 +38,7 @@ public class CopySeparatedByDlg extends JDialog JButton btnOk = new JButton(s_stringMgr.getString("CopySeparatedByDlg.cell.ok")); JButton btnCancel = new JButton(s_stringMgr.getString("CopySeparatedByDlg.cell.cancel")); + JButton btnInCellDataPopup = new JButton(s_stringMgr.getString("CopySeparatedByDlg.cell.show.in.cell.data.popup")); public CopySeparatedByDlg(Frame owningFrame) @@ -56,8 +55,8 @@ public CopySeparatedByDlg(Frame owningFrame) gbc = new GridBagConstraints(0, 1 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0,5,5,5), 0,0); getContentPane().add(createControlsPanel(), gbc); - gbc = new GridBagConstraints(0, 2 , 1, 1, 0,1, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(0,5,5,5), 0,0); - getContentPane().add(createButtoPanel(), gbc); + gbc = new GridBagConstraints(0, 2 , 1, 1, 0,1, GridBagConstraints.SOUTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0,5,5,5), 0,0); + getContentPane().add(createButtonPanel(), gbc); setSize(350, 350); @@ -68,7 +67,7 @@ public CopySeparatedByDlg(Frame owningFrame) getRootPane().setDefaultButton(btnOk); } - private JPanel createButtoPanel() + private JPanel createButtonPanel() { JPanel ret = new JPanel(new GridBagLayout()); @@ -80,6 +79,11 @@ private JPanel createButtoPanel() gbc = new GridBagConstraints(1, 0 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0,0); ret.add(btnCancel, gbc); + gbc = new GridBagConstraints(2, 0 , 1, 1, 1,0, GridBagConstraints.NORTHEAST, GridBagConstraints.HORIZONTAL, new Insets(5,0,5,5), 0,0); + ret.add(new JPanel(), gbc); + + gbc = new GridBagConstraints(3, 0 , 1, 1, 0,0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(5,0,5,5), 0,0); + ret.add(btnInCellDataPopup, gbc); return ret; } @@ -127,7 +131,8 @@ private JPanel createControlsPanel() ret.add(createPreferredLineLengthLabelPanel(), gbc); gbc = new GridBagConstraints(1, 6 , 1, 1, 0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,5,0,5), 0,0); - txtLineLength.setPreferredSize(new Dimension(100, txtLineLength.getPreferredSize().height)); + GUIUtils.setPreferredWidth(txtLineLength, 100); + GUIUtils.setMinimumWidth(txtLineLength, 100); ret.add(txtLineLength, gbc); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties index a970f77b4..c1f96c770 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/I18NStrings.properties @@ -23,3 +23,6 @@ CopySeparatedByDlg.preferred.line.length.info=0 means no line length limit. CopySeparatedByDlg.justConcat.cells=Just concatenate cell values +CopySeparatedByDlg.cell.show.in.cell.data.popup=To cell data popup + +TableCopySeparatedByCommand.cell.data.dialog.title="Copy result" \ No newline at end of file diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java index e648a6dd1..20abd9b53 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/action/copyseparatedby/TableCopySeparatedByCommand.java @@ -2,7 +2,10 @@ import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTable; import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.BaseDataTypeComponent; +import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataDialogHandler; +import net.sourceforge.squirrel_sql.fw.datasetviewer.celldatapopup.CellDataDialogState; import net.sourceforge.squirrel_sql.fw.gui.ClipboardUtil; +import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; import net.sourceforge.squirrel_sql.fw.util.StringUtilities; @@ -131,7 +134,17 @@ else if(null == cellObj) } } - ClipboardUtil.copyToClip(sb); + if(copySeparatedByCtrl.isInCellDataPopup()) + { + CellDataDialogState cellDataDialogState = + new CellDataDialogState(s_stringMgr.getString("TableCopySeparatedByCommand.cell.data.dialog.title"), sb.toString()); + + CellDataDialogHandler.createAndShowCellDataDialog(cellDataDialogState, GUIUtils.getOwningWindow(_table)); + } + else + { + ClipboardUtil.copyToClip(sb); + } } private static int indexOfFirstLineBreakChar(String cellStr) From adbe021b5d5dc1d2dfae2a9211dfd7cc3e50a847 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 7 Feb 2026 22:42:35 +0100 Subject: [PATCH 22/33] Refactoring --- .../client/session/mainpanel/TimerHolder.java | 16 ++----- .../fw/datasetviewer/ResultSetDataSet.java | 45 ++++++++++--------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TimerHolder.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TimerHolder.java index 152661db4..d94135c0d 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TimerHolder.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/TimerHolder.java @@ -1,12 +1,11 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel; +import javax.swing.JCheckBox; +import javax.swing.JTextField; +import javax.swing.Timer; import net.sourceforge.squirrel_sql.client.session.mainpanel.notificationsound.FinishedNotificationSoundHandler; import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet; -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - /** * This timer treatment seems to give better Session GCing behaviour. @@ -32,14 +31,7 @@ public TimerHolder(JTextField txtExecTimeCounter, JTextField txtNumberOfRowsRead _txtExecTimeCounter = txtExecTimeCounter; _txtNumberOfRowsRead = txtNumberOfRowsRead; - _timer = new Timer(300, new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - onUpdateExecutionTime(); - } - }); + _timer = new Timer(300, e -> onUpdateExecutionTime()); _timer.setRepeats(true); _timer.start(); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java index 9b977c62a..eed94f148 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java @@ -21,6 +21,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Types; +import java.util.ArrayList; +import java.util.List; import net.sourceforge.squirrel_sql.fw.dialects.DialectType; import net.sourceforge.squirrel_sql.fw.sql.JDBCTypeMapper; import net.sourceforge.squirrel_sql.fw.sql.ResultSetReader; @@ -30,10 +37,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import java.sql.*; -import java.util.ArrayList; -import java.util.List; - public class ResultSetDataSet implements IDataSet { private final static ILogger s_log = LoggerController.createLogger(ResultSetDataSet.class); @@ -47,7 +50,7 @@ public class ResultSetDataSet implements IDataSet private DataSetDefinition _dataSetDefinition; - private List _alData; + private List _allData; /** * If true cancel has been requested. @@ -161,7 +164,7 @@ private int _setResultSet(ResultSetWrapper rs, } _iCurrent = -1; - _alData = new ArrayList<>(); + _allData = new ArrayList<>(); if (rs == null) { @@ -193,7 +196,7 @@ private int _setResultSet(ResultSetWrapper rs, { if (_cancel) { - return _alData.size(); + return _allData.size(); } Object[] row = createRow(columnIndices, useColumnDefs, colDefs, BlockMode.FIRST_BLOCK); @@ -204,11 +207,11 @@ private int _setResultSet(ResultSetWrapper rs, } else { - _alData.add(row); + _allData.add(row); } } - return _alData.size(); + return _allData.size(); // ColumnDisplayDefinition[] colDefs = createColumnDefinitions(md, // columnIndices, computeWidths); @@ -282,9 +285,9 @@ public synchronized boolean next(IMessageHandler msgHandler) throws DataSetException { // TODO: This should be handled with an Iterator - if (++_iCurrent < _alData.size()) + if (++_iCurrent < _allData.size()) { - _currentRow = _alData.get(_iCurrent); + _currentRow = _allData.get(_iCurrent); return true; } return false; @@ -327,9 +330,9 @@ private ColumnDisplayDefinition[] createColumnDefinitions( if (computeWidths) { colWidths = new int[_columnCount]; - for (int i = 0; i < _alData.size(); i++) + for (int i = 0; i < _allData.size(); i++) { - Object[] row = _alData.get(i); + Object[] row = _allData.get(i); for (int col = 0; i < _columnCount; i++) { if (row[col] != null) @@ -569,7 +572,7 @@ private void reset() _currentRow = null; _columnCount = 0; _dataSetDefinition = null; - _alData = null; + _allData = null; } public void resetCursor() @@ -587,9 +590,9 @@ public void resetCursor() */ public Object removeRow(int index) { - if (_alData.size() > index) + if (_allData.size() > index) { - return _alData.remove(index); + return _allData.remove(index); } else { @@ -617,7 +620,7 @@ public String toString() } - for (Object[] row : _alData) + for (Object[] row : _allData) { for (Object rowItem : row) { @@ -639,7 +642,7 @@ public String toString() public List getAllDataForReadOnly() { - return _alData; + return _allData; } public void readMoreResults() @@ -655,7 +658,7 @@ public void readMoreResults() } else { - _alData.add(row); + _allData.add(row); } } @@ -670,7 +673,7 @@ public void readMoreResults() public int currentRowCount() { - return _alData.size(); + return _allData.size(); } public boolean isAllResultsRead() @@ -696,6 +699,6 @@ public void closeStatementAndResultSet() public void replaceDataOnUserEdits(ArrayList updatedRows) { resetCursor(); - _alData = updatedRows; + _allData = updatedRows; } } From 803e18ad3a082f228d4381bb3ede5170c1e11011 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 14 Feb 2026 19:25:12 +0100 Subject: [PATCH 23/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/87 The right mouse menu of UI-tables now offers to toggle columns between a monospaced font and the default font. See the right mouse menu entry named "Toggle selected columns monospaced". --- sql12/core/doc/changes.txt | 4 ++ .../fw/datasetviewer/DataSetViewerTable.java | 34 +++++---- .../fw/datasetviewer/FontService.java | 69 +++++++++++++++++++ .../cellcomponent/CellRenderer.java | 19 ++++- .../MarkDuplicatesStateHandler.java | 10 +-- .../fw/gui/ColumnsMonospacedCommand.java | 21 ++++++ .../fw/gui/I18NStrings.properties | 1 + .../squirrel_sql/fw/gui/TablePopupMenu.java | 40 +++++++---- .../fw/gui/table/ButtonTableHeader.java | 44 +++++++----- .../ButtonTableHeaderColumnDragListener.java | 7 ++ ...uttonTableHeaderDraggedColumnListener.java | 7 -- 11 files changed, 199 insertions(+), 57 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/FontService.java create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/ColumnsMonospacedCommand.java create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderColumnDragListener.java delete mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderDraggedColumnListener.java diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 26268de7d..58067403c 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -6,6 +6,10 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/87 + The right mouse menu of UI-tables now offers to toggle columns between a monospaced font and the default font. + See the right mouse menu entry named "Toggle selected columns monospaced". + The UI-table's "Copy separated by ..." right mouse menu function now allows to display the copy result in a cell data dialog. diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/DataSetViewerTable.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/DataSetViewerTable.java index ed46978b3..20a28aa7b 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/DataSetViewerTable.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/DataSetViewerTable.java @@ -1,5 +1,17 @@ package net.sourceforge.squirrel_sql.fw.datasetviewer; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.DefaultCellEditor; +import javax.swing.JOptionPane; +import javax.swing.JTable; +import javax.swing.table.DefaultTableColumnModel; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableColumnModel; import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.CellComponentFactory; import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.CellRenderer; @@ -15,19 +27,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.DefaultCellEditor; -import javax.swing.JOptionPane; -import javax.swing.JTable; -import javax.swing.table.DefaultTableColumnModel; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableColumnModel; -import java.awt.Graphics; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - /* * The JTable used for displaying all DB ResultSet info. */ @@ -51,6 +50,7 @@ public final class DataSetViewerTable extends JTable private ColoringService _coloringService; + private FontService _fontService; DataSetViewerTable(DataSetViewerTablePanel dataSetViewerTablePanel, IDataSetViewAccess dataSetViewAccess, IDataSetUpdateableModel dataSetUpdateableModel, int listSelectionMode, ISession session) @@ -80,6 +80,7 @@ public final class DataSetViewerTable extends JTable // Do in the end of constructor as we pass this as parameter. _coloringService = new ColoringService(this); + _fontService = new FontService(this); } @@ -283,6 +284,8 @@ else if (colWidth < IDataSetViewer.MIN_COLUMN_WIDTH * _multiplier) CellRenderer tableCellRenderer = CellComponentFactory.getTableCellRenderer(colDefs[i]); tableCellRenderer.setColoringService(_coloringService); + tableCellRenderer.setFontService(_fontService); + ExtTableColumn col = new ExtTableColumn(i, colWidth, tableCellRenderer, null); @@ -411,6 +414,11 @@ public ColoringService getColoringService() return _coloringService; } + public FontService getFontService() + { + return _fontService; + } + public void scrollToVisible(int viewRow, int viewCol) { Rectangle cellRect = getCellRect(viewRow, viewCol, true); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/FontService.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/FontService.java new file mode 100644 index 000000000..299eb2e55 --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/FontService.java @@ -0,0 +1,69 @@ +package net.sourceforge.squirrel_sql.fw.datasetviewer; + +import java.awt.Component; +import java.awt.Font; +import java.util.HashSet; +import java.util.Set; + +public class FontService +{ + public static final Font MONO_SPACED_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 12); + + private final DataSetViewerTable _dataSetViewerTable; + private Font _originalCellFont = null; + private Set _monospacedColumns = new HashSet<>(); + + public FontService(DataSetViewerTable dataSetViewerTable) + { + _dataSetViewerTable = dataSetViewerTable; + _dataSetViewerTable.getButtonTableHeader().addColumnDragListener(() -> onColumnDragged()); + } + + private void onColumnDragged() + { + _monospacedColumns.clear(); + _dataSetViewerTable.repaint(); + } + + public void initCellFont(Component tableCellRendererComponent, int columnIx) + { + if (RowNumberTableColumn.ROW_NUMBER_MODEL_INDEX == _dataSetViewerTable.getColumnModel().getColumn(columnIx).getModelIndex()) + { + return; + } + + if(null == _originalCellFont) + { + _originalCellFont = tableCellRendererComponent.getFont(); + } + + if(_monospacedColumns.contains(columnIx)) + { + tableCellRendererComponent.setFont(MONO_SPACED_FONT); + } + else + { + tableCellRendererComponent.setFont(_originalCellFont); + } + } + + public void toggleMonoSpaced(int[] selectedColumnIndexes) + { + //List buf = List.of(Arrays.stream(selectedColumnIndexes).boxed().toArray(Integer[]::new)); + //_monospacedColumns.removeIf(ix -> false == buf.contains(ix)); + + for(int selectedColumn : selectedColumnIndexes) + { + if(_monospacedColumns.contains(selectedColumn)) + { + _monospacedColumns.remove(selectedColumn); + } + else + { + _monospacedColumns.add(selectedColumn); + } + } + + _dataSetViewerTable.repaint(); + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/CellRenderer.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/CellRenderer.java index e4775f991..90b12788e 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/CellRenderer.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/cellcomponent/CellRenderer.java @@ -1,11 +1,11 @@ package net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent; -import net.sourceforge.squirrel_sql.fw.datasetviewer.coloring.ColoringService; - +import java.awt.Component; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.DefaultTableCellRenderer; -import java.awt.Component; +import net.sourceforge.squirrel_sql.fw.datasetviewer.FontService; +import net.sourceforge.squirrel_sql.fw.datasetviewer.coloring.ColoringService; /** * The base component of a DefaultTableCellRenderer is a JLabel. @@ -16,6 +16,7 @@ public final class CellRenderer extends DefaultTableCellRenderer implements Squi { private final IDataTypeComponent _dataTypeObject; private ColoringService _coloringService; + private FontService _fontService; CellRenderer(IDataTypeComponent dataTypeObject) { @@ -50,6 +51,13 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole _coloringService.colorCell(this, _dataTypeObject, table, value, isSelected, hasFocus, row, column); } + if (null != _fontService) + { + + + _fontService.initCellFont(this, column); + } + BlobClobLoadCheck.check(_dataTypeObject, table, value, isSelected, hasFocus, row, column); return label; @@ -86,4 +94,9 @@ public void setColoringService(ColoringService coloringService) { _coloringService = coloringService; } + + public void setFontService(FontService fontService) + { + _fontService = fontService; + } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java index 6b319fc97..d28e70be3 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/coloring/markduplicates/MarkDuplicatesStateHandler.java @@ -10,7 +10,7 @@ import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTablePanel; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetViewer; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; -import net.sourceforge.squirrel_sql.fw.gui.table.ButtonTableHeaderDraggedColumnListener; +import net.sourceforge.squirrel_sql.fw.gui.table.ButtonTableHeaderColumnDragListener; import net.sourceforge.squirrel_sql.fw.gui.table.SortableTableModel; import net.sourceforge.squirrel_sql.fw.gui.table.SortingListener; @@ -18,7 +18,7 @@ public class MarkDuplicatesStateHandler { private final ActionListener _noResultTabFallBackActionListener; private final SortingListener _tableSortingListener; - private final ButtonTableHeaderDraggedColumnListener _buttonTableHeaderDraggedColumnListener; + private final ButtonTableHeaderColumnDragListener _buttonTableHeaderColumnDragListener; private Action _actionProxy; private IDataSetViewer _sqlResultDataSetViewer; @@ -27,11 +27,11 @@ public class MarkDuplicatesStateHandler public MarkDuplicatesStateHandler(ActionListener noResultTabFallBackActionListener, SortingListener tableSortingListener, - ButtonTableHeaderDraggedColumnListener buttonTableHeaderDraggedColumnListener) + ButtonTableHeaderColumnDragListener buttonTableHeaderColumnDragListener) { _noResultTabFallBackActionListener = noResultTabFallBackActionListener; _tableSortingListener = tableSortingListener; - _buttonTableHeaderDraggedColumnListener = buttonTableHeaderDraggedColumnListener; + _buttonTableHeaderColumnDragListener = buttonTableHeaderColumnDragListener; _actionProxy = new AbstractAction() { @@ -81,7 +81,7 @@ public void init(IDataSetViewer dataSetViewer, IResultTab resultTab) if(_sqlResultDataSetViewer instanceof DataSetViewerTablePanel) { - ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getButtonTableHeader().setDraggedColumnListener(_buttonTableHeaderDraggedColumnListener); + ((DataSetViewerTablePanel) _sqlResultDataSetViewer).getTable().getButtonTableHeader().addColumnDragListener(_buttonTableHeaderColumnDragListener); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/ColumnsMonospacedCommand.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/ColumnsMonospacedCommand.java new file mode 100644 index 000000000..7fd278cd5 --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/ColumnsMonospacedCommand.java @@ -0,0 +1,21 @@ +package net.sourceforge.squirrel_sql.fw.gui; + +import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTable; + +public class ColumnsMonospacedCommand +{ + private final DataSetViewerTable _table; + + public ColumnsMonospacedCommand(DataSetViewerTable table) + { + _table = table; + } + + public void execute() + { + int[] selectedColumns = _table.getSelectedColumns(); + + _table.getFontService().toggleMonoSpaced(selectedColumns); + + } +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/I18NStrings.properties index afebf0013..5e7bbaa6f 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/I18NStrings.properties @@ -78,6 +78,7 @@ TablePopupMenu.ColorSelectedRows=Color selected rows TablePopupMenu.ColorSelectedCells=Color selected cells TablePopupMenu.GotoColor=Go to color TablePopupMenu.CopyColoredRowsToNewWindow=Copy colored rows to new window +TablePopupMenu.ToggleColumnsMonospaced=Toggle selected columns monospaced ChooserPreviewer.errorReadingFile=Error reading file {0}: {1} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java index 8ae8233a8..4c3c8be6d 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java @@ -18,6 +18,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.print.PrinterJob; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.SQLExecutionInfo; @@ -60,18 +71,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; import org.apache.commons.lang3.time.StopWatch; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JMenuItem; -import javax.swing.KeyStroke; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.print.PrinterJob; - public class TablePopupMenu extends BasePopupMenu { @@ -106,6 +105,8 @@ public class TablePopupMenu extends BasePopupMenu private GotoColorMenuController _gotoColorMenuController = new GotoColorMenuController(); private CopyColoredRowsToNewWindowAction _copyColoredRowsToNewWindow = new CopyColoredRowsToNewWindowAction(); + private ToggleColumnsMonospacedAction _toggleColumnsMonospaced = new ToggleColumnsMonospacedAction(); + private ExportAction _export; private AdjustAllColWidthsAction _adjustAllColWidthsAction = new AdjustAllColWidthsAction(); private AlwaysAdjustAllColWidthsAction _alwaysAdjustAllColWidthsAction = new AlwaysAdjustAllColWidthsAction(); @@ -190,6 +191,8 @@ public TablePopupMenu(boolean allowEditing, add(_copyColoredRowsToNewWindow); addSeparator(); + add(_toggleColumnsMonospaced); + addSeparator(); _export = new ExportAction(DataSetViewerTablePanel.getDataModelImplementationDetails().getSQLExecutionInfo()); addAction(_export); @@ -611,6 +614,19 @@ public void actionPerformed(ActionEvent evt) } } + private class ToggleColumnsMonospacedAction extends BaseAction + { + ToggleColumnsMonospacedAction() + { + super(s_stringMgr.getString("TablePopupMenu.ToggleColumnsMonospaced")); + } + + public void actionPerformed(ActionEvent evt) + { + new ColumnsMonospacedCommand(_dataSetViewerTablePanel.getTable()).execute(); + } + } + private class AdjustAllColWidthsAction extends BaseAction { diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeader.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeader.java index 509d2c1a2..d988cefca 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeader.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeader.java @@ -18,6 +18,22 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.Component; +import java.awt.Cursor; +import java.awt.FontMetrics; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.event.TableModelListener; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.fw.datasetviewer.RowNumberTableColumn; import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.SquirrelTableCellRenderer; @@ -26,18 +42,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import javax.swing.*; -import javax.swing.event.TableModelListener; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionListener; -import java.awt.geom.Rectangle2D; - public class ButtonTableHeader extends JTableHeader { private static final StringManager s_stringMgr = StringManagerFactory.getStringManager(ButtonTableHeader.class); @@ -54,7 +58,7 @@ public class ButtonTableHeader extends JTableHeader private TableAccessForHeader _tableAccess; - private ButtonTableHeaderDraggedColumnListener _buttonTableHeaderDraggedColumnListener; + private java.util.List _buttonTableHeaderDragListeners = new ArrayList<>(); /** * Constructor for ButtonTableHeader. @@ -284,9 +288,15 @@ private void adjustColWidth(int colIx, boolean includeColHeaders) } - public void setDraggedColumnListener(ButtonTableHeaderDraggedColumnListener buttonTableHeaderDraggedColumnListener) + public void addColumnDragListener(ButtonTableHeaderColumnDragListener buttonTableHeaderColumnDragListener) + { + _buttonTableHeaderDragListeners.remove(buttonTableHeaderColumnDragListener); + _buttonTableHeaderDragListeners.add(buttonTableHeaderColumnDragListener); + } + + public void removeColumnDragListener(ButtonTableHeaderColumnDragListener buttonTableHeaderColumnDragListener) { - _buttonTableHeaderDraggedColumnListener = buttonTableHeaderDraggedColumnListener; + _buttonTableHeaderDragListeners.remove(buttonTableHeaderColumnDragListener); } class HeaderListener extends MouseAdapter implements MouseMotionListener @@ -376,9 +386,9 @@ public void mouseReleased(MouseEvent e) } else { - if(null != _buttonTableHeaderDraggedColumnListener) + for(ButtonTableHeaderColumnDragListener l : _buttonTableHeaderDragListeners.toArray(new ButtonTableHeaderColumnDragListener[0])) { - _buttonTableHeaderDraggedColumnListener.columnDragged(); + l.columnDragged(); } } _mouseState.setDragged(false); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderColumnDragListener.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderColumnDragListener.java new file mode 100644 index 000000000..b1a9c4f02 --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderColumnDragListener.java @@ -0,0 +1,7 @@ +package net.sourceforge.squirrel_sql.fw.gui.table; + +@FunctionalInterface +public interface ButtonTableHeaderColumnDragListener +{ + void columnDragged(); +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderDraggedColumnListener.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderDraggedColumnListener.java deleted file mode 100644 index 88183060c..000000000 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/table/ButtonTableHeaderDraggedColumnListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.sourceforge.squirrel_sql.fw.gui.table; - -@FunctionalInterface -public interface ButtonTableHeaderDraggedColumnListener -{ - public void columnDragged(); -} From 2893f405e30c1a2a4c17f5e30db4971b30118fb2 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 14 Feb 2026 19:58:38 +0100 Subject: [PATCH 24/33] Refactoring --- .../ProcedureAndFunctionMetaData.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/ProcedureAndFunctionMetaData.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/ProcedureAndFunctionMetaData.java index c9b1ff76f..7a94d37db 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/ProcedureAndFunctionMetaData.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/ProcedureAndFunctionMetaData.java @@ -1,18 +1,21 @@ package net.sourceforge.squirrel_sql.fw.sql.databasemetadata; -import net.sourceforge.squirrel_sql.fw.datasetviewer.BlockMode; -import net.sourceforge.squirrel_sql.fw.dialects.DialectFactory; -import net.sourceforge.squirrel_sql.fw.dialects.DialectType; -import net.sourceforge.squirrel_sql.fw.sql.*; -import net.sourceforge.squirrel_sql.fw.util.log.ILogger; -import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; - import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import net.sourceforge.squirrel_sql.fw.datasetviewer.BlockMode; +import net.sourceforge.squirrel_sql.fw.dialects.DialectFactory; +import net.sourceforge.squirrel_sql.fw.dialects.DialectType; +import net.sourceforge.squirrel_sql.fw.sql.IProcedureInfo; +import net.sourceforge.squirrel_sql.fw.sql.ProcedureInfo; +import net.sourceforge.squirrel_sql.fw.sql.ProgressCallBack; +import net.sourceforge.squirrel_sql.fw.sql.ResultSetReader; +import net.sourceforge.squirrel_sql.fw.sql.SQLUtilities; +import net.sourceforge.squirrel_sql.fw.util.log.ILogger; +import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; public class ProcedureAndFunctionMetaData { @@ -30,7 +33,7 @@ static List getProcedureInfos(String catalog, String schemaPatte int count = 0; try { - final int[] cols = new int[] + final int[] columnsToReadFomMetaDataResult = new int[] { 1, // PROCEDURE_CAT 2, // PROCEDURE_SCHEM @@ -40,7 +43,7 @@ static List getProcedureInfos(String catalog, String schemaPatte }; DialectType dialectType = DialectFactory.getDialectType(md); - final ResultSetReader rdr = new ResultSetReader(rs, cols, dialectType); + final ResultSetReader rdr = new ResultSetReader(rs, columnsToReadFomMetaDataResult, dialectType); Object[] row; while ((row = rdr.readRow(BlockMode.INDIFFERENT)) != null) { From cd17fbecc5acbdefb7c077206fe38cd1bc0686eb Mon Sep 17 00:00:00 2001 From: GWA Date: Mon, 16 Feb 2026 12:37:04 +0100 Subject: [PATCH 25/33] Refactoring of method names in ResultSetDataSet --- .../client/cli/CliSQLExecuterHandler.java | 18 +++--- .../mainpanel/SQLExecutionHandler.java | 12 ++-- .../tabs/BasePreparedStatementTab.java | 16 +++--- .../objecttree/tabs/table/ContentsTab.java | 3 +- .../objecttree/tabs/table/RowCountTab.java | 2 +- .../fw/datasetviewer/ResultSetDataSet.java | 56 ++++++------------- .../databasemetadata/SQLDatabaseMetaData.java | 19 ++++--- .../plugins/mssql/gui/MonitorPanel.java | 5 +- .../plugins/mysql/tab/BaseSQLTab.java | 16 +++--- .../plugins/vertica/tab/ContentPlusTab.java | 12 ++-- .../plugins/vertica/tab/ProjectionTab.java | 10 ++-- 11 files changed, 74 insertions(+), 95 deletions(-) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/cli/CliSQLExecuterHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/cli/CliSQLExecuterHandler.java index 5e8d1c69e..359bdbf12 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/cli/CliSQLExecuterHandler.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/cli/CliSQLExecuterHandler.java @@ -1,5 +1,13 @@ package net.sourceforge.squirrel_sql.client.cli; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.SQLException; +import java.util.ArrayList; + import net.sourceforge.squirrel_sql.client.session.SQLExecutionInfo; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetUpdateableTableModel; @@ -11,14 +19,6 @@ import net.sourceforge.squirrel_sql.fw.sql.querytokenizer.QueryHolder; import net.sourceforge.squirrel_sql.fw.util.Utilities; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.sql.SQLException; -import java.util.ArrayList; - public class CliSQLExecuterHandler extends CliSQLExecuterHandlerAdapter { private CliSession _cliSession; @@ -124,7 +124,7 @@ public void sqlResultSetAvailable(ResultSetWrapper rst, SQLExecutionInfo info, I DialectFactory.getDialectType(_cliSession.getMetaData()); - rsds.setSqlExecutionTabResultSet(rst, null, dialectType); + rsds.readDataFromJdbcResultSetForSqlExecution(rst, null, dialectType); ResultAsText resultAsText = new ResultAsText(rsds.getDataSetDefinition().getColumnDefinitions(), true, line -> onAddLine(line)); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLExecutionHandler.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLExecutionHandler.java index 30acdc86c..fb4ac0c1c 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLExecutionHandler.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLExecutionHandler.java @@ -1,5 +1,10 @@ package net.sourceforge.squirrel_sql.client.session.mainpanel; +import java.sql.SQLWarning; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; + import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences; import net.sourceforge.squirrel_sql.client.session.ISQLExecuterHandler; import net.sourceforge.squirrel_sql.client.session.ISession; @@ -25,11 +30,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import java.sql.SQLWarning; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Arrays; - /** * This class is the handler for the execution of sql against the SQLExecuterPanel */ @@ -396,7 +396,7 @@ public void sqlResultSetAvailable(ResultSetWrapper rs, SQLExecutionInfo info, ID // rsds.setContentsTabResultSet() reads the result set. So results processing on the DB is over // and this time is measured. None is interested in the time that it takes us to render Swing tables ... - info.resultsProcessingComplete(_rsds.setSqlExecutionTabResultSet(rs, null, dialectType)); + info.resultsProcessingComplete(_rsds.readDataFromJdbcResultSetForSqlExecution(rs, null, dialectType)); _executionHandlerListener.addResultsTab(info, _rsds, rsmdds, model, _resultTabToReplace); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/BasePreparedStatementTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/BasePreparedStatementTab.java index 2109744be..468c569c3 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/BasePreparedStatementTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/BasePreparedStatementTab.java @@ -19,6 +19,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.Component; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + import net.sourceforge.squirrel_sql.client.session.DataModelImplementationDetails; import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.properties.SessionProperties; @@ -32,13 +39,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import java.awt.Component; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; - public abstract class BasePreparedStatementTab extends BaseObjectTab { /** Title to display for tab. */ @@ -168,7 +168,7 @@ protected void refreshComponent() throws DataSetException protected IDataSet createDataSetFromResultSet(ResultSet rs) throws DataSetException { final ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, getDialectType()); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, getDialectType()); if (!_firstRowOnly) { return rsds; diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/ContentsTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/ContentsTab.java index d690a4660..429a27f5c 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/ContentsTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/ContentsTab.java @@ -24,6 +24,7 @@ import java.sql.SQLException; import java.sql.Statement; import javax.swing.JTable; + import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.gui.session.SessionPanel; import net.sourceforge.squirrel_sql.client.session.DataSetUpdateableTableModelImpl; @@ -287,7 +288,7 @@ protected IDataSet createDataSet() throws DataSetException // distinguish this table from other tables in the DB. // We also include the URL used to connect to the DB so that // the same table/DB on different machines is treated differently. - rsds.setContentsTabResultSet(rs, _dataSetUpdateableTableModel.getFullTableName(), DialectFactory.getDialectType(md)); + rsds.readDataFromJdbcResultSetForObjectTreeContentTabs(rs, _dataSetUpdateableTableModel.getFullTableName(), DialectFactory.getDialectType(md)); SQLUtilities.closeResultSet(rs); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/RowCountTab.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/RowCountTab.java index de1330a5f..a9fc8e38c 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/RowCountTab.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/objecttree/tabs/table/RowCountTab.java @@ -77,7 +77,7 @@ protected IDataSet createDataSet() throws DataSetException try { final ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, getDialectType()); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, getDialectType()); return rsds; } finally diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java index eed94f148..7d462a61d 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/ResultSetDataSet.java @@ -28,6 +28,7 @@ import java.sql.Types; import java.util.ArrayList; import java.util.List; + import net.sourceforge.squirrel_sql.fw.dialects.DialectType; import net.sourceforge.squirrel_sql.fw.sql.JDBCTypeMapper; import net.sourceforge.squirrel_sql.fw.sql.ResultSetReader; @@ -90,19 +91,6 @@ public ResultSetDataSet() this.tableColumnInfos = new TableColumnInfo[]{}; } - /** - * Form used by Tabs other than ContentsTab - * - * @param rs the ResultSet to set. - * @param dialectType the type of dialect in use. - * @throws DataSetException - */ - public int setResultSet(ResultSet rs, DialectType dialectType) throws DataSetException - { - return _setResultSet(new ResultSetWrapper(rs), null, null, false, false, dialectType); - } - - /** * Content Tab may wish to limit data read for big columns. * @@ -113,47 +101,39 @@ public void setLimitDataRead(boolean limitDataRead) this._limitDataRead = limitDataRead; } - /** - * Form used by ContentsTab, and for SQL results - * - * @param rs the ResultSet to set. - * @param fullTableName the fully-qualified table name - * @param dialectType the type of dialect in use. - * @throws DataSetException - */ - public int setContentsTabResultSet(ResultSet rs, String fullTableName, DialectType dialectType) throws DataSetException + public int readDataFromJdbcResultSetForObjectTreeContentTabs(ResultSet rs, String fullTableName, DialectType dialectType) throws DataSetException { - return _setResultSet(new ResultSetWrapper(rs), fullTableName, null, false, true, dialectType); + return _readDataFromJdbcResultSet(new ResultSetWrapper(rs), fullTableName, null, false, true, dialectType); } - public int setSqlExecutionTabResultSet(ResultSetWrapper rs, String fullTableName, DialectType dialectType) throws DataSetException + public int readDataFromJdbcResultSetForSqlExecution(ResultSetWrapper rs, String fullTableName, DialectType dialectType) throws DataSetException { - return _setResultSet(rs, fullTableName, null, false, true, dialectType); + return _readDataFromJdbcResultSet(rs, fullTableName, null, false, true, dialectType); } + public int readDataFromJdbcResultSetForDatabaseMetaData(ResultSet rs, int[] columnIndices, boolean computeWidths, DialectType dialectType) throws DataSetException + { + return _readDataFromJdbcResultSet(new ResultSetWrapper(rs), null, columnIndices, computeWidths, false, dialectType); + } - /** - * External method to read the contents of a ResultSet that is used by all - * Tab classes except ContentsTab. This tunrs all the data into strings for - * simplicity of operation. - */ - public int setResultSet(ResultSet rs, int[] columnIndices, boolean computeWidths, DialectType dialectType) throws DataSetException + public int readDataFromJdbcResultSetForGeneralPurpose(ResultSet rs, DialectType dialectType) throws DataSetException { - return _setResultSet(new ResultSetWrapper(rs), null, columnIndices, computeWidths, false, dialectType); + return _readDataFromJdbcResultSet(new ResultSetWrapper(rs), null, null, false, false, dialectType); } + /** * Internal method to read the contents of a ResultSet that is used by all * Tab classes * * @return The number of rows read from the ResultSet */ - private int _setResultSet(ResultSetWrapper rs, - String fullTableName, - int[] columnIndices, - boolean computeWidths, - boolean useColumnDefs, - DialectType dialectType) throws DataSetException + private int _readDataFromJdbcResultSet(ResultSetWrapper rs, + String fullTableName, + int[] columnIndices, + boolean computeWidths, + boolean useColumnDefs, + DialectType dialectType) throws DataSetException { reset(); _dialectType = dialectType; diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/SQLDatabaseMetaData.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/SQLDatabaseMetaData.java index f07ede36e..bb14a9670 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/SQLDatabaseMetaData.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/sql/databasemetadata/SQLDatabaseMetaData.java @@ -33,6 +33,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; + import net.sourceforge.squirrel_sql.client.session.schemainfo.synonym.SynonymHandler; import net.sourceforge.squirrel_sql.fw.datasetviewer.BlockMode; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException; @@ -1232,7 +1233,7 @@ public synchronized IDataSet getColumnPrivilegesDataSet(ITableInfo ti, int[] col rs = md.getColumnPrivileges(ti.getCatalogName(), ti.getSchemaName(), ti.getSimpleName(), columns); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForDatabaseMetaData(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1267,7 +1268,7 @@ public synchronized IDataSet getExportedKeysDataSet(ITableInfo ti) throws DataSe privateGetJDBCMetaData().getExportedKeys(ti.getCatalogName(), ti.getSchemaName(), ti.getSimpleName()); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, null, true, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForDatabaseMetaData(rs, null, true, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1326,7 +1327,7 @@ public synchronized IDataSet getImportedKeysDataSet(ITableInfo ti) throws DataSe { rs = privateGetJDBCMetaData().getImportedKeys(ti.getCatalogName(), ti.getSchemaName(), ti.getSimpleName()); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, null, true, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForDatabaseMetaData(rs, null, true, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1438,7 +1439,7 @@ public synchronized ResultSetDataSet getIndexInfo(ITableInfo ti, int[] columnInd { rs = _getIndexInfo(ti); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForDatabaseMetaData(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1518,7 +1519,7 @@ public synchronized IDataSet getPrimaryKey(ITableInfo ti, int[] columnIndices, b privateGetJDBCMetaData().getPrimaryKeys(ti.getCatalogName(), ti.getSchemaName(), ti.getSimpleName()); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForDatabaseMetaData(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1584,7 +1585,7 @@ public synchronized IDataSet getProcedureColumnsDataSet(IProcedureInfo ti) throw DatabaseMetaData md = privateGetJDBCMetaData(); rs = md.getProcedureColumns(ti.getCatalogName(), ti.getSchemaName(), ti.getSimpleName(), "%"); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1623,7 +1624,7 @@ public synchronized IDataSet getTablePrivilegesDataSet(ITableInfo ti, int[] colu DatabaseMetaData md = privateGetJDBCMetaData(); rs = md.getTablePrivileges(ti.getCatalogName(), ti.getSchemaName(), ti.getSimpleName()); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForDatabaseMetaData(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1660,7 +1661,7 @@ public synchronized IDataSet getVersionColumnsDataSet(ITableInfo ti) throws Data DatabaseMetaData md = privateGetJDBCMetaData(); rs = md.getVersionColumns(ti.getCatalogName(), ti.getSchemaName(), ti.getSimpleName()); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectFactory.getDialectType(this)); return rsds; } catch (SQLException e) @@ -1704,7 +1705,7 @@ public synchronized IDataSet getColumns(ITableInfo ti, int[] columnIndices, bool { rs = getColumns(ti); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); + rsds.readDataFromJdbcResultSetForDatabaseMetaData(rs, columnIndices, computeWidths, DialectFactory.getDialectType(this)); // Workaround for DB2/AIX64 driver: COLUMN_SIZE is not CHAR_OCTET_LENGTH for double-bytes datatypes GRAPHIC/VARGRAPHIC result = rsds; diff --git a/sql12/plugins/mssql/src/net/sourceforge/squirrel_sql/plugins/mssql/gui/MonitorPanel.java b/sql12/plugins/mssql/src/net/sourceforge/squirrel_sql/plugins/mssql/gui/MonitorPanel.java index 51006a29d..962c15161 100644 --- a/sql12/plugins/mssql/src/net/sourceforge/squirrel_sql/plugins/mssql/gui/MonitorPanel.java +++ b/sql12/plugins/mssql/src/net/sourceforge/squirrel_sql/plugins/mssql/gui/MonitorPanel.java @@ -27,7 +27,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Date; - import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JPanel; @@ -168,11 +167,11 @@ private void refreshData() { _refreshDate = new Date(); rs = _whoStmt.executeQuery(); - _whoDataSet.setResultSet(rs, DialectType.MSSQL); + _whoDataSet.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectType.MSSQL); _whoViewer.show(_whoDataSet); rs = _perfStmt.executeQuery(); - _perfDataSet.setResultSet(rs, DialectType.MSSQL); + _perfDataSet.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectType.MSSQL); _perfViewer.show(_perfDataSet); } catch (java.sql.SQLException ex) diff --git a/sql12/plugins/mysql/src/net/sourceforge/squirrel_sql/plugins/mysql/tab/BaseSQLTab.java b/sql12/plugins/mysql/src/net/sourceforge/squirrel_sql/plugins/mysql/tab/BaseSQLTab.java index 946662eda..e29077eef 100644 --- a/sql12/plugins/mysql/src/net/sourceforge/squirrel_sql/plugins/mysql/tab/BaseSQLTab.java +++ b/sql12/plugins/mysql/src/net/sourceforge/squirrel_sql/plugins/mysql/tab/BaseSQLTab.java @@ -18,6 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.Component; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; + import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.tabs.BaseObjectTab; import net.sourceforge.squirrel_sql.client.session.properties.SessionProperties; @@ -31,13 +38,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import java.awt.Component; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.HashMap; -import java.util.Map; - abstract class BaseSQLTab extends BaseObjectTab { /** Title to display for tab. */ @@ -159,7 +159,7 @@ protected IDataSet createDataSetFromResultSet(ResultSet rs) throws DataSetException { final ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, DialectType.MYSQL); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectType.MYSQL); if (!_firstRowOnly) { return rsds; diff --git a/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ContentPlusTab.java b/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ContentPlusTab.java index 8ed426d41..c3a380172 100644 --- a/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ContentPlusTab.java +++ b/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ContentPlusTab.java @@ -29,7 +29,6 @@ import net.sourceforge.squirrel_sql.client.session.sqlfilter.OrderByClausePanel; import net.sourceforge.squirrel_sql.client.session.sqlfilter.SQLFilterClauses; import net.sourceforge.squirrel_sql.client.session.sqlfilter.WhereClausePanel; -import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSet; import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet; @@ -38,12 +37,11 @@ import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData; import net.sourceforge.squirrel_sql.fw.sql.ITableInfo; import net.sourceforge.squirrel_sql.fw.sql.SQLUtilities; -import net.sourceforge.squirrel_sql.fw.sql.TableColumnInfo; import net.sourceforge.squirrel_sql.fw.sql.dbobj.BestRowIdentifier; -import net.sourceforge.squirrel_sql.fw.util.log.ILogger; -import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; +import net.sourceforge.squirrel_sql.fw.util.log.ILogger; +import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; public class ContentPlusTab extends ContentsTab { @@ -237,9 +235,9 @@ protected IDataSet createDataSet() throws DataSetException // distinguish this table from other tables in the DB. // We also include the URL used to connect to the DB so that // the same table/DB on different machines is treated differently. - rsds.setContentsTabResultSet(rs, - _dataSetUpdateableTableModel.getFullTableName(), - DialectFactory.getDialectType(md)); + rsds.readDataFromJdbcResultSetForObjectTreeContentTabs(rs, + _dataSetUpdateableTableModel.getFullTableName(), + DialectFactory.getDialectType(md)); if (rs != null) { try { rs.close(); } catch (SQLException e) {} } diff --git a/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ProjectionTab.java b/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ProjectionTab.java index c929f60ed..e1fc3888c 100644 --- a/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ProjectionTab.java +++ b/sql12/plugins/vertica/src/net/sourceforge/squirrel_sql/plugins/vertica/tab/ProjectionTab.java @@ -16,6 +16,10 @@ package net.sourceforge.squirrel_sql.plugins.vertica.tab; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.tabs.table.BaseTableTab; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSet; @@ -28,10 +32,6 @@ import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - /** * This tab shows the primary key info for the currently selected table. */ @@ -99,7 +99,7 @@ protected IDataSet createDataSet() throws DataSetException pstmt.setString(2, ti.getSimpleName()); rs = pstmt.executeQuery(); ResultSetDataSet rsds = new ResultSetDataSet(md.getColumnInfo(ti)); - rsds.setResultSet(rs, DialectFactory.getDialectType(md)); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectFactory.getDialectType(md)); return rsds; } From d976b5b720fd394a22720d61a7cfbc0b2e0ad260 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Mon, 16 Feb 2026 21:06:30 +0100 Subject: [PATCH 26/33] Fixed compile bug --- .../squirrel_sql/plugins/postgres/tab/ActiveConnections.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/ActiveConnections.java b/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/ActiveConnections.java index a38b9ef6b..8c6fe2e77 100644 --- a/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/ActiveConnections.java +++ b/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/ActiveConnections.java @@ -3,7 +3,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; - import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.tabs.BaseDataSetTab; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException; @@ -54,7 +53,7 @@ protected IDataSet createDataSet() throws DataSetException { Statement stmt = con.createStatement(); ResultSet rs = isPostgres92(con) ? stmt.executeQuery(QUERY_92) : stmt.executeQuery(QUERY); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, DialectType.POSTGRES); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectType.POSTGRES); return rsds; } catch (SQLException ex) { From 2bcd825fe6d67e384265cbb1155437e11f87a42b Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Mon, 16 Feb 2026 21:09:42 +0100 Subject: [PATCH 27/33] Fixed compile bug --- .../explain/ExplainExecutorPanel.java | 35 +++++++++---------- .../plugins/postgres/tab/LockTab.java | 3 +- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/explain/ExplainExecutorPanel.java b/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/explain/ExplainExecutorPanel.java index adae275fb..e99730e5d 100644 --- a/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/explain/ExplainExecutorPanel.java +++ b/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/explain/ExplainExecutorPanel.java @@ -19,6 +19,22 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +import java.awt.BorderLayout; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; import net.sourceforge.squirrel_sql.client.gui.builders.UIFactory; import net.sourceforge.squirrel_sql.client.session.ISQLEntryPanel; import net.sourceforge.squirrel_sql.client.session.ISQLExecuterHandler; @@ -44,23 +60,6 @@ import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JTabbedPane; -import javax.swing.SwingUtilities; -import java.awt.BorderLayout; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; - public class ExplainExecutorPanel extends JPanel implements ISQLResultExecutor { static final String EXPLAIN_PREFIX = "EXPLAIN ANALYZE "; @@ -287,7 +286,7 @@ public void sqlResultSetAvailable(ResultSetWrapper rs, final SQLExecutionInfo in { final ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs.getResultSet(), _dialectType); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs.getResultSet(), _dialectType); GUIUtils.processOnSwingEventThread( new Runnable() diff --git a/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/LockTab.java b/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/LockTab.java index d549267da..622e7e301 100644 --- a/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/LockTab.java +++ b/sql12/plugins/postgres/src/net/sourceforge/squirrel_sql/plugins/postgres/tab/LockTab.java @@ -3,7 +3,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; - import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.tabs.BaseDataSetTab; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException; @@ -62,7 +61,7 @@ protected IDataSet createDataSet() throws DataSetException { Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(QUERY); ResultSetDataSet rsds = new ResultSetDataSet(); - rsds.setResultSet(rs, DialectType.POSTGRES); + rsds.readDataFromJdbcResultSetForGeneralPurpose(rs, DialectType.POSTGRES); return rsds; } catch (SQLException ex) From 9a66d17a7fd931d3b3d102a9cbd808972c04faec Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 7 Mar 2026 18:05:44 +0100 Subject: [PATCH 28/33] Web page update --- sql12/web-site/home.html | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/sql12/web-site/home.html b/sql12/web-site/home.html index 66dcfe81e..9099ed438 100755 --- a/sql12/web-site/home.html +++ b/sql12/web-site/home.html @@ -118,7 +118,42 @@

Feature highlights of 5.0.0:

Latest News

-

+

+ The latest snapshot-20260215_1841 a release candidate for the 5.1.0 release.
+ Changes are since the 5.0.0 release are

+ + + + + + + + + + + +
⇒ Table columns can be toggled between a monospaced font and default font
⇒ Table cell contents can be concatenated without separator
⇒ SQL results can be rerun automatically after a configurable number of seconds
⇒ The SQL editor allows to run bookmarks by the syntax @runbookmark <bookmarkNameInSingleQuotes>
⇒ MS Excel file export allows to add or replace sheet-tabs in an MS Excel file
⇒ Option to execute SQL in multiple Sessions
⇒ Single click connect to multiple Aliases
⇒ Enhanced security for encrypting Alias passwords
⇒ "Copy as WIKI Table" - function of tables now supports copying the Jira/Cloud table format
⇒ User Bookmarks can be displayed as tree
+ Please give it a try.

+
+ For all new features and bug fixes see our change log at + SourceForge + or GitHub.

+ snapshot-20260215_1841 releases on SourceForge are:
+ Download installer for Windows/Linux/others
+ Download installer for Mac OS
+ snapshot-20260215_1841 releases on GitHub are:
+ Download installer for Windows/Linux/others
+ Download installer for Mac OS

+

+

+ Note: We don't announce every snapshot release here. If you are interested please check
+ https://github.com/squirrel-sql-client/squirrel-sql-snapshot-releases/releases
+ or
+ https://sourceforge.net/projects/squirrel-sql/files/3-snapshots
+ for the latest snapshots regularly.
+

+
+

SQuirreL 5.0.0 is released (09/18/2025).
The list of feature highlights is rather long and can be found above.
For all new features and bug fixes see our change log at SourceForge From ba243bbfd7c3d9ee8031fbc287929989d0dbcbf1 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Sat, 7 Mar 2026 18:12:19 +0100 Subject: [PATCH 29/33] Web page update --- sql12/web-site/home.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql12/web-site/home.html b/sql12/web-site/home.html index 9099ed438..652759d08 100755 --- a/sql12/web-site/home.html +++ b/sql12/web-site/home.html @@ -119,8 +119,8 @@

Latest News

- The latest snapshot-20260215_1841 a release candidate for the 5.1.0 release.
- Changes are since the 5.0.0 release are

+ The latest snapshot-20260215_1841 is a release candidate for the 5.1.0 release.
+ Changes since the 5.0.0 release are

From 27a32b4d4a55573109d27bbe6d665a5ad849e8dc Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Fri, 27 Mar 2026 10:11:18 +0100 Subject: [PATCH 30/33] 5.1.0 Release --- sql12/build.xml | 4 ++-- sql12/core/doc/changes.txt | 4 ++-- sql12/installer/mac/installer-readme.html | 2 +- sql12/installer/other/installer-readme.html | 2 +- sql12/web-site/faq.html | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sql12/build.xml b/sql12/build.xml index 037360ea3..d02db94b8 100644 --- a/sql12/build.xml +++ b/sql12/build.xml @@ -8,8 +8,8 @@ - - + + diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 58067403c..34baed2d7 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -1,8 +1,8 @@ SQuirreL SQL Client Change Log ============================== -Not yet released, available in our GIT repository, snapshots and future releases. -=============================================================================================== +5.1.0 (03/26/2026) +================== Enhancements: diff --git a/sql12/installer/mac/installer-readme.html b/sql12/installer/mac/installer-readme.html index bfd0ce8a9..0199378b1 100644 --- a/sql12/installer/mac/installer-readme.html +++ b/sql12/installer/mac/installer-readme.html @@ -28,7 +28,7 @@ - + diff --git a/sql12/installer/other/installer-readme.html b/sql12/installer/other/installer-readme.html index fe1830589..afdd99d99 100644 --- a/sql12/installer/other/installer-readme.html +++ b/sql12/installer/other/installer-readme.html @@ -28,7 +28,7 @@ - + diff --git a/sql12/web-site/faq.html b/sql12/web-site/faq.html index cd6d7f89a..477698c34 100755 --- a/sql12/web-site/faq.html +++ b/sql12/web-site/faq.html @@ -409,7 +409,7 @@

Which version of the JVM

- + From fac274f86f26e0332cfcc168f7aead49f9724e3f Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Tue, 31 Mar 2026 20:28:52 +0200 Subject: [PATCH 31/33] Web page update for 5.1.0 Release --- sql12/web-site/header.html | 2 +- sql12/web-site/home.html | 106 ++++++++++++------------------------- 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/sql12/web-site/header.html b/sql12/web-site/header.html index 53ab51c75..98951bba9 100644 --- a/sql12/web-site/header.html +++ b/sql12/web-site/header.html @@ -18,7 +18,7 @@ @@ -269,19 +229,19 @@

Available downloads are:

From cf28f8bc702aaeb91c1d6ced9a101ad5e63b83a3 Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Mon, 6 Apr 2026 21:21:35 +0200 Subject: [PATCH 32/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/88 The keyboard short cuts tab now contains the action's description (tooltip). Bug fix: Oracle Plugin: Fixed typo, DB Ouptut --> DB Output --- sql12/core/doc/changes.txt | 14 ++ .../docktabdesktop/DockTabDesktopPane.java | 48 +++++-- .../shortcut/I18NStrings.properties | 5 +- .../shortcut/ShortcutPrefsCtrl.java | 48 ++++--- .../rsyntax/SquirreLRSyntaxTextAreaUI.java | 45 ++++--- .../mainpanel/SQLResultExecutorPanel.java | 3 +- .../shortcut/ShortCutDescriptionReader.java | 126 ++++++++++++++++++ .../client/shortcut/ShortCutReader.java | 9 +- .../client/shortcut/Shortcut.java | 14 +- .../client/shortcut/ShortcutManager.java | 43 +++--- .../datasetviewer/JavabeanArrayDataSet.java | 15 +-- .../squirrel_sql/fw/gui/TablePopupMenu.java | 5 +- .../fw/gui/stdtextpopup/TextActionHelper.java | 6 +- .../squirrel_sql/fw/resources/Resources.java | 39 +++++- .../plugins/hibernate/HibernatePlugin.java | 9 +- .../plugins/oracle/oracle.properties | 2 +- 16 files changed, 324 insertions(+), 107 deletions(-) create mode 100644 sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutDescriptionReader.java diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 34baed2d7..8c8a037e5 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -1,6 +1,20 @@ SQuirreL SQL Client Change Log ============================== +Not yet released, available in our GIT repository, snapshots and future releases. +=============================================================================================== + +Enhancements: + +https://github.com/squirrel-sql-client/squirrel-sql-code/issues/88 +The keyboard short cuts tab now contains the action's description (tooltip). + + +Bug fixes: + +Oracle Plugin: Fixed typo, DB Ouptut --> DB Output + + 5.1.0 (03/26/2026) ================== diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DockTabDesktopPane.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DockTabDesktopPane.java index e0caec2a9..8c7537d8a 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DockTabDesktopPane.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DockTabDesktopPane.java @@ -1,9 +1,41 @@ package net.sourceforge.squirrel_sql.client.gui.desktopcontainer.docktabdesktop; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.util.ArrayList; +import java.util.HashSet; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JToggleButton; +import javax.swing.KeyStroke; +import javax.swing.WindowConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import net.sourceforge.squirrel_sql.client.ApplicationListener; import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; -import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.*; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DialogWidget; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DockDelegate; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.DockWidget; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.IDesktopContainer; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.IWidget; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.TabDelegate; +import net.sourceforge.squirrel_sql.client.gui.desktopcontainer.TabWidget; import net.sourceforge.squirrel_sql.client.gui.mainframe.SquirrelDesktopManager; import net.sourceforge.squirrel_sql.client.mainframe.action.CloseAllButCurrentSessionsAction; import net.sourceforge.squirrel_sql.client.mainframe.action.CloseAllSessionsAction; @@ -11,22 +43,12 @@ import net.sourceforge.squirrel_sql.client.session.action.CloseSessionWindowAction; import net.sourceforge.squirrel_sql.client.session.action.GoToAliasSessionAction; import net.sourceforge.squirrel_sql.client.session.action.RenameSessionAction; +import net.sourceforge.squirrel_sql.client.shortcut.ShortCutDescriptionReader; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; import net.sourceforge.squirrel_sql.fw.gui.buttontabcomponent.ButtonTabComponent; import net.sourceforge.squirrel_sql.fw.gui.buttontabcomponent.SmallTabButton; import net.sourceforge.squirrel_sql.fw.resources.Resources; -import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.util.ArrayList; -import java.util.HashSet; - // public class DockTabDesktopPane extends JComponent implements IDesktopContainer { @@ -602,7 +624,7 @@ private JMenuItem createMenu(Action action) JMenuItem ret = new JMenuItem(action); String accel = (String) action.getValue(Resources.ACCELERATOR_STRING); - Main.getApplication().getShortcutManager().setAccelerator(ret, KeyStroke.getKeyStroke(accel), action); + Main.getApplication().getShortcutManager().setAccelerator(ret, KeyStroke.getKeyStroke(accel), action, ShortCutDescriptionReader.of(action)); return ret; } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/I18NStrings.properties b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/I18NStrings.properties index 49b8a4476..1ce884279 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/I18NStrings.properties +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/I18NStrings.properties @@ -1,12 +1,13 @@ keystroke.prefs.title=Keyboard shortcuts keystroke.prefs.hint=Configure keyboard shortcuts -ShortcutPrefsCtrl.column.actionName=Action Name +ShortcutPrefsCtrl.column.actionName=Action name ShortcutPrefsCtrl.column.validKeyStroke=Valid shortcut ShortcutPrefsCtrl.column.defaultKeyStroke=Default shortcut +ShortcutPrefsCtrl.column.description=Action description ShortcutPrefsPanel.lbl.edit.shortcut=Enter shortcut: -ShortcutPrefsPanel.txt.shortcut.formated=Selected action: "{0}" (Default shortcut: {1}) +ShortcutPrefsPanel.txt.shortcut.formated_extended=Selected action: "{0}" / Default shortcut: {1} / Description: {2} ShortcutPrefsPanel.btn.apply=Apply shortcut ShortcutPrefsPanel.btn.remove=Remove shortcut diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/ShortcutPrefsCtrl.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/ShortcutPrefsCtrl.java index 739eab771..e906ae75a 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/ShortcutPrefsCtrl.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/preferences/shortcut/ShortcutPrefsCtrl.java @@ -1,5 +1,14 @@ package net.sourceforge.squirrel_sql.client.preferences.shortcut; +import java.awt.Color; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.List; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.shortcut.Shortcut; import net.sourceforge.squirrel_sql.client.shortcut.ShortcutUtil; @@ -10,16 +19,7 @@ import net.sourceforge.squirrel_sql.fw.util.StringManager; import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory; import net.sourceforge.squirrel_sql.fw.util.Utilities; - -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.KeyStroke; -import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; -import java.awt.Color; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.List; +import org.apache.commons.lang3.StringUtils; public class ShortcutPrefsCtrl @@ -30,10 +30,12 @@ public class ShortcutPrefsCtrl private static final String PREF_KEY_ACTION_NAME_COL_WIDTH = "ShortcutPrefsCtrl.column.actionName.width"; private static final String PREF_KEY_VALID_SHORTCUT_COL_WIDTH = "ShortcutPrefsCtrl.column.validShortcut.width"; private static final String PREF_KEY_DEFAULT_SHORTCUT_COL_WIDTH = "ShortcutPrefsCtrl.column.defaultShortcut.width"; + private static final String PREF_KEY_ACTION_DESCRIPTION_COL_WIDTH = "ShortcutPrefsCtrl.column.actionDescription.width"; public static final String COL_HEADER_ACTION_NAME = s_stringMgr.getString("ShortcutPrefsCtrl.column.actionName"); public static final String COL_HEADER_VALID_SHORTCUT = s_stringMgr.getString("ShortcutPrefsCtrl.column.validKeyStroke"); public static final String COL_HEADER_DEFAULT_SHORTCUT = s_stringMgr.getString("ShortcutPrefsCtrl.column.defaultKeyStroke"); + public static final String COL_HEADER_ACTION_DESCRIPTION = s_stringMgr.getString("ShortcutPrefsCtrl.column.description"); private ShortcutPrefsPanel _shortcutPrefsPanel = new ShortcutPrefsPanel(); private KeyStroke _currentKeyStroke; @@ -46,7 +48,7 @@ public void applyChanges() Props.putInt(PREF_KEY_ACTION_NAME_COL_WIDTH, _shortcutPrefsPanel.tblShortcuts.getColumnWidthForHeader(COL_HEADER_ACTION_NAME)); Props.putInt(PREF_KEY_VALID_SHORTCUT_COL_WIDTH, _shortcutPrefsPanel.tblShortcuts.getColumnWidthForHeader(COL_HEADER_VALID_SHORTCUT)); Props.putInt(PREF_KEY_DEFAULT_SHORTCUT_COL_WIDTH, _shortcutPrefsPanel.tblShortcuts.getColumnWidthForHeader(COL_HEADER_DEFAULT_SHORTCUT)); - + Props.putInt(PREF_KEY_ACTION_DESCRIPTION_COL_WIDTH, _shortcutPrefsPanel.tblShortcuts.getColumnWidthForHeader(COL_HEADER_ACTION_DESCRIPTION)); Main.getApplication().getShortcutManager().save(); @@ -60,17 +62,22 @@ public JPanel getPanel() _shortcutDataSet = new JavabeanArrayDataSet(Shortcut.class); _shortcutDataSet.setColHeader("actionName", COL_HEADER_ACTION_NAME); - _shortcutDataSet.setColPos("actionName", 1); + _shortcutDataSet.setColPos("actionName", 0); _shortcutDataSet.setAbsoluteWidht("actionName", Props.getInt(PREF_KEY_ACTION_NAME_COL_WIDTH, 200)); _shortcutDataSet.setColHeader("validKeyStroke", COL_HEADER_VALID_SHORTCUT); - _shortcutDataSet.setColPos("validKeyStroke", 2); + _shortcutDataSet.setColPos("validKeyStroke", 1); _shortcutDataSet.setAbsoluteWidht("validKeyStroke", Props.getInt(PREF_KEY_VALID_SHORTCUT_COL_WIDTH, 200)); _shortcutDataSet.setColHeader("defaultKeyStroke", COL_HEADER_DEFAULT_SHORTCUT); _shortcutDataSet.setColPos("defaultKeyStroke", 2); _shortcutDataSet.setAbsoluteWidht("defaultKeyStroke", Props.getInt(PREF_KEY_DEFAULT_SHORTCUT_COL_WIDTH, 200)); + _shortcutDataSet.setColHeader("actionDescription", COL_HEADER_ACTION_DESCRIPTION); + _shortcutDataSet.setColPos("actionDescription", 3); + _shortcutDataSet.setAbsoluteWidht("actionDescription", Props.getInt(PREF_KEY_ACTION_DESCRIPTION_COL_WIDTH, 200)); + + _shortcutDataSet.setIgnoreProperty("userKeyStroke"); displayShortcuts(); @@ -108,7 +115,7 @@ private Color onGetCellColor(int row, int column, boolean isSelected) { int modelColumn = _shortcutPrefsPanel.tblShortcuts.getTable().getColumnModel().getColumn(column).getModelIndex(); - if(2 != modelColumn) + if(1 != modelColumn) { return null; } @@ -156,15 +163,20 @@ private void onSelectedShortcutChanged() if(0 == _shortcutPrefsPanel.tblShortcuts.getSelectedModelRows().length) { - _shortcutPrefsPanel.txtSelectedShortcut.setText(s_stringMgr.getString("ShortcutPrefsPanel.txt.shortcut.formated", "", "", "", "")); return; - } - Shortcut selectedShortcut = getSelectedShortcut(); - _shortcutPrefsPanel.txtSelectedShortcut.setText(s_stringMgr.getString("ShortcutPrefsPanel.txt.shortcut.formated", selectedShortcut.getActionName(), selectedShortcut.getDefaultKeyStroke())); + _shortcutPrefsPanel.txtSelectedShortcut.setText(s_stringMgr.getString("ShortcutPrefsPanel.txt.shortcut.formated_extended", selectedShortcut.getActionName(), selectedShortcut.getDefaultKeyStroke(), getDescription(selectedShortcut))); + + _shortcutPrefsPanel.txtSelectedShortcut.setCaretPosition(0); + } + + private String getDescription(Shortcut selectedShortcut) + { + return StringUtils.isBlank(selectedShortcut.getActionDescription()) ? "" : selectedShortcut.getActionDescription(); } private void displayShortcuts() diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/action/syntax/rsyntax/SquirreLRSyntaxTextAreaUI.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/action/syntax/rsyntax/SquirreLRSyntaxTextAreaUI.java index 3fd23c93f..5304b0fc1 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/action/syntax/rsyntax/SquirreLRSyntaxTextAreaUI.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/action/syntax/rsyntax/SquirreLRSyntaxTextAreaUI.java @@ -1,7 +1,19 @@ package net.sourceforge.squirrel_sql.client.session.action.syntax.rsyntax; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import javax.swing.Action; +import javax.swing.InputMap; +import javax.swing.KeyStroke; +import javax.swing.UIManager; +import javax.swing.plaf.InputMapUIResource; +import javax.swing.text.EditorKit; +import javax.swing.text.JTextComponent; +import javax.swing.text.TextAction; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.session.mainpanel.IUndoHandler; +import net.sourceforge.squirrel_sql.client.shortcut.ShortCutDescriptionReader; import net.sourceforge.squirrel_sql.fw.gui.stdtextpopup.TextActionUtil; import net.sourceforge.squirrel_sql.fw.gui.stdtextpopup.TextBeginAction; import net.sourceforge.squirrel_sql.fw.gui.stdtextpopup.TextBeginLineAction; @@ -17,18 +29,6 @@ import org.fife.ui.rtextarea.RTextArea; import org.fife.ui.rtextarea.RTextAreaEditorKit; -import javax.swing.Action; -import javax.swing.InputMap; -import javax.swing.KeyStroke; -import javax.swing.UIManager; -import javax.swing.plaf.InputMapUIResource; -import javax.swing.text.EditorKit; -import javax.swing.text.JTextComponent; -import javax.swing.text.TextAction; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - public class SquirreLRSyntaxTextAreaUI extends RSyntaxTextAreaUI { private static final KeyStroke RS_KEY_STROKE_TO_UPPER_CASE = KeyStroke.getKeyStroke(KeyEvent.VK_U, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); @@ -192,26 +192,37 @@ public static Action getActionForName(SquirrelRSyntaxTextArea squirrelRSyntaxTex public static KeyStroke getToUpperCaseKeyStroke() { - return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaUpperSelectionCaseAction, SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_TO_UPPER_CASE)); + return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaUpperSelectionCaseAction, + SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_TO_UPPER_CASE, + ShortCutDescriptionReader.of())); } public static KeyStroke getToLowerCaseKeyStroke() { - return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaLowerSelectionCaseAction, SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_TO_LOWER_CASE)); + return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaLowerSelectionCaseAction, + SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_TO_LOWER_CASE, + ShortCutDescriptionReader.of())); } public static KeyStroke getLineUpKeyStroke() { - return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaLineUpAction, SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_LINE_UP)); + return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaLineUpAction, + SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_LINE_UP, + ShortCutDescriptionReader.of())); + } public static KeyStroke getLineDownKeyStroke() { - return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaLineDownAction, SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_LINE_DOWN)); + return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.rtaLineDownAction, + SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_LINE_DOWN, + ShortCutDescriptionReader.of())); } public static KeyStroke getSelectWordStroke() { - return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.selectWordAction, SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_SELECT_WORD)); + return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(RTextAreaEditorKit.selectWordAction, + SquirreLRSyntaxTextAreaUI.RS_KEY_STROKE_SELECT_WORD, + ShortCutDescriptionReader.of())); } @Override diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java index f5f84b73e..bafa4db85 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecutorPanel.java @@ -51,6 +51,7 @@ import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabheader.ResultTabAdder; import net.sourceforge.squirrel_sql.client.session.mainpanel.resulttabheader.ResultTabComponent; import net.sourceforge.squirrel_sql.client.session.properties.SessionProperties; +import net.sourceforge.squirrel_sql.client.shortcut.ShortCutDescriptionReader; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetUpdateableTableModel; import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet; import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetMetaDataDataSet; @@ -933,7 +934,7 @@ private void initAccelerator(Class actionClass, JMenuItem mnuI Action action = _session.getApplication().getActionCollection().get(actionClass); String accel = (String) action.getValue(Resources.ACCELERATOR_STRING); - Main.getApplication().getShortcutManager().setAccelerator(mnuItem, KeyStroke.getKeyStroke(accel), action); + Main.getApplication().getShortcutManager().setAccelerator(mnuItem, KeyStroke.getKeyStroke(accel), action, ShortCutDescriptionReader.of(action, mnuItem)); } public JTabbedPane getTabbedPane() diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutDescriptionReader.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutDescriptionReader.java new file mode 100644 index 000000000..4bc765dbb --- /dev/null +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutDescriptionReader.java @@ -0,0 +1,126 @@ +package net.sourceforge.squirrel_sql.client.shortcut; + +import java.util.MissingResourceException; +import javax.swing.Action; +import javax.swing.JMenuItem; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.fw.resources.IResources; +import net.sourceforge.squirrel_sql.fw.resources.ResourceBundleHandler; +import net.sourceforge.squirrel_sql.fw.resources.Resources; +import org.apache.commons.lang3.StringUtils; + +public record ShortCutDescriptionReader(Action action, + Class actionClass, + JMenuItem mnuItem, + Resources resources, + ResourceBundleHandler bundleHandler, + String fullResourceKey) +{ + public static ShortCutDescriptionReader of(Action action) + { + return new ShortCutDescriptionReader(action, null, null, null, null, null); + } + + public static ShortCutDescriptionReader of(Action action, JMenuItem mnuItem) + { + return new ShortCutDescriptionReader(action, null, mnuItem, null, null, null); + } + + public static ShortCutDescriptionReader of(JMenuItem menuItem) + { + return new ShortCutDescriptionReader(null, null, menuItem, null, null, null); + } + + public static ShortCutDescriptionReader of(Resources resources, Class actionClass) + { + return new ShortCutDescriptionReader(null, actionClass, null, resources, null, null); + } + + public static ShortCutDescriptionReader of(Action action, String fullResourceKey, ResourceBundleHandler bundleHandler) + { + return new ShortCutDescriptionReader(action, null, null, null, bundleHandler, fullResourceKey); + } + + public static ShortCutDescriptionReader of() + { + return new ShortCutDescriptionReader(null, null, null, null, null, null); + } + + public String getDescription() + { + String description = null; + + Class actCls = actionClass; + + if(null == actCls && null != action) + { + actCls = action.getClass(); + } + + + if(null != resources && null != actCls) + { + description = resources.getTooltipFromResource(actCls); + } + + if(StringUtils.isBlank(description)) + { + Action act = action; + + if(null == act && null != actionClass) + { + act = Main.getApplication().getActionCollection().get(actionClass); + } + + if(null != act) + { + description = (null == act.getValue(Action.SHORT_DESCRIPTION) ? null : "" + act.getValue(Action.SHORT_DESCRIPTION)); + + if(StringUtils.isBlank(description)) + { + description = (null == act.getValue(Action.SHORT_DESCRIPTION) ? null : "" + act.getValue(Action.LONG_DESCRIPTION)); + } + } + } + + if(StringUtils.isBlank(description) && !StringUtils.isBlank(fullResourceKey)) + { + String resKey = fullResourceKey; + + if(fullResourceKey.startsWith(IResources.Keys.MENU_ITEM)) + { + resKey = StringUtils.replace(fullResourceKey, IResources.Keys.MENU_ITEM, IResources.Keys.ACTION, 1); + } + + if(null != resources) + { + try + { + description = resources.getTooltipFromResource(resKey); + } + catch(MissingResourceException e) + { + } + } + + if(StringUtils.isBlank(description) && null != bundleHandler) + { + try + { + description = bundleHandler.getResourceString(resKey, IResources.ActionProperties.TOOLTIP); + } + catch(MissingResourceException e) + { + } + } + } + + if(StringUtils.isBlank(description)) + { + description = null; + } + + return description; + } + +} diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutReader.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutReader.java index 9b502abc3..9b4356924 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutReader.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortCutReader.java @@ -1,14 +1,13 @@ package net.sourceforge.squirrel_sql.client.shortcut; +import java.util.MissingResourceException; +import javax.swing.Action; +import javax.swing.KeyStroke; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.fw.resources.IResources; import net.sourceforge.squirrel_sql.fw.resources.ResourceBundleHandler; import net.sourceforge.squirrel_sql.fw.util.StringUtilities; -import javax.swing.Action; -import javax.swing.KeyStroke; -import java.util.MissingResourceException; - public class ShortCutReader { private ResourceBundleHandler _bundleHandler; @@ -63,7 +62,7 @@ private String _getShortcutAsString(String fullResourceKey, String actionName, A if (false == defaultShortCut && false == StringUtilities.isEmpty(actionName, true)) { // Possibly replace the standard shortcut with the user defined one. - ret = Main.getApplication().getShortcutManager().registerAccelerator(actionName, KeyStroke.getKeyStroke(ret)); + ret = Main.getApplication().getShortcutManager().registerAccelerator(actionName, KeyStroke.getKeyStroke(ret), ShortCutDescriptionReader.of(action, fullResourceKey, _bundleHandler)); } return ret; diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/Shortcut.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/Shortcut.java index e0f3bc4ee..d45cf0fcf 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/Shortcut.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/Shortcut.java @@ -1,20 +1,21 @@ package net.sourceforge.squirrel_sql.client.shortcut; -import org.jfree.chart.util.ObjectUtils; - import javax.swing.KeyStroke; +import org.jfree.chart.util.ObjectUtils; public class Shortcut { private final String _actionName; + private final String _actionDescription; private final KeyStroke _defaultKeyStroke; private KeyStroke _userKeyStroke; private boolean _userKeyStrokeEmpty; - public Shortcut(String actionName, KeyStroke defaultKeyStroke) + public Shortcut(String actionName, KeyStroke defaultKeyStroke, String actionDescription) { _actionName = actionName; _defaultKeyStroke = defaultKeyStroke; + _actionDescription = actionDescription; } /** @@ -57,6 +58,13 @@ public KeyStroke validKeyStroke() return _defaultKeyStroke; } + /** + * Used via reflection by JavabeanArrayDataSet + */ + public String getActionDescription() + { + return _actionDescription; + } public void setUserKeyStroke(KeyStroke userKeyStroke) { diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortcutManager.java b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortcutManager.java index f49b51744..6eee09d98 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortcutManager.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/client/shortcut/ShortcutManager.java @@ -5,15 +5,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.type.SimpleType; -import net.sourceforge.squirrel_sql.client.Main; -import net.sourceforge.squirrel_sql.client.util.ApplicationFiles; -import net.sourceforge.squirrel_sql.fw.resources.Resources; -import net.sourceforge.squirrel_sql.fw.util.StringUtilities; -import net.sourceforge.squirrel_sql.fw.util.Utilities; - -import javax.swing.Action; -import javax.swing.JMenuItem; -import javax.swing.KeyStroke; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -22,6 +13,13 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import javax.swing.Action; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import net.sourceforge.squirrel_sql.client.util.ApplicationFiles; +import net.sourceforge.squirrel_sql.fw.resources.Resources; +import net.sourceforge.squirrel_sql.fw.util.StringUtilities; +import net.sourceforge.squirrel_sql.fw.util.Utilities; public class ShortcutManager { @@ -71,14 +69,14 @@ public List getShortcuts() return new ArrayList<>(_shortcuts); } - public KeyStroke setAccelerator(JMenuItem item, KeyStroke defaultKeyStroke, Action action) + public KeyStroke setAccelerator(JMenuItem item, KeyStroke defaultKeyStroke, Action action, ShortCutDescriptionReader descReader) { - return setAccelerator(item, defaultKeyStroke, (String) action.getValue(Action.NAME)); + return setAccelerator(item, defaultKeyStroke, (String) action.getValue(Action.NAME), descReader); } - public KeyStroke setAccelerator(JMenuItem item, KeyStroke defaultKeyStroke, String actionName) + public KeyStroke setAccelerator(JMenuItem item, KeyStroke defaultKeyStroke, String actionName, ShortCutDescriptionReader descReader) { - Shortcut shortcut = _registerAccelerator(actionName, defaultKeyStroke); + Shortcut shortcut = _registerAccelerator(actionName, defaultKeyStroke, descReader); item.setAccelerator(shortcut.validKeyStroke()); @@ -86,33 +84,28 @@ public KeyStroke setAccelerator(JMenuItem item, KeyStroke defaultKeyStroke, Stri } - public void registerAccelerator(Class actionClass) - { - registerAccelerator(actionClass, Main.getApplication().getResources()); - } - - public String registerAccelerator(Class actionClass, Resources resources) + public String registerAccelerator(Class actionClass, Resources resources, ShortCutDescriptionReader descReader) { String actionName = resources.getActionName(actionClass); KeyStroke defaultKeyStroke = resources.getShortCutReader().getDefaultShortcutAsKeyStroke(resources.getFullMenuItemKey(actionClass), actionName); - return _registerAccelerator(actionName, defaultKeyStroke).getValidKeyStroke(); + return _registerAccelerator(actionName, defaultKeyStroke, descReader).getValidKeyStroke(); } - public String registerAccelerator(String actionName, KeyStroke defaultKeyStroke) + public String registerAccelerator(String actionName, KeyStroke defaultKeyStroke, ShortCutDescriptionReader descReader) { - return _registerAccelerator(actionName, defaultKeyStroke).getValidKeyStroke(); + return _registerAccelerator(actionName, defaultKeyStroke, descReader).getValidKeyStroke(); } - private Shortcut _registerAccelerator(String actionName, KeyStroke defaultKeyStroke) + private Shortcut _registerAccelerator(String actionName, KeyStroke defaultKeyStroke, ShortCutDescriptionReader descReader) { if(StringUtilities.isEmpty(actionName, true)) { - return new Shortcut(actionName, defaultKeyStroke); + return new Shortcut(actionName, defaultKeyStroke, descReader.getDescription()); } - Shortcut ret = new Shortcut(actionName, defaultKeyStroke); + Shortcut ret = new Shortcut(actionName, defaultKeyStroke, descReader.getDescription()); String userShortCutString = _shortcutsJsonBeanLoadedAtStartUp.getShortcutByKey().get(ret.generateKey()); diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/JavabeanArrayDataSet.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/JavabeanArrayDataSet.java index 69d5ebfa1..affeadfca 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/JavabeanArrayDataSet.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/datasetviewer/JavabeanArrayDataSet.java @@ -18,10 +18,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -import net.sourceforge.squirrel_sql.fw.util.EmptyIterator; -import net.sourceforge.squirrel_sql.fw.util.IMessageHandler; -import net.sourceforge.squirrel_sql.fw.util.Utilities; - import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; @@ -35,6 +31,9 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import net.sourceforge.squirrel_sql.fw.util.EmptyIterator; +import net.sourceforge.squirrel_sql.fw.util.IMessageHandler; +import net.sourceforge.squirrel_sql.fw.util.Utilities; public class JavabeanArrayDataSet implements IDataSet { @@ -48,10 +47,10 @@ public class JavabeanArrayDataSet implements IDataSet private Class _beanClass; private BeanPorpertyColumnDisplayDefinition[] _beanPorpertyColumnDisplayDefinitions; - private HashMap _headers = new HashMap(); - private HashMap _positions = new HashMap(); - private HashMap _absoluteWidths = new HashMap(); - private HashSet _ignoreProperties = new HashSet(); + private HashMap _headers = new HashMap<>(); + private HashMap _positions = new HashMap<>(); + private HashMap _absoluteWidths = new HashMap<>(); + private HashSet _ignoreProperties = new HashSet<>(); /** diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java index 4c3c8be6d..97f6256f0 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/TablePopupMenu.java @@ -33,6 +33,7 @@ import net.sourceforge.squirrel_sql.client.session.ISession; import net.sourceforge.squirrel_sql.client.session.SQLExecutionInfo; import net.sourceforge.squirrel_sql.client.session.action.dbdiff.tableselectiondiff.TableSelectionDiff; +import net.sourceforge.squirrel_sql.client.shortcut.ShortCutDescriptionReader; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTable; import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetViewerTablePanel; import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetUpdateableModel; @@ -248,7 +249,7 @@ public TablePopupMenu(boolean allowEditing, private void addMenuItem(JMenuItem menuItem) { String actionName = menuItem.getText(); - KeyStroke validKeyStroke = Main.getApplication().getShortcutManager().setAccelerator(menuItem, null, actionName); + KeyStroke validKeyStroke = Main.getApplication().getShortcutManager().setAccelerator(menuItem, null, actionName, ShortCutDescriptionReader.of(menuItem)); add(menuItem); if (null != validKeyStroke) @@ -275,7 +276,7 @@ private void addAction(Action action) private void addAction(Action action, KeyStroke defaultKeyStroke) { JMenuItem mnuAdded = add(action); - KeyStroke validKeyStroke = Main.getApplication().getShortcutManager().setAccelerator(mnuAdded, defaultKeyStroke, action); + KeyStroke validKeyStroke = Main.getApplication().getShortcutManager().setAccelerator(mnuAdded, defaultKeyStroke, action, ShortCutDescriptionReader.of(action)); ResourceUtil.trySetToolTip(mnuAdded, action); if (null != validKeyStroke) diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/stdtextpopup/TextActionHelper.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/stdtextpopup/TextActionHelper.java index 64837fc8b..3b83fb73e 100644 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/stdtextpopup/TextActionHelper.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/gui/stdtextpopup/TextActionHelper.java @@ -1,10 +1,10 @@ package net.sourceforge.squirrel_sql.fw.gui.stdtextpopup; -import net.sourceforge.squirrel_sql.client.Main; - import javax.swing.Action; import javax.swing.KeyStroke; import javax.swing.text.JTextComponent; +import net.sourceforge.squirrel_sql.client.Main; +import net.sourceforge.squirrel_sql.client.shortcut.ShortCutDescriptionReader; public class TextActionHelper { @@ -36,6 +36,6 @@ public void initKeyStroke(JTextComponent comp) public static KeyStroke getKeyStroke(String defaultEditorKitActionName, KeyStroke defaultKeyStroke) { - return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(defaultEditorKitActionName, defaultKeyStroke)); + return KeyStroke.getKeyStroke(Main.getApplication().getShortcutManager().registerAccelerator(defaultEditorKitActionName, defaultKeyStroke, ShortCutDescriptionReader.of())); } } diff --git a/sql12/core/src/net/sourceforge/squirrel_sql/fw/resources/Resources.java b/sql12/core/src/net/sourceforge/squirrel_sql/fw/resources/Resources.java index ba4f9f5d5..405ee3811 100755 --- a/sql12/core/src/net/sourceforge/squirrel_sql/fw/resources/Resources.java +++ b/sql12/core/src/net/sourceforge/squirrel_sql/fw/resources/Resources.java @@ -19,6 +19,16 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.net.URL; +import java.util.MissingResourceException; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.shortcut.ShortCutReader; import net.sourceforge.squirrel_sql.fw.gui.GUIUtils; @@ -28,10 +38,7 @@ import net.sourceforge.squirrel_sql.fw.util.Utilities; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; - -import javax.swing.*; -import java.net.URL; -import java.util.MissingResourceException; +import org.apache.commons.lang3.StringUtils; public abstract class Resources implements IResources { @@ -304,6 +311,30 @@ public String getActionName(Class actionClass) return getResourceString(getActionKey(actionClass), ActionProperties.NAME); } + public String getTooltipFromResource(Class actionClass) + { + String ret = getResourceString(getActionKey(actionClass), ActionProperties.TOOLTIP); + if(false == StringUtils.isBlank(ret)) + { + return ret; + } + + return null; + } + + public String getTooltipFromResource(String fullResourceString) + { + String ret = getResourceString(fullResourceString, ActionProperties.TOOLTIP); + + if(false == StringUtils.isBlank(ret)) + { + return ret; + } + + return null; + } + + private String getActionKey(Class actionClass) { final String actionClassName = actionClass.getName(); diff --git a/sql12/plugins/hibernate/src/net/sourceforge/squirrel_sql/plugins/hibernate/HibernatePlugin.java b/sql12/plugins/hibernate/src/net/sourceforge/squirrel_sql/plugins/hibernate/HibernatePlugin.java index fdfbd6a3f..6e0176aff 100644 --- a/sql12/plugins/hibernate/src/net/sourceforge/squirrel_sql/plugins/hibernate/HibernatePlugin.java +++ b/sql12/plugins/hibernate/src/net/sourceforge/squirrel_sql/plugins/hibernate/HibernatePlugin.java @@ -1,8 +1,6 @@ package net.sourceforge.squirrel_sql.plugins.hibernate; import java.util.HashMap; - -import net.sourceforge.squirrel_sql.client.IApplication; import net.sourceforge.squirrel_sql.client.Main; import net.sourceforge.squirrel_sql.client.plugin.DefaultSessionPlugin; import net.sourceforge.squirrel_sql.client.plugin.PluginException; @@ -10,6 +8,7 @@ import net.sourceforge.squirrel_sql.client.plugin.PluginSessionCallbackAdaptor; import net.sourceforge.squirrel_sql.client.preferences.IGlobalPreferencesPanel; import net.sourceforge.squirrel_sql.client.session.ISession; +import net.sourceforge.squirrel_sql.client.shortcut.ShortCutDescriptionReader; import net.sourceforge.squirrel_sql.fw.id.IIdentifier; import net.sourceforge.squirrel_sql.fw.util.log.ILogger; import net.sourceforge.squirrel_sql.fw.util.log.LoggerController; @@ -78,9 +77,9 @@ public synchronized void initialize() throws PluginException { _resources = new HibernatePluginResources(this); - Main.getApplication().getShortcutManager().registerAccelerator(HQLCompleteCodeAction.class, _resources); - Main.getApplication().getShortcutManager().registerAccelerator(HQLBookmarksAction.class, _resources); - Main.getApplication().getShortcutManager().registerAccelerator(HQLToolsPopUpAction.class, _resources); + Main.getApplication().getShortcutManager().registerAccelerator(HQLCompleteCodeAction.class, _resources, ShortCutDescriptionReader.of(_resources, HQLCompleteCodeAction.class)); + Main.getApplication().getShortcutManager().registerAccelerator(HQLBookmarksAction.class, _resources, ShortCutDescriptionReader.of(_resources, HQLBookmarksAction.class)); + Main.getApplication().getShortcutManager().registerAccelerator(HQLToolsPopUpAction.class, _resources, ShortCutDescriptionReader.of(_resources, HQLToolsPopUpAction.class)); } diff --git a/sql12/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/oracle.properties b/sql12/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/oracle.properties index 84aef5476..14f21ad4a 100755 --- a/sql12/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/oracle.properties +++ b/sql12/plugins/oracle/src/net/sourceforge/squirrel_sql/plugins/oracle/oracle.properties @@ -52,7 +52,7 @@ net.sourceforge.squirrel_sql.plugins.oracle.SGAtrace.SGATraceInternalFrame.frame # Configuration information for Actions. ######## action.net.sourceforge.squirrel_sql.plugins.oracle.dboutput.NewDBOutputWorksheetAction.image=dboutput.gif -action.net.sourceforge.squirrel_sql.plugins.oracle.dboutput.NewDBOutputWorksheetAction.name=DB Ouptut +action.net.sourceforge.squirrel_sql.plugins.oracle.dboutput.NewDBOutputWorksheetAction.name=DB Output action.net.sourceforge.squirrel_sql.plugins.oracle.dboutput.NewDBOutputWorksheetAction.tooltip=View Oracle Database Output action.net.sourceforge.squirrel_sql.plugins.oracle.dboutput.ClearDBOutputAction.image=Delete16.gif From 502694e132e0430404c9241e0907f3c619f09dda Mon Sep 17 00:00:00 2001 From: gerdwagner Date: Mon, 6 Apr 2026 21:32:48 +0200 Subject: [PATCH 33/33] Feature: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/88 The keyboard short cuts tab now contains the action's description (tooltip). Bug fix: Oracle Plugin: Fixed typo, DB Ouptut --> DB Output --- sql12/build.xml | 4 ++-- sql12/core/doc/changes.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sql12/build.xml b/sql12/build.xml index d02db94b8..4abd28762 100644 --- a/sql12/build.xml +++ b/sql12/build.xml @@ -8,8 +8,8 @@ - - + + diff --git a/sql12/core/doc/changes.txt b/sql12/core/doc/changes.txt index 8c8a037e5..b195c6c7f 100755 --- a/sql12/core/doc/changes.txt +++ b/sql12/core/doc/changes.txt @@ -7,7 +7,8 @@ Not yet released, available in our GIT repository, snapshots and future releases Enhancements: https://github.com/squirrel-sql-client/squirrel-sql-code/issues/88 -The keyboard short cuts tab now contains the action's description (tooltip). + The keyboard short cuts tab now contains the action's description (tooltip). + See menu File --> Global Preferences --> tab "Keyboard shortcuts" Bug fixes:
⇒ Table columns can be toggled between a monospaced font and default font
⇒ Table cell contents can be concatenated without separator
SQuirreL SQL Client Version JRE Minimum Version
5.0.0 and higher 5.1.0 and higher 17
SQuirreL SQL Client Version JRE Minimum Version
5.0.0 and higher5.1.0 and higher 17
5.0.0 and higher5.1.0 and higher 17
Universal SQL Client - Version 5.0.0 + Version 5.1.0
diff --git a/sql12/web-site/home.html b/sql12/web-site/home.html index 652759d08..c682aae96 100755 --- a/sql12/web-site/home.html +++ b/sql12/web-site/home.html @@ -41,32 +41,20 @@

  -

Feature highlights of 5.0.0:

+

Feature highlights of 5.1.0:

    -
  • The Object tree's root node has a new detail tab named "Client Properties"
  • -
  • The Object tree didn't show tables when the JDBC driver didn't provide table types
  • -
  • Support for Java 25
  • -
  • SQL result table search now highlights results in cell detail display, too
  • -
  • Cell data image display offers to scale images to fit the display size
  • -
  • MS Excel exports offer to create tabs containing the exports' SQL statements
  • -
  • Improved memory footprint
  • -
  • Enhanced 'Copy separated by ...' function
  • -
  • Searching all open SQL results and cell data dialogs
  • -
  • Code completion for JOIN ON clauses
  • -
  • Cell data display highlights JSON and XML after reformatting
  • -
  • Choosing fonts for MS-Excel export
  • -
  • Aliases can be made read-only
  • -
  • SQL result tabs that match the current SQL in the editor are marked
  • -
  • SQL result's find function now offers to narrow the columns to search
  • -
  • SQL result's detail data display now allows to automatically reformat XML or Json
  • -
  • Numeric values can be right aligned
  • -
  • Export to MS-Excel allows to configure auto filtering
  • -
  • Header rows of MS-Excel exports can be made bold/centered/frozen
  • -
  • Option to change the statement separator during SQL execution using --#SET TERMINATOR <separator>
  • -
  • Besides sums, means and deviations can now be displayed for selections in numerical columns
  • -
  • New Alias tree icons which for FlatLaf Look and Feels show if top level folders are expanded or collapsed
  • +
  • Table columns can be toggled between a monospaced font and default font
  • +
  • Table cell contents can be concatenated without separator
  • +
  • SQL results can be rerun automatically after a configurable number of seconds
  • +
  • The SQL editor allows to run bookmarks by the syntax @runbookmark <bookmarkNameInSingleQuotes>
  • +
  • MS Excel file export allows to add or replace sheet-tabs in an MS Excel file
  • +
  • Option to execute SQL in multiple Sessions
  • +
  • Single click connect to multiple Aliases
  • +
  • Enhanced security for encrypting Alias passwords
  • +
  • "Copy as WIKI Table" - function of tables now supports copying the Jira/Cloud table format
  • +
  • User Bookmarks can be displayed as tree
- All new features and bug fixes of the 5.0.0 release can be found in our change log at + All new features and bug fixes of the 5.1.0 release can be found in our change log at SourceForge or GitHub. @@ -118,6 +106,21 @@

Feature highlights of 5.0.0:

Latest News

+

+ SQuirreL 5.1.0 is released (03/26/2026).
+ The list of feature highlights is rather long and can be found above.
+ For all new features and bug fixes see our change log at SourceForge + or GitHub.
+ Note that SQuirreL 5.1.0 requires at least Java 17.
+
+ 5.1.0 releases on SourceForge:
+ Download installer for Windows/Linux/others
+ Download installer for Mac OS

+ 5.1.0 releases on GitHub:
+ Download installer for Windows/Linux/others
+ Download installer for Mac OS
+

+

The latest snapshot-20260215_1841 is a release candidate for the 5.1.0 release.
Changes since the 5.0.0 release are

@@ -153,49 +156,6 @@

for the latest snapshots regularly.

-

- SQuirreL 5.0.0 is released (09/18/2025).
- The list of feature highlights is rather long and can be found above.
- For all new features and bug fixes see our change log at SourceForge - or GitHub.
- Note that SQuirreL 5.0.0 requires at least Java 17.
-
- 5.0.0 releases on SourceForge:
- Download installer for Windows/Linux/others
- Download installer for Mac OS

- 5.0.0 releases on GitHub:
- Download installer for Windows/Linux/others
- Download installer for Mac OS

-

-
-

- The latest snapshot-20250824_2124 is one more candidate for the 5.0.0 release.
- Latest changes are
- - - - -
⇒ the Object tree's root node has new detail tab named "Client Properties"
⇒ the Object tree didn't show tables when the JDBC driver didn't provide table types
⇒ support for the upcoming Java 25 release
- Please give it a try.

- The minimum required Java version for this snapshot is 17.x.
-
- For all new features and bug fixes see our change log at - SourceForge - or GitHub.

- snapshot-20250824_2124 releases on SourceForge are:
- Download installer for Windows/Linux/others
- Download installer for Mac OS
- snapshot-20250824_2124 releases on GitHub are:
- Download installer for Windows/Linux/others
- Download installer for Mac OS

-

-

- Note: We don't announce every snapshot release here. If you are interested please check
- https://github.com/squirrel-sql-client/squirrel-sql-snapshot-releases/releases
- or
- https://sourceforge.net/projects/squirrel-sql/files/3-snapshots
- for the latest snapshots regularly.
-