PrEditor 0.0.0.dev1__py2.py3-none-any.whl → 0.1.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.0.dist-info/LICENSE +165 -0
- PrEditor-0.1.0.dist-info/METADATA +212 -0
- PrEditor-0.1.0.dist-info/RECORD +149 -0
- {PrEditor-0.0.0.dev1.dist-info → PrEditor-0.1.0.dist-info}/WHEEL +1 -1
- PrEditor-0.1.0.dist-info/entry_points.txt +18 -0
- PrEditor-0.1.0.dist-info/top_level.txt +1 -0
- preditor/__init__.py +301 -0
- {blurdev → preditor}/__main__.py +13 -13
- preditor/about_module.py +166 -0
- preditor/cli.py +192 -0
- {blurdev → preditor}/contexts.py +119 -119
- preditor/cores/core.py +65 -0
- preditor/dccs/maya/PrEditor_maya.mod +2 -0
- preditor/dccs/maya/plug-ins/PrEditor_maya.py +108 -0
- preditor/debug.py +294 -0
- blurdev/scintilla/delayable_engine.py → preditor/delayable_engine/__init__.py +310 -299
- blurdev/scintilla/delayables/base.py → preditor/delayable_engine/delayables.py +85 -85
- {blurdev → preditor}/enum.py +728 -1003
- {blurdev → preditor}/gui/__init__.py +84 -125
- preditor/gui/app.py +159 -0
- {blurdev → preditor}/gui/codehighlighter.py +209 -219
- {blurdev → preditor}/gui/completer.py +226 -236
- {blurdev → preditor}/gui/console.py +801 -858
- {blurdev → preditor}/gui/dialog.py +200 -216
- preditor/gui/drag_tab_bar.py +190 -0
- preditor/gui/editor_chooser.py +57 -0
- {blurdev → preditor}/gui/errordialog.py +100 -97
- preditor/gui/fuzzy_search/fuzzy_search.py +93 -0
- preditor/gui/group_tab_widget/__init__.py +319 -0
- preditor/gui/group_tab_widget/grouped_tab_menu.py +35 -0
- preditor/gui/group_tab_widget/grouped_tab_models.py +108 -0
- preditor/gui/group_tab_widget/grouped_tab_widget.py +75 -0
- preditor/gui/group_tab_widget/one_tab_widget.py +54 -0
- preditor/gui/level_buttons.py +349 -0
- {blurdev → preditor}/gui/logger_window_handler.py +46 -45
- {blurdev → preditor}/gui/loggerwindow.py +1205 -1417
- {blurdev → preditor}/gui/newtabwidget.py +69 -68
- {blurdev → preditor}/gui/redmine_login_dialog.py +63 -61
- {blurdev → preditor}/gui/set_text_editor_path_dialog.py +59 -57
- preditor/gui/ui/editor_chooser.ui +93 -0
- {blurdev → preditor}/gui/ui/errordialog.ui +81 -81
- {blurdev → preditor}/gui/ui/loggerwindow.ui +1030 -864
- {blurdev → preditor}/gui/ui/redmine_login_dialog.ui +124 -124
- {blurdev → preditor}/gui/ui/set_text_editor_path_dialog.ui +149 -149
- {blurdev → preditor}/gui/window.py +183 -199
- preditor/gui/workbox_mixin.py +357 -0
- preditor/gui/workbox_text_edit.py +117 -0
- preditor/gui/workboxwidget.py +276 -0
- preditor/logging_config.py +52 -0
- preditor/osystem.py +401 -0
- preditor/plugins.py +65 -0
- preditor/prefs.py +74 -0
- {blurdev → preditor}/resource/environment_variables.html +26 -38
- {blurdev → preditor}/resource/error_mail.html +85 -85
- {blurdev → preditor}/resource/error_mail_inline.html +41 -41
- preditor/resource/img/README.md +7 -0
- preditor/resource/img/arrow_forward.png +0 -0
- preditor/resource/img/check-bold.png +0 -0
- preditor/resource/img/chevron-down.png +0 -0
- preditor/resource/img/chevron-up.png +0 -0
- preditor/resource/img/close-thick.png +0 -0
- preditor/resource/img/comment-edit.png +0 -0
- preditor/resource/img/content-copy.png +0 -0
- preditor/resource/img/content-cut.png +0 -0
- preditor/resource/img/content-duplicate.png +0 -0
- preditor/resource/img/content-paste.png +0 -0
- preditor/resource/img/content-save.png +0 -0
- preditor/resource/img/debug_disabled.png +0 -0
- preditor/resource/img/eye-check.png +0 -0
- preditor/resource/img/file-plus.png +0 -0
- preditor/resource/img/file-remove.png +0 -0
- preditor/resource/img/format-align-left.png +0 -0
- preditor/resource/img/format-letter-case-lower.png +0 -0
- preditor/resource/img/format-letter-case-upper.png +0 -0
- preditor/resource/img/information.png +0 -0
- preditor/resource/img/logging_critical.png +0 -0
- preditor/resource/img/logging_custom.png +0 -0
- preditor/resource/img/logging_debug.png +0 -0
- preditor/resource/img/logging_error.png +0 -0
- preditor/resource/img/logging_info.png +0 -0
- preditor/resource/img/logging_not_set.png +0 -0
- preditor/resource/img/logging_warning.png +0 -0
- preditor/resource/img/marker.png +0 -0
- preditor/resource/img/play.png +0 -0
- preditor/resource/img/playlist-play.png +0 -0
- preditor/resource/img/plus-minus-variant.png +0 -0
- preditor/resource/img/preditor.ico +0 -0
- preditor/resource/img/preditor.png +0 -0
- preditor/resource/img/preditor.psd +0 -0
- preditor/resource/img/preditor.svg +44 -0
- preditor/resource/img/restart.svg +1 -0
- preditor/resource/img/skip-forward-outline.png +0 -0
- preditor/resource/img/skip-next-outline.png +0 -0
- preditor/resource/img/skip-next.png +0 -0
- preditor/resource/img/skip-previous.png +0 -0
- preditor/resource/img/subdirectory-arrow-right.png +0 -0
- preditor/resource/img/text-search-variant.png +0 -0
- {blurdev → preditor}/resource/lang/python.json +30 -30
- preditor/resource/settings.ini +25 -0
- {blurdev/resource/stylesheet/logger → preditor/resource/stylesheet}/Bright.css +56 -61
- {blurdev → preditor}/resource/stylesheet/Dark.css +190 -132
- {blurdev → preditor}/scintilla/__init__.py +22 -28
- preditor/scintilla/delayables/__init__.py +11 -0
- {blurdev → preditor}/scintilla/delayables/smart_highlight.py +94 -93
- {blurdev → preditor}/scintilla/delayables/spell_check.py +173 -172
- {blurdev → preditor}/scintilla/documenteditor.py +2039 -2115
- {blurdev → preditor}/scintilla/finddialog.py +68 -81
- {blurdev → preditor}/scintilla/lang/__init__.py +80 -93
- {blurdev → preditor}/scintilla/lang/config/bash.ini +15 -15
- {blurdev → preditor}/scintilla/lang/config/batch.ini +14 -14
- {blurdev → preditor}/scintilla/lang/config/cpp.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/css.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/eyeonscript.ini +17 -17
- {blurdev → preditor}/scintilla/lang/config/html.ini +21 -21
- {blurdev → preditor}/scintilla/lang/config/javascript.ini +24 -24
- {blurdev → preditor}/scintilla/lang/config/lua.ini +16 -16
- {blurdev → preditor}/scintilla/lang/config/maxscript.ini +20 -20
- {blurdev → preditor}/scintilla/lang/config/mel.ini +18 -18
- {blurdev → preditor}/scintilla/lang/config/mu.ini +22 -22
- {blurdev → preditor}/scintilla/lang/config/nsi.ini +5 -5
- {blurdev → preditor}/scintilla/lang/config/perl.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/puppet.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/python.ini +28 -28
- {blurdev → preditor}/scintilla/lang/config/ruby.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/sql.ini +7 -7
- {blurdev → preditor}/scintilla/lang/config/xml.ini +21 -21
- {blurdev → preditor}/scintilla/lang/config/yaml.ini +18 -18
- {blurdev → preditor}/scintilla/lang/language.py +240 -250
- preditor/scintilla/lexers/__init__.py +0 -0
- {blurdev → preditor}/scintilla/lexers/cpplexer.py +21 -30
- {blurdev → preditor}/scintilla/lexers/javascriptlexer.py +25 -34
- {blurdev → preditor}/scintilla/lexers/maxscriptlexer.py +234 -253
- {blurdev → preditor}/scintilla/lexers/mellexer.py +368 -376
- {blurdev → preditor}/scintilla/lexers/mulexer.py +32 -41
- {blurdev → preditor}/scintilla/lexers/pythonlexer.py +41 -50
- {blurdev → preditor}/scintilla/ui/finddialog.ui +160 -160
- preditor/settings.py +71 -0
- preditor/stream/__init__.py +80 -0
- preditor/stream/director.py +56 -0
- preditor/stream/manager.py +74 -0
- preditor/streamhandler_helper.py +46 -0
- preditor/utils/__init__.py +0 -0
- preditor/utils/cute.py +30 -0
- preditor/utils/stylesheets.py +54 -0
- {blurdev → preditor}/version.py +5 -5
- preditor/weakref.py +363 -0
- PrEditor-0.0.0.dev1.dist-info/METADATA +0 -51
- PrEditor-0.0.0.dev1.dist-info/RECORD +0 -279
- PrEditor-0.0.0.dev1.dist-info/top_level.txt +0 -1
- blurdev/__init__.py +0 -356
- blurdev/cores/__init__.py +0 -98
- blurdev/cores/application.py +0 -26
- blurdev/cores/core.py +0 -634
- blurdev/debug.py +0 -593
- blurdev/external.py +0 -391
- blurdev/gui/level_buttons.py +0 -585
- blurdev/gui/workboxwidget.py +0 -205
- blurdev/logger.py +0 -238
- blurdev/osystem.py +0 -813
- blurdev/prefs.py +0 -33
- blurdev/protocols/__init__.py +0 -71
- blurdev/protocols/write_std_output_handler.py +0 -83
- blurdev/resource/designer_plugins.xml +0 -9
- blurdev/resource/error_email_old.html +0 -41
- blurdev/resource/img/add.png +0 -0
- blurdev/resource/img/ajax-loader.gif +0 -0
- blurdev/resource/img/application.png +0 -0
- blurdev/resource/img/applications.png +0 -0
- blurdev/resource/img/assburner.png +0 -0
- blurdev/resource/img/assfreezer.png +0 -0
- blurdev/resource/img/bar.gif +0 -0
- blurdev/resource/img/blank.png +0 -0
- blurdev/resource/img/blurdev.png +0 -0
- blurdev/resource/img/calendar_disabled.png +0 -0
- blurdev/resource/img/calendar_enabled.png +0 -0
- blurdev/resource/img/cancel.png +0 -0
- blurdev/resource/img/custom.png +0 -0
- blurdev/resource/img/debug_high.png +0 -0
- blurdev/resource/img/debug_low.png +0 -0
- blurdev/resource/img/debug_mid.png +0 -0
- blurdev/resource/img/debug_off.png +0 -0
- blurdev/resource/img/django.png +0 -0
- blurdev/resource/img/doc.png +0 -0
- blurdev/resource/img/edit.png +0 -0
- blurdev/resource/img/elemental.png +0 -0
- blurdev/resource/img/explore.png +0 -0
- blurdev/resource/img/favorite.png +0 -0
- blurdev/resource/img/file.png +0 -0
- blurdev/resource/img/folder.png +0 -0
- blurdev/resource/img/ide/add.png +0 -0
- blurdev/resource/img/ide/add_note.png +0 -0
- blurdev/resource/img/ide/arrow_down.png +0 -0
- blurdev/resource/img/ide/arrow_up.png +0 -0
- blurdev/resource/img/ide/check.png +0 -0
- blurdev/resource/img/ide/class.png +0 -0
- blurdev/resource/img/ide/clean.png +0 -0
- blurdev/resource/img/ide/clearlog.png +0 -0
- blurdev/resource/img/ide/close.png +0 -0
- blurdev/resource/img/ide/comment_add.png +0 -0
- blurdev/resource/img/ide/comment_remove.png +0 -0
- blurdev/resource/img/ide/comment_toggle.png +0 -0
- blurdev/resource/img/ide/console.png +0 -0
- blurdev/resource/img/ide/copy.png +0 -0
- blurdev/resource/img/ide/copylstrip.png +0 -0
- blurdev/resource/img/ide/cut.png +0 -0
- blurdev/resource/img/ide/edit.png +0 -0
- blurdev/resource/img/ide/find.png +0 -0
- blurdev/resource/img/ide/find_replace.png +0 -0
- blurdev/resource/img/ide/findnext.png +0 -0
- blurdev/resource/img/ide/findprev.png +0 -0
- blurdev/resource/img/ide/folder_find.png +0 -0
- blurdev/resource/img/ide/function.png +0 -0
- blurdev/resource/img/ide/git-bash.png +0 -0
- blurdev/resource/img/ide/git-gui.png +0 -0
- blurdev/resource/img/ide/gitk.png +0 -0
- blurdev/resource/img/ide/goto.png +0 -0
- blurdev/resource/img/ide/goto_def.png +0 -0
- blurdev/resource/img/ide/help.png +0 -0
- blurdev/resource/img/ide/highlighter.png +0 -0
- blurdev/resource/img/ide/lowercase.png +0 -0
- blurdev/resource/img/ide/newfile.png +0 -0
- blurdev/resource/img/ide/newfolder.png +0 -0
- blurdev/resource/img/ide/newproject.png +0 -0
- blurdev/resource/img/ide/newwizard.png +0 -0
- blurdev/resource/img/ide/open.png +0 -0
- blurdev/resource/img/ide/paste.png +0 -0
- blurdev/resource/img/ide/pdb_continue.png +0 -0
- blurdev/resource/img/ide/pdb_down.png +0 -0
- blurdev/resource/img/ide/pdb_next.png +0 -0
- blurdev/resource/img/ide/pdb_step.png +0 -0
- blurdev/resource/img/ide/pdb_up.png +0 -0
- blurdev/resource/img/ide/plus_minus.png +0 -0
- blurdev/resource/img/ide/preferences.png +0 -0
- blurdev/resource/img/ide/project_find.png +0 -0
- blurdev/resource/img/ide/python.png +0 -0
- blurdev/resource/img/ide/pyular.png +0 -0
- blurdev/resource/img/ide/qt.png +0 -0
- blurdev/resource/img/ide/quit.png +0 -0
- blurdev/resource/img/ide/redo.png +0 -0
- blurdev/resource/img/ide/refresh.png +0 -0
- blurdev/resource/img/ide/remove.png +0 -0
- blurdev/resource/img/ide/ruler.png +0 -0
- blurdev/resource/img/ide/run.png +0 -0
- blurdev/resource/img/ide/runall.png +0 -0
- blurdev/resource/img/ide/runallclear.png +0 -0
- blurdev/resource/img/ide/runselected.png +0 -0
- blurdev/resource/img/ide/runselectedclear.png +0 -0
- blurdev/resource/img/ide/save.png +0 -0
- blurdev/resource/img/ide/saveas.png +0 -0
- blurdev/resource/img/ide/sdk.png +0 -0
- blurdev/resource/img/ide/separator.png +0 -0
- blurdev/resource/img/ide/tabbed.png +0 -0
- blurdev/resource/img/ide/tile.png +0 -0
- blurdev/resource/img/ide/toolbar.png +0 -0
- blurdev/resource/img/ide/undo.png +0 -0
- blurdev/resource/img/ide/uppercase.png +0 -0
- blurdev/resource/img/ide/view_as.png +0 -0
- blurdev/resource/img/ide/windowed.png +0 -0
- blurdev/resource/img/ide.ico +0 -0
- blurdev/resource/img/ide.png +0 -0
- blurdev/resource/img/ide48.png +0 -0
- blurdev/resource/img/info.png +0 -0
- blurdev/resource/img/legacy tool.png +0 -0
- blurdev/resource/img/library.png +0 -0
- blurdev/resource/img/logger/about.png +0 -0
- blurdev/resource/img/logger/arrow_forward.png +0 -0
- blurdev/resource/img/logger/clear.png +0 -0
- blurdev/resource/img/logger/close.png +0 -0
- blurdev/resource/img/logger/debug_disabled.png +0 -0
- blurdev/resource/img/logger/debug_high.png +0 -0
- blurdev/resource/img/logger/debug_low.png +0 -0
- blurdev/resource/img/logger/debug_mid.png +0 -0
- blurdev/resource/img/logger/down.png +0 -0
- blurdev/resource/img/logger/find.png +0 -0
- blurdev/resource/img/logger/logging_critical.png +0 -0
- blurdev/resource/img/logger/logging_debug.png +0 -0
- blurdev/resource/img/logger/logging_error.png +0 -0
- blurdev/resource/img/logger/logging_info.png +0 -0
- blurdev/resource/img/logger/logging_not_set.png +0 -0
- blurdev/resource/img/logger/logging_warning.png +0 -0
- blurdev/resource/img/logger/next.png +0 -0
- blurdev/resource/img/logger/play.png +0 -0
- blurdev/resource/img/logger/playlist_play.png +0 -0
- blurdev/resource/img/logger/previous.png +0 -0
- blurdev/resource/img/logger/return.png +0 -0
- blurdev/resource/img/logger/save.png +0 -0
- blurdev/resource/img/logger/subdirectory_arrow_right.png +0 -0
- blurdev/resource/img/logger/up.png +0 -0
- blurdev/resource/img/lovebar.png +0 -0
- blurdev/resource/img/new.png +0 -0
- blurdev/resource/img/new_selected.png +0 -0
- blurdev/resource/img/node.png +0 -0
- blurdev/resource/img/ok.png +0 -0
- blurdev/resource/img/options.png +0 -0
- blurdev/resource/img/packages.png +0 -0
- blurdev/resource/img/preview/add.png +0 -0
- blurdev/resource/img/preview/brush.png +0 -0
- blurdev/resource/img/preview/delete.png +0 -0
- blurdev/resource/img/preview/delte.png +0 -0
- blurdev/resource/img/preview/fill.png +0 -0
- blurdev/resource/img/preview/layers.png +0 -0
- blurdev/resource/img/preview/media.png +0 -0
- blurdev/resource/img/preview/navigate.png +0 -0
- blurdev/resource/img/preview/pencil.png +0 -0
- blurdev/resource/img/preview/select.png +0 -0
- blurdev/resource/img/preview/type.png +0 -0
- blurdev/resource/img/preview/visible.png +0 -0
- blurdev/resource/img/project.png +0 -0
- blurdev/resource/img/python_logger.ico +0 -0
- blurdev/resource/img/python_logger.png +0 -0
- blurdev/resource/img/refresh.png +0 -0
- blurdev/resource/img/remove.png +0 -0
- blurdev/resource/img/reset.png +0 -0
- blurdev/resource/img/richtext/font_bold.png +0 -0
- blurdev/resource/img/richtext/font_italic.png +0 -0
- blurdev/resource/img/richtext/link_image.png +0 -0
- blurdev/resource/img/richtext/spell_check.png +0 -0
- blurdev/resource/img/richtext/unordered_list.png +0 -0
- blurdev/resource/img/save.png +0 -0
- blurdev/resource/img/savesettings.png +0 -0
- blurdev/resource/img/settings.png +0 -0
- blurdev/resource/img/tool.png +0 -0
- blurdev/resource/img/toolbarHandleHorizontal.png +0 -0
- blurdev/resource/img/toolbarHandleVertical.png +0 -0
- blurdev/resource/img/trash.png +0 -0
- blurdev/resource/img/trax.png +0 -0
- blurdev/resource/img/tree.png +0 -0
- blurdev/resource/img/treegrunt.ico +0 -0
- blurdev/resource/img/treegrunt.png +0 -0
- blurdev/resource/img/treegruntedit.png +0 -0
- blurdev/resource/img/user interface.png +0 -0
- blurdev/resource/img/warning.png +0 -0
- blurdev/resource/img/watermark.png +0 -0
- blurdev/resource/sdk/blurdev.sdk +0 -3
- blurdev/resource/settings.ini +0 -82
- blurdev/resource/softimage/BlurApplication.dll +0 -0
- blurdev/resource/softimage/BlurApplication64.dll +0 -0
- blurdev/resource/stylesheet/Carbon.css +0 -35
- blurdev/resource/stylesheet/logger/Dark.css +0 -62
- blurdev/resource/templ/py_comment.templ +0 -1
- blurdev/resource/templ/py_debug_raise_error.templ +0 -7
- blurdev/resource/templ/py_doc_string.templ +0 -10
- blurdev/resource/templ/py_header.templ +0 -9
- blurdev/resource/templ/py_line_comment.templ +0 -1
- blurdev/resource/templ/py_log_to_file.templ +0 -22
- blurdev/resource/templ/py_module_path.templ +0 -1
- blurdev/resource/templ/py_pyqt_core.templ +0 -1
- blurdev/resource/templ/py_pyqt_gui.templ +0 -1
- blurdev/resource/templ/py_splashscreen.templ +0 -6
- blurdev/resource/templ/py_testing_note.templ +0 -1
- blurdev/resource/templ/py_testing_note_end.templ +0 -1
- blurdev/resource/tools_environments.json +0 -72
- blurdev/resource/tools_environments.xml +0 -11
- blurdev/resource/tools_environments_linux.xml +0 -11
- blurdev/resource/tools_environments_offline.xml +0 -7
- blurdev/runtimes/__init__.py +0 -2
- blurdev/runtimes/logger.py +0 -44
- blurdev/scintilla/delayables/__init__.py +0 -9
- blurdev/settings.py +0 -312
- blurdev/utils/error.py +0 -389
- {blurdev/scintilla/lexers → preditor/cores}/__init__.py +0 -0
- {blurdev/utils → preditor/gui/fuzzy_search}/__init__.py +0 -0
- {blurdev → preditor}/resource/img/warning-big.png +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import absolute_import
|
|
2
|
+
|
|
3
|
+
from Qt.QtCore import Slot
|
|
4
|
+
from Qt.QtGui import QIcon
|
|
5
|
+
from Qt.QtWidgets import QWidget
|
|
6
|
+
|
|
7
|
+
from .. import plugins, resourcePath
|
|
8
|
+
from ..gui import loadUi
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EditorChooser(QWidget):
|
|
12
|
+
"""A widget that lets the user choose from a a list of available editors."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, parent=None, editor_name=None):
|
|
15
|
+
super(EditorChooser, self).__init__(parent=parent)
|
|
16
|
+
loadUi(__file__, self)
|
|
17
|
+
icon = QIcon(resourcePath('img/warning-big.png'))
|
|
18
|
+
self.uiWarningIconLBL.setPixmap(icon.pixmap(icon.availableSizes()[0]))
|
|
19
|
+
if editor_name:
|
|
20
|
+
self.set_editor_name(editor_name)
|
|
21
|
+
|
|
22
|
+
def editor_name(self):
|
|
23
|
+
return self.uiWorkboxEditorDDL.currentText()
|
|
24
|
+
|
|
25
|
+
def set_editor_name(self, name):
|
|
26
|
+
index = self.uiWorkboxEditorDDL.findText(name)
|
|
27
|
+
if index == -1:
|
|
28
|
+
self.uiWorkboxEditorDDL.addItem(name)
|
|
29
|
+
index = self.uiWorkboxEditorDDL.findText(name)
|
|
30
|
+
self.uiWorkboxEditorDDL.setCurrentIndex(index)
|
|
31
|
+
|
|
32
|
+
@Slot()
|
|
33
|
+
def refresh(self):
|
|
34
|
+
warning = "Choose an editor to enable Workboxs."
|
|
35
|
+
editor_name = self.editor_name()
|
|
36
|
+
if editor_name:
|
|
37
|
+
_, editor = plugins.editor(editor_name)
|
|
38
|
+
warning = editor._warning_text
|
|
39
|
+
self.uiWarningIconLBL.setVisible(bool(warning))
|
|
40
|
+
self.uiWarningTextLBL.setVisible(bool(warning))
|
|
41
|
+
self.uiWarningTextLBL.setText(warning)
|
|
42
|
+
|
|
43
|
+
def refresh_editors(self):
|
|
44
|
+
current = self.editor_name()
|
|
45
|
+
self.uiWorkboxEditorDDL.blockSignals(True)
|
|
46
|
+
self.uiWorkboxEditorDDL.clear()
|
|
47
|
+
for name, _ in sorted(plugins.editors()):
|
|
48
|
+
self.uiWorkboxEditorDDL.addItem(name)
|
|
49
|
+
|
|
50
|
+
self.uiWorkboxEditorDDL.setCurrentIndex(
|
|
51
|
+
self.uiWorkboxEditorDDL.findText(current)
|
|
52
|
+
)
|
|
53
|
+
self.uiWorkboxEditorDDL.blockSignals(False)
|
|
54
|
+
|
|
55
|
+
def showEvent(self, event): # noqa: N802
|
|
56
|
+
super(EditorChooser, self).showEvent(event)
|
|
57
|
+
self.refresh_editors()
|
|
@@ -1,97 +1,100 @@
|
|
|
1
|
-
from __future__ import absolute_import
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
from
|
|
8
|
-
from Qt.
|
|
9
|
-
from Qt.
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
self.
|
|
24
|
-
self.
|
|
25
|
-
self.
|
|
26
|
-
self.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
self.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
'
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
'
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return
|
|
97
|
-
|
|
1
|
+
from __future__ import absolute_import
|
|
2
|
+
|
|
3
|
+
import getpass
|
|
4
|
+
import os
|
|
5
|
+
import traceback
|
|
6
|
+
|
|
7
|
+
from Qt.QtCore import Qt
|
|
8
|
+
from Qt.QtGui import QPixmap
|
|
9
|
+
from Qt.QtWidgets import QDialog
|
|
10
|
+
from redminelib.exceptions import ImpersonateError
|
|
11
|
+
|
|
12
|
+
from .. import __file__ as pfile
|
|
13
|
+
from . import Dialog, loadUi
|
|
14
|
+
from .redmine_login_dialog import RedmineLoginDialog
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ErrorDialog(Dialog):
|
|
18
|
+
def __init__(self, parent):
|
|
19
|
+
super(ErrorDialog, self).__init__(parent)
|
|
20
|
+
|
|
21
|
+
loadUi(__file__, self)
|
|
22
|
+
|
|
23
|
+
self.parent_ = parent
|
|
24
|
+
self.requestPimpPID = None
|
|
25
|
+
self.setWindowTitle('Error Occurred')
|
|
26
|
+
self.errorLabel.setTextFormat(Qt.RichText)
|
|
27
|
+
self.iconLabel.setPixmap(
|
|
28
|
+
QPixmap(
|
|
29
|
+
os.path.join(
|
|
30
|
+
os.path.dirname(pfile),
|
|
31
|
+
'resource',
|
|
32
|
+
'img',
|
|
33
|
+
'warning-big.png',
|
|
34
|
+
)
|
|
35
|
+
).scaledToHeight(64, Qt.SmoothTransformation)
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
self.loggerButton.clicked.connect(self.showLogger)
|
|
39
|
+
self.requestButton.clicked.connect(self.submitRequest)
|
|
40
|
+
self.ignoreButton.clicked.connect(self.close)
|
|
41
|
+
|
|
42
|
+
def setText(self, exc_info):
|
|
43
|
+
from .console import ConsolePrEdit
|
|
44
|
+
|
|
45
|
+
self.traceback_msg = "".join(traceback.format_exception(*exc_info))
|
|
46
|
+
msg = (
|
|
47
|
+
'The following error has occurred:<br>'
|
|
48
|
+
'<br><font color=%(color)s>%(text)s</font>'
|
|
49
|
+
)
|
|
50
|
+
self.errorLabel.setText(
|
|
51
|
+
msg
|
|
52
|
+
% {
|
|
53
|
+
'text': self.traceback_msg.split('\n')[-2],
|
|
54
|
+
'color': ConsolePrEdit._errorMessageColor.name(),
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def showLogger(self):
|
|
59
|
+
"""Create/show the main PrEditor instance with the full traceback."""
|
|
60
|
+
from .. import launch
|
|
61
|
+
|
|
62
|
+
launch()
|
|
63
|
+
self.close()
|
|
64
|
+
|
|
65
|
+
def submitRequest(self):
|
|
66
|
+
from ..utils.errorEmail import buildErrorMessage
|
|
67
|
+
|
|
68
|
+
subject, description = buildErrorMessage(self.traceback_msg, fmt='markdown')
|
|
69
|
+
subject = self.traceback_msg.split('\n')[-2]
|
|
70
|
+
from ..actions.create_redmine_issue import CreateRedmineIssue
|
|
71
|
+
|
|
72
|
+
kwargs = {
|
|
73
|
+
'subject': subject,
|
|
74
|
+
'description': description,
|
|
75
|
+
'screenshot': True,
|
|
76
|
+
'username': getpass.getuser(),
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# Tryin a first connection impersonating the current user.
|
|
80
|
+
try:
|
|
81
|
+
CreateRedmineIssue(**kwargs)()
|
|
82
|
+
|
|
83
|
+
# If that failed, we will use a dialog to prompt for credentials.
|
|
84
|
+
except ImpersonateError:
|
|
85
|
+
dialog = RedmineLoginDialog(parent=self)
|
|
86
|
+
result = dialog.exec_()
|
|
87
|
+
if result == QDialog.Accepted:
|
|
88
|
+
kwargs.update(
|
|
89
|
+
{
|
|
90
|
+
'username': dialog.username(),
|
|
91
|
+
'password': dialog.password(),
|
|
92
|
+
'redmine': dialog.redmine(),
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# The dialog can only return a successful connection.
|
|
97
|
+
CreateRedmineIssue(**kwargs)()
|
|
98
|
+
elif result == QDialog.Rejected:
|
|
99
|
+
return
|
|
100
|
+
self.close()
|
|
@@ -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)
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
from __future__ import absolute_import
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
import six
|
|
7
|
+
from Qt.QtCore import Qt
|
|
8
|
+
from Qt.QtGui import QIcon
|
|
9
|
+
from Qt.QtWidgets import QHBoxLayout, QMessageBox, QToolButton, QWidget
|
|
10
|
+
|
|
11
|
+
from ... import resourcePath
|
|
12
|
+
from ...prefs import prefs_path
|
|
13
|
+
from ..drag_tab_bar import DragTabBar
|
|
14
|
+
from ..workbox_text_edit import WorkboxTextEdit
|
|
15
|
+
from .grouped_tab_menu import GroupTabMenu
|
|
16
|
+
from .grouped_tab_widget import GroupedTabWidget
|
|
17
|
+
from .one_tab_widget import OneTabWidget
|
|
18
|
+
|
|
19
|
+
DEFAULT_STYLE_SHEET = """
|
|
20
|
+
/* Make the two buttons in the GroupTabWidget take up the
|
|
21
|
+
same horizontal space as the GroupedTabWidget's buttons. */
|
|
22
|
+
GroupTabWidget>QTabBar::tab{
|
|
23
|
+
max-height: 1.5em;
|
|
24
|
+
}
|
|
25
|
+
/* We have an icon, no need to show the menu indicator */
|
|
26
|
+
#group_tab_widget_menu_btn::menu-indicator{
|
|
27
|
+
width: 0px;
|
|
28
|
+
}
|
|
29
|
+
/* The GroupedTabWidget has a single button, make it take
|
|
30
|
+
the same space as the GroupTabWidget buttons. */
|
|
31
|
+
GroupedTabWidget>QToolButton,GroupTabWidget>QWidget{
|
|
32
|
+
width: 3em;
|
|
33
|
+
}
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class GroupTabWidget(OneTabWidget):
|
|
38
|
+
"""A QTabWidget where each tab contains another tab widget, allowing users
|
|
39
|
+
to group code editors. It has a corner button to add a new tab, and a menu
|
|
40
|
+
allowing users to quickly focus on any tab in the entire group.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, editor_kwargs=None, core_name=None, *args, **kwargs):
|
|
44
|
+
super(GroupTabWidget, self).__init__(*args, **kwargs)
|
|
45
|
+
DragTabBar.install_tab_widget(self, 'group_tab_widget')
|
|
46
|
+
self.editor_kwargs = editor_kwargs
|
|
47
|
+
self.editor_cls = WorkboxTextEdit
|
|
48
|
+
self.core_name = core_name
|
|
49
|
+
self.setStyleSheet(DEFAULT_STYLE_SHEET)
|
|
50
|
+
corner = QWidget(self)
|
|
51
|
+
lyt = QHBoxLayout(corner)
|
|
52
|
+
lyt.setSpacing(0)
|
|
53
|
+
lyt.setContentsMargins(0, 0, 0, 0)
|
|
54
|
+
|
|
55
|
+
corner.uiNewTabBTN = QToolButton(corner)
|
|
56
|
+
corner.uiNewTabBTN.setObjectName('group_tab_widget_new_btn')
|
|
57
|
+
corner.uiNewTabBTN.setText('+')
|
|
58
|
+
corner.uiNewTabBTN.setIcon(QIcon(resourcePath('img/file-plus.png')))
|
|
59
|
+
corner.uiNewTabBTN.released.connect(lambda: self.add_new_tab(None))
|
|
60
|
+
lyt.addWidget(corner.uiNewTabBTN)
|
|
61
|
+
|
|
62
|
+
corner.uiMenuBTN = QToolButton(corner)
|
|
63
|
+
corner.uiMenuBTN.setIcon(QIcon(resourcePath('img/chevron-down.png')))
|
|
64
|
+
corner.uiMenuBTN.setObjectName('group_tab_widget_menu_btn')
|
|
65
|
+
corner.uiMenuBTN.setPopupMode(QToolButton.InstantPopup)
|
|
66
|
+
corner.uiCornerMENU = GroupTabMenu(self, parent=corner.uiMenuBTN)
|
|
67
|
+
corner.uiMenuBTN.setMenu(corner.uiCornerMENU)
|
|
68
|
+
lyt.addWidget(corner.uiMenuBTN)
|
|
69
|
+
|
|
70
|
+
self.uiCornerBTN = corner
|
|
71
|
+
self.setCornerWidget(self.uiCornerBTN, Qt.TopRightCorner)
|
|
72
|
+
|
|
73
|
+
def add_new_tab(self, group, title="Workbox"):
|
|
74
|
+
"""Adds a new tab to the requested group, creating the group if the group
|
|
75
|
+
doesn't exist.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
group: The group to add a new tab to. This can be an int index of an
|
|
79
|
+
existing tab, or the name of the group and it will create the group
|
|
80
|
+
if needed. If None is passed it will add a new tab `Group {last+1}`.
|
|
81
|
+
If True is passed, then the current group tab is used.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
GroupedTabWidget: The tab group for this group.
|
|
85
|
+
WorkboxMixin: The new text editor.
|
|
86
|
+
"""
|
|
87
|
+
parent = None
|
|
88
|
+
if not group:
|
|
89
|
+
last = 0
|
|
90
|
+
for i in range(self.count()):
|
|
91
|
+
match = re.match(r'Group (\d+)', self.tabText(i))
|
|
92
|
+
if match:
|
|
93
|
+
last = max(last, int(match.group(1)))
|
|
94
|
+
group = "Group {}".format(last + 1)
|
|
95
|
+
elif group is True:
|
|
96
|
+
group = self.currentIndex()
|
|
97
|
+
if isinstance(group, int):
|
|
98
|
+
group_title = self.tabText(group)
|
|
99
|
+
parent = self.widget(group)
|
|
100
|
+
elif isinstance(group, six.string_types):
|
|
101
|
+
group_title = group
|
|
102
|
+
index = self.index_for_text(group)
|
|
103
|
+
if index != -1:
|
|
104
|
+
parent = self.widget(index)
|
|
105
|
+
|
|
106
|
+
if not parent:
|
|
107
|
+
parent, group_title = self.default_tab(group_title)
|
|
108
|
+
self.addTab(parent, group_title)
|
|
109
|
+
|
|
110
|
+
# Create the first editor tab and make it visible
|
|
111
|
+
editor = parent.add_new_editor(title)
|
|
112
|
+
self.setCurrentIndex(self.indexOf(parent))
|
|
113
|
+
|
|
114
|
+
return parent, editor
|
|
115
|
+
|
|
116
|
+
def all_widgets(self):
|
|
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
|
|
131
|
+
|
|
132
|
+
def close_current_tab(self):
|
|
133
|
+
"""Convenient method to close the currently open editor tab prompting
|
|
134
|
+
the user to confirm closing."""
|
|
135
|
+
editor_tab = self.currentWidget()
|
|
136
|
+
editor_tab.close_tab(editor_tab.currentIndex())
|
|
137
|
+
|
|
138
|
+
def close_tab(self, index):
|
|
139
|
+
ret = QMessageBox.question(
|
|
140
|
+
self,
|
|
141
|
+
'Close all editors under this tab?',
|
|
142
|
+
'Are you sure you want to close all tabs under the "{}" tab?'.format(
|
|
143
|
+
self.tabText(self.currentIndex())
|
|
144
|
+
),
|
|
145
|
+
QMessageBox.Yes | QMessageBox.Cancel,
|
|
146
|
+
)
|
|
147
|
+
if ret == QMessageBox.Yes:
|
|
148
|
+
# Clean up all temp files created by this group's editors if they
|
|
149
|
+
# are not using actual saved files.
|
|
150
|
+
tab_widget = self.widget(self.currentIndex())
|
|
151
|
+
for index in range(tab_widget.count()):
|
|
152
|
+
editor = tab_widget.widget(index)
|
|
153
|
+
editor.__remove_tempfile__()
|
|
154
|
+
|
|
155
|
+
super(GroupTabWidget, self).close_tab(self.currentIndex())
|
|
156
|
+
|
|
157
|
+
def current_groups_widget(self):
|
|
158
|
+
"""Returns the current widget of the currently selected group or None."""
|
|
159
|
+
editor_tab = self.currentWidget()
|
|
160
|
+
if editor_tab:
|
|
161
|
+
return editor_tab.currentWidget()
|
|
162
|
+
|
|
163
|
+
def default_tab(self, title='Group 1'):
|
|
164
|
+
widget = GroupedTabWidget(
|
|
165
|
+
parent=self,
|
|
166
|
+
editor_kwargs=self.editor_kwargs,
|
|
167
|
+
editor_cls=self.editor_cls,
|
|
168
|
+
core_name=self.core_name,
|
|
169
|
+
)
|
|
170
|
+
return widget, title
|
|
171
|
+
|
|
172
|
+
def restore_prefs(self, prefs):
|
|
173
|
+
"""Adds tab groups and tabs, restoring the selected tabs. If a tab is
|
|
174
|
+
linked to a file that no longer exists, will not be added. Restores the
|
|
175
|
+
current tab for each group and the current group of tabs. If a current
|
|
176
|
+
tab is no longer valid, it will default to the first tab.
|
|
177
|
+
|
|
178
|
+
Preference schema:
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"groups": [
|
|
182
|
+
{
|
|
183
|
+
// Name of the group tab. [Required]
|
|
184
|
+
"name": "My Group",
|
|
185
|
+
// This group should be the active group. First in list wins.
|
|
186
|
+
"current": true,
|
|
187
|
+
"tabs": [
|
|
188
|
+
{
|
|
189
|
+
// If filename is not null, this file is loaded
|
|
190
|
+
"filename": "C:\\temp\\invalid_asdfdfd.py",
|
|
191
|
+
// Name of the editor's tab [Optional]
|
|
192
|
+
"name": "invalid_asdfdfd.py",
|
|
193
|
+
"tempfile": null
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
// This tab should be active for the group.
|
|
197
|
+
"current": true,
|
|
198
|
+
"filename": null,
|
|
199
|
+
"name": "Workbox",
|
|
200
|
+
// If tempfile is not null, this file is loaded.
|
|
201
|
+
// Ignored if filename is not null.
|
|
202
|
+
"tempfile": "workbox_2yrwctco_a.py"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
self.clear()
|
|
212
|
+
|
|
213
|
+
workbox_dir = prefs_path('workboxes', core_name=self.core_name)
|
|
214
|
+
current_group = None
|
|
215
|
+
for group in prefs.get('groups', []):
|
|
216
|
+
current_tab = None
|
|
217
|
+
group_name = group['name']
|
|
218
|
+
tab_widget = None
|
|
219
|
+
|
|
220
|
+
for tab in group.get('tabs', []):
|
|
221
|
+
# Only add this tab if, there is data on disk to load. The user can
|
|
222
|
+
# open multiple instances of PrEditor using the same prefs. The
|
|
223
|
+
# json pref data represents the last time the prefs were saved.
|
|
224
|
+
# Each editor's contents are saved to individual files on disk.
|
|
225
|
+
# When a editor tab is closed, the temp file is removed, not on
|
|
226
|
+
# preferences save.
|
|
227
|
+
# By not restoring tabs for deleted files we prevent accidentally
|
|
228
|
+
# restoring a tab with empty text.
|
|
229
|
+
filename = tab.get('filename')
|
|
230
|
+
temp_name = tab.get('tempfile')
|
|
231
|
+
if filename:
|
|
232
|
+
if not os.path.exists(filename):
|
|
233
|
+
continue
|
|
234
|
+
if not temp_name:
|
|
235
|
+
continue
|
|
236
|
+
temp_name = os.path.join(workbox_dir, temp_name)
|
|
237
|
+
if not os.path.exists(temp_name):
|
|
238
|
+
continue
|
|
239
|
+
|
|
240
|
+
# There is a file on disk, add the tab, creating the group
|
|
241
|
+
# tab if it hasn't already been created.
|
|
242
|
+
name = tab['name']
|
|
243
|
+
tab_widget, editor = self.add_new_tab(group_name, name)
|
|
244
|
+
editor.__restore_prefs__(tab)
|
|
245
|
+
|
|
246
|
+
# If more than one tab in this group is listed as current, only
|
|
247
|
+
# respect the first
|
|
248
|
+
if current_tab is None and tab.get('current'):
|
|
249
|
+
current_tab = tab_widget.indexOf(editor)
|
|
250
|
+
|
|
251
|
+
# If there were no files to load, this tab was not added and there
|
|
252
|
+
# we don't need to restore the current tab for this group
|
|
253
|
+
if tab_widget is None:
|
|
254
|
+
continue
|
|
255
|
+
|
|
256
|
+
# Restore the current tab for this group
|
|
257
|
+
if current_tab is None:
|
|
258
|
+
# If there is no longer a current tab, default to the first tab
|
|
259
|
+
current_tab = 0
|
|
260
|
+
tab_widget.setCurrentIndex(current_tab)
|
|
261
|
+
|
|
262
|
+
# Which tab group is the active one? If more than one tab in this
|
|
263
|
+
# group is listed as current, only respect the first.
|
|
264
|
+
if current_group is None and group.get('current'):
|
|
265
|
+
current_group = self.indexOf(tab_widget)
|
|
266
|
+
|
|
267
|
+
# Restore the current group for this widget
|
|
268
|
+
if current_group is None:
|
|
269
|
+
# If there is no longer a current tab, default to the first tab
|
|
270
|
+
current_group = 0
|
|
271
|
+
self.setCurrentIndex(current_group)
|
|
272
|
+
|
|
273
|
+
def save_prefs(self, prefs=None):
|
|
274
|
+
groups = []
|
|
275
|
+
if prefs is None:
|
|
276
|
+
prefs = {}
|
|
277
|
+
|
|
278
|
+
prefs['groups'] = groups
|
|
279
|
+
current_group = self.currentIndex()
|
|
280
|
+
for i in range(self.count()):
|
|
281
|
+
tabs = []
|
|
282
|
+
group = {}
|
|
283
|
+
# Hopefully the alphabetical sorting of this dict is preserved in py3
|
|
284
|
+
# to make it easy to diff the json pref file if ever required.
|
|
285
|
+
if i == current_group:
|
|
286
|
+
group['current'] = True
|
|
287
|
+
group['name'] = self.tabText(i)
|
|
288
|
+
group['tabs'] = tabs
|
|
289
|
+
|
|
290
|
+
tab_widget = self.widget(i)
|
|
291
|
+
current_editor = tab_widget.currentIndex()
|
|
292
|
+
for j in range(tab_widget.count()):
|
|
293
|
+
current = True if j == current_editor else None
|
|
294
|
+
tabs.append(
|
|
295
|
+
tab_widget.widget(j).__save_prefs__(
|
|
296
|
+
name=tab_widget.tabText(j), current=current
|
|
297
|
+
)
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
groups.append(group)
|
|
301
|
+
|
|
302
|
+
return prefs
|
|
303
|
+
|
|
304
|
+
def set_current_groups_from_index(self, group, editor):
|
|
305
|
+
"""Make the specified indexes the current widget and return it. If the
|
|
306
|
+
indexes are out of range the current widget is not changed.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
group (int): The index of the group tab to make current.
|
|
310
|
+
editor (int): The index of the editor under the group tab to
|
|
311
|
+
make current.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
QWidget: The current widget after applying.
|
|
315
|
+
"""
|
|
316
|
+
self.setCurrentIndex(group)
|
|
317
|
+
tab_widget = self.currentWidget()
|
|
318
|
+
tab_widget.setCurrentIndex(editor)
|
|
319
|
+
return tab_widget.currentWidget()
|