From 9e205c186ededf7a3d70c021633a2477a5e5ef05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Guilherme?= Date: Wed, 18 Oct 2023 02:55:42 +0100 Subject: [PATCH] Fix multiple Ctrl-V in macOS, improves upgrade dialog, other fixes (#2662) --- src/robotide/application/updatenotifier.py | 54 ++++++++++++++-------- src/robotide/context/__init__.py | 8 ++++ src/robotide/editor/texteditor.py | 6 +-- src/robotide/postinstall/__main__.py | 16 ++++--- src/robotide/version.py | 2 +- utest/application/test_updatenotifier.py | 13 +++++- utest/resources/fake.cfg | 2 + 7 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/robotide/application/updatenotifier.py b/src/robotide/application/updatenotifier.py index 14f6312df..fc45030ac 100644 --- a/src/robotide/application/updatenotifier.py +++ b/src/robotide/application/updatenotifier.py @@ -32,6 +32,7 @@ _CHECK_FOR_UPDATES_SETTING = "check for updates" _LAST_UPDATE_CHECK_SETTING = "last update check" +SPC = " " class UpdateNotifierController(object): @@ -100,29 +101,33 @@ def upgrade_from_dev_dialog(version_installed): main_dict = {'VERSION': VERSION} exec(master_code, main_dict) # defines VERSION if cmp_versions(version_installed, main_dict['VERSION']) == -1: - # Here is the Menu Help->Upgrade insertion part, try to highlight menu - if not _askyesno("Upgrade?", f"New development version is available.\nYou may install" - f" version {main_dict['VERSION']} with:\npip install -U https://github.com/" - f"robotframework/RIDE/archive/master.zip", wx.GetActiveWindow()): + # Here is the Menu Help->Upgrade insertion part, try to highlight menu # wx.CANCEL_DEFAULT + command = sys.executable + " -m pip install -U https://github.com/robotframework/RIDE/archive/master.zip" + _add_content_to_clipboard(command) + if not _askyesno("Upgrade?", f"{SPC}New development version is available.{SPC}\n{SPC}You may install" + f" version {main_dict['VERSION']} with:\n{SPC}{command}{SPC}\n\n" + f"{SPC}Click OK to Upgrade now!\n{SPC}After upgrade you will see another dialog informing" + f" to close this RIDE instance.{SPC}\n", + wx.GetActiveWindow(), no_default=True): return False else: - command = sys.executable + " -m pip install -U https://github.com/robotframework/RIDE/archive/master.zip" do_upgrade(command) return True else: - _askyesno("No Upgrade Available", "You have the latest version of RIDE.\nHave a nice day :)", + _askyesno("No Upgrade Available", f"{SPC}You have the latest version of RIDE.{SPC}" + f"\n\n{SPC} Have a nice day :)\n", wx.GetActiveWindow()) return False -def _askyesno(title, message, frame=None): +def _askyesno(title, message, frame=None, no_default=False): if frame is None: - _ = wx.App() + _ = wx.GetApp() or wx.App() parent = wx.Frame(None, size=(0, 0)) else: parent = wx.Frame(frame, size=(0, 0)) parent.CenterOnScreen() - dlg = MessageDialog(parent, message, title, ttl=8) + dlg = MessageDialog(parent, message, title, ttl=8, no_default=no_default) dlg.Fit() result = dlg.ShowModal() in [wx.ID_YES, wx.ID_OK] # print("DEBUG: updatenotifier _askyesno Result %s" % result) @@ -150,6 +155,9 @@ def do_upgrade(command): outs, errs = my_pip.communicate() # DEBUG: Add output to a notebook tab print(f"{outs}\n") + if errs: + print(f"\nERRORS: {errs}\n") + errs = None result = my_pip.returncode if result == 0: break @@ -164,7 +172,7 @@ def do_upgrade(command): """ time.sleep(1) if result != 0: - _askyesno("Failed to Upgrade", "An error occurred when installing new version", + _askyesno("Failed to Upgrade", f"{SPC}An error occurred when installing new version", wx.GetActiveWindow()) return False command = sys.executable + " -m robotide.__init__ --noupdatecheck" @@ -173,7 +181,7 @@ def do_upgrade(command): """ Not working well: wx.CallLater(10000, psutil.Process.kill, my_pid.pid) """ - _askyesno("Completed Upgrade", f"You should close this RIDE (Process ID = {my_pid.pid})", + _askyesno("Completed Upgrade", f"\n{SPC}You should close this RIDE (Process ID = {my_pid.pid}){SPC}", wx.GetActiveWindow()) @@ -189,22 +197,25 @@ def OnLinkClicked(self, link): # Overrides wx method class UpdateDialog(RIDEDialog): - def __init__(self, uversion, url, settings): + def __init__(self, uversion, url, settings, modal=True): self._settings = settings self._command = sys.executable + f" -m pip install -U robotframework-ride=={uversion}" - RIDEDialog.__init__(self, title="Update available", size=(400, 400), + _add_content_to_clipboard(self._command) + RIDEDialog.__init__(self, title="Update available", size=(600, 400), style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT) # set Left to Right direction (while we don't have localization) self.SetLayoutDirection(wx.Layout_LeftToRight) self.SetBackgroundColour(Colour(self.color_background)) self.SetForegroundColour(Colour(self.color_foreground)) sizer = wx.BoxSizer(orient=wx.VERTICAL) - hwin = LocalHtmlWindow(self, size=(400, 200)) - hwin.set_content(f"New version {uversion} available from {url}
" - f"See this version {url}
" + f"{SPC}See this version Release Notes

" - f"You can update with the command:
pip install -U robotframework-ride" - f"

See the latest development {self._command}" + f"

{SPC}Or, click Upgrade Now.
" + f"{SPC}After upgrade you will see another dialog informing to close this RIDE instance." + f"

{SPC}See the latest development
CHANGELOG") irep = hwin.GetInternalRepresentation() hwin.SetSize((irep.GetWidth()+25, irep.GetHeight()+20)) @@ -228,8 +239,11 @@ def __init__(self, uversion, url, settings): self.CentreOnParent(wx.BOTH) self.Fit() self.SetFocus() - self.ShowModal() - self.Destroy() + if modal: + self.ShowModal() + self.Destroy() + else: + self.Show() def on_remind_me_later(self, event): _ = event diff --git a/src/robotide/context/__init__.py b/src/robotide/context/__init__.py index 9350b501f..a7053ba6d 100644 --- a/src/robotide/context/__init__.py +++ b/src/robotide/context/__init__.py @@ -356,6 +356,14 @@ def bind_keys_to_evt_menu(target, actions): CtrlCmd-Shift-G Find previous search result + + CtrlCmd-Z + Undo + + + CtrlCmd-Y + Redo + CtrlCmd-1 Make scalar variable body diff --git a/src/robotide/editor/texteditor.py b/src/robotide/editor/texteditor.py index c96e70536..b15426522 100644 --- a/src/robotide/editor/texteditor.py +++ b/src/robotide/editor/texteditor.py @@ -89,8 +89,8 @@ def f(event): if IS_MAC: # Mac needs this key binding self.register_shortcut('CtrlCmd-A', focused(lambda e: self._editor.select_all())) - self.register_shortcut('CtrlCmd-V', focused(lambda e: self._editor.paste())) - # IS_WINDOWS and Linux does not need this key binding + # No system needs this key binding, because is already global + # self.register_shortcut('CtrlCmd-V', focused(lambda e: self._editor.paste())) # self.register_shortcut('CtrlCmd-S', focused(lambda e: self.on_saving(e))) self.register_shortcut('CtrlCmd-F', focused(lambda e: self._editor.search_field.SetFocus())) # To avoid double actions these moved to on_key_down @@ -276,7 +276,7 @@ def validate_and_update(self, data, text): data.update_from(data.format_text(m_text)) else: # DEBUG: This is the area where we will implement to not reformat code - data.update_from(text) + data.update_from(m_text) # There is no way to update the model without reformatting # DEBUG: this only updates the editor, but not the model, changes in Text Editor are not reflected # in Grid or when saving diff --git a/src/robotide/postinstall/__main__.py b/src/robotide/postinstall/__main__.py index 013fdec92..130f677dc 100755 --- a/src/robotide/postinstall/__main__.py +++ b/src/robotide/postinstall/__main__.py @@ -67,7 +67,7 @@ def verify_install(): class MessageDialog(RIDEDialog): - def __init__(self, parent, message, title, ttl=10): + def __init__(self, parent, message, title, ttl=10, no_default=False): RIDEDialog.__init__(self, title=title, parent=parent, size=(300, 200)) self.CenterOnScreen(wx.BOTH) @@ -82,7 +82,7 @@ def __init__(self, parent, message, title, ttl=10): vbox.Add(self.settimetolivemsg, 0, wx.ALIGN_CENTER | wx.TOP, 10) self.SetSizer(vbox) self.SetAffirmativeId(wx.ID_OK) - self._create_buttons(None) + self._create_buttons(None, no_default) self.SetBackgroundColour(Colour(self.color_background)) self.SetForegroundColour(Colour(self.color_foreground)) self.timer = wx.Timer(self) @@ -118,8 +118,11 @@ def on_timer(self, evt): self.timer.Stop() self.EndModal(wx.ID_NO) - def _create_buttons(self, sizer): - buttons = self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL) + def _create_buttons(self, sizer, no_default=False): + flags = wx.OK | wx.CANCEL + if no_default: + flags |= wx.NO_DEFAULT + buttons = self.CreateStdDialogButtonSizer(flags) self.SetBackgroundColour(Colour(self.color_background)) self.SetForegroundColour(Colour(self.color_foreground)) for item in self.GetChildren(): @@ -131,14 +134,15 @@ def _create_buttons(self, sizer): self.Sizer.Add(buttons, flag=wx.ALIGN_CENTER | wx.ALL, border=5) -def _askyesno(title, message, frame=None): +def _askyesno(title, message, frame=None, no_default=False): if frame is None: _ = wx.App() parent = wx.Frame(None, size=(0, 0)) else: parent = wx.Frame(frame, size=(0, 0)) parent.CenterOnScreen() - dlg = MessageDialog(parent, message, title, ttl=8) + dlg = MessageDialog(parent, message, title, ttl=8, no_default=no_default) + dlg.Fit() result = dlg.ShowModal() in [wx.ID_YES, wx.ID_OK] print("Result %s" % result) if dlg: diff --git a/src/robotide/version.py b/src/robotide/version.py index 886cf1c16..245153cee 100644 --- a/src/robotide/version.py +++ b/src/robotide/version.py @@ -14,4 +14,4 @@ # limitations under the License. # # Automatically generated by `tasks.py`. -VERSION = 'v2.0.8dev23' +VERSION = 'v2.0.8dev24' diff --git a/utest/application/test_updatenotifier.py b/utest/application/test_updatenotifier.py index 9ed9e1575..a4b4a8f70 100644 --- a/utest/application/test_updatenotifier.py +++ b/utest/application/test_updatenotifier.py @@ -16,9 +16,11 @@ import unittest import time import urllib + +import pytest import wx -from robotide.application.updatenotifier import UpdateNotifierController +from robotide.application.updatenotifier import UpdateNotifierController, UpdateDialog CHECKFORUPDATES = 'check for updates' LASTUPDATECHECK = 'last update check' @@ -185,6 +187,15 @@ def test_forced_check_development_ok(self): self.assertTrue(settings[CHECKFORUPDATES]) self.assertFalse(self._callback_called) + def test_normal_update_dialog(self): + """ This is not actually doing a test """ + app = wx.App() + settings = self.internal_settings() + ctrl=UpdateDialog('1.0.0', 'http://localhost', settings, False) + wx.CallLater(3000, ctrl.EndModal,wx.CANCEL) + ctrl.ShowModal() + ctrl.Destroy() + if __name__ == '__main__': unittest.main() diff --git a/utest/resources/fake.cfg b/utest/resources/fake.cfg index 9847987a0..90fe4e8b6 100644 --- a/utest/resources/fake.cfg +++ b/utest/resources/fake.cfg @@ -2,4 +2,6 @@ auto imports = [] pythonpath = [] global_settings = [] +excludes = None +txt number of spaces = 2 [Plugins]