Skip to content

Commit 9dcc934

Browse files
authored
Merge pull request #13 from dreamworksanimation/dev
Version 0.7.0
2 parents c81edfe + 615e675 commit 9dcc934

File tree

6 files changed

+263
-120
lines changed

6 files changed

+263
-120
lines changed

usdmanager/__init__.py

Lines changed: 80 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ class UsdMngrWindow(QtWidgets.QMainWindow):
163163
- AddressBar file completer has problems occasionally.
164164
- Figure out why network printers aren't showing up. Linux or DWA
165165
issue? macOS and Windows are fine.
166-
- When reading in a USDZ file, the progress bar gets stuck.
167166
- Qt.py problems:
168167
169168
- PyQt5
@@ -208,7 +207,7 @@ def __init__(self, parent=None, **kwargs):
208207
# externally. The user's preferred programs are stored in
209208
# self.programs.
210209
self.defaultPrograms = {x: "" for x in USD_EXTS}
211-
self.defaultPrograms.update(self.app.appConfig.get("defaultPrograms", {}))
210+
self.defaultPrograms.update(self.app.DEFAULTS['defaultPrograms'])
212211
self.programs = self.defaultPrograms
213212
self.masterHighlighters = {}
214213

@@ -247,12 +246,14 @@ def setupUi(self):
247246
self.baseInstance = utils.loadUiWidget('main_window.ui', self)
248247

249248
# You now have access to the widgets defined in the ui file.
250-
self.defaultDocFont = QtGui.QFont()
251-
self.defaultDocFont.setStyleHint(QtGui.QFont.Courier)
252-
self.defaultDocFont.setFamily("Monospace")
253-
self.defaultDocFont.setPointSize(9)
254-
self.defaultDocFont.setBold(False)
255-
self.defaultDocFont.setItalic(False)
249+
# Update some app defaults that required the GUI to be created first.
250+
defaultDocFont = QtGui.QFont()
251+
defaultDocFont.setStyleHint(QtGui.QFont.Courier)
252+
defaultDocFont.setFamily("Monospace")
253+
defaultDocFont.setPointSize(9)
254+
defaultDocFont.setBold(False)
255+
defaultDocFont.setItalic(False)
256+
self.app.DEFAULTS['font'] = defaultDocFont
256257

