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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PrEditor
3
- Version: 0.1.0rc2
3
+ Version: 0.3.0
4
4
  Summary: A python REPL and Editor and console based on Qt.
5
5
  Home-page: https://github.com/blurstudio/PrEditor.git
6
6
  Author: Blur Studio
@@ -20,13 +20,13 @@ Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: Qt.py
23
- Requires-Dist: configparser (>=4.0.2)
24
- Requires-Dist: future (>=0.18.2)
25
- Requires-Dist: python-redmine (>=2.1.1)
26
- Requires-Dist: signalslot (>=0.1.2)
27
- Requires-Dist: importlib-metadata (>=4.8.3) ; python_version >= "3.6"
23
+ Requires-Dist: configparser >=4.0.2
24
+ Requires-Dist: future >=0.18.2
25
+ Requires-Dist: python-redmine >=2.1.1
26
+ Requires-Dist: signalslot >=0.1.2
27
+ Requires-Dist: importlib-metadata >=4.8.3 ; python_version >= "3.6"
28
28
  Provides-Extra: cli
29
- Requires-Dist: click (>=7.1.2) ; extra == 'cli'
29
+ Requires-Dist: click >=7.1.2 ; extra == 'cli'
30
30
  Requires-Dist: click-default-group ; extra == 'cli'
31
31
  Provides-Extra: dev
32
32
  Requires-Dist: black ; extra == 'dev'
@@ -38,7 +38,7 @@ Requires-Dist: pep8-naming ; extra == 'dev'
38
38
  Requires-Dist: pytest ; extra == 'dev'
39
39
  Requires-Dist: tox ; extra == 'dev'
40
40
  Provides-Extra: shortcut
41
- Requires-Dist: casement (>=0.1.0) ; (platform_system == "Windows") and extra == 'shortcut'
41
+ Requires-Dist: casement >=0.1.0 ; (platform_system == "Windows") and extra == 'shortcut'
42
42
 
43
43
  # PrEditor
44
44
 
@@ -1,7 +1,7 @@
1
- preditor/__init__.py,sha256=9EeqALlJ18tsP6kuvg8jk93dxRJp8WqFUHckxg6BVaQ,10323
1
+ preditor/__init__.py,sha256=JlIK0Gp7g7DsKbyt1c5PMD9-3EyeE7q7wv1sJmhrlYc,10585
2
2
  preditor/__main__.py,sha256=boRVSmxX6eF8EkzbePtCZbzdcaPseqVae4RPPLp3U1A,449
3
3
  preditor/about_module.py,sha256=KIvCxZrMLhm5TR6lYskM4Y9VctJ0QtSQD5Nu8Ip1CGY,5267
4
- preditor/cli.py,sha256=xwW75wPHp-fjSQoZ5LXSvCJnQktt-LI5hfi07BhLvmg,5283
4
+ preditor/cli.py,sha256=kyVr0V43KYSMLIEWXH54CA0ByFmPcpbFF-8cli6PVow,5300
5
5
  preditor/contexts.py,sha256=xxRbOFORsvlG___EuSiKuT1aiKJvnkFojFZFZE0HPNk,5147
6
6
  preditor/debug.py,sha256=xcOslCByK7nSebh5DR6m-uC6uV9tuJBZu-JAAPBl8aA,9515
7
7
  preditor/enum.py,sha256=snG5V259dH9SI1kwBqZeZdhat36F1iAmIjYErosnDUg,23489
@@ -11,7 +11,7 @@ preditor/plugins.py,sha256=W3DfdDEE5DtEXOXioEyIe4tuIVV1V-RLcV8LoZJWpWU,1916
11
11
  preditor/prefs.py,sha256=BPtSsdv2yuiRpIaqEml9fxlVYKHNfqQ77hp5YIQRDBg,2172
12
12
  preditor/settings.py,sha256=DV9_DbJorEnhdIvW15E7h7PswlQUsy0UlA8bXUYN0og,2206
13
13
  preditor/streamhandler_helper.py,sha256=kiU6T9WqJ3JKTTKCa7IUU8brwK7zO5UUpEzLhEfKe44,1788
14
- preditor/version.py,sha256=Ff7DlJZp6xbq0kxOMwDY4PnhOQdzCeVT0lbvo05JvRo,150
14
+ preditor/version.py,sha256=YNd1dEdZGzG2MvXfaTQdmMYCLOQm-rV09_xmC5Hxu5Y,142
15
15
  preditor/weakref.py,sha256=b--KomFAHcMWr3DEAIN2j3XxRhjDWKw0WABXyn1nxDg,12177
