pyqt-code-editor 0.0.46__tar.gz → 0.0.48__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/PKG-INFO +1 -1
  2. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/__init__.py +1 -1
  3. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/app.py +4 -0
  4. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/editor_panel.py +11 -3
  5. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/settings_panel.py +1 -1
  6. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/base.py +7 -0
  7. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/file_link.py +21 -20
  8. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/tabbed_editor.py +13 -9
  9. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/COPYING +0 -0
  10. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyproject.toml +0 -0
  11. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/_settings.py +0 -0
  12. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/__init__.py +0 -0
  13. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/code_editors.py +0 -0
  14. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/languages/__init__.py +0 -0
  15. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/languages/generic.py +0 -0
  16. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/languages/javascript.py +0 -0
  17. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/languages/markdown.py +0 -0
  18. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/languages/python.py +0 -0
  19. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/code_editors/languages/text.py +0 -0
  20. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/__init__.py +0 -0
  21. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/find_in_files.py +0 -0
  22. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/jupyter_console.py +0 -0
  23. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/project_explorer.py +0 -0
  24. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/sigmund.py +0 -0
  25. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/components/workspace_explorer.py +0 -0
  26. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/environment_manager.py +0 -0
  27. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/__init__.py +0 -0
  28. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/auto_indent.py +0 -0
  29. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/auto_pair.py +0 -0
  30. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/check.py +0 -0
  31. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/comment.py +0 -0
  32. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/complete.py +0 -0
  33. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/execute.py +0 -0
  34. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/line_number.py +0 -0
  35. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/python_auto_indent.py +0 -0
  36. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/search_replace.py +0 -0
  37. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/shortcuts.py +0 -0
  38. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/smart_backspace_delete.py +0 -0
  39. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/symbols.py +0 -0
  40. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/theme.py +0 -0
  41. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/widgets/__init__.py +0 -0
  42. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/mixins/zoom.py +0 -0
  43. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/sigmund-analyst.png +0 -0
  44. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/signal_router.py +0 -0
  45. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/syntax_highlighters/__init__.py +0 -0
  46. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/syntax_highlighters/languages/__init__.py +0 -0
  47. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/syntax_highlighters/languages/generic.py +0 -0
  48. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/syntax_highlighters/languages/python.py +0 -0
  49. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/syntax_highlighters/syntax_highlighter.py +0 -0
  50. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/themes.py +0 -0
  51. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/utils/__init__.py +0 -0
  52. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/utils/languages/__init__.py +0 -0
  53. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/utils/languages/python/__init__.py +0 -0
  54. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/utils/languages/python/_auto_indent.py +0 -0
  55. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/utils/languages/python/_extract_cells.py +0 -0
  56. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/utils/languages/python/_mask_str_in_code.py +0 -0
  57. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/watchdog.py +0 -0
  58. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/__init__.py +0 -0
  59. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/calltip_widget.py +0 -0
  60. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/completion_popup.py +0 -0
  61. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/dock.py +0 -0
  62. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/quick_open_dialog.py +0 -0
  63. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/quick_open_file_dialog.py +0 -0
  64. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/quick_symbol_dialog.py +0 -0
  65. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/search_replace_frame.py +0 -0
  66. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/widgets/tab_splitter.py +0 -0
  67. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/__init__.py +0 -0
  68. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/languages/__init__.py +0 -0
  69. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/languages/generic.py +0 -0
  70. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/languages/python.py +0 -0
  71. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/manager.py +0 -0
  72. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/process.py +0 -0
  73. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/providers/__init__.py +0 -0
  74. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/providers/codestral.py +0 -0
  75. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/providers/jedi.py +0 -0
  76. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/providers/ruff.py +0 -0
  77. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/providers/sigmund.py +0 -0
  78. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/providers/symbol.py +0 -0
  79. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/pyqt_code_editor/worker/settings.py +0 -0
  80. {pyqt_code_editor-0.0.46 → pyqt_code_editor-0.0.48}/readme.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyqt_code_editor
3
- Version: 0.0.46
3
+ Version: 0.0.48
4
4
  Summary: Fully featured code-editor widgets for PyQt
5
5
  Keywords: code editor,pyqt,ide
6
6
  Author-email: Sebastiaan Mathôt <s.mathot@cogsci.nl>
