PrEditor 0.4.0__py2.py3-none-any.whl → 0.6.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/__init__.py +5 -0
- preditor/gui/console.py +121 -13
- preditor/gui/editor_chooser.py +1 -1
- preditor/gui/group_tab_widget/__init__.py +1 -1
- preditor/gui/group_tab_widget/grouped_tab_widget.py +3 -0
- preditor/gui/loggerwindow.py +154 -70
- preditor/gui/set_text_editor_path_dialog.py +4 -4
- preditor/gui/status_label.py +25 -5
- preditor/gui/suggest_path_quotes_dialog.py +50 -0
- preditor/gui/ui/loggerwindow.ui +82 -34
- preditor/gui/ui/set_text_editor_path_dialog.ui +48 -8
- preditor/gui/ui/suggest_path_quotes_dialog.ui +225 -0
- preditor/gui/workbox_mixin.py +50 -18
- preditor/gui/workbox_text_edit.py +24 -4
- preditor/gui/workboxwidget.py +24 -2
- preditor/scintilla/documenteditor.py +3 -3
- preditor/version.py +2 -2
- {PrEditor-0.4.0.dist-info → preditor-0.6.0.dist-info}/METADATA +19 -18
- {PrEditor-0.4.0.dist-info → preditor-0.6.0.dist-info}/RECORD +23 -21
- {PrEditor-0.4.0.dist-info → preditor-0.6.0.dist-info}/WHEEL +1 -1
- {PrEditor-0.4.0.dist-info → preditor-0.6.0.dist-info}/entry_points.txt +0 -0
- {PrEditor-0.4.0.dist-info → preditor-0.6.0.dist-info/licenses}/LICENSE +0 -0
- {PrEditor-0.4.0.dist-info → preditor-0.6.0.dist-info}/top_level.txt +0 -0
preditor/__init__.py
CHANGED
|
@@ -113,6 +113,11 @@ def configure(name, parent_callback=None, excepthook=True, logging=True, streams
|
|
|
113
113
|
preditor.debug.BlurExcepthook.install()
|
|
114
114
|
|
|
115
115
|
|
|
116
|
+
def get_core_name():
|
|
117
|
+
"""Returns the configured core_name or DEFAULT_CORE_NAME."""
|
|
118
|
+
return _global_config.get('core_name', DEFAULT_CORE_NAME)
|
|
119
|
+
|
|
120
|
+
|
|
116
121
|
def launch(run_workbox=False, app_id=None, name=None, standalone=False):
|
|
117
122
|
"""Launches the preditor gui creating the QApplication instance if not
|
|
118
123
|
already created.
|
preditor/gui/console.py
CHANGED
|
@@ -9,17 +9,20 @@ import sys
|
|
|
9
9
|
import time
|
|
10
10
|
import traceback
|
|
11
11
|
from builtins import str as text
|
|
12
|
+
from fractions import Fraction
|
|
13
|
+
from functools import partial
|
|
12
14
|
|
|
13
15
|
import __main__
|
|
14
16
|
from Qt import QtCompat
|
|
15
|
-
from Qt.QtCore import QPoint, Qt
|
|
17
|
+
from Qt.QtCore import QPoint, Qt, QTimer
|
|
16
18
|
from Qt.QtGui import QColor, QFontMetrics, QTextCharFormat, QTextCursor, QTextDocument
|
|
17
|
-
from Qt.QtWidgets import QAction, QApplication, QTextEdit
|
|
19
|
+
from Qt.QtWidgets import QAbstractItemView, QAction, QApplication, QTextEdit
|
|
18
20
|
|
|
19
21
|
from .. import debug, settings, stream
|
|
20
22
|
from ..streamhandler_helper import StreamHandlerHelper
|
|
21
23
|
from .codehighlighter import CodeHighlighter
|
|
22
24
|
from .completer import PythonCompleter
|
|
25
|
+
from .suggest_path_quotes_dialog import SuggestPathQuotesDialog
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
class ConsolePrEdit(QTextEdit):
|
|
@@ -47,6 +50,7 @@ class ConsolePrEdit(QTextEdit):
|
|
|
47
50
|
# If still using a #
|
|
48
51
|
self._outputPrompt = '#Result: '
|
|
49
52
|
# Method used to update the gui when code is executed
|
|
53
|
+
self.clearExecutionTime = None
|
|
50
54
|
self.reportExecutionTime = None
|
|
51
55
|
|
|
52
56
|
self._firstShow = True
|
|
@@ -102,9 +106,46 @@ class ConsolePrEdit(QTextEdit):
|
|
|
102
106
|
self.clickPos = None
|
|
103
107
|
self.anchor = None
|
|
104
108
|
|
|
109
|
+
# Make sure console cursor is visible. It can get it's width set to 0 with
|
|
110
|
+
# unusual(ie not 100%) os display scaling.
|
|
111
|
+
if not self.cursorWidth():
|
|
112
|
+
self.setCursorWidth(1)
|
|
113
|
+
|
|
114
|
+
def doubleSingleShotSetScrollValue(self, origPercent):
|
|
115
|
+
"""This double QTimer.singleShot monkey business seems to be the only way
|
|
116
|
+
to get scroll.maximum() to update properly so that we calc newValue
|
|
117
|
+
correctly. It's quite silly. Apparently, the important part is that
|
|
118
|
+
calling scroll.maximum() has had a pause since the font had been set.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def singleShotSetScrollValue(self, origPercent):
|
|
122
|
+
scroll = self.verticalScrollBar()
|
|
123
|
+
maximum = scroll.maximum()
|
|
124
|
+
if maximum is not None:
|
|
125
|
+
newValue = round(origPercent * maximum)
|
|
126
|
+
QTimer.singleShot(1, partial(scroll.setValue, newValue))
|
|
127
|
+
|
|
128
|
+
# The 100 ms timer amount is somewhat arbitrary. It must be more than
|
|
129
|
+
# some value to work, but what that value is is unknown, and may change
|
|
130
|
+
# under various circumstances. Briefly disable updates for smoother transition.
|
|
131
|
+
self.setUpdatesEnabled(False)
|
|
132
|
+
try:
|
|
133
|
+
QTimer.singleShot(100, partial(singleShotSetScrollValue, self, origPercent))
|
|
134
|
+
finally:
|
|
135
|
+
self.setUpdatesEnabled(True)
|
|
136
|
+
|
|
105
137
|
def setConsoleFont(self, font):
|
|
106
138
|
"""Set the console's font and adjust the tabStopWidth"""
|
|
139
|
+
|
|
140
|
+
# Capture the scroll bar's current position (by percentage of max)
|
|
141
|
+
origPercent = None
|
|
142
|
+
scroll = self.verticalScrollBar()
|
|
143
|
+
if scroll.maximum():
|
|
144
|
+
origPercent = Fraction(scroll.value(), scroll.maximum())
|
|
145
|
+
|
|
146
|
+
# Set console and completer popup fonts
|
|
107
147
|
self.setFont(font)
|
|
148
|
+
self.completer().popup().setFont(font)
|
|
108
149
|
|
|
109
150
|
# Set the setTabStopWidth for the console's font
|
|
110
151
|
tab_width = 4
|
|
@@ -117,6 +158,10 @@ class ConsolePrEdit(QTextEdit):
|
|
|
117
158
|
fontPixelWidth = QFontMetrics(font).width(" ")
|
|
118
159
|
self.setTabStopWidth(fontPixelWidth * tab_width)
|
|
119
160
|
|
|
161
|
+
# Scroll to same relative position where we started
|
|
162
|
+
if origPercent is not None:
|
|
163
|
+
self.doubleSingleShotSetScrollValue(origPercent)
|
|
164
|
+
|
|
120
165
|
def mousePressEvent(self, event):
|
|
121
166
|
"""Overload of mousePressEvent to capture click position, so on release, we can
|
|
122
167
|
check release position. If it's the same (ie user clicked vs click-drag to
|
|
@@ -213,6 +258,23 @@ class ConsolePrEdit(QTextEdit):
|
|
|
213
258
|
return
|
|
214
259
|
|
|
215
260
|
if modulePath:
|
|
261
|
+
# Check if cmdTempl filepaths aren't wrapped in double=quotes to handle
|
|
262
|
+
# spaces. If not, suggest to user to update the template, offering the
|
|
263
|
+
# suggested change.
|
|
264
|
+
pattern = r"(?<!\")({\w+Path})(?!\")"
|
|
265
|
+
repl = r'"\g<1>"'
|
|
266
|
+
quotedCmdTempl = re.sub(pattern, repl, cmdTempl)
|
|
267
|
+
if quotedCmdTempl != cmdTempl:
|
|
268
|
+
# Instantiate dialog to maybe show (unless user previously chose "Don't
|
|
269
|
+
# ask again")
|
|
270
|
+
dialog = SuggestPathQuotesDialog(
|
|
271
|
+
self.window(), cmdTempl, quotedCmdTempl
|
|
272
|
+
)
|
|
273
|
+
self.window().maybeDisplayDialog(dialog)
|
|
274
|
+
|
|
275
|
+
# Refresh cmdTempl in case user just had it changed.
|
|
276
|
+
cmdTempl = window.textEditorCmdTempl
|
|
277
|
+
|
|
216
278
|
# Attempt to create command from template and run the command
|
|
217
279
|
try:
|
|
218
280
|
command = cmdTempl.format(
|
|
@@ -317,6 +379,8 @@ class ConsolePrEdit(QTextEdit):
|
|
|
317
379
|
self._foregroundColor = color
|
|
318
380
|
|
|
319
381
|
def executeString(self, commandText, filename='<ConsolePrEdit>', extraPrint=True):
|
|
382
|
+
if self.clearExecutionTime is not None:
|
|
383
|
+
self.clearExecutionTime()
|
|
320
384
|
cursor = self.textCursor()
|
|
321
385
|
cursor.select(QTextCursor.BlockUnderCursor)
|
|
322
386
|
line = cursor.selectedText()
|
|
@@ -333,18 +397,27 @@ class ConsolePrEdit(QTextEdit):
|
|
|
333
397
|
# exec which has no Return.
|
|
334
398
|
wasEval = False
|
|
335
399
|
startTime = time.time()
|
|
400
|
+
|
|
336
401
|
try:
|
|
337
402
|
compiled = compile(commandText, filename, 'eval')
|
|
338
403
|
wasEval = True
|
|
339
404
|
except Exception:
|
|
340
405
|
compiled = compile(commandText, filename, 'exec')
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
406
|
+
|
|
407
|
+
# We wrap in try / finally so that elapsed time gets updated, even when an
|
|
408
|
+
# exception is raised.
|
|
409
|
+
try:
|
|
410
|
+
if wasEval:
|
|
411
|
+
cmdresult = eval(compiled, __main__.__dict__, __main__.__dict__)
|
|
412
|
+
else:
|
|
413
|
+
exec(compiled, __main__.__dict__, __main__.__dict__)
|
|
414
|
+
finally:
|
|
415
|
+
# Report the total time it took to execute this code.
|
|
416
|
+
if self.reportExecutionTime is not None:
|
|
417
|
+
delta = time.time() - startTime
|
|
418
|
+
self.reportExecutionTime((delta, commandText))
|
|
345
419
|
|
|
346
420
|
# Provide user feedback when running long code execution.
|
|
347
|
-
delta = time.time() - startTime
|
|
348
421
|
if self.flash_window and self.flash_time and delta >= self.flash_time:
|
|
349
422
|
if settings.OS_TYPE == "Windows":
|
|
350
423
|
try:
|
|
@@ -356,9 +429,6 @@ class ConsolePrEdit(QTextEdit):
|
|
|
356
429
|
hwnd = int(self.flash_window.winId())
|
|
357
430
|
utils.flash_window(hwnd)
|
|
358
431
|
|
|
359
|
-
# Report the total time it took to execute this code.
|
|
360
|
-
if self.reportExecutionTime is not None:
|
|
361
|
-
self.reportExecutionTime(delta)
|
|
362
432
|
return cmdresult, wasEval
|
|
363
433
|
|
|
364
434
|
def executeCommand(self):
|
|
@@ -478,6 +548,17 @@ class ConsolePrEdit(QTextEdit):
|
|
|
478
548
|
|
|
479
549
|
completer = self.completer()
|
|
480
550
|
|
|
551
|
+
# Define prefix so we can determine if the exact prefix is in
|
|
552
|
+
# completions and highlight it. We must manually add the currently typed
|
|
553
|
+
# character, or remove it if backspace or delete has just been pressed.
|
|
554
|
+
key = event.text()
|
|
555
|
+
_, prefix = completer.currentObject(scope=__main__.__dict__)
|
|
556
|
+
isBackspaceOrDel = event.key() in (Qt.Key_Backspace, Qt.Key_Delete)
|
|
557
|
+
if key.isalnum() or key in ("-", "_"):
|
|
558
|
+
prefix += str(key)
|
|
559
|
+
elif isBackspaceOrDel and prefix:
|
|
560
|
+
prefix = prefix[:-1]
|
|
561
|
+
|
|
481
562
|
if completer and event.key() in (
|
|
482
563
|
Qt.Key_Backspace,
|
|
483
564
|
Qt.Key_Delete,
|
|
@@ -560,9 +641,30 @@ class ConsolePrEdit(QTextEdit):
|
|
|
560
641
|
or completer.wasCompletingCounter
|
|
561
642
|
):
|
|
562
643
|
completer.refreshList(scope=__main__.__dict__)
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
)
|
|
644
|
+
|
|
645
|
+
model = completer.completionModel()
|
|
646
|
+
index = model.index(0, 0)
|
|
647
|
+
|
|
648
|
+
# If option chosen, if the exact prefix exists in the
|
|
649
|
+
# possible completions, highlight it, even if it's not the
|
|
650
|
+
# topmost completion.
|
|
651
|
+
if self.window().uiHighlightExactCompletionACT.isChecked():
|
|
652
|
+
for i in range(completer.completionCount()):
|
|
653
|
+
completer.setCurrentRow(i)
|
|
654
|
+
curCompletion = completer.currentCompletion()
|
|
655
|
+
if prefix == curCompletion:
|
|
656
|
+
index = model.index(i, 0)
|
|
657
|
+
break
|
|
658
|
+
elif prefix == curCompletion.lower():
|
|
659
|
+
index = model.index(i, 0)
|
|
660
|
+
break
|
|
661
|
+
|
|
662
|
+
# Set completer current Row, so finishing the completer will use
|
|
663
|
+
# correct text
|
|
664
|
+
completer.setCurrentRow(index.row())
|
|
665
|
+
|
|
666
|
+
# Make sure that current selection is visible, ie scroll to it
|
|
667
|
+
completer.popup().scrollTo(index, QAbstractItemView.EnsureVisible)
|
|
566
668
|
|
|
567
669
|
# show the completer for the rect
|
|
568
670
|
rect = self.cursorRect()
|
|
@@ -640,6 +742,7 @@ class ConsolePrEdit(QTextEdit):
|
|
|
640
742
|
def startInputLine(self):
|
|
641
743
|
"""create a new command prompt line"""
|
|
642
744
|
self.startPrompt(self.prompt())
|
|
745
|
+
self._prevCommandIndex = 0
|
|
643
746
|
|
|
644
747
|
def startPrompt(self, prompt):
|
|
645
748
|
"""create a new command prompt line with the given prompt
|
|
@@ -661,6 +764,11 @@ class ConsolePrEdit(QTextEdit):
|
|
|
661
764
|
|
|
662
765
|
self.insertPlainText(inputstr)
|
|
663
766
|
|
|
767
|
+
scroll = self.verticalScrollBar()
|
|
768
|
+
maximum = scroll.maximum()
|
|
769
|
+
if maximum is not None:
|
|
770
|
+
scroll.setValue(maximum)
|
|
771
|
+
|
|
664
772
|
def startOutputLine(self):
|
|
665
773
|
"""Create a new line to show output text."""
|
|
666
774
|
self.startPrompt(self._outputPrompt)
|
preditor/gui/editor_chooser.py
CHANGED
|
@@ -44,7 +44,7 @@ class EditorChooser(QWidget):
|
|
|
44
44
|
current = self.editor_name()
|
|
45
45
|
self.uiWorkboxEditorDDL.blockSignals(True)
|
|
46
46
|
self.uiWorkboxEditorDDL.clear()
|
|
47
|
-
for name, _ in sorted(plugins.editors()):
|
|
47
|
+
for name, _ in sorted(set(plugins.editors())):
|
|
48
48
|
self.uiWorkboxEditorDDL.addItem(name)
|
|
49
49
|
|
|
50
50
|
self.uiWorkboxEditorDDL.setCurrentIndex(
|
|
@@ -110,7 +110,7 @@ class GroupTabWidget(OneTabWidget):
|
|
|
110
110
|
# Create the first editor tab and make it visible
|
|
111
111
|
editor = parent.add_new_editor(title)
|
|
112
112
|
self.setCurrentIndex(self.indexOf(parent))
|
|
113
|
-
|
|
113
|
+
self.window().focusToWorkbox()
|
|
114
114
|
return parent, editor
|
|
115
115
|
|
|
116
116
|
def all_widgets(self):
|
|
@@ -71,5 +71,8 @@ class GroupedTabWidget(OneTabWidget):
|
|
|
71
71
|
if editor and editor.isVisible():
|
|
72
72
|
editor.__show__()
|
|
73
73
|
|
|
74
|
+
if hasattr(self.window(), "setWorkboxFontBasedOnConsole"):
|
|
75
|
+
self.window().setWorkboxFontBasedOnConsole()
|
|
76
|
+
|
|
74
77
|
def update_closable_tabs(self):
|
|
75
78
|
self.setTabsClosable(self.count() != 1)
|
preditor/gui/loggerwindow.py
CHANGED
|
@@ -14,9 +14,10 @@ import __main__
|
|
|
14
14
|
import six
|
|
15
15
|
from Qt import QtCompat, QtCore, QtWidgets
|
|
16
16
|
from Qt.QtCore import QByteArray, Qt, QTimer, Signal, Slot
|
|
17
|
-
from Qt.QtGui import QCursor, QFont,
|
|
17
|
+
from Qt.QtGui import QCursor, QFont, QIcon, QTextCursor
|
|
18
18
|
from Qt.QtWidgets import (
|
|
19
19
|
QApplication,
|
|
20
|
+
QFontDialog,
|
|
20
21
|
QInputDialog,
|
|
21
22
|
QMessageBox,
|
|
22
23
|
QTextBrowser,
|
|
@@ -29,6 +30,7 @@ from .. import (
|
|
|
29
30
|
about_preditor,
|
|
30
31
|
core,
|
|
31
32
|
debug,
|
|
33
|
+
get_core_name,
|
|
32
34
|
osystem,
|
|
33
35
|
plugins,
|
|
34
36
|
prefs,
|
|
@@ -59,7 +61,7 @@ class LoggerWindow(Window):
|
|
|
59
61
|
|
|
60
62
|
def __init__(self, parent, name=None, run_workbox=False, standalone=False):
|
|
61
63
|
super(LoggerWindow, self).__init__(parent=parent)
|
|
62
|
-
self.name = name if name else
|
|
64
|
+
self.name = name if name else get_core_name()
|
|
63
65
|
self.aboutToClearPathsEnabled = False
|
|
64
66
|
self._stylesheet = 'Bright'
|
|
65
67
|
|
|
@@ -75,6 +77,7 @@ class LoggerWindow(Window):
|
|
|
75
77
|
loadUi(__file__, self)
|
|
76
78
|
|
|
77
79
|
self.uiConsoleTXT.flash_window = self
|
|
80
|
+
self.uiConsoleTXT.clearExecutionTime = self.clearExecutionTime
|
|
78
81
|
self.uiConsoleTXT.reportExecutionTime = self.reportExecutionTime
|
|
79
82
|
self.uiClearToLastPromptACT.triggered.connect(
|
|
80
83
|
self.uiConsoleTXT.clearToLastPrompt
|
|
@@ -119,12 +122,38 @@ class LoggerWindow(Window):
|
|
|
119
122
|
self.uiCloseLoggerACT.triggered.connect(self.closeLogger)
|
|
120
123
|
|
|
121
124
|
self.uiRunAllACT.triggered.connect(self.execAll)
|
|
122
|
-
|
|
125
|
+
# Even though the RunSelected actions (with shortcuts) are connected
|
|
126
|
+
# here, this only affects if the action is chosen from the menu. The
|
|
127
|
+
# shortcuts are always intercepted by the workbox document editor. To
|
|
128
|
+
# handle this, the workbox.keyPressEvent method will perceive the
|
|
129
|
+
# shortcut press, and call .execSelected, which will then ultimately call
|
|
130
|
+
# workbox.__exec_selected__
|
|
131
|
+
self.uiRunSelectedACT.triggered.connect(
|
|
132
|
+
partial(self.execSelected, truncate=True)
|
|
133
|
+
)
|
|
134
|
+
self.uiRunSelectedDontTruncateACT.triggered.connect(
|
|
135
|
+
partial(self.execSelected, truncate=False)
|
|
136
|
+
)
|
|
123
137
|
|
|
124
|
-
self.
|
|
138
|
+
self.uiConsoleAutoCompleteEnabledACT.toggled.connect(
|
|
139
|
+
partial(self.setAutoCompleteEnabled, console=True)
|
|
140
|
+
)
|
|
141
|
+
self.uiWorkboxAutoCompleteEnabledACT.toggled.connect(
|
|
142
|
+
partial(self.setAutoCompleteEnabled, console=False)
|
|
143
|
+
)
|
|
125
144
|
|
|
126
145
|
self.uiAutoCompleteCaseSensitiveACT.toggled.connect(self.setCaseSensitive)
|
|
127
146
|
|
|
147
|
+
self.uiSelectMonospaceFontACT.triggered.connect(
|
|
148
|
+
partial(self.selectFont, monospace=True)
|
|
149
|
+
)
|
|
150
|
+
self.uiSelectProportionalFontACT.triggered.connect(
|
|
151
|
+
partial(self.selectFont, proportional=True)
|
|
152
|
+
)
|
|
153
|
+
self.uiSelectAllFontACT.triggered.connect(
|
|
154
|
+
partial(self.selectFont, monospace=True, proportional=True)
|
|
155
|
+
)
|
|
156
|
+
|
|
128
157
|
# Setup ability to cycle completer mode, and create action for each mode
|
|
129
158
|
self.completerModeCycle = itertools.cycle(CompleterMode)
|
|
130
159
|
# create CompleterMode submenu
|
|
@@ -234,27 +263,9 @@ class LoggerWindow(Window):
|
|
|
234
263
|
# Make action shortcuts available anywhere in the Logger
|
|
235
264
|
self.addAction(self.uiClearLogACT)
|
|
236
265
|
|
|
266
|
+
self.dont_ask_again = []
|
|
237
267
|
self.restorePrefs()
|
|
238
268
|
|
|
239
|
-
# add font menu list
|
|
240
|
-
curFamily = self.console().font().family()
|
|
241
|
-
fontDB = QFontDatabase()
|
|
242
|
-
fontFamilies = fontDB.families(QFontDatabase.Latin)
|
|
243
|
-
monospaceFonts = [fam for fam in fontFamilies if fontDB.isFixedPitch(fam)]
|
|
244
|
-
|
|
245
|
-
self.uiMonospaceFontMENU.clear()
|
|
246
|
-
self.uiProportionalFontMENU.clear()
|
|
247
|
-
|
|
248
|
-
for family in fontFamilies:
|
|
249
|
-
if family in monospaceFonts:
|
|
250
|
-
action = self.uiMonospaceFontMENU.addAction(family)
|
|
251
|
-
else:
|
|
252
|
-
action = self.uiProportionalFontMENU.addAction(family)
|
|
253
|
-
action.setObjectName(u'ui{}FontACT'.format(family))
|
|
254
|
-
action.setCheckable(True)
|
|
255
|
-
action.setChecked(family == curFamily)
|
|
256
|
-
action.triggered.connect(partial(self.selectFont, action))
|
|
257
|
-
|
|
258
269
|
# add stylesheet menu options.
|
|
259
270
|
for style_name in stylesheets.stylesheets():
|
|
260
271
|
action = self.uiStyleMENU.addAction(style_name)
|
|
@@ -276,6 +287,9 @@ class LoggerWindow(Window):
|
|
|
276
287
|
)
|
|
277
288
|
)
|
|
278
289
|
|
|
290
|
+
self.setWorkboxFontBasedOnConsole()
|
|
291
|
+
self.setEditorChooserFontBasedOnConsole()
|
|
292
|
+
|
|
279
293
|
self.setup_run_workbox()
|
|
280
294
|
|
|
281
295
|
if not standalone:
|
|
@@ -429,7 +443,7 @@ class LoggerWindow(Window):
|
|
|
429
443
|
if not workbox.hasFocus():
|
|
430
444
|
return
|
|
431
445
|
|
|
432
|
-
text = workbox.__selected_text__()
|
|
446
|
+
text, _line = workbox.__selected_text__(selectText=True)
|
|
433
447
|
if not text:
|
|
434
448
|
line, index = workbox.__cursor_position__()
|
|
435
449
|
text = workbox.__text__(line)
|
|
@@ -506,22 +520,14 @@ class LoggerWindow(Window):
|
|
|
506
520
|
delta = event.angleDelta().y()
|
|
507
521
|
|
|
508
522
|
# convert delta to +1 or -1, depending
|
|
509
|
-
delta = delta
|
|
523
|
+
delta = delta // abs(delta)
|
|
510
524
|
minSize = 5
|
|
511
525
|
maxSize = 50
|
|
512
526
|
font = self.console().font()
|
|
513
527
|
newSize = font.pointSize() + delta
|
|
514
528
|
newSize = max(min(newSize, maxSize), minSize)
|
|
515
529
|
|
|
516
|
-
|
|
517
|
-
self.console().setConsoleFont(font)
|
|
518
|
-
|
|
519
|
-
for workbox in self.uiWorkboxTAB.all_widgets():
|
|
520
|
-
marginsFont = workbox.__margins_font__()
|
|
521
|
-
marginsFont.setPointSize(newSize)
|
|
522
|
-
workbox.__set_margins_font__(marginsFont)
|
|
523
|
-
|
|
524
|
-
workbox.__set_font__(font)
|
|
530
|
+
self.setFontSize(newSize)
|
|
525
531
|
else:
|
|
526
532
|
Window.wheelEvent(self, event)
|
|
527
533
|
|
|
@@ -539,41 +545,76 @@ class LoggerWindow(Window):
|
|
|
539
545
|
menu = action.parentWidget()
|
|
540
546
|
QToolTip.showText(QCursor.pos(), text, menu)
|
|
541
547
|
|
|
542
|
-
def
|
|
543
|
-
"""
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
action = None
|
|
548
|
-
for act in actions:
|
|
549
|
-
if act.isChecked():
|
|
550
|
-
action = act
|
|
551
|
-
break
|
|
552
|
-
|
|
553
|
-
return action
|
|
554
|
-
|
|
555
|
-
def selectFont(self, action):
|
|
556
|
-
"""Set console and workbox font to current font
|
|
548
|
+
def selectFont(self, monospace=False, proportional=False):
|
|
549
|
+
"""Present a QFontChooser dialog, offering, monospace, proportional, or all
|
|
550
|
+
fonts, based on user choice. If a font is chosen, set it on the console and
|
|
551
|
+
workboxes.
|
|
557
552
|
|
|
558
553
|
Args:
|
|
559
554
|
action (QAction): menu action associated with chosen font
|
|
560
555
|
"""
|
|
556
|
+
origFont = self.console().font()
|
|
557
|
+
curFontFamily = origFont.family()
|
|
558
|
+
|
|
559
|
+
if monospace and proportional:
|
|
560
|
+
options = QFontDialog.MonospacedFonts | QFontDialog.ProportionalFonts
|
|
561
|
+
kind = "monospace or proportional "
|
|
562
|
+
elif monospace:
|
|
563
|
+
options = QFontDialog.MonospacedFonts
|
|
564
|
+
kind = "monospace "
|
|
565
|
+
elif proportional:
|
|
566
|
+
options = QFontDialog.ProportionalFonts
|
|
567
|
+
kind = "proportional "
|
|
568
|
+
|
|
569
|
+
# Present a QFontDialog for user to choose a font
|
|
570
|
+
title = "Pick a {} font. Current font is: {}".format(kind, curFontFamily)
|
|
571
|
+
newFont, okClicked = QFontDialog.getFont(origFont, self, title, options=options)
|
|
572
|
+
|
|
573
|
+
if okClicked:
|
|
574
|
+
self.console().setConsoleFont(newFont)
|
|
575
|
+
self.setWorkboxFontBasedOnConsole()
|
|
576
|
+
self.setEditorChooserFontBasedOnConsole()
|
|
577
|
+
|
|
578
|
+
def setFontSize(self, newSize):
|
|
579
|
+
"""Update the font size in the console and current workbox.
|
|
561
580
|
|
|
562
|
-
|
|
563
|
-
|
|
581
|
+
Args:
|
|
582
|
+
newSize (int): The new size to set the font
|
|
583
|
+
"""
|
|
584
|
+
font = self.console().font()
|
|
585
|
+
font.setPointSize(newSize)
|
|
586
|
+
self.console().setConsoleFont(font)
|
|
564
587
|
|
|
565
|
-
|
|
566
|
-
|
|
588
|
+
self.setWorkboxFontBasedOnConsole()
|
|
589
|
+
self.setEditorChooserFontBasedOnConsole()
|
|
567
590
|
|
|
568
|
-
|
|
591
|
+
def setWorkboxFontBasedOnConsole(self):
|
|
592
|
+
"""If the current workbox's font is different to the console's font, set it to
|
|
593
|
+
match.
|
|
594
|
+
"""
|
|
569
595
|
font = self.console().font()
|
|
570
|
-
font.setFamily(family)
|
|
571
|
-
self.console().setConsoleFont(font)
|
|
572
596
|
|
|
573
|
-
|
|
597
|
+
workboxGroup = self.uiWorkboxTAB.currentWidget()
|
|
598
|
+
if workboxGroup is None:
|
|
599
|
+
return
|
|
600
|
+
|
|
601
|
+
workbox = workboxGroup.currentWidget()
|
|
602
|
+
if workbox is None:
|
|
603
|
+
return
|
|
604
|
+
|
|
605
|
+
if workbox.__font__() != font:
|
|
574
606
|
workbox.__set_margins_font__(font)
|
|
575
607
|
workbox.__set_font__(font)
|
|
576
608
|
|
|
609
|
+
def setEditorChooserFontBasedOnConsole(self):
|
|
610
|
+
"""Set the EditorChooser font to match console. This helps with legibility when
|
|
611
|
+
using EditorChooser.
|
|
612
|
+
"""
|
|
613
|
+
font = self.console().font()
|
|
614
|
+
for child in self.uiEditorChooserWGT.children():
|
|
615
|
+
if hasattr(child, "font"):
|
|
616
|
+
child.setFont(font)
|
|
617
|
+
|
|
577
618
|
@classmethod
|
|
578
619
|
def _genPrefName(cls, baseName, index):
|
|
579
620
|
if index:
|
|
@@ -635,11 +676,21 @@ class LoggerWindow(Window):
|
|
|
635
676
|
prompt = console.prompt()
|
|
636
677
|
console.startPrompt(prompt)
|
|
637
678
|
|
|
638
|
-
def execSelected(self):
|
|
639
|
-
"""Clears the console before executing selected workbox code
|
|
679
|
+
def execSelected(self, truncate=True):
|
|
680
|
+
"""Clears the console before executing selected workbox code.
|
|
681
|
+
|
|
682
|
+
NOTE! This method is not called when the uiRunSelectedACT is triggered,
|
|
683
|
+
because the workbox will always intercept it. So instead, the workbox's
|
|
684
|
+
keyPressEvent will notice the shortcut and call this method.
|
|
685
|
+
"""
|
|
686
|
+
|
|
640
687
|
if self.uiClearBeforeRunningACT.isChecked():
|
|
641
688
|
self.clearLog()
|
|
642
|
-
|
|
689
|
+
|
|
690
|
+
self.current_workbox().__exec_selected__(truncate=truncate)
|
|
691
|
+
|
|
692
|
+
if self.uiAutoPromptACT.isChecked():
|
|
693
|
+
self.console().startInputLine()
|
|
643
694
|
|
|
644
695
|
def keyPressEvent(self, event):
|
|
645
696
|
# Fix 'Maya : Qt tools lose focus' https://redmine.blur.com/issues/34430
|
|
@@ -652,6 +703,11 @@ class LoggerWindow(Window):
|
|
|
652
703
|
if self.uiClearLogOnRefreshACT.isChecked():
|
|
653
704
|
self.clearLog()
|
|
654
705
|
|
|
706
|
+
def clearExecutionTime(self):
|
|
707
|
+
"""Update status text with hyphens to indicate execution has begun."""
|
|
708
|
+
self.setStatusText('Exec: -.- Seconds')
|
|
709
|
+
QApplication.instance().processEvents()
|
|
710
|
+
|
|
655
711
|
def reportExecutionTime(self, seconds):
|
|
656
712
|
"""Update status text with seconds passed in."""
|
|
657
713
|
self.uiStatusLBL.showSeconds(seconds)
|
|
@@ -671,11 +727,15 @@ class LoggerWindow(Window):
|
|
|
671
727
|
'SplitterSize': self.uiSplitterSPLIT.sizes(),
|
|
672
728
|
'tabIndent': self.uiIndentationsTabsACT.isChecked(),
|
|
673
729
|
'copyIndentsAsSpaces': self.uiCopyTabsToSpacesACT.isChecked(),
|
|
674
|
-
'hintingEnabled': self.
|
|
730
|
+
'hintingEnabled': self.uiConsoleAutoCompleteEnabledACT.isChecked(),
|
|
731
|
+
'workboxHintingEnabled': (
|
|
732
|
+
self.uiWorkboxAutoCompleteEnabledACT.isChecked()
|
|
733
|
+
),
|
|
675
734
|
'spellCheckEnabled': self.uiSpellCheckEnabledACT.isChecked(),
|
|
676
735
|
'wordWrap': self.uiWordWrapACT.isChecked(),
|
|
677
736
|
'clearBeforeRunning': self.uiClearBeforeRunningACT.isChecked(),
|
|
678
737
|
'clearBeforeEnvRefresh': self.uiClearLogOnRefreshACT.isChecked(),
|
|
738
|
+
'uiSelectTextACT': self.uiSelectTextACT.isChecked(),
|
|
679
739
|
'toolbarStates': six.text_type(self.saveState().toHex(), 'utf-8'),
|
|
680
740
|
'consoleFont': self.console().font().toString(),
|
|
681
741
|
'uiAutoSaveSettingssACT': self.uiAutoSaveSettingssACT.isChecked(),
|
|
@@ -693,6 +753,10 @@ class LoggerWindow(Window):
|
|
|
693
753
|
),
|
|
694
754
|
'find_files_context': self.uiFindInWorkboxesWGT.uiContextSPN.value(),
|
|
695
755
|
'find_files_text': self.uiFindInWorkboxesWGT.uiFindTXT.text(),
|
|
756
|
+
'uiHighlightExactCompletionACT': (
|
|
757
|
+
self.uiHighlightExactCompletionACT.isChecked()
|
|
758
|
+
),
|
|
759
|
+
'dont_ask_again': self.dont_ask_again,
|
|
696
760
|
}
|
|
697
761
|
)
|
|
698
762
|
|
|
@@ -727,6 +791,15 @@ class LoggerWindow(Window):
|
|
|
727
791
|
with open(filename, 'w') as fp:
|
|
728
792
|
json.dump(pref, fp, indent=4)
|
|
729
793
|
|
|
794
|
+
def maybeDisplayDialog(self, dialog):
|
|
795
|
+
"""If user hasn't previously opted to not show this particular dialog again,
|
|
796
|
+
show it.
|
|
797
|
+
"""
|
|
798
|
+
if dialog.objectName() in self.dont_ask_again:
|
|
799
|
+
return
|
|
800
|
+
|
|
801
|
+
dialog.exec_()
|
|
802
|
+
|
|
730
803
|
def restartLogger(self):
|
|
731
804
|
"""Closes this PrEditor instance and starts a new process with the same
|
|
732
805
|
cli arguments.
|
|
@@ -776,21 +849,20 @@ class LoggerWindow(Window):
|
|
|
776
849
|
self.setWindowState(Qt.WindowStates(pref.get('windowState', 0)))
|
|
777
850
|
self.uiIndentationsTabsACT.setChecked(pref.get('tabIndent', True))
|
|
778
851
|
self.uiCopyTabsToSpacesACT.setChecked(pref.get('copyIndentsAsSpaces', False))
|
|
779
|
-
self.uiAutoCompleteEnabledACT.setChecked(pref.get('hintingEnabled', True))
|
|
780
852
|
|
|
781
853
|
# completer settings
|
|
782
854
|
self.setCaseSensitive(pref.get('caseSensitive', True))
|
|
783
855
|
completerMode = CompleterMode(pref.get('completerMode', 0))
|
|
784
856
|
self.cycleToCompleterMode(completerMode)
|
|
785
857
|
self.setCompleterMode(completerMode)
|
|
858
|
+
self.uiHighlightExactCompletionACT.setChecked(
|
|
859
|
+
pref.get('uiHighlightExactCompletionACT', False)
|
|
860
|
+
)
|
|
786
861
|
|
|
787
862
|
self.setSpellCheckEnabled(self.uiSpellCheckEnabledACT.isChecked())
|
|
788
863
|
self.uiSpellCheckEnabledACT.setChecked(pref.get('spellCheckEnabled', False))
|
|
789
864
|
self.uiSpellCheckEnabledACT.setDisabled(False)
|
|
790
865
|
|
|
791
|
-
self.uiConsoleTXT.completer().setEnabled(
|
|
792
|
-
self.uiAutoCompleteEnabledACT.isChecked()
|
|
793
|
-
)
|
|
794
866
|
self.uiAutoSaveSettingssACT.setChecked(pref.get('uiAutoSaveSettingssACT', True))
|
|
795
867
|
|
|
796
868
|
self.uiAutoPromptACT.setChecked(pref.get('uiAutoPromptACT', False))
|
|
@@ -814,7 +886,7 @@ class LoggerWindow(Window):
|
|
|
814
886
|
|
|
815
887
|
# External text editor filepath and command template
|
|
816
888
|
defaultExePath = r"C:\Program Files\Sublime Text 3\sublime_text.exe"
|
|
817
|
-
defaultCmd = r"{exePath} {modulePath}:{lineNum}
|
|
889
|
+
defaultCmd = r'"{exePath}" "{modulePath}":{lineNum}'
|
|
818
890
|
self.textEditorPath = pref.get('textEditorPath', defaultExePath)
|
|
819
891
|
self.textEditorCmdTempl = pref.get('textEditorCmdTempl', defaultCmd)
|
|
820
892
|
|
|
@@ -823,6 +895,7 @@ class LoggerWindow(Window):
|
|
|
823
895
|
self.uiClearBeforeRunningACT.setChecked(pref.get('clearBeforeRunning', False))
|
|
824
896
|
self.uiClearLogOnRefreshACT.setChecked(pref.get('clearBeforeEnvRefresh', False))
|
|
825
897
|
self.setClearBeforeRunning(self.uiClearBeforeRunningACT.isChecked())
|
|
898
|
+
self.uiSelectTextACT.setChecked(pref.get('uiSelectTextACT', True))
|
|
826
899
|
|
|
827
900
|
self._stylesheet = pref.get('currentStyleSheet', 'Bright')
|
|
828
901
|
if self._stylesheet == 'Custom':
|
|
@@ -833,6 +906,13 @@ class LoggerWindow(Window):
|
|
|
833
906
|
|
|
834
907
|
self.uiWorkboxTAB.restore_prefs(pref.get('workbox_prefs', {}))
|
|
835
908
|
|
|
909
|
+
hintingEnabled = pref.get('hintingEnabled', True)
|
|
910
|
+
self.uiConsoleAutoCompleteEnabledACT.setChecked(hintingEnabled)
|
|
911
|
+
self.setAutoCompleteEnabled(hintingEnabled, console=True)
|
|
912
|
+
workboxHintingEnabled = pref.get('workboxHintingEnabled', True)
|
|
913
|
+
self.uiWorkboxAutoCompleteEnabledACT.setChecked(workboxHintingEnabled)
|
|
914
|
+
self.setAutoCompleteEnabled(workboxHintingEnabled, console=False)
|
|
915
|
+
|
|
836
916
|
# Ensure the correct workbox stack page is shown
|
|
837
917
|
self.update_workbox_stack()
|
|
838
918
|
|
|
@@ -842,6 +922,8 @@ class LoggerWindow(Window):
|
|
|
842
922
|
if font.fromString(_font):
|
|
843
923
|
self.console().setConsoleFont(font)
|
|
844
924
|
|
|
925
|
+
self.dont_ask_again = pref.get('dont_ask_again', [])
|
|
926
|
+
|
|
845
927
|
def restoreToolbars(self, pref=None):
|
|
846
928
|
if pref is None:
|
|
847
929
|
pref = self.load_prefs()
|
|
@@ -851,10 +933,12 @@ class LoggerWindow(Window):
|
|
|
851
933
|
state = QByteArray.fromHex(bytes(state, 'utf-8'))
|
|
852
934
|
self.restoreState(state)
|
|
853
935
|
|
|
854
|
-
def setAutoCompleteEnabled(self, state):
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
936
|
+
def setAutoCompleteEnabled(self, state, console=True):
|
|
937
|
+
if console:
|
|
938
|
+
self.uiConsoleTXT.completer().setEnabled(state)
|
|
939
|
+
else:
|
|
940
|
+
for workbox, _, _, _, _ in self.uiWorkboxTAB.all_widgets():
|
|
941
|
+
workbox.__set_auto_complete_enabled__(state)
|
|
858
942
|
|
|
859
943
|
def setSpellCheckEnabled(self, state):
|
|
860
944
|
try:
|