16
16
  preditor/cores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  preditor/cores/core.py,sha256=ZXB4bts05DMQtc-dtkk81chIWNqYXImMuWCYuUHwLdA,2389
@@ -28,30 +28,35 @@ preditor/gui/dialog.py,sha256=Vw8Wflb2P3TngO8b-2suWP6JKHBVHdbGgYiRDKzYRlQ,7488
28
28
  preditor/gui/drag_tab_bar.py,sha256=5J-BSKQzS6_WuYxxGqmnUJr6AriTAvwfVK7Q3p7knrM,7933
29
29
  preditor/gui/editor_chooser.py,sha256=v82SPuxPgai3XiRWi9ypT0aRkbV6_IrbfBoAljM9pRY,1986
30
30
  preditor/gui/errordialog.py,sha256=FZzSykNtqgTZ-CKEsLFXfcw_k8zwx7g_aMaHbpnq2xI,3110
31
+ preditor/gui/find_files.py,sha256=eG935f9Xbh7F1M8IK7PKko84a37shoaoplQitPMv_-c,4116
31
32
  preditor/gui/level_buttons.py,sha256=yPFIWKc0bgKLrP2XHyBqNuvvTnXZqGdtN_p27jSb1Og,11925
32
33
  preditor/gui/logger_window_handler.py,sha256=VTNhaoFUnConE3NHj9KaDZlVoifix8xCbCuN5Ozjz0M,1482
33
- preditor/gui/loggerwindow.py,sha256=JM4PIEso1Sw4AtsIXzpvT52ALxVSsvbE4FXsEK3jnm8,42537
34
+ preditor/gui/loggerwindow.py,sha256=_f7T6e04pFHF1MZQYE77JvAHUQnJ28TS7CPGizNS2yo,47589
34
35
  preditor/gui/newtabwidget.py,sha256=5aCWn9xAl5h1oZACqVuEsOAbzKTS2RegrLI41gROC8A,1971
35
36
  preditor/gui/redmine_login_dialog.py,sha256=cMPBuecSZD5yjycNkMwHa1AbdwgGoyHvX8anIvWjEFo,1893
36
37
  preditor/gui/set_text_editor_path_dialog.py,sha256=6mbHAXEVQhaWyg0N67f54aZpd5fp6puGWzeM0tPepiU,2251
37
38
  preditor/gui/window.py,sha256=bZAEKQDM6V4aew1nlSTPyq_tG-_IoSvyXHcZxrdFMaE,6924
38
- preditor/gui/workbox_mixin.py,sha256=8Lk7zxM4sl6__28LDOlDpqDKhooqDQba9ZYPsikEFds,11174
39
- preditor/gui/workbox_text_edit.py,sha256=gc0QT--zX2Z3q-PAbod3eqjFDWQaoGQxWNygTfrEl5U,3890
40
- preditor/gui/workboxwidget.py,sha256=JZzM3HUmtaEcXOq6-rNucP0WV4ZwUhqqZMwR18fnk-w,9208
41
- preditor/gui/group_tab_widget/__init__.py,sha256=Jh3QeDbH7UhIELJAxZ7F7r6dc-pq4_82lmp03cej96g,12157
39
+ preditor/gui/workbox_mixin.py,sha256=4tUiOWRFc0tEOAAo9BDD3idlkfO6t4VCuL4tklYNnTY,12543
40
+ preditor/gui/workbox_text_edit.py,sha256=fJY7eo1bpMyzLri5DfdVb2vad9znJjBvzLkY34T8gb4,3678
41
+ preditor/gui/workboxwidget.py,sha256=1uGSPZv3GxmOAIsA4oTaiPUHl003Yp6IA_rXanIToC4,8966
42
+ preditor/gui/fuzzy_search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ preditor/gui/fuzzy_search/fuzzy_search.py,sha256=6npanW6aLmG_ezdHmpsKN7p2zwck_Qq6YUy9duCNN8Q,3595
44
+ preditor/gui/group_tab_widget/__init__.py,sha256=KpQKkX_FyFQLy2UtBQcLoMuj0eRA7E_2-KXrTwPqA9k,12530
42
45
  preditor/gui/group_tab_widget/grouped_tab_menu.py,sha256=lopd3mjHJIE_5xLdlZL0ghuBzsYo36vO1OZE6L6tqbI,1288