@@ -2,4 +2,4 @@
2
2
 
3
3
  from ._settings import settings
4
4
 
5
- __version__ = '0.0.46'
5
+ __version__ = '0.0.48'
@@ -37,6 +37,7 @@ class SigmundAnalyst(QMainWindow):
37
37
  # The editor panel provides splittable editor tabs
38
38
  self._editor_panel = EditorPanel()
39
39
  self._editor_panel.open_folder_requested.connect(self._open_folder)
40
+ self._editor_panel.open_file_requested.connect(self._open_file)
40
41
  self.setCentralWidget(self._editor_panel)
41
42
  self._project_explorers = []
42
43
  # Track if project explorers are hidden as a group
@@ -407,6 +408,9 @@ class SigmundAnalyst(QMainWindow):
407
408
  self._project_explorers_hidden = False
408
409
  for explorer in self._project_explorers:
409
410
  explorer.setVisible(True)
411
+
412
+ def _open_file(self, path):
413
+ self._editor_panel.open_file(path)
410
414
 
411
415
  def closeEvent(self, event):
412
416
  # Check if there are unsaved changes, and ask for confirmation if there
@@ -11,6 +11,7 @@ logger = logging.getLogger(__name__)
11
11
  class EditorPanel(QWidget):
12
12
 
13
13
  open_folder_requested = Signal(str)
14
+ open_file_requested = Signal(str)
14
15
 
15
16
  def __init__(self, parent=None, initial_path=None):
16
17
  super().__init__(parent)
@@ -58,6 +59,7 @@ class EditorPanel(QWidget):
58
59
  t.lastTabClosed.connect(self.handle_tabbed_editor_empty)
59
60
  t.tabCloseRequested.connect(self._relabel_tabs)
60
61
  t.open_folder_requested.connect(self.open_folder_requested)
62
+ t.open_file_requested.connect(self.open_file_requested)
61
63
  return t
62
64
 
63
65
  def unsaved_changes(self):
@@ -92,7 +94,7 @@ class EditorPanel(QWidget):
92
94
  settings.current_folder = os.path.dirname(path)
93
95
  self.open_file(path)
94
96
 
95
- def _keep_track_of_active_editor(self, editor):
97
+ def _keep_track_of_active_editor(self, editor):
96
98
  logger.info(f"active editor = {editor}")
97
99
  self._active_editor = editor
98
100
  self._active_tab_widget = self._active_editor.parent().parent()
@@ -226,8 +228,14 @@ class EditorPanel(QWidget):
226
228
  return find_first_tab_widget(self)
227
229
 
228
230
  def active_editor(self):
229
- if self._active_editor and self._active_editor.isVisible():
230
- return self._active_editor
231
+ try:
232
+ if self._active_editor and self._active_editor.isVisible():
233
+ return self._active_editor
234
+ except RuntimeError:
235
+ # This may happen when an editor has been closed, causing Qt to
236
+ # delete it, while the _active_editor property hasn't been properly
237
+ # updated.
238
+ pass
231
239
  active_tab_widget = self.active_tab_widget()
232
240
  if active_tab_widget is None:
233
241
  return None
@@ -104,7 +104,7 @@ class SettingsWidget(QWidget):
104
104
 
105
105
  elif isinstance(value, int):
106
106
  widget = QSpinBox()
107
- widget.setRange(-9999, 9999) # Reasonable default range
107
+ widget.setRange(int(-1e9), int(1e9)) # Reasonable default range
108
108
  widget.setValue(value)
109
109
  widget.valueChanged.connect(lambda val, name=setting_name:
110
110
  self.update_setting(name, val))
@@ -50,6 +50,13 @@ class Base:
50
50
  for example to avoid certain keypresses from being consumed.
51
51
  """
52
52
  return False
53
+
54
+ def setFocus(self):
55
+ """Allows managing widgets, such as the editor panel, to keep track of
56
+ which editor is active
57
+ """
58
+ super().setFocus()
59
+ self.received_focus.emit(self)
53
60
 
54
61
  def focusInEvent(self, event):
55
62
  """Allows managing widgets, such as the editor panel, to keep track of
@@ -42,29 +42,30 @@ class FileLink:
42
42
  # Check file size
43
43
  file_size = path.stat().st_size
