PrEditor 0.1.0rc2__py2.py3-none-any.whl → 0.3.0__py2.py3-none-any.whl

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.

Potentially problematic release.


This version of PrEditor might be problematic. Click here for more details.

@@ -37,6 +37,8 @@ from .. import (
37
37
  )
38
38
  from ..delayable_engine import DelayableEngine
39
39
  from ..gui import Dialog, Window, loadUi
40
+ from ..gui.fuzzy_search.fuzzy_search import FuzzySearch
41
+ from ..gui.group_tab_widget.grouped_tab_models import GroupTabListItemModel
40
42
  from ..logging_config import LoggingConfig
41
43
  from ..utils import stylesheets
42
44
  from .completer import CompleterMode
@@ -55,7 +57,7 @@ class LoggerWindow(Window):
55
57
  _instance = None
56
58
  styleSheetChanged = Signal(str)
57
59
 
58
- def __init__(self, parent, name=None, run_workbox=False):
60
+ def __init__(self, parent, name=None, run_workbox=False, standalone=False):
59
61
  super(LoggerWindow, self).__init__(parent=parent)
60
62
  self.name = name if name else DEFAULT_CORE_NAME
61
63
  self.aboutToClearPathsEnabled = False
@@ -103,11 +105,17 @@ class LoggerWindow(Window):
103
105
  )
104
106
  self.uiConsoleTOOLBAR.insertSeparator(self.uiRunSelectedACT)
105
107
 
108
+ # Configure Find in Workboxes
109
+ self.uiFindInWorkboxesWGT.hide()
110
+ self.uiFindInWorkboxesWGT.managers.append(self.uiWorkboxTAB)
111
+ self.uiFindInWorkboxesWGT.console = self.console()
112
+
106
113
  # Initial configuration of the logToFile feature
107
114
  self._logToFilePath = None
108
115
  self._stds = None
109
116
  self.uiLogToFileClearACT.setVisible(False)
110
117
 
118
+ self.uiRestartACT.triggered.connect(self.restartLogger)
111
119
  self.uiCloseLoggerACT.triggered.connect(self.closeLogger)
112
120
 
113
121
  self.uiRunAllACT.triggered.connect(self.execAll)
@@ -179,6 +187,8 @@ class LoggerWindow(Window):
179
187
  self.uiGroup8ACT.triggered.connect(partial(self.gotoGroupByIndex, 8))
180
188
  self.uiGroupLastACT.triggered.connect(partial(self.gotoGroupByIndex, -1))
181
189
 
190
+ self.uiFocusNameACT.triggered.connect(self.show_focus_name)
191
+
182
192
  self.uiCommentToggleACT.triggered.connect(self.comment_toggle)
183
193
 
184
194
  self.uiSpellCheckEnabledACT.toggled.connect(self.setSpellCheckEnabled)
@@ -218,6 +228,7 @@ class LoggerWindow(Window):
218
228
  QIcon(resourcePath('img/content-save.png'))
219
229
  )
220
230
  self.uiAboutPreditorACT.setIcon(QIcon(resourcePath('img/information.png')))
231
+ self.uiRestartACT.setIcon(QIcon(resourcePath('img/restart.svg')))
221
232
  self.uiCloseLoggerACT.setIcon(QIcon(resourcePath('img/close-thick.png')))
222
233
 
223
234
  # Make action shortcuts available anywhere in the Logger
@@ -267,6 +278,10 @@ class LoggerWindow(Window):
267
278
 
268
279
  self.setup_run_workbox()
269
280
 
281
+ if not standalone:
282
+ # This action only is valid when running in standalone mode
283
+ self.uiRestartACT.setVisible(False)
284
+
270
285
  # Run the current workbox after the LoggerWindow is shown.
271
286
  if run_workbox:
272
287
  # By using two singleShot timers, we can show and draw the LoggerWindow,
@@ -305,7 +320,61 @@ class LoggerWindow(Window):
305
320
  return self.uiWorkboxTAB.current_groups_widget()
306
321
 
307
322
  @classmethod