46
+ preditor/gui/group_tab_widget/grouped_tab_models.py,sha256=zlmbcv3JAC5BzjKpm4CM7Hobibm1T_3GjaPoWIQbXiQ,3970
43
47
  preditor/gui/group_tab_widget/grouped_tab_widget.py,sha256=EwzYVqhJaBaYS9tdd4FXUl-PxjplWtOi7f0t99De_bw,2803
44
48
  preditor/gui/group_tab_widget/one_tab_widget.py,sha256=PdZAXjmV9oTHakh8aFYRlLnfwcoT459vQWVKgpZZx4Y,1971
45
49
  preditor/gui/ui/editor_chooser.ui,sha256=cYSVHK0A4-zst6JyDkrBZK9qcAontbhV4Mmnw5ps72E,2736
46
50
  preditor/gui/ui/errordialog.ui,sha256=H1wJJVU1t7kbnYkzGtGa8SBVpKjesJG_0imdBkJaEUY,2034
47
- preditor/gui/ui/loggerwindow.ui,sha256=e2Y7kSyP__d1I8ixFNZLzrEdfAbfdC-TqPVUJ7Urr0U,28476
51
+ preditor/gui/ui/find_files.ui,sha256=8mdD3Vg3ofRMChdKntxiDHO3JXHQSKjjY6OLY_1W5lc,3328
52
+ preditor/gui/ui/loggerwindow.ui,sha256=JVpvGWrnI4cQdX4DFwfsCMEnNh1iipc1Vxihcg8FJvU,30035
48
53
  preditor/gui/ui/redmine_login_dialog.ui,sha256=PmGuJWvBcSDLya5UblFj5brwDH9VL2fJEveH-r5-nJ8,2911
49
54
  preditor/gui/ui/set_text_editor_path_dialog.ui,sha256=QoSorDlyfUoNSrHQRP1Yrls5az4TyUsTQw_qYOe_Ljc,4004
50
55
  preditor/resource/environment_variables.html,sha256=-uWicgOkour-sxtY-crrjMiLMyJzAzshwUXKqSm6TmI,3134
51
56
  preditor/resource/error_mail.html,sha256=oCzynF3QSHi_Xg1wlmU5M5u1Q05mp7QV0ZtQ4e8KQDA,2400
52
57
  preditor/resource/error_mail_inline.html,sha256=ceZ8HReyTirMOX-xNgVB9kMO8QhpbHI4-WObFeOG9KY,4014
53
58
  preditor/resource/settings.ini,sha256=JhPumV7SzlRTZG3Fs1dxPokat3bthfZPw84lJ7E9zPQ,893
54
- preditor/resource/img/README.md,sha256=Opxd7axkbUhMvxRcTLLlB95z7Iuu6dITNKP-jvCs_Pc,309
59
+ preditor/resource/img/README.md,sha256=gJo4tydTyeZgUlpoEjiNI7SHlKz5Y-e8aE8Yb7mPrHk,1025
55
60
  preditor/resource/img/arrow_forward.png,sha256=41jN4EuemyaZtJ1vcynlAvCGRPJmq3NYq1HeWBGRbko,426
56
61
  preditor/resource/img/check-bold.png,sha256=FLu28U1BTyUaljouxEGaoHXhG2z4OzvL57MfMSwAnSI,500
57
62
  preditor/resource/img/chevron-down.png,sha256=4GNzTPW-q4LR_3tHj1ymlHsRymVma9J_N1eUvNboTJw,451
@@ -70,6 +75,7 @@ preditor/resource/img/file-remove.png,sha256=pnJVe9EBzvpMq8G7ikY_DXXDhM9e2m2pJtP
70
75
  preditor/resource/img/format-align-left.png,sha256=y2ixRoDurohX5E5ddxr4tVib_bczRRT7DN9CBDhDmcw,331
71
76
  preditor/resource/img/format-letter-case-lower.png,sha256=CkqlY2HABrGLyCEkDC8CPI4To873uNysB-f5PUK1gJA,978
72
77
  preditor/resource/img/format-letter-case-upper.png,sha256=NECM28lYBHhnQ_GgKvgli2xbCbiVylNyfWY7VVNpSXw,977
78
+ preditor/resource/img/format-letter-case.svg,sha256=iny15GecoxoRdExnnPNNWQqpqoWicDSTBSV8kRIYF3M,964
73
79
  preditor/resource/img/information.png,sha256=vb_-kGXq2T_zeAJlrt5FJGSK8WUFYstzQl8WuMSfs5I,778
74
80
  preditor/resource/img/logging_critical.png,sha256=lj4U6l8iRcgmWZWxdaJALvWn_KQELiqY936ZkPlRWJU,151