44
44
  is_large = file_size > settings.max_file_size
45
-
46
- raw_data = path.read_bytes()
47
45
  encoding_unknown = False
48
46
 
49
- if encoding is None:
50
- # First see if everything is within ASCII range
51
- try:
52
- raw_data.decode("utf-8")
53
- # If no error -> it's strictly ASCII, so decode as UTF-8
54
- used_encoding = "utf-8"
55
- except UnicodeDecodeError:
56
- # Not pure ASCII; let chardet pick
57
- detect_result = chardet.detect(raw_data)
58
- # If detection fails or returns None, or confidence is low
59
- if (detect_result is None or
60
- detect_result.get("encoding") is None or
61
- detect_result.get("confidence", 0) < 0.7):
47
+ if not is_large:
48
+ raw_data = path.read_bytes()
49
+
50
+ if encoding is None:
51
+ # First see if everything is within ASCII range
52
+ try:
53
+ raw_data.decode("utf-8")
54
+ # If no error -> it's strictly ASCII, so decode as UTF-8
62
55
  used_encoding = "utf-8"
63
- encoding_unknown = True
64
- else:
65
- used_encoding = detect_result["encoding"]
66
- else:
67
- used_encoding = encoding
56
+ except UnicodeDecodeError:
57
+ # Not pure ASCII; let chardet pick
58
+ detect_result = chardet.detect(raw_data)
59
+ # If detection fails or returns None, or confidence is low
60
+ if (detect_result is None or
61
+ detect_result.get("encoding") is None or
62
+ detect_result.get("confidence", 0) < 0.7):
63
+ used_encoding = "utf-8"
64
+ encoding_unknown = True
65
+ else:
66
+ used_encoding = detect_result["encoding"]
67
+ else:
68
+ used_encoding = encoding
68
69
 
69
70
  # Show warning if file is large or encoding is uncertain
70
71
  if is_large or encoding_unknown:
@@ -111,6 +111,7 @@ class TabbedEditor(QTabWidget):
111
111
  """A tab widget that can hold multiple CodeEditor instances."""
112
112
  lastTabClosed = Signal(QTabWidget)
113
113
  open_folder_requested = Signal(str)
114
+ open_file_requested = Signal(str)
114
115
 
115
116
  def __init__(self, parent=None):
116
117
  super().__init__(parent)
@@ -312,6 +313,14 @@ class TabbedEditor(QTabWidget):
312
313
  event.ignore()
313
314
 
314
315
  def dropEvent(self, event):
316
+ # Insert the tab at the position that the user dropped on
317
+ dropPos = event.position().toPoint()
318
+ tabBar = self.tabBar()
319
+ index = tabBar.tabAt(dropPos)
320
+ if index < 0:
321
+ # If the user dropped to the right of all existing tabs
322
+ index = self.count()
323
+ logger.info(f'dropping on tab index {index}')
315
324
  # If a file is dropped, open it in a new tab
316
325
  if event.mimeData().hasUrls():
317
326
  for url in event.mimeData().urls():
@@ -321,7 +330,10 @@ class TabbedEditor(QTabWidget):
321
330
  if os.path.isdir(path):
322
331
  self.open_folder_requested.emit(path)
323
332
  else:
324
- self.add_code_editor(path)
333
+ # Change the focus to the widget that is dopped to make
334
+ # sure the file is opened in the right panel
335
+ self.widget(min(self.count() - 1, index)).setFocus()
336
+ self.open_file_requested.emit(path)
325
337
 
326
338
  if not event.mimeData().hasFormat("application/x-tabdata"):
327
339
  event.ignore()
@@ -346,14 +358,6 @@ class TabbedEditor(QTabWidget):
346
358
  editor.modification_changed.connect(self._on_modification_changed)
347
359
  editor.file_name_changed.connect(self._on_file_name_changed)
348
360
  logger.info("dropping editor")
349
-
350
- # Insert the tab at the position that the user dropped on
351
- dropPos = event.position().toPoint()
352
- tabBar = self.tabBar()
353
- index = tabBar.tabAt(dropPos)
354
- if index < 0:
355
- # If the user dropped to the right of all existing tabs
356
- index = self.count()
357
361
 
358
362
  self.insertTab(index, editor, tabText)
359
363
  self.setCurrentIndex(index)