PrEditor 0.3.0__py2.py3-none-any.whl → 0.5.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.

@@ -14,11 +14,11 @@ 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, QFontDatabase, QIcon, QTextCursor
17
+ from Qt.QtGui import QCursor, QFont, QIcon, QTextCursor
18
18
  from Qt.QtWidgets import (
19
19
  QApplication,
20
+ QFontDialog,
20
21
  QInputDialog,
21
- QLabel,
22
22
  QMessageBox,
23
23
  QTextBrowser,
24
24
  QToolTip,
@@ -44,6 +44,7 @@ from ..utils import stylesheets
44
44
  from .completer import CompleterMode
45
45
  from .level_buttons import LoggingLevelButton
46
46
  from .set_text_editor_path_dialog import SetTextEditorPathDialog
47
+ from .status_label import StatusLabel
47
48
 
48
49
 
49
50
  class WorkboxPages:
@@ -75,6 +76,7 @@ class LoggerWindow(Window):
75
76
  loadUi(__file__, self)
76
77
 
77
78
  self.uiConsoleTXT.flash_window = self
79
+ self.uiConsoleTXT.clearExecutionTime = self.clearExecutionTime
78
80
  self.uiConsoleTXT.reportExecutionTime = self.reportExecutionTime
79
81
  self.uiClearToLastPromptACT.triggered.connect(
80
82
  self.uiConsoleTXT.clearToLastPrompt
@@ -84,7 +86,7 @@ class LoggerWindow(Window):
84
86
  self.uiConsoleTXT.uiClearToLastPromptACT.setShortcut('')
85
87
 
86
88
  # create the status reporting label
87
- self.uiStatusLBL = QLabel(self)
89
+ self.uiStatusLBL = StatusLabel(self)
88
90
  self.uiMenuBar.setCornerWidget(self.uiStatusLBL)
89
91
 
90
92
  # create the workbox tabs
@@ -119,12 +121,38 @@ class LoggerWindow(Window):
119
121
  self.uiCloseLoggerACT.triggered.connect(self.closeLogger)
120
122
 
121
123
  self.uiRunAllACT.triggered.connect(self.execAll)
122
- self.uiRunSelectedACT.triggered.connect(self.execSelected)
124
+ # Even though the RunSelected actions (with shortcuts) are connected
125
+ # here, this only affects if the action is chosen from the menu. The
126
+ # shortcuts are always intercepted by the workbox document editor. To
127
+ # handle this, the workbox.keyPressEvent method will perceive the
128
+ # shortcut press, and call .execSelected, which will then ultimately call
129
+ # workbox.__exec_selected__
130
+ self.uiRunSelectedACT.triggered.connect(
131
+ partial(self.execSelected, truncate=True)
132
+ )
133
+ self.uiRunSelectedDontTruncateACT.triggered.connect(
134
+ partial(self.execSelected, truncate=False)
135
+ )
123
136
 
124
- self.uiAutoCompleteEnabledACT.toggled.connect(self.setAutoCompleteEnabled)
137
+ self.uiConsoleAutoCompleteEnabledACT.toggled.connect(
138
+ partial(self.setAutoCompleteEnabled, console=True)
139
+ )
140
+ self.uiWorkboxAutoCompleteEnabledACT.toggled.connect(
141
+ partial(self.setAutoCompleteEnabled, console=False)
142
+ )
125
143
 
126
144
  self.uiAutoCompleteCaseSensitiveACT.toggled.connect(self.setCaseSensitive)
127
145
 
146
+ self.uiSelectMonospaceFontACT.triggered.connect(
147
+ partial(self.selectFont, monospace=True)
148
+ )
149
+ self.uiSelectProportionalFontACT.triggered.connect(
150
+ partial(self.selectFont, proportional=True)
151
+ )
152
+ self.uiSelectAllFontACT.triggered.connect(
153
+ partial(self.selectFont, monospace=True, proportional=True)
154
+ )
155
+
128
156
  # Setup ability to cycle completer mode, and create action for each mode
129
157
  self.completerModeCycle = itertools.cycle(CompleterMode)
130
158
  # create CompleterMode submenu
@@ -234,27 +262,9 @@ class LoggerWindow(Window):
234
262
  # Make action shortcuts available anywhere in the Logger
235
263
  self.addAction(self.uiClearLogACT)
236
264
 
265
+ self.dont_ask_again = []
237
266
  self.restorePrefs()
238
267
 
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
268
  # add stylesheet menu options.
259
269
  for style_name in stylesheets.stylesheets():
260
270
  action = self.uiStyleMENU.addAction(style_name)
@@ -276,6 +286,9 @@ class LoggerWindow(Window):
276
286
  )
277
287
  )