308
- def run_workbox(cls, indicator):
323
+ def name_for_workbox(cls, workbox):
324
+ """Returns the name for a given workbox.
325
+ The name is the group tab text and the workbox tab text joined by a `/`"""
326
+ ret = []
327
+ logger = cls.instance()
328
+ index = logger.uiWorkboxTAB.currentIndex()
329
+ ret.append(logger.uiWorkboxTAB.tabText(index))
330
+ group_widget = logger.uiWorkboxTAB.currentWidget()
331
+ index = group_widget.currentIndex()
332
+ ret.append(group_widget.tabText(index))
333
+ return "/".join(ret)
334
+
335
+ @classmethod
336
+ def workbox_for_name(cls, name, show=False, visible=False):
337
+ """Used to find a workbox for a given name. It accepts a string matching
338
+ the "{group}/{workbox}" format, or if True, the current workbox.
339
+
340
+ Args:
341
+ name(str, boolean): Used to define which workbox to run.
342
+ show (bool, optional): If a workbox is found, call `__show__` on it
343
+ to ensure that it is initialized and its text is loaded.
344
+ visible (bool, optional): Make the this workbox visible if found.
345
+ """
346
+ logger = cls.instance()
347
+
348
+ workbox = None
349
+
350
+ # If name is True, run the current workbox
351
+ if isinstance(name, bool):
352
+ if name:
353
+ workbox = logger.current_workbox()
354
+
355
+ # If name is a string, find first tab with that name
356
+ elif isinstance(name, six.string_types):
357
+ split = name.split('/', 1)
358
+ if len(split) < 2:
359
+ return None
360
+ group, editor = split
361
+ group_index = logger.uiWorkboxTAB.index_for_text(group)
362
+ if group_index != -1:
363
+ tab_widget = logger.uiWorkboxTAB.widget(group_index)
364
+ index = tab_widget.index_for_text(editor)
365
+ if index != -1:
366
+ workbox = tab_widget.widget(index)
367
+ if visible:
368
+ tab_widget.setCurrentIndex(index)
369
+ logger.uiWorkboxTAB.setCurrentIndex(group_index)
370
+
371
+ if show and workbox:
372
+ workbox.__show__()
373
+
374
+ return workbox
375
+
376
+ @classmethod
377
+ def run_workbox(cls, name):
309
378
  """This is a function which will be added to __main__, and therefore
310
379
  available to PythonLogger users. It will accept a string matching the
311
380
  "{group}/{workbox}" format, or a boolean that will run the current tab
@@ -313,7 +382,7 @@ class LoggerWindow(Window):
313
382
  current workbox on launch.
314
383
 
315
384
  Args:
316
- indicator(str, boolean): Used to define which workbox to run.
385
+ name(str, boolean): Used to define which workbox to run.
317
386
 
318
387
  Raises:
319
388
  Exception: "Cannot call current workbox."
@@ -323,30 +392,12 @@ class LoggerWindow(Window):
323
392
  run_workbox('some/stuff.py')
324
393
  (from command line): blurdev launch Python_Logger --run_workbox
325
394
  """
326
- logger = cls.instance()
327
-
328
- # Determine the workbox widget
329
- workbox = None
330
-
331
- # If indicator is True, run the current workbox
332
- if isinstance(indicator, bool):
333
- if indicator:
334
- workbox = logger.current_workbox()
335
-
336
- # If indicator is a string, find first tab with that name
337
- elif isinstance(indicator, six.string_types):
338
- group, editor = indicator.split('/', 1)
339
- index = logger.uiWorkboxTAB.index_for_text(group)
340
- if index != -1:
341
- tab_widget = logger.uiWorkboxTAB.widget(index)
342
- index = tab_widget.index_for_text(editor)
343
- if index != -1:
344
- workbox = tab_widget.widget(index)
395
+ workbox = cls.workbox_for_name(name)
345
396
 
346
397
  if workbox is not None:
347
- # if indicator is True, its ok to run the workbox, this option
398
+ # if name is True, its ok to run the workbox, this option
348
399
  # is passed by the cli to run the current tab
349
- if workbox.hasFocus() and indicator is not True:
400
+ if workbox.hasFocus() and name is not True:
350
401
  raise Exception("Cannot call current workbox.")
351
402
  else:
352
403
  # Make sure the workbox text is loaded as it likely has not
@@ -566,6 +617,10 @@ class LoggerWindow(Window):
566
617
  if self.uiConsoleTOOLBAR.isFloating():
567
618
  self.uiConsoleTOOLBAR.hide()
568
619
 
620
+ # Handle any cleanup each workbox tab may need to do before closing
621
+ for editor, _, _, _, _ in self.uiWorkboxTAB.all_widgets():
622
+ editor.__close__()
623
+
569
624
  def closeLogger(self):