257258
self.readSettings()
258259
self.compileLinkRegEx()
@@ -288,13 +289,13 @@ def setupUi(self):
288289
</style></head><body style="white-space:pre">{}</body></html>"""
289290

290291
searchPaths = QtGui.QIcon.themeSearchPaths()
291-
extraSearchPaths = [x for x in self.app.appConfig.get("themeSearchPaths", []) if x not in searchPaths]
292+
extraSearchPaths = [x for x in self.app.DEFAULTS['themeSearchPaths'] if x not in searchPaths]
292293
if extraSearchPaths:
293294
searchPaths = extraSearchPaths + searchPaths
294295
QtGui.QIcon.setThemeSearchPaths(searchPaths)
295296

296297
# Set the preferred theme name for some non-standard icons.
297-
QtGui.QIcon.setThemeName(self.app.appConfig.get("iconTheme", "crystal_project"))
298+
QtGui.QIcon.setThemeName(self.app.DEFAULTS['iconTheme'])
298299

299300
# Try to adhere to the freedesktop icon standards (https://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html).
300301
# Some icons are preferred from the crystal_project set, which sadly follows different naming standards.
@@ -633,27 +634,27 @@ def readSettings(self):
633634
""" Read in user config settings.
634635
"""
635636
logger.debug("Reading user settings from {}".format(self.config.fileName()))
636-
# Get basic preferences.
637-
# TODO: Read some of these from the same places as the preferences dialog so we don't have to maintain defaults in 2 places.
637+
default = self.app.DEFAULTS
638638
self.preferences = {
639-
'parseLinks': self.config.boolValue("parseLinks", True),
640-
'newTab': self.config.boolValue("newTab", False),
641-
'syntaxHighlighting': self.config.boolValue("syntaxHighlighting", True),
642-
'teletype': self.config.boolValue("teletype", True),
643-
'lineNumbers': self.config.boolValue("lineNumbers", True),
644-
'showAllMessages': self.config.boolValue("showAllMessages", True),
645-
'showHiddenFiles': self.config.boolValue("showHiddenFiles", False),
646-
'font': self.config.value("font", self.defaultDocFont),
647-
'fontSizeAdjust': int(self.config.value("fontSizeAdjust", 0)),
648-
'findMatchCase': self.config.boolValue("findMatchCase", self.checkBoxMatchCase.isChecked()),
649-
'includeVisible': self.config.boolValue("includeVisible", self.actionIncludePanel.isChecked()),
650-
'lastOpenWithStr': self.config.value("lastOpenWithStr", ""),
651-
'textEditor': self.config.value("textEditor", os.getenv("EDITOR", self.app.appConfig.get("textEditor", "nedit"))),
652-
'diffTool': self.config.value("diffTool", self.app.appConfig.get("diffTool", "xdiff")),
653-
'autoCompleteAddressBar': self.config.boolValue("autoCompleteAddressBar", True),
654-
'useSpaces': self.config.boolValue("useSpaces", True),
655-
'tabSpaces': int(self.config.value("tabSpaces", 4)),
656-
'theme': self.config.value("theme", None),
639+
'parseLinks': self.config.boolValue("parseLinks", default['parseLinks']),
640+
'newTab': self.config.boolValue("newTab", default['newTab']),
641+
'syntaxHighlighting': self.config.boolValue("syntaxHighlighting", default['syntaxHighlighting']),
642+
'teletype': self.config.boolValue("teletype", default['teletype']),
643+
'lineNumbers': self.config.boolValue("lineNumbers", default['lineNumbers']),
644+
'showAllMessages': self.config.boolValue("showAllMessages", default['showAllMessages']),
645+
'showHiddenFiles': self.config.boolValue("showHiddenFiles", default['showHiddenFiles']),
646+
'font': self.config.value("font", default['font']),
647+
'fontSizeAdjust': int(self.config.value("fontSizeAdjust", default['fontSizeAdjust'])),
648+
'findMatchCase': self.config.boolValue("findMatchCase", default['findMatchCase']),
649+
'includeVisible': self.config.boolValue("includeVisible", default['includeVisible']),
650+
'lastOpenWithStr': self.config.value("lastOpenWithStr", default['lastOpenWithStr']),
651+
'textEditor': self.config.value("textEditor", default['textEditor']),
652+
'diffTool': self.config.value("diffTool", default['diffTool']),
653+
'autoCompleteAddressBar': self.config.boolValue("autoCompleteAddressBar", default['autoCompleteAddressBar']),
654+
'useSpaces': self.config.boolValue("useSpaces", default['useSpaces']),
655+
'tabSpaces': int(self.config.value("tabSpaces", default['tabSpaces'])),
656+
'theme': self.config.value("theme", default['theme']),
657+
'lineLimit': int(self.config.value("lineLimit", default['lineLimit'])),
657658
}
658659

659660
# Read 'programs' settings object into self.programs.
@@ -736,6 +737,7 @@ def writeSettings(self):
736737
self.config.setValue("useSpaces", self.preferences['useSpaces'])
737738
self.config.setValue("tabSpaces", self.preferences['tabSpaces'])
738739
self.config.setValue("theme", self.preferences['theme'])
740+
self.config.setValue("lineLimit", self.preferences['lineLimit'])
739741

740742
# Write self.programs to settings object
741743
exts = self.programs.keys()
@@ -1918,11 +1920,14 @@ def editPreferences(self):
19181920
dlg = PreferencesDialog(self)
19191921
# Open dialog.
19201922
if dlg.exec_() == dlg.Accepted:
1921-
# Save new preferences.
1923+
# Users currently have to refresh to see these changes.
19221924
self.preferences['parseLinks'] = dlg.getPrefParseLinks()
1923-
self.preferences['newTab'] = dlg.getPrefNewTab()
19241925
self.preferences['syntaxHighlighting'] = dlg.getPrefSyntaxHighlighting()
19251926
self.preferences['teletype'] = dlg.getPrefTeletypeConversion()
1927+
self.preferences['theme'] = dlg.getPrefTheme()
1928+
1929+
# These changes do not require the user to refresh any tabs to see the change.
1930+
self.preferences['newTab'] = dlg.getPrefNewTab()
19261931
self.preferences['lineNumbers'] = dlg.getPrefLineNumbers()
19271932
self.preferences['showAllMessages'] = dlg.getPrefShowAllMessages()
19281933
self.preferences['showHiddenFiles'] = dlg.getPrefShowHiddenFiles()
@@ -1932,7 +1937,7 @@ def editPreferences(self):
19321937
self.preferences['font'] = dlg.getPrefFont()
19331938
self.preferences['useSpaces'] = dlg.getPrefUseSpaces()
19341939
self.preferences['tabSpaces'] = dlg.getPrefTabSpaces()
1935-
self.preferences['theme'] = dlg.getPrefTheme()
1940+
self.preferences['lineLimit'] = dlg.getPrefLineLimit()
19361941

19371942
# Update font and line number visibility in all tabs.
19381943
self.tabWidget.setFont(self.preferences['font'])
@@ -1964,9 +1969,6 @@ def editPreferences(self):
19641969
else:
19651970
self.addressBar.setCompleter(QtWidgets.QCompleter())
19661971

1967-
if not self.currTab.isDirty():
1968-
self.refreshTab()
1969-
19701972
self.writeSettings()
19711973

19721974
@Slot(int)
@@ -1977,7 +1979,7 @@ def updatePreference_findMatchCase(self, checked):
19771979
checked : `int`
19781980
State of checkbox.
19791981
"""
1980-
checked = checked & QtCore.Qt.Checked
1982+
checked = checked == QtCore.Qt.Checked
19811983
if checked != self.preferences['findMatchCase']:
19821984
self.preferences['findMatchCase'] = checked
19831985
for lang, h in self.masterHighlighters.iteritems():
@@ -2185,7 +2187,7 @@ def restoreTab(self, tab):
21852187
self.menuRecentlyClosedTabs.setEnabled(False)
21862188