278
288
 
289
+ self.setWorkboxFontBasedOnConsole()
290
+ self.setEditorChooserFontBasedOnConsole()
291
+
279
292
  self.setup_run_workbox()
280
293
 
281
294
  if not standalone:
@@ -429,7 +442,7 @@ class LoggerWindow(Window):
429
442
  if not workbox.hasFocus():
430
443
  return
431
444
 
432
- text = workbox.__selected_text__()
445
+ text, _line = workbox.__selected_text__(selectText=True)
433
446
  if not text:
434
447
  line, index = workbox.__cursor_position__()
435
448
  text = workbox.__text__(line)
@@ -513,15 +526,7 @@ class LoggerWindow(Window):
513
526
  newSize = font.pointSize() + delta
514
527
  newSize = max(min(newSize, maxSize), minSize)
515
528
 
516
- font.setPointSize(newSize)
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)
529
+ self.setFontSize(newSize)
525
530
  else:
526
531
  Window.wheelEvent(self, event)
527
532
 
@@ -539,41 +544,76 @@ class LoggerWindow(Window):
539
544
  menu = action.parentWidget()
540
545
  QToolTip.showText(QCursor.pos(), text, menu)
541
546
 
542
- def findCurrentFontAction(self):
543
- """Find and return current font's action"""
544
- actions = self.uiMonospaceFontMENU.actions()
545
- actions.extend(self.uiProportionalFontMENU.actions())
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
547
+ def selectFont(self, monospace=False, proportional=False):
548
+ """Present a QFontChooser dialog, offering, monospace, proportional, or all
549
+ fonts, based on user choice. If a font is chosen, set it on the console and
550
+ workboxes.
557
551
 
558
552
  Args:
559
553
  action (QAction): menu action associated with chosen font
560
554
  """
555
+ origFont = self.console().font()
556
+ curFontFamily = origFont.family()
557
+
558
+ if monospace and proportional:
559
+ options = QFontDialog.MonospacedFonts | QFontDialog.ProportionalFonts
560
+ kind = "monospace or proportional "
561
+ elif monospace:
562
+ options = QFontDialog.MonospacedFonts
563
+ kind = "monospace "
564
+ elif proportional:
565
+ options = QFontDialog.ProportionalFonts
566
+ kind = "proportional "
567
+
568
+ # Present a QFontDialog for user to choose a font
569
+ title = "Pick a {} font. Current font is: {}".format(kind, curFontFamily)
570
+ newFont, okClicked = QFontDialog.getFont(origFont, self, title, options=options)
571
+
572
+ if okClicked:
573
+ self.console().setConsoleFont(newFont)
574
+ self.setWorkboxFontBasedOnConsole()
575
+ self.setEditorChooserFontBasedOnConsole()
576
+
577
+ def setFontSize(self, newSize):
578
+ """Update the font size in the console and current workbox.
561
579
 
562
- actions = self.uiMonospaceFontMENU.actions()
563
- actions.extend(self.uiProportionalFontMENU.actions())
580
+ Args:
581
+ newSize (int): The new size to set the font
582
+ """
583
+ font = self.console().font()
584
+ font.setPointSize(newSize)
585
+ self.console().setConsoleFont(font)
564
586
 