75
81
  preditor/resource/img/logging_custom.png,sha256=zmVRkBX2CVjqD8QdnRKxv7Jss1114bhBt6vpDVkxxdo,297
@@ -86,6 +92,8 @@ preditor/resource/img/preditor.ico,sha256=HjJbjJ3MYBmw5pFmkY2hEaomK-zPO7LJsOgGgA
86
92
  preditor/resource/img/preditor.png,sha256=y-AdFUy_zDnkylDe8kX1BTfwZS_TIgmEBqrHhx_IhWE,32788
87
93
  preditor/resource/img/preditor.psd,sha256=SZgadVDuDAzlUcg6ymlfAL7uw_JzLb1PsmkSAoSazv0,200136
88
94
  preditor/resource/img/preditor.svg,sha256=MRsRxcZw3HSJ4ZRDA3XMLytJX34QPJVIAET4lG613KU,3804
95
+ preditor/resource/img/regex.svg,sha256=nIZ6QnNUycEYB9wacB8-DcxzDdcb1ris0ewi3DzGwlM,682
96
+ preditor/resource/img/restart.svg,sha256=v3CFD1bROBch5n8vSQAzQqQc-bzvL_YwkD0JAhn4fuc,403
89
97
  preditor/resource/img/skip-forward-outline.png,sha256=5PAOknMYBZcuzskG8OO_QGAjLvA8g9M08MgjTvxfDrM,475
90
98
  preditor/resource/img/skip-next-outline.png,sha256=FUTDclE-U4nF5JhjvX-31QTwfv5pKgaX4UziY6UUioU,478
91
99
  preditor/resource/img/skip-next.png,sha256=q9V896VWgwatGShqSL7Ebv8sia3Q2XwBv5Y4KaZA60o,446
@@ -132,14 +140,15 @@ preditor/scintilla/lexers/mulexer.py,sha256=Y2FVp6ZJ9CgLIuIvItOzXMMRemuToID66dpB
132
140
  preditor/scintilla/lexers/pythonlexer.py,sha256=WgL74RQGvGgsdAL-l2ioOMybqRw7M0GG-SxmzXsW4xw,1682
133
141
  preditor/scintilla/ui/finddialog.ui,sha256=CEXouVKqVCDOfMBciK-89OmsGe2Kr6XdMbSPiffp0PA,4048
134
142
  preditor/stream/__init__.py,sha256=SxILA3U3W8aNfVBd_oJ4-WXkA214cl1zGLSCelFx5QU,2682
135
- preditor/stream/director.py,sha256=ymay-JYrw96MwLiR7DoFJ9af3BhTODJSoEPNnkivOuE,1915
143
+ preditor/stream/director.py,sha256=Gklbl6jwTmB0BtyR6MZxRytdlufaz5MoiW9Le9WFTmo,2733
136
144
  preditor/stream/manager.py,sha256=NP4lf6hd5L_Ui-9Ws66gVEk6ZL8YqF7BxOzUsdrh3v0,2811
137
145
  preditor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
146
  preditor/utils/cute.py,sha256=LfF8gXMAkkQAdo4mm6J9aVkDLwWZbE6prQ0moDbtCys,1045
139
147
  preditor/utils/stylesheets.py,sha256=EVWZNq3WnaRiyUPoYMKQo_dLEwbRyKu26b03I1JDA-s,1622
