Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ All notable changes to this project will be documented in this file.
The format is based on http://keepachangelog.com/en/1.0.0/[Keep a Changelog]
and this project adheres to http://semver.org/spec/v2.0.0.html[Semantic Versioning].

// == https://github.com/robotframework/RIDE[Unreleased]
== https://github.com/robotframework/RIDE[Unreleased]

=== Added
- Added divided Status Bar. Left side for main window, right side for Plugins. Working example in Text Editor,
when selecting in Tree shows the filename in StatusBar.

=== Changed
- On Windows ignore false modification on files when opening Test Suites, causing confirmation dialog.

== https://github.com/robotframework/RIDE/blob/master/doc/releasenotes/ride-2.1.3.rst[2.1.3] - 2025-03-24

Expand Down
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Likewise, the current version of wxPython, is 4.2.2, but RIDE is known to work w

`pip install -U robotframework-ride`

(3.8 <= python <= 3.13) Install current development version (**2.2dev15**) with:
(3.8 <= python <= 3.13) Install current development version (**2.2dev16**) with:

`pip install -U https://github.com/robotframework/RIDE/archive/develop.zip`

Expand Down
109 changes: 57 additions & 52 deletions src/robotide/application/CHANGELOG.html

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/robotide/application/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class RIDE(wx.App):
def __init__(self, path=None, updatecheck=True, settingspath=None):
self._updatecheck = updatecheck
self.workspace_path = path
self.changed_workspace = False
self.settings_path = settingspath
context.APP = self
wx.App.__init__(self, redirect=False)
Expand Down Expand Up @@ -401,7 +402,7 @@ def OnEventLoopEnter(self, loop): # Overrides wx method
def on_app_activate(self, event):
if self.workspace_path is not None and RideFSWatcherHandler.is_watcher_created():
if event.GetActive():
if RideFSWatcherHandler.is_workspace_dirty():
if not self.changed_workspace and RideFSWatcherHandler.is_workspace_dirty():
self.frame.show_confirm_reload_dlg(event)
RideFSWatcherHandler.stop_listening()
else:
Expand Down
22 changes: 6 additions & 16 deletions src/robotide/application/releasenotes.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ def set_content(self, html_win, content):

<p><a class="reference external" href="https://github.com/robotframework/RIDE/">RIDE (Robot Framework IDE)</a>
{VERSION} is a new release with some enhancements and bug fixes. The reference for valid arguments is
<a class="reference external" href="https://robotframework.org/">Robot Framework</a> previous version, which was 7.1.1
(currently is 7.2.2). However, internal library code is originally based on version 3.1.2, but adapted for new versions.</p>
<a class="reference external" href="https://robotframework.org/">Robot Framework</a> current version, 7.2.2. However,
internal library code is originally based on version 3.1.2, but adapted for new versions.</p>
<ul class="simple">
<li>This version supports Python 3.8 up to 3.13.</li>
<li>There are some changes, or known issues:<ul>
Expand All @@ -168,19 +168,9 @@ def set_content(self, html_win, content):
</ul>
<p><strong>New Features and Fixes Highlights</strong></p>
<ul class="simple">
<li>Better Search element in Text Editor which allows to be cleared.</li>
<li>When saving in Text Editor, the cursor remains at position, instead of jumping to Tree selection.</li>
<li>Improved autocompletion lists, by using existing words in Test Suite file (still needs more improvements).</li>
<li>Fixed not set text color on row labels in Grid Editor. Now the General <b>secondary foreground</b> is applied.</li>
<li>Added on Text Editor, tab indentation markers and <b>tab markers</b> boolean setting with default <b>True</b>.</li>
<li>Added on Text Editor, folding margin with markers style configurable with <b>fold symbols</b> in settings.cfg.</li>
<li>Create directories when needed in New Project dialog.</li>
<li>Improved the recognition of BDD/Gherkin prefixes when localized in autocomplete on Grid Editor.</li>
<li>Added syntax colorization for the <em>GROUP</em> marker. Improved colorization for multiple Gherkin words, for
example in the French language.</li>
<li>Fixed multiple scroll bars in Grid Editor when editing Test Cases or Keywords. This caused bad navigation on cells.</li>
<li>Regression fix from v2.1b1 - Fix wrong item selection, like Test Suite, when doing right-click actions in
Project Explorer.</li>
<li>On Windows ignore false modification on files when opening Test Suites, causing confirmation dialog.</li>
<li>Added divided Status Bar. Left side for main window, right side for Plugins. Working example in Text Editor,
when selecting in Tree shows the filename in StatusBar.</li>
</ul>
<!-- <p>We hope to implement or complete features and make fixes on next major version 2.1 (in mid Autumm of 2024).</p>
-->
Expand Down Expand Up @@ -235,7 +225,7 @@ def set_content(self, html_win, content):
<pre class="literal-block">python -m robotide.postinstall -install</pre>
<p>or</p>
<pre class="literal-block">ride_postinstall.py -install</pre>
<p>RIDE {VERSION} was released on 25/March/2025.</p>
<p>RIDE {VERSION} was released on 28/March/2025.</p>
<!-- <br/>
<h3>May The Fourth Be With You!</h3>
<h3>Celebrate the bank holiday, 10th June, Day of Portugal, Portuguese Communities and Camões!!</h3>
Expand Down
14 changes: 10 additions & 4 deletions src/robotide/editor/texteditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from ..preferences.editors import read_fonts
from ..publish import RideSettingsChanged, PUBLISHER
from ..publish.messages import RideMessage
from ..widgets import TextField, Label, HtmlDialog
from ..widgets import SearchField, Label, HtmlDialog
from ..widgets import VerticalSizer, HorizontalSizer, ButtonWithHandler, RIDEDialog