565
- for act in actions:
566
- act.setChecked(act == action)
587
+ self.setWorkboxFontBasedOnConsole()
588
+ self.setEditorChooserFontBasedOnConsole()
567
589
 
568
- family = action.text()
590
+ def setWorkboxFontBasedOnConsole(self):
591
+ """If the current workbox's font is different to the console's font, set it to
592
+ match.
593
+ """
569
594
  font = self.console().font()
570
- font.setFamily(family)
571
- self.console().setConsoleFont(font)
572
595
 
573
- for workbox in self.uiWorkboxTAB.all_widgets():
596
+ workboxGroup = self.uiWorkboxTAB.currentWidget()
597
+ if workboxGroup is None:
598
+ return
599
+
600
+ workbox = workboxGroup.currentWidget()
601
+ if workbox is None:
602
+ return
603
+
604
+ if workbox.__font__() != font:
574
605
  workbox.__set_margins_font__(font)
575
606
  workbox.__set_font__(font)
576
607
 
608
+ def setEditorChooserFontBasedOnConsole(self):
609
+ """Set the EditorChooser font to match console. This helps with legibility when
610
+ using EditorChooser.
611
+ """
612
+ font = self.console().font()
613
+ for child in self.uiEditorChooserWGT.children():
614
+ if hasattr(child, "font"):
615
+ child.setFont(font)
616
+
577
617
  @classmethod
578
618
  def _genPrefName(cls, baseName, index):
579
619
  if index:
@@ -635,11 +675,21 @@ class LoggerWindow(Window):
635
675
  prompt = console.prompt()
636
676
  console.startPrompt(prompt)
637
677
 
638
- def execSelected(self):
639
- """Clears the console before executing selected workbox code"""
678
+ def execSelected(self, truncate=True):
679
+ """Clears the console before executing selected workbox code.
680
+
681
+ NOTE! This method is not called when the uiRunSelectedACT is triggered,
682
+ because the workbox will always intercept it. So instead, the workbox's
683
+ keyPressEvent will notice the shortcut and call this method.
684
+ """
685
+
640
686
  if self.uiClearBeforeRunningACT.isChecked():
641
687
  self.clearLog()
642
- self.current_workbox().__exec_selected__()
688
+
689
+ self.current_workbox().__exec_selected__(truncate=truncate)
690
+
691
+ if self.uiAutoPromptACT.isChecked():
692
+ self.console().startInputLine()
643
693
 
644
694
  def keyPressEvent(self, event):
645
695
  # Fix 'Maya : Qt tools lose focus' https://redmine.blur.com/issues/34430
@@ -652,9 +702,15 @@ class LoggerWindow(Window):
652
702
  if self.uiClearLogOnRefreshACT.isChecked():
653
703
  self.clearLog()
654
704
 
705
+ def clearExecutionTime(self):
706
+ """Update status text with hyphens to indicate execution has begun."""
707
+ self.setStatusText('Exec: -.- Seconds')
708
+ QApplication.instance().processEvents()
709
+
655
710
  def reportExecutionTime(self, seconds):
656
711
  """Update status text with seconds passed in."""
657
- self.setStatusText('Exec: {:0.04f} Seconds'.format(seconds))
712
+ self.uiStatusLBL.showSeconds(seconds)
713
+ self.uiMenuBar.adjustSize()
658
714
 
659
715
  def recordPrefs(self, manual=False):
660
716
  if not manual and not self.uiAutoSaveSettingssACT.isChecked():
@@ -670,17 +726,22 @@ class LoggerWindow(Window):
670
726
  'SplitterSize': self.uiSplitterSPLIT.sizes(),
671
727
  'tabIndent': self.uiIndentationsTabsACT.isChecked(),
672
728
  'copyIndentsAsSpaces': self.uiCopyTabsToSpacesACT.isChecked(),