570
625
  self.close()
571
626
 
@@ -630,6 +685,12 @@ class LoggerWindow(Window):
630
685
  'textEditorCmdTempl': self.textEditorCmdTempl,
631
686
  'currentStyleSheet': self._stylesheet,
632
687
  'flash_time': self.uiConsoleTXT.flash_time,
688
+ 'find_files_regex': self.uiFindInWorkboxesWGT.uiRegexBTN.isChecked(),
689
+ 'find_files_cs': (
690
+ self.uiFindInWorkboxesWGT.uiCaseSensitiveBTN.isChecked()
691
+ ),
692
+ 'find_files_context': self.uiFindInWorkboxesWGT.uiContextSPN.value(),
693
+ 'find_files_text': self.uiFindInWorkboxesWGT.uiFindTXT.text(),
633
694
  }
634
695
  )
635
696
 
@@ -664,6 +725,28 @@ class LoggerWindow(Window):
664
725
  with open(filename, 'w') as fp:
665
726
  json.dump(pref, fp, indent=4)
666
727
 
728
+ def restartLogger(self):
729
+ """Closes this PrEditor instance and starts a new process with the same
730
+ cli arguments.
731
+
732
+ Note: This only works if PrEditor is running in standalone mode. It doesn't
733
+ quit the QApplication or other host process. It simply closes this instance
734
+ of PrEditor, saving its preferences, which should allow Qt to exit if no
735
+ other windows are open.
736
+ """
737
+ self.close()
738
+
739
+ # Get the current command and launch it as a new process. This handles
740
+ # use of the preditor/preditor executable launchers.
741
+ cmd = sys.argv[0]
742
+ args = sys.argv[1:]
743
+
744
+ if os.path.basename(cmd) == "__main__.py":
745
+ # Handles using `python -m preditor` style launch.
746
+ cmd = sys.executable
747
+ args = ["-m", "preditor"] + args
748
+ QtCore.QProcess.startDetached(cmd, args)
749
+
667
750
  def restorePrefs(self):
668
751
  pref = self.load_prefs()
669
752
 
@@ -714,6 +797,18 @@ class LoggerWindow(Window):
714
797
  )
715
798
  self.uiErrorHyperlinksACT.setChecked(pref.get('uiErrorHyperlinksACT', True))
716
799
 
800
+ # Find Files settings
801
+ self.uiFindInWorkboxesWGT.uiRegexBTN.setChecked(
802
+ pref.get('find_files_regex', False)
803
+ )
804
+ self.uiFindInWorkboxesWGT.uiCaseSensitiveBTN.setChecked(
805
+ pref.get('find_files_cs', False)
806
+ )
807
+ self.uiFindInWorkboxesWGT.uiContextSPN.setValue(
808
+ pref.get('find_files_context', 3)
809
+ )
810
+ self.uiFindInWorkboxesWGT.uiFindTXT.setText(pref.get('find_files_text', ''))
811
+
717
812
  # External text editor filepath and command template
718
813
  defaultExePath = r"C:\Program Files\Sublime Text 3\sublime_text.exe"
719
814
  defaultCmd = r"{exePath} {modulePath}:{lineNum}"
@@ -755,7 +850,7 @@ class LoggerWindow(Window):
755
850
 
756
851
  def setAutoCompleteEnabled(self, state):
757
852
  self.uiConsoleTXT.completer().setEnabled(state)
758
- for workbox in self.uiWorkboxTAB.all_widgets():
853
+ for workbox, _, _, _, _ in self.uiWorkboxTAB.all_widgets():
759
854
  workbox.__set_auto_complete_enabled__(state)
760
855
 
761
856
  def setSpellCheckEnabled(self, state):
@@ -951,14 +1046,35 @@ class LoggerWindow(Window):
951
1046
  def show_workbox_options(self):
952
1047
  self.uiWorkboxSTACK.setCurrentIndex(WorkboxPages.Options)
953
1048
 