140
- PrEditor-0.1.0rc2.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
141
- PrEditor-0.1.0rc2.dist-info/METADATA,sha256=w6CX92U_pkq-JVEWhGZKWkvaZQXXQqwaXPavac2G2Ac,9294
142
- PrEditor-0.1.0rc2.dist-info/WHEEL,sha256=k3vXr0c0OitO0k9eCWBlI2yTYnpb_n_I2SGzrrfY7HY,110
143
- PrEditor-0.1.0rc2.dist-info/entry_points.txt,sha256=mpe0HFD_oIEBNPTJNyUEbmMV6Ivrp4EuYyZ34C5d_PU,519
144
- PrEditor-0.1.0rc2.dist-info/top_level.txt,sha256=iX1_mrUOky_BQr2oG0l_MbEUYF6idyjiWSzu9z3irIw,9
145
- PrEditor-0.1.0rc2.dist-info/RECORD,,
148
+ preditor/utils/text_search.py,sha256=21kuSDTpLIPUcriB81WP1kWfzuDBuP13ZtHUtypP5jE,14218
149
+ PrEditor-0.3.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
150
+ PrEditor-0.3.0.dist-info/METADATA,sha256=wl3HFhDCOPwPoRizXgfCytrF8KIK8T9ov7lYFXm51FI,9277
151
+ PrEditor-0.3.0.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
152
+ PrEditor-0.3.0.dist-info/entry_points.txt,sha256=mpe0HFD_oIEBNPTJNyUEbmMV6Ivrp4EuYyZ34C5d_PU,519
153
+ PrEditor-0.3.0.dist-info/top_level.txt,sha256=iX1_mrUOky_BQr2oG0l_MbEUYF6idyjiWSzu9z3irIw,9
154
+ PrEditor-0.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
preditor/__init__.py CHANGED
@@ -113,7 +113,7 @@ def configure(name, parent_callback=None, excepthook=True, logging=True, streams
113
113
  preditor.debug.BlurExcepthook.install()
114
114
 
115
115
 
116
- def launch(run_workbox=False, app_id=None, name=None):
116
+ def launch(run_workbox=False, app_id=None, name=None, standalone=False):
117
117
  """Launches the preditor gui creating the QApplication instance if not
118
118
  already created.
119
119
 
@@ -125,6 +125,9 @@ def launch(run_workbox=False, app_id=None, name=None):
125
125
  app_id (str, optional): Set the QApplication's applicationName to this
126
126
  value. This is normally only used when launching a standalone
127
127
  instance of the PrEditor gui.
128
+ standalone (bool, optional): Launch PrEditor in standalone mode. This
129
+ enables extra options that only make sense when it is running as
130
+ its own app, not inside of another app.
128
131
 
129
132
  Returns:
130
133
  preditor.gui.loggerwindow.LoggerWindow: The instance of the PrEditor
@@ -147,7 +150,9 @@ def launch(run_workbox=False, app_id=None, name=None):
147
150
 
148
151
  # Check if we can actually run the PrEditor gui and setup Qt if required
149
152
  app = App(name=app_id)
150
- widget = LoggerWindow.instance(run_workbox=run_workbox, name=name)
153
+ widget = LoggerWindow.instance(
154
+ run_workbox=run_workbox, name=name, standalone=standalone
155
+ )
151
156
 
152
157
  # Show the PrEditor instance and make sure it regains focus and visibility
153
158
  widget.show()
preditor/cli.py CHANGED
@@ -66,7 +66,7 @@ def launch(name, run_workbox):
66
66
  parameter_source = click.get_current_context().get_parameter_source('name')
67
67
  app_id = get_app_id(name, parameter_source == ParameterSource.DEFAULT)
68
68
 
69
- preditor.launch(run_workbox=run_workbox, app_id=app_id, name=name)
69
+ preditor.launch(run_workbox=run_workbox, app_id=app_id, name=name, standalone=True)
70
70
 
71
71
 
72
72
  # shortcut
@@ -0,0 +1,119 @@
1
+ from __future__ import absolute_import, print_function
2
+
3
+ from Qt.QtCore import Qt
4
+ from Qt.QtGui import QIcon
5
+ from Qt.QtWidgets import QApplication, QShortcut, QWidget
6
+
7
+ from .. import resourcePath
8
+ from ..utils.text_search import RegexTextSearch, SimpleTextSearch
9
+ from . import loadUi
10
+
11
+
12
+ class FindFiles(QWidget):
13
+ def __init__(self, parent=None, managers=None, console=None):
14
+ super(FindFiles, self).__init__(parent=parent)
15
+ if managers is None:
16
+ managers = []
17
+ self.managers = managers
18
+ self.console = console
19
+ self.finder = None
20
+ self.match_files_count = 0
21
+
22
+ loadUi(__file__, self)
23
+
24
+ # Set the icons
25
+ self.uiCaseSensitiveBTN.setIcon(
26
+ QIcon(resourcePath("img/format-letter-case.svg"))
27
+ )
28
+ self.uiCloseBTN.setIcon(QIcon(resourcePath('img/close-thick.png')))
29
+ self.uiRegexBTN.setIcon(QIcon(resourcePath("img/regex.svg")))
30
+
31
+ # Create shortcuts
32
+ self.uiCloseSCT = QShortcut(
33
+ Qt.Key_Escape, self, context=Qt.WidgetWithChildrenShortcut
34
+ )
35
+ self.uiCloseSCT.activated.connect(self.hide)
36
+
37
+ self.uiCaseSensitiveSCT = QShortcut(
38
+ Qt.AltModifier | Qt.Key_C, self, context=Qt.WidgetWithChildrenShortcut
39
+ )
40
+ self.uiCaseSensitiveSCT.activated.connect(self.uiCaseSensitiveBTN.toggle)
41
+
42
+ self.uiRegexSCT = QShortcut(
43
+ Qt.AltModifier | Qt.Key_R, self, context=Qt.WidgetWithChildrenShortcut
44
+ )
45
+ self.uiRegexSCT.activated.connect(self.uiRegexBTN.toggle)
46
+
47
+ def activate(self):
48
+ """Called to make this widget ready for the user to interact with."""
49
+ self.show()
50
+ self.uiFindTXT.setFocus()
51
+
52
+ def find(self):
53
+ find_text = self.uiFindTXT.text()
54
+ context = self.uiContextSPN.value()
55
+ # Create an instance of the TextSearch to use for this search
56
+ if self.uiRegexBTN.isChecked():
57
+ TextSearch = RegexTextSearch
58
+ else:
59
+ TextSearch = SimpleTextSearch
60
+ self.finder = TextSearch(
61
+ find_text, self.uiCaseSensitiveBTN.isChecked(), context=context
62
+ )
63
+ self.finder.callback_matching = self.insert_found_text
64
+ self.finder.callback_non_matching = self.insert_text
65
+
66
+ self.insert_text(self.finder.title())
67
+
68
+ self.match_files_count = 0
69
+ for manager in self.managers:
70
+ for (
71
+ editor,
72
+ group_name,
73
+ tab_name,
74
+ group_index,
75
+ tab_index,
76
+ ) in manager.all_widgets():
77
+ path = "/".join((group_name, tab_name))
78
+ workbox_id = '{},{}'.format(group_index, tab_index)
79
+ self.find_in_editor(editor, path, workbox_id)
80
+
81
+ self.insert_text(
82
+ '\n{} matches in {} workboxes\n'.format(
83
+ self.finder.match_count, self.match_files_count
84
+ )
85
+ )
86
+
87
+ def find_in_editor(self, editor, path, workbox_id):
88
+ # Ensure the editor text is loaded and get its raw text
89
+ editor.__show__()
90
+ text = editor.__text__()
91
+
92
+ # Use the finder to check for matches
93
+ found = self.finder.search_text(text, path, workbox_id)
94
+ if found:
95
+ self.match_files_count += 1
96
+
97
+ def insert_found_text(self, text, workbox_id, line_num, tool_tip):
98
+ href = ', {}, {}'.format(workbox_id, line_num)
99
+ cursor = self.console.textCursor()
100
+ # Insert hyperlink
101
+ fmt = cursor.charFormat()
102
+ fmt.setAnchor(True)
103
+ fmt.setAnchorHref(href)
104
+ fmt.setFontUnderline(True)
105
+ fmt.setToolTip(tool_tip)
106
+ cursor.insertText(text, fmt)
107
+ # Show the updated text output
108
+ QApplication.instance().processEvents()
109
+
110
+ def insert_text(self, text):
111
+ cursor = self.console.textCursor()
112
+ fmt = cursor.charFormat()
113
+ fmt.setAnchor(False)
114
+ fmt.setAnchorHref('')
115
+ fmt.setFontUnderline(False)
116
+ fmt.setToolTip('')
117
+ cursor.insertText(text, fmt)
118
+ # Show the updated text output
119
+ QApplication.instance().processEvents()
File without changes
@@ -0,0 +1,93 @@
1
+ from __future__ import absolute_import
2
+
3
+ from functools import partial
4
+
5
+ from Qt.QtCore import QModelIndex, QPoint, Qt, Signal
6
+ from Qt.QtWidgets import QFrame, QLineEdit, QListView, QShortcut, QVBoxLayout
7
+
8
+ from ..group_tab_widget.grouped_tab_models import GroupTabFuzzyFilterProxyModel
9
+
10
+
11
+ class FuzzySearch(QFrame):
12
+ canceled = Signal("QModelIndex")
13
+ """Passes the original QModelIndex for the tab that was selected when the
14
+ widget was first shown. This lets you reset back to the orignal state."""
15
+ highlighted = Signal("QModelIndex")
16
+ """Emitted when the user navitages to the given index, but hasn't selected."""
17
+ selected = Signal("QModelIndex")
18
+ """Emitted when the user selects a item."""
19
+
20
+ def __init__(self, model, parent=None, **kwargs):
21
+ super(FuzzySearch, self).__init__(parent=parent, **kwargs)
22
+ self.y_offset = 100
23
+ self.setMinimumSize(400, 200)
24
+ self.uiCloseSCT = QShortcut(
25
+ Qt.Key_Escape, self, context=Qt.WidgetWithChildrenShortcut
26
+ )
27
+ self.uiCloseSCT.activated.connect(self._canceled)
28
+
29
+ self.uiUpSCT = QShortcut(Qt.Key_Up, self, context=Qt.WidgetWithChildrenShortcut)
30
+ self.uiUpSCT.activated.connect(partial(self.increment_selection, -1))
31
+ self.uiDownSCT = QShortcut(
32
+ Qt.Key_Down, self, context=Qt.WidgetWithChildrenShortcut
33
+ )
34
+ self.uiDownSCT.activated.connect(partial(self.increment_selection, 1))
35
+
36
+ lyt = QVBoxLayout(self)
37
+ self.uiLineEDIT = QLineEdit(parent=self)
38
+ self.uiLineEDIT.textChanged.connect(self.update_completer)
39
+ self.uiLineEDIT.returnPressed.connect(self.activated)
40
+ lyt.addWidget(self.uiLineEDIT)
41
+ self.uiResultsLIST = QListView(self)
42
+ self.uiResultsLIST.activated.connect(self.activated)
43
+ self.proxy_model = GroupTabFuzzyFilterProxyModel(self)
44
+ self.proxy_model.setSourceModel(model)
45
+ self.uiResultsLIST.setModel(self.proxy_model)
46
+ lyt.addWidget(self.uiResultsLIST)
47
+
48
+ self.original_model_index = model.original_model_index
49
+
50
+ def activated(self):
51
+ current = self.uiResultsLIST.currentIndex()
52
+ self.selected.emit(current)
53
+ self.hide()
54
+
55
+ def increment_selection(self, direction):
56
+ current = self.uiResultsLIST.currentIndex()
57
+ col = 0
58
+ row = 0
59
+ if current.isValid():
60
+ col = current.column()
61
+ row = current.row() + direction
62
+ new = self.uiResultsLIST.model().index(row, col)
63
+ self.uiResultsLIST.setCurrentIndex(new)
64
+ self.highlighted.emit(new)
65
+
66
+ def update_completer(self, wildcard):
67
+ if wildcard:
68
+ if not self.uiResultsLIST.currentIndex().isValid():
69
+ new = self.uiResultsLIST.model().index(0, 0)
70
+ self.uiResultsLIST.setCurrentIndex(new)
71
+ else:
72
+ self.uiResultsLIST.clearSelection()
73
+ self.uiResultsLIST.setCurrentIndex(QModelIndex())
74
+ self.proxy_model.setFuzzySearch(wildcard)
75
+ self.highlighted.emit(self.uiResultsLIST.currentIndex())
76
+
77
+ def _canceled(self):
78
+ # Restore the original tab as the user didn't choose the new tab
79
+ self.canceled.emit(self.original_model_index)
80
+ self.hide()
81
+
82
+ def reposition(self):
83
+ pgeo = self.parent().geometry()
84
+ geo = self.geometry()
85
+ center = QPoint(pgeo.width() // 2, 0)
86
+ geo.moveCenter(center)
87
+ geo.setY(self.y_offset)
88
+ self.setGeometry(geo)
89
+
90
+ def popup(self):
91
+ self.show()
92
+ self.reposition()
93
+ self.uiLineEDIT.setFocus(Qt.PopupFocusReason)
@@ -114,11 +114,20 @@ class GroupTabWidget(OneTabWidget):
114
114
  return parent, editor
115
115
 
116
116
  def all_widgets(self):
117
- """Returns every widget under every group."""
118
- for i in range(self.count()):
119
- tab_widget = self.widget(i)
120
- for j in range(tab_widget.count()):
121
- yield tab_widget.widget(j)
117
+ """A generator yielding information about every widget under every group.
118
+
119
+ Yields:
120
+ widget, group tab name, widget tab name, group tab index, widget tab index
121
+ """
122
+ for group_index in range(self.count()):
123
+ group_name = self.tabText(group_index)
124
+
125
+ tab_widget = self.widget(group_index)
126
+ for tab_index in range(tab_widget.count()):
127
+ tab_name = tab_widget.tabText(tab_index)
128
+ yield tab_widget.widget(
129
+ tab_index
130
+ ), group_name, tab_name, group_index, tab_index
122
131
 
123
132
  def close_current_tab(self):
124
133
  """Convenient method to close the currently open editor tab prompting
@@ -0,0 +1,108 @@
1
+ from __future__ import absolute_import
2
+
3
+ import re
4
+
5
+ from Qt.QtCore import QSortFilterProxyModel, Qt
6
+ from Qt.QtGui import QStandardItem, QStandardItemModel
7
+
8
+
9
+ class GroupTabItemModel(QStandardItemModel):
10
+ GroupIndexRole = Qt.UserRole + 1
11
+ TabIndexRole = GroupIndexRole + 1
12
+
13
+ def __init__(self, manager, *args, **kwargs):
14
+ super(GroupTabItemModel, self).__init__(*args, **kwargs)
15
+ self.manager = manager
16
+
17
+ def workbox_indexes_from_model_index(self, index):
18
+ """Returns the group_index and tab_index for the provided QModelIndex"""
19
+ return (
20
+ index.data(self.GroupIndexRole),
21
+ index.data(self.TabIndexRole),
22
+ )
23
+
24
+ def pathFromIndex(self, index):
25
+ parts = [""]
26
+ while index.isValid():
27
+ parts.append(self.data(index, Qt.DisplayRole))
28
+ index = index.parent()
29
+ if len(parts) == 1:
30
+ return ""
31
+ return "/".join([x for x in parts[::-1] if x])
32
+
33
+
34
+ class GroupTabTreeItemModel(GroupTabItemModel):
35
+ def process(self):
36
+ root = self.invisibleRootItem()
37
+ current_group = self.manager.currentIndex()
38
+ current_tab = self.manager.currentWidget().currentIndex()
39
+
40
+ prev_group = -1
41
+ all_widgets = self.manager.all_widgets()
42
+ for _, group_name, tab_name, group_index, tab_index in all_widgets:
43
+ if prev_group != group_index:
44
+ group_item = QStandardItem(group_name)
45
+ group_item.setData(group_index, self.GroupIndexRole)
46
+ root.appendRow(group_item)
47
+ prev_group = group_index
48
+
49
+ tab_item = QStandardItem(tab_name)
50
+ tab_item.setData(group_index, self.GroupIndexRole)
51
+ tab_item.setData(tab_index, self.TabIndexRole)
52
+ group_item.appendRow(tab_item)
53
+ if group_index == current_group and tab_index == current_tab:
54
+ self.original_model_index = self.indexFromItem(tab_item)
55
+
56
+
57
+ class GroupTabListItemModel(GroupTabItemModel):
58
+ def flags(self, index):
59
+ return Qt.ItemIsEnabled | Qt.ItemIsSelectable
60
+
61
+ def process(self):
62
+ root = self.invisibleRootItem()
63
+ current_group = self.manager.currentIndex()
64
+ current_tab = self.manager.currentWidget().currentIndex()
65
+
66
+ all_widgets = self.manager.all_widgets()
67
+ for _, group_name, tab_name, group_index, tab_index in all_widgets:
68
+ tab_item = QStandardItem('/'.join((group_name, tab_name)))
69
+ tab_item.setData(group_index, self.GroupIndexRole)
70
+ tab_item.setData(tab_index, self.TabIndexRole)
71
+ root.appendRow(tab_item)
72
+ if group_index == current_group and tab_index == current_tab:
73
+ self.original_model_index = self.indexFromItem(tab_item)
74
+
75
+
76
+ class GroupTabFuzzyFilterProxyModel(QSortFilterProxyModel):
77
+ """Implements a fuzzy search filter proxy model."""
78
+
79
+ def __init__(self, parent=None):
80
+ super(GroupTabFuzzyFilterProxyModel, self).__init__(parent=parent)
81
+ self._fuzzy_regex = None
82
+
83
+ def setFuzzySearch(self, search):
84
+ search = '.*'.join(search)
85
+ # search = '.*{}.*'.format(search)
86
+ self._fuzzy_regex = re.compile(search, re.I)
87
+ self.invalidateFilter()
88
+
89
+ def filterAcceptsRow(self, sourceRow, sourceParent):
90
+ if self.filterKeyColumn() == 0 and self._fuzzy_regex:
91
+
92
+ index = self.sourceModel().index(sourceRow, 0, sourceParent)
93
+ data = self.sourceModel().data(index)
94
+ ret = bool(self._fuzzy_regex.search(data))
95
+ return ret
96
+
97
+ return super(GroupTabFuzzyFilterProxyModel, self).filterAcceptsRow(
98
+ sourceRow, sourceParent
99
+ )
100
+
101
+ def pathFromIndex(self, index):
102
+ parts = [""]
103
+ while index.isValid():
104
+ parts.append(self.data(index, Qt.DisplayRole))
105
+ index = index.parent()
106
+ if len(parts) == 1:
107
+ return ""
108
+ return "/".join([x for x in parts[::-1] if x])