from robotide.lib.compat.parsing.language import Language
Expand Down Expand Up @@ -386,6 +386,8 @@ def __init__(self, application):
self._doc_language = None
self._save_flag = 0
self.jump = True
# self.status_bar = self.frame.FindWindowByName("StatusBar", self.frame)
# self.frame.SetStatusBarPane(1)
self.reformat = application.settings.get('reformat', False)
self._register_shortcuts()

Expand Down Expand Up @@ -459,6 +461,7 @@ def _open(self):
# print(f"DEBUG: texteditor _open language={self._doc_language}")
self._open_data_for_controller(datafile_controller)
self._editor.store_position()
wx.CallLater(2000, self.statusbar_message, f'{_("Source: ")}{self._editor.datafile_controller.source}', 2000)

def _get_shared_doc_lang(self):
try:
Expand Down Expand Up @@ -1013,7 +1016,7 @@ def _create_editor_toolbar(self):
def _create_search(self, container_sizer):
container_sizer.AddSpacer(5)
size = wx.Size(200, 32)
self.search_field = TextField(self, '', size=size, process_enters=True)
self.search_field = SearchField(self, '', size=size, process_enters=True)
self.search_field.SetBackgroundColour(Colour(self.dlg.color_secondary_background))
self.search_field.SetForegroundColour(Colour(self.dlg.color_secondary_foreground))
self.search_field.Bind(wx.EVT_TEXT_ENTER, self.on_find)
Expand Down Expand Up @@ -1116,8 +1119,10 @@ def language(self, flanguage):