21872189
# Update settings in the recently re-opened tab that may have changed.
2188-
if self.preferences['font'] != self.defaultDocFont:
2190+
if self.preferences['font'] != self.app.DEFAULTS['font']:
21892191
tab.textBrowser.setFont(self.preferences['font'])
21902192
tab.textEditor.setFont(self.preferences['font'])
21912193
tab.lineNumbers.setVisible(self.preferences['lineNumbers'])
@@ -2348,7 +2350,7 @@ def launchTextEditor(self):
23482350
def launchUsdView(self):
23492351
""" Launch the current file in usdview.
23502352
"""
2351-
app = self.app.appConfig.get("usdview", "usdview")
2353+
app = self.app.DEFAULTS['usdview']
23522354
path = self.currTab.getCurrentPath()
23532355
# Files with spaces have to be double-quoted on Windows for usdview.
23542356
if os.name == "nt":
@@ -2557,9 +2559,9 @@ def setSource(self, link, isNewFile=True, newTab=False, hScrollPos=0, vScrollPos
25572559
vScrollPos : `int`
25582560
Vertical scroll bar position.
25592561
"""
2560-
# Check if the current tab is dirty before doing anything.
2562+
# If we're staying in the current tab, check if the tab is dirty before doing anything.
25612563
# Perform save operations if necessary.
2562-
if not self.dirtySave():
2564+
if not newTab and not self.dirtySave():
25632565
return True
25642566

25652567
# Re-cast the QUrl so any query strings are evaluated properly.
@@ -2681,6 +2683,8 @@ def setSource(self, link, isNewFile=True, newTab=False, hScrollPos=0, vScrollPos
26812683
layer = utils.queryItemValue(link, "layer")
26822684
dest = utils.unzip(fileStr, layer, self.app.tmpDir)
26832685
self.restoreOverrideCursor()
2686+
self.statusbar.removeWidget(loadingProgressBar)
2687+
self.statusbar.removeWidget(loadingProgressLabel)
26842688
return self.setSource(QtCore.QUrl(dest))
26852689
else:
26862690
if ext == "usda":
@@ -2709,11 +2713,13 @@ def setSource(self, link, isNewFile=True, newTab=False, hScrollPos=0, vScrollPos
27092713

27102714
# TODO: Figure out a better way to handle streaming text for large files like Crate geometry.
27112715
# Large chunks of text (e.g. 2.2 billion characters) will cause Qt to segfault when creating a QString.
2712-
if length > LINE_LIMIT:
2713-
length = LINE_LIMIT
2716+
lineLimit = self.preferences['lineLimit']
2717+
if length > lineLimit:
2718+
length = lineLimit
27142719
truncated = True
27152720
fileText = fileText[:length]
2716-
warning = "Extremely large file! Capping display at {:,d} lines.".format(LINE_LIMIT)
2721+
warning = "Extremely large file! Capping display at {:,d} lines. You can edit this cap in the "\
2722+
"Advanced tab of Preferences.".format(lineLimit)
27172723

27182724
loadingProgressBar.setMaximum(length - 1)
27192725
if self.stopLoadingTab:
@@ -4274,13 +4280,40 @@ def run(self):
42744280
try:
42754281
logger.info("Loading app config from {}".format(appConfigPath))
42764282
with open(appConfigPath) as f:
4277-
self.appConfig = json.load(f)
4283+
appConfig = json.load(f)
42784284
except Exception as e:
42794285
logger.error("Failed to load app config from {}: {}".format(appConfigPath, e))
4280-
self.appConfig = {}
4286+
appConfig = {}
4287+
4288+
# Define app defaults that we use when the user preference doesn't exist and when resetting preferences in the
4289+
# Preferences dialog.
4290+
self.DEFAULTS = {
4291+
'autoCompleteAddressBar': True,
4292+
'defaultPrograms': appConfig.get("defaultPrograms", {}),
4293+
'diffTool': appConfig.get("diffTool", "xdiff"),
4294+
'findMatchCase': False,
4295+
'fontSizeAdjust': 0,
4296+
'iconTheme': appConfig.get("iconTheme", "crystal_project"),
4297+
'includeVisible': True,
4298+
'lastOpenWithStr': "",
4299+
'lineLimit': LINE_LIMIT,
4300+
'lineNumbers': True,
4301+
'newTab': False,
4302+
'parseLinks': True,
4303+
'showAllMessages': True,
4304+
'showHiddenFiles': False,
4305+
'syntaxHighlighting': True,
4306+
'tabSpaces': 4,
4307+
'teletype': True,
4308+
'textEditor': os.getenv("EDITOR", appConfig.get("textEditor", "nedit")),
4309+
'theme': None,
4310+
'themeSearchPaths': appConfig.get("themeSearchPaths", []),
4311+
'usdview': appConfig.get("usdview", "usdview"),
4312+
'useSpaces': True,
4313+
}
42814314

42824315
# Documentation URL.
4283-
self.appURL = self.appConfig.get("appURL", "https://github.com/dreamworksanimation/usdmanager")
4316+
self.appURL = appConfig.get("appURL", "https://github.com/dreamworksanimation/usdmanager")
42844317

42854318
# Create a main window.
42864319
window = self.newWindow()

usdmanager/constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252

5353
# Truncate loading files with more lines than this.
5454
# Display can slow down and/or become unusable with too many lines.
55-
LINE_LIMIT = 10000
55+
# This number is less important than the total number of characters and can be overridden in Preferences.
56+
LINE_LIMIT = 50000
5657

5758
# Truncate loading files with more total chars than this.
5859
# QString crashes at ~2.1 billion chars, but display slows down way before that.

usdmanager/preferences_dialog.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from Qt.QtGui import QIcon, QRegExpValidator
2020
from Qt.QtWidgets import (QAbstractButton, QDialog, QDialogButtonBox, QFontDialog, QLineEdit, QMessageBox, QVBoxLayout)
2121

22+
from .constants import LINE_LIMIT
2223
from .utils import loadUiWidget
2324

2425

@@ -77,6 +78,7 @@ def setupUi(self, widget):
7778
self.lineEditTextEditor.setText(parent.preferences['textEditor'])
7879
self.lineEditDiffTool.setText(parent.preferences['diffTool'])
7980
self.themeWidget.setChecked(parent.preferences['theme'] == "dark")
81+
self.lineLimitSpinBox.setValue(parent.preferences['lineLimit'])
8082
self.updateFontLabel()
8183

8284
# ----- Programs tab -----
@@ -189,6 +191,15 @@ def getPrefAutoCompleteAddressBar(self):
189191
"""
190192
return self.checkBox_autoCompleteAddressBar.isChecked()
191193

194+
def getPrefLineLimit(self):
195+
"""
196+
:Returns:
197+
Number of lines to display before truncating a file.
198+
:Rtype:
199+
`int`
200+
"""
201+
return self.lineLimitSpinBox.value()
202+
192203
def getPrefSyntaxHighlighting(self):
193204
"""
194205
:Returns:
@@ -319,22 +330,23 @@ def restoreDefaults(self, btn):
319330
self.deleteItems(self.extLayout)
320331

321332
# Set other preferences in the GUI.
322-
window = self.parent().window()
323-
self.checkBox_parseLinks.setChecked(True)
324-
self.checkBox_newTab.setChecked(False)
325-
self.checkBox_syntaxHighlighting.setChecked(True)
326-
self.checkBox_teletypeConversion.setChecked(True)
327-
self.checkBox_lineNumbers.setChecked(True)
328-
self.checkBox_showAllMessages.setChecked(True)
329-
self.checkBox_showHiddenFiles.setChecked(False)
330-
self.checkBox_autoCompleteAddressBar.setChecked(True)
331-
self.lineEditTextEditor.setText(os.getenv("EDITOR", window.app.appConfig.get("textEditor", "nedit")))
332-
self.lineEditDiffTool.setText(window.app.appConfig.get("diffTool", "xdiff"))
333-
self.useSpacesCheckBox.setChecked(True)
334-
self.useSpacesSpinBox.setValue(4)
333+
default = self.parent().window().app.DEFAULTS
334+
self.checkBox_parseLinks.setChecked(default['parseLinks'])
335+
self.checkBox_newTab.setChecked(default['newTab'])
336+
self.checkBox_syntaxHighlighting.setChecked(default['syntaxHighlighting'])
337+
self.checkBox_teletypeConversion.setChecked(default['teletype'])
338+
self.checkBox_lineNumbers.setChecked(default['lineNumbers'])
339+
self.checkBox_showAllMessages.setChecked(default['showAllMessages'])
340+
self.checkBox_showHiddenFiles.setChecked(default['showHiddenFiles'])
341+
self.checkBox_autoCompleteAddressBar.setChecked(default['autoCompleteAddressBar'])
342+
self.lineEditTextEditor.setText(default['textEditor'])
343+
self.lineEditDiffTool.setText(default['diffTool'])
344+
self.useSpacesCheckBox.setChecked(default['useSpaces'])
345+
self.useSpacesSpinBox.setValue(default['tabSpaces'])
335346
self.themeWidget.setChecked(False)
336-
self.docFont = window.defaultDocFont
347+
self.docFont = default['font']
337348
self.updateFontLabel()
349+
self.lineLimitSpinBox.setValue(default['lineLimit'])
338350

339351
# Re-create file association fields with the default programs.
340352
self.populateProgsAndExts(self.parent().defaultPrograms)

0 commit comments

Comments
 (0)