diff --git a/FileName.zip b/FileName.zip new file mode 100644 index 0000000..a77c8df Binary files /dev/null and b/FileName.zip differ diff --git a/Help/searcher/changelog/index.txt b/Help/searcher/changelog/index.txt index c76c967..599a536 100644 --- a/Help/searcher/changelog/index.txt +++ b/Help/searcher/changelog/index.txt @@ -5,7 +5,7 @@ #display: inverted notoc #billboard: /images/billboards/blueprint.png #style: background-color: #000000; background-size: auto; -#version: 1.00 +#version: {#version} @@ -18,7 +18,7 @@ -:disclosure:v1.00 +:disclosure:{#version} table width="100%">> tr>> @@ -29,3 +29,23 @@ :platform:Mac * Due to a discrepancy with the way MacOS handles windowing, the MacOS version of Searcher will be released at a later date. + + +table width="100%">> + tr>> + td>> + * [website|https://instance.id/] + #glyph: fa-firefox + td>> + * [twitter| https://twitter.com/instance_id] + #glyph: fa-twitter + td>> + * [github|https://github.com/instance-id] + #glyph: fa-github + td>> + * [issues|https://github.com/instance-id/searcher_addon/issues?q=] + #glyph: fa-bug + td>> + * [email|https://github.com/instance-id/searcher_addon/issues?q=] + #glyph: fa-at \ No newline at end of file diff --git a/Help/searcher/contact/index.txt b/Help/searcher/contact/index.txt new file mode 100644 index 0000000..fdaa3b7 --- /dev/null +++ b/Help/searcher/contact/index.txt @@ -0,0 +1,38 @@ += Searcher = + + +#display: inverted notoc +#billboard: /images/billboards/blueprint.png +#style: background-color: #000000; background-size: auto; +#version: {#version} + + +== Change Log == + + + [ Main Window |/searcher/main] | [ Settings Window |/searcher/settings/] | [ Change Log |/searcher/changelog/]| [ Contact |/searcher/contact/] + + + + +table width="100%">> + tr>> + td>> + * [website|https://instance.id/] + #glyph: fa-firefox + td>> + * [twitter| https://twitter.com/instance_id] + #glyph: fa-twitter + td>> + * [github|https://github.com/instance-id] + #glyph: fa-github + td>> + * [issues|https://github.com/instance-id/searcher_addon/issues?q=] + #glyph: fa-bug + td>> + * [email|https://github.com/instance-id/searcher_addon/issues?q=] + #glyph: fa-at diff --git a/Help/searcher/main.txt b/Help/searcher/main.txt index d7b7e16..6e3b724 100644 --- a/Help/searcher/main.txt +++ b/Help/searcher/main.txt @@ -3,7 +3,7 @@ #display: inverted notoc #billboard: /images/billboards/blueprint.png #style: background-color: #000000; background-size: auto; -#version: 1.00 +#version: {#version} @@ -15,7 +15,7 @@ table width="100%">> tr>> td>> - [ Main Window |/searcher/main] | [ Settings Window |/searcher/settings/] | [ Change Log |/searcher/changelog/] + [ Main Window |/searcher/main] | [ Settings Window |/searcher/settings/] | [ Change Log |/searcher/changelog/] tr>> td>> [ Menu Items |#menu] | [ Search Box |#searchbox] | [ Results Box |#resultsbox] | [ Hotkeys |#hotkeys] @@ -81,7 +81,7 @@ table width="100%">> tr>> td colspan="1">> :platform:Mac - Due to a discrepancy with the way MacOS handles windowing, the MacOS version of Searcher will be released at a later date. + Due to some discrepancies between how Linux/Windows and MacOS operate, the MacOS version of Searcher will be released at a later date. - +table width="100%">> + tr>> + td>> + * [website|https://instance.id/] + #glyph: fa-firefox + td>> + * [twitter| https://twitter.com/instance_id] + #glyph: fa-twitter + td>> + * [github|https://github.com/instance-id] + #glyph: fa-github + td>> + * [issues|https://github.com/instance-id/searcher_addon/issues?q=] + #glyph: fa-bug + td>> + * [email|https://github.com/instance-id/searcher_addon/issues?q=] + #glyph: fa-at \ No newline at end of file diff --git a/Help/searcher/settings/index.txt b/Help/searcher/settings/index.txt index 6271864..d36bac9 100644 --- a/Help/searcher/settings/index.txt +++ b/Help/searcher/settings/index.txt @@ -5,7 +5,7 @@ #display: inverted notoc #billboard: /images/billboards/blueprint.png #style: background-color: #000000; background-size: auto; -#version: 1.00 +#version: {#version} @@ -41,3 +41,23 @@ table width="100%">> # Bug report menu allows you to submit a bug report, suggestion, or feature request (Invokes browser window for proper submission type) # Info menu contains links to our website and GitHub pages + + +table width="100%">> + tr>> + td>> + * [website|https://instance.id/] + #glyph: fa-firefox + td>> + * [twitter| https://twitter.com/instance_id] + #glyph: fa-twitter + td>> + * [github|https://github.com/instance-id] + #glyph: fa-github + td>> + * [issues|https://github.com/instance-id/searcher_addon/issues?q=] + #glyph: fa-bug + td>> + * [email|mailto:support@instance.id] + #glyph: fa-at \ No newline at end of file diff --git a/README.md b/README.md index 722e138..2184ba1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,64 @@ -# Searcher -Fuzzy Houdini + + +## Searcher +##### {#version} + +#### [Installation](#install) | [Compatability Details](#notes) +--- +Thanks for checking out Searcher. Below are the instructions to get you up and running. + +#### Install + +1. Extract/unzip 'Searcher_\.zip'. (ex. Searcher_{#version}.zip) Inside will be a packages and Searcher folder as well as a README.md and a url link to this page. + ``` + Searcher_{#version}.zip / + Searcher_{#version}/__ /packages/ + |_ /Searcher/ + |__ README.md + |__ Searcher_install_instructions.url + ``` + +2. Move the Searcher folder somewhere permanent. It can be placed where ever you would like. Make note of the folder path, as it will be needed in a later step. Examples below: + | OS | Path (replace \ with your actual username) | + | -------------------------------------------- | ------------------------------------------------- | + | Windows: | C:\Users\\\\houdini_addons\Searcher | + | Linux: | /home/\/houdini_addons/Searcher | + | MacOS: | /Users/\/Library/h_addons/Searcher | + +3. Move the 'packages' folder into your Houdini $HOME directory. The locations are seen below: + | OS | Path (replace \ with your actual username) | + | -------------------------------------------- | ---------------------------------------------------------------------- | + | Windows: | C:\Users\\\\Documents\houdini18.0\packages\Searcher.json | + | Linux: | /home/\/houdini18.0/packages/Searcher.json | + | MacOS: | /Users/\/Library/Preferences/houdini/18.0/packages/Searcher.json | + +4. Within the 'packages' folder is the Searcher.json file. Open this file in your editor of choice and edit line #27. Within the second set of quotation marks input the path to the Searcher folder from step #2. On Windows, replace the backslashes (\\) in the path with a forwardslashs (/) +Ex. If using Windows and following the example listed above, line 27 would look like this: + ``` + "SEARCHERLOCATION": "C:/Users//houdini_addons/Searcher", + ``` +5. Save the file and start Houdini. On the main shelf toolbar add the Searcher shelf by clicking on the plus(+) button, then the Shelves tab, followed by selecting "Searcher Shelf" seen in the images below: + ![](https://i.imgur.com/GzdyUYt.png) + ![](https://i.imgur.com/F4C5MOx.png) + +6. You should now be able to hit the hotkey below to open the Searcher window: + Open Searcher Window: Ctrl+` + +### Notes + +##### Compatability: + +| Houdini | Versions Tested | +| --------------------------------------------- | ------------------------ | +| ![](https://i.imgur.com/h9Nefqz.png) Houdini: | Version: 18.0.348 and up | + +##### Tested versions +| OS | Versions Tested | +| ---------- | -------------------------------------- | +| ⊞ Windows: | Windows 10 Pro v10.0.19041.264 (v2004) | +| 🐧 Linux: | Pop_OS! (Ubuntu) 19.04/19.10/20.04 | +| 🍎 MacOS: | Coming soon! | + + + + [website](https://instance.id/) | [twitter](https://twitter.com/instance_id) | [github](https://github.com/instance-id) | [issues](https://github.com/instance-id/searcher_addon/issues?q=) | [email](https://github.com/instance-id/searcher_addon/issues?q=) diff --git a/Searcher_install_instructions.url b/Searcher_install_instructions.url new file mode 100644 index 0000000..b115dfd --- /dev/null +++ b/Searcher_install_instructions.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://github.com/instance-id/searcher_addon diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..2afc684 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,67 @@ +# .\build.ps1 -Zip -Version v0.1.0 +Param ( + [Parameter()] + [string]$Version, + [switch]$Zip +) + +if ($Version) { + Write-Host "Building $Version..." +} else { + 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" + +$source1 = "E:\GitHub\Searcher\" +$destination1 = "E:\Searcher" +$log1 = "--log-file=C:\files\rclone\logs\searcher_$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 + +if ($Version) { + Write-Host "Building $Version..." + + $searcher = "Searcher" + $destination2 = $searcher, $Version -join "_" + $folderVer = "$destination1\$destination2" + + Write-Host "Destination2: $destination2" + + if([System.IO.File]::Exists($folderVer)){ + Get-ChildItem $folderVer -Recurse -ErrorAction SilentlyContinue | Remove-Item -Recurse + } + 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\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 + } + + $FileName = "$destination1\$destination2.zip" + if (Test-Path $FileName) { + Write-Host "Removing $FileName and recreating" + Remove-Item $FileName + } + if($Zip) + { + Compress-Archive -Path $folderVer -DestinationPath $FileName + } + Write-Host "Update Complete" +} else { + Write-Host "Update Complete" +} \ No newline at end of file diff --git a/packages/Searcher.json b/packages/Searcher.json index b258455..8a0794c 100644 --- a/packages/Searcher.json +++ b/packages/Searcher.json @@ -1,17 +1,38 @@ +// ------------------------------ Searcher -------------------------------------- +// --- Make sure this file resides in your Houdini settings/packages -- +// --- folder as listed below: -- +// --- Windows: C:\Users\\Documents\houdini18.0\packages -- +// --- Linux: /home//houdini18.0/packages -- +// --- MacOS: /Users//Library/Preferences/houdini/18.0/packages -- +// ----------------------------- instance.id ------------------------------------ { - "enable": "houdini_version <= '18.0.418'", + // --- Not compatible with versions under 18.0.348 | MacOS not operational -- + "enable": "houdini_version >= '18.0.348' and (houdini_os != 'macos')", + // -------------------------------------------------------------------------- "env": [ - // --- Add path to Searcher root folder here using "/" as separator: - // --- ex. Windows : C:/Users/Me/houdini_addons/searcher - // --- ex. Linux : /home/me/houdini_addons/searcher + // ---------------------------------------------------------------------- + // --- Add path to Searcher root folder below using "/" as separator: -- + // --- The folder can reside wherever you would like. Examples below: -- + // ---------------------------------------------------------------------- + // --- ex. Windows: -- + // --- "SEARCHERLOCATION": "C:/Users//houdini_addons/searcher" -- + // --- ex. Linux: -- + // --- "SEARCHERLOCATION": "/home//houdini_addons/searcher" -- + // --- ex. MacOS: -- + // --- "SEARCHERLOCATION": "/Users//Library/h_addons/searcher" -- + // ---------------------------------------------------------------------- { - "SEARCHERLOCATION": "E:/GitHub/Searcher" + // ------------------------------------------- + // --------------------- Change Path Here ---- + "SEARCHERLOCATION": "", + // ------------------------------------------- }, - // ----------------------------------------- { - "SEARCHER": "$SEARCHERLOCATION" + // -------------------- Do not edit + "SEARCHER": "$SEARCHERLOCATION", }, { + // -------------------- Do not edit "HOUDINI_PATH": "$SEARCHER/" } ] diff --git a/python2.7libs/searcher/__init__.py b/python2.7libs/searcher/__init__.py index 231af2c..c688ca8 100644 --- a/python2.7libs/searcher/__init__.py +++ b/python2.7libs/searcher/__init__.py @@ -1,5 +1,4 @@ __package__ = "searcher" -__version__ = "0.1b" __author__ = "instance.id" __copyright__ = "2020 All rights reserved. See LICENSE for more details." __status__ = "Prototype" diff --git a/python2.7libs/searcher/about.py b/python2.7libs/searcher/about.py index 13c91b6..50aff6d 100644 --- a/python2.7libs/searcher/about.py +++ b/python2.7libs/searcher/about.py @@ -2,6 +2,7 @@ from searcher import about_ui from searcher import util import os +import hou hver = 0 if os.environ["HFS"] != "": @@ -10,10 +11,15 @@ 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""" @@ -25,22 +31,74 @@ def __init__(self, parent=None): self.ui.setupUi(self) self.ui.retranslateUi(self) - self.ui.github.mousePressEvent = self.openGithub + 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 openGithub(self, event): + 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 openWeb(self, event): - weburl = '''https://instance.id/''' - QtGui.QDesktopServices.openUrl(QtCore.QUrl(weburl)) + 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 diff --git a/python2.7libs/searcher/about_ui.py b/python2.7libs/searcher/about_ui.py index 2f232b0..9263ac3 100644 --- a/python2.7libs/searcher/about_ui.py +++ b/python2.7libs/searcher/about_ui.py @@ -1,5 +1,16 @@ -from hutil.Qt import QtCore, QtGui, QtWidgets +# -*- 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__)) @@ -19,6 +30,8 @@ def setupUi(self, About): 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) @@ -31,23 +44,63 @@ def setupUi(self, About): 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.web.setOpenExternalLinks(True) + self.secondrow.addWidget(self.web_icon) self.secondrow.addWidget(self.web) self.verticalLayout.addLayout(self.secondrow) - self.headerrow = QtWidgets.QHBoxLayout() - self.headerrow.setObjectName("headerrow") + + # -------------------------------------------------- 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.github.setOpenExternalLinks(True) - self.headerrow.addWidget(self.github) - self.verticalLayout.addLayout(self.headerrow) + 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) @@ -67,8 +120,10 @@ def setupUi(self, About): def retranslateUi(self, About): _translate = QtCore.QCoreApplication.translate About.setWindowTitle(_translate("About", "Form")) - self.github.setText(_translate("About", 'github/instance-id')) - self.web.setText(_translate("About", 'instance.id')) + 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): diff --git a/python2.7libs/searcher/database.py b/python2.7libs/searcher/database.py index abd7a55..190229c 100644 --- a/python2.7libs/searcher/database.py +++ b/python2.7libs/searcher/database.py @@ -9,8 +9,6 @@ from searcher import settings_data from searcher import ptime as ptime - - from peewee import * from playhouse.sqlite_ext import SqliteExtDatabase, RowIDField, FTS5Model, SearchField import time @@ -23,6 +21,7 @@ def get_settings(): def get_dbconnection(): return getattr(hou.session, "DBCONNECTION", None) + scriptpath = os.path.dirname(os.path.realpath(__file__)) db = get_dbconnection() @@ -213,7 +212,7 @@ def getlastusedhk(self): if len(hkcheck) is 0: self.settings[util.SETTINGS_KEYS[11]] = "" settings_data.savesettings(settingdata) - updatechangeindex(int(currentidx)) + self.updatechangeindex(int(currentidx)) else: hou.hotkeys.clearAssignments(str(lasthk[0])) hou.hotkeys.saveOverrides() @@ -221,7 +220,7 @@ def getlastusedhk(self): if len(hkcheck) is 0: self.settings[util.SETTINGS_KEYS[11]] = "" settings_data.savesettings(settingdata) - updatechangeindex(int(currentidx)) + 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) @@ -291,7 +290,7 @@ def ctxfilterresults(self, inputTerm): 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): @@ -307,7 +306,7 @@ def searchresults(self, inputTerm, debug, limit=0): ) result = self.cur.fetchall() uniqueresult = py_unique(result) - + time2 = ptime.time() self.hotkeystime = ((time2 - time1) * 1000.0) diff --git a/python2.7libs/searcher/datahandler.py b/python2.7libs/searcher/datahandler.py index c5dc9eb..40ca165 100644 --- a/python2.7libs/searcher/datahandler.py +++ b/python2.7libs/searcher/datahandler.py @@ -30,7 +30,7 @@ def __init__(self, debug=None): 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__)) diff --git a/python2.7libs/searcher/images/icons/at-solid.svg b/python2.7libs/searcher/images/icons/at-solid.svg new file mode 100644 index 0000000..8b72d6f --- /dev/null +++ b/python2.7libs/searcher/images/icons/at-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python2.7libs/searcher/images/icons/bug-solid.svg b/python2.7libs/searcher/images/icons/bug-solid.svg new file mode 100644 index 0000000..c7af707 --- /dev/null +++ b/python2.7libs/searcher/images/icons/bug-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python2.7libs/searcher/images/icons/firefox-browser-brands.svg b/python2.7libs/searcher/images/icons/firefox-browser-brands.svg new file mode 100644 index 0000000..316a13c --- /dev/null +++ b/python2.7libs/searcher/images/icons/firefox-browser-brands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python2.7libs/searcher/images/icons/github-brands.svg b/python2.7libs/searcher/images/icons/github-brands.svg new file mode 100644 index 0000000..7870c06 --- /dev/null +++ b/python2.7libs/searcher/images/icons/github-brands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python2.7libs/searcher/images/icons/twitter-brands.svg b/python2.7libs/searcher/images/icons/twitter-brands.svg new file mode 100644 index 0000000..9ac9e0b --- /dev/null +++ b/python2.7libs/searcher/images/icons/twitter-brands.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python2.7libs/searcher/searcher.py b/python2.7libs/searcher/searcher.py index 2fc58c6..ae3f70d 100644 --- a/python2.7libs/searcher/searcher.py +++ b/python2.7libs/searcher/searcher.py @@ -23,10 +23,10 @@ import hou import threading import hdefereval as hd +# noinspection PyUnresolvedReferences from canvaseventtypes import * from collections import Iterable -hver = 0 if os.environ["HFS"] != "": ver = os.environ["HFS"] # hver = int(ver[ver.rindex('.')+1:]) @@ -1631,6 +1631,7 @@ 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") diff --git a/python2.7libs/searcher/searchersetup.py b/python2.7libs/searcher/searchersetup.py new file mode 100644 index 0000000..06c3250 --- /dev/null +++ b/python2.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/python2.7libs/searcher/settings_data.py b/python2.7libs/searcher/settings_data.py index 31a7b47..854dc84 100644 --- a/python2.7libs/searcher/settings_data.py +++ b/python2.7libs/searcher/settings_data.py @@ -42,7 +42,7 @@ 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]] = False + def_set[util.SETTINGS_KEYS[8]] = True settingsdata.beginGroup('Searcher') try: for i in range(len(util.SETTINGS_KEYS)): diff --git a/python2.7libs/searcher/util.py b/python2.7libs/searcher/util.py index 67fa1f8..2f9b5a7 100644 --- a/python2.7libs/searcher/util.py +++ b/python2.7libs/searcher/util.py @@ -55,9 +55,9 @@ def get_settings(): # @formatter:off ----------------------------- get_settings # NOTE get_settings --------------------------------------- def get_path(folders=None): - script_path = os.path.dirname(os.path.realpath(__file__)) - PATH = os.path.join(script_path, '/'.join(folders)) - return PATH.replace("\\", "/") + 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 ------------------------------------- @@ -146,11 +146,11 @@ def bc(v): 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 + 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 } @@ -582,6 +582,7 @@ def getcontext(editor): # vop_terminals_connected # vop_terminals_collapsed + # @formatter:off ------------------------------------ Icons # NOTE Icons ---------------------------------------------- ICON_SIZE = hou.ui.scaledSize(32) @@ -627,7 +628,7 @@ def getcontext(editor): ) EXPAND_ALL_ICON = hou.ui.createQtIcon( - (root + "/expand_all.png"), + (root + "/expand_all.png"), EDIT_ICON_SIZE, EDIT_ICON_SIZE ) @@ -693,7 +694,7 @@ def getcontext(editor): EDIT_ICON_SIZE ) -# !SECTION UI Info +# !SECTION UI Info # SECTION Widget Tools --------------------------------------------------- diff --git a/toolbar/searcher_tool.shelf b/toolbar/searcher_tool.shelf index 8af7c2c..c824f08 100644 --- a/toolbar/searcher_tool.shelf +++ b/toolbar/searcher_tool.shelf @@ -7,7 +7,6 @@ - @@ -34,15 +33,11 @@ class Logger(object): self.log.write(message) def flush(self): - #this flush method is needed for python 3 compatibility. - #this handles the flush command by doing nothing. - #you might want to specify some extra behavior here. + # This flush method is needed for python 3 compatibility. pass sys.stdout = Logger() - - try: searcher.CreateSearcherPanel(**kwargs) except(AttributeError, TypeError) as e: