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.
- {PrEditor-0.1.0rc2.dist-info → PrEditor-0.3.0.dist-info}/METADATA +8 -8
- {PrEditor-0.1.0rc2.dist-info → PrEditor-0.3.0.dist-info}/RECORD +26 -17
- {PrEditor-0.1.0rc2.dist-info → PrEditor-0.3.0.dist-info}/WHEEL +1 -1
- preditor/__init__.py +7 -2
- preditor/cli.py +1 -1
- preditor/gui/find_files.py +119 -0
- preditor/gui/fuzzy_search/__init__.py +0 -0
- preditor/gui/fuzzy_search/fuzzy_search.py +93 -0
- preditor/gui/group_tab_widget/__init__.py +14 -5
- preditor/gui/group_tab_widget/grouped_tab_models.py +108 -0
- preditor/gui/loggerwindow.py +152 -29
- preditor/gui/ui/find_files.ui +140 -0
- preditor/gui/ui/loggerwindow.ui +60 -3
- preditor/gui/workbox_mixin.py +34 -0
- preditor/gui/workbox_text_edit.py +3 -8
- preditor/gui/workboxwidget.py +2 -7
- preditor/resource/img/README.md +10 -0
- preditor/resource/img/format-letter-case.svg +1 -0
- preditor/resource/img/regex.svg +1 -0
- preditor/resource/img/restart.svg +1 -0
- preditor/stream/director.py +20 -3
- preditor/utils/text_search.py +342 -0
- preditor/version.py +2 -2
- {PrEditor-0.1.0rc2.dist-info → PrEditor-0.3.0.dist-info}/LICENSE +0 -0
- {PrEditor-0.1.0rc2.dist-info → PrEditor-0.3.0.dist-info}/entry_points.txt +0 -0
- {PrEditor-0.1.0rc2.dist-info → PrEditor-0.3.0.dist-info}/top_level.txt +0 -0
preditor/gui/loggerwindow.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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>
|
preditor/gui/ui/loggerwindow.ui
CHANGED
|
@@ -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
|
|
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>
|
|
994
|
-
<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>
|
preditor/gui/workbox_mixin.py
CHANGED
|
@@ -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
|
-
|
|
116
|
-
|
|
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)
|
preditor/gui/workboxwidget.py
CHANGED
|
@@ -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
|
|
201
|
-
|
|
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
|
|
preditor/resource/img/README.md
CHANGED
|
@@ -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
|
+
|  [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
|
+
|  [regex.svg](preditor/resource/img/regex.svg) | https://pictogrammers.com/library/mdi/icon/regex/ | | [Doug C. Hardester](https://pictogrammers.com/contributor/r3volution11/) |
|