673
- 'hintingEnabled': self.uiAutoCompleteEnabledACT.isChecked(),
729
+ 'hintingEnabled': self.uiConsoleAutoCompleteEnabledACT.isChecked(),
730
+ 'workboxHintingEnabled': (
731
+ self.uiWorkboxAutoCompleteEnabledACT.isChecked()
732
+ ),
674
733
  'spellCheckEnabled': self.uiSpellCheckEnabledACT.isChecked(),
675
734
  'wordWrap': self.uiWordWrapACT.isChecked(),
676
735
  'clearBeforeRunning': self.uiClearBeforeRunningACT.isChecked(),
677
736
  'clearBeforeEnvRefresh': self.uiClearLogOnRefreshACT.isChecked(),
737
+ 'uiSelectTextACT': self.uiSelectTextACT.isChecked(),
678
738
  'toolbarStates': six.text_type(self.saveState().toHex(), 'utf-8'),
679
739
  'consoleFont': self.console().font().toString(),
680
740
  'uiAutoSaveSettingssACT': self.uiAutoSaveSettingssACT.isChecked(),
681
741
  'uiAutoPromptACT': self.uiAutoPromptACT.isChecked(),
682
742
  'uiLinesInNewWorkboxACT': self.uiLinesInNewWorkboxACT.isChecked(),
683
743
  'uiErrorHyperlinksACT': self.uiErrorHyperlinksACT.isChecked(),
744
+ 'uiStatusLbl_limit': self.uiStatusLBL.limit(),
684
745
  'textEditorPath': self.textEditorPath,
685
746
  'textEditorCmdTempl': self.textEditorCmdTempl,
686
747
  'currentStyleSheet': self._stylesheet,
@@ -691,6 +752,10 @@ class LoggerWindow(Window):
691
752
  ),
692
753
  'find_files_context': self.uiFindInWorkboxesWGT.uiContextSPN.value(),
693
754
  'find_files_text': self.uiFindInWorkboxesWGT.uiFindTXT.text(),
755
+ 'uiHighlightExactCompletionACT': (
756
+ self.uiHighlightExactCompletionACT.isChecked()
757
+ ),
758
+ 'dont_ask_again': self.dont_ask_again,
694
759
  }
695
760
  )
696
761
 
@@ -725,6 +790,15 @@ class LoggerWindow(Window):
725
790
  with open(filename, 'w') as fp:
726
791
  json.dump(pref, fp, indent=4)
727
792
 
793
+ def maybeDisplayDialog(self, dialog):
794
+ """If user hasn't previously opted to not show this particular dialog again,
795
+ show it.
796
+ """
797
+ if dialog.objectName() in self.dont_ask_again:
798
+ return
799
+
800
+ dialog.exec_()
801
+
728
802
  def restartLogger(self):