def on_find(self, event, forward=True):
if self.source_editor:
if event.GetEventType() != wx.wxEVT_TEXT_ENTER: # Was getting selected item from Tree
text = self.source_editor.GetSelectedText() or event.GetString()
if event.GetEventType() == wx.wxEVT_SEARCH:
text = event.GetString()
elif event.GetEventType() != wx.wxEVT_TEXT_ENTER: # Was getting selected item from Tree
text = self.source_editor.GetSelectedText()
else:
text = ''
if (len(text) > 0 and text.lower() != self.search_field.GetValue().lower() and
Expand Down Expand Up @@ -1372,6 +1377,7 @@ def open(self, data):
if hasattr(self._data, 'content'): # Special case for unit test
self.source_editor.set_text(self._data.content)
self.set_editor_caret_position()
wx.CallAfter(self.plugin.statusbar_message, f'{_("Source: ")}{self._controller_for_context.source}', 4000)
self._words_cache.clear()
self._suggestions.update_from_local(self.words_cache(self.source_editor.GetLineCount()), self.language)

Expand Down
55 changes: 44 additions & 11 deletions src/robotide/lib/compat/pygments/robotframework.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,10 @@ def __init__(self, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_','-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = ['En']
else:
self.new_lang = new_lang
self._index = 0
Expand Down Expand Up @@ -286,7 +289,10 @@ def __init__(self, template_setter=None, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_','-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
pass
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down Expand Up @@ -356,7 +362,10 @@ def __init__(self, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand All @@ -380,7 +389,10 @@ def __init__(self, template_setter=None, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down Expand Up @@ -427,7 +439,10 @@ def __init__(self, template_setter=None, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down Expand Up @@ -465,7 +480,10 @@ def __init__(self, support_assign=True, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down Expand Up @@ -496,7 +514,10 @@ def __init__(self, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down Expand Up @@ -535,7 +556,10 @@ def __init__(self, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand All @@ -561,7 +585,10 @@ def __init__(self, prev_tokenizer=None, new_lang=None):
set_lang = shared_memory.ShareableList(name="language")
except FileNotFoundError:
set_lang = ['En']
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_','-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down Expand Up @@ -621,7 +648,10 @@ def __init__(self, template_setter, prev_tokenizer=None, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down Expand Up @@ -666,7 +696,10 @@ def __init__(self, prev_tokenizer=None, new_lang=None):
if self.new_lang is None:
if new_lang is None:
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_', '-'))
except ValueError:
self.new_lang = None
else:
self.new_lang = new_lang
if self.new_lang is None:
Expand Down
5 changes: 4 additions & 1 deletion src/robotide/namespace/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,10 @@ def __init__(self, keywords, caseless=True, new_lang=None):
set_lang = shared_memory.ShareableList(new_lang, name="language")
except FileExistsError: # Other instance created file
set_lang = shared_memory.ShareableList(name="language")
self.new_lang = Language.from_name(set_lang[0].replace('_','-'))
try:
self.new_lang = Language.from_name(set_lang[0].replace('_','-'))
except ValueError:
self.new_lang = new_lang
else:
self.new_lang = new_lang
self.normalized_bdd_prefixes = utils.normalize_pipe_list(list(self.new_lang.bdd_prefixes), spaces=False)
Expand Down
25 changes: 25 additions & 0 deletions src/robotide/pluginapi/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class Plugin(object):
filemgr = property(lambda self: self.__frame.filemgr, doc='Provides access to the files and folders explorer')
menubar = property(lambda self: self.__frame.GetMenuBar(), doc='Provides access to the application menubar')
toolbar = property(lambda self: self.__frame.GetToolBar(), doc='Provides access to the application toolbar')
statusbar = property(lambda self: self.__frame.FindWindowByName("StatusBar", self.__frame),
doc='Provides access to the application statusbar')
notebook = property(lambda self: self.__frame.notebook, doc='Provides access to the tabbed notebook')
model = property(lambda self: self.__app.model, doc='Provides access to the data model')
frame = property(lambda self: self.__frame, doc='Reference to the RIDE main frame')
Expand Down Expand Up @@ -448,3 +450,26 @@ def highlight(self, data, text):
if not self.tree:
return
self.tree.highlight(data, text)

def statusbar_message(self, text, ttl=0):
"""Set a text message at Plugin area of StatusBar
:Parameters:
text
Message to show in StatusBar
ttl
Time to live in milliseconds, default = 0, means does not expire
"""
if text is None:
text = ''
self.statusbar.SetStatusText(text, 1)
wx.CallAfter(self._delayed_clear, ttl)

def _delayed_clear(self, ttl):
if ttl >= 100:
from time import sleep
sleep(ttl/1000)
self.statusbar.SetStatusText('', 1)

def statusbar_clear(self):
"""Clears the message at Plugin area of StatusBar"""
self.statusbar.SetStatusText('', 1)
20 changes: 14 additions & 6 deletions src/robotide/ui/mainframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from .treeplugin import Tree
from ..action import action_info_collection, action_factory, SeparatorInfo
from ..action.shortcut import localize_shortcuts
from ..context import get_about_ride, SHORTCUT_KEYS
from ..context import get_about_ride, SHORTCUT_KEYS, IS_WINDOWS
from ..controller.ctrlcommands import SaveFile, SaveAll
from ..editor import customsourceeditor
from ..preferences import PreferenceEditor
Expand Down Expand Up @@ -289,14 +289,15 @@ def _init_ui(self):

# self.main_menu.take_menu_bar_into_use()
if new_ui: # Only when creating UI we add panes
self.CreateStatusBar(name="StatusBar")
self.CreateStatusBar(number=2, name="StatusBar")
self._status_bar = self.FindWindowByName("StatusBar", self)
if self._status_bar:
self._status_bar.SetFont(wx.Font(self.fontinfo))
self._status_bar.SetBackgroundColour(Colour(self.color_background))
self._status_bar.SetForegroundColour(Colour(self.color_foreground))
# set main frame icon
self.SetIcons(self._image_provider.PROGICONS)
if self._status_bar:
self.SetStatusBarPane(0)
self._status_bar.SetFont(wx.Font(self.fontinfo))
self._status_bar.SetBackgroundColour(Colour(self.color_background))
self._status_bar.SetForegroundColour(Colour(self.color_foreground))
# change notebook theme
self.set_notebook_theme()
# tell the manager to "commit" all the changes just made
Expand Down Expand Up @@ -497,6 +498,8 @@ def open_suite(self, path):
# self._controller.default_dir will only save dir path
# need to save path to self._application.workspace_path too
self._application.workspace_path = path
if IS_WINDOWS:
self._application.changed_workspace = True
from ..lib.compat.parsing.language import check_file_language
self.controller.file_language = check_file_language(path)
set_lang = []
Expand All @@ -519,8 +522,13 @@ def open_suite(self, path):
except UserWarning:
return False
self._populate_tree()
if IS_WINDOWS:
wx.CallLater(60000, self.clear_workspace_state)
return True

def clear_workspace_state(self):
self._application.changed_workspace = False

def refresh_datafile(self, item, event):
self.tree.refresh_datafile(item, event)
if self.filemgr:
Expand Down
Loading