diff --git a/.gitignore b/.gitignore index 1c0384c..c938ddb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ #General ------------------------------------------------------------ -**.idea* +**.idea/* **.experiments* #Golang ------------------------------------------------------------- @@ -49,13 +49,13 @@ share/python-wheels/ *.egg MANIFEST *.db -python2.7libs/* -!python2.7libs/searcher/ -python2.7libs/searcher/.history +python*.7libs/* +!python*.7libs/searcher/ +python*.7libs/searcher/.history **.history* -python2.7libs/searcher/go/houdini -python2.7libs/searcher/db -python2.7libs/searcher/_conversion +python*.7libs/searcher/go/houdini +python*.7libs/searcher/db +python*.7libs/searcher/_conversion # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. @@ -158,3 +158,5 @@ dmypy.json .pyre/ venv1/* .DS_Store + +.idea/ diff --git a/.idea/Searcher.iml b/.idea/Searcher.iml deleted file mode 100644 index e5da05c..0000000 --- a/.idea/Searcher.iml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index e6361d2..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index e2f46d8..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 04c43ba..804e4a0 100644 --- a/README.md +++ b/README.md @@ -13,17 +13,17 @@ Thanks for checking out Searcher. Below are the instructions to get you up and r ## Help Docs https://help.instance.id/searcher/ -## Note for Houdini 18.5 -SideFX has only included SQLite v 3.31.0 with H18.5 and their support has told me they have no plans to upgrade it to 3.33.0 (which has FTS5 enabled (Full-Text Search), which is needed by Searcher). Because of this, an extra step is required to install/use Searcher with Houdini 18.5 until/unless they decide to include SQLite 3.33.0 instead of 3.31.0. +## Note for Houdini 18.5+ +SideFX has only included SQLite v 3.31.0 with H18.5 and their support has told me they have no plans to upgrade it to 3.33.0 (which has FTS5 enabled (Full-Text Search), which is needed by Searcher). Because of this, an extra step is required to install/use Searcher with Houdini 18.5+ until/unless they decide to include SQLite 3.33.0 instead of 3.31.0. Download: Windows x64: [SQLite v3.33.0](https://www.sqlite.org/2020/sqlite-dll-win64-x64-3330000.zip) - Extract the downloaded sqlite-dll-win64-x64-3330000.zip file, then in another window browse to your Houdini installation directory: aka `$HFS/bin`. - By default this is located at: `C:\Program Files\SideFX\Houdini18.5.351\bin` + By default this is located at: `C:\Program Files\SideFX\Houdini19.0.xxx\bin` - In the Houdini $HFS/bin folder, locate the `sqlite3.dll` file and either make a backup copy to save elsewhere (just in case), or simply rename it to `sqlite3.dll.bak` - From the extracted sqlite-dll-win64-x64-3330000.zip, locate the new `sqlite3.dll` then copy and paste it into the `$HFS/bin` folder. -From my testing, that was all that needed to be done, as Searcher worked for me at that point, but Houdini support mentioned that the sqlite3.dll located in the `$HFS/python27/dlls` folder should be replaced as well. Just make sure to back it up/rename it as well. Always better to be safe than sorry! +From my testing, that was all that needed to be done, as Searcher worked for me at that point, but Houdini support mentioned that the sqlite3.dll located in the `$HFS/python27/dlls` or `$HFS/python37/dlls` folder should be replaced as well. Just make sure to back it up/rename it as well. Always better to be safe than sorry! The process is the same for Unix OS's, you just have to go to the `$HFS/bin` folder that cooresponds to your particular OS and instead of looking for sqlite3.dll, the file will just be `sqlite3`. I would love to test it, but Houdini 18.5 on Linux crashes when I try to open it on both my laptop and VM on my desktop. diff --git a/build.ps1 b/build.ps1 index 2afc684..5f64ba2 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,3 +1,5 @@ +#!/usr/bin/env pwsh + # .\build.ps1 -Zip -Version v0.1.0 Param ( [Parameter()] @@ -8,60 +10,84 @@ Param ( if ($Version) { Write-Host "Building $Version..." } else { - Write-Host "Just updating files..." + Write-Host 'Just updating files...' } -$date = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" -$exclude = "--exclude-from=E:\GitHub\Searcher\build\exclude.excl" -$include = "--include-from=E:\GitHub\Searcher\build\include.incl" -$config = "--config=C:/Users/mosthated/.backup/rclone.conf" - -$cmd = "C:\files\rclone\rclone.exe" +$date = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss' +$exclude = '--exclude-from=build/exclude.excl' +$include = '--include-from=build/include.incl' +$config = '--config=C:/Users/mosthated/.backup/rclone.conf' +$cmd = '' +$source1 = '' +$destination1 = '' -$source1 = "E:\GitHub\Searcher\" -$destination1 = "E:\Searcher" -$log1 = "--log-file=C:\files\rclone\logs\searcher_$date.log" +if ($IsWindows) { + $cmd = 'C:\files\rclone\rclone.exe' + $source1 = 'E:\GitHub\Searcher\' + $destination1 = 'E:\Searcher' + $log1 = "--log-file=C:\files\rclone\logs\Searcher_Build_$date.log" +} elseif ($IsLinux) { + $cmd = 'rclone' + $source1 = '/mnt/x/GitHub/instance-id/1_Projects/Searcher' + $destination1 = '/mnt/x/_dev/Searcher' + $log1 = "--log-file=$HOME/.backup/logs/Searcher_Build_$date.log" +} -&$cmd sync $source1 $destination1 $log1 $exclude $config --log-level NOTICE --progress --no-update-modtime --transfers=4 --checkers=8 --contimeout=60s --timeout=300s --retries=3 --low-level-retries=10 -L --stats=1s --stats-file-name-length=0 -P --ignore-case --fast-list --drive-chunk-size=64M +&$cmd sync $source1 $destination1 $log1 $exclude $config --log-level NOTICE ` + --progress ` + --no-update-modtime ` + --transfers=4 ` + --checkers=8 ` + --contimeout=60s ` + --timeout=300s ` + --retries=3 ` + --low-level-retries=10 ` + -L ` + --stats=1s ` + --stats-file-name-length=0 ` + -P ` + --ignore-case ` + --fast-list ` + --drive-chunk-size=64M if ($Version) { Write-Host "Building $Version..." - $searcher = "Searcher" - $destination2 = $searcher, $Version -join "_" + $searcher = 'Searcher' + $destination2 = $searcher, $Version -join '_' $folderVer = "$destination1\$destination2" - + Write-Host "Destination2: $destination2" - - if([System.IO.File]::Exists($folderVer)){ + + if ([System.IO.File]::Exists($folderVer)) { Get-ChildItem $folderVer -Recurse -ErrorAction SilentlyContinue | Remove-Item -Recurse } - New-Item "$folderVer\$searcher" -Type Directory + New-Item "$folderVer\$searcher" -Type Directory Move-Item -Path $destination1\packages -Destination $folderVer\packages Move-Item -Path $destination1\README.md -Destination $folderVer\README.md Move-Item -Path $destination1\Searcher_install_instructions.url -Destination $folderVer\Searcher_install_instructions.url - + Move-Item -Path $destination1\dso -Destination $folderVer\$searcher\dso Move-Item -Path $destination1\help -Destination $folderVer\$searcher\help Move-Item -Path $destination1\python2.7libs -Destination $folderVer\$searcher\python2.7libs + Move-Item -Path $destination1\python3.7libs -Destination $folderVer\$searcher\python3.7libs Move-Item -Path $destination1\toolbar -Destination $folderVer\$searcher\toolbar - + $listfiles = Get-ChildItem $folderVer -Recurse -File -Include '*.md', '*.txt' $old = '{#version}' - foreach($file in $listfiles) { - (Get-Content $file) -Replace ($old,$Version) | Set-Content $file + foreach ($file in $listfiles) { + (Get-Content $file) -Replace ($old, $Version) | Set-Content $file } - + $FileName = "$destination1\$destination2.zip" if (Test-Path $FileName) { Write-Host "Removing $FileName and recreating" Remove-Item $FileName } - if($Zip) - { + if ($Zip) { Compress-Archive -Path $folderVer -DestinationPath $FileName } - Write-Host "Update Complete" + Write-Host 'Update Complete' } else { - Write-Host "Update Complete" + Write-Host 'Update Complete' } \ No newline at end of file diff --git a/python2.7libs/searcher/__init__.py b/python2.7libs/searcher/__init__.py index c688ca8..8f3e41d 100644 --- a/python2.7libs/searcher/__init__.py +++ b/python2.7libs/searcher/__init__.py @@ -2,3 +2,5 @@ __author__ = "instance.id" __copyright__ = "2020 All rights reserved. See LICENSE for more details." __status__ = "Prototype" + +from . searcher import * diff --git a/python2.7libs/searcher/bugreport.py b/python2.7libs/searcher/bugreport.py index 5aa1ace..04fe76f 100644 --- a/python2.7libs/searcher/bugreport.py +++ b/python2.7libs/searcher/bugreport.py @@ -3,7 +3,6 @@ import os import hou - hver = 0 if os.environ["HFS"] != "": ver = os.environ["HFS"] diff --git a/python2.7libs/searcher/nodegraphhooks.py b/python2.7libs/searcher/nodegraphhooks.py index c6a0a9c..af011c3 100644 --- a/python2.7libs/searcher/nodegraphhooks.py +++ b/python2.7libs/searcher/nodegraphhooks.py @@ -5,13 +5,9 @@ sys.dont_write_bytecode = True import hou - from PySide2 import QtWidgets - from houdini_markingmenu import markingmenu as mm - from canvaseventtypes import * - import nodegraphbase as base sys.path.insert(0, os.path.join(hou.getenv('HOUDINI_USER_PREF_DIR'), diff --git a/python3.7libs/searcher/.extra/Untitled.json b/python3.7libs/searcher/.extra/Untitled.json new file mode 100644 index 0000000..887b166 --- /dev/null +++ b/python3.7libs/searcher/.extra/Untitled.json @@ -0,0 +1,14 @@ +{ + "env": [ + { + "MODELER": "C:/Users/PATH/TO/modeler/" + }, + { + "HOUDINI_PATH" : + { + "value": "$MODELER/", + "method": "append" + } + } + ] +} \ No newline at end of file diff --git a/python3.7libs/searcher/.extra/__init__.py b/python3.7libs/searcher/.extra/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python3.7libs/searcher/.extra/bug.html b/python3.7libs/searcher/.extra/bug.html new file mode 100644 index 0000000..33c26fa --- /dev/null +++ b/python3.7libs/searcher/.extra/bug.html @@ -0,0 +1,25 @@ + + + + + + + + Demo + + + + + + + + + + \ No newline at end of file diff --git a/python3.7libs/searcher/.extra/bugsubmit.html b/python3.7libs/searcher/.extra/bugsubmit.html new file mode 100644 index 0000000..d01f5d7 --- /dev/null +++ b/python3.7libs/searcher/.extra/bugsubmit.html @@ -0,0 +1,20 @@ + + + + + + ISSUE_TITLE + + + + + + + + \ No newline at end of file diff --git a/python3.7libs/searcher/.extra/scratch b/python3.7libs/searcher/.extra/scratch new file mode 100644 index 0000000..f1527a4 --- /dev/null +++ b/python3.7libs/searcher/.extra/scratch @@ -0,0 +1,324 @@ +# C:\Users\mosthated\AppData\Roaming\Python\Python37\Scripts\pyuic5.exe .\SearcherSettings.ui -o .\SearcherSettings.py + + # panetab = None + # for pane in hou.ui.floatingPaneTabs(): + # if pane.type() == hou.paneTabType.PythonPanel: + # print(pane.activeInterface().name()) + # if pane.activeInterface().name() == 'SceneGraphDetailsPanel': + # panetab = pane + # break + + # ret = [] + # for t in tabs: + # if t.type() == hou.paneTabType.PythonPanel: + # if t.activeInterface() == pytype: + # t.pane().setIsSplitMaximized(False) + # ret.append(t) + + +# else: +# os.environ['QT_API'] = 'pyside2' +# from PySide import QtUiTools +# from qtpy import QtGui +# from qtpy import QtCore +# from qtpy import QtWidgets +# endregion + + + + # ------------------------------------- checkforchanges + def checkforchanges(self): + for i in range(len(util.SETTINGS_KEYS)): + if util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "bool": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Get attribute: ", getattr(self, util.SETTINGS_KEYS[i])) + print("Get settings: ", bc(self.currentsettings[util.SETTINGS_KEYS[i]])) + if getattr(self, util.SETTINGS_KEYS[i]).isChecked() != bc(self.currentsettings[util.SETTINGS_KEYS[i]]): + if self.isdebug and self.isdebug.level in {"ALL"}: + print("{} value {}".format(util.SETTINGS_KEYS[i], getattr(self, util.SETTINGS_KEYS[i]).isChecked())) + print("{} value {}".format(util.SETTINGS_KEYS[i], bc(self.currentsettings[util.SETTINGS_KEYS[i]]))) + return True + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "text": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Get attribute: ", getattr(self, util.SETTINGS_KEYS[i])) + print("Get settings: ", self.currentsettings[util.SETTINGS_KEYS[i]]) + if getattr(self, util.SETTINGS_KEYS[i]).text() != self.currentsettings[util.SETTINGS_KEYS[i]]: + if self.isdebug and self.isdebug.level in {"ALL"}: + print("{} value {}".format(util.SETTINGS_KEYS[i], getattr(self, util.SETTINGS_KEYS[i]).text())) + print("{} value {}".format(util.SETTINGS_KEYS[i], self.currentsettings[util.SETTINGS_KEYS[i]])) + return True + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "intval": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Get attribute: ", getattr(self, util.SETTINGS_KEYS[i])) + print("Get settings: ", self.currentsettings[util.SETTINGS_KEYS[i]]) + if getattr(self, util.SETTINGS_KEYS[i]).value() != self.currentsettings[util.SETTINGS_KEYS[i]]: + if self.isdebug and self.isdebug.level in {"ALL"}: + print("{} value {}".format(util.SETTINGS_KEYS[i], getattr(self, util.SETTINGS_KEYS[i]).value())) + print("{} value {}".format(util.SETTINGS_KEYS[i], int(self.currentsettings[util.SETTINGS_KEYS[i]]))) + return True + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "cbx": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Get attribute: ", getattr(self, util.SETTINGS_KEYS[i])) + print("Get settings: ", self.currentsettings[util.SETTINGS_KEYS[i]]) + if getattr(self, util.SETTINGS_KEYS[i]).currentText() != self.currentsettings[util.SETTINGS_KEYS[i]]: + if self.isdebug and self.isdebug.level in {"ALL"}: + print("{} value {}".format(util.SETTINGS_KEYS[i], getattr(self, util.SETTINGS_KEYS[i]).currentText())) + print("{} value {}".format(util.SETTINGS_KEYS[i], str(self.currentsettings[util.SETTINGS_KEYS[i]]))) + return True + return False + + + def bug_cb(self, toggled): + if toggled == True and not self.bugreport.isVisible(): + if self.animatedsettings.isChecked(): + pos = self.bugreportbtn.mapToGlobal( + QtCore.QPoint( -43, 34)) + else: + pos = self.bugreportbtn.mapToGlobal( + QtCore.QPoint( -45, 35)) + self.bugreport.setGeometry( + pos.x(), + pos.y(), + self.bugreport.width(), + self.bugreport.height() + ) + self.bugreport.show() + else: + self.bugreport.close() + + def theme_cb(self, toggled): + if toggled == True and not self.theme.isVisible(): + if self.animatedsettings.isChecked(): + pos = self.themebtn.mapToGlobal( + QtCore.QPoint( -77, 34)) + else: + pos = self.themebtn.mapToGlobal( + QtCore.QPoint( -79, 35)) + self.theme.setGeometry( + pos.x(), + pos.y(), + self.theme.width(), + self.theme.height() + ) + self.theme.show() + else: + self.theme.close() + + def about_cb(self): + self.aboutui = about.About(self.parentwindow) + self.aboutui.setAttribute(QtCore.Qt.WA_StyledBackground, True) + self.aboutui.setWindowFlags( + QtCore.Qt.Popup | + QtCore.Qt.WindowStaysOnTopHint | + QtCore.Qt.NoDropShadowWindowHint | + QtCore.Qt.WindowStaysOnTopHint + ) + self.aboutui.setParent(self.parentwindow) + self.aboutui.move(self.pos().x() - 175, self.pos().y()) + self.aboutui.show() + + +# ------------------------------------------------------- CUSTOM FONT LOADER +style script ---------- +def getfontdb(): + return getattr(hou.session, "FONTDB", None) + +def getfont(font, size = -1, weight = -1): + if font in getfontdb().families(): + fontstr = "" + fontstr += ("Using %s" % font) + if size >= 0: + fontstr += (" : Size %s" % size) + if weight >= 0: + fontstr += (" : Weight %s" % weight) + else: + if hou.isUIAvailable(): + hou.ui.setStatusMessage(("%s not available" % font), severity=hou.severityType.Message) + return QtGui.QFont() + else: + print(("%s not available" % font)) + return QtGui.QFont() + + return QtGui.QFont(font, size, weight) +------- + + # CUSTOM FONT LOADER + self.infolbl = self.sui.info_lbl + self.infolbl_font = style.getfont("JetBrains Mono", 8) + self.infolbl_font.setWeight(40) + self.infolbl_font.setLetterSpacing(QtGui.QFont.AbsoluteSpacing, -1) + self.infolbl_font.setWordSpacing(-2) + # self.infolbl.setFont(self.infolbl_font) + + self.treetotal_lbl = self.sui.treetotal_lbl + self.treetotal_lbl_font = style.getfont("JetBrains Mono", 8) + self.treetotal_lbl_font.setWeight(40) + self.treetotal_lbl_font.setLetterSpacing(QtGui.QFont.AbsoluteSpacing, -1) + self.treetotal_lbl_font.setWordSpacing(0) + # self.treetotal_lbl.setFont(self.treetotal_lbl_font) + # self.treetotal_lbl.setMinimumSize(QtCore.QSize(50, 0)) + + # ------------------------------------------------------- Spacing + # tnum = str(treeitemsnum) + # goalnum = 5 + # if len(tnum) == 3: + # itmvald = tnum.rjust((goalnum + 2) - count_chars(str(treeitemsnum)), " ") + # else: + # itmvald = tnum.rjust((goalnum) - count_chars(str(treeitemsnum)), " ") + # itm = itmvald.replace(" ", " ") + + # ------------------------------------------------------- Auto - Add font + jbfont = getattr(hou.session, "FONTDB", None) + if not getattr(hou.session, "FONTDB", None): + fontlocation = os.path.join(script_path, "fonts") + jbfontfolder = "JetBrainsMono-1.0.0" + f = [] + for (dirpath, dirnames, filenames) in os.walk(os.path.join(fontlocation, jbfontfolder)): + f.extend(filenames) + break + if f: + for font in f: + fontdb = QtGui.QFontDatabase() + fontdb.addApplicationFont(os.path.join(fontlocation, jbfontfolder, font)) + print("Added %s" % font) + hou.session.FONTDB = fontdb + + + + # # ----------------------------------------- chooseColor + # # NOTE chooseColor ------------------------------------ + # def chooseColor(self): + # sender = self.sender() + # name = sender.objectName() + # colorfield = getattr(self.ui, name) + + # qcolor = QtGui.QColor() + # qcolor.setNamedColor(colorfield.text()) + + # color = hou.Color() + # color.setRGB(( + # qcolor.redF(), + # qcolor.greenF(), + # qcolor.blueF()) + # ) + + # result = hou.ui.selectColor(initial_color = color) + # allWidgets = QtWidgets.QApplication.allWidgets() + # for w in allWidgets: + # if "Select Color" in w.windowTitle(): + # pos = self.parent.mapToGlobal( + # QtCore.QPoint(-self.parent.width(), -self.parent.height())) + # w.setGeometry( + # pos.x(), + # pos.y(), + # w.width(), + # w.height() + # ) + # # w.move(self.parent.width()200, 100) + + # if result: + # rgb = result.rgb() + # newcolor = QtGui.QColor( + # rgb[0]*255, + # rgb[1]*255, + # rgb[2]*255 + # ) + + # if newcolor.isValid(): + # colorfield.setText(newcolor.name()) + # sender.setStyleSheet("background-color:" + colorfield.text()) + + + + + + # ----------------------------------------- chooseColor + # NOTE chooseColor ------------------------------------ + def chooseColor(self): + sender = self.sender() + + self.name = sender.objectName() + self.colorfield[self.name] = (getattr(self.ui, self.name), sender) + + qcolor = QtGui.QColor() + qcolor.setNamedColor(self.colorfield[self.name][0].text()) + + # color = hou.Color() + # color = QtGui.QColor() + # color.setRGB(( + # qcolor.redF(), + # qcolor.greenF(), + # qcolor.blueF()) + # ) + + # hou.ui.openColorEditor(self.colorchange_cb, include_alpha=False, initial_color = color) + # hd.executeDeferred(self._opencoloreditor, color) + colord = QtWidgets.QColorDialog(self) + colord.setModal(False) + pos = self.parentwindow.mapToGlobal( + QtCore.QPoint(self.parentwindow.width(), self.parentwindow.height())) + colord.move( + pos.x() + 300, + pos.y(), + ) + colord.getColor( + initial=qcolor, + parent=self, + options=QtWidgets.QColorDialog.DontUseNativeDialog + ) + # colord.setWindowFlags( + # QtCore.Qt.CustomizeWindowHint + # # | QtCore.Qt.WindowStaysOnTopHint + # # | QtCore.Qt.X11BypassWindowManagerHint + # ) + # self.activateWindow() + # self._opencoloreditor(color) + + + + # NOTE PANES --------------------------- + # hou.playbar.moveToBottom() + + # for ii in i: + # print(ii) + # print("Under mouse: ", i.windowTitle()) + print("--------------------------------------") + current_desktop = hou.ui.curDesktop() + # allpanes = current_desktop.panes() + # if allpanes: + # try: + # self.processdesktop("current_desktop.panes()", allpanes) + # except: + # pass + # panetabsd = current_desktop.paneTabs() + # panetabs = hou.ui.paneTabs() + # if panetabs: + # try: + # self.processdesktop("current_desktop.paneTabs()", panetabsd) + # self.processdesktop("hou.ui.paneTabs()", panetabs) # ------ Good one + # except: + # pass + # floating = hou.ui.floatingPanels() + # if floating: + # try: + # self.processdesktop("current_desktop.floatingPanels()", floating) + # print(floating.name()) + # except: + # pass + # desktoppane = current_desktop.paneUnderCursor() + # if desktoppane: + # try: + # self.processdesktop("current_desktop.paneUnderCursor()", desktoppane) + # except: + # pass + # desktoptab = current_desktop.paneTabUnderCursor() + # if desktoptab: + # try: + # self.processdesktop("current_desktop.paneTabUnderCursor()", desktoptab) + # except: + # pass + + allWidgets = QtWidgets.QApplication.allWidgets() + for w in allWidgets: + if "playbar" in w.windowTitle(): + print("Is Playbar? ", w.windowTitle(), w) \ No newline at end of file diff --git a/python3.7libs/searcher/.extra/session.py b/python3.7libs/searcher/.extra/session.py new file mode 100644 index 0000000..949cca5 --- /dev/null +++ b/python3.7libs/searcher/.extra/session.py @@ -0,0 +1,111 @@ + + +import os +import time + +# attempt to import hou module. if it fails, not in a houdini session. +try: + import hou +except ImportError: + HOU_IMPORTED = False +else: + HOU_IMPORTED = True + +# ----------------------------------------------------------------------------- +# attempt to import hou ui module. if it fails, not in the UI +try: + from PySide import QtCore, QtGui +except: + HOU_UI_IMPORTED = False +else: + HOU_UI_IMPORTED = True + +from dpa.app.session import RemoteMixin, Session, SessionRegistry, SessionError + +# ----------------------------------------------------------------------------- +class HoudiniSession(RemoteMixin, Session): + + app_name = 'houdini' + + # XXX should come from config + SERVER_EXECUTABLE = "/home/jtomlin/dev/dpa-pipe/bin/dpa_houdini_server" + + # ------------------------------------------------------------------------- + @classmethod + def current(cls): + if not HOU_IMPORTED: + return None + return cls() + + # ------------------------------------------------------------------------- + def __init__(self, filepath=None, remote=False): + + super(HoudiniSession, self).__init__(remote=remote) + + self._hou = self.init_module('hou') + + if filepath: + self.open_file(filepath) + + # ------------------------------------------------------------------------- + def close(self): + if self.remote_connection: + self.shutdown() + else: + self.hou.hipFile.clear() + + # ------------------------------------------------------------------------- + def open_file(self, filepath): + + if not os.path.exists(filepath): + raise SessionError( + "Can not open '{f}'. File does not exist.".format(f=filepath)) + + try: + self.hou.hipFile.load(filepath) + except RuntimeError as e: + raise SessionError(str(e)) + + # ------------------------------------------------------------------------- + def save(self, filepath=None, overwrite=False): + + if filepath and os.path.exists(filepath) and not overwrite: + raise SessionError( + "Can not save '{f}'. File exists.".format(f=filepath)) + + self.hou.hipFile.save(file_name=filepath) + + # ------------------------------------------------------------------------- + @property + def hou(self): + return self._hou + + # ------------------------------------------------------------------------- + @property + def in_session(self): + """Returns True if inside a current app session.""" + return HOU_IMPORTED or self.remote_connection + + # ------------------------------------------------------------------------- + @property + def main_window(self): + + if not HOU_UI_IMPORTED: + return None + + return QtGui.QApplication.activeWindow() + + # ------------------------------------------------------------------------- + @property + def name(self): + """Returns the name of the application.""" + return "houdini" + + # ------------------------------------------------------------------------- + @property + def server_executable(self): + return self.__class__.SERVER_EXECUTABLE + + +# ----------------------------------------------------------------------------- +SessionRegistry().register(HoudiniSession) diff --git a/python3.7libs/searcher/.extra/shelf.py b/python3.7libs/searcher/.extra/shelf.py new file mode 100644 index 0000000..e5a4406 --- /dev/null +++ b/python3.7libs/searcher/.extra/shelf.py @@ -0,0 +1,55 @@ +import hou + + +def create_shelf_current_desktop(shelf_obj): + # Add the shelf to the current desktop. + desktop = hou.ui.curDesktop() + dock = desktop.shelfDock() + shelfSets = dock.shelfSets() + shelfSet = shelfSets[0] + if shelf_obj not in shelfSet.shelves(): + shelfSet.setShelves(shelfSet.shelves() + (shelf_obj, )) + return shelf_obj + +def is_shelf_created(shelf_name, shelf_tab="shelf_set_1"): + try: + shelf_set = hou.shelves.shelfSets()[shelf_tab] + except KeyError: + print("Key not Found! for shelf.") + return False + return shelf_name in shelf_set.shelves() + +def create_shelf_under_tab(shelf_name, shelf_tab="shelf_set_1"): + shelves = hou.shelves.shelves() + _shelf = shelves.get(shelf_name) + if not _shelf: + _shelf = hou.shelves.newShelf(name=shelf_name, label=shelf_name) + try: + shelf_set = hou.shelves.shelfSets()[shelf_tab] + except KeyError: + print("Key not Found! for shelf.") + return 0 + shelf_set.setShelves(shelf_set.shelves() + (_shelf, )) + return _shelf + +def create_tool_under_shelf(shelf_obj, tool_name): + # Clear the existing tools + shelf_obj.setTools(()) + + tools = hou.shelves.tools() + tool = tools.get(tool_name) + if not tool: + tool = hou.shelves.newTool(name=tool_name) + + # Set up the tool. + tool.setLabel(tool_name) + # tool.setScript('from houtools.shelf import dispatch; dispatch(%r)' % spec['entrypoint']) + shelf_obj.setTools(shelf_obj.tools() + (tool, )) + +def run_shelf_creation(): + print("Trying to create the shelf.") + if is_shelf_created("BpCustom"): + print("Not running shelf creation as its present.") + return 1 + shelf_obj = create_shelf_under_tab("BpCustom") + create_tool_under_shelf(shelf_obj, "BpTool1") \ No newline at end of file diff --git a/python3.7libs/searcher/.vscode/settings.json b/python3.7libs/searcher/.vscode/settings.json new file mode 100644 index 0000000..e657cfe --- /dev/null +++ b/python3.7libs/searcher/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "python.pythonPath": "C:\\Python27\\python.exe", + "python.formatting.provider": "autopep8", + "python.linting.pylintEnabled": false, + "python.linting.flake8Enabled": true, + "python.linting.enabled": true, + "cSpell.words": [ + "gocommandtext", + "updatetmphk", + "updatetmphotkey" + ] +} \ No newline at end of file diff --git a/python3.7libs/searcher/HelpButton.py b/python3.7libs/searcher/HelpButton.py new file mode 100644 index 0000000..0e8151a --- /dev/null +++ b/python3.7libs/searcher/HelpButton.py @@ -0,0 +1,61 @@ +from __future__ import print_function +from __future__ import absolute_import +from searcher import util + +import hou +import os + +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtCore + from qtpy import QtWidgets + + +# ---------------------------------------------------- Help +# NOTE Help ----------------------------------------------- +class HelpButton(QtWidgets.QToolButton): + """Generic Help button.""" + + def __init__(self, name, tooltip, size, searcher, parent=None): + super(HelpButton, self).__init__(parent=parent) + + self.parentWindow = searcher + self._name = name + self.setToolTip(tooltip) + self.clicked.connect(self.display_help) + help_button_size = hou.ui.scaledSize(size) + self.setProperty("flat", True) + self.setIcon(hou.qt.createIcon(util.get_path(["images", "help1.png"]))) + self.setIconSize(QtCore.QSize( + help_button_size, + help_button_size + )) + + def display_help(self): + """Display help panel.""" + # Look for an existing, float help browser. + for pane_tab in hou.ui.paneTabs(): + if isinstance(pane_tab, hou.HelpBrowser): + if pane_tab.isFloating(): + browser = pane_tab + break + + # Didn't find one, so create a new floating browser. + else: + desktop = hou.ui.curDesktop() + + posx = self.parentWindow.pos().x() + posy = self.parentWindow.pos().y() + sizew = self.parentWindow.width() + sizeh = self.parentWindow.height() + + browser = desktop.createFloatingPaneTab( + hou.paneTabType.HelpBrowser, position=(posx + sizew / 8, posy - (sizeh / 2)), size=(805, 650)) + self.parentWindow.close() + + browser.displayHelpPath("/searcher/{}".format(self._name)) diff --git a/python3.7libs/searcher/__init__.py b/python3.7libs/searcher/__init__.py new file mode 100644 index 0000000..66960fc --- /dev/null +++ b/python3.7libs/searcher/__init__.py @@ -0,0 +1,7 @@ +__package__ = "searcher" +__author__ = "instance.id" +__copyright__ = "2020 All rights reserved. See LICENSE for more details." +__status__ = "Prototype" + +from . searcher import * +# from settings_data import * \ No newline at end of file diff --git a/python3.7libs/searcher/about.py b/python3.7libs/searcher/about.py new file mode 100644 index 0000000..50aff6d --- /dev/null +++ b/python3.7libs/searcher/about.py @@ -0,0 +1,115 @@ +from __future__ import absolute_import +from searcher import about_ui +from searcher import util +import os +import hou + +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtGui + from qtpy import QtCore + from qtpy import QtWidgets + +scriptpath = os.path.dirname(os.path.realpath(__file__)) + + +# noinspection PyCallByClass,PyUnresolvedReferences +class About(QtWidgets.QWidget): + """ Searcher Settings and Debug Menu""" + + def __init__(self, parent=None): + super(About, self).__init__(parent=parent) + self.setParent(parent) + self.parentwindow = parent + self.ui = about_ui.Ui_About() + self.ui.setupUi(self) + self.ui.retranslateUi(self) + + self.ui.web_icon.setIcon(hou.qt.createIcon( + util.get_path(["images", "icons", "firefox-browser-brands.svg"]))) + self.ui.web_icon.clicked.connect(self.openWeb) + web_icon_size = hou.ui.scaledSize(16) + self.ui.web_icon.setProperty("flat", True) + self.ui.web_icon.setIconSize(QtCore.QSize( + web_icon_size, + web_icon_size + )) + + self.ui.github_icon.setIcon(hou.qt.createIcon( + util.get_path(["images", "icons", "github-brands.svg"]))) + self.ui.github_icon.clicked.connect(self.openGithub) + github_icon_size = hou.ui.scaledSize(16) + self.ui.github_icon.setProperty("flat", True) + self.ui.github_icon.setIconSize(QtCore.QSize( + github_icon_size, + github_icon_size + )) + + self.ui.twitter_icon.setIcon(hou.qt.createIcon( + util.get_path(["images", "icons", "twitter-brands.svg"]))) + self.ui.twitter_icon.clicked.connect(self.openTwitter) + twitter_icon_size = hou.ui.scaledSize(16) + self.ui.twitter_icon.setProperty("flat", True) + self.ui.twitter_icon.setIconSize(QtCore.QSize( + twitter_icon_size, + twitter_icon_size + )) + + self.ui.email_icon.setIcon(hou.qt.createIcon( + util.get_path(["images", "icons", "at-solid.svg"]))) + self.ui.email_icon.clicked.connect(self.openEmail) + email_icon_size = hou.ui.scaledSize(16) + self.ui.email_icon.setProperty("flat", True) + self.ui.email_icon.setIconSize(QtCore.QSize( + email_icon_size, + email_icon_size + )) + + self.ui.web.mousePressEvent = self.openWeb + self.ui.github.mousePressEvent = self.openGithub + self.ui.twitter.mousePressEvent = self.openTwitter + self.ui.email.mousePressEvent = self.openEmail + + self.installEventFilter(self) + + def initmenu(self): + return + + def openWeb(self, _): + weburl = '''https://instance.id/''' + QtGui.QDesktopServices.openUrl(QtCore.QUrl(weburl)) + self.parentwindow.parentwindow.close() + + def openGithub(self, _): + ghurl = '''https://github.com/instance-id/''' + QtGui.QDesktopServices.openUrl(QtCore.QUrl(ghurl)) + self.parentwindow.parentwindow.close() + + def openTwitter(self, _): + twitterurl = '''https://twitter.com/instance_id''' + QtGui.QDesktopServices.openUrl(QtCore.QUrl(twitterurl)) + self.parentwindow.parentwindow.close() + + def openEmail(self, _): + email = '''mailto:support@instance.id''' + QtGui.QDesktopServices.openUrl(QtCore.QUrl(email)) + self.parentwindow.parentwindow.close() + + # ------------------------------------------------------------- Events + # SECTION Events ----------------------------------------------------- + def eventFilter(self, obj, event): + event_type = event.type() + + # ---------------------------------------- Keypress + # NOTE Keypress ----------------------------------- + if event_type == QtCore.QEvent.KeyPress: + if event.key() == QtCore.Qt.Key_Escape: + self.parentwindow.closeroutine() + + return QtCore.QObject.eventFilter(self, obj, event) diff --git a/python3.7libs/searcher/about_ui.py b/python3.7libs/searcher/about_ui.py new file mode 100644 index 0000000..9263ac3 --- /dev/null +++ b/python3.7libs/searcher/about_ui.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +import os +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtGui + from qtpy import QtCore + from qtpy import QtWidgets + +scriptpath = os.path.dirname(os.path.realpath(__file__)) + + +# noinspection PyAttributeOutsideInit,DuplicatedCode,PyPep8Naming +class Ui_About(object): + def setupUi(self, About): + About.setObjectName("About") + About.setWindowModality(QtCore.Qt.NonModal) + About.resize(185, 251) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(About.sizePolicy().hasHeightForWidth()) + About.setSizePolicy(sizePolicy) + About.setMinimumSize(QtCore.QSize(100, 0)) + About.setBaseSize(QtCore.QSize(0, 0)) + About.setStyleSheet("") + + # ------------------------------------------------- gridsetup + # NOTE gridsetup -------------------------------------------- + self.gridLayout = QtWidgets.QGridLayout(About) + self.gridLayout.setContentsMargins(-1, -1, -1, 6) + self.gridLayout.setSpacing(6) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout_4 = QtWidgets.QVBoxLayout() + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem) + + # ------------------------------------------------- secondrow + # NOTE Second Row ------------------------------------------- + self.secondrow = QtWidgets.QHBoxLayout() + self.secondrow.setObjectName("secondrow") + self.web_icon = QtWidgets.QToolButton(About) + self.web_icon.setObjectName("web_icon") + self.web = QtWidgets.QLabel(About) + self.web.setObjectName("web") + self.secondrow.addWidget(self.web_icon) + self.secondrow.addWidget(self.web) + self.verticalLayout.addLayout(self.secondrow) + + # -------------------------------------------------- thirdrow + # NOTE Third Row -------------------------------------------- + self.thirdrow = QtWidgets.QHBoxLayout() + self.thirdrow.setObjectName("thirdrow") + self.github_icon = QtWidgets.QToolButton(About) + self.github_icon.setObjectName("github_icon") + self.github = QtWidgets.QLabel(About) + self.github.setObjectName("github") + self.thirdrow.addWidget(self.github_icon) + self.thirdrow.addWidget(self.github) + self.verticalLayout.addLayout(self.thirdrow) + + # ------------------------------------------------- fourthrow + # NOTE fourthrow -------------------------------------------- + self.fourthrow = QtWidgets.QHBoxLayout() + self.fourthrow.setObjectName("fourthrow") + self.twitter_icon = QtWidgets.QToolButton(About) + self.twitter_icon.setObjectName("twitter_icon") + self.twitter = QtWidgets.QLabel(About) + self.twitter.setObjectName("twitter") + self.fourthrow.addWidget(self.twitter_icon) + self.fourthrow.addWidget(self.twitter) + self.verticalLayout.addLayout(self.fourthrow) + + # ------------------------------------------------- fifthrow + # NOTE fifthrow -------------------------------------------- + self.fifthrow = QtWidgets.QHBoxLayout() + self.fifthrow.setObjectName("fifthrow") + self.email_icon = QtWidgets.QToolButton(About) + self.email_icon.setObjectName("email_icon") + self.email = QtWidgets.QLabel(About) + self.email.setObjectName("email") + self.fifthrow.addWidget(self.email_icon) + self.fifthrow.addWidget(self.email) + self.verticalLayout.addLayout(self.fifthrow) + + # ----------------------------------------------- columnsetup + # NOTE columnsetup ------------------------------------------ + self.horizontalLayout.addLayout(self.verticalLayout) + self.verticalLayout_4.addLayout(self.horizontalLayout) + self.gridLayout.addLayout(self.verticalLayout_4, 0, 0, 1, 1) + + # ----------------------------------------------------- image + # NOTE image --- -------------------------------------------- + self.logo = QtWidgets.QLabel(About) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.logo.sizePolicy().hasHeightForWidth()) + self.logo.setSizePolicy(sizePolicy) + self.logo.setMaximumSize(QtCore.QSize(120, 120)) + self.logo.setText("") + self.logo.setPixmap(QtGui.QPixmap(scriptpath + "/images/logo.png")) + self.logo.setScaledContents(True) + self.logo.setObjectName("logo") + self.gridLayout.addWidget(self.logo, 0, 1, 1, 1) + + self.retranslateUi(About) + QtCore.QMetaObject.connectSlotsByName(About) + + def retranslateUi(self, About): + _translate = QtCore.QCoreApplication.translate + About.setWindowTitle(_translate("About", "Form")) + self.web.setText(_translate("About", 'website')) + self.github.setText(_translate("About", 'github')) + self.twitter.setText(_translate("About", 'twitter')) + self.email.setText(_translate("About", 'email')) + +# class LinkLabel(QtWidgets.QLabel): +# def __init__(self, parent, text): +# super(LinkLabel, self).__init__(parent) + +# self.setText(text) +# self.setTextFormat(QtCore.Qt.RichText) +# self.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction) +# self.setOpenExternalLinks(True) \ No newline at end of file diff --git a/python3.7libs/searcher/animator.py b/python3.7libs/searcher/animator.py new file mode 100644 index 0000000..79f1b09 --- /dev/null +++ b/python3.7libs/searcher/animator.py @@ -0,0 +1,58 @@ +from hutil.Qt import QtCore, QtGui, QtWidgets + + +class Animator(QtWidgets.QWidget): + def __init__(self, parent=None, close_cb=None, animationDuration=200): + super(Animator, self).__init__(parent) + + self.animationDuration = animationDuration + + self.toggleAnimation = QtCore.QParallelAnimationGroup() + if close_cb is not None: + self.toggleAnimation.finished.connect(close_cb) + + self.contentArea = QtWidgets.QScrollArea( + maximumHeight=0, minimumHeight=0, minimumWidth=500) + self.contentArea.setStyleSheet( + "QScrollArea { background-color: rgba(58 58, 58, 1); border: none;}") + self.contentArea.setSizePolicy( + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Fixed) + + toggleAnimation = self.toggleAnimation + toggleAnimation.addAnimation( + QtCore.QPropertyAnimation(self, b"minimumHeight")) + toggleAnimation.addAnimation( + QtCore.QPropertyAnimation(self, b"maximumHeight")) + toggleAnimation.addAnimation(QtCore.QPropertyAnimation( + self.contentArea, b"maximumHeight")) + + mainLayout = QtWidgets.QVBoxLayout(self) + mainLayout.setSpacing(0) + mainLayout.setContentsMargins(0, 0, 0, 0) + mainLayout.addWidget(self.contentArea) + + def start_animation(self, checked): + direction = QtCore.QAbstractAnimation.Forward if checked else QtCore.QAbstractAnimation.Backward + self.toggleAnimation.setDirection(direction) + self.toggleAnimation.start() + + def setContentLayout(self, contentLayout): + # Not sure if this is equivalent to self.contentArea.destroy() + lay = self.contentArea.layout() + del lay + self.contentArea.setLayout(contentLayout) + collapsedHeight = self.sizeHint().height() - self.contentArea.maximumHeight() + + contentHeight = contentLayout.sizeHint().height() + for i in range(self.toggleAnimation.animationCount()-1): + expandAnimation = self.toggleAnimation.animationAt(i) + expandAnimation.setDuration(self.animationDuration) + expandAnimation.setStartValue(collapsedHeight) + expandAnimation.setEndValue(collapsedHeight + contentHeight) + + contentAnimation = self.toggleAnimation.animationAt( + self.toggleAnimation.animationCount() - 1) + contentAnimation.setDuration(self.animationDuration) + contentAnimation.setStartValue(0) + contentAnimation.setEndValue(contentHeight) diff --git a/python3.7libs/searcher/bugreport.py b/python3.7libs/searcher/bugreport.py new file mode 100644 index 0000000..91afd0e --- /dev/null +++ b/python3.7libs/searcher/bugreport.py @@ -0,0 +1,102 @@ +from __future__ import absolute_import + +from hutil.py23 import reload + +from searcher import bugreport_ui +import os + +import hou + +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.') + 1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets + +try: + pyside = os.environ['HOUDINI_QT_PREFERRED_BINDING'] + parent = hou.qt.mainWindow() +except KeyError: + parent = hou.ui.mainQtWindow() + pyside = 'PySide' + +if pyside == 'PySide2': + # noinspection PyUnresolvedReferences + from PySide2 import QtWebEngineWidgets + +elif pyside == 'PySide': + # noinspection PyUnresolvedReferences + from PySide.QtWebKit import QWebView + +reload(bugreport_ui) + +scriptpath = os.path.dirname(os.path.realpath(__file__)) + + +def submittypeswitch(argument): + switcher = { + 0: "assignees=&labels=bug&template=bug_report.md&title=", + 1: "assignees=&labels=enhancement&template=feature_request.md&title=", + 2: "assignees=&labels=&template=general-question.md&title=", + } + return switcher.get(argument, "nothing") + + +class BugReport(QtWidgets.QWidget): + """ Searcher Settings and Debug Menu""" + + def __init__(self, parent=None): + super(BugReport, self).__init__(parent=parent) + self.priortext = "" + self.isediting = True + self.setParent(parent) + self.parentwindow = parent + self.ui = bugreport_ui.Ui_BugReport() + self.ui.setupUi(self) + self.ui.retranslateUi(self) + self._webview = None + self.installEventFilter(self) + self.ui.title.installEventFilter(self) + + def initmenu(self): + self.resize(self.width(), self.parentwindow.height() - 300) + self._webview = None + self.ui.title.setText("") + self.ui.edittitle_btn.pressed.connect(self.doweb) + + self.ui.title.setFocus() + + def doweb(self): + if self.ui.title.text() == "": + self.parentwindow.parentwindow.setstatusmsg("Please enter a title for your bug report", "ImportantMessage") + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + "Please enter a title for your bug report.", severity=hou.severityType.Warning) + return + + submittype = submittypeswitch(self.ui.label_cbox.currentIndex()) + reporturl = '''https://github.com/instance-id/searcher_addon/issues/new?%s%s''' % (submittype, self.ui.title.text()) + + QtGui.QDesktopServices.openUrl(QtCore.QUrl(reporturl)) + self.parentwindow.parentwindow.close() + + # ------------------------------------------------------------- Events + # SECTION Events ----------------------------------------------------- + def eventFilter(self, obj, event): + event_type = event.type() + + # ---------------------------------------- Keypress + # NOTE Keypress ----------------------------------- + if event_type == QtCore.QEvent.KeyPress: + self.priortext = self.ui.title.text() + if event.key() == QtCore.Qt.Key_Escape: + self.parentwindow.closeroutine() + return True + + if event_type == QtCore.QEvent.Close: + self._webview = None + self.isediting = True + + return QtCore.QObject.eventFilter(self, obj, event) diff --git a/python3.7libs/searcher/bugreport_ui.py b/python3.7libs/searcher/bugreport_ui.py new file mode 100644 index 0000000..c2ec21a --- /dev/null +++ b/python3.7libs/searcher/bugreport_ui.py @@ -0,0 +1,69 @@ +from hutil.Qt import QtCore, QtGui, QtWidgets +import os + +scriptpath = os.path.dirname(os.path.realpath(__file__)) + + +class Ui_BugReport(object): + def setupUi(self, BugReport): + BugReport.setObjectName("BugReport") + BugReport.setWindowModality(QtCore.Qt.NonModal) + BugReport.resize(450, 20) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(BugReport.sizePolicy().hasHeightForWidth()) + BugReport.setSizePolicy(sizePolicy) + BugReport.setMinimumSize(QtCore.QSize(25, 0)) + BugReport.setBaseSize(QtCore.QSize(0, 0)) + BugReport.setContentsMargins(-1, -1, -1,-1) + BugReport.setStyleSheet("") + self.gridLayout = QtWidgets.QGridLayout(BugReport) + self.gridLayout.setContentsMargins(-1, -1, -1, -1) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout_4 = QtWidgets.QVBoxLayout() + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.secondrow = QtWidgets.QHBoxLayout() + self.secondrow.setObjectName("secondrow") + self.title = QtWidgets.QLineEdit(BugReport) + self.title.setMinimumSize(QtCore.QSize(175, 0)) + self.title.setObjectName("title") + self.secondrow.addWidget(self.title) + self.verticalLayout_4.addLayout(self.secondrow) + self.thirdrow = QtWidgets.QHBoxLayout() + self.thirdrow.setObjectName("thirdrow") + spacerItem1 = QtWidgets.QSpacerItem(40, 25, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.thirdrow.addItem(spacerItem1) + self.label_cbox = QtWidgets.QComboBox(BugReport) + self.label_cbox.setObjectName("label_cbox") + self.label_cbox.setLayoutDirection(QtCore.Qt.LeftToRight) + self.label_cbox.setMaximumSize(QtCore.QSize(100, 25)) + self.label_cbox.addItem("Bug") + self.label_cbox.addItem("Suggestion") + self.label_cbox.addItem("Question") + self.thirdrow.addWidget(self.label_cbox) + spacerItem1 = QtWidgets.QSpacerItem(5, 30, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.thirdrow.addItem(spacerItem1) + self.edittitle_btn = QtWidgets.QPushButton(BugReport) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.edittitle_btn.sizePolicy().hasHeightForWidth()) + self.edittitle_btn.setSizePolicy(sizePolicy) + self.edittitle_btn.setMaximumSize(QtCore.QSize(75, 16777215)) + self.edittitle_btn.setObjectName("edittitle") + self.thirdrow.addWidget(self.edittitle_btn) + + self.verticalLayout_4.addLayout(self.thirdrow) + self.gridLayout.addLayout(self.verticalLayout_4, 0, 0, 1, 1) + + self.retranslateUi(BugReport) + QtCore.QMetaObject.connectSlotsByName(BugReport) + + def retranslateUi(self, BugReport): + _translate = QtCore.QCoreApplication.translate + BugReport.setWindowTitle(_translate("BugReport", "Form")) + self.edittitle_btn.setText(_translate("BugReport", "Create")) + self.title.setPlaceholderText(_translate("BugReport", "Please enter descriptive bug report title:")) + # self.continue_btn.setText(_translate("BugReport", "Continue")) diff --git a/python3.7libs/searcher/colorfieldselector.py b/python3.7libs/searcher/colorfieldselector.py new file mode 100644 index 0000000..8a14c10 --- /dev/null +++ b/python3.7libs/searcher/colorfieldselector.py @@ -0,0 +1,121 @@ +import hou + +from hutil.Qt import QtCore +from hutil.Qt import QtGui +from hutil.Qt import QtWidgets + +_MIN_RGB_VALUE = 0 +_MAX_RGB_VALUE = 255 + +class ColorFieldSelector(QtWidgets.QWidget): + """ +hou.qt.ColorField + +A widget for color input. + +The widget contains a color swatch button and an input field for RGBA +values. + +This class inherits from Qt's QtWidgets.QWidget class. + +""" + def __init__(self, label="", include_alpha=False): + """ +__init__(self, label=\"\", include_alpha=False) + + Create and return a new ColorField object. + + + label + If set to a non-empty string then a label is added to the color + field. + + include_alpha + If True, then an alpha component is added to the color field. + +""" + QtWidgets.QWidget.__init__(self) + + layout = QtWidgets.QHBoxLayout() + layout.setSpacing(hou.ui.scaledSize(2)) + layout.setContentsMargins(0, 0, 0, 0) + + self.colorSwatchButton = hou.qt.ColorSwatchButton(include_alpha) + + # Use the color swatch button's colorChanged signal as our own. + self.colorChanged = self.colorSwatchButton.colorChanged + + self.inputField = hou.qt.InputField( + hou.qt.InputField.FloatType, + 4 if include_alpha else 3) + + if label is not None and label != "": + layout.addWidget(hou.qt.FieldLabel(label)) + + layout.addWidget(self.colorSwatchButton) + layout.addSpacing(hou.ui.scaledSize(5)) + layout.addWidget(self.inputField) + + # Connect color swatch button to field so their values + # are always in-sync. + self.colorSwatchButton.colorChanged.connect( + self._updateFieldFromColorSwatch) + self.inputField.valueChanged.connect( + self._updateColorSwatchFromField) + + # Sync input field with color swatch. + self._updateFieldFromColorSwatch(self.colorSwatchButton.color()) + + self.setLayout(layout) + + def color(self): + """ +color() -> QtGui.QColor + + Return the field's current color. + +""" + return self.colorSwatchButton.color() + + def setColor(self, color): + """ +setColor(color) + + Set the field's current color. color must be a QtGui.QColor object. + +""" + self.colorSwatchButton.setColor(color) + + # Update the input field with the new color. + self._updateFieldFromColorSwatch(color) + + def _updateFieldFromColorSwatch(self, color): + if self.colorSwatchButton.hasAlpha(): + self.inputField.setValues([ + color.redF(), color.greenF(), color.blueF(), color.alphaF()]) + else: + self.inputField.setValues([ + color.redF(), color.greenF(), color.blueF()]) + + def _updateColorSwatchFromField(self): + values = list(self.inputField.values()) + + color = QtGui.QColor() + color.setRedF(self._clampRGBValue(values[0])) + color.setGreenF(self._clampRGBValue(values[1])) + color.setBlueF(self._clampRGBValue(values[2])) + + if self.colorSwatchButton.hasAlpha(): + color.setAlphaF(self._clampRGBValue(values[3])) + + self.colorSwatchButton.setColor(color) + + def _clampRGBValue(self, val): + if val > 1.0: + return 1.0 + + if val < 0.0: + return 0.0 + + return val + diff --git a/python3.7libs/searcher/database.py b/python3.7libs/searcher/database.py new file mode 100644 index 0000000..b4b306b --- /dev/null +++ b/python3.7libs/searcher/database.py @@ -0,0 +1,437 @@ +from __future__ import print_function +from __future__ import absolute_import +import weakref + +import hou +import os + +from . import util +from . import settings_data +from . import ptime as ptime + +from peewee import * +from playhouse.sqlite_ext import SqliteExtDatabase, RowIDField, FTS5Model, SearchField +import time + +# --------------------------------------------- hou.session +# NOTE hou.session ---------------------------------------- +def get_settings(): + return getattr(hou.session, "SETTINGS", None) + +def get_dbconnection(): + return getattr(hou.session, "DBCONNECTION", None) + + +scriptpath = os.path.dirname(os.path.realpath(__file__)) +db = get_dbconnection() + +# --------------------------------------------------------- DatabaseModels +# SECTION DatabaseModels ------------------------------------------------- +# ------------------------------------------------ Settings +# NOTE Settings ------------------------------------------- +class Settings(Model): + id = IntegerField(unique=True) + indexvalue = IntegerField() + defaulthotkey = TextField() + searchdescription = IntegerField() + searchprefix = IntegerField() + searchcurrentcontext = IntegerField() + lastused = TextField() + + class Meta: + table_name = 'settings' + database = db + +# ------------------------------------------------ HContext +# NOTE HContext ------------------------------------------- +class HContext(Model): + id = AutoField() + context = TextField(unique=True) + title = TextField() + description = TextField() + + class Meta: + table_name = 'hcontext' + database = db + +# # # ------------------------------------------- HContextIndex +# # # NOTE HContextIndex -------------------------------------- +# class HContextIndex(FTS5Model): +# # rowid = RowIDField() +# context = SearchField() +# title = SearchField() +# description = SearchField() + +# class Meta: +# database = db +# options = {'prefix': [2, 3], 'tokenize': 'porter'} + +# ------------------------------------------------- Hotkeys +# NOTE Hotkeys -------------------------------------------- +class Hotkeys(Model): + hotkey_symbol = CharField(unique=True) + label = CharField() + description = TextField() + assignments = TextField() + context = TextField() + + class Meta: + table_name = 'hotkeys' + database = db + +# -------------------------------------------- HotkeysIndex +# NOTE HotkeysIndex --------------------------------------- +class HotkeysIndex(FTS5Model): + # rowid = RowIDField() + hotkey_symbol = SearchField(unindexed=True) + label = SearchField() + description = SearchField() + assignments = SearchField(unindexed=True) + context = SearchField(unindexed=True) + + def clear_index(self): + HotkeysIndex.delete().where(HotkeysIndex.rowid == self.id).execute() + + class Meta: + # table_name = 'hotkeysindex' + database = db + options = {'prefix': [2, 3], 'tokenize': 'porter'} +# !SECTION + +# -------------------------------------------------------------- Functions +# SECTION Functions ------------------------------------------------------ +# ----------------------------------------------- py_unique +# NOTE py_unique ------------------------------------------ +def py_unique(data): + return list(set(data)) + +# ------------------------------------------------- getdata +# NOTE getdata -------------------------------------------- +def getdata(): + rval = [] + contextdata = [] + hotkeydata = [] + + def getcontexts(r, context_symbol, root): + keys = None + branches = hou.hotkeys.contextsInContext(context_symbol) + for branch in branches: + branch_path = "%s/%s" % (r, branch['label']) + contextdata.append( + {'context': branch['symbol'], + 'title': branch['label'], + 'description': branch['help']} + ) + commands = hou.hotkeys.commandsInContext(branch['symbol']) + for command in commands: + keys = hou.hotkeys.assignments(command['symbol']) + ctx = command['symbol'].rsplit('.', 1) + hotkeydata.append( + {'hotkey_symbol': command['symbol'], + 'label': command['label'], + 'description': command['help'], + 'assignments': " ".join(keys), + 'context': ctx[0]} + ) + getcontexts(branch_path, branch['symbol'], root) + + getcontexts("", "", rval) + return contextdata, hotkeydata +# !SECTION + +# ----------------------------------------------------------- Database +# SECTION Database --------------------------------------------------- +class Databases(object): + def __init__(self): + + self.settings = get_settings() + self.isdebug = util.bc(self.settings[util.SETTINGS_KEYS[4]]) + inmemory = util.bc(self.settings[util.SETTINGS_KEYS[0]]) + if inmemory: + val = ':memory:' + else: + val = (self.settings[util.SETTINGS_KEYS[1]]) + + self.db = db + if not self.db: + hou.session.DBCONNECTION = DatabaseProxy() + self.db.initialize( + SqliteExtDatabase( + val, + pragmas=( + ("cache_size", -1024 * 64), + ("journal_mode", "off"), + ("temp_store", "memory"), + ("synchronous", 0) + ))) + if inmemory or not os.path.isfile(self.settings[util.SETTINGS_KEYS[1]]): + db.create_tables([ + Settings, + HContext, + Hotkeys, + HotkeysIndex,] + ) + self.initialsetup(self.cur) + + self.cur = db.cursor() + self.isdebug = None + self.contexttime = 0 + self.hotkeystime = 0 + + # ----------------------------------------------------------- Retrieve + # SECTION Retrieve --------------------------------------------------- + # -------------------------------------- getchangeindex + # NOTE getchangeindex --------------------------------- + def getchangeindex(self): + try: + self.cur.execute("SELECT indexvalue FROM settings") + result = self.cur.fetchall() + return result + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not get Searcher changeindex: " + str(e)), severity=hou.severityType.Error) + + # ------------------------------------------- getlastusedhk + # NOTE getlastusedhk -------------------------------------- + def getlastusedhk(self): + try: + lastkey = self.settings[util.SETTINGS_KEYS[11]] + if str(lastkey) != "": + lasthk = str(lastkey).split(' ') + hkcheck = hou.hotkeys.assignments(str(lasthk[0])) + + if len(hkcheck) is 0: + self.settings[util.SETTINGS_KEYS[11]] = "" + settings_data.savesettings(settingdata) + return + + rmresult = hou.hotkeys.removeAssignment( + str(lasthk[0]).strip(), str(lasthk[1]).strip()) + if rmresult: + hkcheck = hou.hotkeys.assignments(str(lasthk[0])) + hou.hotkeys.saveOverrides() + if len(hkcheck) is 0: + self.settings[util.SETTINGS_KEYS[11]] = "" + settings_data.savesettings(settingdata) + self.updatechangeindex(int(currentidx)) + else: + hou.hotkeys.clearAssignments(str(lasthk[0])) + hou.hotkeys.saveOverrides() + hkcheck = hou.hotkeys.assignments(str(lasthk[0])) + if len(hkcheck) is 0: + self.settings[util.SETTINGS_KEYS[11]] = "" + settings_data.savesettings(settingdata) + self.updatechangeindex(int(currentidx)) + else: + if hou.isUIAvailable(): + hou.ui.setStatusMessage(("Could not clear last assigned temp hotkey on last attempt:"), severity=hou.severityType.Warning) + else: + print("Could not clear last assigned temp hotkey on last attempt:") + else: + if hou.isUIAvailable(): + hou.ui.setStatusMessage(("Could not clear last assigned temp hotkey:"), severity=hou.severityType.Warning) + else: + print("Could not clear last assigned temp hotkey:") + + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage(("Could not query last assigned temp hotkey:" + str(e)), severity=hou.severityType.Warning) + else: + print("Could not query last assigned temp hotkey: " + str(e)) + + # -------------------------------------------- getdefhotkey + # NOTE getdefhotkey --------------------------------------- + def getdefhotkey(self): + try: + self.cur.execute("SELECT defaulthotkey FROM settings") + result = self.cur.fetchall() + return result + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not get Searcher default hotkey: " + str(e)), severity=hou.severityType.Error) + + # -------------------------------------------- gethcontexts + # NOTE gethcontexts --------------------------------------- + def gethcontexts(self): + try: + self.cur.execute("SELECT * FROM hcontext") + result = self.cur.fetchall() + return result + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not get Searcher hcontext: " + str(e)), severity=hou.severityType.Error) + + # ------------------------------------------- gethcontextod + # NOTE gethcontextod -------------------------------------- + def gethcontextod(self, inputlist): + try: + time1 = ptime.time() + result = [] + query = (HContext + .select() + .where(HContext.context.in_(inputlist))).execute() + for hctx in query: + result.append((hctx.title, hctx.description, hctx.context)) + uniqueresult = py_unique(result) + time2 = ptime.time() + self.contexttime = ((time2 - time1) * 1000.0) + return uniqueresult, self.contexttime + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not update Searcher context database: " + str(e)), severity=hou.severityType.Error) + + # ---------------------------------------- ctxfilterresults + # NOTE ctxfilterresults ----------------------------------- + def ctxfilterresults(self, inputTerm): + try: + result = [] + query = (Hotkeys + .select() + .where(Hotkeys.context.in_(inputTerm))).execute() + for hctx in query: + result.append((hctx.label, hctx.description, hctx.assignments, hctx.hotkey_symbol, hctx.context)) + uniqueresult = py_unique(result) + return uniqueresult + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not get Searcher context results: " + str(e)), severity=hou.severityType.Error) + + # ------------------------------------------- searchresults + # NOTE searchresults -------------------------------------- + def searchresults(self, inputTerm, debug, limit=0): + self.isdebug = debug + try: + time1 = ptime.time() + self.cur.execute( + "SELECT label, description, assignments, hotkey_symbol, context FROM hotkeysindex WHERE hotkeysindex MATCH '" + + str(inputTerm) + + "' ORDER BY rank" + + " LIMIT " + + str(limit) + ) + result = self.cur.fetchall() + uniqueresult = py_unique(result) + + time2 = ptime.time() + self.hotkeystime = ((time2 - time1) * 1000.0) + + return uniqueresult, self.hotkeystime + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not get Searcher results: " + str(e)), severity=hou.severityType.Error) + # !SECTION + + # ------------------------------------------------------------ Updates + # SECTION Updates ---------------------------------------------------- + # --------------------------------------- updatechangeindex + # NOTE updatechangeindex ---------------------------------- + def updatechangeindex(self, indexval, new=False): + try: + if new is True: + defaultkey = "" + for i in range(len(util.HOTKEYLIST)): + result = hou.hotkeys.findConflicts("h", util.HOTKEYLIST[i]) + if not result: + defaultkey = util.HOTKEYLIST[i] + + Settings.insert(indexvalue=indexval, + defaulthotkey=defaultkey, searchdescription=0, searchprefix=0, searchcurrentcontext=0, lastused="", id=1).execute() + else: + Settings.update(indexvalue=indexval).where( + Settings.id == 1).execute() + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + ("Could not update Searcher context database: " + str(e)), + severity=hou.severityType.Warning + ) + else: + print("Could not update Searcher context database: " + str(e)) + + # --------------------------------------------- updatetmphk + # NOTE updatetmphk ---------------------------------------- + def updatetmphk(self, tmpkey): + try: + _ = Settings.update( + defaulthotkey=tmpkey).where(id == 1).execute() + return + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not update Searcher temp hotkey: " + str(e)), severity=hou.severityType.Error) + + # ------------------------------------------- updatelastkey + # NOTE updatelastkey -------------------------------------- + def updatelastkey(self, lastkey): + try: + _ = Settings.update(lastused=lastkey).where(id == 1).execute() + return + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not update Searcher temp hotkey: " + str(e)), severity=hou.severityType.Error) + + # ------------------------------------------- updatecontext + # NOTE updatecontext -------------------------------------- + def updatecontext(self, debug): + self.isdebug = debug + try: + time1 = ptime.time() + self.cleardatabase() + ctxdata, hkeydata = getdata() + with db.atomic(): + for data_dict in ctxdata: + HContext.replace_many(data_dict).execute() + with db.atomic(): + for idx in hkeydata: + Hotkeys.replace_many(idx).execute() + HotkeysIndex.replace_many(idx).execute() + time2 = ptime.time() + if self.isdebug and self.isdebug.level in {"TIMER", "ALL"}: + res = ((time2 - time1) * 1000.0) + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + ('DB update took %0.4f ms' % res), severity=hou.severityType.Message) + else: + print('DB update took %0.4f ms' % res) + return res + + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not update Searcher context database: " + str(e)), severity=hou.severityType.Error) + # !SECTION + + # ------------------------------------------- cleardatabase + # NOTE cleardatabase -------------------------------------- + def cleardatabase(self): + try: + delhk = "DELETE FROM hotkeys" + delctx = "DELETE FROM hcontext" + delhkindex = "DELETE FROM hotkeysindex" + # delhcindex = "DELETE FROM hcontextindex" + self.cur.execute(delhk) + self.cur.execute(delctx) + self.cur.execute(delhkindex) + result = self.cur.fetchall() + + return result + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage(("Could not update Searcher temp hotkey: " + str(e)),severity=hou.severityType.Error) + + # -------------------------------------------- initialsetup + # NOTE initialsetup --------------------------------------- + def initialsetup(self): + currentidx = hou.hotkeys.changeIndex() + chindex = self.getchangeindex() + + if len(chindex) == 0: + chindex = int(currentidx) + self.updatechangeindex(chindex, True) + self.updatecontext(self.isdebug) + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + "Searcher database created", severity=hou.severityType.Message) + else: + print("Searcher database created") + else: + chindex = int(chindex[0][0]) + + if int(currentidx) != chindex: + self.getlastusedhk() + self.updatecontext() + self.updatechangeindex(int(currentidx)) + + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + "Searcher database created and populated", severity=hou.severityType.Message) + # !SECTION +# !SECTION \ No newline at end of file diff --git a/python3.7libs/searcher/datahandler.py b/python3.7libs/searcher/datahandler.py new file mode 100644 index 0000000..6658a9f --- /dev/null +++ b/python3.7libs/searcher/datahandler.py @@ -0,0 +1,121 @@ +from __future__ import print_function +from __future__ import absolute_import + +import hou +import os + +from hutil.py23 import reload + +from searcher import util +from searcher import settings_data +from searcher import ptime as ptime +from searcher import database + +import os +import threading +import hdefereval as hd + +reload(database) + +def get_db(): + return getattr(hou.session, "DATABASE", None) + +def worker(): + hd.executeInMainThreadWithResult(DataHandler().updatedata) + + +class DataHandler(object): + """Searcher data and communication handler""" + + def __init__(self, debug=None): + self.db = get_db() + if not self.db: + hou.session.DATABASE = database.Databases() + self.db = get_db() + + self.isdebug = debug + self.scriptpath = os.path.dirname(os.path.realpath(__file__)) + + # ----------------------------------------------------------- Retrieve + # SECTION Retrieve --------------------------------------------------- + # -------------------------------------- getchangeindex + # NOTE getchangeindex --------------------------------- + def getchangeindex(self): + index = self.db.getchangeindex() + return index + + # ------------------------------------ getdefaulthotkey + # NOTE getdefaulthotkey ------------------------------- + def getdefaulthotkey(self): + index = self.db.getdefhotkey() + return index + + # ----------------------------------------- gethcontext + # NOTE gethcontext ------------------------------------ + # @staticmethod + def gethcontext(self): + results = self.db.gethcontexts() + return results + + # --------------------------------------- gethcontextod + # NOTE gethcontextod ---------------------------------- + def gethcontextod(self, inputtext): + results, timer = self.db.gethcontextod(inputtext) + return results, timer + + # ------------------------------------------- searchctx + # NOTE searchctx -------------------------------------- + def searchctx(self, txt): + results = self.db.ctxfilterresults(txt) + return results + + # ------------------------------------------ searchtext + # NOTE searchtext ------------------------------------- + def searchtext(self, txt, debug, limit=0): + self.isdebug = debug + results, timer = self.db.searchresults(txt, self.isdebug, limit) + return results, timer + + # !SECTION Retrieve + + # ------------------------------------------------------------- Update + # SECTION Update ----------------------------------------------------- + # ----------------------------------- updatechangeindex + # NOTE updatechangeindex ------------------------------ + def updatechangeindex(self, indexval, new=False): + self.db.updatechangeindex(indexval, new) + return + + # ------------------------------------- updatedataasync + # NOTE updatedataasync -------------------------------- + def updatedataasync(self, debug): + self.isdebug = debug + thread = threading.Thread(target=worker) + thread.daemon = True + thread.start() + + # ------------------------------------------ updatedata + # NOTE updatedata ------------------------------------- + def updatedata(self): + self.db.updatecontext(self.isdebug) + return + + # ------------------------------------- updatetmphotkey + # NOTE updatetmphotkey -------------------------------- + def updatetmphotkey(self, tmpkey): + self.db.updatetmphk(tmpkey) + return + + # ---------------------------------------- updatelasthk + # NOTE updatelasthk ----------------------------------- + def updatelasthk(self, lastkey): + self.db.updatelastkey(lastkey) + return + + # !SECTION Update + + # --------------------------------------------- cleardb + # NOTE cleardb ---------------------------------------- + def cleardb(self): + results = self.db.cleardatabase() + return results \ No newline at end of file diff --git a/python3.7libs/searcher/debugutils.py b/python3.7libs/searcher/debugutils.py new file mode 100644 index 0000000..a5bab8a --- /dev/null +++ b/python3.7libs/searcher/debugutils.py @@ -0,0 +1,48 @@ +from __future__ import print_function +from __future__ import division + +from builtins import range +from past.utils import old_div +from hutil.Qt import QtCore +from hutil.Qt import QtGui +from hutil.Qt import QtWidgets + + +def dumpWidgetLayout(widget, prefix=''): + """ Debug utility to print out tree of widgets with relevant layout + properties + """ + text = "" + if not isinstance(widget, QtWidgets.QWidget) \ + and not isinstance(widget, QtWidgets.QDialog): + return + + text += str((prefix, "* name:", str(widget.objectName()))) + text += str((prefix, " visible:", str(widget.isVisible()))) + text += str((prefix, " minimumSize:", str(widget.minimumSize()))) + text += str((prefix, " minimumSizeHint:", str(widget.minimumSizeHint()))) + text += str((prefix, " sizeHint:", str(widget.sizeHint()))) + text += str((prefix, " contentsMargins:", str(widget.contentsMargins()))) + text += str((prefix, " sizePolicy:", str(widget.sizePolicy()))) + if widget.layout(): + layout = widget.layout() + text += str((prefix, " layout.minimumSize:", str(widget.layout().minimumSize()))) + text += str((prefix, " layout.sizeHint:", str(widget.layout().sizeHint()))) + text += str((prefix, " layout.contentsMargins:", str(widget.layout().contentsMargins()))) + for i in range(0, layout.count()): + item = layout.itemAt(i) + dir_flag = item.expandingDirections() + if (dir_flag & QtCore.Qt.Orientation.Horizontal): + text += str((prefix, " -> ", i, ": expand HORIZ")) + elif (dir_flag & QtCore.Qt.Orientation.Vertical): + text += str((prefix, " -> ", i, ": expand VERTICAL")) + else: + text += str((prefix, " -> ", i, ": NO expand")) + text += str((prefix, " -> ", i, ": sizeHint", str(item.sizeHint()))) + if item.widget(): + text += str((prefix, " -> ", i, ": widget.sizeHint", str(item.widget().sizeHint()))) + text += str((prefix, " numChildren:", len(widget.children()))) + for child in widget.children(): + dumpWidgetLayout(child, prefix + ' ') + + return text diff --git a/python3.7libs/searcher/enum.py b/python3.7libs/searcher/enum.py new file mode 100644 index 0000000..83d8868 --- /dev/null +++ b/python3.7libs/searcher/enum.py @@ -0,0 +1,38 @@ +# -------------------------------------------- +# http://code.activestate.com/recipes/413486/ +# -------------------------------------------- +def Enum(*names): + ##assert names, "Empty enums are not supported" # <- Don't like empty enums? Uncomment! + + class EnumClass(object): + __slots__ = names + def __iter__(self): return iter(constants) + def __len__(self): return len(constants) + def __getitem__(self, i): return constants[i] + def __repr__(self): return 'Enum' + str(names) + def __str__(self): return 'enum ' + str(constants) + + class EnumValue(object): + __slots__ = ('__value') + def __init__(self, value): self.__value = value + Value = property(lambda self: self.__value) + EnumType = property(lambda self: EnumType) + def __hash__(self): return hash(self.__value) + def __cmp__(self, other): + # C fans might want to remove the following assertion + # to make all enums comparable by ordinal value {;)) + assert self.EnumType is other.EnumType, "Only values from the same enum are comparable" + return cmp(self.__value, other.__value) + def __invert__(self): return constants[maximum - self.__value] + def __nonzero__(self): return bool(self.__value) + def __repr__(self): return str(names[self.__value]) + + maximum = len(names) - 1 + constants = [None] * len(names) + for i, each in enumerate(names): + val = EnumValue(i) + setattr(EnumClass, each, val) + constants[i] = val + constants = tuple(constants) + EnumType = EnumClass() + return EnumType \ No newline at end of file diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Bold-Italic.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Bold-Italic.ttf new file mode 100644 index 0000000..87b9bf8 Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Bold-Italic.ttf differ diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Bold.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Bold.ttf new file mode 100644 index 0000000..fd1ab3c Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Bold.ttf differ diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-ExtraBold-Italic.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-ExtraBold-Italic.ttf new file mode 100644 index 0000000..bff0884 Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-ExtraBold-Italic.ttf differ diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-ExtraBold.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-ExtraBold.ttf new file mode 100644 index 0000000..0e09b46 Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-ExtraBold.ttf differ diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Italic.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Italic.ttf new file mode 100644 index 0000000..2b6d374 Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Italic.ttf differ diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Medium-Italic.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Medium-Italic.ttf new file mode 100644 index 0000000..8f7ad12 Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Medium-Italic.ttf differ diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Medium.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Medium.ttf new file mode 100644 index 0000000..f01ae48 Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Medium.ttf differ diff --git a/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Regular.ttf b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000..dfbece6 Binary files /dev/null and b/python3.7libs/searcher/fonts/JetBrainsMono-1.0.0/JetBrainsMono-Regular.ttf differ diff --git a/python3.7libs/searcher/images/collapse_all.png b/python3.7libs/searcher/images/collapse_all.png new file mode 100644 index 0000000..3adcc10 Binary files /dev/null and b/python3.7libs/searcher/images/collapse_all.png differ diff --git a/python3.7libs/searcher/images/expand_all.png b/python3.7libs/searcher/images/expand_all.png new file mode 100644 index 0000000..eecb11a Binary files /dev/null and b/python3.7libs/searcher/images/expand_all.png differ diff --git a/python3.7libs/searcher/images/help.png b/python3.7libs/searcher/images/help.png new file mode 100644 index 0000000..a82dd24 Binary files /dev/null and b/python3.7libs/searcher/images/help.png differ diff --git a/python3.7libs/searcher/images/help1.png b/python3.7libs/searcher/images/help1.png new file mode 100644 index 0000000..7cd312e Binary files /dev/null and b/python3.7libs/searcher/images/help1.png differ diff --git a/python3.7libs/searcher/images/icon_branch_closed.png b/python3.7libs/searcher/images/icon_branch_closed.png new file mode 100644 index 0000000..fa785cc Binary files /dev/null and b/python3.7libs/searcher/images/icon_branch_closed.png differ diff --git a/python3.7libs/searcher/images/icon_branch_end.png b/python3.7libs/searcher/images/icon_branch_end.png new file mode 100644 index 0000000..d90a04c Binary files /dev/null and b/python3.7libs/searcher/images/icon_branch_end.png differ diff --git a/python3.7libs/searcher/images/icon_branch_more.png b/python3.7libs/searcher/images/icon_branch_more.png new file mode 100644 index 0000000..bdbe4ed Binary files /dev/null and b/python3.7libs/searcher/images/icon_branch_more.png differ diff --git a/python3.7libs/searcher/images/icon_branch_open.png b/python3.7libs/searcher/images/icon_branch_open.png new file mode 100644 index 0000000..9dd05d6 Binary files /dev/null and b/python3.7libs/searcher/images/icon_branch_open.png differ diff --git a/python3.7libs/searcher/images/icon_vline.png b/python3.7libs/searcher/images/icon_vline.png new file mode 100644 index 0000000..14228c8 Binary files /dev/null and b/python3.7libs/searcher/images/icon_vline.png differ diff --git a/python3.7libs/searcher/images/icons/at-solid.svg b/python3.7libs/searcher/images/icons/at-solid.svg new file mode 100644 index 0000000..8b72d6f --- /dev/null +++ b/python3.7libs/searcher/images/icons/at-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python3.7libs/searcher/images/icons/bug-solid.svg b/python3.7libs/searcher/images/icons/bug-solid.svg new file mode 100644 index 0000000..c7af707 --- /dev/null +++ b/python3.7libs/searcher/images/icons/bug-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python3.7libs/searcher/images/icons/firefox-browser-brands.svg b/python3.7libs/searcher/images/icons/firefox-browser-brands.svg new file mode 100644 index 0000000..316a13c --- /dev/null +++ b/python3.7libs/searcher/images/icons/firefox-browser-brands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python3.7libs/searcher/images/icons/github-brands.svg b/python3.7libs/searcher/images/icons/github-brands.svg new file mode 100644 index 0000000..7870c06 --- /dev/null +++ b/python3.7libs/searcher/images/icons/github-brands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python3.7libs/searcher/images/icons/twitter-brands.svg b/python3.7libs/searcher/images/icons/twitter-brands.svg new file mode 100644 index 0000000..9ac9e0b --- /dev/null +++ b/python3.7libs/searcher/images/icons/twitter-brands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python3.7libs/searcher/images/logo.png b/python3.7libs/searcher/images/logo.png new file mode 100644 index 0000000..4292cea Binary files /dev/null and b/python3.7libs/searcher/images/logo.png differ diff --git a/python3.7libs/searcher/images/resizeleft.png b/python3.7libs/searcher/images/resizeleft.png new file mode 100644 index 0000000..b3f4732 Binary files /dev/null and b/python3.7libs/searcher/images/resizeleft.png differ diff --git a/python3.7libs/searcher/images/resizeright.png b/python3.7libs/searcher/images/resizeright.png new file mode 100644 index 0000000..e984170 Binary files /dev/null and b/python3.7libs/searcher/images/resizeright.png differ diff --git a/python3.7libs/searcher/inspect.py b/python3.7libs/searcher/inspect.py new file mode 100644 index 0000000..0a6cfd7 --- /dev/null +++ b/python3.7libs/searcher/inspect.py @@ -0,0 +1,1066 @@ +# -*- coding: iso-8859-1 -*- +"""Get useful information from live Python objects. + +This module encapsulates the interface provided by the internal special +attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion. +It also provides some help for examining source code and class layout. + +Here are some of the useful functions provided by this module: + + ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), + isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), + isroutine() - check object types + getmembers() - get members of an object that satisfy a given condition + + getfile(), getsourcefile(), getsource() - find an object's source code + getdoc(), getcomments() - get documentation on an object + getmodule() - determine the module that an object came from + getclasstree() - arrange classes so as to represent their hierarchy + + getargspec(), getargvalues(), getcallargs() - get info about function arguments + formatargspec(), formatargvalues() - format an argument spec + getouterframes(), getinnerframes() - get info about frames + currentframe() - get the current stack frame + stack(), trace() - get info about frames on the stack or in a traceback +""" + +# This module is in the public domain. No warranties. + +__author__ = 'Ka-Ping Yee ' +__date__ = '1 Jan 2001' + +import sys +import os +import types +import string +import re +import dis +import imp +import tokenize +import linecache +from operator import attrgetter +from collections import namedtuple + +# These constants are from Include/code.h. +CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 0x1, 0x2, 0x4, 0x8 +CO_NESTED, CO_GENERATOR, CO_NOFREE = 0x10, 0x20, 0x40 +# See Include/object.h +TPFLAGS_IS_ABSTRACT = 1 << 20 + +# ----------------------------------------------------------- type-checking +def ismodule(object): + """Return true if the object is a module. + + Module objects provide these attributes: + __doc__ documentation string + __file__ filename (missing for built-in modules)""" + return isinstance(object, types.ModuleType) + +def isclass(object): + """Return true if the object is a class. + + Class objects provide these attributes: + __doc__ documentation string + __module__ name of module in which this class was defined""" + return isinstance(object, (type, types.ClassType)) + +def ismethod(object): + """Return true if the object is an instance method. + + Instance method objects provide these attributes: + __doc__ documentation string + __name__ name with which this method was defined + im_class class object in which this method belongs + im_func function object containing implementation of method + im_self instance to which this method is bound, or None""" + return isinstance(object, types.MethodType) + +def ismethoddescriptor(object): + """Return true if the object is a method descriptor. + + But not if ismethod() or isclass() or isfunction() are true. + + This is new in Python 2.2, and, for example, is true of int.__add__. + An object passing this test has a __get__ attribute but not a __set__ + attribute, but beyond that the set of attributes varies. __name__ is + usually sensible, and __doc__ often is. + + Methods implemented via descriptors that also pass one of the other + tests return false from the ismethoddescriptor() test, simply because + the other tests promise more -- you can, e.g., count on having the + im_func attribute (etc) when an object passes ismethod().""" + return (hasattr(object, "__get__") + and not hasattr(object, "__set__") # else it's a data descriptor + and not ismethod(object) # mutual exclusion + and not isfunction(object) + and not isclass(object)) + +def isdatadescriptor(object): + """Return true if the object is a data descriptor. + + Data descriptors have both a __get__ and a __set__ attribute. Examples are + properties (defined in Python) and getsets and members (defined in C). + Typically, data descriptors will also have __name__ and __doc__ attributes + (properties, getsets, and members have both of these attributes), but this + is not guaranteed.""" + return (hasattr(object, "__set__") and hasattr(object, "__get__")) + +if hasattr(types, 'MemberDescriptorType'): + # CPython and equivalent + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.MemberDescriptorType) +else: + # Other implementations + def ismemberdescriptor(object): + """Return true if the object is a member descriptor. + + Member descriptors are specialized descriptors defined in extension + modules.""" + return False + +if hasattr(types, 'GetSetDescriptorType'): + # CPython and equivalent + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return isinstance(object, types.GetSetDescriptorType) +else: + # Other implementations + def isgetsetdescriptor(object): + """Return true if the object is a getset descriptor. + + getset descriptors are specialized descriptors defined in extension + modules.""" + return False + +def isfunction(object): + """Return true if the object is a user-defined function. + + Function objects provide these attributes: + __doc__ documentation string + __name__ name with which this function was defined + func_code code object containing compiled function bytecode + func_defaults tuple of any default values for arguments + func_doc (same as __doc__) + func_globals global namespace in which this function was defined + func_name (same as __name__)""" + return isinstance(object, types.FunctionType) + +def isgeneratorfunction(object): + """Return true if the object is a user-defined generator function. + + Generator function objects provide the same attributes as functions. + See help(isfunction) for a list of attributes.""" + return bool((isfunction(object) or ismethod(object)) and + object.func_code.co_flags & CO_GENERATOR) + +def isgenerator(object): + """Return true if the object is a generator. + + Generator objects provide these attributes: + __iter__ defined to support iteration over container + close raises a new GeneratorExit exception inside the + generator to terminate the iteration + gi_code code object + gi_frame frame object or possibly None once the generator has + been exhausted + gi_running set to 1 when generator is executing, 0 otherwise + next return the next item from the container + send resumes the generator and "sends" a value that becomes + the result of the current yield-expression + throw used to raise an exception inside the generator""" + return isinstance(object, types.GeneratorType) + +def istraceback(object): + """Return true if the object is a traceback. + + Traceback objects provide these attributes: + tb_frame frame object at this level + tb_lasti index of last attempted instruction in bytecode + tb_lineno current line number in Python source code + tb_next next inner traceback object (called by this level)""" + return isinstance(object, types.TracebackType) + +def isframe(object): + """Return true if the object is a frame object. + + Frame objects provide these attributes: + f_back next outer frame object (this frame's caller) + f_builtins built-in namespace seen by this frame + f_code code object being executed in this frame + f_exc_traceback traceback if raised in this frame, or None + f_exc_type exception type if raised in this frame, or None + f_exc_value exception value if raised in this frame, or None + f_globals global namespace seen by this frame + f_lasti index of last attempted instruction in bytecode + f_lineno current line number in Python source code + f_locals local namespace seen by this frame + f_restricted 0 or 1 if frame is in restricted execution mode + f_trace tracing function for this frame, or None""" + return isinstance(object, types.FrameType) + +def iscode(object): + """Return true if the object is a code object. + + Code objects provide these attributes: + co_argcount number of arguments (not including * or ** args) + co_code string of raw compiled bytecode + co_consts tuple of constants used in the bytecode + co_filename name of file in which this code object was created + co_firstlineno number of first line in Python source code + co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg + co_lnotab encoded mapping of line numbers to bytecode indices + co_name name with which this code object was defined + co_names tuple of names of local variables + co_nlocals number of local variables + co_stacksize virtual machine stack space required + co_varnames tuple of names of arguments and local variables""" + return isinstance(object, types.CodeType) + +def isbuiltin(object): + """Return true if the object is a built-in function or method. + + Built-in functions and methods provide these attributes: + __doc__ documentation string + __name__ original name of this function or method + __self__ instance to which a method is bound, or None""" + return isinstance(object, types.BuiltinFunctionType) + +def isroutine(object): + """Return true if the object is any kind of function or method.""" + return (isbuiltin(object) + or isfunction(object) + or ismethod(object) + or ismethoddescriptor(object)) + +def isabstract(object): + """Return true if the object is an abstract base class (ABC).""" + return bool(isinstance(object, type) and object.__flags__ & TPFLAGS_IS_ABSTRACT) + +def getmembers(object, predicate=None): + """Return all members of an object as (name, value) pairs sorted by name. + Optionally, only return members that satisfy a given predicate.""" + results = [] + for key in dir(object): + try: + value = getattr(object, key) + except AttributeError: + continue + if not predicate or predicate(value): + results.append((key, value)) + results.sort() + return results + +Attribute = namedtuple('Attribute', 'name kind defining_class object') + +def classify_class_attrs(cls): + """Return list of attribute-descriptor tuples. + + For each name in dir(cls), the return list contains a 4-tuple + with these elements: + + 0. The name (a string). + + 1. The kind of attribute this is, one of these strings: + 'class method' created via classmethod() + 'static method' created via staticmethod() + 'property' created via property() + 'method' any other flavor of method + 'data' not a method + + 2. The class which defined this attribute (a class). + + 3. The object as obtained directly from the defining class's + __dict__, not via getattr. This is especially important for + data attributes: C.data is just a data object, but + C.__dict__['data'] may be a data descriptor with additional + info, like a __doc__ string. + """ + + mro = getmro(cls) + names = dir(cls) + result = [] + for name in names: + # Get the object associated with the name, and where it was defined. + # Getting an obj from the __dict__ sometimes reveals more than + # using getattr. Static and class methods are dramatic examples. + # Furthermore, some objects may raise an Exception when fetched with + # getattr(). This is the case with some descriptors (bug #1785). + # Thus, we only use getattr() as a last resort. + homecls = None + for base in (cls,) + mro: + if name in base.__dict__: + obj = base.__dict__[name] + homecls = base + break + else: + obj = getattr(cls, name) + homecls = getattr(obj, "__objclass__", homecls) + + # Classify the object. + if isinstance(obj, staticmethod): + kind = "static method" + elif isinstance(obj, classmethod): + kind = "class method" + elif isinstance(obj, property): + kind = "property" + elif ismethoddescriptor(obj): + kind = "method" + elif isdatadescriptor(obj): + kind = "data" + else: + obj_via_getattr = getattr(cls, name) + if (ismethod(obj_via_getattr) or + ismethoddescriptor(obj_via_getattr)): + kind = "method" + else: + kind = "data" + obj = obj_via_getattr + + result.append(Attribute(name, kind, homecls, obj)) + + return result + +# ----------------------------------------------------------- class helpers +def _searchbases(cls, accum): + # Simulate the "classic class" search order. + if cls in accum: + return + accum.append(cls) + for base in cls.__bases__: + _searchbases(base, accum) + +def getmro(cls): + "Return tuple of base classes (including cls) in method resolution order." + if hasattr(cls, "__mro__"): + return cls.__mro__ + else: + result = [] + _searchbases(cls, result) + return tuple(result) + +# -------------------------------------------------- source code extraction +def indentsize(line): + """Return the indent size, in spaces, at the start of a line of text.""" + expline = string.expandtabs(line) + return len(expline) - len(string.lstrip(expline)) + +def getdoc(object): + """Get the documentation string for an object. + + All tabs are expanded to spaces. To clean up docstrings that are + indented to line up with blocks of code, any whitespace than can be + uniformly removed from the second line onwards is removed.""" + try: + doc = object.__doc__ + except AttributeError: + return None + if not isinstance(doc, types.StringTypes): + return None + return cleandoc(doc) + +def cleandoc(doc): + """Clean up indentation from docstrings. + + Any whitespace that can be uniformly removed from the second line + onwards is removed.""" + try: + lines = string.split(string.expandtabs(doc), '\n') + except UnicodeError: + return None + else: + # Find minimum indentation of any non-blank lines after first line. + margin = sys.maxint + for line in lines[1:]: + content = len(string.lstrip(line)) + if content: + indent = len(line) - content + margin = min(margin, indent) + # Remove indentation. + if lines: + lines[0] = lines[0].lstrip() + if margin < sys.maxint: + for i in range(1, len(lines)): lines[i] = lines[i][margin:] + # Remove any trailing or leading blank lines. + while lines and not lines[-1]: + lines.pop() + while lines and not lines[0]: + lines.pop(0) + return string.join(lines, '\n') + +def getfile(object): + """Work out which source or compiled file an object was defined in.""" + if ismodule(object): + if hasattr(object, '__file__'): + return object.__file__ + raise TypeError('{!r} is a built-in module'.format(object)) + if isclass(object): + object = sys.modules.get(object.__module__) + if hasattr(object, '__file__'): + return object.__file__ + raise TypeError('{!r} is a built-in class'.format(object)) + if ismethod(object): + object = object.im_func + if isfunction(object): + object = object.func_code + if istraceback(object): + object = object.tb_frame + if isframe(object): + object = object.f_code + if iscode(object): + return object.co_filename + raise TypeError('{!r} is not a module, class, method, ' + 'function, traceback, frame, or code object'.format(object)) + +ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type') + +def getmoduleinfo(path): + """Get the module name, suffix, mode, and module type for a given file.""" + filename = os.path.basename(path) + suffixes = map(lambda info: + (-len(info[0]), info[0], info[1], info[2]), + imp.get_suffixes()) + suffixes.sort() # try longest suffixes first, in case they overlap + for neglen, suffix, mode, mtype in suffixes: + if filename[neglen:] == suffix: + return ModuleInfo(filename[:neglen], suffix, mode, mtype) + +def getmodulename(path): + """Return the module name for a given file, or None.""" + info = getmoduleinfo(path) + if info: return info[0] + +def getsourcefile(object): + """Return the filename that can be used to locate an object's source. + Return None if no way can be identified to get the source. + """ + filename = getfile(object) + if string.lower(filename[-4:]) in ('.pyc', '.pyo'): + filename = filename[:-4] + '.py' + for suffix, mode, kind in imp.get_suffixes(): + if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix: + # Looks like a binary file. We want to only return a text file. + return None + if os.path.exists(filename): + return filename + # only return a non-existent filename if the module has a PEP 302 loader + if hasattr(getmodule(object, filename), '__loader__'): + return filename + # or it is in the linecache + if filename in linecache.cache: + return filename + +def getabsfile(object, _filename=None): + """Return an absolute path to the source or compiled file for an object. + + The idea is for each object to have a unique origin, so this routine + normalizes the result as much as possible.""" + if _filename is None: + _filename = getsourcefile(object) or getfile(object) + return os.path.normcase(os.path.abspath(_filename)) + +modulesbyfile = {} +_filesbymodname = {} + +def getmodule(object, _filename=None): + """Return the module an object was defined in, or None if not found.""" + if ismodule(object): + return object + if hasattr(object, '__module__'): + return sys.modules.get(object.__module__) + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) + # Try the cache again with the absolute file name + try: + file = getabsfile(object, _filename) + except TypeError: + return None + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Update the filename to module name cache and check yet again + # Copy sys.modules in order to cope with changes while iterating + for modname, module in sys.modules.items(): + if ismodule(module) and hasattr(module, '__file__'): + f = module.__file__ + if f == _filesbymodname.get(modname, None): + # Have already mapped this module, so skip it + continue + _filesbymodname[modname] = f + f = getabsfile(module) + # Always map to the name the module knows itself by + modulesbyfile[f] = modulesbyfile[ + os.path.realpath(f)] = module.__name__ + if file in modulesbyfile: + return sys.modules.get(modulesbyfile[file]) + # Check the main module + main = sys.modules['__main__'] + if not hasattr(object, '__name__'): + return None + if hasattr(main, object.__name__): + mainobject = getattr(main, object.__name__) + if mainobject is object: + return main + # Check builtins + builtin = sys.modules['__builtin__'] + if hasattr(builtin, object.__name__): + builtinobject = getattr(builtin, object.__name__) + if builtinobject is object: + return builtin + +def findsource(object): + """Return the entire source file and starting line number for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of all the lines + in the file and the line number indexes a line in that list. An IOError + is raised if the source code cannot be retrieved.""" + + file = getfile(object) + sourcefile = getsourcefile(object) + if not sourcefile and file[:1] + file[-1:] != '<>': + raise IOError('source code not available') + file = sourcefile if sourcefile else file + + module = getmodule(object, file) + if module: + lines = linecache.getlines(file, module.__dict__) + else: + lines = linecache.getlines(file) + if not lines: + raise IOError('could not get source code') + + if ismodule(object): + return lines, 0 + + if isclass(object): + name = object.__name__ + pat = re.compile(r'^(\s*)class\s*' + name + r'\b') + # make some effort to find the best matching class definition: + # use the one with the least indentation, which is the one + # that's most probably not inside a function definition. + candidates = [] + for i in range(len(lines)): + match = pat.match(lines[i]) + if match: + # if it's at toplevel, it's already the best one + if lines[i][0] == 'c': + return lines, i + # else add whitespace to candidate list + candidates.append((match.group(1), i)) + if candidates: + # this will sort by whitespace, and by line number, + # less whitespace first + candidates.sort() + return lines, candidates[0][1] + else: + raise IOError('could not find class definition') + + if ismethod(object): + object = object.im_func + if isfunction(object): + object = object.func_code + if istraceback(object): + object = object.tb_frame + if isframe(object): + object = object.f_code + if iscode(object): + if not hasattr(object, 'co_firstlineno'): + raise IOError('could not find function definition') + lnum = object.co_firstlineno - 1 + pat = re.compile(r'^(\s*def\s)|(.*(? 0: + if pat.match(lines[lnum]): break + lnum = lnum - 1 + return lines, lnum + raise IOError('could not find code object') + +def getcomments(object): + """Get lines of comments immediately preceding an object's source code. + + Returns None when source can't be found. + """ + try: + lines, lnum = findsource(object) + except (IOError, TypeError): + return None + + if ismodule(object): + # Look for a comment block at the top of the file. + start = 0 + if lines and lines[0][:2] == '#!': start = 1 + while start < len(lines) and string.strip(lines[start]) in ('', '#'): + start = start + 1 + if start < len(lines) and lines[start][:1] == '#': + comments = [] + end = start + while end < len(lines) and lines[end][:1] == '#': + comments.append(string.expandtabs(lines[end])) + end = end + 1 + return string.join(comments, '') + + # Look for a preceding block of comments at the same indentation. + elif lnum > 0: + indent = indentsize(lines[lnum]) + end = lnum - 1 + if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \ + indentsize(lines[end]) == indent: + comments = [string.lstrip(string.expandtabs(lines[end]))] + if end > 0: + end = end - 1 + comment = string.lstrip(string.expandtabs(lines[end])) + while comment[:1] == '#' and indentsize(lines[end]) == indent: + comments[:0] = [comment] + end = end - 1 + if end < 0: break + comment = string.lstrip(string.expandtabs(lines[end])) + while comments and string.strip(comments[0]) == '#': + comments[:1] = [] + while comments and string.strip(comments[-1]) == '#': + comments[-1:] = [] + return string.join(comments, '') + +class EndOfBlock(Exception): pass + +class BlockFinder: + """Provide a tokeneater() method to detect the end of a code block.""" + def __init__(self): + self.indent = 0 + self.islambda = False + self.started = False + self.passline = False + self.last = 1 + + def tokeneater(self, type, token, srow_scol, erow_ecol, line): + srow, scol = srow_scol + erow, ecol = erow_ecol + if not self.started: + # look for the first "def", "class" or "lambda" + if token in ("def", "class", "lambda"): + if token == "lambda": + self.islambda = True + self.started = True + self.passline = True # skip to the end of the line + elif type == tokenize.NEWLINE: + self.passline = False # stop skipping when a NEWLINE is seen + self.last = srow + if self.islambda: # lambdas always end at the first NEWLINE + raise EndOfBlock + elif self.passline: + pass + elif type == tokenize.INDENT: + self.indent = self.indent + 1 + self.passline = True + elif type == tokenize.DEDENT: + self.indent = self.indent - 1 + # the end of matching indent/dedent pairs end a block + # (note that this only works for "def"/"class" blocks, + # not e.g. for "if: else:" or "try: finally:" blocks) + if self.indent <= 0: + raise EndOfBlock + elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL): + # any other token on the same indentation level end the previous + # block as well, except the pseudo-tokens COMMENT and NL. + raise EndOfBlock + +def getblock(lines): + """Extract the block of code at the top of the given list of lines.""" + blockfinder = BlockFinder() + try: + tokenize.tokenize(iter(lines).next, blockfinder.tokeneater) + except (EndOfBlock, IndentationError): + pass + return lines[:blockfinder.last] + +def getsourcelines(object): + """Return a list of source lines and starting line number for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a list of the lines + corresponding to the object and the line number indicates where in the + original source file the first line of code was found. An IOError is + raised if the source code cannot be retrieved.""" + lines, lnum = findsource(object) + + if ismodule(object): return lines, 0 + else: return getblock(lines[lnum:]), lnum + 1 + +def getsource(object): + """Return the text of the source code for an object. + + The argument may be a module, class, method, function, traceback, frame, + or code object. The source code is returned as a single string. An + IOError is raised if the source code cannot be retrieved.""" + lines, lnum = getsourcelines(object) + return string.join(lines, '') + +# --------------------------------------------------- class tree extraction +def walktree(classes, children, parent): + """Recursive helper function for getclasstree().""" + results = [] + classes.sort(key=attrgetter('__module__', '__name__')) + for c in classes: + results.append((c, c.__bases__)) + if c in children: + results.append(walktree(children[c], children, c)) + return results + +def getclasstree(classes, unique=0): + """Arrange the given list of classes into a hierarchy of nested lists. + + Where a nested list appears, it contains classes derived from the class + whose entry immediately precedes the list. Each entry is a 2-tuple + containing a class and a tuple of its base classes. If the 'unique' + argument is true, exactly one entry appears in the returned structure + for each class in the given list. Otherwise, classes using multiple + inheritance and their descendants will appear multiple times.""" + children = {} + roots = [] + for c in classes: + if c.__bases__: + for parent in c.__bases__: + if not parent in children: + children[parent] = [] + if c not in children[parent]: + children[parent].append(c) + if unique and parent in classes: break + elif c not in roots: + roots.append(c) + for parent in children: + if parent not in classes: + roots.append(parent) + return walktree(roots, children, None) + +# ------------------------------------------------ argument list extraction +Arguments = namedtuple('Arguments', 'args varargs keywords') + +def getargs(co): + """Get information about the arguments accepted by a code object. + + Three things are returned: (args, varargs, varkw), where 'args' is + a list of argument names (possibly containing nested lists), and + 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" + + if not iscode(co): + raise TypeError('{!r} is not a code object'.format(co)) + + nargs = co.co_argcount + names = co.co_varnames + args = list(names[:nargs]) + step = 0 + + # The following acrobatics are for anonymous (tuple) arguments. + for i in range(nargs): + if args[i][:1] in ('', '.'): + stack, remain, count = [], [], [] + while step < len(co.co_code): + op = ord(co.co_code[step]) + step = step + 1 + if op >= dis.HAVE_ARGUMENT: + opname = dis.opname[op] + value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256 + step = step + 2 + if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'): + remain.append(value) + count.append(value) + elif opname in ('STORE_FAST', 'STORE_DEREF'): + if opname == 'STORE_FAST': + stack.append(names[value]) + else: + stack.append(co.co_cellvars[value]) + + # Special case for sublists of length 1: def foo((bar)) + # doesn't generate the UNPACK_TUPLE bytecode, so if + # `remain` is empty here, we have such a sublist. + if not remain: + stack[0] = [stack[0]] + break + else: + remain[-1] = remain[-1] - 1 + while remain[-1] == 0: + remain.pop() + size = count.pop() + stack[-size:] = [stack[-size:]] + if not remain: break + remain[-1] = remain[-1] - 1 + if not remain: break + args[i] = stack[0] + + varargs = None + if co.co_flags & CO_VARARGS: + varargs = co.co_varnames[nargs] + nargs = nargs + 1 + varkw = None + if co.co_flags & CO_VARKEYWORDS: + varkw = co.co_varnames[nargs] + return Arguments(args, varargs, varkw) + +ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') + +def getargspec(func): + """Get the names and default values of a function's arguments. + + A tuple of four things is returned: (args, varargs, varkw, defaults). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'defaults' is an n-tuple of the default values of the last n arguments. + """ + + if ismethod(func): + func = func.im_func + if not isfunction(func): + raise TypeError('{!r} is not a Python function'.format(func)) + args, varargs, varkw = getargs(func.func_code) + return ArgSpec(args, varargs, varkw, func.func_defaults) + +ArgInfo = namedtuple('ArgInfo', 'args varargs keywords locals') + +def getargvalues(frame): + """Get information about arguments passed into a particular frame. + + A tuple of four things is returned: (args, varargs, varkw, locals). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'locals' is the locals dictionary of the given frame.""" + args, varargs, varkw = getargs(frame.f_code) + return ArgInfo(args, varargs, varkw, frame.f_locals) + +def joinseq(seq): + if len(seq) == 1: + return '(' + seq[0] + ',)' + else: + return '(' + string.join(seq, ', ') + ')' + +def strseq(object, convert, join=joinseq): + """Recursively walk a sequence, stringifying each element.""" + if type(object) in (list, tuple): + return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object)) + else: + return convert(object) + +def formatargspec(args, varargs=None, varkw=None, defaults=None, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value), + join=joinseq): + """Format an argument spec from the 4 values returned by getargspec. + + The first four arguments are (args, varargs, varkw, defaults). The + other four arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The ninth + argument is an optional function to format the sequence of arguments.""" + specs = [] + if defaults: + firstdefault = len(args) - len(defaults) + for i, arg in enumerate(args): + spec = strseq(arg, formatarg, join) + if defaults and i >= firstdefault: + spec = spec + formatvalue(defaults[i - firstdefault]) + specs.append(spec) + if varargs is not None: + specs.append(formatvarargs(varargs)) + if varkw is not None: + specs.append(formatvarkw(varkw)) + return '(' + string.join(specs, ', ') + ')' + +def formatargvalues(args, varargs, varkw, locals, + formatarg=str, + formatvarargs=lambda name: '*' + name, + formatvarkw=lambda name: '**' + name, + formatvalue=lambda value: '=' + repr(value), + join=joinseq): + """Format an argument spec from the 4 values returned by getargvalues. + + The first four arguments are (args, varargs, varkw, locals). The + next four arguments are the corresponding optional formatting functions + that are called to turn names and values into strings. The ninth + argument is an optional function to format the sequence of arguments.""" + def convert(name, locals=locals, + formatarg=formatarg, formatvalue=formatvalue): + return formatarg(name) + formatvalue(locals[name]) + specs = [] + for i in range(len(args)): + specs.append(strseq(args[i], convert, join)) + if varargs: + specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) + if varkw: + specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) + return '(' + string.join(specs, ', ') + ')' + +def getcallargs(func, *positional, **named): + """Get the mapping of arguments to values. + + A dict is returned, with keys the function argument names (including the + names of the * and ** arguments, if any), and values the respective bound + values from 'positional' and 'named'.""" + args, varargs, varkw, defaults = getargspec(func) + f_name = func.__name__ + arg2value = {} + + # The following closures are basically because of tuple parameter unpacking. + assigned_tuple_params = [] + def assign(arg, value): + if isinstance(arg, str): + arg2value[arg] = value + else: + assigned_tuple_params.append(arg) + value = iter(value) + for i, subarg in enumerate(arg): + try: + subvalue = next(value) + except StopIteration: + raise ValueError('need more than %d %s to unpack' % + (i, 'values' if i > 1 else 'value')) + assign(subarg,subvalue) + try: + next(value) + except StopIteration: + pass + else: + raise ValueError('too many values to unpack') + def is_assigned(arg): + if isinstance(arg,str): + return arg in arg2value + return arg in assigned_tuple_params + if ismethod(func) and func.im_self is not None: + # implicit 'self' (or 'cls' for classmethods) argument + positional = (func.im_self,) + positional + num_pos = len(positional) + num_total = num_pos + len(named) + num_args = len(args) + num_defaults = len(defaults) if defaults else 0 + for arg, value in zip(args, positional): + assign(arg, value) + if varargs: + if num_pos > num_args: + assign(varargs, positional[-(num_pos-num_args):]) + else: + assign(varargs, ()) + elif 0 < num_args < num_pos: + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at most' if defaults else 'exactly', num_args, + 'arguments' if num_args > 1 else 'argument', num_total)) + elif num_args == 0 and num_total: + if varkw: + if num_pos: + # XXX: We should use num_pos, but Python also uses num_total: + raise TypeError('%s() takes exactly 0 arguments ' + '(%d given)' % (f_name, num_total)) + else: + raise TypeError('%s() takes no arguments (%d given)' % + (f_name, num_total)) + for arg in args: + if isinstance(arg, str) and arg in named: + if is_assigned(arg): + raise TypeError("%s() got multiple values for keyword " + "argument '%s'" % (f_name, arg)) + else: + assign(arg, named.pop(arg)) + if defaults: # fill in any missing values with the defaults + for arg, value in zip(args[-num_defaults:], defaults): + if not is_assigned(arg): + assign(arg, value) + if varkw: + assign(varkw, named) + elif named: + unexpected = next(iter(named)) + try: + unicode + except NameError: + pass + else: + if isinstance(unexpected, unicode): + unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (f_name, unexpected)) + unassigned = num_args - len([arg for arg in args if is_assigned(arg)]) + if unassigned: + num_required = num_args - num_defaults + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at least' if defaults else 'exactly', num_required, + 'arguments' if num_required > 1 else 'argument', num_total)) + return arg2value + +# -------------------------------------------------- stack frame extraction + +Traceback = namedtuple('Traceback', 'filename lineno function code_context index') + +def getframeinfo(frame, context=1): + """Get information about a frame or traceback object. + + A tuple of five things is returned: the filename, the line number of + the current line, the function name, a list of lines of context from + the source code, and the index of the current line within that list. + The optional second argument specifies the number of lines of context + to return, which are centered around the current line.""" + if istraceback(frame): + lineno = frame.tb_lineno + frame = frame.tb_frame + else: + lineno = frame.f_lineno + if not isframe(frame): + raise TypeError('{!r} is not a frame or traceback object'.format(frame)) + + filename = getsourcefile(frame) or getfile(frame) + if context > 0: + start = lineno - 1 - context//2 + try: + lines, lnum = findsource(frame) + except IOError: + lines = index = None + else: + start = max(start, 1) + start = max(0, min(start, len(lines) - context)) + lines = lines[start:start+context] + index = lineno - 1 - start + else: + lines = index = None + + return Traceback(filename, lineno, frame.f_code.co_name, lines, index) + +def getlineno(frame): + """Get the line number from a frame object, allowing for optimization.""" + # FrameType.f_lineno is now a descriptor that grovels co_lnotab + return frame.f_lineno + +def getouterframes(frame, context=1): + """Get a list of records for a frame and all higher (calling) frames. + + Each record contains a frame object, filename, line number, function + name, a list of lines of context, and index within the context.""" + framelist = [] + while frame: + framelist.append((frame,) + getframeinfo(frame, context)) + frame = frame.f_back + return framelist + +def getinnerframes(tb, context=1): + """Get a list of records for a traceback's frame and all lower frames. + + Each record contains a frame object, filename, line number, function + name, a list of lines of context, and index within the context.""" + framelist = [] + while tb: + framelist.append((tb.tb_frame,) + getframeinfo(tb, context)) + tb = tb.tb_next + return framelist + +if hasattr(sys, '_getframe'): + currentframe = sys._getframe +else: + currentframe = lambda _=None: None + +def stack(context=1): + """Return a list of records for the stack above the caller's frame.""" + return getouterframes(sys._getframe(1), context) + +def trace(context=1): + """Return a list of records for the stack below the current exception.""" + return getinnerframes(sys.exc_info()[2], context) diff --git a/python3.7libs/searcher/language_en.py b/python3.7libs/searcher/language_en.py new file mode 100644 index 0000000..6c49b7b --- /dev/null +++ b/python3.7libs/searcher/language_en.py @@ -0,0 +1,69 @@ +# SECTION Language US +language = "en" + + +# NOTE Tooltips +TT_MW = { + "searchbox": "Begin typing to search or click magnifying glass icon to display options", + "contexttoggle": "Toggle to enable or disable the 'context' column in the search results", + "pinwindow": "Pin the search window to keep it from closing automatically when losing focus", + "searchfilter": "Select a predefined filter", + "opensettingstool": "General application settings", + "searchresultstree": "Press tab to highlight or double click an action to attempt to perform it. Some actions only work in specific contexts", + "helpButton": "Open help panel", + "metricposmain": "Change the position of metrics to Houdinis main window", + "metricposself": "Change the position of metrics to Searchers window", + "expand_all": "Expand all tree items", + "collapse_all": "Collapse all tree items", +} + +# NOTE Tooltops Settings +TT_SETTINGS = { + "about": "Contact and other info", + "projectTitle": "Thanks for using Searcher!", + "lang_cbox": "When translations become available they can be selected here", + "inmemory_chk": "Enable to use an in-memory database instead of SQLite file", + "windowsize_chk": "Enable to save the size and location of the main window upon closing. Defaults to center (1000px, 600px)", + "maxresults_lbl": "Maximum results to load per query as you type your search term. (Too many can make results feel sluggish)", + "maxresults_txt": "Maximum results to load per query as you type your search term (Too many can make results feel sluggish)", + "animatedsettings_chk": "Enables animated menus", + "dbpath_icon": "Select the location to store the Searcher database", + "dbpath_lbl": "The location in which Searcher stores it's database file", + "databasepath_txt": "The location in which Searcher stores it's database file", + "defaulthotkey_lbl": "Key used to trigger unbound actions", + "defaulthotkey_txt": "Key used to trigger unbound actions", + "cleardata_btn": "If, for some reason, Searcher is having issues this function will clear out the database and start fresh", + "save_btn": "Save your settings", + "discard_btn": "Disgard settings changes", + "debugflag_chk": "Toggle debug messages", + "debuglevel_cbx": "Select level of debugging", + "bugreport": "Bug report form", + "theme": "Change colors", + "metrics_chk": "Enable performance metrics to view query and render times", +} + +# NOTE database - General Errors +DBERRORMSG = { + "cleardatabase": "Could not clear db for refresh: ", + "updatecontext": "Could not update Searcher context database: ", + "updatechangeindex": "Could not update Searcher context database: ", + "getlastusedhk1": "Could not query last assigned temp hotkey: ", + "getlastusedhk2": "Could not clear last assigned temp hotkey: ", + "getlastusedh3": "Could not clear last assigned temp hotkey on last attempt: ", + "getchangeindex": "Could not get Searcher changeindex: ", +} + +# NOTE 456 - Initial setup +MESSAGES = { + "initialsetup1": "Searcher database created", + "initialsetup2": "Searcher database created and populated", + "createdefaults": "Searcher database created and populated", +} + +# NOTE settings_data - Save/Load +SETTINGSMESSAGES = { + "savesettings": "Could not save settings: ", + "loadsettings": "Could not load settings: ", +} + +# !SECTION diff --git a/python3.7libs/searcher/nodegraphhooks.py b/python3.7libs/searcher/nodegraphhooks.py new file mode 100644 index 0000000..c6a0a9c --- /dev/null +++ b/python3.7libs/searcher/nodegraphhooks.py @@ -0,0 +1,62 @@ +import os + +import sys + +sys.dont_write_bytecode = True + +import hou + +from PySide2 import QtWidgets + +from houdini_markingmenu import markingmenu as mm + +from canvaseventtypes import * + +import nodegraphbase as base + +sys.path.insert(0, os.path.join(hou.getenv('HOUDINI_USER_PREF_DIR'), + 'python2.7libs', + 'houdini_markingmenu')) + +import buttonfunctions as cmds + +def buildHandler(uievent, pending_actions): + import nodegraph # to avoid circular imports + class MarkingMenuMouseHandler(nodegraph.NodeMouseHandler): + def handleEvent(self, uievent, pending_actions): + if isinstance(uievent, MouseEvent) and uievent.eventtype == 'mousedrag': + reload(mm) + for entry in QtWidgets.QApplication.instance().allWidgets(): + if type(entry).__name__ == 'NEMarkingMenu': + entry.setParent(None) + entry.close() + markingMenu = mm.NEMarkingMenu(uievent.editor) + # return None if we handled event and launched a marking menu + return None + # Return traditional nodegraph rmb handling if we didn't launch a marking menu + # If an input, output, or dependancy arrow was right clicked, for example. + return nodegraph.NodeMouseHandler.handleEvent( + self, uievent, pending_actions) + return MarkingMenuMouseHandler(uievent) + +# We catch the mousedown event and then further handling is done by our custom class +# createEventHandler catches mouse events and either does stuff +# and/or returns an eventHandler class with a handleEvent() method that +# handles the events until completion of the event or hands it off to a different handler + +# createEventHandler catches events (see "Extending the Network Editor docs page") +# every time an event is registered, we check to see if it's a right mouse button being held down +# if it is, we check to see if our menu variable is set to 1 +# if our menu is on, then we call our custom function that wil ultimately open our menu window + + +def createEventHandler(uievent, pending_actions): + if isinstance(uievent, MouseEvent) and uievent.eventtype == 'mousedown' and uievent.mousestate.rmb: + reload(cmds) + if uievent.selected.item is None: + if cmds.MENU_ACTIVATE: + a = buildHandler(uievent, pending_actions) + return a, True + else: + return None, False + return None, False \ No newline at end of file diff --git a/python3.7libs/searcher/platformselect.py b/python3.7libs/searcher/platformselect.py new file mode 100644 index 0000000..4e44bd2 --- /dev/null +++ b/python3.7libs/searcher/platformselect.py @@ -0,0 +1,31 @@ +import os +import sys +import platform +import ctypes + +PLATFORM = None +SEARCHER_PATH = os.environ["SEARCHER"] + +def get_platform(): + """Returns a string for the current platform""" + global PLATFORM + + if PLATFORM is None: + p = sys.platform + if p == 'darwin': + PLATFORM = 'darwin' + elif p.startswith('win'): + PLATFORM = 'windows' + else: + PLATFORM = 'unix' + + return PLATFORM + +def get_sqlite(): + if get_platform() == "windows": + path_sqlite_dll = os.path.join(SEARCHER_PATH, 'dso/sqlite3.dll') + ctypes.cdll.LoadLibrary(path_sqlite_dll) + elif get_platform() == "Darwin": + path_sqlite_dll = os.path.join(SEARCHER_PATH, 'python27/dlls/sqlite3.dll') + else: + path_sqlite_dll = os.path.join(SEARCHER_PATH, 'python27/dlls/sqlite3.dll') diff --git a/python3.7libs/searcher/ptime.py b/python3.7libs/searcher/ptime.py new file mode 100644 index 0000000..450e6fd --- /dev/null +++ b/python3.7libs/searcher/ptime.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +""" +ptime.py - Precision time function made os-independent (should have been taken care of by python) +Copyright 2010 Luke Campagnola +Distributed under MIT/X11 license. See license.txt for more infomation. +""" + + +import sys + +if sys.version_info[0] < 3: + from time import clock + from time import time as system_time +else: + from time import perf_counter as clock + from time import time as system_time + +START_TIME = None +time = None + +def winTime(): + """Return the current time in seconds with high precision (windows version, use Manager.time() to stay platform independent).""" + return clock() - START_TIME + #return systime.time() + +def unixTime(): + """Return the current time in seconds with high precision (unix version, use Manager.time() to stay platform independent).""" + return system_time() + +if sys.platform.startswith('win'): + cstart = clock() ### Required to start the clock in windows + START_TIME = system_time() - cstart + + time = winTime +else: + time = unixTime \ No newline at end of file diff --git a/python3.7libs/searcher/searcher.py b/python3.7libs/searcher/searcher.py new file mode 100644 index 0000000..527c13e --- /dev/null +++ b/python3.7libs/searcher/searcher.py @@ -0,0 +1,1685 @@ +# ---------------------------------------------------------------- Imports +# SECTION Imports -------------------------------------------------------- +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division + +from searcher import util +from searcher import style +from searcher import ptime +from searcher import animator +from searcher import database +from searcher import HelpButton +from searcher import datahandler +from searcher import searcher_ui +from searcher import settings_data +from searcher import searcher_settings +from searcher import searcher_settings_ui +from searcher import language_en as la + +import os +import re +import sys +import hou +import threading +import hdefereval as hd +from hutil.py23 import reload +# noinspection PyUnresolvedReferences +from canvaseventtypes import * +from collections import Iterable + +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtGui + from qtpy import QtCore + from qtpy import QtWidgets + +reload(searcher_settings_ui) +reload(searcher_settings) +reload(settings_data) +reload(searcher_ui) +reload(datahandler) +reload(HelpButton) +reload(animator) +reload(database) +reload(style) +reload(ptime) +reload(util) +reload(la) + +# !SECTION Imports + + +# ---------------------------------------------------------------- Globals +# SECTION Globals -------------------------------------------------------- +# ----------------------------------------------- Variables +# NOTE Variables ------------------------------------------ +kwargs = {} +settings = {} +hasran = False +mousePos = None +cur_screen = QtWidgets.QDesktopWidget().screenNumber( + QtWidgets.QDesktopWidget().cursor().pos() +) +screensize = QtWidgets.QDesktopWidget().screenGeometry(cur_screen) +centerPoint = QtWidgets.QDesktopWidget().availableGeometry(cur_screen).center() + +sys.path.append(os.path.join(os.path.dirname(__file__))) +script_path = os.path.dirname(os.path.realpath(__file__)) +name = "Searcher" + +parent_widget = hou.qt.mainWindow() + + +# ----------------------------------------------- Functions +# NOTE Functions ------------------------------------------ +def get_settings(): + return getattr(hou.session, "SETTINGS", None) + + +def get_dbhandler(): + return getattr(hou.session, "DBHANDLER", None) + + +def keyconversion(key): + for i in range(len(key)): + if key[i] in util.KEYCONVERSIONS: + key[i] = util.KEYCONVERSIONS[key[i]] + return key + + +# !SECTION Globals + +# --------------------------------------------------------- Searcher Class +# SECTION Searcher Class ------------------------------------------------- +# noinspection PyUnresolvedReferences +class Searcher(QtWidgets.QWidget): + """instance.id Searcher for Houdini""" + + # --------------------------------------------------------- Class init + # SECTION Class init ------------------------------------------------- + def __init__(self, settings, windowsettings, animated, kwargs): + super(Searcher, self).__init__(parent=hou.qt.mainWindow()) + # self.timerprofile = None # ANCHOR hou perf timer + # self.loadhevent = None # ANCHOR hou perf timer + + # -------------------------- Constructed + # NOTE Constructed ---------------------- + self.goalnum = 7 + self.kwargs = kwargs + self.animated = animated + self.settingdata = settings + self.searcher_window = self + self.parentwindow = hou.qt.mainWindow() + self.windowsettings = windowsettings + + # -------------------------- Setting vars + # NOTE Setting vars---------------------- + self.isdebug = util.Dbug( + self.settingdata[util.SETTINGS_KEYS[4]], + str(self.settingdata[util.SETTINGS_KEYS[10]]), + self.settingdata[util.SETTINGS_KEYS[12]], + self.settingdata[util.SETTINGS_KEYS[13]], + ) + + self._drag_active = False + self.animationDuration = 200 + self.app = QtWidgets.QApplication.instance() + self.settingslayout = QtWidgets.QVBoxLayout() + self.showctx = self.settingdata[util.SETTINGS_KEYS[7]] + self.windowispin = self.settingdata[util.SETTINGS_KEYS[5]] + self.originalsize = self.settingdata[util.SETTINGS_KEYS[3]] + self.expanditems = self.settingdata[util.SETTINGS_KEYS[15]] + self.animatedsettings = self.settingdata[util.SETTINGS_KEYS[8]] + self.appcolors = util.AppColors(self.settingdata[util.SETTINGS_KEYS[14]]) + + if self.animatedsettings: + self.uiwidth = int(520) + self.uiheight = int(300) + else: + self.uiwidth = int(520) + self.uiheight = int(242) + + # ------------------------------------ Function Vars + # NOTE Function Vars ------------------------------- + self.hotkeys = [] + self.lastused = {} + self.context_list = [] + self.hcontext_tli = {} + + self.tmpkey = None + self.getpane = None + self.tiptimer = None + self.resizing = False + self.mouseout = False + self.tmpsymbol = None + self.searching = False + self.ctxsearch = False + self.showglobal = True + self.menuopened = False + self.overhandle = False + self.previous_pos = None + self.searchprefix = False + self.keys_changed = False + self.holdinfobanner = False + self.searchdescription = False + self.searchcurrentcontext = False + + # --------------------------------- Performance Vars + # NOTE Performance Vars ---------------------------- + self.endtime = 0 + self.starttime = 0 + self.treecatnum = 0 + self.hotkeystime = 0 + self.regtimetotal = 0 + self.hcontexttime = 0 + self.treeitemsnum = 0 + self.threadtimer = None + + # ---------------------------------- Init Functions + # NOTE Init Functionss ----------------------------- + self.handler = self.initialsetup() + self.ui = searcher_settings.SearcherSettings( + self.handler, + self.uiwidth, + self.uiheight, + self + ) + if self.animatedsettings: + self.anim = animator.Animator(self.ui, self.anim_complete) + + hou.hotkeys._createBackupTables() + self.uisetup() + self.addshortcuts() + self.buildsettingsmenu() + + # !SECTION Class init + + def getwidgets(self): + from searcher import debugutils as dbug + reload(dbug) + data = "" + + for shelf in hou.shelves.shelves().values(): + data += ("Shelf name: %s -------------------------- \n" % shelf) + for tool in shelf.tools(): + data += ("Tool name: %s \n" % tool.name()) + data += ("Tool label: %s \n" % tool.label()) + data += ("Tool keywords: %s \n" % tool.script()) + # data += ("Tool toolMenuLocations: %s \n" % tool.toolMenuOpType()) + + outputpath = os.path.join( + hou.homeHoudiniDirectory(), 'Searcher', "output.json" + ) + # info = hou.ui.viewerStateInfo() + sample = open(outputpath, 'w') + print(data, file=sample) + sample.close() + # print(info) + + # shelfkeys = hou.shelves.tools().keys() + # tools = hou.shelves.tools() + + # for i in range(0, 10): + # tool = tools[shelfkeys[i]] + # print("Tool: %s" % tool) + # for t in tool: + # print("Tool data: %s" % t) + # tools = tools[shelfkeys[t]] + # print("Tool data: %s" % tool[t]) + + # toolkeys = tool.keys() + # print("Tool keys: %s" % toolkeys) + # print(shelfkeys[i]) + + # runningtool = hou.shelves.runningTool() + # print(runningtool) + + print(self.kwargs) + if "editor" in self.kwargs: + print(self.kwargs["editor"].pwd()) + + # print(hou.shelves.tools().keys()) + + pos = QtGui.QCursor.pos() + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Position: X:%d Y: %d" % (pos.x(), pos.y())) + + mainwin = QtWidgets.QApplication + undermouse = util.widgets_at(mainwin, pos) + + widgetdata = "" + outputpath2 = os.path.join( + hou.homeHoudiniDirectory(), 'Searcher', "widgets.json" + ) + sample2 = open(outputpath2, 'w') + for w in undermouse: + print(dbug.dumpWidgetLayout(w, "_____"), file=sample2) + if w.windowTitle() != "": + print("Title: %s" % w.windowTitle()) + + sample2.close() + + # allWidgets = QtWidgets.QApplication.allWidgets() + # for w in allWidgets: + # if w.windowTitle() != "": + # print("Title: %s" % w.windowTitle()) + + # outputpath = os.path.join( + # hou.homeHoudiniDirectory(), 'Searcher', "output.json" + # ) + # info = hou.ui.viewerStateInfo() + # sample = open(outputpath, 'w') + # print(info, file = sample) + # sample.close() + # print(info) + + # ------------------------------------------------------ Settings Menu + # SECTION Settings Menu ---------------------------------------------- + # ----------------------------------- buildsettingsmenu + # NOTE buildsettingsmenu ------------------------------ + def buildsettingsmenu(self): + self.ui.setWindowFlags( + QtCore.Qt.Tool + | QtCore.Qt.CustomizeWindowHint + | QtCore.Qt.FramelessWindowHint + ) + self.ui.setAttribute(QtCore.Qt.WA_StyledBackground, True) + if self.settingdata[util.SETTINGS_KEYS[8]]: + self.ui.setAttribute(QtCore.Qt.WA_TranslucentBackground, True) + self.ui.setStyleSheet(style.SETTINGSMENU) + + self.settingslayout = self.ui.settingslayout + if self.animatedsettings: + self.anim.setContentLayout(self.settingslayout) + self.anim.resize( + self.uiwidth, + self.uiheight + ) + self.ui.resize( + self.uiwidth, + self.uiheight + ) + + # !SECTION Settings Menu + + # ----------------------------------------------------------------- UI + # SECTION UI --------------------------------------------------------- + # -------------------------------------------- UI Setup + # SECTION UI Setup ------------------------------------ + def uisetup(self): + names = ["open", "save", "hotkey", "perference"] + # self.completer = QtWidgets.QCompleter(names) + self.completer = QtWidgets.QCompleter(names) + self.completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) + self.completer.setModel(QtWidgets.QDirModel(self.completer)) + self.completer.setCompletionMode(self.completer.InlineCompletion) + + self.sui = searcher_ui.Ui_Searcher() + self.sui.setupUi(self, self.animated) + self.sui.mainlayout.addLayout(self.sui.gridLayout) + self.setLayout(self.sui.mainlayout) + + # ---------------------------------- UI Connections + # NOTE UI Connections ----------------------------- + self.helpButton = self.sui.helpButton + + # ------------------------------------- Result Tree + # NOTE Result Tree -------------------------------- + self.searchresultstree = self.sui.searchresults_tree + self.searchresultstree.itemActivated.connect(self.searchclick_cb) + + # -------------------------------------- Search Box + # NOTE Search Box --------------------------------- + self.searchbox = self.sui.searchbox_txt + self.searchbox.textChanged.connect(self.textchange_cb) + self.searchbox.customContextMenuRequested.connect(self.openmenu) + self.searchbox.setPlaceholderText(" Begin typing to search..") + self.searchbox.setFocusPolicy(QtCore.Qt.StrongFocus) + self.searchbox.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.searchbox.setClearButtonEnabled(True) + self.searchbox.setCompleter(self.completer) + + # ----------------------------------- Search Filter + # NOTE Search Filter ------------------------------ + self.searchfilter = self.sui.searchfilter_btn + self.searchfilter.clicked.connect(self.searchfilter_cb) + self.searchfilter.setFixedWidth(26) + self.searchfilter.setFixedHeight(26) + self.searchfilter.setProperty("flat", True) + self.searchfilter.setIcon(util.SEARCH_ICON) + self.searchfilter.setIconSize(QtCore.QSize( + hou.ui.scaledSize(16), + hou.ui.scaledSize(16) + )) + + # ----------------------------------- Item Expander + # NOTE Item Expander ------------------------------ + self.expander = self.sui.expander + self.setexpandericon() + self.expander.clicked.connect(self.expander_cb) + expander_button_size = hou.ui.scaledSize(18) + self.expander.setProperty("flat", True) + self.expander.setIconSize(QtCore.QSize( + expander_button_size, + expander_button_size + )) + + # -------------------------------------- Metric Pos + # NOTE Metric Pos --------------------------------- + self.metricpos = self.sui.metricpos + self.setmetricicon() + self.metricpos.clicked.connect(self.metricpos_cb) + metricpos_button_size = hou.ui.scaledSize(16) + self.metricpos.setProperty("flat", True) + self.metricpos.setIconSize(QtCore.QSize( + metricpos_button_size, + metricpos_button_size + )) + self.metricpos.setVisible(self.settingdata[util.SETTINGS_KEYS[12]]) + + # ---------------------------------- Context Toggle + # NOTE Context Toggle ----------------------------- + self.contexttoggle = self.sui.contexttoggle + self.contexttoggle.clicked[bool].connect(self.showctx_cb) + self.contexttoggle.setCheckable(True) + self.contexttoggle.setChecked(self.showctx) + self.contexttoggle.setFixedWidth(20) + self.contexttoggle.setFixedHeight(20) + contexttoggle_button_size = hou.ui.scaledSize(16) + self.contexttoggle.setProperty("flat", True) + self.contexttoggle.setIconSize(QtCore.QSize( + contexttoggle_button_size, + contexttoggle_button_size + )) + self.setctxicon() + self.contexttoggle.setStyleSheet(style.CONTEXTTOGGLE) + + # -------------------------------------- Pin Window + # NOTE Pin Window --------------------------------- + self.pinwindow = self.sui.pinwindow_btn + self.setpinicon() + self.pinwindow.clicked.connect(self.pinwindow_cb) + pinwindow_button_size = hou.ui.scaledSize(16) + self.pinwindow.setProperty("flat", True) + self.pinwindow.setIconSize(QtCore.QSize( + pinwindow_button_size, + pinwindow_button_size + )) + + # ----------------------------------- Settings Menu + # NOTE Settings Menu ------------------------------ + self.opensettingstool = self.sui.opensettings_btn + self.opensettingstool.setCheckable(True) + self.opensettingstool.setChecked(False) + self.opensettingstool.clicked.connect(self.opensettings_cb) + opensettingstool_button_size = hou.ui.scaledSize(16) + self.opensettingstool.setProperty("flat", True) + self.opensettingstool.setIcon(util.SETTINGS_ICON) + self.opensettingstool.setIconSize(QtCore.QSize( + opensettingstool_button_size, + opensettingstool_button_size + )) + + # ---------------------------------------- Info Bar + # NOTE Info Bar ----------------------------------- + self.infolbl = self.sui.info_lbl + self.treetotal_lbl = self.sui.treetotal_lbl + + # ---------------------------------- Resize Handles + # NOTE Resize Handles ----------------------------- + self.leftresize = self.sui.leftresize + self.rightresize = self.sui.rightresize + + # ---------------------------------------- Tooltips + # NOTE Tooltips ----------------------------------- + self.searchbox.setToolTip(la.TT_MW[self.searchbox.objectName()]) + self.contexttoggle.setToolTip(la.TT_MW[self.contexttoggle.objectName()]) + self.pinwindow.setToolTip(la.TT_MW[self.pinwindow.objectName()]) + self.searchfilter.setToolTip(la.TT_MW[self.searchfilter.objectName()]) + self.opensettingstool.setToolTip(la.TT_MW[self.opensettingstool.objectName()]) + self.searchresultstree.setToolTip(la.TT_MW[self.searchresultstree.objectName()]) + + self.setupresulttree() + self.searchbox.setFocus() + self.searchbox.grabKeyboard() + + # !SECTION UI Setup + + # ----------------------------------- Setup Result Tree + # NOTE Setup Result Tree ------------------------------ + def setupresulttree(self): + cols = 4 + self.searchresultstree.setColumnCount(cols) + self.searchresultstree.setColumnWidth(0, 250) + if self.isdebug and self.isdebug.level in {"ALL"}: + self.searchresultstree.setColumnWidth(1, 350) + else: + self.searchresultstree.setColumnWidth(1, 450) + self.searchresultstree.setColumnWidth(2, 100) + self.searchresultstree.setColumnWidth(3, 150) + self.searchresultstree.setColumnWidth(4, 150) + self.searchresultstree.setHeaderLabels([ + "Label", + "Description", + "Assignments", + "Symbol", + "Context" + ]) + self.searchresultstree.setColumnHidden(3, self.showctx) + if not self.isdebug.level in {"ALL"}: + self.searchresultstree.hideColumn(4) + + self.searchresultstree.header().setMinimumSectionSize(85) + self.searchresultstree.header().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents) + self.searchresultstree.header().setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents) + self.searchresultstree.header().setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents) + self.searchresultstree.header().setSectionResizeMode(3, QtWidgets.QHeaderView.Stretch) + self.searchresultstree.header().setSectionResizeMode(4, QtWidgets.QHeaderView.ResizeToContents) + self.searchresultstree.setStyleSheet(style.gettreeviewstyle()) + + # --------------------------------------------------- Search Menu + # SECTION Search Menu ------------------------------------------- + # -------------------------------------------- openmenu + # NOTE openmenu --------------------------------------- + def openmenu(self): + self.menuopened = True + self.searchmenu = QtWidgets.QMenu() + self.searchmenu.setProperty('flat', True) + self.searchmenu.setStyleSheet(style.MENUSTYLE) + self.searchmenu.setWindowFlags( + self.searchmenu.windowFlags() | + QtCore.Qt.NoDropShadowWindowHint | + QtCore.Qt.X11BypassWindowManagerHint + ) + self.globalprefix = self.searchmenu.addAction("Global items") + self.contextprefix = self.searchmenu.addAction("Context items") + self.viewprefix = self.searchmenu.addAction("View items") + + self.globalprefix.setToolTip( + "View application-wide actions") + + self.contextprefix.setToolTip( + "Shows possible actions for the view in which the mouse was in when the window was opened") + + self.viewprefix.setToolTip( + "Shows the available view panes (ex. Scene View, Render View, Composit View, etc") + + self.searchmenu.hovered.connect(self.handlemenuhovered) + + self.action = self.searchmenu.exec_( + self.searchbox.mapToGlobal(QtCore.QPoint(0, 29))) + if self.action == self.globalprefix: + self.searchbox.setText(":g") + if self.action == self.contextprefix: + self.searchbox.setText(":c") + if self.action == self.viewprefix: + self.searchbox.setText(":v") + + self.searchmenu.installEventFilter(self) + + # ----------------------------------- handlemenuhovered + # NOTE handlemenuhovered ------------------------------ + def handlemenuhovered(self, action): + self.setinfotext(200, action.toolTip()) + + # !SECTION Search Menu + # !SECTION UI + + # ---------------------------------------------------------- Functions + # SECTION Functions -------------------------------------------------- + # ---------------------------------------- setstatusmsg + # NOTE setstatusmsg ----------------------------------- + def setstatusmsg(self, msg, severity): + if self.isdebug.mainwindow: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + message=(str(msg)), severity=severity) + else: + print(str(msg)) + else: + styledmsg, severitytype = style.setstatusmsg(msg, severity) + self.setinfotext(200, styledmsg, True) + + # ----------------------------------------- setinfotext + # NOTE setinfotext ------------------------------------ + def setinfotext(self, duration, text, status=False): + if not status: text = style.gettooltipstyle(text) + self.infolbl.setStyleSheet(style.INFOLABEL) + self.infolbl.setText(text) + self.fade_in(self.infolbl, duration) + + # ----------------------------------------- count_chars + # NOTE count_chars ------------------------------------ + def count_chars(self, txt): + result = 0 + for char in txt: + result += 1 # same as result = result + 1 + return result + + # --------------------------------------- Initial Setup + # NOTE Initial Setup ---------------------------------- + def initialsetup(self): + self.handler = get_dbhandler() + if not self.handler: + hou.session.DBHANDLER = datahandler.DataHandler(self.isdebug) + self.handler = get_dbhandler() + + currentidx = hou.hotkeys.changeIndex() + chindex = self.handler.getchangeindex() + + if len(chindex) == 0: + chindex = int(currentidx) + self.handler.updatechangeindex(chindex, True) + self.handler.updatedataasync(self.isdebug) + hou.ui.setStatusMessage( + "Searcher database created", + severity=hou.severityType.Message + ) + else: + chindex = int(chindex[0][0]) + + if int(currentidx) != chindex: + self.handler.updatedataasync(self.isdebug) + self.handler.updatechangeindex(int(currentidx)) + + return self.handler + + # --------------------------------------------- getnode + # NOTE getnode ---------------------------------------- + def getnode(self): + nodeSelect = hou.selectedNodes() + for node in nodeSelect: + getName = node.name() + if self.isdebug and self.isdebug.level in {"ALL"}: + print(getName) + + # ---------------------------------------------- getpane + # NOTE getpane ----------------------------------------- + def getpanedata(self): + try: + return hou.ui.paneTabUnderCursor() + except (AttributeError, TypeError) as e: + hou.ui.setStatusMessage( + ("No context options to display: " + str(e)), + severity=hou.severityType.Message + ) + + # !SECTION Functions + + # ---------------------------------------------------------- Callbacks + # SECTION Callbacks -------------------------------------------------- + # ------------------------------------- searchfilter_cb + # NOTE searchfilter_cb -------------------------------- + def searchfilter_cb(self): + self.openmenu() + + # ------------------------------------- setexpandericon + # NOTE setexpandericon -------------------------------- + def setexpandericon(self): + if self.expanditems: + self.expander.setIcon(util.COLLAPSE_ALL_ICON) + self.expander.setToolTip(la.TT_MW['collapse_all']) + else: + self.expander.setIcon(util.EXPAND_ALL_ICON) + self.expander.setToolTip(la.TT_MW['expand_all']) + + # ----------------------------------------- expander_cb + # NOTE expander_cb ------------------------------------ + def expander_cb(self): + if self.expanditems: + self.searchresultstree.collapseAll() + else: + self.searchresultstree.expandAll() + + self.expanditems = not self.expanditems + self.setexpandericon() + self.settingdata[util.SETTINGS_KEYS[15]] = self.expanditems + settings_data.savesettings(self.settingdata) + + # --------------------------------------- setmetricicon + # NOTE setmetricicon ---------------------------------- + def setmetricicon(self): + if self.isdebug.mainwindow: + self.metricpos.setIcon(util.UP_ICON) + self.metricpos.setToolTip(la.TT_MW['metricposself']) + + else: + self.metricpos.setIcon(util.DOWN_ICON) + self.metricpos.setToolTip(la.TT_MW['metricposmain']) + + # ---------------------------------------- metricpos_cb + # NOTE metricpos_cb ----------------------------------- + def metricpos_cb(self): + self.isdebug.mainwindow = not self.isdebug.mainwindow + self.settingdata[util.SETTINGS_KEYS[13]] = self.isdebug.mainwindow + settings_data.savesettings(self.settingdata) + self.setmetricicon() + + # ------------------------------------------ setctxicon + # NOTE setctxicon ------------------------------------- + def setctxicon(self): + if self.showctx: + self.contexttoggle.setIcon(util.COLLAPSE_ICON) + else: + self.contexttoggle.setIcon(util.EXPAND_ICON) + self.searchresultstree.setColumnHidden(3, self.showctx) + + # ------------------------------------------ showctx_cb + # NOTE showctx_cb ------------------------------------- + def showctx_cb(self, pressed): + self.showctx = True if pressed else False + self.settingdata[util.SETTINGS_KEYS[7]] = self.showctx + settings_data.savesettings(self.settingdata) + self.setctxicon() + + # ---------------------------------------- pinwindow_cb + # NOTE pinwindow_cb ----------------------------------- + def pinwindow_cb(self): + self.windowispin = not self.windowispin + self.settingdata[util.SETTINGS_KEYS[5]] = self.windowispin + settings_data.savesettings(self.settingdata) + self.setpinicon() + + # ------------------------------------------ setpinicon + # NOTE setpinicon ------------------------------------- + def setpinicon(self): + if self.windowispin: + self.pinwindow.setIcon(util.PIN_IN_ICON) + else: + self.pinwindow.setIcon(util.PIN_OUT_ICON) + + # ------------------------------------- opensettings_cb + # NOTE opensettings_cb -------------------------------- + def opensettings_cb(self, doopen): + self.ui.isopened = self.ui.isVisible() + + if self.animatedsettings: + self.open_settings(doopen) + elif self.ui.isopened: + self.open_settings(False) + else: + self.open_settings(True) + + # --------------------------------------- open_settings + # NOTE open_settings ---------------------------------- + def open_settings(self, doopen): + if doopen: + pos = self.opensettingstool.mapToGlobal( + QtCore.QPoint(-self.ui.width() + 31, 28)) + self.ui.setGeometry( + pos.x(), + pos.y(), + self.ui.width(), + self.ui.height() + ) + self.ui.updatecurrentvalues() + self.ui.show() + self.ui.activateWindow() + self.ui.setFocus() + if self.animatedsettings: + self.anim.start_animation(True) + else: + if self.ui.performcheck: + if self.ui.checkforchanges(): + self.ui.savecheck() + if self.animatedsettings and not self.ui.waitforclose: + self.ui.closewindows() + _ = self.anim.start_animation(False) + else: + self.ui.isopened = True + self.ui.closewindows() + self.ui.close() + if self.ui.waitforclose: + self.close() + + def anim_complete(self): + if self.ui.isopened: + self.ui.close() + self.ui.isopened = False + self.opensettingstool.setChecked(False) + + # --------------------------------------- textchange_cb + # NOTE textchange_cb ---------------------------------- + def textchange_cb(self, text): + self.starttime = ptime.time() # ----------------------------- # ANCHOR Search Timer Start + if len(text) > 0 and not self.holdinfobanner: + self.setinfotext(200, self.searchresultstree.toolTip()) + if text in util.CTXSHOTCUTS: + self.ctxsearcher(text) + elif len(text) > 1 and text not in util.CTXSHOTCUTS: + self.searching = True + allowed = re.compile(r'[^a-zA-Z ]+') + text = re.sub(allowed, '', text) + str = text.split() + searchstring = ['%s*' % (x,) for x in str] + regtime = ptime.time() # ----------------------------- # ANCHOR Regex Timer Start + self.regtimetotal = ((regtime - self.starttime) * 1000.0) + if searchstring: + if self.isdebug and self.isdebug.level in {"ALL"}: + print(searchstring) + txt, timer = self.handler.searchtext( + ' '.join(searchstring), + self.isdebug, + self.settingdata[util.SETTINGS_KEYS[9]] + ) + self.hotkeystime = timer + self.searchtablepopulate(txt) + else: + self.getpane = None + self.holdinfobanner = False + self.searching = False + self.treetotal_lbl.setText("") + self.searchresultstree.clear() + self.setinfotext(200, self.searchbox.toolTip()) + + # -------------------------------------- searchclick_cb + # NOTE searchclick_cb --------------------------------- + def searchclick_cb(self, item, column): + hk = item.text(2) + self.tmpsymbol = item.text(3) + + if hk == "": + self.chindex = hou.hotkeys.changeIndex() + result = self.createtemphotkey(self.tmpsymbol) + if result is True: + self.chindex = hou.hotkeys.changeIndex() + hk = hou.hotkeys.assignments(self.tmpsymbol) + self.processkey(hk, True) + else: + hk = hou.hotkeys.assignments(self.tmpsymbol) + self.processkey(hk) + self.tmpsymbol = None + return + + # ---------------------------------------- ctxhotkey_cb + # NOTE ctxhotkey_cb ----------------------------------- + def ctxhotkey_cb(self): + if self.menuopened: + self.searchmenu.setFocus() + else: + self.searchbox.setFocus() + self.searchbox.blockSignals(True) + self.searchbox.setText(":c") + self.searchbox.blockSignals(False) + self.ctxsearcher() + + # ------------------------------------------ getContext + # NOTE getContext ------------------------------------- + def getContext(self, ctx): + """Return Houdini context string.""" + try: + hou_context = ctx.pwd().childTypeCategory().name() + except: + return None + + print("Hou Context: ", hou_context) + return util.CONTEXTTYPE[hou_context] + + # !SECTION Callbacks + + # -------------------------------------------------- Hotkey Processing + # SECTION Hotkey Processing ------------------------------------------ + # ------------------------------------- savelastkey + # NOTE savelastkey -------------------------------- + def savelastkey(self, symbol, key): + self.settingdata[util.SETTINGS_KEYS[11]] = (str(symbol) + " " + str(key[0])) + settings_data.savesettings(self.settingdata) + + # -------------------------------------- processkey + # NOTE processkey --------------------------------- + def processkey(self, key, tmphk=False): + if tmphk: + self.savelastkey(self.tmpsymbol, key) + + if (key[0] is not '+'): + key = key[0].split('+') + + skey = None + ikey = None + key = keyconversion(key) + modifiers = util.MODIFIERS + mod_flag = QtCore.Qt.KeyboardModifiers() + for i in range(len(key)): + if str(key[i]) in modifiers: + mod_flag = mod_flag | util.MODIFIERS[str(key[i])] + else: + skey = key[i] + ikey = util.KEY_DICT[str(key[i])] + + keypress = QtGui.QKeyEvent( + QtGui.QKeyEvent.KeyPress, # Keypress event identifier + ikey, # Qt key identifier + mod_flag, # Qt key modifier + skey # String of Qt key identifier + ) + + focustarget = self.getpane if self.getpane else hou.ui.mainQtWindow() + if self.getpane: + for pane_tab in hou.ui.curDesktop().paneTabs(): + if pane_tab.name() == focustarget.name(): + pane_tab.setIsCurrentTab() + + try: + if sys.platform == "darwin": + hou.qt.mainWindow().setFocus() + hd.executeDeferredAfterWaiting(self.app.sendEvent, 5, hou.qt.mainWindow(), keypress) + else: + hou.qt.mainWindow().setFocus() + hd.executeDeferred(self.app.sendEvent, hou.qt.mainWindow(), keypress) + # event = QtWidgets.QApplication.postEvent(hou.ui.mainQtWindow(), keypress) + self.close() + + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage( + ("Could not trigger hotkey event: " + str(e)), + severity=hou.severityType.Warning + ) + print("Could not trigger hotkey event: " + str(e)) + + # ---------------------------------- setKeysChanged + # NOTE setKeysChanged ----------------------------- + def setKeysChanged(self, changed): + if self.keys_changed and not changed: + if not hou.hotkeys.saveOverrides(): + print("ERROR: Couldn't save hotkey override file.") + self.keys_changed = changed + self.chindex = hou.hotkeys.changeIndex() + self.handler.updatechangeindex(self.chindex) + + # -------------------------------- createtemphotkey + # NOTE createtemphotkey --------------------------- + def createtemphotkey(self, symbol): + hkeys = util.gethotkeys() + hou.hotkeys._createBackupTables() + for i in range(len(hkeys)): + result = hou.hotkeys.findConflicts(symbol, hkeys[i]) + if not result: + assignresult = hou.hotkeys.addAssignment(symbol, hkeys[i]) + if assignresult: + self.tmpkey = hkeys[i] + break + else: + pass + else: + pass + + self.keys_changed = True + self.setKeysChanged(False) + return assignresult + + # -------------------------------- removetemphotkey + # NOTE removetemphotkey --------------------------- + def removetemphotkey(self, symbol, tmpkey): + hou.hotkeys._restoreBackupTables() + hou.hotkeys.revertToDefaults(symbol, True) + self.keys_changed = True + self.setKeysChanged(False) + hkcheck = hou.hotkeys.assignments(str(symbol)) + if len(hkcheck) is 0: + self.settingdata[util.SETTINGS_KEYS[11]] = "" + settings_data.savesettings(self.settingdata) + + # !SECTION Hotkey Processing + + # ------------------------------------------------------------- Search + # SECTION Search ----------------------------------------------------- + # ---------------------------------- createcontextitems + # TODO createcontextitems ----------------------------- + def createcontextitems(self, result, hc): + result[2] = (QtWidgets.QTreeWidgetItem(self.searchresultstree, [result[hc][0], result[hc][1]])) + + # -------------------------------------------- openmenu + # TODO openmenu --------------------------------------- + def appendcontextlist(self, list): + if list[4] not in self.context_list: + return self.context_list.append(list[4]) + + # ------------------------------------- globalkeysearch + # NOTE globalkeysearch -------------------------------- + def globalkeysearch(self): + self.ctxsearch = True + ctx = ["h"] + results = self.handler.searchctx(ctx) + self.searchtablepopulate(results) + self.ctxsearch = False + + def processdesktop(self, ran, result): + print("---- %s" % ran) + print(result) + print("Window Name: %s | Whats This?: %s | Type: %s" % ( + result.windowTitle(), result.whatsThis(), result.accessibleName())) + if isinstance(result, Iterable): + print("Item amount: %d" % len(result)) + try: + for i in result: + print(i.windowTitle()) + if ran == "hou.ui.paneTabs()": + print("Name : %s | Item: %s | Type: %s" % (i.name(), i, i.type)) + elif ran == "util.widgets_at(mainwin, pos)": + print("Window Name: %s | Item: %s | Type: %s" % (i.windowTitle(), i.type, i.type)) + else: + print(i) + + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (("Error in %s : " % ran) + str(e)), severity=hou.severityType.Warning) + pass + else: + print(("Error in %s : " % ran) + str(e)) + pass + + # ------------------------------------------------------ Context Terms + # SECTION Context Terms ---------------------------------------------- + # ----------------------------------------- ctxsearcher + # NOTE ctxsearcher ------------------------------------ + def ctxsearcher(self, ctx=None): + self.starttime = ptime.time() + results = None + ctxresult = [] + + # ---------------------------- None or :c + # NOTE None or :c ----------------------- + if ctx is None or ctx == ":c": + self.ctxsearch = True + self.getpane = None + skipelse = False + undermouse = None + pane = "" + mainwin = QtWidgets.QApplication + + try: + selected_node = hou.selectedNodes() + if selected_node: + print("#1 - Selected Node: %s" % selected_node) + print(selected_node[0].parmTuples()) + for i in selected_node[0].parmTuples(): + print(i) + skipelse = True + else: + pass + except(AttributeError, TypeError) as e: + self.setstatusmsg(str(e), "Warning") + + if not skipelse: + try: + self.getpane = self.getpanedata() + if self.isdebug and self.isdebug.level in {"ALL"}: print(self.getpane) + if self.getpane: + panetype = self.getpane.type() + ctxresult = util.PANETYPES[self.getpane.type()] + results = self.handler.searchctx(ctxresult[0]) + self.searchbox.blockSignals(True) + self.searchbox.setText(":c %s" % ctxresult[1]) + self.searchbox.blockSignals(False) + skipelse = True + else: + pass + except(AttributeError, TypeError) as e: + self.setstatusmsg(str(e), "Warning") + + if not skipelse: + try: + pos = QtGui.QCursor.pos() + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Position: X:%d Y: %d" % (pos.x(), pos.y())) + + undermouse = util.widgets_at(QtWidgets.QApplication, pos) + if undermouse: + for w in undermouse: + if w.windowTitle() != "": + ctxresult = util.PANETYPES.get( + w.windowTitle()) if w.windowTitle() in util.PANETYPES else None + if ctxresult is not None: + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Title: %s HContext: %s" % (ctxresult[0], ctxresult[1])) + results = self.handler.searchctx(ctxresult[0]) + self.searchbox.blockSignals(True) + self.searchbox.setText(":c %s" % ctxresult[1]) + self.searchbox.blockSignals(False) + break + else: + e = "#3 - Object under mouse cannot be queried" + self.setstatusmsg(str(e), "ImportantMessage") + pass + + except(AttributeError, TypeError) as e: + self.setstatusmsg(str(e), "Warning") + return + + # ------------------------------------ :v + # NOTE :v ------------------------------- + elif ctx == ":v": + self.ctxsearch = True + ctxresult.append("h.pane") + results = self.handler.searchctx(ctxresult) + + # ------------------------------------ :g + # NOTE :g ------------------------------- + elif ctx == ":g": + self.ctxsearch = True + ctxresult.append("h") + results = self.handler.searchctx(ctxresult) + # !SECTION Context Terms + if results: + self.searchtablepopulate(results) + self.ctxsearch = False + self.searchbox.clearFocus() + self.searchresultstree.setFocus() + self.searchresultstree.setCurrentItem( + self.searchresultstree.topLevelItem(0).child(0) + ) + # endtime = ptime.time() -------------------------------------- # ANCHOR CTXHotkey Performance Timer + # timetotal = ((endtime - self.starttime) * 1000.0) + # print("CTX Timer: %0.4f" % timetotal) + else: + e = "Unable to locate usable context item" + self.setstatusmsg(str(e), "ImportantMessage") + + # --------------------------------- searchtablepopulate + # NOTE searchtablepopulate ---------------------------- + def searchtablepopulate(self, data): + if len(data) > 0: + # tabletimer = hou.perfMon.startEvent("Table_Populate") ------- # ANCHOR hou perf timer + self.treecatnum = 0 + self.treeitemsnum = 0 + self.searchresultstree.clear() + + self.hotkeys[:] = [] + self.context_list[:] = [] + self.hcontext_tli.clear() + + # list(map(self.appendcontextlist, data)) + for i in range(len(data)): + if data[i][4] not in self.context_list: + self.context_list.append(data[i][4]) + # if self.ctxsearch: + # else: + # self.context_list.append(data[i][4]) + + result, hctimer = self.handler.gethcontextod(self.context_list) + self.hcontexttime = hctimer + treebuildtimer = ptime.time() # ------------------------------ # ANCHOR Tree builder Start + # TODO Test Map --------- + for hc in range(len(result)): + self.hcontext_tli[result[hc][2]] = (QtWidgets.QTreeWidgetItem( + self.searchresultstree, [ + result[hc][0], + result[hc][1] + ] + )) + if self.expanditems: + self.searchresultstree.expandItem(self.hcontext_tli[result[hc][2]]) + self.treecatnum += 1 + + base_keys = list(self.hcontext_tli.keys()) + for i in range(len(data)): + for j in range(len(base_keys)): + if base_keys[j] == data[i][4]: + if self.isdebug and self.isdebug.level in {"ALL"}: + self.hotkeys.append(QtWidgets.QTreeWidgetItem( + self.hcontext_tli[base_keys[j]], [ + data[i][0], + data[i][1], + data[i][2], + data[i][3], + data[i][4] + ] + )) + self.treeitemsnum += 1 + else: + self.hotkeys.append(QtWidgets.QTreeWidgetItem( + self.hcontext_tli[base_keys[j]], [ + data[i][0], + data[i][1], + data[i][2], + data[i][3] + ] + )) + self.treeitemsnum += 1 + + # tabletimer.stop() # ANCHOR hou perf timer ---------------------------------------- hou perf timer + # self.searchevent.stop() # ANCHOR hou perf timer ---------------------------------------- hou perf timer + # self.timerprofile.stop() # ANCHOR hou perf timer ---------------------------------------- hou perf timer + + treebuildtimerend = ptime.time() # --------------------------- # ANCHOR Tree Builder End + treebuildtotal = ((treebuildtimerend - treebuildtimer) * 1000.0) + + if not self.holdinfobanner: + try: + self.infolabeldelayasync() + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage(str(e), severity=hou.severityType.Message) + else: + print(e) + + self.styleresultstotalasync(self.treecatnum, self.treeitemsnum) + self.endtime = ptime.time() # ----------------------------- # ANCHOR Search Timer End + totaltime = ((self.endtime - self.starttime) * 1000.0) + if self.isdebug.performance: + outdata = [self.regtimetotal, self.hcontexttime, self.hotkeystime, treebuildtotal, totaltime] + self.styletimersasync(outdata) + + # !SECTION Search + + # ------------------------------------------------------ Async Methods + # SECTION Async Methods ---------------------------------------------- + # ------------------------------------------------- worker1 + # SECTION Workers : NOTE worker1 -------------------------- + def worker1(self, d1): + hd.executeInMainThreadWithResult(self.styletimers, d1) + + # ------------------------------------------------- worker2 + # NOTE worker2 -------------------------------------------- + def worker2(self, d1, d2): + hd.executeInMainThreadWithResult(self.styletotals, d1, d2) + + # ------------------------------------------------- worker3 + # NOTE worker3 -------------------------------------------- + def worker3(self): + hd.executeInMainThreadWithResult(self.infolabeldelay) + + # !SECTION Workers + + # ---------------------------------------- styletimersasync + # SECTION styletimers : NOTE styletimersasync ----------------------------------- + def styletimersasync(self, d1): + thread = threading.Thread(target=self.worker1, args=(d1,)) + thread.daemon = True + thread.start() + + # --------------------------------------------- styletimers + # NOTE styletimers ---------------------------------------- + def styletimers(self, d1): + if self.isdebug.mainwindow: + perftime = style.returntimers(d1) + if hou.isUIAvailable(): + hou.ui.setStatusMessage(perftime, severity=hou.severityType.Message) + else: + print(perftime) + else: + perftime = style.styletimers(d1) + self.infolbl.setStyleSheet(style.INFOLABEL) + self.infolbl.setText(perftime) + + # !SECTION styletimers + + # ---------------------------------- styleresultstotalasync + # SECTION styleresultstotal : NOTE styleresultstotalasync - + def styleresultstotalasync(self, d1, d2): + thread = threading.Thread(target=self.worker2, args=(d1, d2)) + thread.daemon = True + thread.start() + + # --------------------------------------------- styletotals + # NOTE styletotals ---------------------------------------- + def styletotals(self, d1, d2): + result = style.styleresulttotal(d1, d2) + self.treetotal_lbl.setText(result) + + # !SECTION styleresultstotal + + # --------------------------------------infolabeldelayasync + # SECTION infolabeldelay : NOTE infolabeldelayasync ------ + def infolabeldelayasync(self): + if self.threadtimer: + self.threadtimer.cancel() + self.holdinfobanner = True + self.infolbl.setStyleSheet(style.INFOLABEL) + self.threadtimer = threading.Timer(5, self.infolabeldelay) + self.threadtimer.start() + + # ------------------------------------------ infolabeldelay + # NOTE infolabeldelay ------------------------------------- + def infolabeldelay(self): + try: + self.infolbl.setText(style.gettooltipstyle(self.searchresultstree.toolTip())) + hd.executeDeferred(self.fade_in, self.infolbl, 200) + self.holdinfobanner = False + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage(e, severity=hou.severityType.Message) + else: + print(e) + else: + pass + # print(self.timerprofile.stats()) # ANCHOR hou perf timer ---------------------------------------- hou perf timer + + # !SECTION infolabeldelay + + # --------------------------------------------- createtimer + # NOTE createtimer ---------------------------------------- + def createtimer(self, time, func, p): + if self.tiptimer: + if self.tiptimer.isAlive(): + self.tiptimer.cancel() + + self.tiptimer = threading.Timer(time, (func(p))) + self.tiptimer.start() + + # !SECTION Async Methods + + # --------------------------------------------------------- Animations + # SECTION Animations ------------------------------------------------- + # ----------------------------------------- fade_in + # NOTE fade_in ------------------------------------ + def fade_in(self, target, duration): + self.effect = QtWidgets.QGraphicsOpacityEffect() + self.tar = target + self.tar.setGraphicsEffect(self.effect) + self.an = QtCore.QPropertyAnimation(self.effect, b"opacity") + self.an.setDuration(duration) + self.an.setStartValue(0) + self.an.setEndValue(1) + self.an.start() + + # ---------------------------------------- fade_out + # NOTE fade_out ----------------------------------- + def fade_out(self, target, duration): + self.effect = QtWidgets.QGraphicsOpacityEffect() + self.tar = target + self.tar.setGraphicsEffect(self.effect) + self.an = QtCore.QPropertyAnimation(self.effect, b"opacity") + self.an.setDuration(duration) + self.an.setStartValue(1) + self.an.setEndValue(0) + self.an.start() + + # !SECTION + + # ------------------------------------------------------------- Events + # SECTION Events ---------------------------------------------------- + # ------------------------------------- addeventfilters + # NOTE addeventfilters -------------------------------- + def addeventfilters(self): + self.installEventFilter(self) + self.expander.installEventFilter(self) + self.metricpos.installEventFilter(self) + self.searchbox.installEventFilter(self) + self.pinwindow.installEventFilter(self) + self.helpButton.installEventFilter(self) + self.leftresize.installEventFilter(self) + self.rightresize.installEventFilter(self) + self.searchfilter.installEventFilter(self) + self.contexttoggle.installEventFilter(self) + self.opensettingstool.installEventFilter(self) + self.searchresultstree.installEventFilter(self) + + # ---------------------------------- removeeventfilters + # NOTE removeeventfilters ----------------------------- + def removeeventfilters(self): + self.removeEventFilter(self) + self.expander.removeEventFilter(self) + self.metricpos.removeEventFilter(self) + self.searchbox.removeEventFilter(self) + self.pinwindow.removeEventFilter(self) + self.helpButton.removeEventFilter(self) + self.leftresize.removeEventFilter(self) + self.rightresize.removeEventFilter(self) + self.searchfilter.removeEventFilter(self) + self.contexttoggle.removeEventFilter(self) + self.opensettingstool.removeEventFilter(self) + self.searchresultstree.removeEventFilter(self) + + # --------------------------------------- cancelthreads + # NOTE cancelthreads ---------------------------------- + def cancelthreads(self): + if self.threadtimer: + self.threadtimer.cancel() + if self.tiptimer: + self.tiptimer.cancel() + + # ------------------------------ createdelayedinfolabel + # NOTE createdelayedinfolabel ------------------------- + def createdelayedinfolabel(self, tiptext): + self.infolbl.setText(style.gettooltipstyle(tiptext)) + self.fade_in(self.infolbl, 200) + + # ---------------------------------------- checktooltip + # NOTE checktooltip ----------------------------------- + def checktooltip(self, obj, hasleft=False): + if hasleft: + if self.searching and self.infolbl.text() != self.searchresultstree.toolTip(): + self.setinfotext(700, self.searchresultstree.toolTip()) + elif not self.searching and self.infolbl.text() != self.searchbox.toolTip(): + self.setinfotext(700, self.searchbox.toolTip()) + else: + if obj == self.searchresultstree or obj == self.searchbox: + if self.searching and self.infolbl.text() != self.searchresultstree.toolTip(): + self.setinfotext(200, self.searchresultstree.toolTip()) + elif not self.searching and self.infolbl.text() != self.searchbox.toolTip(): + self.setinfotext(200, self.searchbox.toolTip()) + elif self.infolbl.text() != obj.toolTip(): + self.setinfotext(200, obj.toolTip()) + + # ---------------------------------------- addshortcuts + # NOTE addshortcuts ----------------------------------- + def addshortcuts(self): + toggleexpand_shct = QtWidgets.QShortcut(QtGui.QKeySequence("Ctrl+W"), self) + toggleexpand_shct.activated.connect(self.expander_cb) + + opensettings_shct = QtWidgets.QShortcut(QtGui.QKeySequence("Ctrl+S"), self) + opensettings_shct.activated.connect(self.opensettingstool.click) + + getpanes_shct = QtWidgets.QShortcut(QtGui.QKeySequence("ALT+V"), self) + getpanes_shct.activated.connect(self.getwidgets) + + getpanes_shct = QtWidgets.QShortcut(QtGui.QKeySequence("Ctrl+Tab"), self) + getpanes_shct.activated.connect(self.ctxhotkey_cb) + + # -------------------------------------------------------- Event Types + # SECTION Event Types ------------------------------------------------ + # def createEventHandler(self, uievent, pending_actions): + # if isinstance(uievent, MouseEvent): + def onFocusWindowChanged(self, focusWindow): + if focusWindow is None: + print("None!") + + def onMouseEvent(self, kwargs): + ui_event = kwargs["ui_event"] + print(ui_event) + reason = ui_event.reason() + device = ui_event.device() + if device.isLeftButton(): + print("Clicked") + + if reason == hou.uiEventReason.Picked: + print("LMB click") + + elif reason == hou.uiEventReason.Start: + print("LMB was pressed down") + + elif reason == hou.uiEventReason.Active: + print("Mouse dragged with LMB down") + + elif reason == hou.uiEventReason.Changed: + print("LMB was released") + + def eventFilter(self, obj, event): + event_type = event.type() + + # ------------------------------------------- Mouse + # NOTE Mouse -------------------------------------- + # --------------------------------- Enter + # NOTE Enter ---------------------------- + if event_type == QtCore.QEvent.Enter: + if obj == self: + self.mouseout = False + if obj == self.leftresize or obj == self.rightresize: + self.overhandle = True + style.styleresizehandle(obj, True) + self.checktooltip(obj) + + # --------------------------------- Leave + # NOTE Leave ---------------------------- + if event_type == QtCore.QEvent.Leave: + if obj == self: + self.mouseout = True + if obj == self.leftresize or obj == self.rightresize: + self.overhandle = False + style.styleresizehandle(obj, False) + self.checktooltip(obj, True) + + # ------------------------------- ToolTip + # NOTE ToolTip -------------------------- + if event_type == QtCore.QEvent.ToolTip: + return True + + # ---------------------- MouseButtonPress + # NOTE MouseButtonPress ----------------- + if event_type == QtCore.QEvent.MouseButtonPress: + if obj == self.leftresize or obj == self.rightresize: + self.resizing = True + self.previous_pos = event.globalPos() + + if obj == self.searchbox: + return QtCore.QObject.eventFilter(self, obj, event) + else: + if obj == self: + self.activateWindow() + self.previous_pos = event.globalPos() + if obj == self.parentwindow: + self.close() + + # -------------------- MouseButtonRelease + # NOTE MouseButtonRelease --------------- + if event_type == QtCore.QEvent.MouseButtonRelease: + if obj == self.leftresize or obj == self.rightresize: + self.resizing = False + + if self._drag_active: + self._drag_active = False + + # ----------------------------- MouseMove + # NOTE MouseMove ------------------------ + if event_type == QtCore.QEvent.MouseMove: + if obj == self: + delta = event.globalPos() - self.previous_pos + self.move(self.x() + delta.x(), self.y() + delta.y()) + + if self.ui.isVisible(): + self.ui.move(self.ui.x() + delta.x(), self.ui.y() + delta.y()) + self.ui.movesubwindows(delta) + + self.previous_pos = event.globalPos() + self._drag_active = True + + if self.resizing: + if obj == self.rightresize: + delta = event.globalPos() - self.previous_pos + + if self.ui.isVisible(): + self.ui.move(self.ui.x() + delta.x(), self.ui.y()) + self.ui.movesubwindows(delta, True) + self.previous_pos = event.globalPos() + else: + return QtCore.QObject.eventFilter(self, obj, event) + + # ---------------------------- MouseHover + # NOTE MouseHover ----------------------- + if event_type == QtCore.QEvent.HoverMove: + pass + + # ---------------------------------------- Keypress + # NOTE Keypress ----------------------------------- + if event_type == QtCore.QEvent.KeyPress: + # # ----------------------------- Enter + # # NOTE Enter ------------------------ + # if event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter): + # print('Enter:') + # enter_event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Enter, QtCore.Qt.NoModifier) + # QtWidgets.QApplication.postEvent(self, enter_event) + # return True + + # ------------------------------- TAB + # NOTE TAB -------------------------- + if event.key() == QtCore.Qt.Key_Tab: + if self.searching: + self.searchbox.releaseKeyboard() + self.searchbox.clearFocus() + self.searchresultstree.setFocus() + self.searchresultstree.setCurrentItem( + self.searchresultstree.topLevelItem(0).child(0)) + return True + else: + pass + + # ------------------------------- ESC + # NOTE ESC -------------------------- + if event.key() == QtCore.Qt.Key_Escape: + if self.ui.isVisible(): + self.ui.closeroutine() + return True + else: + if self.menuopened: + if self.searchmenu.isVisible(): + self.searchmenu.setVisible(False) + return True + else: + self.menuopened = False + return True + else: + self.close() + return True + + # ------------------------------- ":" + # NOTE ":" -------------------------- + if event.key() == QtCore.Qt.Key_Colon: + if self.searchbox.text() == "": + self.searchbox.releaseKeyboard() + self.searchbox.clearFocus() + self.openmenu() + return True + + # ------------------------------------------ Window + # NOTE Window ------------------------------------- + # ------------------------------ Activate + # NOTE Activate ------------------------- + if event_type == QtCore.QEvent.WindowActivate: + if obj == self: + self.searchbox.grabKeyboard() + + # ---------------------------- Deactivate + # NOTE Deactivate ----------------------- + if event_type == QtCore.QEvent.WindowDeactivate: + if self.ui.isVisible(): + self.searchbox.releaseKeyboard() + return True + if self.windowispin: + return QtCore.QObject.eventFilter(self, obj, event) + if self.mouseout: + self.close() + + # ------------------------------- FocusIn + # NOTE FocusIn -------------------------- + if event_type == QtCore.QEvent.FocusIn: + if obj == self: + pass + + # ------------------------------ FocusOut + # NOTE FocusOut ------------------------- + if event_type == QtCore.QEvent.FocusOut: + if obj == self: + pass + + # ------------------------------------------- Close + # NOTE Close -------------------------------------- + if event_type == QtCore.QEvent.Close: + self.cancelthreads() + try: + if util.bc(self.settingdata[util.SETTINGS_KEYS[2]]): + self.windowsettings.setValue("geometry", self.saveGeometry()) + except (AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage(("Could not save window dimensions: " + str(e)), + severity=hou.severityType.Warning) + else: + print("Could not save window dimensions: " + str(e)) + + if self.menuopened: + self.searchmenu.setVisible(False) + + if self.tmpsymbol is not None: + hd.executeDeferredAfterWaiting( + self.removetemphotkey, + 25, + self.tmpsymbol, + self.tmpkey) + + self.searchbox.releaseKeyboard() + try: + self.parentwindow.activateWindow() + self.parentwindow.setFocus() + self.setParent(None) + self.deleteLater() + except: + self.parentwindow.activateWindow() + self.setParent(None) + self.deleteLater() + try: + return QtCore.QObject.eventFilter(self, obj, event) + except RuntimeError: + return True + + # !SECTION Event Types + # !SECTION Events + # !SECTION Searcher Class + + +# -------------------------------------------------------------- Setup +# SECTION Setup ------------------------------------------------------ +# ----------------------------------- Center Window +# NOTE Center Window ------------------------------ +def center(): + return parent_widget.mapToGlobal( + QtCore.QPoint( + parent_widget.rect().center().x(), + parent_widget.rect().center().y() + ) + ) + + +# ----------------------------------- Create Window +# NOTE Create Window ------------------------------ +def CreateSearcherPanel(searcher_window=None, **kwargs): + # timerprofile = hou.perfMon.startProfile("Load_Timer") # ANCHOR hou perf timer ---------------- hou perf timer + # loadevent = hou.perfMon.startEvent("Start _Timer") # ANCHOR hou perf timer ---------------- hou perf timer + # starttime = ptime.time() + + kwargs = kwargs + settings = get_settings() + windowsettings = QtCore.QSettings("instance.id", "Searcher") + + animated = True + searcher_window = Searcher(settings, windowsettings, animated, kwargs) + searcher_window.addeventfilters() + searcher_window.setStyleSheet(style.MAINWINDOW) + searcher_window.setAttribute(QtCore.Qt.WA_StyledBackground, True) + searcher_window.setWindowFlags( + QtCore.Qt.Tool + | QtCore.Qt.CustomizeWindowHint + | QtCore.Qt.FramelessWindowHint + | QtCore.Qt.WindowStaysOnTopHint + ) + + if util.bc(settings[util.SETTINGS_KEYS[2]]) and windowsettings.value("geometry") is not None: + searcher_window.restoreGeometry(windowsettings.value("geometry")) + else: + searcher_window.resize( + int(settings[util.SETTINGS_KEYS[3]][0]), + int(settings[util.SETTINGS_KEYS[3]][1]), + ) + spos = center() + searcher_window.setGeometry( + spos.x() - (searcher_window.width() / 2), + spos.y() - (searcher_window.height() / 2), + searcher_window.width(), + searcher_window.height(), + ) + searcher_window.searchbox.setFocus() + searcher_window.setWindowTitle('Searcher') + if not searcher_window.isVisible(): + searcher_window.show() + searcher_window.activateWindow() + + # endtime = ptime.time() + # timetotal = ((endtime - starttime) * 1000.0) + # print("Time: %0.4f" % timetotal) + # loadevent.stop() # ANCHOR hou perf timer ---------------------------------------- hou perf timer + # timerprofile.stop() # ANCHOR hou perf timer ---------------------------------------- hou perf timer + # print(timerprofile.stats()) # ANCHOR hou perf timer ---------------------------------------- hou perf timer + + # searcher_window.activateWindow() + + +# !SECTION Setup + + +__package__ = "searcher" diff --git a/python3.7libs/searcher/searcher_settings.py b/python3.7libs/searcher/searcher_settings.py new file mode 100644 index 0000000..8e75cd1 --- /dev/null +++ b/python3.7libs/searcher/searcher_settings.py @@ -0,0 +1,700 @@ +from __future__ import division +from __future__ import print_function +from __future__ import absolute_import + +from searcher import util +from searcher import about +from searcher import theme +from searcher import about_ui +from searcher import theme_ui +from searcher import bugreport +from searcher import bugreport_ui +from searcher import settings_data +from searcher import language_en as la +from searcher import searcher_settings_ui + +from builtins import range +import os + +import hou +from hutil.py23 import reload + +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.') + 1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtGui + from qtpy import QtCore + from qtpy import QtWidgets + +reload(about) +reload(theme) +reload(about_ui) +reload(theme_ui) +reload(bugreport) +reload(bugreport_ui) +reload(searcher_settings_ui) + + +# --------------------------------------------- hou.session +# NOTE hou.session ---------------------------------------- +def get_settings(): + return getattr(hou.session, "SETTINGS", None) + + +the_scaled_icon_size = hou.ui.scaledSize(16) +the_icon_size = 16 + +scriptpath = os.path.dirname(os.path.realpath(__file__)) + + +def bc(v): + return str(v).lower() in ("yes", "true", "t", "1") + + +class SearcherSettings(QtWidgets.QWidget): + """ Searcher Settings and Debug Menu""" + + def __init__(self, handler, width, height, parent=None): + super(SearcherSettings, self).__init__(parent=parent) + # -------------------------------------------- settings + # NOTE settings --------------------------------------- + self.parentwindow = parent + self.settings = {} + self.context_dict = {} + self.command_dict = {} + self.currentsettings = {} + self.performcheck = True + self.contexts = None + self.commands = None + self.addKeyWidget = None + self.context_data = None + self.command_data = None + self.keys_changed = False + self.keystring = "" + self.keyindex = 0 + self.canedit = False + self.KeySequence = None + self.hkholder = "" + self.datahandler = handler + self.isopened = False + self.resetdb = False + self.waitforclose = False + self.modifylayout = False + self.uiwidth = width + self.uiheight = height + self.windowlist = ["about", "bugreport", "theme"] + self.parentwindow.oldPos = self.parentwindow.pos() + + # --------------------------------------------- beginui + # NOTE beginui ---------------------------------------- + self.setObjectName('searcher-settings') + self.setAutoFillBackground(True) + self.setBackgroundRole(QtGui.QPalette.Window) + self.settings = get_settings() + self.isdebug = util.Dbug( + self.settings[util.SETTINGS_KEYS[4]], + str(self.settings[util.SETTINGS_KEYS[10]]), + self.settings[util.SETTINGS_KEYS[12]], + self.settings[util.SETTINGS_KEYS[13]], + ) + + self.la = la.TT_SETTINGS + # Load UI File + self.ui = searcher_settings_ui.Ui_SearcherSettings() + self.ui.setupUi(self, self.uiwidth, self.uiheight, bc(self.settings[util.SETTINGS_KEYS[8]])) + self.ui.retranslateUi(self) + + self.about = about.About(self) + self.about.setAttribute(QtCore.Qt.WA_StyledBackground, True) + self.about.setWindowFlags( + QtCore.Qt.Tool + | QtCore.Qt.FramelessWindowHint + | QtCore.Qt.CustomizeWindowHint + ) + self.about.resize(width, height - 180) + + self.bugreport = bugreport.BugReport(self) + self.bugreport.setAttribute(QtCore.Qt.WA_StyledBackground, True) + self.bugreport.setWindowFlags( + QtCore.Qt.Tool + | QtCore.Qt.FramelessWindowHint + | QtCore.Qt.CustomizeWindowHint + ) + self.bugreport.resize(width, height - 300) + + self.theme = theme.Theme(self) + self.theme.setAttribute(QtCore.Qt.WA_StyledBackground, True) + self.theme.setWindowFlags( + QtCore.Qt.Tool + | QtCore.Qt.FramelessWindowHint + | QtCore.Qt.CustomizeWindowHint + | QtCore.Qt.NoDropShadowWindowHint + ) + self.theme.resize(width, height - 90) + + self.settingslayout = QtWidgets.QVBoxLayout() + + # Get UI Elements + self.hotkey_icon = self.ui.hotkey_icon + + # headerrow + self.in_memory_db = self.ui.inmemory_chk + self.in_memory_db.setToolTip(la.TT_SETTINGS[self.in_memory_db.objectName()]) + self.savewindowsize = self.ui.windowsize_chk + self.savewindowsize.setToolTip(la.TT_SETTINGS[self.savewindowsize.objectName()]) + + # secondrow + self.ui.maxresults_lbl.setToolTip(la.TT_SETTINGS[self.ui.maxresults_lbl.objectName()]) + self.maxresults = self.ui.maxresults_txt + self.maxresults.setToolTip(la.TT_SETTINGS[self.maxresults.objectName()]) + self.animatedsettings = self.ui.animatedsettings_chk + self.animatedsettings.setToolTip(la.TT_SETTINGS[self.animatedsettings.objectName()]) + + # thirdrow + self.ui.defaulthotkey_lbl.setToolTip(la.TT_SETTINGS[self.ui.defaulthotkey_lbl.objectName()]) + self.defaulthotkey = self.ui.defaulthotkey_txt + self.defaulthotkey.setToolTip(la.TT_SETTINGS[self.defaulthotkey.objectName()]) + + # fourthrow + self.ui.dbpath_lbl.setToolTip(la.TT_SETTINGS[self.ui.dbpath_lbl.objectName()]) + self.database_path = self.ui.databasepath_txt + self.database_path.setToolTip(la.TT_SETTINGS[self.database_path.objectName()]) + self.dbpath_btn = self.ui.dbpath_icon + self.dbpath_btn.setToolTip(la.TT_SETTINGS[self.dbpath_btn.objectName()]) + dbpath_button_size = hou.ui.scaledSize(16) + self.dbpath_btn.setProperty("flat", True) + self.dbpath_btn.setIcon(util.FILE_ICON) + self.dbpath_btn.setIconSize(QtCore.QSize( + dbpath_button_size, + dbpath_button_size + )) + + # fifthrow + self.metrics = self.ui.metrics_chk + self.metrics.setVisible(bc(self.settings[util.SETTINGS_KEYS[4]])) + self.metrics.setToolTip(la.TT_SETTINGS[self.metrics.objectName()]) + # self.cleardata = self.ui.cleardata_btn + # self.cleardata.setToolTip(la.TT_SETTINGS[self.cleardata.objectName()]) + + # sixthrow + self.aboutbtn = self.ui.about_btn + self.aboutbtn.setToolTip(la.TT_SETTINGS[self.aboutbtn.objectName()]) + self.aboutbtn.setCheckable(True) + self.aboutbtn.setChecked(False) + about_button_size = hou.ui.scaledSize(32) + self.aboutbtn.setProperty("flat", True) + self.aboutbtn.setIcon(util.ABOUT_ICON1) + self.aboutbtn.setIconSize(QtCore.QSize( + about_button_size, + about_button_size + )) + + self.bugreportbtn = self.ui.bug_btn + self.bugreportbtn.setToolTip(la.TT_SETTINGS[self.bugreportbtn.objectName()]) + self.bugreportbtn.setCheckable(True) + self.bugreportbtn.setChecked(False) + bugreport_button_size = hou.ui.scaledSize(21) + self.bugreportbtn.setProperty("flat", True) + self.bugreportbtn.setIcon(util.BUG_ICON) + self.bugreportbtn.setIconSize(QtCore.QSize( + bugreport_button_size, + bugreport_button_size + )) + + self.themebtn = self.ui.theme_btn + self.themebtn.setToolTip(la.TT_SETTINGS[self.themebtn.objectName()]) + self.themebtn.setCheckable(True) + self.themebtn.setChecked(False) + theme_button_size = hou.ui.scaledSize(27) + self.themebtn.setProperty("flat", True) + self.themebtn.setIcon(util.COLOR_ICON) + self.themebtn.setIconSize(QtCore.QSize( + theme_button_size, + theme_button_size + )) + + self.debuglevel = self.ui.debuglevel_cbx + for lvl in util.DEBUG_LEVEL: + self.debuglevel.addItem(str(lvl)) + self.debuglevel.setToolTip(la.TT_SETTINGS[self.debuglevel.objectName()]) + self.debugflag = self.ui.debugflag_chk + self.debugflag.setToolTip(la.TT_SETTINGS[self.debugflag.objectName()]) + self.debuglevel.setVisible(bc(self.settings[util.SETTINGS_KEYS[4]])) + self.debugflag.setVisible(bc(self.settings[util.SETTINGS_KEYS[4]])) + + self.savedata = self.ui.save_btn + self.savedata.setToolTip(la.TT_SETTINGS[self.savedata.objectName()]) + + self.discarddata = self.ui.discard_btn + self.discarddata.setToolTip(la.TT_SETTINGS[self.discarddata.objectName()]) + + # -------------------------------------------- sixthrow + # NOTE sixthrow --------------------------------------- + info_button_size = hou.ui.scaledSize(16) + self.hotkey_icon.setProperty("flat", True) + self.hotkey_icon.setIcon(util.INFO_ICON) + self.hotkey_icon.setIconSize(QtCore.QSize( + info_button_size, + info_button_size + )) + + # --------------------------------------------- connect + # NOTE connect ---------------------------------------- + self.hotkey_icon.clicked.connect(self.hotkeyicon_cb) + self.dbpath_btn.clicked.connect(self.dbpath_cb) + # self.cleardata.clicked.connect(self.cleardata_cb) + self.aboutbtn.clicked.connect(self.window_cb) + self.bugreportbtn.clicked.connect(self.window_cb) + self.themebtn.clicked.connect(self.window_cb) + self.savedata.clicked.connect(self.save_cb) + self.discarddata.clicked.connect(self.discard_cb) + + # -------------------------------------------- about_cb + # NOTE about_cb --------------------------------------- + self.settingslayout = self.ui.verticallayout + self.setLayout(self.ui.gridLayout) + + # ----------------------------------- Startup Functions + # NOTE Startup Functions ------------------------------ + self.updatecurrentvalues() + self.fieldsetup() + + # --------------------------------------------------------------- Functions + # SECTION Functions ------------------------------------------------------- + def closewindows(self): + for i in range(len(self.windowlist)): + if getattr(self, self.windowlist[i]).isVisible(): + getattr(self, self.windowlist[i]).close() + getattr(self, self.windowlist[i] + "btn").setChecked(False) + + # ----------------------------------------- mapposition + # NOTE mapposition ------------------------------------ + def mapposition(self, w, h, s): + parent = s.parent() + pos = parent.mapToGlobal(QtCore.QPoint(w, h)) + getattr(self, s.objectName()).setGeometry( + pos.x(), + pos.y() + parent.height(), + getattr(self, s.objectName()).width(), + getattr(self, s.objectName()).height()) + getattr(self, s.objectName()).show() + + # !SECTION Functions + + # --------------------------------------------------------------- Callbacks + # SECTION Callbacks ------------------------------------------------------- + # ------------------------------------------- window_cb + # The sender is the actual button, but the button is + # the same as the window instance so that both can be + # sent and accessed in methods via one variable. + # NOTE window_cb -------------------------------------- + def window_cb(self, toggled): + self.closewindows() + s = self.sender() + + if toggled is True and not getattr(self, s.objectName()).isVisible(): + self.mapposition(0, 0, s) if self.animatedsettings.isChecked() else self.mapposition(0, 0, s) + getattr(self, s.objectName()).initmenu() + else: + if s.objectName() in self.windowlist: + getattr(self, s.objectName()).close() + + # --------------------------------------- hotkeyicon_cb + # NOTE hotkeyicon_cb ---------------------------------- + def hotkeyicon_cb(self): + return + # self.settings['in_memory_db'] = self.in_memory_db.isChecked() + # print(self.settings['in_memory_db']) + + # ------------------------------------------- dbpath_cb + # NOTE dbpath_cb -------------------------------------- + def dbpath_cb(self): + path = os.path.normpath(self.database_path.text()).replace("\\", "/") + dbpath = hou.expandString(hou.ui.selectFile( + start_directory=os.path.dirname(path), + title="Save Database", + pattern="searcher.db", + file_type=hou.fileType.Clip, + default_value="searcher.db")) + if dbpath != "": + if not dbpath.endswith("searcher.db"): + dbpath = dbpath + "searcher.db" + self.database_path.setText((os.path.normpath(dbpath))) + + # ---------------------------------------- defaulthk_cb + # NOTE defaulthk_cb ----------------------------------- + def defaulthk_cb(self): + return + + # -------------------------------------------- test1_cb + # NOTE test1_cb --------------------------------------- + def test1_cb(self): + hkeys = [] + for i in range(len(util.HOTKEYLIST)): + result = hou.hotkeys.findConflicts("h", util.HOTKEYLIST[i]) + if result: + print("Confliction found: {}".format(result)) + else: + print("No Confliction: {}".format(result)) + hkeys.append(result) + print(hkeys) + + # --------------------------------------- cleardata_cb + # NOTE cleardata_cb ---------------------------------- + # def cleardata_cb(self): + # self.datahandler.cleardb() + + # --------------------------------------------- save_cb + # NOTE save_cb ---------------------------------------- + def save_cb(self): + if self.defaulthotkey.text() == "": + _ = hou.ui.displayMessage("Please enter a hotkey") + self.activateWindow() + self.defaulthotkey.setFocus() + self.canedit = True + else: + self.checkforchanges() + for i in range(len(util.SETTINGS_KEYS)): + if util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "bool": + self.settings[util.SETTINGS_KEYS[i]] = getattr(self, util.SETTINGS_KEYS[i]).isChecked() + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "text": + self.settings[util.SETTINGS_KEYS[i]] = getattr(self, util.SETTINGS_KEYS[i]).text() + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "intval": + self.settings[util.SETTINGS_KEYS[i]] = getattr(self, util.SETTINGS_KEYS[i]).value() + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "cbx": + self.settings[util.SETTINGS_KEYS[i]] = getattr(self, util.SETTINGS_KEYS[i]).currentText() + + if self.isdebug and self.isdebug.level in {"ALL"}: + print(self.settings) + + settings_data.savesettings(self.settings) + + if self.resetdb: + hou.session.DBCONNECTION = None + hou.session.DATABASE = None + self.resetdb = False + + if self.modifylayout: + self.parentwindow.sui.metricpos.setVisible( + self.settings[util.SETTINGS_KEYS[12]]) + + self.performcheck = False + self.closewindows() + + if self.animatedsettings.isChecked() and not self.waitforclose: + self.parentwindow.anim.start_animation(False) + self.isopened = True + elif self.waitforclose: + if self.bugreport.isVisible(): + self.bugreport.close() + self.close() + self.parentwindow.close() + else: + self.close() + + # ------------------------------------------ discard_cb + # NOTE discard_cb ------------------------------------- + def discard_cb(self): + self.closewindows() + + if self.settings[util.SETTINGS_KEYS[8]]: + self.parentwindow.anim.start_animation(False) + self.isopened = True + self.performcheck = True + else: + self.close() + + # !SECTION Callbacks + + # ----------------------------------------------------------------- Actions + # SECTION Actions --------------------------------------------------------- + # --------------------------------- updatecurrentvalues + # NOTE updatecurrentvalues ---------------------------- + def updatecurrentvalues(self): + for i in range(len(util.SETTINGS_KEYS)): + self.currentsettings[util.SETTINGS_KEYS[i]] = self.settings[util.SETTINGS_KEYS[i]] + if util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "bool": + getattr(self, util.SETTINGS_KEYS[i]).setChecked(bc(self.currentsettings[util.SETTINGS_KEYS[i]])) + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "text": + getattr(self, util.SETTINGS_KEYS[i]).setText(self.currentsettings[util.SETTINGS_KEYS[i]]) + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "intval": + getattr(self, util.SETTINGS_KEYS[i]).setValue(int(self.currentsettings[util.SETTINGS_KEYS[i]])) + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "cbx": + getattr(self, util.SETTINGS_KEYS[i]).setCurrentText(str(self.currentsettings[util.SETTINGS_KEYS[i]])) + + # ------------------------------------------ fieldsetup + # NOTE fieldsetup ------------------------------------- + def fieldsetup(self): + for i in range(len(util.SETTINGS_KEYS)): + if util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "bool": + getattr(self, util.SETTINGS_KEYS[i]).setChecked(bc(self.currentsettings[util.SETTINGS_KEYS[i]])) + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "text": + getattr(self, util.SETTINGS_KEYS[i]).setText(self.currentsettings[util.SETTINGS_KEYS[i]]) + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "intval": + getattr(self, util.SETTINGS_KEYS[i]).setValue(int(self.currentsettings[util.SETTINGS_KEYS[i]])) + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "cbx": + getattr(self, util.SETTINGS_KEYS[i]).setCurrentText(str(self.currentsettings[util.SETTINGS_KEYS[i]])) + try: + getattr(self, util.SETTINGS_KEYS[i]).installEventFilter(self) + except (AttributeError, TypeError): + pass + + if self.isdebug and self.isdebug.level in {"ALL"}: + print(self.currentsettings) + + # ------------------------------------- checkforchanges + # NOTE checkforchanges -------------------------------- + def checkforchanges(self): + if self.isdebug and self.isdebug.level in {"ALL"}: + print(len(util.SETTINGS_KEYS)) + for i in range(len(util.SETTINGS_KEYS)): + if self.isdebug and self.isdebug.level in {"ALL"}: + print(i) + if util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "bool": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Name: ", getattr(self, util.SETTINGS_KEYS[i]).objectName()) + print("Shown settings: ", getattr(self, util.SETTINGS_KEYS[i]).isChecked()) + print("Current settings: ", bc(self.currentsettings[util.SETTINGS_KEYS[i]])) + if getattr(self, util.SETTINGS_KEYS[i]).isChecked() != bc(self.currentsettings[util.SETTINGS_KEYS[i]]): + if util.SETTINGS_KEYS[i] == util.SETTINGS_KEYS[0]: + self.resetdb = True + elif util.SETTINGS_KEYS[i] == util.SETTINGS_KEYS[8]: + self.waitforclose = True + elif util.SETTINGS_KEYS[i] == util.SETTINGS_KEYS[12]: + self.modifylayout = True + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Offending item: ", i) + return True + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "text": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Name: ", getattr(self, util.SETTINGS_KEYS[i]).objectName()) + print("Shown settings: ", getattr(self, util.SETTINGS_KEYS[i]).text()) + print("Current settings: ", self.currentsettings[util.SETTINGS_KEYS[i]]) + if getattr(self, util.SETTINGS_KEYS[i]).text() != self.currentsettings[util.SETTINGS_KEYS[i]]: + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Offending item: ", i) + return True + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "intval": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Name: ", getattr(self, util.SETTINGS_KEYS[i]).objectName()) + print("Shown settings: ", getattr(self, util.SETTINGS_KEYS[i]).value()) + print("Current settings: ", self.currentsettings[util.SETTINGS_KEYS[i]]) + if getattr(self, util.SETTINGS_KEYS[i]).value() != int(self.currentsettings[util.SETTINGS_KEYS[i]]): + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Offending item: ", i) + return True + elif util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] == "cbx": + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Name: ", getattr(self, util.SETTINGS_KEYS[i]).objectName()) + print("Shown settings: ", getattr(self, util.SETTINGS_KEYS[i]).currentText()) + print("Current settings: ", str(self.currentsettings[util.SETTINGS_KEYS[i]])) + if getattr(self, util.SETTINGS_KEYS[i]).currentText() != str( + self.currentsettings[util.SETTINGS_KEYS[i]]): + if self.isdebug and self.isdebug.level in {"ALL"}: + print("Offending item: ", i) + return True + return False + + # ------------------------------------------- savecheck + # NOTE savecheck -------------------------------------- + def savecheck(self): + buttonindex = hou.ui.displayMessage( + "Save changes?", + buttons=('Save', 'Discard'), + default_choice=0, + title="Unsaved Changes:" + ) + if buttonindex == 0: + self.save_cb() + self.hkholder = "" + elif buttonindex == 1: + self.hkholder = "" + + # ------------------------------------ closeroutine + # NOTE closeroutine ------------------------------- + def closeroutine(self): + if self.performcheck: + if self.checkforchanges(): + self.savecheck() + if self.animatedsettings.isChecked() and not self.waitforclose: + self.closewindows() + self.parentwindow.anim.start_animation(False) + self.isopened = True + return True + elif self.waitforclose: + self.closewindows() + self.close() + self.parentwindow.close() + return True + else: + self.closewindows() + self.close() + + # !SECTION Actions + + # @formatter:off + def movesubwindows(self, pos, resize=False): + if self.about.isVisible(): + if resize: self.about.move(self.about.x() + pos.x(), self.about.y()) + else: self.about.move(self.about.x() + pos.x(), self.about.y() + pos.y()) + if self.bugreport.isVisible(): + if resize: self.bugreport.move(self.bugreport.x() + pos.x(), self.bugreport.y()) + else: self.bugreport.move(self.bugreport.x() + pos.x(), self.bugreport.y() + pos.y()) + if self.theme.isVisible(): + if resize: self.theme.move(self.theme.x() + pos.x(), self.theme.y()) + else: self.theme.move(self.theme.x() + pos.x(), self.theme.y() + pos.y()) + + # ------------------------------------------------------------- Events + # SECTION Events ----------------------------------------------------- + # ------------------------------------- addeventfilters + # NOTE addeventfilters -------------------------------- + def addeventfilters(self): + self.installEventFilter(self) + self.aboutbtn.installEventFilter(self) + self.themebtn.installEventFilter(self) + self.savedata.installEventFilter(self) + self.dbpath_btn.installEventFilter(self) + # self.cleardata.installEventFilter(self) + self.discarddata.installEventFilter(self) + self.bugreportbtn.installEventFilter(self) + self.ui.dbpath_lbl.installEventFilter(self) + self.ui.maxresults_lbl.installEventFilter(self) + self.ui.defaulthotkey_lbl.installEventFilter(self) + + # ---------------------------------- removeeventfilters + # NOTE removeeventfilters ----------------------------- + def removeeventfilters(self): + self.removeEventFilter(self) + self.aboutbtn.removeEventFilter(self) + self.themebtn.removeEventFilter(self) + self.savedata.removeEventFilter(self) + self.dbpath_btn.removeEventFilter(self) + # self.cleardata.removeEventFilter(self) + self.discarddata.removeEventFilter(self) + self.bugreportbtn.removeEventFilter(self) + self.ui.dbpath_lbl.removeEventFilter(self) + self.ui.maxresults_lbl.removeEventFilter(self) + self.ui.defaulthotkey_lbl.removeEventFilter(self) + + def eventFilter(self, obj, event): + event_type = event.type() + + # ------------------------------------------ Window + # NOTE Window ------------------------------------- + if event_type == QtCore.QEvent.WindowActivate: + self.addeventfilters() + self.ui.isopened = True + self.performcheck = True + + # ------------------------------------------- Mouse + # SECTION Mouse ----------------------------------- + # ----------------------- MouseButtonPress + # NOTE MouseButtonPress ------------------ + if event_type == QtCore.QEvent.MouseButtonPress: + if obj == self: + self.activateWindow() + + # -------------------- MouseButtonDblClick + # NOTE MouseButtonDblClick --------------- + if event_type == QtCore.QEvent.MouseButtonDblClick: + if obj == self.defaulthotkey: + self.hkholder = self.defaulthotkey.text() + self.defaulthotkey.setText("") + self.defaulthotkey.setPlaceholderText("Input key sequence") + self.canedit = True + + # ---------------------------------- Enter + # NOTE Enter ----------------------------- + if event_type == QtCore.QEvent.Enter: + self.parentwindow.checktooltip(obj) + + # ---------------------------------- Leave + # NOTE Leave ----------------------------- + if event_type == QtCore.QEvent.Leave: + self.parentwindow.checktooltip(obj, True) + + # -------------------------------- ToolTip + # NOTE ToolTip --------------------------- + if event_type == QtCore.QEvent.ToolTip: + return True + # !SECTION + + # ---------------------------------------- Keypress + # SECTION Keypress -------------------------------- + if event_type == QtCore.QEvent.KeyPress: + # ---------------------------------- Key_D + # NOTE Key_D ----------------------------- + if event.key() == QtCore.Qt.Key_D: + if obj != self.defaulthotkey: + if not self.debugflag.isVisible(): + self.debugflag.setVisible(True) + + # ----------------------------- Key_Escape + # NOTE Key_Escape ------------------------ + if event.key() == QtCore.Qt.Key_Escape: + if obj == self: + self.closeroutine() + return True + + # ----------------------------------- else + # NOTE else ------------------------------ + else: + if obj == self.defaulthotkey: + self.keyindex += 1 + self.keystring = hou.qt.qtKeyToString( + event.key(), + int(event.modifiers()), + event.text() + ) + if self.canedit: + if self.keystring not in ["Esc", "Backspace"]: + if self.defaulthotkey.hasFocus(): + self.KeySequence = QtGui.QKeySequence(self.keystring).toString() + self.defaulthotkey.setText(self.KeySequence) + if self.keystring in ["Esc", "Backspace"]: + self.defaulthotkey.setText(self.hkholder) + # !SECTION + + # -------------------------------------- Keyrelease + # SECTION Keyrelease ------------------------------ + if event_type == QtCore.QEvent.KeyRelease: + if event.key() == QtCore.Qt.Key_Escape: + return QtCore.QObject.eventFilter(self, obj, event) + else: + self.keyindex -= 1 + if self.keyindex == 0: + if self.defaulthotkey.text() == "": + self.defaulthotkey.setText(self.hkholder) + if self.defaulthotkey.text() != "": + self.canedit = False + # !SECTION + + # ------------------------------------------- Close + # NOTE Close -------------------------------------- + if event_type == QtCore.QEvent.Close: + self.ui.isopened = False + self.resetdb = False + self.parentwindow.opensettingstool.setChecked(False) + self.performcheck = True + if not self.parentwindow.isActiveWindow(): + self.parentwindow.activateWindow() + self.removeeventfilters() + + return QtCore.QObject.eventFilter(self, obj, event) + + # !SECTION Events + + +# class LinkLabel(QtWidgets.QLabel): +# def __init__(self, parent, text): +# super(LinkLabel, self).__init__(parent) +# +# self.setText(text) +# self.setTextFormat(Qt.RichText) +# self.setTextInteractionFlags(Qt.TextBrowserInteraction) +# self.setOpenExternalLinks(True) diff --git a/python3.7libs/searcher/searcher_settings_ui.py b/python3.7libs/searcher/searcher_settings_ui.py new file mode 100644 index 0000000..f9e9ad0 --- /dev/null +++ b/python3.7libs/searcher/searcher_settings_ui.py @@ -0,0 +1,269 @@ +# -*- coding: utf-8 -*- +import os +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtGui + from qtpy import QtCore + from qtpy import QtWidgets + +def bc(v): + return str(v).lower() in ("yes", "true", "t", "1") + + +class Ui_SearcherSettings(object): + def setupUi(self, SearcherSettings, width, height, animated): + self.width = width + self.height = height + self.animated = animated + + SearcherSettings.setObjectName("SearcherSettings") + SearcherSettings.setWindowModality(QtCore.Qt.NonModal) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(SearcherSettings.sizePolicy().hasHeightForWidth()) + SearcherSettings.setSizePolicy(sizePolicy) + SearcherSettings.setMinimumSize(QtCore.QSize(width, height)) + SearcherSettings.setBaseSize(QtCore.QSize(0, 0)) + + self.gridLayout = QtWidgets.QGridLayout(SearcherSettings) + self.gridLayout.setContentsMargins(-1, -1, -1, -1) + self.gridLayout.setObjectName("gridLayout") + self.verticallayout = QtWidgets.QVBoxLayout() + self.verticallayout.setObjectName("verticalLayout") + self.verticallayout.setSpacing(10) + + # ------------------------------------------------- headerrow + # NOTE headerrow -------------------------------------------- + self.headerrow = QtWidgets.QHBoxLayout() + self.headerrow.setObjectName("headerrow") + + self.projectTitle = QtWidgets.QLabel(SearcherSettings) + font = QtGui.QFont() + font.setPointSize(15) + self.projectTitle.setFont(font) + self.projectTitle.setAlignment(QtCore.Qt.AlignCenter) + self.projectTitle.setObjectName("projectTitle") + self.headerrow.addWidget(self.projectTitle) + + spaceritem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.headerrow.addItem(spaceritem) + + self.animatedsettings_chk = QtWidgets.QCheckBox(SearcherSettings) + self.animatedsettings_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + self.animatedsettings_chk.setObjectName("animatedsettings_chk") + self.headerrow.addWidget(self.animatedsettings_chk) + + self.windowsize_chk = QtWidgets.QCheckBox(SearcherSettings) + self.windowsize_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + self.windowsize_chk.setObjectName("windowsize_chk") + self.headerrow.addWidget(self.windowsize_chk) + self.verticallayout.addLayout(self.headerrow) + + self.line = QtWidgets.QFrame(SearcherSettings) + self.line.setFrameShape(QtWidgets.QFrame.HLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.verticallayout.addWidget(self.line) + + # ------------------------------------------------- secondrow + # NOTE Second Row ------------------------------------------- + self.secondrow = QtWidgets.QHBoxLayout() + self.secondrow.setObjectName("secondrow") + + # self.lang_cbox = QtWidgets.QComboBox(SearcherSettings) + # self.lang_cbox.setObjectName("lang_cbox") + # self.lang_cbox.addItem("") + # self.secondrow.addWidget(self.lang_cbox) + + spaceritem = QtWidgets.QSpacerItem( + 40, 20, + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Minimum + ) + self.secondrow.addItem(spaceritem) + + self.maxresults_lbl = QtWidgets.QLabel(SearcherSettings) + self.maxresults_lbl.setObjectName("maxresults_lbl") + self.secondrow.addWidget(self.maxresults_lbl) + self.maxresults_txt = QtWidgets.QSpinBox(SearcherSettings) + self.maxresults_txt.setMinimum(1) + self.maxresults_txt.setMaximum(9999) + self.maxresults_txt.setObjectName("maxresults_txt") + self.secondrow.addWidget(self.maxresults_txt) + + self.inmemory_chk = QtWidgets.QCheckBox(SearcherSettings) + self.inmemory_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + self.inmemory_chk.setTristate(False) + self.inmemory_chk.setObjectName("inmemory_chk") + self.secondrow.addWidget(self.inmemory_chk) + + self.verticallayout.addLayout(self.secondrow) + + # -------------------------------------------------- thirdrow + # NOTE Third Row -------------------------------------------- + self.thirdrow = QtWidgets.QHBoxLayout() + self.thirdrow.setObjectName("thirdrow") + + self.defaulthotkey_lbl = QtWidgets.QLabel(SearcherSettings) + self.defaulthotkey_lbl.setObjectName("defaulthotkey_lbl") + self.thirdrow.addWidget(self.defaulthotkey_lbl) + + self.defaulthotkey_txt = QtWidgets.QLineEdit(SearcherSettings) + self.defaulthotkey_txt.setToolTip("") + self.defaulthotkey_txt.setReadOnly(True) + self.defaulthotkey_txt.setObjectName("defaulthotkey_txt") + self.thirdrow.addWidget(self.defaulthotkey_txt) + + self.hotkey_icon = QtWidgets.QToolButton(SearcherSettings) + self.hotkey_icon.setPopupMode(QtWidgets.QToolButton.InstantPopup) + self.hotkey_icon.setObjectName("hotkey_icon") + self.thirdrow.addWidget(self.hotkey_icon) + self.verticallayout.addLayout(self.thirdrow) + + # ------------------------------------------------- fourthrow + # NOTE Fourth Row ------------------------------------------- + self.fourthrow = QtWidgets.QHBoxLayout() + self.fourthrow.setObjectName("fourthrow") + + self.dbpath_lbl = QtWidgets.QLabel(SearcherSettings) + self.dbpath_lbl.setObjectName("dbpath_lbl") + self.fourthrow.addWidget(self.dbpath_lbl) + + self.databasepath_txt = QtWidgets.QLineEdit(SearcherSettings) + self.databasepath_txt.setObjectName("databasepath_txt") + self.fourthrow.addWidget(self.databasepath_txt) + + self.dbpath_icon = QtWidgets.QToolButton(SearcherSettings) + self.dbpath_icon.setObjectName("dbpath_icon") + self.fourthrow.addWidget(self.dbpath_icon) + + self.verticallayout.addLayout(self.fourthrow) + + # -------------------------------------------------- fifthrow + # NOTE Fifth Row -------------------------------------------- + self.fifthrow = QtWidgets.QHBoxLayout() + self.fifthrow.setObjectName("fifthrow") + + # self.maint_lbl = QtWidgets.QLabel(SearcherSettings) + # self.maint_lbl.setObjectName("maint_lbl") + # self.fifthrow.addWidget(self.maint_lbl) + + # self.metrics_chk = QtWidgets.QCheckBox(SearcherSettings) + # self.metrics_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + # self.metrics_chk.setTristate(False) + # self.metrics_chk.setObjectName("metrics_chk") + # self.fifthrow.addWidget(self.metrics_chk) + + # self.cleardata_btn = QtWidgets.QPushButton(SearcherSettings) + # self.cleardata_btn.setObjectName("cleardata_btn") + # self.fifthrow.addWidget(self.cleardata_btn) + + # self.verticallayout.addLayout(self.fifthrow) + + # ---------------------------------------------------- Spacer + self.line2 = QtWidgets.QFrame(SearcherSettings) + self.line2.setFrameShape(QtWidgets.QFrame.HLine) + self.line2.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line2.setObjectName("line2") + self.verticallayout.addWidget(self.line2) + # ---------------------------------------------------- Spacer + + # -------------------------------------------------- sixthrow + # NOTE Sixth Row -------------------------------------------- + self.sixthrow = QtWidgets.QHBoxLayout() + self.sixthrow.setObjectName("sixthrow") + + self.about_btn = QtWidgets.QToolButton(SearcherSettings) + self.about_btn.setObjectName("about") + self.sixthrow.addWidget(self.about_btn) + + self.bug_btn = QtWidgets.QToolButton(SearcherSettings) + self.bug_btn.setObjectName("bugreport") + self.sixthrow.addWidget(self.bug_btn) + + self.theme_btn = QtWidgets.QToolButton(SearcherSettings) + self.theme_btn.setObjectName("theme") + self.sixthrow.addWidget(self.theme_btn) + + spacerItem1 = QtWidgets.QSpacerItem(40, 25, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.sixthrow.addItem(spacerItem1) + + + self.metrics_chk = QtWidgets.QCheckBox(SearcherSettings) + self.metrics_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + self.metrics_chk.setTristate(False) + self.metrics_chk.setObjectName("metrics_chk") + self.sixthrow.addWidget(self.metrics_chk) + + + self.debuglevel_cbx = QtWidgets.QComboBox(SearcherSettings) + self.debuglevel_cbx.setObjectName("debuglevel_cbx") + self.sixthrow.addWidget(self.debuglevel_cbx) + + self.debugflag_chk = QtWidgets.QCheckBox(SearcherSettings) + self.debugflag_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + self.debugflag_chk.setObjectName("debugflag_chk") + self.sixthrow.addWidget(self.debugflag_chk) + + self.discard_btn = QtWidgets.QPushButton(SearcherSettings) + self.discard_btn.setObjectName("discard_btn") + self.sixthrow.addWidget(self.discard_btn) + + self.save_btn = QtWidgets.QPushButton(SearcherSettings) + self.save_btn.setObjectName("save_btn") + self.sixthrow.addWidget(self.save_btn) + + self.verticallayout.addLayout(self.sixthrow) + + if not self.animated: + self.gridLayout.addLayout(self.verticallayout, 1, 0, 1, 1) + + # ----------------------------------------------------------- + self.retranslateUi(SearcherSettings) + QtCore.QMetaObject.connectSlotsByName(SearcherSettings) + + def retranslateUi(self, SearcherSettings): + _translate = QtCore.QCoreApplication.translate + SearcherSettings.setWindowTitle(_translate("SearcherSettings", "Form")) + + # ------------------------------------------------- headerrow + self.projectTitle.setText(_translate("SearcherSettings", "Settings")) + self.animatedsettings_chk.setText(_translate("SearcherSettings", "Use Animated Menus:")) + self.windowsize_chk.setText(_translate("SearcherSettings", "Remember Search Window Size")) + + # ------------------------------------------------- secondrow + self.maxresults_lbl.setText(_translate("SearcherSettings", "Maximum Search Results")) + self.inmemory_chk.setText(_translate("SearcherSettings", "Use In-Memory Database")) + + # -------------------------------------------------- thirdrow + # self.label_3.setText(_translate("SearcherSettings", "Language:")) + # self.lang_cbox.setCurrentText(_translate("SearcherSettings", "English")) + # self.lang_cbox.setItemText(0, _translate("SearcherSettings", "English")) + self.defaulthotkey_lbl.setText(_translate("SearcherSettings", "Hotkey to use for opening unassigned items: ")) + self.defaulthotkey_txt.setPlaceholderText(_translate("SearcherSettings", "Double Click")) + self.hotkey_icon.setText(_translate("SearcherSettings", "...")) + + # ------------------------------------------------- fourthrow + self.dbpath_lbl.setText(_translate("SearcherSettings", "Database location: ")) + self.dbpath_icon.setText(_translate("SearcherSettings", "...")) + + # -------------------------------------------------- fifthrow + # self.maint_lbl.setText(_translate("SearcherSettings", "Maintenance utilities:")) + # self.cleardata_btn.setText(_translate("SearcherSettings", "Clear Data")) + + # ------------------------------------------------- sixthrow + self.about_btn.setText(_translate("SearcherSettings", "...")) + self.bug_btn.setText(_translate("SearcherSettings", "...")) + self.theme_btn.setText(_translate("SearcherSettings", "...")) + self.metrics_chk.setText(_translate("SearcherSettings", "Metrics")) + self.debugflag_chk.setText(_translate("SearcherSettings", "Debug Mode")) + self.discard_btn.setText(_translate("SearcherSettings", "Discard")) + self.save_btn.setText(_translate("SearcherSettings", "Save")) + diff --git a/python3.7libs/searcher/searcher_ui.py b/python3.7libs/searcher/searcher_ui.py new file mode 100644 index 0000000..53bd43a --- /dev/null +++ b/python3.7libs/searcher/searcher_ui.py @@ -0,0 +1,284 @@ +from __future__ import print_function +from __future__ import absolute_import + +import os +import sys +from searcher import HelpButton +from searcher import language_en as la + +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtGui + from qtpy import QtCore + from qtpy import QtWidgets + + +# noinspection PyAttributeOutsideInit +class Ui_Searcher(object): + def setupUi(self, Searcher, animated): + self.animated = animated + Searcher.setObjectName("Searcher") + Searcher.setWindowModality(QtCore.Qt.NonModal) + Searcher.setStyleSheet(u"background-color: rgb(42,42,42); border: 0px solid black") + + self.mainlayout = QtWidgets.QVBoxLayout() + self.gridLayout = QtWidgets.QGridLayout() + self.gridLayout.setSpacing(0) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setSpacing(0) + + self.titlerow = QtWidgets.QHBoxLayout() + self.titlerow.setSpacing(5) + + self.titlespacer1 = QtWidgets.QSpacerItem( + 8, 0, + QtWidgets.QSizePolicy.Fixed, + QtWidgets.QSizePolicy.Minimum + ) + + # ------------------------------------------ Header + # NOTE Header ------------------------------------- + self.searcherlbl = QtWidgets.QLabel("Searcher") + font = QtGui.QFont() + font.setPointSize(15) + self.searcherlbl.setFont(font) + self.searcherlbl.setAlignment(QtCore.Qt.AlignCenter) + + self.titlespacer2 = QtWidgets.QSpacerItem( + 40, 30, + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Minimum + ) + + self.expander = QtWidgets.QToolButton() + self.expander.setObjectName("expander") + + self.metricpos = QtWidgets.QToolButton() + self.metricpos.setObjectName("metricpos") + + self.contexttoggle = QtWidgets.QPushButton() + self.contexttoggle.setObjectName("contexttoggle") + + self.helpButton = HelpButton.HelpButton("main", la.TT_MW['helpButton'], 16, Searcher) + self.helpButton.setObjectName("helpButton") + + self.pinwindow_btn = QtWidgets.QToolButton() + self.pinwindow_btn.setObjectName("pinwindow") + + self.opensettings_btn = QtWidgets.QToolButton() + self.opensettings_btn.setObjectName("opensettingstool") + + self.titlespacer3 = QtWidgets.QSpacerItem( + 8, 0, + QtWidgets.QSizePolicy.Fixed, + QtWidgets.QSizePolicy.Minimum + ) + + # ----------------------------------- Search Filter + # NOTE Search Filter ------------------------------ + self.searchrow = QtWidgets.QHBoxLayout() + self.searchrow.setSpacing(0) + self.frame = QtWidgets.QFrame() + searchframe_details = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Preferred + ) + searchframe_details.setHorizontalStretch(0) + searchframe_details.setVerticalStretch(0) + searchframe_details.setHeightForWidth( + self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(searchframe_details) + self.frame.setMinimumSize(QtCore.QSize(20, 20)) + self.frame.setMaximumSize(QtCore.QSize(500, 200)) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Plain) + self.frame.setStyleSheet(u"background-color: rgb(19, 19, 19); color: rgb(19, 19, 19);") + self.searchfilter_btn = QtWidgets.QToolButton(self.frame) + self.searchfilter_btn.setObjectName("searchfilter") + self.searchfilter_btn.setGeometry(QtCore.QRect(0, 0, 36, 36)) + self.searchfilter_btn.setBaseSize(QtCore.QSize(30, 30)) + self.searchfilter_btn.setStyleSheet(u"background-color: rgb(19, 19, 19);") + self.searchfilter_btn.setArrowType(QtCore.Qt.NoArrow) + self.searchfilter_btn.setParent(self.frame) + + # -------------------------------------- Search Box + # NOTE Search Box --------------------------------- + self.searchbox_txt = QtWidgets.QLineEdit() + self.searchbox_txt.setObjectName("searchbox") + searchbox_details = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Minimum + ) + searchbox_details.setHorizontalStretch(99) + searchbox_details.setVerticalStretch(0) + # searchbox_details.setHeightForWidth( + # self.searchbox_txt.sizePolicy().hasHeightForWidth()) + self.searchbox_txt.setSizePolicy(searchbox_details) + self.searchbox_txt.setMinimumSize(QtCore.QSize(50, 0)) + self.searchbox_txt.setMouseTracking(False) + self.searchbox_txt.setStyleSheet(u"background-color: rgb(19, 19, 19);") + self.searchbox_txt.setFrame(False) + + # ------------------------------------ Results Tree + # NOTE Results Tree ------------------------------- + self.searchresults_tree = QtWidgets.QTreeWidget() + self.searchresults_tree.setObjectName("searchresultstree") + + # Header --------- + __qtreewidgetitem = QtWidgets.QTreeWidgetItem() + __qtreewidgetitem.setText(0, u"1") + resultstree_header = QtGui.QFont() + resultstree_header.setPointSize(9) + __qtreewidgetitem.setFont(0, resultstree_header) + self.searchresults_tree.setHeaderItem(__qtreewidgetitem) + + resultstree_details = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Preferred, + QtWidgets.QSizePolicy.Expanding + ) + resultstree_details.setHorizontalStretch(0) + resultstree_details.setVerticalStretch(0) + self.searchresults_tree.setSizePolicy(resultstree_details) + + resultstree_font = QtGui.QFont() + resultstree_font.setPointSize(9) + self.searchresults_tree.setFont(resultstree_font) + + self.searchresults_tree.setMouseTracking(False) + self.searchresults_tree.setFocusPolicy(QtCore.Qt.NoFocus) + self.searchresults_tree.setFrameShadow(QtWidgets.QFrame.Sunken) + self.searchresults_tree.setLineWidth(0) + + self.searchresults_tree.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) + self.searchresults_tree.setAlternatingRowColors(True) + self.searchresults_tree.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) + self.searchresults_tree.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) + + # -------------------------------------- Info Panel + # NOTE Info Panel --------------------------------- + self.infobar = QtWidgets.QHBoxLayout() + self.infobar.setObjectName("infobar") + self.infobargrid = QtWidgets.QGridLayout() + self.infobargrid.setObjectName("infobargrid") + + # -------------------------------------- Info Panel + # NOTE Info Panel --------------------------------- + self.info_lbl = QtWidgets.QLabel() + self.infolbl_font = QtGui.QFont() + self.infolbl_font.setPointSize(9) + self.infolbl_font.setBold(False) + self.infolbl_font.setWeight(40) + self.info_lbl.setFont(self.infolbl_font) + self.info_lbl.setStyleSheet( + u"background-color: rgba(11, 11, 11, 0); border-bottom: 1px solid rgb(100, 100, 100);") + self.info_lbl.setMargin(3) + self.info_lbl.setIndent(5) + + # -------------------------------------- Info Panel + # NOTE Info Panel --------------------------------- + self.overlay = overlayLabel(self.info_lbl) + self.overlay.setFont(self.infolbl_font) + self.overlay.setStyleSheet(u"background-color: rgb(11, 11, 11); border-bottom: 1px solid rgb(100, 100, 100); ") + self.overlay.setMargin(3) + self.overlay.setIndent(5) + + # -------------------------------------- Info Panel + # NOTE Info Panel --------------------------------- + self.treetotal_lbl = QtWidgets.QLabel() + self.treetotal_lbl.setObjectName("treetotal_lbl") + # Size ---------- + treetotal_size = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) + treetotal_size.setHorizontalStretch(0) + treetotal_size.setVerticalStretch(0) + treetotal_size.setHeightForWidth(self.treetotal_lbl.sizePolicy().hasHeightForWidth()) + self.treetotal_lbl.setSizePolicy(treetotal_size) + self.treetotal_lbl.setMinimumSize(QtCore.QSize(160, 0)) + self.treetotal_lbl.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) + + # Style --------- + self.treetotallbl_font = QtGui.QFont() + self.treetotallbl_font.setPointSize(9) + self.treetotallbl_font.setBold(False) + self.treetotallbl_font.setWeight(50) + self.treetotal_lbl.setFont(self.treetotallbl_font) + self.treetotal_lbl.setStyleSheet( + u"background-color: rgb(11, 11, 11); border-bottom: 1px solid rgb(100, 100, 100); ") + self.treetotal_lbl.setMargin(3) + self.treetotal_lbl.setIndent(5) + + # ------------------------------------------ Layout + # NOTE Layout ------------------------------------- + self.titlerow.addItem(self.titlespacer1) + self.titlerow.addWidget(self.searcherlbl) + self.titlerow.addItem(self.titlespacer2) + self.titlerow.addWidget(self.expander) + self.titlerow.addWidget(self.metricpos) + self.titlerow.addWidget(self.contexttoggle) + self.titlerow.addWidget(self.helpButton) + self.titlerow.addWidget(self.pinwindow_btn) + self.titlerow.addWidget(self.opensettings_btn) + self.titlerow.addItem(self.titlespacer3) + self.verticalLayout.addLayout(self.titlerow) + + # self.searchrow.addWidget(self.frame) + self.searchgrid = QtWidgets.QGridLayout() + self.searchgrid.addWidget(self.frame, 1, 0, 1, 1) + self.searchgrid.addWidget(self.searchfilter_btn, 1, 0, 1, 1) + self.searchgrid.addWidget(self.searchbox_txt, 1, 1, 1, 1) + self.searchrow.addLayout(self.searchgrid) + self.verticalLayout.addLayout(self.searchrow) + + self.verticalLayout.addWidget(self.searchresults_tree) + self.gridLayout.addLayout(self.verticalLayout, 1, 0, 1, 1) + + self.infobargrid.addWidget(self.overlay, 1, 0, 1, 1) + self.infobargrid.addWidget(self.info_lbl, 1, 0, 1, 1) + self.infobargrid.addWidget(self.treetotal_lbl, 1, 1, 1, 1) + self.infobar.addLayout(self.infobargrid) + self.gridLayout.addLayout(self.infobar, 3, 0, 1, 1) + + self.mainlayout.setContentsMargins(0, 0, 0, 0) + + # --------------------------------------- ResizeHandles + # NOTE ResizeHandles ---------------------------------- + self.leftresize = QtWidgets.QSizeGrip(self.info_lbl) + self.leftresize.setObjectName("resizeleft") + self.leftresize.setMaximumSize(QtCore.QSize(25, 25)) + self.leftresize.setStyleSheet(u"color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);") + pos = self.info_lbl.mapToGlobal( + QtCore.QPoint(-3, 0)) + self.leftresize.setGeometry( + pos.x(), + pos.y(), + self.leftresize.width(), + self.leftresize.height() + ) + + self.rightresize = QtWidgets.QSizeGrip(self.treetotal_lbl) + self.rightresize.setMaximumSize(QtCore.QSize(25, 25)) + self.rightresize.setObjectName("resizeright") + self.rightresize.setStyleSheet(u"color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);") + pos = self.treetotal_lbl.mapToGlobal( + QtCore.QPoint(138, 0)) + self.rightresize.setGeometry( + pos.x(), + pos.y(), + self.rightresize.width(), + self.rightresize.height() + ) + self.vlayout = self.gridLayout + # self.mainlayout.addLayout(self.gridLayout) + + +class overlayLabel(QtWidgets.QLabel): + def __init__(self, parent=None): + super(overlayLabel, self).__init__(parent) + self.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) diff --git a/python3.7libs/searcher/searchersetup.py b/python3.7libs/searcher/searchersetup.py new file mode 100644 index 0000000..06c3250 --- /dev/null +++ b/python3.7libs/searcher/searchersetup.py @@ -0,0 +1,465 @@ +from __future__ import print_function +from __future__ import absolute_import + +from searcher import settings_data +from searcher import util +from searcher import platformselect +from searcher import ptime as ptime +from searcher import language_en as la + +from peewee import * +from peewee import SQL +from playhouse.sqlite_ext import SqliteExtDatabase, RowIDField, FTS5Model, SearchField +# from playhouse.apsw_ext import APSWDatabase +import inspect +import threading +import time +import hou +import hdefereval as hd +import os +import sys + +# info +__author__ = "instance.id" +__copyright__ = "2020 All rights reserved." +__status__ = "Release Candidate" + +# current_file_path = os.path.abspath( +# inspect.getsourcefile(lambda: 0) +# ) + +def get_platform(): + return getattr(hou.session, "PLATFORM", None) + + +def get_settings(): + return getattr(hou.session, "SETTINGS", None) + + +def get_dbconnection(): + return getattr(hou.session, "DBCONNECTION", None) + + +# scriptpath = os.path.dirname(current_file_path) +dbfile = "searcher.db" +dbpath = os.path.join( + hou.homeHoudiniDirectory(), 'Searcher', dbfile +) + +hou.session.SETTINGS = {} +hou.session.DBCONNECTION = DatabaseProxy() +db = DatabaseProxy() + + +# --------------------------------------------------------- DatabaseModels +# SECTION DatabaseModels ------------------------------------------------- +# ------------------------------------------------ Settings +# NOTE Settings ------------------------------------------- +class Settings(Model): + id = IntegerField(unique=True) + indexvalue = IntegerField() + defaulthotkey = TextField() + searchdescription = IntegerField() + searchprefix = IntegerField() + searchcurrentcontext = IntegerField() + lastused = TextField() + + class Meta: + table_name = 'settings' + database = db + + +# ------------------------------------------------ HContext +# NOTE HContext ------------------------------------------- +class HContext(Model): + id = AutoField() + context = TextField(unique=True) + title = TextField() + description = TextField() + + class Meta: + table_name = 'hcontext' + database = db + + +# # ------------------------------------------- HContextIndex +# # NOTE HContextIndex -------------------------------------- +# class HContextIndex(FTS5Model): +# # rowid = RowIDField() +# context = SearchField() +# title = SearchField() +# description = SearchField() + +# class Meta: +# database = db +# options = {'prefix': [2, 3], 'tokenize': 'porter'} + +# ------------------------------------------------- Hotkeys +# NOTE Hotkeys -------------------------------------------- +class Hotkeys(Model): + hotkey_symbol = CharField(unique=True) + label = CharField() + description = TextField() + assignments = TextField() + context = TextField() + + class Meta: + table_name = 'hotkeys' + database = db + + +# -------------------------------------------- HotkeysIndex +# NOTE HotkeysIndex --------------------------------------- +class HotkeysIndex(FTS5Model): + # rowid = RowIDField() + hotkey_symbol = SearchField(unindexed=True) + label = SearchField() + description = SearchField() + assignments = SearchField(unindexed=True) + context = SearchField(unindexed=True) + + class Meta: + # table_name = 'hotkeysindex' + database = db + options = {'prefix': [2, 3], 'tokenize': 'porter'} + + +# !SECTION DatabaseModels + +def create_tables(dbc): + dbc.create_tables([Settings, HContext, Hotkeys, HotkeysIndex]) + + +def worker(): + hd.executeInMainThreadWithResult(updatecontext) + + +def py_unique(data): + return list(set(data)) + + +# ------------------------------------------------- getdata +# NOTE getdata -------------------------------------------- +def getdata(): + rval = [] + contextdata = [] + hotkeydata = [] + + def getcontexts(r, context_symbol, root): + keys = None + branches = hou.hotkeys.contextsInContext(context_symbol) + for branch in branches: + branch_path = "%s/%s" % (r, branch['label']) + contextdata.append({ + 'context': branch['symbol'], + 'title': branch['label'], + 'description': branch['help'] + }) + commands = hou.hotkeys.commandsInContext(branch['symbol']) + for command in commands: + keys = hou.hotkeys.assignments(command['symbol']) + ctx = command['symbol'].rsplit('.', 1) + hotkeydata.append({ + 'hotkey_symbol': command['symbol'], + 'label': command['label'], + 'description': command['help'], + 'assignments': " ".join(keys), + 'context': ctx[0] + }) + getcontexts(branch_path, branch['symbol'], root) + + getcontexts("", "", rval) + return contextdata, hotkeydata + + +# -------------------------------------------- initialsetup +# NOTE initialsetup --------------------------------------- +def initialsetup(cur): + currentidx = hou.hotkeys.changeIndex() + chindex = getchangeindex(cur) + + if len(chindex) == 0: + chindex = int(currentidx) + updatechangeindex(chindex, True) + updatedataasync() + if hou.isUIAvailable(): + try: + hou.ui.setStatusMessage( + la.MESSAGES['initialsetup1'], severity=hou.severityType.Message) + except: + print(la.MESSAGES['initialsetup1']) + else: + print(la.MESSAGES['initialsetup1']) + else: + chindex = int(chindex[0][0]) + + if int(currentidx) != chindex: + getlastusedhk(cur) + updatedataasync() + updatechangeindex(int(currentidx)) + + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + la.MESSAGES['initialsetup2'], severity=hou.severityType.Message) + + +# --------------------------------------------------------------- Retrieve +# SECTION Retrieve ------------------------------------------------------- +# ------------------------------------------ getchangeindex +# NOTE getchangeindex ------------------------------------- +def getchangeindex(cur): + try: + cur.execute("SELECT indexvalue FROM settings") + result = cur.fetchall() + return result + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.DBERRORMSG['getchangeindex'] + str(e)), severity=hou.severityType.Warning) + else: + print(la.DBERRORMSG['getchangeindex'] + str(e)) + + +# ------------------------------------------- getlastusedhk +# NOTE getlastusedhk -------------------------------------- +def getlastusedhk(cur): + settingdata = get_settings() + lastkey = settingdata[util.SETTINGS_KEYS[11]] + try: + if str(lastkey) != "": + lasthk = str(lastkey).split(' ') + hkcheck = hou.hotkeys.assignments(str(lasthk[0])) + + if len(hkcheck) is 0: + settingdata[util.SETTINGS_KEYS[11]] = "" + settings_data.savesettings(settingdata) + return + + rmresult = hou.hotkeys.removeAssignment(str(lasthk[0]).strip(), str(lasthk[1]).strip()) + if rmresult: + hkcheck = hou.hotkeys.assignments(str(lasthk[0])) + hou.hotkeys.saveOverrides() + if len(hkcheck) is 0: + settingdata[util.SETTINGS_KEYS[11]] = "" + settings_data.savesettings(settingdata) + currentidx = hou.hotkeys.changeIndex() + updatechangeindex(int(currentidx)) + else: + hou.hotkeys.clearAssignments(str(lasthk[0])) + hou.hotkeys.saveOverrides() + hkcheck = hou.hotkeys.assignments(str(lasthk[0])) + if len(hkcheck) is 0: + settingdata[util.SETTINGS_KEYS[11]] = "" + settings_data.savesettings(settingdata) + currentidx = hou.hotkeys.changeIndex() + updatechangeindex(int(currentidx)) + else: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.DBERRORMSG['getlastusedhk3']), severity=hou.severityType.Warning) + else: + print(la.DBERRORMSG['getlastusedhk3']) + else: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.DBERRORMSG['getlastusedhk2']), severity=hou.severityType.Warning) + else: + print(la.DBERRORMSG['getlastusedhk2']) + + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.DBERRORMSG['getlastusedhk1'] + str(e)), severity=hou.severityType.Warning) + else: + print(la.DBERRORMSG['getlastusedhk1'] + str(e)) + + +# !SECTION + +# ----------------------------------------------------------------- Update +# SECTION Update --------------------------------------------------------- +# ------------------------------------------------ dbupdate +# NOTE dbupdate ------------------------------------------- +def dbupdate(cur): + currentidx = hou.hotkeys.changeIndex() + chindex = getchangeindex(cur) + + if int(currentidx) != chindex: + getlastusedhk(cur) + updatedataasync() + updatechangeindex(int(currentidx)) + + +# ----------------------------------------- updatedataasync +# NOTE updatedataasync ------------------------------------ +def updatedataasync(): + thread = threading.Thread(target=worker) + thread.daemon = True + thread.start() + + +# --------------------------------------- updatechangeindex +# NOTE updatechangeindex ---------------------------------- +def updatechangeindex(indexval, new=False): + try: + if new is True: + defaultkey = "" + for i in range(len(util.HOTKEYLIST)): + result = hou.hotkeys.findConflicts("h", util.HOTKEYLIST[i]) + if not result: + defaultkey = util.HOTKEYLIST[i] + + Settings.insert( + indexvalue=indexval, + defaulthotkey=defaultkey, + searchdescription=0, + searchprefix=0, + searchcurrentcontext=0, + lastused="", + id=1).execute() + else: + Settings.update(indexvalue=indexval).where( + Settings.id == 1).execute() + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.DBERRORMSG['updatechangeindex'] + str(e)), severity=hou.severityType.Warning) + else: + print(la.DBERRORMSG['updatechangeindex'] + str(e)) + + +# ------------------------------------------- updatecontext +# NOTE updatecontext -------------------------------------- +def updatecontext(debug=False): + try: + cleardatabase() + ctxdata, hkeydata = getdata() + with db.atomic(): + for data_dict in ctxdata: + HContext.replace_many(data_dict).execute() + with db.atomic(): + for idx in hkeydata: + Hotkeys.replace_many(idx).execute() + HotkeysIndex.replace_many(idx).execute() + + except(AttributeError, TypeError) as e: + hou.ui.setStatusMessage( + (la.DBERRORMSG['updatecontext'] + str(e)), severity=hou.severityType.Warning) + + +# endregion + +# ------------------------------------------- cleardatabase +# NOTE cleardatabase -------------------------------------- +def cleardatabase(): + try: + delhk = "DELETE FROM hotkeys" + delctx = "DELETE FROM hcontext" + delhkindex = "DELETE FROM hotkeysindex" + db.cursor().execute(delhk) + db.cursor().execute(delctx) + db.cursor().execute(delhkindex) + result = db.cursor().fetchall() + return result + + except(AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.DBERRORMSG['cleardatabase'] + str(e)), severity=hou.severityType.Warning) + else: + print(la.DBERRORMSG['cleardatabase'] + str(e)) + + +# !SECTION + +def contextsetup(): + searcher_context = "h.tool" + hou.hotkeys.addContext(searcher_context, "Searcher", "These keys apply to Searcher operations") + + open_symbol = searcher_context + ":searcher::searcher" + hou.hotkeys.addCommand( + open_symbol, + "Searcher", + "Open the main Searcher interface window", + ["Ctrl+`"] + ) + + +def deferaction(action, val): + hd.executeDeferred(action, val) + + +def checklasthk(cur): + getlastusedhk(cur) + + +def main(): + platform = platformselect.get_platform() + + if not os.path.exists(settings_data.searcher_path): + os.mkdir(settings_data.searcher_path) + if not os.path.isfile(settings_data.searcher_settings): + if platform == "unix": + os.system(("touch %s" % settings_data.searcher_settings)) + else: + open(settings_data.searcher_settings, "wt").close() + settings_data.createdefaults(platform) + + hou.session.SETTINGS = settings_data.loadsettings() + settingdata = get_settings() + + isdebug = util.Dbug( + settingdata[util.SETTINGS_KEYS[4]], + str(settingdata[util.SETTINGS_KEYS[10]]), + settingdata[util.SETTINGS_KEYS[12]], + settingdata[util.SETTINGS_KEYS[13]], + ) + + inmemory = (settingdata[util.SETTINGS_KEYS[0]]) + if inmemory: + val = ':memory:' + else: + val = str(settingdata[util.SETTINGS_KEYS[1]]) + + db.initialize( + SqliteExtDatabase( + val, + pragmas=( + ("cache_size", -1024 * 64), + ("journal_mode", "off"), + ("temp_store", "memory"), + ("synchronous", 0) + ))) + + hou.session.DBCONNECTION = db + dbc = get_dbconnection() + + time1 = ptime.time() + if inmemory: + create_tables(dbc) + cur = dbc.cursor() + initialsetup(cur) + else: + if not os.path.isfile(settingdata[util.SETTINGS_KEYS[1]]): + create_tables(dbc) + cur = dbc.cursor() + deferaction(initialsetup, cur) + else: + cur = dbc.cursor() + deferaction(dbupdate, cur) + + time2 = ptime.time() + + contextsetup() + + if isdebug and isdebug.level in {"TIMER", "ALL"}: + res = ((time2 - time1) * 1000.0) + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + ('Startup took %0.4f ms' % res), severity=hou.severityType.Message) + else: + print('Startup took %0.4f ms' % res) + + +if __name__ == '__main__': + main() diff --git a/python3.7libs/searcher/settings_data.py b/python3.7libs/searcher/settings_data.py new file mode 100644 index 0000000..4c4a353 --- /dev/null +++ b/python3.7libs/searcher/settings_data.py @@ -0,0 +1,100 @@ +# region Imports +from __future__ import print_function +from __future__ import absolute_import + +from searcher import util +from searcher import language_en as la + +import os +import hou + +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.') + 1:]) + from hutil.Qt import QtCore + +# ------------------------------------------------------ Setting Paths +# SECTION Setting Paths ---------------------------------------------- +scriptpath = os.path.dirname(os.path.realpath(__file__)) +app_name = "Searcher" +settingsfile = "searcher_settings.ini" +dbfile = "searcher.db" +searcher_path = os.path.join( + hou.homeHoudiniDirectory(), app_name +) +searcher_settings = os.path.join( + searcher_path, settingsfile +) +defaultdbpath = os.path.join( + searcher_path, dbfile +) +settingsdata = QtCore.QSettings(searcher_settings, QtCore.QSettings.IniFormat) + + +# !SECTION Setting Paths + +# -------------------------------------------------- Setting Functions +# SECTION Setting Functions ------------------------------------------ +# -------------------------------------- createdefaults +# NOTE createdefaults --------------------------------- +def createdefaults(platform): + def_set = util.DEFAULT_SETTINGS + def_set[util.SETTINGS_KEYS[1]] = str(defaultdbpath) + if platform == "unix": + def_set[util.SETTINGS_KEYS[8]] = True + settingsdata.beginGroup('Searcher') + try: + for i in range(len(util.SETTINGS_KEYS)): + settingsdata.setValue(util.SETTINGS_KEYS[i], def_set[util.SETTINGS_KEYS[i]]) + except (AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.SETTINGSMESSAGES['createdefaults'] + str(e)), severity=hou.severityType.Warning) + else: + print(la.SETTINGSMESSAGES['createdefaults'] + str(e)) + settingsdata.endGroup() + settingsdata.setIniCodec('UTF-8') + settingsdata.sync() + + +# ---------------------------------------- savesettings +# NOTE savesettings ----------------------------------- +def savesettings(settingdict): + print("Save Settings?") + try: + settingsdata.beginGroup('Searcher') + keys = list(settingdict.keys()) + for i in range(len(keys)): + settingsdata.setValue(keys[i], settingdict[keys[i]]) + settingsdata.endGroup() + settingsdata.sync() + except (AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.SETTINGSMESSAGES['savesettings'] + str(e)), severity=hou.severityType.Warning) + else: + print(la.SETTINGSMESSAGES['savesettings'] + str(e)) + + +# ---------------------------------------- loadsettings +# NOTE loadsettings ----------------------------------- +def loadsettings(): + results = {} + try: + settingsdata.beginGroup('Searcher') + for i in range(len(util.SETTINGS_KEYS)): + if util.SETTINGS_TYPES[util.SETTINGS_KEYS[i]] in {"bool", "flag"}: + results.update({util.SETTINGS_KEYS[i]: util.bc(settingsdata.value(util.SETTINGS_KEYS[i]))}) + else: + results.update({util.SETTINGS_KEYS[i]: settingsdata.value(util.SETTINGS_KEYS[i])}) + + settingsdata.endGroup() + return results + except (AttributeError, TypeError) as e: + if hou.isUIAvailable(): + hou.ui.setStatusMessage( + (la.SETTINGSMESSAGES['loadsettings'] + str(e)), severity=hou.severityType.Warning) + else: + print(la.SETTINGSMESSAGES['loadsettings'] + str(e)) +# !SECTION Setting Functions diff --git a/python3.7libs/searcher/style.py b/python3.7libs/searcher/style.py new file mode 100644 index 0000000..22d6d76 --- /dev/null +++ b/python3.7libs/searcher/style.py @@ -0,0 +1,334 @@ +from __future__ import print_function +from __future__ import absolute_import + +import hou +import os +from searcher import util + +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtGui +else: + from qtpy import QtGui + +# --------------------------------------------------- Paths +# NOTE Paths ---------------------------------------------- +script_path = os.path.dirname(os.path.realpath(__file__)) +PATH = os.path.join(script_path, "images") +imgroot = PATH.replace("\\", "/") + +settings = util.get_settings() + + +# ----------------------------------------------- Functions +# NOTE Functions ------------------------------------------ +def count_chars(txt): + result = 0 + for char in txt: + result += 1 + return result + + +# --------------------------------------------------------------- UI Style +# SECTION UI Style ------------------------------------------------------- +# ---------------------------------------------- MAINWINDOW +# NOTE MAINWINDOW ----------------------------------------- +# @formatter:off +MAINWINDOW = """ background-color: rgb(42, 42, 42); """ + +# ------------------------------------------- CONTEXTTOGGLE +# NOTE CONTEXTTOGGLE -------------------------------------- +# @formatter:off +CONTEXTTOGGLE = """ QPushButton { width: 8px; border: none; } + QPushButton:checked { width: 8px; border: none;} """ + +# ----------------------------------------------- INFOLABEL +# NOTE INFOLABEL ------------------------------------------ +INFOLABEL = """ background-color: rgba(11,11,11,1); border-bottom: 1px solid rgb(100, 100, 100); """ + +# ----------------------------------------------- MENUSTYLE +# NOTE MENUSTYLE ------------------------------------------ +# @formatter:off +MENUSTYLE = """QMenu { background-color: rgb(64,64,64); menu-scrollable: 1; margin: 0px; } + QMenu:item { background-color: rgb(46,46,46); padding: 5px 25px; margin: 1px; height:16px; } + QMenu:item:selected { background-color: rgb(64,64,64); } + QMenu:separator { background-color: rgb(0,0,0); height: 1px; margin: 5px; } + QMenu:icon { padding: 5px; } + QMenu:icon:checked { flat: true; }""" + +# ------------------------------------------------- TOOLTIP +# NOTE TOOLTIP -------------------------------------------- +# @formatter:off +TOOLTIP = """QToolTip { background-color: rgb(64,64,64); menu-scrollable: 1; margin: 0px; } + QToolTip:item { background-color: rgb(46,46,46); padding: 5px 25px ; margin: 1px; height:16px; } + QToolTip:icon { padding: 5px; } + QToolTip:icon:checked { flat: true; }""" + +# -------------------------------------------- SETTINGSMENU +# NOTE SETTINGSMENU --------------------------------------- +# @formatter:off +SETTINGSMENU = """ QWidget { background: rgb(58, 58, 58); } + QWidget#SearcherSettings { border: 0px solid rgb(35, 35, 35); } """ + +# --------------------------------------- styleresizehandle +# NOTE styleresizehandle ---------------------------------- +# @formatter:off +def styleresizehandle(obj, enter): + if enter: + resizeimg = (imgroot + "/%s.png" % obj.objectName()) + sheet = "" + sheet += ( + """QSizeGrip { + background-image: url(%s); + background-repeat: no-repeat; + background-position: center; + padding-bottom: 15px; + width: 25px; + height: 25px; + background-color: rgba(0, 0, 0, 0); + }""" + % resizeimg + ) + obj.setStyleSheet(sheet) + else: + sheet = "" + sheet += ( + """QSizeGrip { + image: url(None); + width: 15px; + height: 15px; + background-color: rgba(0, 0, 0, 0); + }""" + ) + obj.setStyleSheet(sheet) + +# ---------------------------------------- styleresulttotal +# NOTE styleresulttotal ----------------------------------- +# @formatter:off +def styleresulttotal(treecatnum, treeitemsnum): + appcolors = settings[util.SETTINGS_KEYS[14]] + return (("%s : Contexts | " % (appcolors[util.COLORFIELDS[2]], treecatnum, appcolors[util.COLORFIELDS[0]])) + + ("%s : Results " % (appcolors[util.COLORFIELDS[2]], treeitemsnum, appcolors[util.COLORFIELDS[0]]))) + +# --------------------------------------------- styletimers +# NOTE styletimers ---------------------------------------- +# @formatter:off +def styletimers(outdata): + appcolors = settings[util.SETTINGS_KEYS[14]] + return (("Search Regex %0.4f ms | " % (str(appcolors[util.COLORFIELDS[0]]), str(appcolors[util.COLORFIELDS[2]]), outdata[0])) + + ("Context Search %0.4f ms | " % (str(appcolors[util.COLORFIELDS[0]]), str(appcolors[util.COLORFIELDS[2]]), outdata[1])) + + ("Hotkey Search %0.4f ms | " % (str(appcolors[util.COLORFIELDS[0]]), str(appcolors[util.COLORFIELDS[2]]), outdata[2])) + + ("Tree build %0.4f ms | " % (str(appcolors[util.COLORFIELDS[0]]), str(appcolors[util.COLORFIELDS[2]]), outdata[3])) + + ("Total : %0.4f ms " % (str(appcolors[util.COLORFIELDS[0]]), str(appcolors[util.COLORFIELDS[2]]), outdata[4]))) + +# -------------------------------------------- returntimers +# NOTE returntimers --------------------------------------- +# @formatter:off +def returntimers(outdata): + return (("Search Regex %0.4f ms | " % outdata[0]) + + ("Context Search %0.4f ms | " % outdata[1]) + + ("Hotkey Search %0.4f ms | " % outdata[2]) + + ("Tree build %0.4f ms | " % outdata[3]) + + ("Total : %0.4f ms " % outdata[4])) + +# -------------------------------------------- setstatusmsg +# NOTE setstatusmsg --------------------------------------- +# @formatter:off +def setstatusmsg(text, severity): + stype, scolor = util.SEVERITY[severity] + msg = (("%s" % (scolor, text))) + return msg, stype + +# ----------------------------------------- gettooltipstyle +# NOTE gettooltipstyle ------------------------------------ +# @formatter:off +def gettooltipstyle(text): + return (("%s" % (settings[util.SETTINGS_KEYS[14]][util.COLORFIELDS[4]], text))) + +# ---------------------------------------- gettreeviewstyle +# NOTE gettreeviewstyle ----------------------------------- +# @formatter:off +def gettreeviewstyle(): + PATH = os.path.join(script_path, "images") + root = PATH.replace("\\", "/") + + sheet = "" + sheet += ("""QTreeWidget { + background: rgb(32, 32, 32); + alternate-background-color: rgb(39, 39, 39); + border: 0px solid rgb(19, 19, 19); + } """ + ) + sheet += ( + """QHeaderView::section { + background: rgb(53, 53, 53); + color: rgb(200, 200, 200); + border: 0px solid rgb(150, 150, 150); + border-bottom: 1px solid rgb(150, 150, 150); + border-left:1px solid rgb(35, 35, 35); + border-right:0px solid rgb(35, 35, 35); + height:20px; + resize:both; + overflow:auto; + padding: 4px; + } + QScrollBar:vertical { + background: rgb(19, 19, 19); + border: 0px solid rgb(25, 25, 25); + width: 10px; + margin: 0px 0px 0px 0px; + } + QScrollBar::handle:vertical { + background: rgb(53,53,53) + } + QScrollBar::add-line:vertical { + background: rgb(19, 19, 19); + border: 0px solid rgb(25, 25, 25); + height: 0px; + subcontrol-position: bottom; + subcontrol-origin: margin; + } + QScrollBar::sub-line:vertical { + background: rgb(19, 19, 19); + border: 0px solid rgb(25,25,25); + height: 0px; + subcontrol-position: top; + subcontrol-origin: margin; + } + QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + color: rgba(255, 193, 7, 0.8); + background: rgb(19, 19, 19); + width: 0px; + height: 0px; + } + QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; + } + QScrollBar:horizontal { + background: rgb(19, 19, 19); + border: 0px solid rgb(25, 25, 25); + height: 10px; + margin: 0x 0px 0px 0px; + } + QScrollBar::handle:horizontal { + background: rgb(53, 53, 53); + } + QScrollBar::add-line:horizontal { + background: rgb(19, 19, 19); + border: 0px solid rgb(25, 25, 25); + width: 0px; + subcontrol-position: right; + subcontrol-origin: margin; + } + QScrollBar::sub-line:horizontal { + background: rgb(19, 19, 19); + border: 0px solid rgb(25, 25, 25); + width: 0px; + subcontrol-position: left; + subcontrol-origin: margin; + } + QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal { + background: rgb(19, 19, 19); + width: 0px; + height: 0px; + } + QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; + } + """ + ) + sheet += ( + """QTreeWidget::item::has-children { + text-align: center; + color: %s; + border: 0px solid rgba(71, 71, 71, 0.8); + padding-left: 0px; padding-bottom: 0px; + padding-top: 0px; + border-radius: 0px; + } """ + % str(settings[util.SETTINGS_KEYS[14]][util.COLORFIELDS[1]]) + ) + sheet += ( + """QTreeWidget::branch:has-siblings:!adjoins-item { + border-image: url(%s/icon_vline.png) 0; + }""" + % root + ) + sheet += ( + """QTreeWidget::branch:has-siblings:adjoins-item { + border-image: url(%s/icon_branch_more.png) 0; + }""" + % root + ) + sheet += ( + """QTreeWidget::branch:!has-children:!has-siblings:adjoins-item { + border-image: url(%s/icon_branch_end.png) 0; + }""" + % root + ) + sheet += ( + """QTreeWidget::branch:has-children:!has-siblings:closed,""" + ) + sheet += ( + """QTreeWidget::branch:closed:has-children:has-siblings { + margin: 4px; + border-image: none; + image: url(%s/icon_branch_closed.png); + }""" + % root + ) + sheet += ( + """QTreeWidget::branch:open:has-children:!has-siblings,""" + ) + sheet += ( + """QTreeWidget::branch:open:has-children:has-siblings { + margin: 4px; + border-image: none; + image: url(%s/icon_branch_open.png); + }""" + % root + ) + sheet += ( + """QTreeWidget::indicator:unchecked { + image: url(%s/icon_branch_closed.png); + padding-left: 15px; + }""" + % root + ) + sheet += ( + """QTreeWidget::indicator:checked { + image: url(%s/icon_branch_open.png); + padding-left: 15px; + }""" + % root + ) + sheet += """QTreeWidget::indicator { + width: 16px; + height: 16px; + }""" + sheet += ( + """QGroupBox::indicator:unchecked { + image: url(%s/icon_branch_closed.png); + padding-left: 15px; + }""" + % root + ) + sheet += ( + """QGroupBox::indicator:checked { + image: url(%s/icon_branch_open.png); + padding-left: 15px; + }""" + % root + ) + sheet += ( + """QGroupBox::indicator { + width: 16px; + height: 16px; + }""" + ) + + return sheet + +# !SECTION UI Style \ No newline at end of file diff --git a/python3.7libs/searcher/theme.py b/python3.7libs/searcher/theme.py new file mode 100644 index 0000000..5f5e43a --- /dev/null +++ b/python3.7libs/searcher/theme.py @@ -0,0 +1,248 @@ +from __future__ import print_function +from __future__ import absolute_import + +from searcher import theme_ui +from searcher import util +from searcher import settings_data +from searcher import style + +import os +import sys + +import hou +import hdefereval as hd +hver = 0 +if os.environ["HFS"] != "": + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.')+1:]) + from hutil.Qt import QtGui + from hutil.Qt import QtCore + from hutil.Qt import QtWidgets +else: + from qtpy import QtGui + from qtpy import QtCore + from qtpy import QtWidgets + +scriptpath = os.path.dirname(os.path.realpath(__file__)) + +def name(**variables): + return [x for x in variables] + +def getHexColor(color): + if isinstance(color, hou.Color): + color = color.rgb() + + rgb = [('00' + hex(int(v * 0xff))[2:])[-2:] for v in color[:3]] + return "#" + ''.join(rgb) + +def getRGBColor(hex): + hex = hex.lstrip('#') + hlen = len(hex) + return tuple(int(hex[i:i+hlen/3], 16) / 255.0 for i in range(0, hlen, hlen/3)) + +class Theme(QtWidgets.QWidget): + """ Searcher coloring""" + + # --------------------------------------------------------------- Init + # SECTION Init ------------------------------------------------------- + def __init__(self, parent=None): + super(Theme, self).__init__(parent=parent) + self.setParent(parent) + self.parentwindow = parent + self.ui = theme_ui.Ui_Theme() + # !SECTION Init + + + self.ui.setupUi(self) + self.ui.retranslateUi(self) + self.colorfield = {} + self.settings = util.get_settings() + self.colors = self.settings[util.SETTINGS_KEYS[14]] + self.coloreditor = None + + self.tabpanel = self.ui.tabWidget + self.tabpanel.currentChanged.connect(self.curTabChange) + + self.tab1 = self.ui.tab + self.tab1.setLayout(self.ui.r1) + + # --------------------------------------------------- Build Fields + # SECTION Build Fields ------------------------------------------- + for i in range(len(util.COLORFIELDS)): + # ---------------------------------- Colorfield + # NOTE Colorfield ----------------------------- + v = getattr(self.ui, util.COLORFIELDS[i]) + v.setText(self.settings[util.SETTINGS_KEYS[14]][util.COLORFIELDS[i]]) + v.setVisible(True) + + # --------------------------- Colorfield Button + # NOTE Colorfield Button ---------------------- + v_btn = getattr(self.ui, util.COLORFIELDS[i] + '_btn') + v_btn.setStyleSheet("background-color:" + v.text()) + v_btn.setAutoFillBackground(True) + v_btn.clicked.connect(self.chooseColor) + v_btn.setObjectName(util.COLORFIELDS[i]) + v_btn.setVisible(True) + + # ---------------------------- Colorfield Label + # NOTE Colorfield Label ----------------------- + v_lbl = getattr(self.ui, util.COLORFIELDS[i] + '_lbl') + v_lbl.setVisible(True) + + # !SECTION Build Fields + + self.save = self.ui.savetheme + self.save.pressed.connect(self.save_cb) + + self.discard = self.ui.discardtheme + self.discard.pressed.connect(self.discard_cb) + + def initmenu(self): + self.curTabChange(0) + self.installEventFilter(self) + + # ------------------------------------------------------------- Callbacks + # SECTION Callbacks ----------------------------------------------------- + # ---------------------------------------- curTabChange + # NOTE curTabChange ----------------------------------- + def curTabChange(self, index): + for i in range(self.tabpanel.count()): + if i == index: + self.tabpanel.widget(i).setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + else: + self.tabpanel.widget(i).setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored) + + # --------------------------------------------- save_cb + # NOTE save_cb ---------------------------------------- + def save_cb(self): + for i in range(len(util.COLORFIELDS)): + self.settings[util.SETTINGS_KEYS[14]][util.COLORFIELDS[i]] = getattr(self.ui, util.COLORFIELDS[i]).text() + + settings_data.savesettings(self.settings) + self.parentwindow.themebtn.setChecked(False) + self.close() + + # ------------------------------------------ discard_cb + # NOTE discard_cb ------------------------------------- + def discard_cb(self): + self.parentwindow.themebtn.setChecked(False) + self.close() + + #-------------------------------------- colorchange_cb + # NOTE colorchange_cb --------------------------------- + def colorchange_cb(self, color, alpha=1.0): + rgb = color.rgb() + newcolor = QtGui.QColor( + rgb[0]*255, + rgb[1]*255, + rgb[2]*255 + ) + + if newcolor.isValid(): + demotext = "" + self.colorfield[self.name][0].setText(newcolor.name()) + self.colorfield[self.name][1].setStyleSheet("background-color:" + self.colorfield[self.name][0].text()) + + if self.colorfield[self.name][0] == getattr(self.ui, util.COLORFIELDS[0]): + outdata = [0.100, 0.200, 0.300, 0.400, 0.500] + demotxt = (("Search Regex %0.4f ms | " % (str(self.colorfield[self.name][0].text()), str(getattr(self.ui, util.COLORFIELDS[2]).text()), outdata[0])) + + ("Context Search %0.4f ms | " % (str(self.colorfield[self.name][0].text()), str(getattr(self.ui, util.COLORFIELDS[2]).text()), outdata[1])) + + ("Hotkey Search %0.4f ms | " % (str(self.colorfield[self.name][0].text()), str(getattr(self.ui, util.COLORFIELDS[2]).text()), outdata[2])) + + ("Tree build %0.4f ms | " % (str(self.colorfield[self.name][0].text()), str(getattr(self.ui, util.COLORFIELDS[2]).text()), outdata[3])) + + ("Total : %0.4f ms " % (str(self.colorfield[self.name][0].text()), str(getattr(self.ui, util.COLORFIELDS[2]).text()), outdata[4]))) + self.parentwindow.parentwindow.infolbl.setText(demotxt) + + elif self.colorfield[self.name][0] == getattr(self.ui, util.COLORFIELDS[2]): + outdata = [0.100, 0.200, 0.300, 0.400, 0.500] + demotxt = (("Search Regex %0.4f ms | " % (str(getattr(self.ui, util.COLORFIELDS[0]).text()), str(self.colorfield[self.name][0].text()), outdata[0])) + + ("Context Search %0.4f ms | " % (str(getattr(self.ui, util.COLORFIELDS[0]).text()), str(self.colorfield[self.name][0].text()), outdata[1])) + + ("Hotkey Search %0.4f ms | " % (str(getattr(self.ui, util.COLORFIELDS[0]).text()), str(self.colorfield[self.name][0].text()), outdata[2])) + + ("Tree build %0.4f ms | " % (str(getattr(self.ui, util.COLORFIELDS[0]).text()), str(self.colorfield[self.name][0].text()), outdata[3])) + + ("Total : %0.4f ms " % (str(getattr(self.ui, util.COLORFIELDS[0]).text()), str(self.colorfield[self.name][0].text()), outdata[4]))) + self.parentwindow.parentwindow.infolbl.setText(demotxt) + + elif self.colorfield[self.name][0] == getattr(self.ui, util.COLORFIELDS[4]): + text = "This is an example of how the ToolTip text will look with this particular color" + demotxt = ("%s" % (self.colorfield[self.name][0].text(), text)) + self.parentwindow.parentwindow.infolbl.setText(demotxt) + + + def _opencoloreditor(self, color): + allWidgets = QtWidgets.QApplication.allWidgets() + for w in allWidgets: + if "Select Color" in w.windowTitle(): + self.coloreditor = w + break + + if self.coloreditor: + pos = self.parentwindow.mapToGlobal( + QtCore.QPoint(self.parentwindow.width(), self.parentwindow.height())) + self.coloreditor.setGeometry( + pos.x() - ((self.parentwindow.width() * 1.55 ) + 20 ), + pos.y() - self.parentwindow.height(), + ((self.parentwindow.width() * 0.5) + 44), + ((self.parentwindow.height() * 1.2) + 86) + ) + self.parentwindow.parentwindow.activateWindow() + + # ----------------------------------------- chooseColor + # NOTE chooseColor ------------------------------------ + def chooseColor(self): + sender = self.sender() + + self.name = sender.objectName() + self.colorfield[self.name] = (getattr(self.ui, self.name), sender) + + qcolor = QtGui.QColor() + qcolor.setNamedColor(self.colorfield[self.name][0].text()) + + colord = QtWidgets.QColorDialog(self) + colord.setModal(False) + pos = self.parentwindow.mapToGlobal( + QtCore.QPoint(self.parentwindow.width(), self.parentwindow.height())) + colord.move( + pos.x() + 300, + pos.y(), + ) + c = colord.getColor( + initial=qcolor, + parent=self, + options=QtWidgets.QColorDialog.DontUseNativeDialog + ) + hcolor = hou.qt.fromQColor(c) + + self.colorchange_cb(hcolor[0]) + + # !SECTION Callbacks + + # ------------------------------------------------------------- Events + # SECTION Events ----------------------------------------------------- + def eventFilter(self, obj, event): + event_type = event.type() + + # ------------------------------------------- Mouse + # SECTION Mouse ----------------------------------- + # ----------------------- MouseButtonPress + # NOTE MouseButtonPress ------------------ + # --- Empty for now --- + # !SECTION Mouse + + # ------------------------------------------ Window + # NOTE Window ------------------------------------- + if event_type == QtCore.QEvent.Show: + self.parentwindow.ui.save_btn.setVisible(False) + self.parentwindow.ui.discard_btn.setVisible(False) + if event_type == QtCore.QEvent.Close: + self.parentwindow.ui.save_btn.setVisible(True) + self.parentwindow.ui.discard_btn.setVisible(True) + + # ---------------------------------------- Keypress + # NOTE Keypress ----------------------------------- + if event_type == QtCore.QEvent.KeyPress: + if event.key() == QtCore.Qt.Key_Escape: + self.parentwindow.closeroutine() + return True + + return QtCore.QObject.eventFilter(self, obj, event) + + # !SECTION Events \ No newline at end of file diff --git a/python3.7libs/searcher/theme_ui.py b/python3.7libs/searcher/theme_ui.py new file mode 100644 index 0000000..e7782cf --- /dev/null +++ b/python3.7libs/searcher/theme_ui.py @@ -0,0 +1,298 @@ +from hutil.Qt import QtCore, QtGui, QtWidgets +import os + +scriptpath = os.path.dirname(os.path.realpath(__file__)) + + +class Ui_Theme(object): + def setupUi(self, Theme): + Theme.setObjectName("Theme") + Theme.setWindowModality(QtCore.Qt.NonModal) + Theme.resize(450, 300) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(Theme.sizePolicy().hasHeightForWidth()) + Theme.setSizePolicy(sizePolicy) + Theme.setMinimumSize(QtCore.QSize(100, 0)) + Theme.setBaseSize(QtCore.QSize(0, 0)) + Theme.setStyleSheet("") + self.gridLayout = QtWidgets.QGridLayout(Theme) + self.gridLayout.setContentsMargins(-1, -1, -1, 6) + self.gridLayout.setSpacing(6) + self.gridLayout.setObjectName("gridLayout") + self.r2 = QtWidgets.QVBoxLayout() + self.r2.setObjectName("r2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_2.addItem(spacerItem) + self.discardtheme = QtWidgets.QPushButton(Theme) + self.discardtheme.setObjectName("discardtheme") + self.horizontalLayout_2.addWidget(self.discardtheme) + self.savetheme = QtWidgets.QPushButton(Theme) + self.savetheme.setObjectName("savetheme") + self.horizontalLayout_2.addWidget(self.savetheme) + self.r2.addLayout(self.horizontalLayout_2) + self.gridLayout.addLayout(self.r2, 2, 0, 1, 1) + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.tabWidget = QtWidgets.QTabWidget(Theme) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.layoutWidget = QtWidgets.QWidget(self.tab) + self.layoutWidget.setGeometry(QtCore.QRect(0, 0, 533, 164)) + self.layoutWidget.setObjectName("layoutWidget") + self.r1 = QtWidgets.QHBoxLayout(self.layoutWidget) + self.r1.setContentsMargins(6, 6, 6, 0) + self.r1.setObjectName("r1") + self.c1 = QtWidgets.QVBoxLayout() + self.c1.setObjectName("c1") + self.h4_c1 = QtWidgets.QHBoxLayout() + self.h4_c1.setObjectName("h4_c1") + self.text2_lbl = QtWidgets.QLabel(self.layoutWidget) + self.text2_lbl.setObjectName("text2_lbl") + self.h4_c1.addWidget(self.text2_lbl) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h4_c1.addItem(spacerItem1) + self.text2_btn = QtWidgets.QToolButton(self.layoutWidget) + self.text2_btn.setText("") + self.text2_btn.setObjectName("text2_btn") + self.h4_c1.addWidget(self.text2_btn) + self.text2 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.text2.sizePolicy().hasHeightForWidth()) + self.text2.setSizePolicy(sizePolicy) + self.text2.setMinimumSize(QtCore.QSize(75, 0)) + self.text2.setMaximumSize(QtCore.QSize(75, 16777215)) + self.text2.setBaseSize(QtCore.QSize(75, 0)) + self.text2.setReadOnly(True) + self.text2.setObjectName("text2") + self.h4_c1.addWidget(self.text2) + spacerItem2 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h4_c1.addItem(spacerItem2) + self.c1.addLayout(self.h4_c1) + self.h1_c2 = QtWidgets.QHBoxLayout() + self.h1_c2.setObjectName("h1_c2") + self.tooltip_lbl = QtWidgets.QLabel(self.layoutWidget) + self.tooltip_lbl.setObjectName("tooltip_lbl") + self.h1_c2.addWidget(self.tooltip_lbl) + self.tooltip_btn = QtWidgets.QToolButton(self.layoutWidget) + self.tooltip_btn.setText("") + self.tooltip_btn.setObjectName("tooltip_btn") + self.h1_c2.addWidget(self.tooltip_btn) + self.tooltip = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tooltip.sizePolicy().hasHeightForWidth()) + self.tooltip.setSizePolicy(sizePolicy) + self.tooltip.setMinimumSize(QtCore.QSize(75, 0)) + self.tooltip.setMaximumSize(QtCore.QSize(75, 16777215)) + self.tooltip.setReadOnly(True) + self.tooltip.setObjectName("tooltip") + self.h1_c2.addWidget(self.tooltip) + spacerItem3 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h1_c2.addItem(spacerItem3) + self.c1.addLayout(self.h1_c2) + self.h3_c1 = QtWidgets.QHBoxLayout() + self.h3_c1.setObjectName("h3_c1") + self.text1_lbl = QtWidgets.QLabel(self.layoutWidget) + self.text1_lbl.setObjectName("text1_lbl") + self.h3_c1.addWidget(self.text1_lbl) + spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h3_c1.addItem(spacerItem4) + self.text1_btn = QtWidgets.QToolButton(self.layoutWidget) + self.text1_btn.setText("") + self.text1_btn.setObjectName("text1_btn") + self.h3_c1.addWidget(self.text1_btn) + self.text1 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.text1.sizePolicy().hasHeightForWidth()) + self.text1.setSizePolicy(sizePolicy) + self.text1.setMinimumSize(QtCore.QSize(75, 0)) + self.text1.setMaximumSize(QtCore.QSize(75, 16777215)) + self.text1.setBaseSize(QtCore.QSize(75, 0)) + self.text1.setReadOnly(True) + self.text1.setObjectName("text1") + self.h3_c1.addWidget(self.text1) + spacerItem5 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h3_c1.addItem(spacerItem5) + self.c1.addLayout(self.h3_c1) + self.h2_c1 = QtWidgets.QHBoxLayout() + self.h2_c1.setObjectName("h2_c1") + self.stats1_lbl = QtWidgets.QLabel(self.layoutWidget) + self.stats1_lbl.setObjectName("stats1_lbl") + self.h2_c1.addWidget(self.stats1_lbl) + spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h2_c1.addItem(spacerItem6) + self.stats1_btn = QtWidgets.QToolButton(self.layoutWidget) + self.stats1_btn.setText("") + self.stats1_btn.setObjectName("stats1_btn") + self.h2_c1.addWidget(self.stats1_btn) + self.stats1 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.stats1.sizePolicy().hasHeightForWidth()) + self.stats1.setSizePolicy(sizePolicy) + self.stats1.setMinimumSize(QtCore.QSize(75, 0)) + self.stats1.setMaximumSize(QtCore.QSize(75, 16777215)) + self.stats1.setBaseSize(QtCore.QSize(75, 0)) + self.stats1.setReadOnly(True) + self.stats1.setObjectName("stats1") + self.h2_c1.addWidget(self.stats1) + spacerItem7 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h2_c1.addItem(spacerItem7) + self.c1.addLayout(self.h2_c1) + spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.c1.addItem(spacerItem8) + self.r1.addLayout(self.c1) + self.c2 = QtWidgets.QVBoxLayout() + self.c2.setObjectName("c2") + self.h1_c1 = QtWidgets.QHBoxLayout() + self.h1_c1.setObjectName("h1_c1") + self.stats2_lbl = QtWidgets.QLabel(self.layoutWidget) + self.stats2_lbl.setObjectName("stats2_lbl") + self.h1_c1.addWidget(self.stats2_lbl) + spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h1_c1.addItem(spacerItem9) + spacerItem10 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h1_c1.addItem(spacerItem10) + self.stats2_btn = QtWidgets.QToolButton(self.layoutWidget) + self.stats2_btn.setText("") + self.stats2_btn.setObjectName("stats2_btn") + self.h1_c1.addWidget(self.stats2_btn) + self.stats2 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.stats2.sizePolicy().hasHeightForWidth()) + self.stats2.setSizePolicy(sizePolicy) + self.stats2.setMinimumSize(QtCore.QSize(75, 0)) + self.stats2.setMaximumSize(QtCore.QSize(75, 16777215)) + self.stats2.setBaseSize(QtCore.QSize(75, 0)) + self.stats2.setReadOnly(True) + self.stats2.setObjectName("stats2") + self.h1_c1.addWidget(self.stats2) + self.c2.addLayout(self.h1_c1) + self.h2_c2 = QtWidgets.QHBoxLayout() + self.h2_c2.setObjectName("h2_c2") + self.label_7 = QtWidgets.QLabel(self.layoutWidget) + self.label_7.setEnabled(True) + self.label_7.setObjectName("label_7") + self.h2_c2.addWidget(self.label_7) + spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h2_c2.addItem(spacerItem11) + self.toolButton_6 = QtWidgets.QToolButton(self.layoutWidget) + self.toolButton_6.setText("") + self.toolButton_6.setObjectName("toolButton_6") + self.h2_c2.addWidget(self.toolButton_6) + self.lineEdit_3 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit_3.sizePolicy().hasHeightForWidth()) + self.lineEdit_3.setSizePolicy(sizePolicy) + self.lineEdit_3.setMinimumSize(QtCore.QSize(75, 0)) + self.lineEdit_3.setMaximumSize(QtCore.QSize(75, 16777215)) + self.lineEdit_3.setReadOnly(True) + self.lineEdit_3.setObjectName("lineEdit_3") + self.h2_c2.addWidget(self.lineEdit_3) + self.c2.addLayout(self.h2_c2) + self.h3_c2 = QtWidgets.QHBoxLayout() + self.h3_c2.setObjectName("h3_c2") + self.label_6 = QtWidgets.QLabel(self.layoutWidget) + self.label_6.setObjectName("label_6") + self.h3_c2.addWidget(self.label_6) + spacerItem12 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h3_c2.addItem(spacerItem12) + self.toolButton_7 = QtWidgets.QToolButton(self.layoutWidget) + self.toolButton_7.setText("") + self.toolButton_7.setObjectName("toolButton_7") + self.h3_c2.addWidget(self.toolButton_7) + self.lineEdit_4 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit_4.sizePolicy().hasHeightForWidth()) + self.lineEdit_4.setSizePolicy(sizePolicy) + self.lineEdit_4.setMinimumSize(QtCore.QSize(75, 0)) + self.lineEdit_4.setMaximumSize(QtCore.QSize(75, 16777215)) + self.lineEdit_4.setReadOnly(True) + self.lineEdit_4.setObjectName("lineEdit_4") + self.h3_c2.addWidget(self.lineEdit_4) + self.c2.addLayout(self.h3_c2) + self.h4_c2 = QtWidgets.QHBoxLayout() + self.h4_c2.setObjectName("h4_c2") + self.label_5 = QtWidgets.QLabel(self.layoutWidget) + self.label_5.setObjectName("label_5") + self.h4_c2.addWidget(self.label_5) + spacerItem13 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h4_c2.addItem(spacerItem13) + self.toolButton_8 = QtWidgets.QToolButton(self.layoutWidget) + self.toolButton_8.setText("") + self.toolButton_8.setObjectName("toolButton_8") + self.h4_c2.addWidget(self.toolButton_8) + self.lineEdit = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth()) + self.lineEdit.setSizePolicy(sizePolicy) + self.lineEdit.setMinimumSize(QtCore.QSize(75, 0)) + self.lineEdit.setMaximumSize(QtCore.QSize(75, 16777215)) + self.lineEdit.setReadOnly(True) + self.lineEdit.setObjectName("lineEdit") + self.h4_c2.addWidget(self.lineEdit) + self.c2.addLayout(self.h4_c2) + spacerItem14 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.c2.addItem(spacerItem14) + self.r1.addLayout(self.c2) + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.tabWidget.addTab(self.tab_2, "") + self.verticalLayout.addWidget(self.tabWidget) + self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) + + self.retranslateUi(Theme) + self.setVisibility() + QtCore.QMetaObject.connectSlotsByName(Theme) + + def retranslateUi(self, Theme): + _translate = QtCore.QCoreApplication.translate + Theme.setWindowTitle(_translate("Theme", "Form")) + self.discardtheme.setText(_translate("Theme", "Discard")) + self.savetheme.setText(_translate("Theme", "Save")) + self.text2_lbl.setText(_translate("Theme", "Search Results Context")) + self.tooltip_lbl.setText(_translate("Theme", "Tool Tip Info")) + self.text1_lbl.setText(_translate("Theme", "Result Stats Text")) + self.stats1_lbl.setText(_translate("Theme", "Result Stat Values")) + self.stats2_lbl.setText(_translate("Theme", "Secondary Stat Values")) + self.label_7.setText(_translate("Theme", "TextLabel")) + self.label_6.setText(_translate("Theme", "TextLabel")) + self.label_5.setText(_translate("Theme", "TextLabel")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Theme", "Text")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Theme", "Window")) + + def setVisibility(self): + self.label_7.setVisible(False) + self.label_6.setVisible(False) + self.label_5.setVisible(False) + self.stats2_lbl.setVisible(False) + + self.lineEdit_4.setVisible(False) + self.lineEdit_3.setVisible(False) + self.lineEdit.setVisible(False) + self.stats2.setVisible(False) + + self.toolButton_6.setVisible(False) + self.toolButton_7.setVisible(False) + self.toolButton_8.setVisible(False) + self.stats2_btn.setVisible(False) \ No newline at end of file diff --git a/python3.7libs/searcher/tools/imagetint.py b/python3.7libs/searcher/tools/imagetint.py new file mode 100644 index 0000000..209ef7a --- /dev/null +++ b/python3.7libs/searcher/tools/imagetint.py @@ -0,0 +1,70 @@ +from PIL import Image +from PIL.ImageColor import getcolor, getrgb +from PIL.ImageOps import grayscale +import os +import PIL.Image +import PIL.ImageOps + +script_path = os.path.dirname(os.path.realpath(__file__)) + + +def image_tint(src, tint='#ffffff'): + if Image.isStringType(src): # file path? + src = Image.open(src) + if src.mode not in ['RGB', 'RGBA']: + raise TypeError('Unsupported source image mode: {}'.format(src.mode)) + src.load() + + tr, tg, tb = getrgb(tint) + tl = getcolor(tint, "L") # tint color's overall luminosity + if not tl: tl = 1 # avoid division by zero + tl = float(tl) # compute luminosity preserving tint factors + sr, sg, sb = map(lambda tv: tv/tl, (tr, tg, tb)) # per component adjustments + + # create look-up tables to map luminosity to adjusted tint + # (using floating-point math only to compute table) + luts = (map(lambda lr: int(lr*sr + 0.5), range(256)) + + map(lambda lg: int(lg*sg + 0.5), range(256)) + + map(lambda lb: int(lb*sb + 0.5), range(256))) + l = grayscale(src) # 8-bit luminosity version of whole image + if Image.getmodebands(src.mode) < 4: + merge_args = (src.mode, (l, l, l)) # for RGB verion of grayscale + else: # include copy of src image's alpha layer + a = Image.new("L", src.size) + a.putdata(src.getdata(3)) + merge_args = (src.mode, (l, l, l, a)) # for RGBA verion of grayscale + luts += range(256) # for 1:1 mapping of copied alpha values + + return Image.merge(*merge_args).point(luts) + +def tint_image(src, color="#FFFFFF"): + if Image.isStringType(src): # file path? + src = Image.open(src) + if src.mode not in ['RGB', 'RGBA']: + raise TypeError('Unsupported source image mode: {}'.format(src.mode)) + src.load() + r, g, b, alpha = src.split() + gray = ImageOps.grayscale(src) + result = ImageOps.colorize(gray, (0, 0, 0, 0), color) + result.putalpha(alpha) + return result + +if __name__ == '__main__': + + PATH = os.path.abspath(os.path.join(script_path, "..", "images")) + p = PATH.replace("\\", "/") + input_image_path = ['branch-vline.png', 'branch-more.png', 'branch-end.png', 'opened.png', 'collapsed.svg'] + for i in range(len(input_image_path)): + input_image = os.path.join(p, input_image_path[i]) + print 'tinting "{}"'.format(input_image) + + root, ext = os.path.splitext(input_image) + result_image_path = root+'_result'+ext + + print 'creating "{}"'.format(result_image_path) + result = image_tint(input_image, '#686868') + if os.path.exists(result_image_path): # delete any previous result file + os.remove(result_image_path) + result.save(result_image_path) # file name's extension determines format + + print 'done' \ No newline at end of file diff --git a/python3.7libs/searcher/ui_files/SearcherSettings.py b/python3.7libs/searcher/ui_files/SearcherSettings.py new file mode 100644 index 0000000..66e102c --- /dev/null +++ b/python3.7libs/searcher/ui_files/SearcherSettings.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'SearcherSettings.ui' +# +# Created by: qtpy UI code generator 5.14.1 +# +# WARNING! All changes made in this file will be lost! + + +from qtpy import QtCore, QtGui, QtWidgets + + +class Ui_SearcherSettings(object): + def setupUi(self, SearcherSettings): + SearcherSettings.setObjectName("SearcherSettings") + SearcherSettings.setWindowModality(QtCore.Qt.NonModal) + SearcherSettings.resize(450, 211) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(SearcherSettings.sizePolicy().hasHeightForWidth()) + SearcherSettings.setSizePolicy(sizePolicy) + SearcherSettings.setMinimumSize(QtCore.QSize(450, 0)) + SearcherSettings.setBaseSize(QtCore.QSize(0, 0)) + SearcherSettings.setStyleSheet("") + self.gridLayout = QtWidgets.QGridLayout(SearcherSettings) + self.gridLayout.setContentsMargins(-1, -1, -1, 6) + self.gridLayout.setSpacing(6) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout_4 = QtWidgets.QVBoxLayout() + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.headerrow = QtWidgets.QHBoxLayout() + self.headerrow.setObjectName("headerrow") + self.projectTitle = QtWidgets.QLabel(SearcherSettings) + font = QtGui.QFont() + font.setPointSize(15) + self.projectTitle.setFont(font) + self.projectTitle.setAlignment(QtCore.Qt.AlignCenter) + self.projectTitle.setObjectName("projectTitle") + self.headerrow.addWidget(self.projectTitle) + self.line_2 = QtWidgets.QFrame(SearcherSettings) + self.line_2.setFrameShape(QtWidgets.QFrame.VLine) + self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line_2.setObjectName("line_2") + self.headerrow.addWidget(self.line_2) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.headerrow.addItem(spacerItem) + self.checkBox = QtWidgets.QCheckBox(SearcherSettings) + self.checkBox.setLayoutDirection(QtCore.Qt.RightToLeft) + self.checkBox.setObjectName("checkBox") + self.headerrow.addWidget(self.checkBox) + self.windowsize_chk = QtWidgets.QCheckBox(SearcherSettings) + self.windowsize_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + self.windowsize_chk.setObjectName("windowsize_chk") + self.headerrow.addWidget(self.windowsize_chk) + self.verticalLayout_4.addLayout(self.headerrow) + self.line = QtWidgets.QFrame(SearcherSettings) + self.line.setFrameShape(QtWidgets.QFrame.HLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.verticalLayout_4.addWidget(self.line) + self.secondrow = QtWidgets.QHBoxLayout() + self.secondrow.setObjectName("secondrow") + self.lang_cbox = QtWidgets.QComboBox(SearcherSettings) + self.lang_cbox.setObjectName("lang_cbox") + self.lang_cbox.addItem("") + self.secondrow.addWidget(self.lang_cbox) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.secondrow.addItem(spacerItem1) + self.label_3 = QtWidgets.QLabel(SearcherSettings) + self.label_3.setObjectName("label_3") + self.secondrow.addWidget(self.label_3) + self.maxresults_txt = QtWidgets.QSpinBox(SearcherSettings) + self.maxresults_txt.setMinimum(1) + self.maxresults_txt.setMaximum(9999) + self.maxresults_txt.setObjectName("maxresults_txt") + self.secondrow.addWidget(self.maxresults_txt) + self.inmemory_chk = QtWidgets.QCheckBox(SearcherSettings) + self.inmemory_chk.setLayoutDirection(QtCore.Qt.RightToLeft) + self.inmemory_chk.setTristate(False) + self.inmemory_chk.setObjectName("inmemory_chk") + self.secondrow.addWidget(self.inmemory_chk) + self.verticalLayout_4.addLayout(self.secondrow) + self.thirdrow = QtWidgets.QHBoxLayout() + self.thirdrow.setObjectName("thirdrow") + self.label_2 = QtWidgets.QLabel(SearcherSettings) + self.label_2.setObjectName("label_2") + self.thirdrow.addWidget(self.label_2) + self.defaulthotkey_txt = QtWidgets.QLineEdit(SearcherSettings) + self.defaulthotkey_txt.setToolTip("") + self.defaulthotkey_txt.setReadOnly(True) + self.defaulthotkey_txt.setObjectName("defaulthotkey_txt") + self.thirdrow.addWidget(self.defaulthotkey_txt) + self.hotkey_icon = QtWidgets.QToolButton(SearcherSettings) + self.hotkey_icon.setPopupMode(QtWidgets.QToolButton.InstantPopup) + self.hotkey_icon.setObjectName("hotkey_icon") + self.thirdrow.addWidget(self.hotkey_icon) + self.verticalLayout_4.addLayout(self.thirdrow) + self.fourthrow = QtWidgets.QHBoxLayout() + self.fourthrow.setObjectName("fourthrow") + self.label = QtWidgets.QLabel(SearcherSettings) + self.label.setObjectName("label") + self.fourthrow.addWidget(self.label) + self.databasepath_txt = QtWidgets.QLineEdit(SearcherSettings) + self.databasepath_txt.setObjectName("databasepath_txt") + self.fourthrow.addWidget(self.databasepath_txt) + self.dbpath_icon = QtWidgets.QToolButton(SearcherSettings) + self.dbpath_icon.setObjectName("dbpath_icon") + self.fourthrow.addWidget(self.dbpath_icon) + self.verticalLayout_4.addLayout(self.fourthrow) + self.fifthrow = QtWidgets.QHBoxLayout() + self.fifthrow.setObjectName("fifthrow") + self.label_4 = QtWidgets.QLabel(SearcherSettings) + self.label_4.setObjectName("label_4") + self.fifthrow.addWidget(self.label_4) + self.test1_btn = QtWidgets.QPushButton(SearcherSettings) + self.test1_btn.setObjectName("test1_btn") + self.fifthrow.addWidget(self.test1_btn) + self.cleardata_btn = QtWidgets.QPushButton(SearcherSettings) + self.cleardata_btn.setObjectName("cleardata_btn") + self.fifthrow.addWidget(self.cleardata_btn) + self.verticalLayout_4.addLayout(self.fifthrow) + self.line_3 = QtWidgets.QFrame(SearcherSettings) + self.line_3.setFrameShape(QtWidgets.QFrame.HLine) + self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line_3.setObjectName("line_3") + self.verticalLayout_4.addWidget(self.line_3) + self.sixthrow = QtWidgets.QHBoxLayout() + self.sixthrow.setObjectName("sixthrow") + self.about_btn = QtWidgets.QToolButton(SearcherSettings) + self.about_btn.setObjectName("about_btn") + self.sixthrow.addWidget(self.about_btn) + spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.sixthrow.addItem(spacerItem2) + self.debuglevel_cbx = QtWidgets.QComboBox(SearcherSettings) + self.debuglevel_cbx.setObjectName("debuglevel_cbx") + self.debuglevel_cbx.addItem("") + self.debuglevel_cbx.addItem("") + self.debuglevel_cbx.addItem("") + self.sixthrow.addWidget(self.debuglevel_cbx) + self.debugflag_chk = QtWidgets.QCheckBox(SearcherSettings) + self.debugflag_chk.setLayoutDirection(QtCore.Qt.LeftToRight) + self.debugflag_chk.setObjectName("debugflag_chk") + self.sixthrow.addWidget(self.debugflag_chk) + self.discard_btn = QtWidgets.QPushButton(SearcherSettings) + self.discard_btn.setObjectName("discard_btn") + self.sixthrow.addWidget(self.discard_btn) + self.save_btn = QtWidgets.QPushButton(SearcherSettings) + self.save_btn.setObjectName("save_btn") + self.sixthrow.addWidget(self.save_btn) + self.verticalLayout_4.addLayout(self.sixthrow) + self.gridLayout.addLayout(self.verticalLayout_4, 0, 0, 1, 1) + + self.retranslateUi(SearcherSettings) + QtCore.QMetaObject.connectSlotsByName(SearcherSettings) + + def retranslateUi(self, SearcherSettings): + _translate = QtCore.QCoreApplication.translate + SearcherSettings.setWindowTitle(_translate("SearcherSettings", "Form")) + self.projectTitle.setText(_translate("SearcherSettings", "Settings")) + self.checkBox.setText(_translate("SearcherSettings", "Use Animated Menus:")) + self.windowsize_chk.setText(_translate("SearcherSettings", "Remember Search Window Size")) + self.lang_cbox.setCurrentText(_translate("SearcherSettings", "English")) + self.lang_cbox.setItemText(0, _translate("SearcherSettings", "English")) + self.label_3.setText(_translate("SearcherSettings", "Maximum Search Results")) + self.inmemory_chk.setText(_translate("SearcherSettings", "Use In-Memory Database")) + self.label_2.setText(_translate("SearcherSettings", "Hotkey to use for opening unassigned items: ")) + self.defaulthotkey_txt.setPlaceholderText(_translate("SearcherSettings", "Double Click")) + self.hotkey_icon.setText(_translate("SearcherSettings", "...")) + self.label.setText(_translate("SearcherSettings", "Database location: ")) + self.dbpath_icon.setText(_translate("SearcherSettings", "...")) + self.label_4.setText(_translate("SearcherSettings", "Maintenance utilities:")) + self.test1_btn.setText(_translate("SearcherSettings", "Test Button 1")) + self.cleardata_btn.setText(_translate("SearcherSettings", "Clear Data")) + self.about_btn.setText(_translate("SearcherSettings", "...")) + self.debuglevel_cbx.setItemText(0, _translate("SearcherSettings", "NONE")) + self.debuglevel_cbx.setItemText(1, _translate("SearcherSettings", "TIMER")) + self.debuglevel_cbx.setItemText(2, _translate("SearcherSettings", "ALL")) + self.debugflag_chk.setText(_translate("SearcherSettings", "Debug Mode")) + self.discard_btn.setText(_translate("SearcherSettings", "Discard")) + self.save_btn.setText(_translate("SearcherSettings", "Save")) diff --git a/python3.7libs/searcher/ui_files/SearcherSettings.ui b/python3.7libs/searcher/ui_files/SearcherSettings.ui new file mode 100644 index 0000000..6840c36 --- /dev/null +++ b/python3.7libs/searcher/ui_files/SearcherSettings.ui @@ -0,0 +1,334 @@ + + + SearcherSettings + + + Qt::NonModal + + + + 0 + 0 + 450 + 211 + + + + + 0 + 0 + + + + + 450 + 0 + + + + + 0 + 0 + + + + Form + + + + + + + 6 + + + 6 + + + + + + + + + + 15 + + + + Settings + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::RightToLeft + + + Use Animated Menus: + + + + + + + Qt::RightToLeft + + + Remember Search Window Size + + + + + + + + + Qt::Horizontal + + + + + + + + + English + + + + English + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Maximum Search Results + + + + + + + 1 + + + 9999 + + + + + + + Qt::RightToLeft + + + Use In-Memory Database + + + false + + + + + + + + + + + Hotkey to use for opening unassigned items: + + + + + + + + + + true + + + Double Click + + + + + + + ... + + + QToolButton::InstantPopup + + + + + + + + + + + Database location: + + + + + + + + + + ... + + + + + + + + + + + Maintenance utilities: + + + + + + + Test Button 1 + + + + + + + Clear Data + + + + + + + + + Qt::Horizontal + + + + + + + + + ... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + NONE + + + + + TIMER + + + + + ALL + + + + + + + + Qt::LeftToRight + + + Debug Mode + + + + + + + Discard + + + + + + + Save + + + + + + + + + + + + diff --git a/python3.7libs/searcher/ui_files/about.py b/python3.7libs/searcher/ui_files/about.py new file mode 100644 index 0000000..d334bba --- /dev/null +++ b/python3.7libs/searcher/ui_files/about.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'about.ui' +# +# Created by: qtpy UI code generator 5.14.1 +# +# WARNING! All changes made in this file will be lost! + + +from qtpy import QtCore, QtGui, QtWidgets + + +class Ui_About(object): + def setupUi(self, About): + About.setObjectName("About") + About.setWindowModality(QtCore.Qt.NonModal) + About.resize(384, 135) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(About.sizePolicy().hasHeightForWidth()) + About.setSizePolicy(sizePolicy) + About.setMinimumSize(QtCore.QSize(100, 0)) + About.setBaseSize(QtCore.QSize(0, 0)) + About.setStyleSheet("") + self.gridLayout = QtWidgets.QGridLayout(About) + self.gridLayout.setContentsMargins(-1, -1, -1, 6) + self.gridLayout.setSpacing(6) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout_4 = QtWidgets.QVBoxLayout() + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem) + self.secondrow = QtWidgets.QHBoxLayout() + self.secondrow.setObjectName("secondrow") + self.web = QtWidgets.QLabel(About) + self.web.setObjectName("web") + self.secondrow.addWidget(self.web) + self.verticalLayout.addLayout(self.secondrow) + self.headerrow = QtWidgets.QHBoxLayout() + self.headerrow.setObjectName("headerrow") + self.github = QtWidgets.QLabel(About) + self.github.setObjectName("github") + self.headerrow.addWidget(self.github) + self.verticalLayout.addLayout(self.headerrow) + self.horizontalLayout.addLayout(self.verticalLayout) + self.verticalLayout_4.addLayout(self.horizontalLayout) + self.gridLayout.addLayout(self.verticalLayout_4, 0, 0, 1, 1) + self.logo = QtWidgets.QLabel(About) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.logo.sizePolicy().hasHeightForWidth()) + self.logo.setSizePolicy(sizePolicy) + self.logo.setMaximumSize(QtCore.QSize(120, 120)) + self.logo.setText("") + self.logo.setPixmap(QtGui.QPixmap("C:/Users/mosthated/Downloads/483688212.png")) + self.logo.setScaledContents(True) + self.logo.setObjectName("logo") + self.gridLayout.addWidget(self.logo, 0, 1, 1, 1) + + self.retranslateUi(About) + QtCore.QMetaObject.connectSlotsByName(About) + + def retranslateUi(self, About): + _translate = QtCore.QCoreApplication.translate + About.setWindowTitle(_translate("About", "Form")) + self.web.setText(_translate("About", "instance.id")) + self.github.setText(_translate("About", "github.com/instance-id")) diff --git a/python3.7libs/searcher/ui_files/about.ui b/python3.7libs/searcher/ui_files/about.ui new file mode 100644 index 0000000..45c7273 --- /dev/null +++ b/python3.7libs/searcher/ui_files/about.ui @@ -0,0 +1,123 @@ + + + About + + + Qt::NonModal + + + + 0 + 0 + 384 + 135 + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 0 + 0 + + + + Form + + + + + + + 6 + + + 6 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + instance.id + + + + + + + + + + + github.com/instance-id + + + + + + + + + + + + + + + + 0 + 0 + + + + + 120 + 120 + + + + + + + C:/Users/mosthated/Downloads/483688212.png + + + true + + + + + + + + diff --git a/python3.7libs/searcher/ui_files/bugreport.bak.ui b/python3.7libs/searcher/ui_files/bugreport.bak.ui new file mode 100644 index 0000000..81b2dae --- /dev/null +++ b/python3.7libs/searcher/ui_files/bugreport.bak.ui @@ -0,0 +1,165 @@ + + + BugReport + + + Qt::NonModal + + + + 0 + 0 + 393 + 172 + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 0 + 0 + + + + Form + + + + + + + 6 + + + 6 + + + + + + + + + + + + + + 175 + 0 + + + + Name: + + + + + + + + + + + + 175 + 0 + + + + Contact: + + + + + + + + + + + What was the issue? + + + + + + + Qt::Vertical + + + + 0 + 40 + + + + + + + + + + + + + + + + + 0 + 0 + + + + + 120 + 120 + + + + + + + C:/Users/mosthated/Downloads/483688212.png + + + true + + + + + + + + + + + Submit Bug + + + + + + + + + + + + + + + + diff --git a/python3.7libs/searcher/ui_files/bugreport.py b/python3.7libs/searcher/ui_files/bugreport.py new file mode 100644 index 0000000..5236825 --- /dev/null +++ b/python3.7libs/searcher/ui_files/bugreport.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'bugreport.ui' +# +# Created by: qtpy UI code generator 5.14.1 +# +# WARNING! All changes made in this file will be lost! + + +from qtpy import QtCore, QtGui, QtWidgets + + +class Ui_BugReport(object): + def setupUi(self, BugReport): + BugReport.setObjectName("BugReport") + BugReport.setWindowModality(QtCore.Qt.NonModal) + BugReport.resize(393, 172) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(BugReport.sizePolicy().hasHeightForWidth()) + BugReport.setSizePolicy(sizePolicy) + BugReport.setMinimumSize(QtCore.QSize(100, 0)) + BugReport.setBaseSize(QtCore.QSize(0, 0)) + BugReport.setStyleSheet("") + self.gridLayout = QtWidgets.QGridLayout(BugReport) + self.gridLayout.setContentsMargins(-1, -1, -1, 6) + self.gridLayout.setSpacing(6) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout_4 = QtWidgets.QVBoxLayout() + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.secondrow = QtWidgets.QHBoxLayout() + self.secondrow.setObjectName("secondrow") + self.title = QtWidgets.QLineEdit(BugReport) + self.title.setMinimumSize(QtCore.QSize(175, 0)) + self.title.setObjectName("title") + self.secondrow.addWidget(self.title) + self.edittitle_btn = QtWidgets.QPushButton(BugReport) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.edittitle_btn.sizePolicy().hasHeightForWidth()) + self.edittitle_btn.setSizePolicy(sizePolicy) + self.edittitle_btn.setMaximumSize(QtCore.QSize(55, 16777215)) + self.edittitle_btn.setObjectName("edittitle") + self.secondrow.addWidget(self.edittitle_btn) + self.verticalLayout_4.addLayout(self.secondrow) + self.webview = QtWidgets.QLabel(BugReport) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.webview.sizePolicy().hasHeightForWidth()) + self.webview.setSizePolicy(sizePolicy) + self.webview.setObjectName("webview") + self.verticalLayout_4.addWidget(self.webview) + self.gridLayout.addLayout(self.verticalLayout_4, 0, 0, 1, 1) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) + self.horizontalLayout.setObjectName("horizontalLayout") + spacerItem = QtWidgets.QSpacerItem(40, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.continue_btn = QtWidgets.QPushButton(BugReport) + self.continue_btn.setObjectName("continue_btn") + self.horizontalLayout.addWidget(self.continue_btn) + self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1) + + self.retranslateUi(BugReport) + QtCore.QMetaObject.connectSlotsByName(BugReport) + + def retranslateUi(self, BugReport): + _translate = QtCore.QCoreApplication.translate + BugReport.setWindowTitle(_translate("BugReport", "Form")) + self.title.setPlaceholderText(_translate("BugReport", "Please enter descriptive bug report title")) + self.edittitle_btn.setText(_translate("BugReport", "Edit")) + self.webview.setText(_translate("BugReport", "TextLabel")) + self.continue_btn.setText(_translate("BugReport", "Continue")) diff --git a/python3.7libs/searcher/ui_files/bugreport.ui b/python3.7libs/searcher/ui_files/bugreport.ui new file mode 100644 index 0000000..b0a9cfa --- /dev/null +++ b/python3.7libs/searcher/ui_files/bugreport.ui @@ -0,0 +1,154 @@ + + + BugReport + + + Qt::NonModal + + + + 0 + 0 + 393 + 172 + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 0 + 0 + + + + Form + + + + + + + 6 + + + 6 + + + + + + + + + Qt::RightToLeft + + + QComboBox::AdjustToContents + + + false + + + + 123 + + + + + 123123 + + + + + + + + + 175 + 0 + + + + Please enter descriptive bug report title + + + + + + + + 0 + 0 + + + + + 55 + 16777215 + + + + Edit Title + + + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + + + QLayout::SetDefaultConstraint + + + + + Qt::Horizontal + + + + 40 + 10 + + + + + + + + Continue + + + + + + + + + + diff --git a/python3.7libs/searcher/ui_files/searcher_ui.py b/python3.7libs/searcher/ui_files/searcher_ui.py new file mode 100644 index 0000000..52e4c64 --- /dev/null +++ b/python3.7libs/searcher/ui_files/searcher_ui.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'searcher_ui.ui' +# +# Created by: qtpy UI code generator 5.14.1 +# +# WARNING! All changes made in this file will be lost! + + +from qtpy import QtCore, QtGui, QtWidgets + + +class Ui_Searcher(object): + def setupUi(self, Searcher): + Searcher.setObjectName("Searcher") + Searcher.setWindowModality(QtCore.Qt.WindowModal) + Searcher.resize(1000, 329) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(Searcher.sizePolicy().hasHeightForWidth()) + Searcher.setSizePolicy(sizePolicy) + Searcher.setMinimumSize(QtCore.QSize(0, 0)) + Searcher.setBaseSize(QtCore.QSize(1000, 350)) + Searcher.setStyleSheet("QTreeWidget QHeaderView::section {\n" +" font-size: 9pt;\n" +"}") + self.gridLayout = QtWidgets.QGridLayout(Searcher) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setSpacing(0) + self.verticalLayout.setObjectName("verticalLayout") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setSpacing(0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.frame = QtWidgets.QFrame(Searcher) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(2) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setMinimumSize(QtCore.QSize(0, 20)) + self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.frame.setObjectName("frame") + self.searchfilter_btn = QtWidgets.QToolButton(self.frame) + self.searchfilter_btn.setGeometry(QtCore.QRect(0, 0, 26, 20)) + self.searchfilter_btn.setBaseSize(QtCore.QSize(16, 16)) + self.searchfilter_btn.setStyleSheet("background-color: rgb(19, 19, 19);") + self.searchfilter_btn.setArrowType(QtCore.Qt.NoArrow) + self.searchfilter_btn.setObjectName("searchfilter_btn") + self.horizontalLayout_3.addWidget(self.frame) + self.searchbox_txt = QtWidgets.QLineEdit(Searcher) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(99) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.searchbox_txt.sizePolicy().hasHeightForWidth()) + self.searchbox_txt.setSizePolicy(sizePolicy) + self.searchbox_txt.setMinimumSize(QtCore.QSize(50, 0)) + self.searchbox_txt.setMouseTracking(False) + self.searchbox_txt.setStyleSheet("background-color: rgb(19, 19, 19);") + self.searchbox_txt.setFrame(False) + self.searchbox_txt.setObjectName("searchbox_txt") + self.horizontalLayout_3.addWidget(self.searchbox_txt) + self.verticalLayout.addLayout(self.horizontalLayout_3) + self.searchresults_tree = QtWidgets.QTreeWidget(Searcher) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.searchresults_tree.sizePolicy().hasHeightForWidth()) + self.searchresults_tree.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(9) + self.searchresults_tree.setFont(font) + self.searchresults_tree.setMouseTracking(False) + self.searchresults_tree.setFocusPolicy(QtCore.Qt.NoFocus) + self.searchresults_tree.setFrameShadow(QtWidgets.QFrame.Sunken) + self.searchresults_tree.setLineWidth(0) + self.searchresults_tree.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) + self.searchresults_tree.setAlternatingRowColors(True) + self.searchresults_tree.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) + self.searchresults_tree.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) + self.searchresults_tree.setObjectName("searchresults_tree") + self.searchresults_tree.headerItem().setText(0, "1") + self.verticalLayout.addWidget(self.searchresults_tree) + self.gridLayout.addLayout(self.verticalLayout, 1, 0, 1, 1) + self.infobar = QtWidgets.QHBoxLayout() + self.infobar.setObjectName("infobar") + self.infobargrid = QtWidgets.QGridLayout() + self.infobargrid.setObjectName("infobargrid") + self.info_lbl = QtWidgets.QLabel(Searcher) + font = QtGui.QFont() + font.setPointSize(8) + font.setBold(False) + font.setWeight(50) + self.info_lbl.setFont(font) + self.info_lbl.setStyleSheet("background-color: rgb(26, 26, 26);") + self.info_lbl.setIndent(5) + self.info_lbl.setObjectName("info_lbl") + self.infobargrid.addWidget(self.info_lbl, 1, 0, 1, 1) + self.label = QtWidgets.QLabel(Searcher) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) + self.label.setSizePolicy(sizePolicy) + self.label.setMaximumSize(QtCore.QSize(50, 16777215)) + self.label.setLayoutDirection(QtCore.Qt.RightToLeft) + self.label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label.setObjectName("label") + self.infobargrid.addWidget(self.label, 1, 1, 1, 1) + self.infobar.addLayout(self.infobargrid) + self.gridLayout.addLayout(self.infobar, 3, 0, 1, 1) + + self.retranslateUi(Searcher) + QtCore.QMetaObject.connectSlotsByName(Searcher) + + def retranslateUi(self, Searcher): + _translate = QtCore.QCoreApplication.translate + Searcher.setWindowTitle(_translate("Searcher", "Searcher")) + self.searchfilter_btn.setText(_translate("Searcher", "...")) + self.info_lbl.setText(_translate("Searcher", "Begin typing to search or click magnifying glass icon to display options")) + self.label.setText(_translate("Searcher", "TextLabel")) diff --git a/python3.7libs/searcher/ui_files/searcher_ui.ui b/python3.7libs/searcher/ui_files/searcher_ui.ui new file mode 100644 index 0000000..2189a62 --- /dev/null +++ b/python3.7libs/searcher/ui_files/searcher_ui.ui @@ -0,0 +1,248 @@ + + + Searcher + + + Qt::WindowModal + + + + 0 + 0 + 1000 + 329 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 1000 + 350 + + + + Searcher + + + QTreeWidget QHeaderView::section { + font-size: 9pt; +} + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + 0 + + + + + + 2 + 0 + + + + + 0 + 20 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 26 + 20 + + + + + 16 + 16 + + + + background-color: rgb(19, 19, 19); + + + ... + + + Qt::NoArrow + + + + + + + + + 99 + 0 + + + + + 50 + 0 + + + + false + + + background-color: rgb(19, 19, 19); + + + false + + + + + + + + + + 0 + 0 + + + + + 9 + + + + false + + + Qt::NoFocus + + + QFrame::Sunken + + + 0 + + + QAbstractScrollArea::AdjustToContents + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + 1 + + + + + + + + + + + + + + + 8 + 50 + false + + + + background-color: rgb(26, 26, 26); + + + Begin typing to search or click magnifying glass icon to display options + + + 2 + + + 5 + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Qt::RightToLeft + + + TextLabel + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + diff --git a/python3.7libs/searcher/ui_files/theme_tabs.py b/python3.7libs/searcher/ui_files/theme_tabs.py new file mode 100644 index 0000000..410a2ea --- /dev/null +++ b/python3.7libs/searcher/ui_files/theme_tabs.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'theme_tabs.ui' +# +# Created by: qtpy UI code generator 5.14.1 +# +# WARNING! All changes made in this file will be lost! + + +from qtpy import QtCore, QtGui, QtWidgets + + +class Ui_Theme(object): + def setupUi(self, Theme): + Theme.setObjectName("Theme") + Theme.setWindowModality(QtCore.Qt.NonModal) + Theme.resize(556, 206) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(Theme.sizePolicy().hasHeightForWidth()) + Theme.setSizePolicy(sizePolicy) + Theme.setMinimumSize(QtCore.QSize(100, 0)) + Theme.setBaseSize(QtCore.QSize(0, 0)) + Theme.setStyleSheet("") + self.gridLayout = QtWidgets.QGridLayout(Theme) + self.gridLayout.setContentsMargins(-1, -1, -1, 6) + self.gridLayout.setSpacing(6) + self.gridLayout.setObjectName("gridLayout") + self.r2 = QtWidgets.QVBoxLayout() + self.r2.setObjectName("r2") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_2.addItem(spacerItem) + self.discardtheme = QtWidgets.QPushButton(Theme) + self.discardtheme.setObjectName("discardtheme") + self.horizontalLayout_2.addWidget(self.discardtheme) + self.savetheme = QtWidgets.QPushButton(Theme) + self.savetheme.setObjectName("savetheme") + self.horizontalLayout_2.addWidget(self.savetheme) + self.r2.addLayout(self.horizontalLayout_2) + self.gridLayout.addLayout(self.r2, 2, 0, 1, 1) + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.tabWidget = QtWidgets.QTabWidget(Theme) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.layoutWidget = QtWidgets.QWidget(self.tab) + self.layoutWidget.setGeometry(QtCore.QRect(0, 0, 533, 164)) + self.layoutWidget.setObjectName("layoutWidget") + self.r1 = QtWidgets.QHBoxLayout(self.layoutWidget) + self.r1.setContentsMargins(6, 6, 6, 0) + self.r1.setObjectName("r1") + self.c1 = QtWidgets.QVBoxLayout() + self.c1.setObjectName("c1") + self.h4_c1 = QtWidgets.QHBoxLayout() + self.h4_c1.setObjectName("h4_c1") + self.text2_lbl = QtWidgets.QLabel(self.layoutWidget) + self.text2_lbl.setObjectName("text2_lbl") + self.h4_c1.addWidget(self.text2_lbl) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h4_c1.addItem(spacerItem1) + self.text2_btn = QtWidgets.QToolButton(self.layoutWidget) + self.text2_btn.setText("") + self.text2_btn.setObjectName("text2_btn") + self.h4_c1.addWidget(self.text2_btn) + self.text2 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.text2.sizePolicy().hasHeightForWidth()) + self.text2.setSizePolicy(sizePolicy) + self.text2.setMinimumSize(QtCore.QSize(75, 0)) + self.text2.setMaximumSize(QtCore.QSize(75, 16777215)) + self.text2.setBaseSize(QtCore.QSize(75, 0)) + self.text2.setReadOnly(True) + self.text2.setObjectName("text2") + self.h4_c1.addWidget(self.text2) + spacerItem2 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h4_c1.addItem(spacerItem2) + self.c1.addLayout(self.h4_c1) + self.h1_c2 = QtWidgets.QHBoxLayout() + self.h1_c2.setObjectName("h1_c2") + self.tooltip_lbl = QtWidgets.QLabel(self.layoutWidget) + self.tooltip_lbl.setObjectName("tooltip_lbl") + self.h1_c2.addWidget(self.tooltip_lbl) + self.tooltip_btn = QtWidgets.QToolButton(self.layoutWidget) + self.tooltip_btn.setText("") + self.tooltip_btn.setObjectName("tooltip_btn") + self.h1_c2.addWidget(self.tooltip_btn) + self.tooltip = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tooltip.sizePolicy().hasHeightForWidth()) + self.tooltip.setSizePolicy(sizePolicy) + self.tooltip.setMinimumSize(QtCore.QSize(75, 0)) + self.tooltip.setMaximumSize(QtCore.QSize(75, 16777215)) + self.tooltip.setReadOnly(True) + self.tooltip.setObjectName("tooltip") + self.h1_c2.addWidget(self.tooltip) + spacerItem3 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h1_c2.addItem(spacerItem3) + self.c1.addLayout(self.h1_c2) + self.h3_c1 = QtWidgets.QHBoxLayout() + self.h3_c1.setObjectName("h3_c1") + self.text1_lbl = QtWidgets.QLabel(self.layoutWidget) + self.text1_lbl.setObjectName("text1_lbl") + self.h3_c1.addWidget(self.text1_lbl) + spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h3_c1.addItem(spacerItem4) + self.text1_btn = QtWidgets.QToolButton(self.layoutWidget) + self.text1_btn.setText("") + self.text1_btn.setObjectName("text1_btn") + self.h3_c1.addWidget(self.text1_btn) + self.text1 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.text1.sizePolicy().hasHeightForWidth()) + self.text1.setSizePolicy(sizePolicy) + self.text1.setMinimumSize(QtCore.QSize(75, 0)) + self.text1.setMaximumSize(QtCore.QSize(75, 16777215)) + self.text1.setBaseSize(QtCore.QSize(75, 0)) + self.text1.setReadOnly(True) + self.text1.setObjectName("text1") + self.h3_c1.addWidget(self.text1) + spacerItem5 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h3_c1.addItem(spacerItem5) + self.c1.addLayout(self.h3_c1) + self.h2_c1 = QtWidgets.QHBoxLayout() + self.h2_c1.setObjectName("h2_c1") + self.stats1_lbl = QtWidgets.QLabel(self.layoutWidget) + self.stats1_lbl.setObjectName("stats1_lbl") + self.h2_c1.addWidget(self.stats1_lbl) + spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h2_c1.addItem(spacerItem6) + self.stats1_btn = QtWidgets.QToolButton(self.layoutWidget) + self.stats1_btn.setText("") + self.stats1_btn.setObjectName("stats1_btn") + self.h2_c1.addWidget(self.stats1_btn) + self.stats1 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.stats1.sizePolicy().hasHeightForWidth()) + self.stats1.setSizePolicy(sizePolicy) + self.stats1.setMinimumSize(QtCore.QSize(75, 0)) + self.stats1.setMaximumSize(QtCore.QSize(75, 16777215)) + self.stats1.setBaseSize(QtCore.QSize(75, 0)) + self.stats1.setReadOnly(True) + self.stats1.setObjectName("stats1") + self.h2_c1.addWidget(self.stats1) + spacerItem7 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h2_c1.addItem(spacerItem7) + self.c1.addLayout(self.h2_c1) + spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.c1.addItem(spacerItem8) + self.r1.addLayout(self.c1) + self.c2 = QtWidgets.QVBoxLayout() + self.c2.setObjectName("c2") + self.h1_c1 = QtWidgets.QHBoxLayout() + self.h1_c1.setObjectName("h1_c1") + self.stats2_lbl = QtWidgets.QLabel(self.layoutWidget) + self.stats2_lbl.setObjectName("stats2_lbl") + self.h1_c1.addWidget(self.stats2_lbl) + spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h1_c1.addItem(spacerItem9) + spacerItem10 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.h1_c1.addItem(spacerItem10) + self.stats2_btn = QtWidgets.QToolButton(self.layoutWidget) + self.stats2_btn.setText("") + self.stats2_btn.setObjectName("stats2_btn") + self.h1_c1.addWidget(self.stats2_btn) + self.stats2 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.stats2.sizePolicy().hasHeightForWidth()) + self.stats2.setSizePolicy(sizePolicy) + self.stats2.setMinimumSize(QtCore.QSize(75, 0)) + self.stats2.setMaximumSize(QtCore.QSize(75, 16777215)) + self.stats2.setBaseSize(QtCore.QSize(75, 0)) + self.stats2.setReadOnly(True) + self.stats2.setObjectName("stats2") + self.h1_c1.addWidget(self.stats2) + self.c2.addLayout(self.h1_c1) + self.h2_c2 = QtWidgets.QHBoxLayout() + self.h2_c2.setObjectName("h2_c2") + self.label_7 = QtWidgets.QLabel(self.layoutWidget) + self.label_7.setEnabled(True) + self.label_7.setObjectName("label_7") + self.h2_c2.addWidget(self.label_7) + spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h2_c2.addItem(spacerItem11) + self.toolButton_6 = QtWidgets.QToolButton(self.layoutWidget) + self.toolButton_6.setText("") + self.toolButton_6.setObjectName("toolButton_6") + self.h2_c2.addWidget(self.toolButton_6) + self.lineEdit_3 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit_3.sizePolicy().hasHeightForWidth()) + self.lineEdit_3.setSizePolicy(sizePolicy) + self.lineEdit_3.setMinimumSize(QtCore.QSize(75, 0)) + self.lineEdit_3.setMaximumSize(QtCore.QSize(75, 16777215)) + self.lineEdit_3.setReadOnly(True) + self.lineEdit_3.setObjectName("lineEdit_3") + self.h2_c2.addWidget(self.lineEdit_3) + self.c2.addLayout(self.h2_c2) + self.h3_c2 = QtWidgets.QHBoxLayout() + self.h3_c2.setObjectName("h3_c2") + self.label_6 = QtWidgets.QLabel(self.layoutWidget) + self.label_6.setObjectName("label_6") + self.h3_c2.addWidget(self.label_6) + spacerItem12 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h3_c2.addItem(spacerItem12) + self.toolButton_7 = QtWidgets.QToolButton(self.layoutWidget) + self.toolButton_7.setText("") + self.toolButton_7.setObjectName("toolButton_7") + self.h3_c2.addWidget(self.toolButton_7) + self.lineEdit_4 = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit_4.sizePolicy().hasHeightForWidth()) + self.lineEdit_4.setSizePolicy(sizePolicy) + self.lineEdit_4.setMinimumSize(QtCore.QSize(75, 0)) + self.lineEdit_4.setMaximumSize(QtCore.QSize(75, 16777215)) + self.lineEdit_4.setReadOnly(True) + self.lineEdit_4.setObjectName("lineEdit_4") + self.h3_c2.addWidget(self.lineEdit_4) + self.c2.addLayout(self.h3_c2) + self.h4_c2 = QtWidgets.QHBoxLayout() + self.h4_c2.setObjectName("h4_c2") + self.label_5 = QtWidgets.QLabel(self.layoutWidget) + self.label_5.setObjectName("label_5") + self.h4_c2.addWidget(self.label_5) + spacerItem13 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.h4_c2.addItem(spacerItem13) + self.toolButton_8 = QtWidgets.QToolButton(self.layoutWidget) + self.toolButton_8.setText("") + self.toolButton_8.setObjectName("toolButton_8") + self.h4_c2.addWidget(self.toolButton_8) + self.lineEdit = QtWidgets.QLineEdit(self.layoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth()) + self.lineEdit.setSizePolicy(sizePolicy) + self.lineEdit.setMinimumSize(QtCore.QSize(75, 0)) + self.lineEdit.setMaximumSize(QtCore.QSize(75, 16777215)) + self.lineEdit.setReadOnly(True) + self.lineEdit.setObjectName("lineEdit") + self.h4_c2.addWidget(self.lineEdit) + self.c2.addLayout(self.h4_c2) + spacerItem14 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.c2.addItem(spacerItem14) + self.r1.addLayout(self.c2) + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setObjectName("tab_2") + self.tabWidget.addTab(self.tab_2, "") + self.verticalLayout.addWidget(self.tabWidget) + self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) + + self.retranslateUi(Theme) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(Theme) + + def retranslateUi(self, Theme): + _translate = QtCore.QCoreApplication.translate + Theme.setWindowTitle(_translate("Theme", "Form")) + self.discardtheme.setText(_translate("Theme", "Discard")) + self.savetheme.setText(_translate("Theme", "Save")) + self.text2_lbl.setText(_translate("Theme", "Search Results Context")) + self.tooltip_lbl.setText(_translate("Theme", "Tool Tip Info")) + self.text1_lbl.setText(_translate("Theme", "Result Stats Text")) + self.stats1_lbl.setText(_translate("Theme", "Result Stat Values")) + self.stats2_lbl.setText(_translate("Theme", "Secondary Stat Values")) + self.label_7.setText(_translate("Theme", "TextLabel")) + self.label_6.setText(_translate("Theme", "TextLabel")) + self.label_5.setText(_translate("Theme", "TextLabel")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Theme", "Text")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Theme", "Window")) diff --git a/python3.7libs/searcher/ui_files/theme_tabs.ui b/python3.7libs/searcher/ui_files/theme_tabs.ui new file mode 100644 index 0000000..ddde525 --- /dev/null +++ b/python3.7libs/searcher/ui_files/theme_tabs.ui @@ -0,0 +1,704 @@ + + + Theme + + + Qt::NonModal + + + + 0 + 0 + 556 + 206 + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 0 + 0 + + + + Form + + + + + + + 6 + + + 6 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Discard + + + + + + + Save + + + + + + + + + + + + + 0 + + + + Text + + + + + 0 + 0 + 533 + 164 + + + + + 6 + + + 6 + + + 6 + + + + + + + + + Search Results Context + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + + 75 + 0 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + Tool Tip Info + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + Result Stats Text + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + + 75 + 0 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + Result Stat Values + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + + 75 + 0 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Secondary Stat Values + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + + 75 + 0 + + + + true + + + + + + + + + + + true + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + true + + + + + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + true + + + + + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 16777215 + + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Window + + + + + + + + + + + diff --git a/python3.7libs/searcher/util.py b/python3.7libs/searcher/util.py new file mode 100644 index 0000000..2f9b5a7 --- /dev/null +++ b/python3.7libs/searcher/util.py @@ -0,0 +1,724 @@ +from __future__ import print_function +from __future__ import absolute_import + +import sys + +from searcher import enum + +from typing import Tuple +import os +import hou + +hver = 0 +if os.environ["HFS"] != "" or os.environ["HFS"] is not None: + ver = os.environ["HFS"] + # hver = int(ver[ver.rindex('.') + 1:]) + from hutil.Qt import QtCore +else: + from qtpy import QtCore + +script_path = os.path.dirname(os.path.realpath(__file__)) + +# @formatter:off ---------------------------------------- Helper Functions +# SECTION Helper Functions ----------------------------------------------- +# @formatter:off ------------------------------ DEBUG_LEVEL +# NOTE DEBUG_LEVEL ---------------------------------------- +DEBUG_LEVEL = enum.Enum('NONE', 'TIMER', 'ALL') +class Dbug(object): + def __init__(self, enabled, level, perf, mainwindow=False): + self.enabled = enabled + self.level = level + self.performance = perf + self.mainwindow = mainwindow + + def __nonzero__(self): return bool(self.enabled) + +class AppColors(object): + def __init__(self, colors={}): + self.text1 = colors[COLORFIELDS[0]] + self.text2 = colors[COLORFIELDS[1]] + self.stats1 = colors[COLORFIELDS[2]] + self.stats2 = colors[COLORFIELDS[3]] + self.tooltip = colors[COLORFIELDS[4]] + +# @formatter:off ----------------------------- get_platform +# NOTE get_platform --------------------------------------- +def get_platform(): + return getattr(hou.session, "PLATFORM", None) + +# @formatter:off ----------------------------- get_settings +# NOTE get_settings --------------------------------------- +def get_settings(): + return getattr(hou.session, "SETTINGS", None) + + +# @formatter:off ----------------------------- get_settings +# NOTE get_settings --------------------------------------- +def get_path(folders=None): + s_path = os.path.dirname(os.path.realpath(__file__)) + path = os.path.join(s_path, '/'.join(folders)) + return path.replace("\\", "/") + +# @formatter:off --------------------------- Bool Converter +# NOTE Bool Converter ------------------------------------- +def bc(v): + return str(v).lower() in ("yes", "true", "t", "1") + +# !SECTION Helper Functions + + +# @formatter:off ------------------------------------------------ Settings +# SECTION Settings ------------------------------------------------------- +# @formatter:off ---------------------------- SETTINGS_KEYS +# NOTE SETTINGS_KEYS -------------------------------------- +SETTINGS_KEYS = [ + 'in_memory_db', # 0 + 'database_path', # 1 + 'savewindowsize', # 2 + 'windowsize', # 3 + 'debugflag', # 4 + 'pinwindow', # 5 + 'defaulthotkey', # 6 + 'showctx', # 7 + 'animatedsettings', # 8 + 'maxresults', # 9 + 'debuglevel', # 10 + 'lastkey', # 11 + 'metrics', # 12 + 'metricsmainwindow', # 13 + 'appcolors', # 14 + 'expanditems', # 15 +] + +# @formatter:off ------------------------------ COLORFIELDS +# The names of the customizable colorfields +# NOTE COLORFIELDS ---------------------------------------- +COLORFIELDS = [ + 'text1', # 0 + 'text2', # 1 + 'stats1', # 2 + 'stats2', # 3 + 'tooltip', # 4 +] + +# @formatter:off --------------------------- SETTINGS_TYPES +# Include type if it is to be processed, else mark NA +# {bool, text, int, intval} get processed by settings menu +# {flag} is a bool but handled separate from settings menu +# {NA} is other, handled separaretly as well +# NOTE SETTINGS_TYPES ------------------------------------- +SETTINGS_TYPES = { + SETTINGS_KEYS[0]: 'bool', # in_memory_db + SETTINGS_KEYS[1]: 'text', # database_path + SETTINGS_KEYS[2]: 'bool', # savewindowsize + SETTINGS_KEYS[3]: 'int', # windowsize + SETTINGS_KEYS[4]: 'bool', # debugflag + SETTINGS_KEYS[5]: 'flag', # pinwindow + SETTINGS_KEYS[6]: 'text', # defaulthotkey + SETTINGS_KEYS[7]: 'flag', # showctx + SETTINGS_KEYS[8]: 'bool', # animatedsettings + SETTINGS_KEYS[9]: 'intval', # maxresults + SETTINGS_KEYS[10]: 'cbx', # debuglevel + SETTINGS_KEYS[11]: 'NA', # lastkey + SETTINGS_KEYS[12]: 'bool', # metrics + SETTINGS_KEYS[13]: 'flag', # metricsmainwindow + SETTINGS_KEYS[14]: 'NA', # appcolors + SETTINGS_KEYS[15]: 'flag', # expanditems +} + +# @formatter:off ------------------------- DEFAULT_SETTINGS +# Default settings automatically applied upon creations +# NOTE DEFAULT_SETTINGS ----------------------------------- +defaultHKeys = u"Cmd+Alt+Shift+F7" if sys.platform == 'darwin' else u"Ctrl+Alt+Shift+F7" +DEFAULT_SETTINGS = { + SETTINGS_KEYS[0]: "False", # in_memory_db + SETTINGS_KEYS[1]: "", # database_path + SETTINGS_KEYS[2]: "True", # savewindowsize + SETTINGS_KEYS[3]: [750, 350], # windowsize + SETTINGS_KEYS[4]: "False", # debugflag + SETTINGS_KEYS[5]: "False", # pinwindow + SETTINGS_KEYS[6]: defaultHKeys, # defaulthotkey + SETTINGS_KEYS[7]: "True", # showctx + SETTINGS_KEYS[8]: "True", # animatedsettings + SETTINGS_KEYS[9]: 100, # maxresults + SETTINGS_KEYS[10]: "NONE", # debuglevel + SETTINGS_KEYS[11]: "", # lastkey + SETTINGS_KEYS[12]: "False", # metrics + SETTINGS_KEYS[13]: "False", # metricsmainwindow + SETTINGS_KEYS[14]: { # appcolors + COLORFIELDS[0]: "#607FAE", # text1 + COLORFIELDS[1]: "#D2A00C", # text2 + COLORFIELDS[2]: "#c2efe5", # stats1 + COLORFIELDS[3]: "#c2efe5", # stats2 + COLORFIELDS[4]: "#607FAE", # tooltip + }, + SETTINGS_KEYS[15]: "True", # expanditems +} +# !SECTION Settings + +# @formatter:off ---------------------------------------- Key Translations +# SECTION Key Translations ----------------------------------------------- + +# @formatter:off ------------------------------ CTXSHOTCUTS +# Context shortcodes for predefined results +# NOTE CTXSHOTCUTS ---------------------------------------- +CTXSHOTCUTS = [":v", ":c", ":g"] + +# @formatter:off --------------------------- KEYCONVERSIONS +# Convertions for arrow keys (Should be moved to main dict) +# NOTE KEYCONVERSIONS ------------------------------------- +KEYCONVERSIONS = { + "DownArrow": "down", + "UpArrow": "up", + "LeftArrow": "left", + "RightArrow": "right", +} + +# @formatter:off ------------------------------- HOTKEYLIST +# List of possible hotkeys to use a temp keys when running commands +# NOTE HOTKEYLIST ----------------------------------------- +HOTKEYLIST = [ + u"Ctrl+Alt+Shift+F7", + u"Ctrl+Alt+Shift+F6", + u"Ctrl+Alt+Shift+F8", + u"Ctrl+Alt+Shift+F9", + u"Ctrl+Alt+Shift+F10" +] + +HOTKEYLISTOSX = [ + u"Cmd+Alt+Shift+F7", + u"Cmd+Alt+Shift+F6", + u"Cmd+Alt+Shift+F8", + u"Cmd+Alt+Shift+F9", + u"Cmd+Alt+Shift+F10" +] + +def gethotkeys(): + hkeys = [] + settings = get_settings() + hkeys.append(settings[SETTINGS_KEYS[6]]) + hklist = HOTKEYLISTOSX if sys.platform == 'darwin' else HOTKEYLIST + for key in hklist: + hkeys.append(key) + return hkeys + + +# Used for bitmasking to determine modifiers +MODIFIERS = {} +# Used for constructing a bitmasked modifier +REVERSE_MODIFIERS = {} + +# @formatter:off ---------------------------- MODIFIER_KEYS +# Used to detect if a keypress was just a modifier +# NOTE MODIFIER_KEYS -------------------------------------- +MODIFIER_KEYS = { + QtCore.Qt.Key_Alt: "Alt", + QtCore.Qt.Key_Meta: "Cmd", + QtCore.Qt.Key_Shift: "Shift", + QtCore.Qt.Key_Control: "Ctrl", +} + +# @formatter:off -------------------------------- MODIFIERS +# NOTE MODIFIERS ------------------------------------------ +MODIFIERS = { + "Control": QtCore.Qt.ControlModifier, + "Ctrl": QtCore.Qt.ControlModifier, + "Shift": QtCore.Qt.ShiftModifier, + "Meta": QtCore.Qt.MetaModifier, + "Cmd": QtCore.Qt.MetaModifier, + "Alt": QtCore.Qt.AltModifier, +} + +# @formatter:off ----------------------------- SPECIAL_KEYS +# Special keys +# NOTE SPECIAL_KEYS --------------------------------------- +SPECIAL_KEYS = { + QtCore.Qt.Key_Backspace: "BACKSPACE", + QtCore.Qt.Key_Delete: "DELETE", + QtCore.Qt.Key_Escape: "ESCAPE", + QtCore.Qt.Key_hyphen: "HYPHEN", + QtCore.Qt.Key_Return: "RETURN", + QtCore.Qt.Key_Enter: "RETURN", + QtCore.Qt.Key_Space: "SPACE", + QtCore.Qt.Key_Tab: "TAB", + QtCore.Qt.Key_Left: "Left", + QtCore.Qt.Key_Right: "Right", + QtCore.Qt.Key_Up: "Up", + QtCore.Qt.Key_Down: "Down", + QtCore.Qt.Key_PageUp: "PageUp", + QtCore.Qt.Key_PageDown: "PageDown", + QtCore.Qt.Key_End: "Page_End", + QtCore.Qt.Key_Home: "Page_Home", +} + +# @formatter:off --------------------------------- Platform +# # Platform conversions +# NOTE Platform ------------------------------------------- +# if platform == "linux" or platform == "linux2": +# tmp = { +# QtCore.Qt.ShiftModifier: "Shift", +# QtCore.Qt.ControlModifier: "Ctrl", +# QtCore.Qt.AltModifier: "Alt", +# QtCore.Qt.MetaModifier: "M" +# } +# MODIFIERS.update(tmp) +# tmp = { +# "Shift": QtCore.Qt.ShiftModifier, +# "Ctrl": QtCore.Qt.ControlModifier, +# "Alt": QtCore.Qt.AltModifier +# } +# REVERSE_MODIFIERS.update(tmp) +# elif platform == "darwin": +# tmp = { +# QtCore.Qt.ShiftModifier: "s", +# QtCore.Qt.ControlModifier: "S", +# QtCore.Qt.AltModifier: "M", +# QtCore.Qt.MetaModifier: "C" +# } +# MODIFIERS.update(tmp) +# tmp = { +# "s": QtCore.Qt.ShiftModifier, +# "S": QtCore.Qt.ControlModifier, +# "M": QtCore.Qt.AltModifier, +# "C": QtCore.Qt.MetaModifier +# } +# REVERSE_MODIFIERS.update(tmp) +# elif platform == "win32" or platform == "win64": +# tmp = { +# QtCore.Qt.ShiftModifier: "Shift", +# QtCore.Qt.ControlModifier: "Ctrl", +# QtCore.Qt.AltModifier: "Alt", +# QtCore.Qt.MetaModifier: "M" +# } +# MODIFIERS.update(tmp) +# tmp = { +# "Shift": QtCore.Qt.ShiftModifier, +# "Ctrl": QtCore.Qt.ControlModifier, +# "Alt": QtCore.Qt.AltModifier +# } +# REVERSE_MODIFIERS.update(tmp) +# endregion + +# @formatter:off --------------------------------- KEY_DICT +# NOTE KEY_DICT ------------------------------------------- +KEY_DICT = { + # @formatter:off ---------------------- Grey keys + "Escape": QtCore.Qt.Key_Escape, + "Tab": QtCore.Qt.Key_Tab, + "Backtab": QtCore.Qt.Key_Backtab, + "Backspace": QtCore.Qt.Key_Backspace, + "Return": QtCore.Qt.Key_Return, + "Enter": QtCore.Qt.Key_Enter, + "Insert": QtCore.Qt.Key_Insert, + "Del": QtCore.Qt.Key_Delete, + "Pause": QtCore.Qt.Key_Pause, + "Print": QtCore.Qt.Key_Print, + "SysReq": QtCore.Qt.Key_SysReq, + "Home": QtCore.Qt.Key_Home, + "End": QtCore.Qt.Key_End, + "Left": QtCore.Qt.Key_Left, + "Up": QtCore.Qt.Key_Up, + "Right": QtCore.Qt.Key_Right, + "Down": QtCore.Qt.Key_Down, + "Prior": None, + "Next": None, + "Shift": QtCore.Qt.Key_Shift, + "Control": QtCore.Qt.Key_Control, + "Ctrl": QtCore.Qt.Key_Control, + "Cmd": QtCore.Qt.Key_Meta, + "Meta": QtCore.Qt.Key_Meta, + "Alt": QtCore.Qt.Key_Alt, + "CapsLock": QtCore.Qt.Key_CapsLock, + "NumLock": QtCore.Qt.Key_NumLock, + "ScrollLock": QtCore.Qt.Key_ScrollLock, + "F1": QtCore.Qt.Key_F1, + "F2": QtCore.Qt.Key_F2, + "F3": QtCore.Qt.Key_F3, + "F4": QtCore.Qt.Key_F4, + "F5": QtCore.Qt.Key_F5, + "F6": QtCore.Qt.Key_F6, + "F7": QtCore.Qt.Key_F7, + "F8": QtCore.Qt.Key_F8, + "F9": QtCore.Qt.Key_F9, + "F10": QtCore.Qt.Key_F10, + "F11": QtCore.Qt.Key_F11, + "F12": QtCore.Qt.Key_F12, + "F13": QtCore.Qt.Key_F13, + "F14": QtCore.Qt.Key_F14, + "F15": QtCore.Qt.Key_F15, + "F16": QtCore.Qt.Key_F16, + "F17": QtCore.Qt.Key_F17, + "F18": QtCore.Qt.Key_F18, + "F19": QtCore.Qt.Key_F19, + "F20": QtCore.Qt.Key_F20, + "F21": QtCore.Qt.Key_F21, + "F22": QtCore.Qt.Key_F22, + "F23": QtCore.Qt.Key_F23, + "F24": QtCore.Qt.Key_F24, + "F25": QtCore.Qt.Key_F25, + "F26": QtCore.Qt.Key_F26, + "F27": QtCore.Qt.Key_F27, + "F28": QtCore.Qt.Key_F28, + "F29": QtCore.Qt.Key_F29, + "F30": QtCore.Qt.Key_F30, + "F31": QtCore.Qt.Key_F31, + "F32": QtCore.Qt.Key_F32, + "F33": QtCore.Qt.Key_F33, + "F34": QtCore.Qt.Key_F34, + "F35": QtCore.Qt.Key_F35, + "Super_L": QtCore.Qt.Key_Super_L, + "Super_R": QtCore.Qt.Key_Super_R, + "Menu": QtCore.Qt.Key_Menu, + "Hyper_L": QtCore.Qt.Key_Hyper_L, + "Hyper_R": QtCore.Qt.Key_Hyper_R, + # @formatter:off ---------------------- Regular keys + "Space": QtCore.Qt.Key_Space, + "Exclam": QtCore.Qt.Key_Exclam, + "!": QtCore.Qt.Key_Exclam, + "QuoteDbl": QtCore.Qt.Key_QuoteDbl, + "\"": QtCore.Qt.Key_QuoteDbl, + "NumberSign": QtCore.Qt.Key_NumberSign, + "#": QtCore.Qt.Key_NumberSign, + "Dollar": QtCore.Qt.Key_Dollar, + "$": QtCore.Qt.Key_Dollar, + "Percent": QtCore.Qt.Key_Percent, + "%": QtCore.Qt.Key_Percent, + "Ampersand": QtCore.Qt.Key_Ampersand, + "&": QtCore.Qt.Key_Ampersand, + "Apostrophe": QtCore.Qt.Key_Apostrophe, + "\'": QtCore.Qt.Key_Apostrophe, + "ParenLeft": QtCore.Qt.Key_ParenLeft, + "(": QtCore.Qt.Key_ParenLeft, + "ParenRight": QtCore.Qt.Key_ParenRight, + ")": QtCore.Qt.Key_ParenRight, + "Asterisk": QtCore.Qt.Key_Asterisk, + "*": QtCore.Qt.Key_Asterisk, + "+": QtCore.Qt.Key_Plus, + "Plus": QtCore.Qt.Key_Plus, + "Comma": QtCore.Qt.Key_Comma, + ",": QtCore.Qt.Key_Comma, + "Minus": QtCore.Qt.Key_Minus, + "-": QtCore.Qt.Key_Minus, + "Period": QtCore.Qt.Key_Period, + ".": QtCore.Qt.Key_Period, + "Slash": QtCore.Qt.Key_Slash, + "/": QtCore.Qt.Key_Slash, + "0": QtCore.Qt.Key_0, + "1": QtCore.Qt.Key_1, + "2": QtCore.Qt.Key_2, + "3": QtCore.Qt.Key_3, + "4": QtCore.Qt.Key_4, + "5": QtCore.Qt.Key_5, + "6": QtCore.Qt.Key_6, + "7": QtCore.Qt.Key_7, + "8": QtCore.Qt.Key_8, + "9": QtCore.Qt.Key_9, + "Colon": QtCore.Qt.Key_Colon, + ":": QtCore.Qt.Key_Colon, + "Semicolon": QtCore.Qt.Key_Semicolon, + ";": QtCore.Qt.Key_Semicolon, + "Less": QtCore.Qt.Key_Less, + "<": QtCore.Qt.Key_Less, + "Equal": QtCore.Qt.Key_Equal, + "=": QtCore.Qt.Key_Equal, + "Greater": QtCore.Qt.Key_Greater, + ">": QtCore.Qt.Key_Greater, + "Question": QtCore.Qt.Key_Question, + "?": QtCore.Qt.Key_Question, + "At": QtCore.Qt.Key_At, + "A": QtCore.Qt.Key_A, + "B": QtCore.Qt.Key_B, + "C": QtCore.Qt.Key_C, + "D": QtCore.Qt.Key_D, + "E": QtCore.Qt.Key_E, + "F": QtCore.Qt.Key_F, + "G": QtCore.Qt.Key_G, + "H": QtCore.Qt.Key_H, + "I": QtCore.Qt.Key_I, + "J": QtCore.Qt.Key_J, + "K": QtCore.Qt.Key_K, + "L": QtCore.Qt.Key_L, + "M": QtCore.Qt.Key_M, + "N": QtCore.Qt.Key_N, + "O": QtCore.Qt.Key_O, + "P": QtCore.Qt.Key_P, + "Q": QtCore.Qt.Key_Q, + "R": QtCore.Qt.Key_R, + "S": QtCore.Qt.Key_S, + "T": QtCore.Qt.Key_T, + "U": QtCore.Qt.Key_U, + "V": QtCore.Qt.Key_V, + "W": QtCore.Qt.Key_W, + "X": QtCore.Qt.Key_X, + "Y": QtCore.Qt.Key_Y, + "Z": QtCore.Qt.Key_Z, + "PageUp": QtCore.Qt.Key_PageUp, + "PageDown": QtCore.Qt.Key_PageDown, + "BracketLeft": QtCore.Qt.Key_BracketLeft, + "[": QtCore.Qt.Key_BracketLeft, + "BracketRight": QtCore.Qt.Key_BracketRight, + "]": QtCore.Qt.Key_BracketRight, + "Backslash": QtCore.Qt.Key_Backslash, + "\\": QtCore.Qt.Key_Backslash, + "Underscore": QtCore.Qt.Key_Underscore, + "_": QtCore.Qt.Key_Underscore, + "QuoteLeft": QtCore.Qt.Key_QuoteLeft, + "BraceLeft": QtCore.Qt.Key_BraceLeft, + "{": QtCore.Qt.Key_BraceLeft, + "BraceRight": QtCore.Qt.Key_BraceRight, + "}": QtCore.Qt.Key_BraceRight, + "Bar": QtCore.Qt.Key_Bar, + "|": QtCore.Qt.Key_Bar, + "AsciiCircum": QtCore.Qt.Key_AsciiCircum, + "^": QtCore.Qt.Key_AsciiCircum, + "AsciiTilde": QtCore.Qt.Key_AsciiTilde, + "~": QtCore.Qt.Key_AsciiTilde, +} +# !SECTION Key Translations + +# @formatter:off ------------------------------------ Houdini Translations +# SECTION Houdini Translations ------------------------------------------- +# @formatter:off ------------------------------- getcontext +# NOTE getcontext ----------------------------------------- +def getcontext(editor): + """Return houdini context string.""" + hou_context = editor.pwd().childTypeCategory().name() + if hou_context == 'Sop': + return 'SOP' + elif hou_context == 'Dop': + return 'DOP' + elif hou_context == 'Object': + return 'OBJ' + elif hou_context == 'Driver': + return 'ROP' + elif hou_context == 'Chop': + return 'CHOP' + elif hou_context == 'Vop': + return 'VOP' + elif hou_context == 'Shop': + return 'SHOP' + elif hou_context == 'Cop2': + return 'COP' + + +# @formatter:off ------------------------------ CONTEXTTYPE +# NOTE CONTEXTTYPE ---------------------------------------- +CONTEXTTYPE = { + "Cop2": "COP", + "CopNet": "COPNET", + "Chop": "CHOP", + "ChopNet": "CHOPNET", + "Dop": "DOP", + "Driver": "ROP", + "Object": "OBJ", + "Particle": "PART", + "Pop": "POP", + "Sop": "SOP", + "Shop": "SHOP", + "Tsop": "TSOP", + "Vop": "VOP", + "VopNet": "VEX", +} + +# @formatter:off -------------------------------- PANETYPES +# NOTE PANETYPES ------------------------------------------ +PANETYPES = { + hou.paneTabType.AssetBrowser: [["h.pane.projectm"], "Asset Browser"], + hou.paneTabType.BundleList: [["h.pane.bundle"], "Bundle List"], + hou.paneTabType.ChannelEditor: [["h.pane.chedit", "h.pane.chedit.dope", "h.pane.chedit.dope.py", "h.pane.chedit.graph", "h.pane.chedit.graph.py", "h.pane.chedit.table", "h.pane.chedit.table.py"], "Channel Editor"], + hou.paneTabType.ChannelList: [["h.pane.chlist", "h.pane.chlist.ch", "h.pane.chlist.layers", "h.pane.chlist.parmbox"], "Channel List"], + hou.paneTabType.ChannelViewer: [["h.pane.gview.selmodechview"], "Channel Viewer"], + hou.paneTabType.CompositorViewer: [["h.pane.imgui.state", "h.pane.imgui.state.cop"], "Compositor Viewer"], + hou.paneTabType.DataTree: [["h.pane.datatree"], "Data Tree"], + hou.paneTabType.DetailsView: [["h.pane.details"], "Details View"], + hou.paneTabType.HandleList: [["h.pane.manip"], "Handle List"], + hou.paneTabType.HelpBrowser: [[""], "Help Browser"], + hou.paneTabType.IPRViewer: [["h.pane.ipr"], "IPR Viewer"], + hou.paneTabType.LightLinker: [["h.pane.linkeditor", "h.pane.linkeditor.sheet", ], "Light Linker"], + hou.paneTabType.MaterialPalette: [["h.pane.material"], "Material Palette"], + hou.paneTabType.NetworkEditor: [["h.pane.wsheet"], "Network Editor"], + hou.paneTabType.OutputViewer: [["h.pane.outputsview"], "Output Viewer"], + hou.paneTabType.Parm: [["h.pane.editparms", "h.pane.parms"], "Parameters"], + hou.paneTabType.ParmSpreadsheet: [["h.pane.parmsheet"], "Parameter Spreadsheet"], + hou.paneTabType.PerformanceMonitor: [["h.pane.perfmon"], "Performance Monitor"], + hou.paneTabType.PythonPanel: [["h.py"], "PythonPanel"], + hou.paneTabType.PythonShell: [["h.pane.pythonshell", "h.py"], "Python Shell"], + hou.paneTabType.SceneViewer: [["h.pane.gview.selmode", "h.pane.gview.state.select"], "Scene Viewer"], + hou.paneTabType.TakeList: [["h.pane.take", "h.pane.take.content", "h.pane.take.list"], "Take List"], + hou.paneTabType.Textport: [["h.pane.textport"], "Textport"], + hou.paneTabType.TreeView: [["tree"], "Tree View"], + "playbar": [["h.playbar"], "Playbar"], + "shelf": [["h.shelf"], "Shelf"], +} +# !SECTION Houdini Translations + +# @formatter:off ------------------------------------------------ UI Info +# SECTION UI Info ------------------------------------------------------- + +# @formatter:off --------------------------------- SEVERITY +# NOTE SEVERITY ------------------------------------------- +SEVERITY = { + "Message": [hou.severityType.Message, "#FF0000"], + "ImportantMessage": [hou.severityType.ImportantMessage, "#FF0000"], + "Warning": [hou.severityType.Warning, "#FF0000"], + "Error": [hou.severityType.Error, "FF0000"], + "Fatal": [hou.severityType.Fatal, "#FF0000"], +} + +# DOP_pyrosolver +# MISC_database +# MISC_python +# MISC_rename +# NETVIEW_64bit_badge # bug +# NETVIEW_comment_badge +# NETVIEW_debug +# NETVIEW_info_button +# NETVIEW_message_badge +# NETVIEW_image_link +# NETVIEW_image_link_located +# BUTTONS_resizegrip_se -------- Resize +# BUTTONS_tree +# COMMON_opencolorio COP2_colorwheel - Nice color things + +# vop_terminals_connected +# vop_terminals_collapsed + +# @formatter:off ------------------------------------ Icons +# NOTE Icons ---------------------------------------------- +ICON_SIZE = hou.ui.scaledSize(32) +EDIT_ICON_SIZE = hou.ui.scaledSize(28) + +PATH = os.path.join(script_path, "images") +root = PATH.replace("\\", "/") + +ABOUT_ICON1 = hou.ui.createQtIcon( + 'NETVIEW_info_button', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +BUG_ICON = hou.ui.createQtIcon( + 'NETVIEW_64bit_badge', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +COLLAPSE_ALL_ICON = hou.ui.createQtIcon( + (root + "/collapse_all.png"), + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +COLLAPSE_ICON = hou.ui.createQtIcon( + 'BUTTONS_collapse_left', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +COLOR_ICON = hou.ui.createQtIcon( + 'BUTTONS_chooser_color', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +DOWN_ICON = hou.ui.createQtIcon( + 'BUTTONS_down', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +EXPAND_ALL_ICON = hou.ui.createQtIcon( + (root + "/expand_all.png"), + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +EXPAND_ICON = hou.ui.createQtIcon( + 'BUTTONS_expand_right', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +FILE_ICON = hou.ui.createQtIcon( + 'BUTTONS_folder', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +HELP_ICON = hou.ui.createQtIcon( + 'BUTTONS_help', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +INFO_ICON = hou.ui.createQtIcon( + 'BUTTONS_info', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +# BUTTONS_pinned +PIN_IN_ICON = hou.ui.createQtIcon( + 'BUTTONS_pinned', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +PIN_OUT_ICON = hou.ui.createQtIcon( + 'BUTTONS_pin_out_mono', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +RESIZEL_ICON = hou.ui.createQtIcon( + 'BUTTONS_resizegrip_se', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +SEARCH_ICON = hou.ui.createQtIcon( + 'BUTTONS_search', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +SETTINGS_ICON = hou.ui.createQtIcon( + 'BUTTONS_gear', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +UP_ICON = hou.ui.createQtIcon( + 'BUTTONS_up', + EDIT_ICON_SIZE, + EDIT_ICON_SIZE +) + +# !SECTION UI Info + + +# SECTION Widget Tools --------------------------------------------------- +def widgets_at(mainwindow, pos): + """Return ALL widgets at `pos` + Arguments: + pos (QPoint): Position at which to get widgets + :param mainwindow: + """ + + widgets = [] + widget_at = mainwindow.widgetAt(pos) + + while widget_at: + widgets.append(widget_at) + + # Make widget invisible to further enquiries + widget_at.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents) + widget_at = mainwindow.widgetAt(pos) + + # Restore attribute + for widget in widgets: + widget.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents, False) + + return widgets + + # !SECTION Widget Tools diff --git a/python3.7libs/searcher/widgets/__init__py b/python3.7libs/searcher/widgets/__init__py new file mode 100644 index 0000000..e69de29 diff --git a/python3.7libs/searcher/widgets/collapsedock.py b/python3.7libs/searcher/widgets/collapsedock.py new file mode 100644 index 0000000..dde58df --- /dev/null +++ b/python3.7libs/searcher/widgets/collapsedock.py @@ -0,0 +1,112 @@ +from qtpy import QtCore, QtGui, QtWidgets + + +class CollapsibleBox(QtWidgets.QWidget): + def __init__(self, title="", parent=None): + super(CollapsibleBox, self).__init__(parent) + + self.toggle_button = QtWidgets.QToolButton( + text=title, checkable=True, checked=False + ) + self.toggle_button.setStyleSheet("QToolButton { border: none; }") + self.toggle_button.setToolButtonStyle( + QtCore.Qt.ToolButtonTextBesideIcon + ) + self.toggle_button.setArrowType(QtCore.Qt.RightArrow) + self.toggle_button.pressed.connect(self.on_pressed) + + self.toggle_animation = QtCore.QParallelAnimationGroup(self) + + self.content_area = QtWidgets.QScrollArea( + maximumHeight=0, minimumHeight=0 + ) + self.content_area.setSizePolicy( + QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed + ) + self.content_area.setFrameShape(QtWidgets.QFrame.NoFrame) + + lay = QtWidgets.QVBoxLayout(self) + lay.setSpacing(0) + lay.setContentsMargins(0, 0, 0, 0) + lay.addWidget(self.toggle_button) + lay.addWidget(self.content_area) + + self.toggle_animation.addAnimation( + QtCore.QPropertyAnimation(self, b"minimumHeight") + ) + self.toggle_animation.addAnimation( + QtCore.QPropertyAnimation(self, b"maximumHeight") + ) + self.toggle_animation.addAnimation( + QtCore.QPropertyAnimation(self.content_area, b"maximumHeight") + ) + + @QtCore.pyqtSlot() + def on_pressed(self): + checked = self.toggle_button.isChecked() + self.toggle_button.setArrowType( + QtCore.Qt.DownArrow if not checked else QtCore.Qt.RightArrow + ) + self.toggle_animation.setDirection( + QtCore.QAbstractAnimation.Forward + if not checked + else QtCore.QAbstractAnimation.Backward + ) + self.toggle_animation.start() + + def setContentLayout(self, layout): + lay = self.content_area.layout() + del lay + self.content_area.setLayout(layout) + collapsed_height = ( + self.sizeHint().height() - self.content_area.maximumHeight() + ) + content_height = layout.sizeHint().height() + for i in range(self.toggle_animation.animationCount()): + animation = self.toggle_animation.animationAt(i) + animation.setDuration(200) + animation.setStartValue(collapsed_height) + animation.setEndValue(collapsed_height + content_height) + + content_animation = self.toggle_animation.animationAt( + self.toggle_animation.animationCount() - 1 + ) + content_animation.setDuration(200) + content_animation.setStartValue(0) + content_animation.setEndValue(content_height) + + +if __name__ == "__main__": + import sys + import random + + app = QtWidgets.QApplication(sys.argv) + + w = QtWidgets.QMainWindow() + w.setCentralWidget(QtWidgets.QWidget()) + dock = QtWidgets.QDockWidget("Collapsible Demo") + w.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock) + scroll = QtWidgets.QScrollArea() + dock.setWidget(scroll) + content = QtWidgets.QWidget() + scroll.setWidget(content) + scroll.setWidgetResizable(True) + vlay = QtWidgets.QVBoxLayout(content) + for i in range(10): + box = CollapsibleBox("Collapsible Box Header-{}".format(i)) + vlay.addWidget(box) + lay = QtWidgets.QVBoxLayout() + for j in range(8): + label = QtWidgets.QLineEdit("{}".format(j)) + color = QtGui.QColor(*[random.randint(0, 255) for _ in range(3)]) + label.setStyleSheet( + "background-color: {}; color : white;".format(color.name()) + ) + label.setAlignment(QtCore.Qt.AlignCenter) + lay.addWidget(label) + + box.setContentLayout(lay) + vlay.addStretch() + w.resize(640, 480) + w.show() + sys.exit(app.exec_()) \ No newline at end of file diff --git a/python_panels/searcher.pypanel b/python_panels/searcher.pypanel index e02af81..d2cb5bc 100644 --- a/python_panels/searcher.pypanel +++ b/python_panels/searcher.pypanel @@ -8,6 +8,7 @@