1049
+ @Slot()
1050
+ def show_find_in_workboxes(self):
1051
+ """Ensure the find workboxes widget is visible and has focus."""
1052
+ self.uiFindInWorkboxesWGT.activate()
1053
+
1054
+ @Slot()
1055
+ def show_focus_name(self):
1056
+ model = GroupTabListItemModel(manager=self.uiWorkboxTAB)
1057
+ model.process()
1058
+
1059
+ def update_tab(index):
1060
+ group, tab = model.workbox_indexes_from_model_index(index)
1061
+ if group is not None:
1062
+ self.uiWorkboxTAB.set_current_groups_from_index(group, tab)
1063
+
1064
+ w = FuzzySearch(model, parent=self)
1065
+ w.selected.connect(update_tab)
1066
+ w.canceled.connect(update_tab)
1067
+ w.highlighted.connect(update_tab)
1068
+ w.popup()
1069
+
954
1070
  def updateCopyIndentsAsSpaces(self):
955
- for workbox in self.uiWorkboxTAB.all_widgets():
1071
+ for workbox, _, _, _, _ in self.uiWorkboxTAB.all_widgets():
956
1072
  workbox.__set_copy_indents_as_spaces__(
957
1073
  self.uiCopyTabsToSpacesACT.isChecked()
958
1074
  )
959
1075
 
960
1076
  def updateIndentationsUseTabs(self):
961
- for workbox in self.uiWorkboxTAB.all_widgets():
1077
+ for workbox, _, _, _, _ in self.uiWorkboxTAB.all_widgets():
962
1078
  workbox.__set_indentations_use_tabs__(
963
1079
  self.uiIndentationsTabsACT.isChecked()
964
1080
  )
@@ -1037,7 +1153,9 @@ class LoggerWindow(Window):
1037
1153
  group_tab.setCurrentIndex(index)
1038
1154
 
1039
1155
  @staticmethod