729
803
  """Closes this PrEditor instance and starts a new process with the same
730
804
  cli arguments.
@@ -774,21 +848,20 @@ class LoggerWindow(Window):
774
848
  self.setWindowState(Qt.WindowStates(pref.get('windowState', 0)))
775
849
  self.uiIndentationsTabsACT.setChecked(pref.get('tabIndent', True))
776
850
  self.uiCopyTabsToSpacesACT.setChecked(pref.get('copyIndentsAsSpaces', False))
777
- self.uiAutoCompleteEnabledACT.setChecked(pref.get('hintingEnabled', True))
778
851
 
779
852
  # completer settings
780
853
  self.setCaseSensitive(pref.get('caseSensitive', True))
781
854
  completerMode = CompleterMode(pref.get('completerMode', 0))
782
855
  self.cycleToCompleterMode(completerMode)
783
856
  self.setCompleterMode(completerMode)
857
+ self.uiHighlightExactCompletionACT.setChecked(
858
+ pref.get('uiHighlightExactCompletionACT', False)
859
+ )
784
860
 
785
861
  self.setSpellCheckEnabled(self.uiSpellCheckEnabledACT.isChecked())
786
862
  self.uiSpellCheckEnabledACT.setChecked(pref.get('spellCheckEnabled', False))
787
863
  self.uiSpellCheckEnabledACT.setDisabled(False)
788
864
 
789
- self.uiConsoleTXT.completer().setEnabled(
790
- self.uiAutoCompleteEnabledACT.isChecked()
791
- )
792
865
  self.uiAutoSaveSettingssACT.setChecked(pref.get('uiAutoSaveSettingssACT', True))
793
866
 
794
867
  self.uiAutoPromptACT.setChecked(pref.get('uiAutoPromptACT', False))
@@ -796,6 +869,7 @@ class LoggerWindow(Window):
796
869
  pref.get('uiLinesInNewWorkboxACT', False)
797
870
  )
798
871
  self.uiErrorHyperlinksACT.setChecked(pref.get('uiErrorHyperlinksACT', True))
872
+ self.uiStatusLBL.setLimit(pref.get('uiStatusLbl_limit', 5))
799
873
 
800
874
  # Find Files settings
801
875
  self.uiFindInWorkboxesWGT.uiRegexBTN.setChecked(
@@ -811,7 +885,7 @@ class LoggerWindow(Window):
811
885
 
812
886
  # External text editor filepath and command template
813
887
  defaultExePath = r"C:\Program Files\Sublime Text 3\sublime_text.exe"
814
- defaultCmd = r"{exePath} {modulePath}:{lineNum}"
888
+ defaultCmd = r'"{exePath}" "{modulePath}":{lineNum}'
815
889
  self.textEditorPath = pref.get('textEditorPath', defaultExePath)
816
890
  self.textEditorCmdTempl = pref.get('textEditorCmdTempl', defaultCmd)
817
891
 
@@ -820,6 +894,7 @@ class LoggerWindow(Window):
820
894
  self.uiClearBeforeRunningACT.setChecked(pref.get('clearBeforeRunning', False))
821
895
  self.uiClearLogOnRefreshACT.setChecked(pref.get('clearBeforeEnvRefresh', False))
822
896
  self.setClearBeforeRunning(self.uiClearBeforeRunningACT.isChecked())
897
+ self.uiSelectTextACT.setChecked(pref.get('uiSelectTextACT', True))
823
898
 
824
899
  self._stylesheet = pref.get('currentStyleSheet', 'Bright')
825
900
  if self._stylesheet == 'Custom':
@@ -830,6 +905,13 @@ class LoggerWindow(Window):
830
905
 
831
906
  self.uiWorkboxTAB.restore_prefs(pref.get('workbox_prefs', {}))
832
907
 
908
+ hintingEnabled = pref.get('hintingEnabled', True)
909
+ self.uiConsoleAutoCompleteEnabledACT.setChecked(hintingEnabled)
910
+ self.setAutoCompleteEnabled(hintingEnabled, console=True)
911
+ workboxHintingEnabled = pref.get('workboxHintingEnabled', True)
912
+ self.uiWorkboxAutoCompleteEnabledACT.setChecked(workboxHintingEnabled)
913
+ self.setAutoCompleteEnabled(workboxHintingEnabled, console=False)
914
+
833
915
  # Ensure the correct workbox stack page is shown
834
916
  self.update_workbox_stack()
835
917
 
@@ -839,6 +921,8 @@ class LoggerWindow(Window):
839
921
  if font.fromString(_font):
840
922
  self.console().setConsoleFont(font)
841
923
 
924
+ self.dont_ask_again = pref.get('dont_ask_again', [])
925
+
842
926
  def restoreToolbars(self, pref=None):
843
927
  if pref is None:
844
928
  pref = self.load_prefs()
@@ -848,10 +932,12 @@ class LoggerWindow(Window):
848
932
  state = QByteArray.fromHex(bytes(state, 'utf-8'))
849
933
  self.restoreState(state)
850
934
 
851
- def setAutoCompleteEnabled(self, state):
852
- self.uiConsoleTXT.completer().setEnabled(state)
853
- for workbox, _, _, _, _ in self.uiWorkboxTAB.all_widgets():
854
- workbox.__set_auto_complete_enabled__(state)
935
+ def setAutoCompleteEnabled(self, state, console=True):
936
+ if console:
937
+ self.uiConsoleTXT.completer().setEnabled(state)
938
+ else:
939
+ for workbox, _, _, _, _ in self.uiWorkboxTAB.all_widgets():
940
+ workbox.__set_auto_complete_enabled__(state)
855
941
 
856
942
  def setSpellCheckEnabled(self, state):
857
943
  try:
@@ -876,7 +962,7 @@ class LoggerWindow(Window):
876
962
 
877
963
  def clearStatusText(self):
878
964
  """Clear any displayed status text"""
879
- self.uiStatusLBL.setText('')
965
+ self.uiStatusLBL.clear()
880
966
  self.uiMenuBar.adjustSize()
881
967
 
882
968
  def autoHideStatusText(self):
@@ -17,7 +17,7 @@ class SetTextEditorPathDialog(QDialog):
17
17
  super(SetTextEditorPathDialog, self).__init__(parent)
18
18
  loadUi(__file__, self)
19
19
 
20
- # Rerieve existing data from LoggerWindow
20
+ # Retrieve existing data from LoggerWindow
21
21
  path = self.parent().textEditorPath
22
22
  cmdTempl = self.parent().textEditorCmdTempl
23
23
 
@@ -29,9 +29,9 @@ class SetTextEditorPathDialog(QDialog):
29
29
 
30
30
  toolTip = (
31
31
  "Examples:\n"
32
- "SublimeText: {exePath} {modulePath}:{lineNum}\n"
33
- "notepad++: {exePath} {modulePath} -n{lineNum}\n"
34
- "vim: {exePath} +{lineNum} {modulePath}"
32
+ 'SublimeText: "{exePath}" "{modulePath}":{lineNum}\n'
33
+ 'notepad++: "{exePath}" "{modulePath}" -n{lineNum}\n'
34
+ 'vim: "{exePath}" + {lineNum} "{modulePath}'
35
35
  )
36
36
  self.uiTextEditorCommandPatternLE.setToolTip(toolTip)
37
37
 
@@ -0,0 +1,90 @@
1
+ from __future__ import absolute_import
2
+
3
+ from collections import deque
4
+
5
+ from Qt.QtCore import QPoint, QTimer
6
+ from Qt.QtWidgets import QInputDialog, QLabel, QMenu
7
+
8
+
9
+ class StatusLabel(QLabel):
10
+ """A label that shows text and an average of code execution times in popup menu."""
11
+
12
+ def __init__(self, *args, limit=5, **kwargs):
13
+ self.render_as_href = False
14
+ super(StatusLabel, self).__init__(*args, **kwargs)
15
+ self.times = deque(maxlen=limit)
16
+
17
+ def clear(self):
18
+ self.setText("")
19
+
20
+ def clearTimes(self):
21
+ """"""
22
+ self.times.clear()
23
+
24
+ def chooseLimit(self):
25
+ limit, success = QInputDialog.getInt(
26
+ self,
27
+ "Choose Avg length",
28
+ "Choose how many execution time history to keep.",
29
+ value=self.limit(),
30
+ min=1,
31
+ max=100,
32
+ )
33
+ if limit:
34
+ self.setLimit(limit)
35
+
36
+ def mouseReleaseEvent(self, event):
37
+ QTimer.singleShot(0, self.showMenu)
38
+ super(StatusLabel, self).mouseReleaseEvent(event)
39
+
40
+ def secondsText(self, seconds):
41
+ """Generates text to show seconds of exec time."""
42
+ return 'Exec: {:0.04f} Seconds'.format(seconds)
43
+
44
+ def limit(self):
45
+ return self.times.maxlen
46
+
47
+ def setLimit(self, limit):
48
+ self.times = deque(self.times, maxlen=limit)
49
+
50
+ def setText(self, text):
51
+ if self.render_as_href:
52
+ text = '<a href="showMenu">{}</a>'.format(text)
53
+ super(StatusLabel, self).setText(text)
54
+
55
+ def showSeconds(self, seconds):
56
+ self.times.append(seconds)
57
+ self.setText(self.secondsText(seconds[0]))
58
+
59
+ def showMenu(self):
60
+ menu = QMenu(self)
61
+ if self.times:
62
+ # Show the time it took to run the last X code calls
63
+ times = []
64
+ for seconds in self.times:
65
+ secs, cmd = seconds
66
+ times.append(secs)
67
+
68
+ # Add a simplified copy of the command that was run
69
+ cmd = cmd.strip()
70
+ cmds = cmd.split("\n")
71
+ if len(cmds) > 1 or len(cmds[0]) > 50:
72
+ cmd = "{} ...".format(cmds[0][:50])
73
+ # Escape &'s so they dont' get turned into a shortcut'
74
+ cmd = cmd.replace("&", "&&")
75
+ menu.addAction("{}: {}".format(self.secondsText(secs), cmd))
76
+
77
+ menu.addSeparator()
78
+ avg = sum(times) / len(times)
79
+ menu.addAction("Average: {:0.04f}s".format(avg))
80
+ act = menu.addAction("Clear")
81
+ act.triggered.connect(self.clearTimes)
82
+
83
+ menu.addSeparator()
84
+ act = menu.addAction("Set limit...")
85
+ act.triggered.connect(self.chooseLimit)
86
+
87
+ # Position the menu at the bottom of the widget
88
+ height = self.geometry().height()
89
+ pos = self.mapToGlobal(QPoint(0, height))
90
+ menu.popup(pos)
@@ -0,0 +1,50 @@
1
+ from __future__ import absolute_import
2
+
3
+ from Qt.QtWidgets import QDialog
4
+
5
+ from . import loadUi
6
+
7
+
8
+ class SuggestPathQuotesDialog(QDialog):
9
+ """A dialog to suggest to enclose paths in double-quotes in the cmdTempl which is
10
+ used to launch an external text editor.
11
+ """
12
+
13
+ def __init__(self, parent, oldCmdTempl, newCmdTempl):
14
+ super(SuggestPathQuotesDialog, self).__init__(parent)
15
+ loadUi(__file__, self)
16
+
17
+ self.parentWindow = self.parent().window()
18
+
19
+ self.uiTextEditorOldCommandPatternLE.setText(oldCmdTempl)
20
+ self.uiTextEditorNewCommandPatternLE.setText(newCmdTempl)
21
+
22
+ toolTip = (
23
+ "Examples:\n"
24
+ 'SublimeText: "{exePath}" "{modulePath}":{lineNum}\n'
25
+ 'notepad++: "{exePath}" "{modulePath}" -n{lineNum}\n'
26
+ 'vim: "{exePath}" + {lineNum} "{modulePath}'
27
+ )
28
+ self.uiTextEditorNewCommandPatternLE.setToolTip(toolTip)
29
+
30
+ def accept(self):
31
+ """Set the parentWindow's textEditorCmdTempl property from the dialog, and
32
+ optionally add dialog to parent's dont_ask_again list, and accept.
33
+ """
34
+
35
+ cmdTempl = self.uiTextEditorNewCommandPatternLE.text()
36
+ self.parentWindow.textEditorCmdTempl = cmdTempl
37
+
38
+ if self.uiDontAskAgainCHK.isChecked():
39
+ if hasattr(self.parentWindow, "dont_ask_again"):
40
+ self.parentWindow.dont_ask_again.append(self.objectName())
41
+
42
+ super(SuggestPathQuotesDialog, self).accept()
43
+
44
+ def reject(self):
45
+ """Optionally add dialog to parentWindow's dont_ask_again list, and reject"""
46
+ if self.uiDontAskAgainCHK.isChecked():
47
+ if hasattr(self.parentWindow, "dont_ask_again"):
48
+ self.parentWindow.dont_ask_again.append(self.objectName())
49
+
50
+ super(SuggestPathQuotesDialog, self).reject()