1040
- def instance(parent=None, name=None, run_workbox=False, create=True):
1156
+ def instance(
1157
+ parent=None, name=None, run_workbox=False, create=True, standalone=False
1158
+ ):
1041
1159
  """Returns the existing instance of the PrEditor gui creating it on first call.
1042
1160
 
1043
1161
  Args:
@@ -1046,6 +1164,9 @@ class LoggerWindow(Window):
1046
1164
  run_workbox (bool, optional): If the instance hasn't been created yet, this
1047
1165
  will execute the active workbox's code once fully initialized.
1048
1166
  create (bool, optional): Returns None if the instance has not been created.
1167
+ standalone (bool, optional): Launch PrEditor in standalone mode. This
1168
+ enables extra options that only make sense when it is running as
1169
+ its own app, not inside of another app.
1049
1170
 
1050
1171
  Returns:
1051
1172
  Returns a fully initialized instance of the PrEditor gui. If called more
@@ -1058,7 +1179,9 @@ class LoggerWindow(Window):
1058
1179
  return None
1059
1180
 
1060
1181
  # create the logger instance
1061
- inst = LoggerWindow(parent, name=name, run_workbox=run_workbox)
1182
+ inst = LoggerWindow(
1183
+ parent, name=name, run_workbox=run_workbox, standalone=standalone
1184
+ )
1062
1185
 
1063
1186
  # RV has a Unique window structure. It makes more sense to not parent a
1064
1187
  # singleton window than to parent it to a specific top level window.
@@ -0,0 +1,140 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>uiFindFilesWGT</class>
4
+ <widget class="QWidget" name="uiFindFilesWGT">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>636</width>
10
+ <height>41</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>Form</string>
15
+ </property>
16
+ <layout class="QGridLayout" name="gridLayout">
17
+ <item row="0" column="1">
18
+ <widget class="QLabel" name="uiFindLBL">
19
+ <property name="text">
20
+ <string>Find:</string>
21
+ </property>
22
+ </widget>
23
+ </item>
24
+ <item row="0" column="0">
25
+ <layout class="QHBoxLayout" name="uiFindOptionsLYT">
26
+ <item>
27
+ <widget class="QToolButton" name="uiRegexBTN">
28
+ <property name="toolTip">
29
+ <string>Regex (Alt + R)</string>
30
+ </property>
31
+ <property name="text">
32
+ <string>Regex</string>
33
+ </property>
34
+ <property name="checkable">
35
+ <bool>true</bool>
36
+ </property>
37
+ </widget>
38
+ </item>
39
+ <item>
40
+ <widget class="QToolButton" name="uiCaseSensitiveBTN">
41
+ <property name="toolTip">
42
+ <string>Case Sensitive (Alt + C)</string>
43
+ </property>
44
+ <property name="text">
45
+ <string>Case Sensitive</string>
46
+ </property>
47
+ <property name="checkable">
48
+ <bool>true</bool>
49
+ </property>
50
+ </widget>
51
+ </item>
52
+ <item>
53
+ <widget class="QSpinBox" name="uiContextSPN">
54
+ <property name="toolTip">
55
+ <string># of lines of context to show</string>
56
+ </property>
57
+ <property name="buttonSymbols">
58
+ <enum>QAbstractSpinBox::PlusMinus</enum>
59
+ </property>
60
+ <property name="value">
61
+ <number>2</number>
62
+ </property>
63
+ </widget>
64
+ </item>
65
+ </layout>
66
+ </item>
67
+ <item row="0" column="2">
68
+ <widget class="QLineEdit" name="uiFindTXT"/>
69
+ </item>
70
+ <item row="0" column="3">
71
+ <widget class="QPushButton" name="uiFindBTN">
72
+ <property name="text">
73
+ <string>Find</string>
74
+ </property>
75
+ </widget>
76
+ </item>
77
+ <item row="0" column="4">
78
+ <widget class="QToolButton" name="uiCloseBTN">
79
+ <property name="text">
80
+ <string>x</string>
81
+ </property>
82
+ </widget>
83
+ </item>
84
+ </layout>
85
+ </widget>
86
+ <resources/>
87
+ <connections>
88
+ <connection>
89
+ <sender>uiFindBTN</sender>
90
+ <signal>released()</signal>
91
+ <receiver>uiFindFilesWGT</receiver>
92
+ <slot>find()</slot>
93
+ <hints>
94
+ <hint type="sourcelabel">
95
+ <x>601</x>
96
+ <y>31</y>
97
+ </hint>
98
+ <hint type="destinationlabel">
99
+ <x>421</x>
100
+ <y>29</y>
101
+ </hint>
102
+ </hints>
103
+ </connection>
104
+ <connection>
105
+ <sender>uiFindTXT</sender>
106
+ <signal>returnPressed()</signal>
107
+ <receiver>uiFindFilesWGT</receiver>
108
+ <slot>find()</slot>
109
+ <hints>
110
+ <hint type="sourcelabel">
111
+ <x>488</x>
112
+ <y>23</y>
113
+ </hint>
114
+ <hint type="destinationlabel">
115
+ <x>501</x>
116
+ <y>65</y>
117
+ </hint>
118
+ </hints>
119
+ </connection>
120
+ <connection>
121
+ <sender>uiCloseBTN</sender>
122
+ <signal>released()</signal>
123
+ <receiver>uiFindFilesWGT</receiver>
124
+ <slot>hide()</slot>
125
+ <hints>
126
+ <hint type="sourcelabel">
127
+ <x>620</x>
128
+ <y>19</y>
129
+ </hint>
130
+ <hint type="destinationlabel">
131
+ <x>676</x>
132
+ <y>24</y>
133
+ </hint>
134
+ </hints>
135
+ </connection>
136
+ </connections>
137
+ <slots>
138
+ <slot>find()</slot>
139
+ </slots>
140
+ </ui>
@@ -81,6 +81,9 @@
81
81
  </widget>
82
82
  </widget>
83
83
  </item>
84
+ <item>
85
+ <widget class="FindFiles" name="uiFindInWorkboxesWGT" native="true"/>
86
+ </item>
84
87
  </layout>
85
88
  </widget>
86
89
  <widget class="QMenuBar" name="uiMenuBar">
@@ -110,6 +113,7 @@
110
113
  <addaction name="uiCloseWorkboxACT"/>
111
114
  <addaction name="separator"/>
112
115
  <addaction name="uiSaveConsoleSettingsACT"/>
116
+ <addaction name="uiRestartACT"/>
113
117
  <addaction name="uiCloseLoggerACT"/>
114
118
  </widget>
115
119
  <widget class="QMenu" name="uiHelpMENU">
@@ -130,7 +134,7 @@
130
134
  </widget>
131
135
  <widget class="QMenu" name="menu_Run">
132
136
  <property name="title">
133
- <string>&amp;Run</string>
137
+ <string>Run</string>
134
138
  </property>
135
139
  <addaction name="uiRunSelectedACT"/>
136
140
  <addaction name="uiRunAllACT"/>
@@ -321,6 +325,9 @@
321
325
  <addaction name="separator"/>
322
326
  <addaction name="menuFocus_to_Group"/>
323
327
  <addaction name="menuFocus_to_Tab"/>
328
+ <addaction name="separator"/>
329
+ <addaction name="uiFindInWorkboxesACT"/>
330
+ <addaction name="uiFocusNameACT"/>
324
331
  </widget>
325
332
  <addaction name="uiScriptingMENU"/>
326
333
  <addaction name="menuEdit"/>
@@ -930,6 +937,33 @@ at the indicated line in the specified text editor.
930
937
  <string>Backup</string>
931
938
  </property>
932
939
  </action>
940
+ <action name="uiFocusNameACT">
941
+ <property name="text">
942
+ <string>Focus To Name</string>
943
+ </property>
944
+ <property name="shortcut">
945
+ <string>Ctrl+P</string>
946
+ </property>
947
+ </action>
948
+ <action name="uiRestartACT">
949
+ <property name="text">
950
+ <string>Restart PrEditor</string>
951
+ </property>
952
+ <property name="toolTip">
953
+ <string>Closes PrEditor and launches a new process with the same cli arguments.</string>
954
+ </property>
955
+ <property name="shortcut">
956
+ <string>Ctrl+Alt+Shift+R</string>
957
+ </property>
958
+ </action>
959
+ <action name="uiFindInWorkboxesACT">
960
+ <property name="text">
961
+ <string>Find in Workboxes</string>
962
+ </property>
963
+ <property name="shortcut">
964
+ <string>Ctrl+Shift+F</string>
965
+ </property>
966
+ </action>
933
967
  </widget>
934
968
  <customwidgets>
935
969
  <customwidget>
@@ -948,6 +982,12 @@ at the indicated line in the specified text editor.
948
982
  <extends>QWidget</extends>
949
983
  <header>preditor.gui.editor_chooser.h</header>
950
984
  </customwidget>
985
+ <customwidget>
986
+ <class>FindFiles</class>
987
+ <extends>QWidget</extends>
988
+ <header>preditor.gui.find_files.h</header>
989
+ <container>1</container>
990
+ </customwidget>
951
991
  </customwidgets>
952
992
  <resources/>
953
993
  <connections>
@@ -990,8 +1030,8 @@ at the indicated line in the specified text editor.
990
1030
  <slot>update_workbox_stack()</slot>
991
1031
  <hints>
992
1032
  <hint type="sourcelabel">
993
- <x>754</x>
994
- <y>377</y>
1033
+ <x>763</x>
1034
+ <y>371</y>
995
1035
  </hint>
996
1036
  <hint type="destinationlabel">
997
1037
  <x>747</x>
@@ -999,11 +1039,28 @@ at the indicated line in the specified text editor.
999
1039
  </hint>
1000
1040
  </hints>
1001
1041
  </connection>
1042
+ <connection>
1043
+ <sender>uiFindInWorkboxesACT</sender>
1044
+ <signal>triggered()</signal>
1045
+ <receiver>PrEditorWindow</receiver>
1046
+ <slot>show_find_in_workboxes()</slot>
1047
+ <hints>
1048
+ <hint type="sourcelabel">
1049
+ <x>-1</x>
1050
+ <y>-1</y>
1051
+ </hint>
1052
+ <hint type="destinationlabel">
1053
+ <x>397</x>
1054
+ <y>202</y>
1055
+ </hint>
1056
+ </hints>
1057
+ </connection>
1002
1058
  </connections>
1003
1059
  <slots>
1004
1060
  <slot>apply_options()</slot>
1005
1061
  <slot>reset_options()</slot>
1006
1062
  <slot>show_workbox_options()</slot>
1007
1063
  <slot>update_workbox_stack()</slot>
1064
+ <slot>show_find_in_workboxes()</slot>
1008
1065
  </slots>
1009
1066
  </ui>
@@ -4,6 +4,7 @@ import os
4
4
  import tempfile
5
5
  import textwrap
6
6
 
7
+ from Qt.QtCore import Qt
7
8
  from Qt.QtWidgets import QStackedWidget
8
9
 
9
10
  from ..prefs import prefs_path
@@ -32,6 +33,9 @@ class WorkboxMixin(object):
32
33
  def __clear__(self):
33
34
  raise NotImplementedError("Mixin method not overridden.")
34
35
 
36
+ def __close__(self):
37
+ """Called just before the LoggerWindow is closed to allow for workbox cleanup"""
38
+
35
39
  def __comment_toggle__(self):
36
40
  raise NotImplementedError("Mixin method not overridden.")
37
41
 
@@ -321,3 +325,33 @@ class WorkboxMixin(object):
321
325
  elif self._tempfile:
322
326
  txt = self.__open_file__(self.__tempfile__())
323
327
  self.__set_text__(txt)
328
+
329
+ def process_shortcut(self, event, run=True):
330
+ """Check for workbox shortcuts and optionally call them.
331
+
332
+ Args:
333
+ event (QEvent): The keyPressEvent to process.
334
+ run (bool, optional): Run the expected action if possible.
335
+
336
+ Returns:
337
+ str or False: Returns False if the key press was not handled, indicating
338
+ that the subclass needs to handle it(or call super). If a known
339
+ shortcut was detected, a string indicating the action is returned
340
+ after running the action if enabled and supported.
341
+
342
+ Known actions:
343
+ __exec_selected__: If the user pressed Shift + Return or pressed the
344
+ number pad enter key calling `__exec_selected__`.
345
+ """
346
+ if event.key() == Qt.Key_Enter or (
347
+ event.key() == Qt.Key_Return and event.modifiers() == Qt.ShiftModifier
348
+ ):
349
+ # Number pad enter, or Shift + Return pressed, execute selected
350
+ if run:
351
+ self.__exec_selected__()
352
+
353
+ if self.window().uiAutoPromptACT.isChecked():
354
+ self.__console__().startInputLine()
355
+ return '__exec_selected__'
356
+
357
+ return False
@@ -2,7 +2,6 @@ from __future__ import absolute_import
2
2
 
3
3
  import logging
4
4
 
5
- from Qt.QtCore import Qt
6
5
  from Qt.QtGui import QFont, QFontMetrics, QTextCursor
7
6
  from Qt.QtWidgets import QTextEdit
8
7
 
@@ -87,7 +86,7 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
87
86
  # TODO: Implement custom tab widths
88
87
  return 4
89
88
 
90
- def __text__(self):
89
+ def __text__(self, line=None, start=None, end=None):
91
90
  return self.toPlainText()
92
91
 
93
92
  def __set_text__(self, text):
@@ -112,11 +111,7 @@ class WorkboxTextEdit(WorkboxMixin, QTextEdit):
112
111
  return self.textCursor().selection().toPlainText()
113
112
 
114
113
  def keyPressEvent(self, event):
115
- # If number pad enter key or Shift and keyboard return key
116
- # are used run selected text.
117
- if event.key() == Qt.Key_Enter or (
118
- event.key() == Qt.Key_Return and event.modifiers() == Qt.ShiftModifier
119
- ):
120
- self.__exec_selected__()
114
+ if self.process_shortcut(event):
115
+ return
121
116
  else:
122
117
  super(WorkboxTextEdit, self).keyPressEvent(event)
@@ -197,13 +197,8 @@ class WorkboxWidget(WorkboxMixin, DocumentEditor):
197
197
  if self._software == 'softimage':
198
198
  DocumentEditor.keyPressEvent(self, event)
199
199
  else:
200
- if event.key() == Qt.Key_Enter or (
201
- event.key() == Qt.Key_Return and event.modifiers() == Qt.ShiftModifier
202
- ):
203
- self.__exec_selected__()
204
-
205
- if self.window().uiAutoPromptACT.isChecked():
206
- self.__console__().startInputLine()
200
+ if self.process_shortcut(event):
201
+ return
207
202
  else:
208
203
  DocumentEditor.keyPressEvent(self, event)
209
204
 
@@ -5,3 +5,13 @@
5
5
  Converted to multi-resolution icon using: https://convertico.com/svg-to-ico/
6
6
 
7
7
  Most other icons downloaded from https://materialdesignicons.com/.
8
+
9
+ Svg icons are preferred as they are plain text files that play nicely with git.
10
+ Please make sure to update the sources table when adding or updating images.
11
+
12
+ # Sources for resources
13
+
14
+ | File | Source | Notes | Author |
15
+ |---|---|---|---|
16
+ | ![](preditor/resource/img/format-letter-case.svg) [format-letter-case.svg](preditor/resource/img/format-letter-case.svg) | https://pictogrammers.com/library/mdi/icon/format-letter-case/ | | [Austin Andrews](https://pictogrammers.com/contributor/Templarian/) |
17
+ | ![](preditor/resource/img/regex.svg) [regex.svg](preditor/resource/img/regex.svg) | https://pictogrammers.com/library/mdi/icon/regex/ | | [Doug C. Hardester](https://pictogrammers.com/contributor/r3volution11/) |