mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #227 from pypeclub/feature/213_move_pyblish_to_tools
feature/213 move pyblish to tools
This commit is contained in:
commit
96609f54ec
48 changed files with 10933 additions and 0 deletions
13
pype/tools/pyblish_pype/__init__.py
Normal file
13
pype/tools/pyblish_pype/__init__.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from .version import version, version_info, __version__
|
||||
|
||||
# This must be run prior to importing the application, due to the
|
||||
# application requiring a discovered copy of Qt bindings.
|
||||
|
||||
from .app import show
|
||||
|
||||
__all__ = [
|
||||
'show',
|
||||
'version',
|
||||
'version_info',
|
||||
'__version__'
|
||||
]
|
||||
19
pype/tools/pyblish_pype/__main__.py
Normal file
19
pype/tools/pyblish_pype/__main__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
from .app import show
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--debug", action="store_true")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
from . import mock
|
||||
import pyblish.api
|
||||
|
||||
for Plugin in mock.plugins:
|
||||
pyblish.api.register_plugin(Plugin)
|
||||
|
||||
show()
|
||||
493
pype/tools/pyblish_pype/app.css
Normal file
493
pype/tools/pyblish_pype/app.css
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
/* Global CSS */
|
||||
|
||||
* {
|
||||
outline: none;
|
||||
color: #ddd;
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* General CSS */
|
||||
|
||||
QWidget {
|
||||
background: #555;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
QMenu {
|
||||
background-color: #555; /* sets background of the menu */
|
||||
border: 1px solid #222;
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
/* sets background of menu item. set this to something non-transparent
|
||||
if you want menu color and menu item color to be different */
|
||||
background-color: transparent;
|
||||
padding: 5px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
QMenu::item:selected { /* when user selects item using mouse or keyboard */
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
QDialog {
|
||||
min-width: 300;
|
||||
background: "#555";
|
||||
}
|
||||
|
||||
QListView {
|
||||
border: 0px;
|
||||
background: "transparent"
|
||||
}
|
||||
|
||||
QTreeView {
|
||||
border: 0px;
|
||||
background: "transparent"
|
||||
}
|
||||
|
||||
QPushButton {
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
background: #555;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
font-family: "FontAwesome";
|
||||
font-size: 11pt;
|
||||
color: white;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QPushButton:pressed {
|
||||
background: "#777";
|
||||
}
|
||||
|
||||
QPushButton:hover {
|
||||
color: white;
|
||||
background: "#666";
|
||||
}
|
||||
|
||||
QPushButton:disabled {
|
||||
color: rgba(255, 255, 255, 50);
|
||||
}
|
||||
|
||||
QTextEdit, QLineEdit {
|
||||
background: #555;
|
||||
border: 1px solid #333;
|
||||
font-size: 9pt;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
QCheckBox {
|
||||
min-width: 17px;
|
||||
max-width: 17px;
|
||||
border: 1px solid #222;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QCheckBox::indicator {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
/*background: #444;*/
|
||||
background: transparent;
|
||||
border: 1px solid #555;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked {
|
||||
background: #222;
|
||||
}
|
||||
|
||||
QComboBox {
|
||||
background: #444;
|
||||
color: #EEE;
|
||||
font-size: 8pt;
|
||||
border: 1px solid #333;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QComboBox[combolist="true"]::drop-down {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
QComboBox[combolist="true"]::down-arrow {
|
||||
max-width: 0px;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
QComboBox[combolist="true"] QAbstractItemView {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
QScrollBar:vertical {
|
||||
border: none;
|
||||
background: transparent;
|
||||
width: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
background: #333;
|
||||
border-radius: 3px;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
|
||||
border: 1px solid #444;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
|
||||
background: none;
|
||||
}
|
||||
|
||||
QToolTip {
|
||||
color: #eee;
|
||||
background-color: #555;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
QLabel {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
QToolButton {
|
||||
background-color: transparent;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Specific CSS */
|
||||
#PerspectiveToggleBtn {
|
||||
border-bottom: 3px solid lightblue;
|
||||
border-top: 0px;
|
||||
border-radius: 0px;
|
||||
border-right: 1px solid #232323;
|
||||
border-left: 0px;
|
||||
font-size: 26pt;
|
||||
font-family: "FontAwesome";
|
||||
}
|
||||
|
||||
#Terminal QComboBox::drop-down {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
#Header {
|
||||
background: #555;
|
||||
border: 1px solid #444;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#Header QRadioButton {
|
||||
border: 3px solid "transparent";
|
||||
border-right: 1px solid #333;
|
||||
left: 2px;
|
||||
}
|
||||
|
||||
#Header QRadioButton::indicator {
|
||||
width: 65px;
|
||||
height: 40px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
image: none;
|
||||
}
|
||||
|
||||
#Header QRadioButton:hover {
|
||||
background-color: rgba(255, 255, 255, 10);
|
||||
}
|
||||
|
||||
#Header QRadioButton:checked {
|
||||
background-color: rgba(255, 255, 255, 20);
|
||||
border-bottom: 3px solid "lightblue";
|
||||
}
|
||||
|
||||
#Body {
|
||||
padding: 0px;
|
||||
border: 1px solid #333;
|
||||
background: #444;
|
||||
}
|
||||
|
||||
#Body QWidget {
|
||||
background: #444;
|
||||
}
|
||||
|
||||
#Header #ArtistTab {
|
||||
background-image: url("img/tab-home.png");
|
||||
}
|
||||
|
||||
#Header #TerminalTab {
|
||||
background-image: url("img/tab-terminal.png");
|
||||
}
|
||||
|
||||
#Header #OverviewTab {
|
||||
background-image: url("img/tab-overview.png");
|
||||
}
|
||||
|
||||
#ButtonWithMenu {
|
||||
background: #555;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 4px;
|
||||
font-family: "FontAwesome";
|
||||
font-size: 11pt;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#ButtonWithMenu:pressed {
|
||||
background: #777;
|
||||
}
|
||||
|
||||
#ButtonWithMenu:hover {
|
||||
color: white;
|
||||
background: #666;
|
||||
}
|
||||
#ButtonWithMenu:disabled {
|
||||
background: #666;
|
||||
color: #999;
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
#FooterSpacer, #FooterInfo, #HeaderSpacer {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#Footer {
|
||||
background: #555;
|
||||
min-height: 43px;
|
||||
}
|
||||
|
||||
#Footer[success="1"] {
|
||||
background: #458056
|
||||
}
|
||||
|
||||
#Footer[success="0"] {
|
||||
background-color: #AA5050
|
||||
}
|
||||
|
||||
#Footer QPushButton {
|
||||
background: #555;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
font-family: "FontAwesome";
|
||||
font-size: 11pt;
|
||||
color: white;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#Footer QPushButton:pressed:hover {
|
||||
color: #3784c5;
|
||||
background: #444;
|
||||
}
|
||||
|
||||
#Footer QPushButton:hover {
|
||||
background: #505050;
|
||||
border: 2px solid #3784c5;
|
||||
}
|
||||
|
||||
#Footer QPushButton:disabled {
|
||||
border: 1px solid #888;
|
||||
background: #666;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
#ClosingPlaceholder {
|
||||
background: rgba(0, 0, 0, 50);
|
||||
}
|
||||
|
||||
#CommentIntentWidget {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#CommentBox, #CommentPlaceholder {
|
||||
font-family: "Open Sans";
|
||||
font-size: 8pt;
|
||||
padding: 5px;
|
||||
background: #444;
|
||||
}
|
||||
|
||||
#CommentBox {
|
||||
selection-background-color: #222;
|
||||
}
|
||||
|
||||
#CommentBox:disabled, #CommentPlaceholder:disabled, #IntentBox:disabled {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
#CommentPlaceholder {
|
||||
color: #888
|
||||
}
|
||||
|
||||
#IntentBox {
|
||||
background: #444;
|
||||
font-size: 8pt;
|
||||
padding: 5px;
|
||||
min-width: 75px;
|
||||
color: #EEE;
|
||||
}
|
||||
|
||||
#IntentBox::drop-down:button {
|
||||
border: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#IntentBox::down-arrow {
|
||||
image: url("/img/down_arrow.png");
|
||||
}
|
||||
|
||||
#IntentBox::down-arrow:disabled {
|
||||
image: url();
|
||||
}
|
||||
|
||||
#TerminalView {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#TerminalView:item {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#TerminalView:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#TerminalView:selected {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#TerminalView:item:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#TerminalView:item:selected {
|
||||
color: #eeeeee;
|
||||
}
|
||||
|
||||
#TerminalView QTextEdit {
|
||||
padding:3px;
|
||||
color: #aaa;
|
||||
border-radius: 7px;
|
||||
border-color: #222;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
#TerminalView QTextEdit:hover {
|
||||
background-color: #353535;
|
||||
}
|
||||
|
||||
#TerminalView QTextEdit:selected {
|
||||
background-color: #303030;
|
||||
}
|
||||
|
||||
#ExpandableWidgetContent {
|
||||
border: none;
|
||||
background-color: #232323;
|
||||
color:#eeeeee;
|
||||
}
|
||||
|
||||
#EllidableLabel {
|
||||
font-size: 16pt;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#PerspectiveScrollContent {
|
||||
border: 1px solid #333;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
#PerspectiveWidgetContent{
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#PerspectiveLabel {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#PerspectiveIndicator {
|
||||
font-size: 16pt;
|
||||
font-weight: normal;
|
||||
padding: 5px;
|
||||
background-color: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
#PerspectiveIndicator[state="warning"] {
|
||||
background-color: #ff9900;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#PerspectiveIndicator[state="active"] {
|
||||
background-color: #99CEEE;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#PerspectiveIndicator[state="error"] {
|
||||
background-color: #cc4a4a;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#PerspectiveIndicator[state="ok"] {
|
||||
background-color: #69a567;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#ExpandableHeader {
|
||||
background-color: transparent;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#ExpandableHeader QWidget {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
#ExpandableHeader QWidget:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#TerminalFilerBtn {
|
||||
/* font: %(font_size_pt)spt; */
|
||||
font-family: "FontAwesome";
|
||||
text-align: center;
|
||||
background-color: transparent;
|
||||
border-width: 1px;
|
||||
border-color: #777777;
|
||||
border-style: none;
|
||||
padding: 0px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#TerminalFilerBtn[type="info"]:checked {color: rgb(255, 255, 255);}
|
||||
#TerminalFilerBtn[type="info"] {color: rgba(255, 255, 255, 63);}
|
||||
|
||||
#TerminalFilerBtn[type="error"]:checked {color: rgb(255, 74, 74);}
|
||||
#TerminalFilerBtn[type="error"] {color: rgba(255, 74, 74, 63);}
|
||||
|
||||
#TerminalFilerBtn[type="log_debug"]:checked {color: rgb(255, 102, 232);}
|
||||
#TerminalFilerBtn[type="log_debug"] {color: rgba(255, 102, 232, 63);}
|
||||
|
||||
#TerminalFilerBtn[type="log_info"]:checked {color: rgb(102, 171, 255);}
|
||||
#TerminalFilerBtn[type="log_info"] {color: rgba(102, 171, 255, 63);}
|
||||
|
||||
#TerminalFilerBtn[type="log_warning"]:checked {color: rgb(255, 186, 102);}
|
||||
#TerminalFilerBtn[type="log_warning"] {color: rgba(255, 186, 102, 63);}
|
||||
|
||||
#TerminalFilerBtn[type="log_error"]:checked {color: rgb(255, 77, 88);}
|
||||
#TerminalFilerBtn[type="log_error"] {color: rgba(255, 77, 88, 63);}
|
||||
|
||||
#TerminalFilerBtn[type="log_critical"]:checked {color: rgb(255, 79, 117);}
|
||||
#TerminalFilerBtn[type="log_critical"] {color: rgba(255, 79, 117, 63);}
|
||||
104
pype/tools/pyblish_pype/app.py
Normal file
104
pype/tools/pyblish_pype/app.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import sys
|
||||
|
||||
from . import compat, control, settings, util, window
|
||||
from .vendor.Qt import QtCore, QtGui, QtWidgets
|
||||
|
||||
self = sys.modules[__name__]
|
||||
|
||||
# Maintain reference to currently opened window
|
||||
self._window = None
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def application():
|
||||
app = QtWidgets.QApplication.instance()
|
||||
|
||||
if not app:
|
||||
print("Starting new QApplication..")
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
yield app
|
||||
app.exec_()
|
||||
else:
|
||||
print("Using existing QApplication..")
|
||||
yield app
|
||||
if os.environ.get("PYBLISH_GUI_ALWAYS_EXEC"):
|
||||
app.exec_()
|
||||
|
||||
|
||||
def install_translator(app):
|
||||
translator = QtCore.QTranslator(app)
|
||||
translator.load(QtCore.QLocale.system(), "i18n/",
|
||||
directory=util.root)
|
||||
app.installTranslator(translator)
|
||||
print("Installed translator")
|
||||
|
||||
|
||||
def install_fonts():
|
||||
database = QtGui.QFontDatabase()
|
||||
fonts = [
|
||||
"opensans/OpenSans-Bold.ttf",
|
||||
"opensans/OpenSans-BoldItalic.ttf",
|
||||
"opensans/OpenSans-ExtraBold.ttf",
|
||||
"opensans/OpenSans-ExtraBoldItalic.ttf",
|
||||
"opensans/OpenSans-Italic.ttf",
|
||||
"opensans/OpenSans-Light.ttf",
|
||||
"opensans/OpenSans-LightItalic.ttf",
|
||||
"opensans/OpenSans-Regular.ttf",
|
||||
"opensans/OpenSans-Semibold.ttf",
|
||||
"opensans/OpenSans-SemiboldItalic.ttf",
|
||||
"fontawesome/fontawesome-webfont.ttf"
|
||||
]
|
||||
|
||||
for font in fonts:
|
||||
path = util.get_asset("font", font)
|
||||
|
||||
# TODO(marcus): Check if they are already installed first.
|
||||
# In hosts, this will be called each time the GUI is shown,
|
||||
# potentially installing a font each time.
|
||||
if database.addApplicationFont(path) < 0:
|
||||
sys.stderr.write("Could not install %s\n" % path)
|
||||
else:
|
||||
sys.stdout.write("Installed %s\n" % font)
|
||||
|
||||
|
||||
def on_destroyed():
|
||||
"""Remove internal reference to window on window destroyed"""
|
||||
self._window = None
|
||||
|
||||
|
||||
def show(parent=None):
|
||||
with open(util.get_asset("app.css")) as f:
|
||||
css = f.read()
|
||||
|
||||
# Make relative paths absolute
|
||||
root = util.get_asset("").replace("\\", "/")
|
||||
css = css.replace("url(\"", "url(\"%s" % root)
|
||||
|
||||
with application() as app:
|
||||
compat.init()
|
||||
|
||||
install_fonts()
|
||||
install_translator(app)
|
||||
|
||||
ctrl = control.Controller()
|
||||
|
||||
if self._window is None:
|
||||
self._window = window.Window(ctrl, parent)
|
||||
self._window.destroyed.connect(on_destroyed)
|
||||
|
||||
self._window.show()
|
||||
self._window.activateWindow()
|
||||
self._window.resize(*settings.WindowSize)
|
||||
self._window.setWindowTitle(settings.WindowTitle)
|
||||
|
||||
font = QtGui.QFont("Open Sans", 8, QtGui.QFont.Normal)
|
||||
self._window.setFont(font)
|
||||
self._window.setStyleSheet(css)
|
||||
|
||||
self._window.reset()
|
||||
|
||||
return self._window
|
||||
733
pype/tools/pyblish_pype/awesome.py
Normal file
733
pype/tools/pyblish_pype/awesome.py
Normal file
|
|
@ -0,0 +1,733 @@
|
|||
|
||||
tags = {
|
||||
"500px": u"\uf26e",
|
||||
"adjust": u"\uf042",
|
||||
"adn": u"\uf170",
|
||||
"align-center": u"\uf037",
|
||||
"align-justify": u"\uf039",
|
||||
"align-left": u"\uf036",
|
||||
"align-right": u"\uf038",
|
||||
"amazon": u"\uf270",
|
||||
"ambulance": u"\uf0f9",
|
||||
"american-sign-language-interpreting": u"\uf2a3",
|
||||
"anchor": u"\uf13d",
|
||||
"android": u"\uf17b",
|
||||
"angellist": u"\uf209",
|
||||
"angle-double-down": u"\uf103",
|
||||
"angle-double-left": u"\uf100",
|
||||
"angle-double-right": u"\uf101",
|
||||
"angle-double-up": u"\uf102",
|
||||
"angle-down": u"\uf107",
|
||||
"angle-left": u"\uf104",
|
||||
"angle-right": u"\uf105",
|
||||
"angle-up": u"\uf106",
|
||||
"apple": u"\uf179",
|
||||
"archive": u"\uf187",
|
||||
"area-chart": u"\uf1fe",
|
||||
"arrow-circle-down": u"\uf0ab",
|
||||
"arrow-circle-left": u"\uf0a8",
|
||||
"arrow-circle-o-down": u"\uf01a",
|
||||
"arrow-circle-o-left": u"\uf190",
|
||||
"arrow-circle-o-right": u"\uf18e",
|
||||
"arrow-circle-o-up": u"\uf01b",
|
||||
"arrow-circle-right": u"\uf0a9",
|
||||
"arrow-circle-up": u"\uf0aa",
|
||||
"arrow-down": u"\uf063",
|
||||
"arrow-left": u"\uf060",
|
||||
"arrow-right": u"\uf061",
|
||||
"arrow-up": u"\uf062",
|
||||
"arrows": u"\uf047",
|
||||
"arrows-alt": u"\uf0b2",
|
||||
"arrows-h": u"\uf07e",
|
||||
"arrows-v": u"\uf07d",
|
||||
"asl-interpreting (alias)": u"\uf2a3",
|
||||
"assistive-listening-systems": u"\uf2a2",
|
||||
"asterisk": u"\uf069",
|
||||
"at": u"\uf1fa",
|
||||
"audio-description": u"\uf29e",
|
||||
"automobile (alias)": u"\uf1b9",
|
||||
"backward": u"\uf04a",
|
||||
"balance-scale": u"\uf24e",
|
||||
"ban": u"\uf05e",
|
||||
"bank (alias)": u"\uf19c",
|
||||
"bar-chart": u"\uf080",
|
||||
"bar-chart-o (alias)": u"\uf080",
|
||||
"barcode": u"\uf02a",
|
||||
"bars": u"\uf0c9",
|
||||
"battery-0 (alias)": u"\uf244",
|
||||
"battery-1 (alias)": u"\uf243",
|
||||
"battery-2 (alias)": u"\uf242",
|
||||
"battery-3 (alias)": u"\uf241",
|
||||
"battery-4 (alias)": u"\uf240",
|
||||
"battery-empty": u"\uf244",
|
||||
"battery-full": u"\uf240",
|
||||
"battery-half": u"\uf242",
|
||||
"battery-quarter": u"\uf243",
|
||||
"battery-three-quarters": u"\uf241",
|
||||
"bed": u"\uf236",
|
||||
"beer": u"\uf0fc",
|
||||
"behance": u"\uf1b4",
|
||||
"behance-square": u"\uf1b5",
|
||||
"bell": u"\uf0f3",
|
||||
"bell-o": u"\uf0a2",
|
||||
"bell-slash": u"\uf1f6",
|
||||
"bell-slash-o": u"\uf1f7",
|
||||
"bicycle": u"\uf206",
|
||||
"binoculars": u"\uf1e5",
|
||||
"birthday-cake": u"\uf1fd",
|
||||
"bitbucket": u"\uf171",
|
||||
"bitbucket-square": u"\uf172",
|
||||
"bitcoin (alias)": u"\uf15a",
|
||||
"black-tie": u"\uf27e",
|
||||
"blind": u"\uf29d",
|
||||
"bluetooth": u"\uf293",
|
||||
"bluetooth-b": u"\uf294",
|
||||
"bold": u"\uf032",
|
||||
"bolt": u"\uf0e7",
|
||||
"bomb": u"\uf1e2",
|
||||
"book": u"\uf02d",
|
||||
"bookmark": u"\uf02e",
|
||||
"bookmark-o": u"\uf097",
|
||||
"braille": u"\uf2a1",
|
||||
"briefcase": u"\uf0b1",
|
||||
"btc": u"\uf15a",
|
||||
"bug": u"\uf188",
|
||||
"building": u"\uf1ad",
|
||||
"building-o": u"\uf0f7",
|
||||
"bullhorn": u"\uf0a1",
|
||||
"bullseye": u"\uf140",
|
||||
"bus": u"\uf207",
|
||||
"buysellads": u"\uf20d",
|
||||
"cab (alias)": u"\uf1ba",
|
||||
"calculator": u"\uf1ec",
|
||||
"calendar": u"\uf073",
|
||||
"calendar-check-o": u"\uf274",
|
||||
"calendar-minus-o": u"\uf272",
|
||||
"calendar-o": u"\uf133",
|
||||
"calendar-plus-o": u"\uf271",
|
||||
"calendar-times-o": u"\uf273",
|
||||
"camera": u"\uf030",
|
||||
"camera-retro": u"\uf083",
|
||||
"car": u"\uf1b9",
|
||||
"caret-down": u"\uf0d7",
|
||||
"caret-left": u"\uf0d9",
|
||||
"caret-right": u"\uf0da",
|
||||
"caret-square-o-down": u"\uf150",
|
||||
"caret-square-o-left": u"\uf191",
|
||||
"caret-square-o-right": u"\uf152",
|
||||
"caret-square-o-up": u"\uf151",
|
||||
"caret-up": u"\uf0d8",
|
||||
"cart-arrow-down": u"\uf218",
|
||||
"cart-plus": u"\uf217",
|
||||
"cc": u"\uf20a",
|
||||
"cc-amex": u"\uf1f3",
|
||||
"cc-diners-club": u"\uf24c",
|
||||
"cc-discover": u"\uf1f2",
|
||||
"cc-jcb": u"\uf24b",
|
||||
"cc-mastercard": u"\uf1f1",
|
||||
"cc-paypal": u"\uf1f4",
|
||||
"cc-stripe": u"\uf1f5",
|
||||
"cc-visa": u"\uf1f0",
|
||||
"certificate": u"\uf0a3",
|
||||
"chain (alias)": u"\uf0c1",
|
||||
"chain-broken": u"\uf127",
|
||||
"check": u"\uf00c",
|
||||
"check-circle": u"\uf058",
|
||||
"check-circle-o": u"\uf05d",
|
||||
"check-square": u"\uf14a",
|
||||
"check-square-o": u"\uf046",
|
||||
"chevron-circle-down": u"\uf13a",
|
||||
"chevron-circle-left": u"\uf137",
|
||||
"chevron-circle-right": u"\uf138",
|
||||
"chevron-circle-up": u"\uf139",
|
||||
"chevron-down": u"\uf078",
|
||||
"chevron-left": u"\uf053",
|
||||
"chevron-right": u"\uf054",
|
||||
"chevron-up": u"\uf077",
|
||||
"child": u"\uf1ae",
|
||||
"chrome": u"\uf268",
|
||||
"circle": u"\uf111",
|
||||
"circle-o": u"\uf10c",
|
||||
"circle-o-notch": u"\uf1ce",
|
||||
"circle-thin": u"\uf1db",
|
||||
"clipboard": u"\uf0ea",
|
||||
"clock-o": u"\uf017",
|
||||
"clone": u"\uf24d",
|
||||
"close (alias)": u"\uf00d",
|
||||
"cloud": u"\uf0c2",
|
||||
"cloud-download": u"\uf0ed",
|
||||
"cloud-upload": u"\uf0ee",
|
||||
"cny (alias)": u"\uf157",
|
||||
"code": u"\uf121",
|
||||
"code-fork": u"\uf126",
|
||||
"codepen": u"\uf1cb",
|
||||
"codiepie": u"\uf284",
|
||||
"coffee": u"\uf0f4",
|
||||
"cog": u"\uf013",
|
||||
"cogs": u"\uf085",
|
||||
"columns": u"\uf0db",
|
||||
"comment": u"\uf075",
|
||||
"comment-o": u"\uf0e5",
|
||||
"commenting": u"\uf27a",
|
||||
"commenting-o": u"\uf27b",
|
||||
"comments": u"\uf086",
|
||||
"comments-o": u"\uf0e6",
|
||||
"compass": u"\uf14e",
|
||||
"compress": u"\uf066",
|
||||
"connectdevelop": u"\uf20e",
|
||||
"contao": u"\uf26d",
|
||||
"copy (alias)": u"\uf0c5",
|
||||
"copyright": u"\uf1f9",
|
||||
"creative-commons": u"\uf25e",
|
||||
"credit-card": u"\uf09d",
|
||||
"credit-card-alt": u"\uf283",
|
||||
"crop": u"\uf125",
|
||||
"crosshairs": u"\uf05b",
|
||||
"css3": u"\uf13c",
|
||||
"cube": u"\uf1b2",
|
||||
"cubes": u"\uf1b3",
|
||||
"cut (alias)": u"\uf0c4",
|
||||
"cutlery": u"\uf0f5",
|
||||
"dashboard (alias)": u"\uf0e4",
|
||||
"dashcube": u"\uf210",
|
||||
"database": u"\uf1c0",
|
||||
"deaf": u"\uf2a4",
|
||||
"deafness (alias)": u"\uf2a4",
|
||||
"dedent (alias)": u"\uf03b",
|
||||
"delicious": u"\uf1a5",
|
||||
"desktop": u"\uf108",
|
||||
"deviantart": u"\uf1bd",
|
||||
"diamond": u"\uf219",
|
||||
"digg": u"\uf1a6",
|
||||
"dollar (alias)": u"\uf155",
|
||||
"dot-circle-o": u"\uf192",
|
||||
"download": u"\uf019",
|
||||
"dribbble": u"\uf17d",
|
||||
"dropbox": u"\uf16b",
|
||||
"drupal": u"\uf1a9",
|
||||
"edge": u"\uf282",
|
||||
"edit (alias)": u"\uf044",
|
||||
"eject": u"\uf052",
|
||||
"ellipsis-h": u"\uf141",
|
||||
"ellipsis-v": u"\uf142",
|
||||
"empire": u"\uf1d1",
|
||||
"envelope": u"\uf0e0",
|
||||
"envelope-o": u"\uf003",
|
||||
"envelope-square": u"\uf199",
|
||||
"envira": u"\uf299",
|
||||
"eraser": u"\uf12d",
|
||||
"eur": u"\uf153",
|
||||
"euro (alias)": u"\uf153",
|
||||
"exchange": u"\uf0ec",
|
||||
"exclamation": u"\uf12a",
|
||||
"exclamation-circle": u"\uf06a",
|
||||
"exclamation-triangle": u"\uf071",
|
||||
"expand": u"\uf065",
|
||||
"expeditedssl": u"\uf23e",
|
||||
"external-link": u"\uf08e",
|
||||
"external-link-square": u"\uf14c",
|
||||
"eye": u"\uf06e",
|
||||
"eye-slash": u"\uf070",
|
||||
"eyedropper": u"\uf1fb",
|
||||
"fa (alias)": u"\uf2b4",
|
||||
"facebook": u"\uf09a",
|
||||
"facebook-f (alias)": u"\uf09a",
|
||||
"facebook-official": u"\uf230",
|
||||
"facebook-square": u"\uf082",
|
||||
"fast-backward": u"\uf049",
|
||||
"fast-forward": u"\uf050",
|
||||
"fax": u"\uf1ac",
|
||||
"feed (alias)": u"\uf09e",
|
||||
"female": u"\uf182",
|
||||
"fighter-jet": u"\uf0fb",
|
||||
"file": u"\uf15b",
|
||||
"file-archive-o": u"\uf1c6",
|
||||
"file-audio-o": u"\uf1c7",
|
||||
"file-code-o": u"\uf1c9",
|
||||
"file-excel-o": u"\uf1c3",
|
||||
"file-image-o": u"\uf1c5",
|
||||
"file-movie-o (alias)": u"\uf1c8",
|
||||
"file-o": u"\uf016",
|
||||
"file-pdf-o": u"\uf1c1",
|
||||
"file-photo-o (alias)": u"\uf1c5",
|
||||
"file-picture-o (alias)": u"\uf1c5",
|
||||
"file-powerpoint-o": u"\uf1c4",
|
||||
"file-sound-o (alias)": u"\uf1c7",
|
||||
"file-text": u"\uf15c",
|
||||
"file-text-o": u"\uf0f6",
|
||||
"file-video-o": u"\uf1c8",
|
||||
"file-word-o": u"\uf1c2",
|
||||
"file-zip-o (alias)": u"\uf1c6",
|
||||
"files-o": u"\uf0c5",
|
||||
"film": u"\uf008",
|
||||
"filter": u"\uf0b0",
|
||||
"fire": u"\uf06d",
|
||||
"fire-extinguisher": u"\uf134",
|
||||
"firefox": u"\uf269",
|
||||
"first-order": u"\uf2b0",
|
||||
"flag": u"\uf024",
|
||||
"flag-checkered": u"\uf11e",
|
||||
"flag-o": u"\uf11d",
|
||||
"flash (alias)": u"\uf0e7",
|
||||
"flask": u"\uf0c3",
|
||||
"flickr": u"\uf16e",
|
||||
"floppy-o": u"\uf0c7",
|
||||
"folder": u"\uf07b",
|
||||
"folder-o": u"\uf114",
|
||||
"folder-open": u"\uf07c",
|
||||
"folder-open-o": u"\uf115",
|
||||
"font": u"\uf031",
|
||||
"font-awesome": u"\uf2b4",
|
||||
"fonticons": u"\uf280",
|
||||
"fort-awesome": u"\uf286",
|
||||
"forumbee": u"\uf211",
|
||||
"forward": u"\uf04e",
|
||||
"foursquare": u"\uf180",
|
||||
"frown-o": u"\uf119",
|
||||
"futbol-o": u"\uf1e3",
|
||||
"gamepad": u"\uf11b",
|
||||
"gavel": u"\uf0e3",
|
||||
"gbp": u"\uf154",
|
||||
"ge (alias)": u"\uf1d1",
|
||||
"gear (alias)": u"\uf013",
|
||||
"gears (alias)": u"\uf085",
|
||||
"genderless": u"\uf22d",
|
||||
"get-pocket": u"\uf265",
|
||||
"gg": u"\uf260",
|
||||
"gg-circle": u"\uf261",
|
||||
"gift": u"\uf06b",
|
||||
"git": u"\uf1d3",
|
||||
"git-square": u"\uf1d2",
|
||||
"github": u"\uf09b",
|
||||
"github-alt": u"\uf113",
|
||||
"github-square": u"\uf092",
|
||||
"gitlab": u"\uf296",
|
||||
"gittip (alias)": u"\uf184",
|
||||
"glass": u"\uf000",
|
||||
"glide": u"\uf2a5",
|
||||
"glide-g": u"\uf2a6",
|
||||
"globe": u"\uf0ac",
|
||||
"google": u"\uf1a0",
|
||||
"google-plus": u"\uf0d5",
|
||||
"google-plus-circle (alias)": u"\uf2b3",
|
||||
"google-plus-official": u"\uf2b3",
|
||||
"google-plus-square": u"\uf0d4",
|
||||
"google-wallet": u"\uf1ee",
|
||||
"graduation-cap": u"\uf19d",
|
||||
"gratipay": u"\uf184",
|
||||
"group (alias)": u"\uf0c0",
|
||||
"h-square": u"\uf0fd",
|
||||
"hacker-news": u"\uf1d4",
|
||||
"hand-grab-o (alias)": u"\uf255",
|
||||
"hand-lizard-o": u"\uf258",
|
||||
"hand-o-down": u"\uf0a7",
|
||||
"hand-o-left": u"\uf0a5",
|
||||
"hand-o-right": u"\uf0a4",
|
||||
"hand-o-up": u"\uf0a6",
|
||||
"hand-paper-o": u"\uf256",
|
||||
"hand-peace-o": u"\uf25b",
|
||||
"hand-pointer-o": u"\uf25a",
|
||||
"hand-rock-o": u"\uf255",
|
||||
"hand-scissors-o": u"\uf257",
|
||||
"hand-spock-o": u"\uf259",
|
||||
"hand-stop-o (alias)": u"\uf256",
|
||||
"hard-of-hearing (alias)": u"\uf2a4",
|
||||
"hashtag": u"\uf292",
|
||||
"hdd-o": u"\uf0a0",
|
||||
"header": u"\uf1dc",
|
||||
"headphones": u"\uf025",
|
||||
"heart": u"\uf004",
|
||||
"heart-o": u"\uf08a",
|
||||
"heartbeat": u"\uf21e",
|
||||
"history": u"\uf1da",
|
||||
"home": u"\uf015",
|
||||
"hospital-o": u"\uf0f8",
|
||||
"hotel (alias)": u"\uf236",
|
||||
"hourglass": u"\uf254",
|
||||
"hourglass-1 (alias)": u"\uf251",
|
||||
"hourglass-2 (alias)": u"\uf252",
|
||||
"hourglass-3 (alias)": u"\uf253",
|
||||
"hourglass-end": u"\uf253",
|
||||
"hourglass-half": u"\uf252",
|
||||
"hourglass-o": u"\uf250",
|
||||
"hourglass-start": u"\uf251",
|
||||
"houzz": u"\uf27c",
|
||||
"html5": u"\uf13b",
|
||||
"i-cursor": u"\uf246",
|
||||
"ils": u"\uf20b",
|
||||
"image (alias)": u"\uf03e",
|
||||
"inbox": u"\uf01c",
|
||||
"indent": u"\uf03c",
|
||||
"industry": u"\uf275",
|
||||
"info": u"\uf129",
|
||||
"info-circle": u"\uf05a",
|
||||
"inr": u"\uf156",
|
||||
"instagram": u"\uf16d",
|
||||
"institution (alias)": u"\uf19c",
|
||||
"internet-explorer": u"\uf26b",
|
||||
"intersex (alias)": u"\uf224",
|
||||
"ioxhost": u"\uf208",
|
||||
"italic": u"\uf033",
|
||||
"joomla": u"\uf1aa",
|
||||
"jpy": u"\uf157",
|
||||
"jsfiddle": u"\uf1cc",
|
||||
"key": u"\uf084",
|
||||
"keyboard-o": u"\uf11c",
|
||||
"krw": u"\uf159",
|
||||
"language": u"\uf1ab",
|
||||
"laptop": u"\uf109",
|
||||
"lastfm": u"\uf202",
|
||||
"lastfm-square": u"\uf203",
|
||||
"leaf": u"\uf06c",
|
||||
"leanpub": u"\uf212",
|
||||
"legal (alias)": u"\uf0e3",
|
||||
"lemon-o": u"\uf094",
|
||||
"level-down": u"\uf149",
|
||||
"level-up": u"\uf148",
|
||||
"life-bouy (alias)": u"\uf1cd",
|
||||
"life-buoy (alias)": u"\uf1cd",
|
||||
"life-ring": u"\uf1cd",
|
||||
"life-saver (alias)": u"\uf1cd",
|
||||
"lightbulb-o": u"\uf0eb",
|
||||
"line-chart": u"\uf201",
|
||||
"link": u"\uf0c1",
|
||||
"linkedin": u"\uf0e1",
|
||||
"linkedin-square": u"\uf08c",
|
||||
"linux": u"\uf17c",
|
||||
"list": u"\uf03a",
|
||||
"list-alt": u"\uf022",
|
||||
"list-ol": u"\uf0cb",
|
||||
"list-ul": u"\uf0ca",
|
||||
"location-arrow": u"\uf124",
|
||||
"lock": u"\uf023",
|
||||
"long-arrow-down": u"\uf175",
|
||||
"long-arrow-left": u"\uf177",
|
||||
"long-arrow-right": u"\uf178",
|
||||
"long-arrow-up": u"\uf176",
|
||||
"low-vision": u"\uf2a8",
|
||||
"magic": u"\uf0d0",
|
||||
"magnet": u"\uf076",
|
||||
"mail-forward (alias)": u"\uf064",
|
||||
"mail-reply (alias)": u"\uf112",
|
||||
"mail-reply-all (alias)": u"\uf122",
|
||||
"male": u"\uf183",
|
||||
"map": u"\uf279",
|
||||
"map-marker": u"\uf041",
|
||||
"map-o": u"\uf278",
|
||||
"map-pin": u"\uf276",
|
||||
"map-signs": u"\uf277",
|
||||
"mars": u"\uf222",
|
||||
"mars-double": u"\uf227",
|
||||
"mars-stroke": u"\uf229",
|
||||
"mars-stroke-h": u"\uf22b",
|
||||
"mars-stroke-v": u"\uf22a",
|
||||
"maxcdn": u"\uf136",
|
||||
"meanpath": u"\uf20c",
|
||||
"medium": u"\uf23a",
|
||||
"medkit": u"\uf0fa",
|
||||
"meh-o": u"\uf11a",
|
||||
"mercury": u"\uf223",
|
||||
"microphone": u"\uf130",
|
||||
"microphone-slash": u"\uf131",
|
||||
"minus": u"\uf068",
|
||||
"minus-circle": u"\uf056",
|
||||
"minus-square": u"\uf146",
|
||||
"minus-square-o": u"\uf147",
|
||||
"mixcloud": u"\uf289",
|
||||
"mobile": u"\uf10b",
|
||||
"mobile-phone (alias)": u"\uf10b",
|
||||
"modx": u"\uf285",
|
||||
"money": u"\uf0d6",
|
||||
"moon-o": u"\uf186",
|
||||
"mortar-board (alias)": u"\uf19d",
|
||||
"motorcycle": u"\uf21c",
|
||||
"mouse-pointer": u"\uf245",
|
||||
"music": u"\uf001",
|
||||
"navicon (alias)": u"\uf0c9",
|
||||
"neuter": u"\uf22c",
|
||||
"newspaper-o": u"\uf1ea",
|
||||
"object-group": u"\uf247",
|
||||
"object-ungroup": u"\uf248",
|
||||
"odnoklassniki": u"\uf263",
|
||||
"odnoklassniki-square": u"\uf264",
|
||||
"opencart": u"\uf23d",
|
||||
"openid": u"\uf19b",
|
||||
"opera": u"\uf26a",
|
||||
"optin-monster": u"\uf23c",
|
||||
"outdent": u"\uf03b",
|
||||
"pagelines": u"\uf18c",
|
||||
"paint-brush": u"\uf1fc",
|
||||
"paper-plane": u"\uf1d8",
|
||||
"paper-plane-o": u"\uf1d9",
|
||||
"paperclip": u"\uf0c6",
|
||||
"paragraph": u"\uf1dd",
|
||||
"paste (alias)": u"\uf0ea",
|
||||
"pause": u"\uf04c",
|
||||
"pause-circle": u"\uf28b",
|
||||
"pause-circle-o": u"\uf28c",
|
||||
"paw": u"\uf1b0",
|
||||
"paypal": u"\uf1ed",
|
||||
"pencil": u"\uf040",
|
||||
"pencil-square": u"\uf14b",
|
||||
"pencil-square-o": u"\uf044",
|
||||
"percent": u"\uf295",
|
||||
"phone": u"\uf095",
|
||||
"phone-square": u"\uf098",
|
||||
"photo (alias)": u"\uf03e",
|
||||
"picture-o": u"\uf03e",
|
||||
"pie-chart": u"\uf200",
|
||||
"pied-piper": u"\uf2ae",
|
||||
"pied-piper-alt": u"\uf1a8",
|
||||
"pied-piper-pp": u"\uf1a7",
|
||||
"pinterest": u"\uf0d2",
|
||||
"pinterest-p": u"\uf231",
|
||||
"pinterest-square": u"\uf0d3",
|
||||
"plane": u"\uf072",
|
||||
"play": u"\uf04b",
|
||||
"play-circle": u"\uf144",
|
||||
"play-circle-o": u"\uf01d",
|
||||
"plug": u"\uf1e6",
|
||||
"plus": u"\uf067",
|
||||
"plus-circle": u"\uf055",
|
||||
"plus-square": u"\uf0fe",
|
||||
"plus-square-o": u"\uf196",
|
||||
"power-off": u"\uf011",
|
||||
"print": u"\uf02f",
|
||||
"product-hunt": u"\uf288",
|
||||
"puzzle-piece": u"\uf12e",
|
||||
"qq": u"\uf1d6",
|
||||
"qrcode": u"\uf029",
|
||||
"question": u"\uf128",
|
||||
"question-circle": u"\uf059",
|
||||
"question-circle-o": u"\uf29c",
|
||||
"quote-left": u"\uf10d",
|
||||
"quote-right": u"\uf10e",
|
||||
"ra (alias)": u"\uf1d0",
|
||||
"random": u"\uf074",
|
||||
"rebel": u"\uf1d0",
|
||||
"recycle": u"\uf1b8",
|
||||
"reddit": u"\uf1a1",
|
||||
"reddit-alien": u"\uf281",
|
||||
"reddit-square": u"\uf1a2",
|
||||
"refresh": u"\uf021",
|
||||
"registered": u"\uf25d",
|
||||
"remove (alias)": u"\uf00d",
|
||||
"renren": u"\uf18b",
|
||||
"reorder (alias)": u"\uf0c9",
|
||||
"repeat": u"\uf01e",
|
||||
"reply": u"\uf112",
|
||||
"reply-all": u"\uf122",
|
||||
"resistance (alias)": u"\uf1d0",
|
||||
"retweet": u"\uf079",
|
||||
"rmb (alias)": u"\uf157",
|
||||
"road": u"\uf018",
|
||||
"rocket": u"\uf135",
|
||||
"rotate-left (alias)": u"\uf0e2",
|
||||
"rotate-right (alias)": u"\uf01e",
|
||||
"rouble (alias)": u"\uf158",
|
||||
"rss": u"\uf09e",
|
||||
"rss-square": u"\uf143",
|
||||
"rub": u"\uf158",
|
||||
"ruble (alias)": u"\uf158",
|
||||
"rupee (alias)": u"\uf156",
|
||||
"safari": u"\uf267",
|
||||
"save (alias)": u"\uf0c7",
|
||||
"scissors": u"\uf0c4",
|
||||
"scribd": u"\uf28a",
|
||||
"search": u"\uf002",
|
||||
"search-minus": u"\uf010",
|
||||
"search-plus": u"\uf00e",
|
||||
"sellsy": u"\uf213",
|
||||
"send (alias)": u"\uf1d8",
|
||||
"send-o (alias)": u"\uf1d9",
|
||||
"server": u"\uf233",
|
||||
"share": u"\uf064",
|
||||
"share-alt": u"\uf1e0",
|
||||
"share-alt-square": u"\uf1e1",
|
||||
"share-square": u"\uf14d",
|
||||
"share-square-o": u"\uf045",
|
||||
"shekel (alias)": u"\uf20b",
|
||||
"sheqel (alias)": u"\uf20b",
|
||||
"shield": u"\uf132",
|
||||
"ship": u"\uf21a",
|
||||
"shirtsinbulk": u"\uf214",
|
||||
"shopping-bag": u"\uf290",
|
||||
"shopping-basket": u"\uf291",
|
||||
"shopping-cart": u"\uf07a",
|
||||
"sign-in": u"\uf090",
|
||||
"sign-language": u"\uf2a7",
|
||||
"sign-out": u"\uf08b",
|
||||
"signal": u"\uf012",
|
||||
"signing (alias)": u"\uf2a7",
|
||||
"simplybuilt": u"\uf215",
|
||||
"sitemap": u"\uf0e8",
|
||||
"skyatlas": u"\uf216",
|
||||
"skype": u"\uf17e",
|
||||
"slack": u"\uf198",
|
||||
"sliders": u"\uf1de",
|
||||
"slideshare": u"\uf1e7",
|
||||
"smile-o": u"\uf118",
|
||||
"snapchat": u"\uf2ab",
|
||||
"snapchat-ghost": u"\uf2ac",
|
||||
"snapchat-square": u"\uf2ad",
|
||||
"soccer-ball-o (alias)": u"\uf1e3",
|
||||
"sort": u"\uf0dc",
|
||||
"sort-alpha-asc": u"\uf15d",
|
||||
"sort-alpha-desc": u"\uf15e",
|
||||
"sort-amount-asc": u"\uf160",
|
||||
"sort-amount-desc": u"\uf161",
|
||||
"sort-asc": u"\uf0de",
|
||||
"sort-desc": u"\uf0dd",
|
||||
"sort-down (alias)": u"\uf0dd",
|
||||
"sort-numeric-asc": u"\uf162",
|
||||
"sort-numeric-desc": u"\uf163",
|
||||
"sort-up (alias)": u"\uf0de",
|
||||
"soundcloud": u"\uf1be",
|
||||
"space-shuttle": u"\uf197",
|
||||
"spinner": u"\uf110",
|
||||
"spoon": u"\uf1b1",
|
||||
"spotify": u"\uf1bc",
|
||||
"square": u"\uf0c8",
|
||||
"square-o": u"\uf096",
|
||||
"stack-exchange": u"\uf18d",
|
||||
"stack-overflow": u"\uf16c",
|
||||
"star": u"\uf005",
|
||||
"star-half": u"\uf089",
|
||||
"star-half-empty (alias)": u"\uf123",
|
||||
"star-half-full (alias)": u"\uf123",
|
||||
"star-half-o": u"\uf123",
|
||||
"star-o": u"\uf006",
|
||||
"steam": u"\uf1b6",
|
||||
"steam-square": u"\uf1b7",
|
||||
"step-backward": u"\uf048",
|
||||
"step-forward": u"\uf051",
|
||||
"stethoscope": u"\uf0f1",
|
||||
"sticky-note": u"\uf249",
|
||||
"sticky-note-o": u"\uf24a",
|
||||
"stop": u"\uf04d",
|
||||
"stop-circle": u"\uf28d",
|
||||
"stop-circle-o": u"\uf28e",
|
||||
"street-view": u"\uf21d",
|
||||
"strikethrough": u"\uf0cc",
|
||||
"stumbleupon": u"\uf1a4",
|
||||
"stumbleupon-circle": u"\uf1a3",
|
||||
"subscript": u"\uf12c",
|
||||
"subway": u"\uf239",
|
||||
"suitcase": u"\uf0f2",
|
||||
"sun-o": u"\uf185",
|
||||
"superscript": u"\uf12b",
|
||||
"support (alias)": u"\uf1cd",
|
||||
"table": u"\uf0ce",
|
||||
"tablet": u"\uf10a",
|
||||
"tachometer": u"\uf0e4",
|
||||
"tag": u"\uf02b",
|
||||
"tags": u"\uf02c",
|
||||
"tasks": u"\uf0ae",
|
||||
"taxi": u"\uf1ba",
|
||||
"television": u"\uf26c",
|
||||
"tencent-weibo": u"\uf1d5",
|
||||
"terminal": u"\uf120",
|
||||
"text-height": u"\uf034",
|
||||
"text-width": u"\uf035",
|
||||
"th": u"\uf00a",
|
||||
"th-large": u"\uf009",
|
||||
"th-list": u"\uf00b",
|
||||
"themeisle": u"\uf2b2",
|
||||
"thumb-tack": u"\uf08d",
|
||||
"thumbs-down": u"\uf165",
|
||||
"thumbs-o-down": u"\uf088",
|
||||
"thumbs-o-up": u"\uf087",
|
||||
"thumbs-up": u"\uf164",
|
||||
"ticket": u"\uf145",
|
||||
"times": u"\uf00d",
|
||||
"times-circle": u"\uf057",
|
||||
"times-circle-o": u"\uf05c",
|
||||
"tint": u"\uf043",
|
||||
"toggle-down (alias)": u"\uf150",
|
||||
"toggle-left (alias)": u"\uf191",
|
||||
"toggle-off": u"\uf204",
|
||||
"toggle-on": u"\uf205",
|
||||
"toggle-right (alias)": u"\uf152",
|
||||
"toggle-up (alias)": u"\uf151",
|
||||
"trademark": u"\uf25c",
|
||||
"train": u"\uf238",
|
||||
"transgender": u"\uf224",
|
||||
"transgender-alt": u"\uf225",
|
||||
"trash": u"\uf1f8",
|
||||
"trash-o": u"\uf014",
|
||||
"tree": u"\uf1bb",
|
||||
"trello": u"\uf181",
|
||||
"tripadvisor": u"\uf262",
|
||||
"trophy": u"\uf091",
|
||||
"truck": u"\uf0d1",
|
||||
"try": u"\uf195",
|
||||
"tty": u"\uf1e4",
|
||||
"tumblr": u"\uf173",
|
||||
"tumblr-square": u"\uf174",
|
||||
"turkish-lira (alias)": u"\uf195",
|
||||
"tv (alias)": u"\uf26c",
|
||||
"twitch": u"\uf1e8",
|
||||
"twitter": u"\uf099",
|
||||
"twitter-square": u"\uf081",
|
||||
"umbrella": u"\uf0e9",
|
||||
"underline": u"\uf0cd",
|
||||
"undo": u"\uf0e2",
|
||||
"universal-access": u"\uf29a",
|
||||
"university": u"\uf19c",
|
||||
"unlink (alias)": u"\uf127",
|
||||
"unlock": u"\uf09c",
|
||||
"unlock-alt": u"\uf13e",
|
||||
"unsorted (alias)": u"\uf0dc",
|
||||
"upload": u"\uf093",
|
||||
"usb": u"\uf287",
|
||||
"usd": u"\uf155",
|
||||
"user": u"\uf007",
|
||||
"user-md": u"\uf0f0",
|
||||
"user-plus": u"\uf234",
|
||||
"user-secret": u"\uf21b",
|
||||
"user-times": u"\uf235",
|
||||
"users": u"\uf0c0",
|
||||
"venus": u"\uf221",
|
||||
"venus-double": u"\uf226",
|
||||
"venus-mars": u"\uf228",
|
||||
"viacoin": u"\uf237",
|
||||
"viadeo": u"\uf2a9",
|
||||
"viadeo-square": u"\uf2aa",
|
||||
"video-camera": u"\uf03d",
|
||||
"vimeo": u"\uf27d",
|
||||
"vimeo-square": u"\uf194",
|
||||
"vine": u"\uf1ca",
|
||||
"vk": u"\uf189",
|
||||
"volume-control-phone": u"\uf2a0",
|
||||
"volume-down": u"\uf027",
|
||||
"volume-off": u"\uf026",
|
||||
"volume-up": u"\uf028",
|
||||
"warning (alias)": u"\uf071",
|
||||
"wechat (alias)": u"\uf1d7",
|
||||
"weibo": u"\uf18a",
|
||||
"weixin": u"\uf1d7",
|
||||
"whatsapp": u"\uf232",
|
||||
"wheelchair": u"\uf193",
|
||||
"wheelchair-alt": u"\uf29b",
|
||||
"wifi": u"\uf1eb",
|
||||
"wikipedia-w": u"\uf266",
|
||||
"windows": u"\uf17a",
|
||||
"won (alias)": u"\uf159",
|
||||
"wordpress": u"\uf19a",
|
||||
"wpbeginner": u"\uf297",
|
||||
"wpforms": u"\uf298",
|
||||
"wrench": u"\uf0ad",
|
||||
"xing": u"\uf168",
|
||||
"xing-square": u"\uf169",
|
||||
"y-combinator": u"\uf23b",
|
||||
"y-combinator-square (alias)": u"\uf1d4",
|
||||
"yahoo": u"\uf19e",
|
||||
"yc (alias)": u"\uf23b",
|
||||
"yc-square (alias)": u"\uf1d4",
|
||||
"yelp": u"\uf1e9",
|
||||
"yen (alias)": u"\uf157",
|
||||
"yoast": u"\uf2b1",
|
||||
"youtube": u"\uf167",
|
||||
"youtube-play": u"\uf16a",
|
||||
"youtube-square": u"\uf166"
|
||||
}
|
||||
14
pype/tools/pyblish_pype/compat.py
Normal file
14
pype/tools/pyblish_pype/compat.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
|
||||
|
||||
def __windows_taskbar_compat():
|
||||
"""Enable icon and taskbar grouping for Windows 7+"""
|
||||
|
||||
import ctypes
|
||||
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
|
||||
u"pyblish_pype")
|
||||
|
||||
|
||||
def init():
|
||||
if os.name == "nt":
|
||||
__windows_taskbar_compat()
|
||||
95
pype/tools/pyblish_pype/constants.py
Normal file
95
pype/tools/pyblish_pype/constants.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
from .vendor.Qt import QtCore
|
||||
|
||||
|
||||
def flags(*args, **kwargs):
|
||||
type_name = kwargs.pop("type_name", "Flags")
|
||||
with_base = kwargs.pop("with_base", False)
|
||||
enums = {}
|
||||
for idx, attr_name in enumerate(args):
|
||||
if with_base:
|
||||
if idx == 0:
|
||||
enums[attr_name] = 0
|
||||
continue
|
||||
idx -= 1
|
||||
enums[attr_name] = 2**idx
|
||||
|
||||
for attr_name, value in kwargs.items():
|
||||
enums[attr_name] = value
|
||||
return type(type_name, (), enums)
|
||||
|
||||
|
||||
def roles(*args, **kwargs):
|
||||
type_name = kwargs.pop("type_name", "Roles")
|
||||
enums = {}
|
||||
for attr_name, value in kwargs.items():
|
||||
enums[attr_name] = value
|
||||
|
||||
offset = 0
|
||||
for idx, attr_name in enumerate(args):
|
||||
_idx = idx + QtCore.Qt.UserRole + offset
|
||||
while _idx in enums.values():
|
||||
offset += 1
|
||||
_idx = idx + offset
|
||||
|
||||
enums[attr_name] = _idx
|
||||
|
||||
return type(type_name, (), enums)
|
||||
|
||||
|
||||
Roles = roles(
|
||||
"ObjectIdRole",
|
||||
"ObjectUIdRole",
|
||||
"TypeRole",
|
||||
"PublishFlagsRole",
|
||||
"LogRecordsRole",
|
||||
|
||||
"IsOptionalRole",
|
||||
"IsEnabledRole",
|
||||
|
||||
"FamiliesRole",
|
||||
|
||||
"DocstringRole",
|
||||
"PathModuleRole",
|
||||
"PluginActionsVisibleRole",
|
||||
"PluginValidActionsRole",
|
||||
"PluginActionProgressRole",
|
||||
|
||||
"TerminalItemTypeRole",
|
||||
|
||||
"IntentItemValue",
|
||||
|
||||
type_name="ModelRoles"
|
||||
)
|
||||
|
||||
InstanceStates = flags(
|
||||
"ContextType",
|
||||
"InProgress",
|
||||
"HasWarning",
|
||||
"HasError",
|
||||
"HasFinished",
|
||||
type_name="InstanceState"
|
||||
)
|
||||
|
||||
PluginStates = flags(
|
||||
"IsCompatible",
|
||||
"InProgress",
|
||||
"WasProcessed",
|
||||
"WasSkipped",
|
||||
"HasWarning",
|
||||
"HasError",
|
||||
type_name="PluginState"
|
||||
)
|
||||
|
||||
GroupStates = flags(
|
||||
"HasWarning",
|
||||
"HasError",
|
||||
"HasFinished",
|
||||
type_name="GroupStates"
|
||||
)
|
||||
|
||||
PluginActionStates = flags(
|
||||
"InProgress",
|
||||
"HasFailed",
|
||||
"HasFinished",
|
||||
type_name="PluginActionStates"
|
||||
)
|
||||
414
pype/tools/pyblish_pype/control.py
Normal file
414
pype/tools/pyblish_pype/control.py
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
"""The Controller in a Model/View/Controller-based application
|
||||
The graphical components of Pyblish Lite use this object to perform
|
||||
publishing. It communicates via the Qt Signals/Slots mechanism
|
||||
and has no direct connection to any graphics. This is important,
|
||||
because this is how unittests are able to run without requiring
|
||||
an active window manager; such as via Travis-CI.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from .vendor.Qt import QtCore
|
||||
|
||||
import pyblish.api
|
||||
import pyblish.util
|
||||
import pyblish.logic
|
||||
import pyblish.lib
|
||||
import pyblish.version
|
||||
|
||||
from . import util
|
||||
from .constants import InstanceStates
|
||||
try:
|
||||
from pypeapp.config import get_presets
|
||||
except Exception:
|
||||
get_presets = dict
|
||||
|
||||
|
||||
class IterationBreak(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Controller(QtCore.QObject):
|
||||
# Emitted when the GUI is about to start processing;
|
||||
# e.g. resetting, validating or publishing.
|
||||
about_to_process = QtCore.Signal(object, object)
|
||||
|
||||
# ??? Emitted for each process
|
||||
was_processed = QtCore.Signal(dict)
|
||||
|
||||
# Emmited when reset
|
||||
# - all data are reset (plugins, processing, pari yielder, etc.)
|
||||
was_reset = QtCore.Signal()
|
||||
|
||||
# Emmited when previous group changed
|
||||
passed_group = QtCore.Signal(object)
|
||||
|
||||
# Emmited when want to change state of instances
|
||||
switch_toggleability = QtCore.Signal(bool)
|
||||
|
||||
# On action finished
|
||||
was_acted = QtCore.Signal(dict)
|
||||
|
||||
# Emitted when processing has stopped
|
||||
was_stopped = QtCore.Signal()
|
||||
|
||||
# Emitted when processing has finished
|
||||
was_finished = QtCore.Signal()
|
||||
|
||||
# Emitted when plugin was skipped
|
||||
was_skipped = QtCore.Signal(object)
|
||||
|
||||
# store OrderGroups - now it is a singleton
|
||||
order_groups = util.OrderGroups
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(Controller, self).__init__(parent)
|
||||
self.context = None
|
||||
self.plugins = {}
|
||||
self.optional_default = {}
|
||||
|
||||
def reset_variables(self):
|
||||
# Data internal to the GUI itself
|
||||
self.is_running = False
|
||||
self.stopped = False
|
||||
self.errored = False
|
||||
|
||||
# Active producer of pairs
|
||||
self.pair_generator = None
|
||||
# Active pair
|
||||
self.current_pair = None
|
||||
|
||||
# Orders which changes GUI
|
||||
# - passing collectors order disables plugin/instance toggle
|
||||
self.collectors_order = None
|
||||
self.collect_state = 0
|
||||
self.collected = False
|
||||
|
||||
# - passing validators order disables validate button and gives ability
|
||||
# to know when to stop on validate button press
|
||||
self.validators_order = None
|
||||
self.validated = False
|
||||
|
||||
# Get collectors and validators order
|
||||
self.order_groups.reset()
|
||||
plugin_groups = self.order_groups.groups()
|
||||
plugin_groups_keys = list(plugin_groups.keys())
|
||||
self.collectors_order = plugin_groups_keys[0]
|
||||
self.validators_order = self.order_groups.validation_order()
|
||||
next_group_order = None
|
||||
if len(plugin_groups_keys) > 1:
|
||||
next_group_order = plugin_groups_keys[1]
|
||||
|
||||
# This is used to track whether or not to continue
|
||||
# processing when, for example, validation has failed.
|
||||
self.processing = {
|
||||
"stop_on_validation": False,
|
||||
# Used?
|
||||
"last_plugin_order": None,
|
||||
"current_group_order": self.collectors_order,
|
||||
"next_group_order": next_group_order,
|
||||
"nextOrder": None,
|
||||
"ordersWithError": set()
|
||||
}
|
||||
|
||||
def presets_by_hosts(self):
|
||||
# Get global filters as base
|
||||
presets = get_presets().get("plugins", {})
|
||||
if not presets:
|
||||
return {}
|
||||
|
||||
result = presets.get("global", {}).get("filter", {})
|
||||
hosts = pyblish.api.registered_hosts()
|
||||
for host in hosts:
|
||||
host_presets = presets.get(host, {}).get("filter")
|
||||
if not host_presets:
|
||||
continue
|
||||
|
||||
for key, value in host_presets.items():
|
||||
if value is None:
|
||||
if key in result:
|
||||
result.pop(key)
|
||||
continue
|
||||
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
|
||||
def reset_context(self):
|
||||
self.context = pyblish.api.Context()
|
||||
|
||||
self.context._publish_states = InstanceStates.ContextType
|
||||
self.context.optional = False
|
||||
|
||||
self.context.data["publish"] = True
|
||||
self.context.data["label"] = "Context"
|
||||
self.context.data["name"] = "context"
|
||||
|
||||
self.context.data["host"] = reversed(pyblish.api.registered_hosts())
|
||||
self.context.data["port"] = int(
|
||||
os.environ.get("PYBLISH_CLIENT_PORT", -1)
|
||||
)
|
||||
self.context.data["connectTime"] = pyblish.lib.time(),
|
||||
self.context.data["pyblishVersion"] = pyblish.version,
|
||||
self.context.data["pythonVersion"] = sys.version
|
||||
|
||||
self.context.data["icon"] = "book"
|
||||
|
||||
self.context.families = ("__context__",)
|
||||
|
||||
def reset(self):
|
||||
"""Discover plug-ins and run collection."""
|
||||
|
||||
self.reset_context()
|
||||
self.reset_variables()
|
||||
|
||||
self.possible_presets = self.presets_by_hosts()
|
||||
|
||||
# Load plugins and set pair generator
|
||||
self.load_plugins()
|
||||
self.pair_generator = self._pair_yielder(self.plugins)
|
||||
|
||||
self.was_reset.emit()
|
||||
|
||||
# Process collectors load rest of plugins with collected instances
|
||||
self.collect()
|
||||
|
||||
def load_plugins(self):
|
||||
self.test = pyblish.logic.registered_test()
|
||||
self.optional_default = {}
|
||||
|
||||
plugins = pyblish.api.discover()
|
||||
|
||||
targets = pyblish.logic.registered_targets() or ["default"]
|
||||
self.plugins = pyblish.logic.plugins_by_targets(plugins, targets)
|
||||
|
||||
def on_published(self):
|
||||
if self.is_running:
|
||||
self.is_running = False
|
||||
self.was_finished.emit()
|
||||
|
||||
def stop(self):
|
||||
self.stopped = True
|
||||
|
||||
def act(self, plugin, action):
|
||||
def on_next():
|
||||
result = pyblish.plugin.process(
|
||||
plugin, self.context, None, action.id
|
||||
)
|
||||
self.is_running = False
|
||||
self.was_acted.emit(result)
|
||||
|
||||
self.is_running = True
|
||||
util.defer(100, on_next)
|
||||
|
||||
def emit_(self, signal, kwargs):
|
||||
pyblish.api.emit(signal, **kwargs)
|
||||
|
||||
def _process(self, plugin, instance=None):
|
||||
"""Produce `result` from `plugin` and `instance`
|
||||
:func:`process` shares state with :func:`_iterator` such that
|
||||
an instance/plugin pair can be fetched and processed in isolation.
|
||||
Arguments:
|
||||
plugin (pyblish.api.Plugin): Produce result using plug-in
|
||||
instance (optional, pyblish.api.Instance): Process this instance,
|
||||
if no instance is provided, context is processed.
|
||||
"""
|
||||
|
||||
self.processing["nextOrder"] = plugin.order
|
||||
|
||||
try:
|
||||
result = pyblish.plugin.process(plugin, self.context, instance)
|
||||
# Make note of the order at which the
|
||||
# potential error error occured.
|
||||
if result["error"] is not None:
|
||||
self.processing["ordersWithError"].add(plugin.order)
|
||||
|
||||
except Exception as exc:
|
||||
raise Exception("Unknown error({}): {}".format(
|
||||
plugin.__name__, str(exc)
|
||||
))
|
||||
|
||||
return result
|
||||
|
||||
def _pair_yielder(self, plugins):
|
||||
for plugin in plugins:
|
||||
if (
|
||||
self.processing["current_group_order"] is not None
|
||||
and plugin.order > self.processing["current_group_order"]
|
||||
):
|
||||
new_next_group_order = None
|
||||
new_current_group_order = self.processing["next_group_order"]
|
||||
if new_current_group_order is not None:
|
||||
current_next_order_found = False
|
||||
for order in self.order_groups.groups().keys():
|
||||
if current_next_order_found:
|
||||
new_next_group_order = order
|
||||
break
|
||||
|
||||
if order == new_current_group_order:
|
||||
current_next_order_found = True
|
||||
|
||||
self.processing["next_group_order"] = new_next_group_order
|
||||
self.processing["current_group_order"] = (
|
||||
new_current_group_order
|
||||
)
|
||||
|
||||
if self.collect_state == 0:
|
||||
self.collect_state = 1
|
||||
self.switch_toggleability.emit(True)
|
||||
self.passed_group.emit(new_current_group_order)
|
||||
yield IterationBreak("Collected")
|
||||
|
||||
self.passed_group.emit(new_current_group_order)
|
||||
if self.errored:
|
||||
yield IterationBreak("Last group errored")
|
||||
|
||||
if self.collect_state == 1:
|
||||
self.collect_state = 2
|
||||
self.switch_toggleability.emit(False)
|
||||
|
||||
if not self.validated and plugin.order > self.validators_order:
|
||||
self.validated = True
|
||||
if self.processing["stop_on_validation"]:
|
||||
yield IterationBreak("Validated")
|
||||
|
||||
# Stop if was stopped
|
||||
if self.stopped:
|
||||
self.stopped = False
|
||||
yield IterationBreak("Stopped")
|
||||
|
||||
# check test if will stop
|
||||
self.processing["nextOrder"] = plugin.order
|
||||
message = self.test(**self.processing)
|
||||
if message:
|
||||
yield IterationBreak("Stopped due to \"{}\"".format(message))
|
||||
|
||||
self.processing["last_plugin_order"] = plugin.order
|
||||
if not plugin.active:
|
||||
pyblish.logic.log.debug("%s was inactive, skipping.." % plugin)
|
||||
self.was_skipped.emit(plugin)
|
||||
continue
|
||||
|
||||
if plugin.__instanceEnabled__:
|
||||
instances = pyblish.logic.instances_by_plugin(
|
||||
self.context, plugin
|
||||
)
|
||||
if not instances:
|
||||
self.was_skipped.emit(plugin)
|
||||
continue
|
||||
|
||||
for instance in instances:
|
||||
if instance.data.get("publish") is False:
|
||||
pyblish.logic.log.debug(
|
||||
"%s was inactive, skipping.." % instance
|
||||
)
|
||||
continue
|
||||
yield (plugin, instance)
|
||||
else:
|
||||
families = util.collect_families_from_instances(
|
||||
self.context, only_active=True
|
||||
)
|
||||
plugins = pyblish.logic.plugins_by_families(
|
||||
[plugin], families
|
||||
)
|
||||
if not plugins:
|
||||
self.was_skipped.emit(plugin)
|
||||
continue
|
||||
yield (plugin, None)
|
||||
|
||||
self.passed_group.emit(self.processing["next_group_order"])
|
||||
|
||||
def iterate_and_process(self, on_finished=lambda: None):
|
||||
""" Iterating inserted plugins with current context.
|
||||
Collectors do not contain instances, they are None when collecting!
|
||||
This process don't stop on one
|
||||
"""
|
||||
def on_next():
|
||||
try:
|
||||
self.current_pair = next(self.pair_generator)
|
||||
if isinstance(self.current_pair, IterationBreak):
|
||||
raise self.current_pair
|
||||
|
||||
except IterationBreak:
|
||||
self.is_running = False
|
||||
self.was_stopped.emit()
|
||||
return
|
||||
|
||||
except StopIteration:
|
||||
self.is_running = False
|
||||
# All pairs were processed successfully!
|
||||
return util.defer(500, on_finished)
|
||||
|
||||
except Exception:
|
||||
# This is a bug
|
||||
exc_type, exc_msg, exc_tb = sys.exc_info()
|
||||
traceback.print_exception(exc_type, exc_msg, exc_tb)
|
||||
self.is_running = False
|
||||
self.was_stopped.emit()
|
||||
return util.defer(
|
||||
500, lambda: on_unexpected_error(error=exc_msg)
|
||||
)
|
||||
|
||||
self.about_to_process.emit(*self.current_pair)
|
||||
util.defer(100, on_process)
|
||||
|
||||
def on_process():
|
||||
try:
|
||||
result = self._process(*self.current_pair)
|
||||
if result["error"] is not None:
|
||||
self.errored = True
|
||||
|
||||
self.was_processed.emit(result)
|
||||
|
||||
except Exception:
|
||||
# TODO this should be handled much differently
|
||||
exc_type, exc_msg, exc_tb = sys.exc_info()
|
||||
traceback.print_exception(exc_type, exc_msg, exc_tb)
|
||||
return util.defer(
|
||||
500, lambda: on_unexpected_error(error=exc_msg)
|
||||
)
|
||||
|
||||
util.defer(10, on_next)
|
||||
|
||||
def on_unexpected_error(error):
|
||||
util.u_print(u"An unexpected error occurred:\n %s" % error)
|
||||
return util.defer(500, on_finished)
|
||||
|
||||
self.is_running = True
|
||||
util.defer(10, on_next)
|
||||
|
||||
def collect(self):
|
||||
""" Iterate and process Collect plugins
|
||||
- load_plugins method is launched again when finished
|
||||
"""
|
||||
self.iterate_and_process()
|
||||
|
||||
def validate(self):
|
||||
""" Process plugins to validations_order value."""
|
||||
self.processing["stop_on_validation"] = True
|
||||
self.iterate_and_process()
|
||||
|
||||
def publish(self):
|
||||
""" Iterate and process all remaining plugins."""
|
||||
self.processing["stop_on_validation"] = False
|
||||
self.iterate_and_process(self.on_published)
|
||||
|
||||
def cleanup(self):
|
||||
"""Forcefully delete objects from memory
|
||||
In an ideal world, this shouldn't be necessary. Garbage
|
||||
collection guarantees that anything without reference
|
||||
is automatically removed.
|
||||
However, because this application is designed to be run
|
||||
multiple times from the same interpreter process, extra
|
||||
case must be taken to ensure there are no memory leaks.
|
||||
Explicitly deleting objects shines a light on where objects
|
||||
may still be referenced in the form of an error. No errors
|
||||
means this was uneccesary, but that's ok.
|
||||
"""
|
||||
|
||||
for instance in self.context:
|
||||
del(instance)
|
||||
|
||||
for plugin in self.plugins:
|
||||
del(plugin)
|
||||
552
pype/tools/pyblish_pype/delegate.py
Normal file
552
pype/tools/pyblish_pype/delegate.py
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
import platform
|
||||
|
||||
from .vendor.Qt import QtWidgets, QtGui, QtCore
|
||||
|
||||
from . import model
|
||||
from .awesome import tags as awesome
|
||||
from .constants import (
|
||||
PluginStates, InstanceStates, PluginActionStates, Roles
|
||||
)
|
||||
|
||||
colors = {
|
||||
"error": QtGui.QColor("#ff4a4a"),
|
||||
"warning": QtGui.QColor("#ff9900"),
|
||||
"ok": QtGui.QColor("#77AE24"),
|
||||
"active": QtGui.QColor("#99CEEE"),
|
||||
"idle": QtCore.Qt.white,
|
||||
"font": QtGui.QColor("#DDD"),
|
||||
"inactive": QtGui.QColor("#888"),
|
||||
"hover": QtGui.QColor(255, 255, 255, 10),
|
||||
"selected": QtGui.QColor(255, 255, 255, 20),
|
||||
"outline": QtGui.QColor("#333"),
|
||||
"group": QtGui.QColor("#333")
|
||||
}
|
||||
|
||||
scale_factors = {"darwin": 1.5}
|
||||
scale_factor = scale_factors.get(platform.system().lower(), 1.0)
|
||||
fonts = {
|
||||
"h3": QtGui.QFont("Open Sans", 10 * scale_factor, QtGui.QFont.Normal),
|
||||
"h4": QtGui.QFont("Open Sans", 8 * scale_factor, QtGui.QFont.Normal),
|
||||
"h5": QtGui.QFont("Open Sans", 8 * scale_factor, QtGui.QFont.DemiBold),
|
||||
"awesome6": QtGui.QFont("FontAwesome", 6 * scale_factor),
|
||||
"awesome10": QtGui.QFont("FontAwesome", 10 * scale_factor),
|
||||
"smallAwesome": QtGui.QFont("FontAwesome", 8 * scale_factor),
|
||||
"largeAwesome": QtGui.QFont("FontAwesome", 16 * scale_factor),
|
||||
}
|
||||
font_metrics = {
|
||||
"awesome6": QtGui.QFontMetrics(fonts["awesome6"]),
|
||||
"h4": QtGui.QFontMetrics(fonts["h4"]),
|
||||
"h5": QtGui.QFontMetrics(fonts["h5"])
|
||||
}
|
||||
icons = {
|
||||
"action": awesome["adn"],
|
||||
"angle-right": awesome["angle-right"],
|
||||
"angle-left": awesome["angle-left"],
|
||||
"plus-sign": awesome['plus'],
|
||||
"minus-sign": awesome['minus']
|
||||
}
|
||||
|
||||
|
||||
class PluginItemDelegate(QtWidgets.QStyledItemDelegate):
|
||||
"""Generic delegate for model items"""
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
"""Paint checkbox and text.
|
||||
_
|
||||
|_| My label >
|
||||
"""
|
||||
|
||||
body_rect = QtCore.QRectF(option.rect)
|
||||
|
||||
check_rect = QtCore.QRectF(body_rect)
|
||||
check_rect.setWidth(check_rect.height())
|
||||
check_offset = (check_rect.height() / 4) + 1
|
||||
check_rect.adjust(
|
||||
check_offset, check_offset, -check_offset, -check_offset
|
||||
)
|
||||
|
||||
check_color = colors["idle"]
|
||||
|
||||
perspective_icon = icons["angle-right"]
|
||||
perspective_rect = QtCore.QRectF(body_rect)
|
||||
perspective_rect.setWidth(perspective_rect.height())
|
||||
perspective_rect.adjust(0, 3, 0, 0)
|
||||
perspective_rect.translate(
|
||||
body_rect.width() - (perspective_rect.width() / 2 + 2),
|
||||
0
|
||||
)
|
||||
|
||||
publish_states = index.data(Roles.PublishFlagsRole)
|
||||
if publish_states & PluginStates.InProgress:
|
||||
check_color = colors["active"]
|
||||
|
||||
elif publish_states & PluginStates.HasError:
|
||||
check_color = colors["error"]
|
||||
|
||||
elif publish_states & PluginStates.HasWarning:
|
||||
check_color = colors["warning"]
|
||||
|
||||
elif publish_states & PluginStates.WasProcessed:
|
||||
check_color = colors["ok"]
|
||||
|
||||
elif not index.data(Roles.IsEnabledRole):
|
||||
check_color = colors["inactive"]
|
||||
|
||||
offset = (body_rect.height() - font_metrics["h4"].height()) / 2
|
||||
label_rect = QtCore.QRectF(body_rect.adjusted(
|
||||
check_rect.width() + 12, offset - 1, 0, 0
|
||||
))
|
||||
|
||||
assert label_rect.width() > 0
|
||||
|
||||
label = index.data(QtCore.Qt.DisplayRole)
|
||||
label = font_metrics["h4"].elidedText(
|
||||
label,
|
||||
QtCore.Qt.ElideRight,
|
||||
label_rect.width() - 20
|
||||
)
|
||||
|
||||
font_color = colors["idle"]
|
||||
if not index.data(QtCore.Qt.CheckStateRole):
|
||||
font_color = colors["inactive"]
|
||||
|
||||
# Maintain reference to state, so we can restore it once we're done
|
||||
painter.save()
|
||||
|
||||
# Draw perspective icon
|
||||
painter.setFont(fonts["awesome10"])
|
||||
painter.setPen(QtGui.QPen(font_color))
|
||||
painter.drawText(perspective_rect, perspective_icon)
|
||||
|
||||
# Draw label
|
||||
painter.setFont(fonts["h4"])
|
||||
painter.setPen(QtGui.QPen(font_color))
|
||||
painter.drawText(label_rect, label)
|
||||
|
||||
# Draw action icon
|
||||
if index.data(Roles.PluginActionsVisibleRole):
|
||||
painter.save()
|
||||
action_state = index.data(Roles.PluginActionProgressRole)
|
||||
if action_state & PluginActionStates.HasFailed:
|
||||
color = colors["error"]
|
||||
elif action_state & PluginActionStates.HasFinished:
|
||||
color = colors["ok"]
|
||||
elif action_state & PluginActionStates.InProgress:
|
||||
color = colors["active"]
|
||||
else:
|
||||
color = colors["idle"]
|
||||
|
||||
painter.setFont(fonts["smallAwesome"])
|
||||
painter.setPen(QtGui.QPen(color))
|
||||
|
||||
icon_rect = QtCore.QRectF(
|
||||
option.rect.adjusted(
|
||||
label_rect.width() - perspective_rect.width() / 2,
|
||||
label_rect.height() / 3, 0, 0
|
||||
)
|
||||
)
|
||||
painter.drawText(icon_rect, icons["action"])
|
||||
|
||||
painter.restore()
|
||||
|
||||
# Draw checkbox
|
||||
pen = QtGui.QPen(check_color, 1)
|
||||
painter.setPen(pen)
|
||||
|
||||
if index.data(Roles.IsOptionalRole):
|
||||
painter.drawRect(check_rect)
|
||||
|
||||
if index.data(QtCore.Qt.CheckStateRole):
|
||||
optional_check_rect = QtCore.QRectF(check_rect)
|
||||
optional_check_rect.adjust(2, 2, -1, -1)
|
||||
painter.fillRect(optional_check_rect, check_color)
|
||||
|
||||
else:
|
||||
painter.fillRect(check_rect, check_color)
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_MouseOver:
|
||||
painter.fillRect(body_rect, colors["hover"])
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_Selected:
|
||||
painter.fillRect(body_rect, colors["selected"])
|
||||
|
||||
# Ok, we're done, tidy up.
|
||||
painter.restore()
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
return QtCore.QSize(option.rect.width(), 20)
|
||||
|
||||
|
||||
class InstanceItemDelegate(QtWidgets.QStyledItemDelegate):
|
||||
"""Generic delegate for model items"""
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
"""Paint checkbox and text.
|
||||
_
|
||||
|_| My label >
|
||||
"""
|
||||
|
||||
body_rect = QtCore.QRectF(option.rect)
|
||||
|
||||
check_rect = QtCore.QRectF(body_rect)
|
||||
check_rect.setWidth(check_rect.height())
|
||||
offset = (check_rect.height() / 4) + 1
|
||||
check_rect.adjust(offset, offset, -(offset), -(offset))
|
||||
|
||||
check_color = colors["idle"]
|
||||
|
||||
perspective_icon = icons["angle-right"]
|
||||
perspective_rect = QtCore.QRectF(body_rect)
|
||||
perspective_rect.setWidth(perspective_rect.height())
|
||||
perspective_rect.adjust(0, 3, 0, 0)
|
||||
perspective_rect.translate(
|
||||
body_rect.width() - (perspective_rect.width() / 2 + 2),
|
||||
0
|
||||
)
|
||||
|
||||
publish_states = index.data(Roles.PublishFlagsRole)
|
||||
if publish_states & InstanceStates.InProgress:
|
||||
check_color = colors["active"]
|
||||
|
||||
elif publish_states & InstanceStates.HasError:
|
||||
check_color = colors["error"]
|
||||
|
||||
elif publish_states & InstanceStates.HasWarning:
|
||||
check_color = colors["warning"]
|
||||
|
||||
elif publish_states & InstanceStates.HasFinished:
|
||||
check_color = colors["ok"]
|
||||
|
||||
elif not index.data(Roles.IsEnabledRole):
|
||||
check_color = colors["inactive"]
|
||||
|
||||
offset = (body_rect.height() - font_metrics["h4"].height()) / 2
|
||||
label_rect = QtCore.QRectF(body_rect.adjusted(
|
||||
check_rect.width() + 12, offset - 1, 0, 0
|
||||
))
|
||||
|
||||
assert label_rect.width() > 0
|
||||
|
||||
label = index.data(QtCore.Qt.DisplayRole)
|
||||
label = font_metrics["h4"].elidedText(
|
||||
label,
|
||||
QtCore.Qt.ElideRight,
|
||||
label_rect.width() - 20
|
||||
)
|
||||
|
||||
font_color = colors["idle"]
|
||||
if not index.data(QtCore.Qt.CheckStateRole):
|
||||
font_color = colors["inactive"]
|
||||
|
||||
# Maintain reference to state, so we can restore it once we're done
|
||||
painter.save()
|
||||
|
||||
# Draw perspective icon
|
||||
painter.setFont(fonts["awesome10"])
|
||||
painter.setPen(QtGui.QPen(font_color))
|
||||
painter.drawText(perspective_rect, perspective_icon)
|
||||
|
||||
# Draw label
|
||||
painter.setFont(fonts["h4"])
|
||||
painter.setPen(QtGui.QPen(font_color))
|
||||
painter.drawText(label_rect, label)
|
||||
|
||||
# Draw checkbox
|
||||
pen = QtGui.QPen(check_color, 1)
|
||||
painter.setPen(pen)
|
||||
|
||||
if index.data(Roles.IsOptionalRole):
|
||||
painter.drawRect(check_rect)
|
||||
|
||||
if index.data(QtCore.Qt.CheckStateRole):
|
||||
optional_check_rect = QtCore.QRectF(check_rect)
|
||||
optional_check_rect.adjust(2, 2, -1, -1)
|
||||
painter.fillRect(optional_check_rect, check_color)
|
||||
|
||||
else:
|
||||
painter.fillRect(check_rect, check_color)
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_MouseOver:
|
||||
painter.fillRect(body_rect, colors["hover"])
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_Selected:
|
||||
painter.fillRect(body_rect, colors["selected"])
|
||||
|
||||
# Ok, we're done, tidy up.
|
||||
painter.restore()
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
return QtCore.QSize(option.rect.width(), 20)
|
||||
|
||||
|
||||
class OverviewGroupSection(QtWidgets.QStyledItemDelegate):
|
||||
"""Generic delegate for section header"""
|
||||
|
||||
item_class = None
|
||||
|
||||
def __init__(self, parent):
|
||||
super(OverviewGroupSection, self).__init__(parent)
|
||||
self.item_delegate = self.item_class(parent)
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
if index.data(Roles.TypeRole) in (
|
||||
model.InstanceType, model.PluginType
|
||||
):
|
||||
self.item_delegate.paint(painter, option, index)
|
||||
return
|
||||
|
||||
self.group_item_paint(painter, option, index)
|
||||
|
||||
def group_item_paint(self, painter, option, index):
|
||||
"""Paint text
|
||||
_
|
||||
My label
|
||||
"""
|
||||
body_rect = QtCore.QRectF(option.rect)
|
||||
bg_rect = QtCore.QRectF(
|
||||
body_rect.left(), body_rect.top() + 1,
|
||||
body_rect.width() - 5, body_rect.height() - 2
|
||||
)
|
||||
radius = 8.0
|
||||
bg_path = QtGui.QPainterPath()
|
||||
bg_path.addRoundedRect(bg_rect, radius, radius)
|
||||
painter.fillPath(bg_path, colors["group"])
|
||||
|
||||
expander_rect = QtCore.QRectF(bg_rect)
|
||||
expander_rect.setWidth(expander_rect.height())
|
||||
text_height = font_metrics["awesome6"].height()
|
||||
adjust_value = (expander_rect.height() - text_height) / 2
|
||||
expander_rect.adjust(
|
||||
adjust_value + 1.5, adjust_value - 0.5,
|
||||
-adjust_value + 1.5, -adjust_value - 0.5
|
||||
)
|
||||
|
||||
offset = (bg_rect.height() - font_metrics["h5"].height()) / 2
|
||||
label_rect = QtCore.QRectF(bg_rect.adjusted(
|
||||
expander_rect.width() + 12, offset - 1, 0, 0
|
||||
))
|
||||
|
||||
assert label_rect.width() > 0
|
||||
|
||||
expander_icon = icons["plus-sign"]
|
||||
|
||||
expanded = self.parent().isExpanded(index)
|
||||
if expanded:
|
||||
expander_icon = icons["minus-sign"]
|
||||
label = index.data(QtCore.Qt.DisplayRole)
|
||||
label = font_metrics["h5"].elidedText(
|
||||
label, QtCore.Qt.ElideRight, label_rect.width()
|
||||
)
|
||||
|
||||
# Maintain reference to state, so we can restore it once we're done
|
||||
painter.save()
|
||||
|
||||
painter.setFont(fonts["awesome6"])
|
||||
painter.setPen(QtGui.QPen(colors["idle"]))
|
||||
painter.drawText(expander_rect, expander_icon)
|
||||
|
||||
# Draw label
|
||||
painter.setFont(fonts["h5"])
|
||||
painter.drawText(label_rect, label)
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_MouseOver:
|
||||
painter.fillPath(bg_path, colors["hover"])
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_Selected:
|
||||
painter.fillPath(bg_path, colors["selected"])
|
||||
|
||||
# Ok, we're done, tidy up.
|
||||
painter.restore()
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
return QtCore.QSize(option.rect.width(), 20)
|
||||
|
||||
|
||||
class PluginDelegate(OverviewGroupSection):
|
||||
"""Generic delegate for model items in proxy tree view"""
|
||||
item_class = PluginItemDelegate
|
||||
|
||||
|
||||
class InstanceDelegate(OverviewGroupSection):
|
||||
"""Generic delegate for model items in proxy tree view"""
|
||||
item_class = InstanceItemDelegate
|
||||
|
||||
|
||||
class ArtistDelegate(QtWidgets.QStyledItemDelegate):
|
||||
"""Delegate used on Artist page"""
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
"""Paint checkbox and text
|
||||
|
||||
_______________________________________________
|
||||
| | label | duration |arrow|
|
||||
|toggle |_____________________| | to |
|
||||
| | families | |persp|
|
||||
|_______|_____________________|___________|_____|
|
||||
|
||||
"""
|
||||
|
||||
# Layout
|
||||
spacing = 10
|
||||
|
||||
body_rect = QtCore.QRectF(option.rect).adjusted(2, 2, -8, -2)
|
||||
content_rect = body_rect.adjusted(5, 5, -5, -5)
|
||||
|
||||
perspective_rect = QtCore.QRectF(body_rect)
|
||||
perspective_rect.setWidth(35)
|
||||
perspective_rect.setHeight(35)
|
||||
perspective_rect.translate(
|
||||
content_rect.width() - (perspective_rect.width() / 2) + 10,
|
||||
(content_rect.height() / 2) - (perspective_rect.height() / 2)
|
||||
)
|
||||
|
||||
toggle_rect = QtCore.QRectF(body_rect)
|
||||
toggle_rect.setWidth(7)
|
||||
toggle_rect.adjust(1, 1, 0, -1)
|
||||
|
||||
icon_rect = QtCore.QRectF(content_rect)
|
||||
icon_rect.translate(toggle_rect.width() + spacing, 3)
|
||||
icon_rect.setWidth(35)
|
||||
icon_rect.setHeight(35)
|
||||
|
||||
duration_rect = QtCore.QRectF(content_rect)
|
||||
duration_rect.translate(content_rect.width() - 50, 0)
|
||||
|
||||
# Colors
|
||||
check_color = colors["idle"]
|
||||
|
||||
publish_states = index.data(Roles.PublishFlagsRole)
|
||||
if publish_states is None:
|
||||
return
|
||||
if publish_states & InstanceStates.InProgress:
|
||||
check_color = colors["active"]
|
||||
|
||||
elif publish_states & InstanceStates.HasError:
|
||||
check_color = colors["error"]
|
||||
|
||||
elif publish_states & InstanceStates.HasWarning:
|
||||
check_color = colors["warning"]
|
||||
|
||||
elif publish_states & InstanceStates.HasFinished:
|
||||
check_color = colors["ok"]
|
||||
|
||||
elif not index.data(Roles.IsEnabledRole):
|
||||
check_color = colors["inactive"]
|
||||
|
||||
perspective_icon = icons["angle-right"]
|
||||
|
||||
if not index.data(QtCore.Qt.CheckStateRole):
|
||||
font_color = colors["inactive"]
|
||||
else:
|
||||
font_color = colors["idle"]
|
||||
|
||||
if (
|
||||
option.state
|
||||
& (
|
||||
QtWidgets.QStyle.State_MouseOver
|
||||
or QtWidgets.QStyle.State_Selected
|
||||
)
|
||||
):
|
||||
perspective_color = colors["idle"]
|
||||
else:
|
||||
perspective_color = colors["inactive"]
|
||||
# Maintan reference to state, so we can restore it once we're done
|
||||
painter.save()
|
||||
|
||||
# Draw background
|
||||
painter.fillRect(body_rect, colors["hover"])
|
||||
|
||||
# Draw icon
|
||||
icon = index.data(QtCore.Qt.DecorationRole)
|
||||
|
||||
painter.setFont(fonts["largeAwesome"])
|
||||
painter.setPen(QtGui.QPen(font_color))
|
||||
painter.drawText(icon_rect, icon)
|
||||
|
||||
# Draw label
|
||||
painter.setFont(fonts["h3"])
|
||||
label_rect = QtCore.QRectF(content_rect)
|
||||
label_x_offset = icon_rect.width() + spacing
|
||||
label_rect.translate(
|
||||
label_x_offset,
|
||||
0
|
||||
)
|
||||
metrics = painter.fontMetrics()
|
||||
label_rect.setHeight(metrics.lineSpacing())
|
||||
label_rect.setWidth(
|
||||
content_rect.width()
|
||||
- label_x_offset
|
||||
- perspective_rect.width()
|
||||
)
|
||||
# Elide label
|
||||
label = index.data(QtCore.Qt.DisplayRole)
|
||||
label = metrics.elidedText(
|
||||
label, QtCore.Qt.ElideRight, label_rect.width()
|
||||
)
|
||||
painter.drawText(label_rect, label)
|
||||
|
||||
# Draw families
|
||||
painter.setFont(fonts["h5"])
|
||||
painter.setPen(QtGui.QPen(colors["inactive"]))
|
||||
|
||||
families = ", ".join(index.data(Roles.FamiliesRole))
|
||||
families = painter.fontMetrics().elidedText(
|
||||
families, QtCore.Qt.ElideRight, label_rect.width()
|
||||
)
|
||||
|
||||
families_rect = QtCore.QRectF(label_rect)
|
||||
families_rect.translate(0, label_rect.height() + spacing)
|
||||
|
||||
painter.drawText(families_rect, families)
|
||||
|
||||
painter.setFont(fonts["largeAwesome"])
|
||||
painter.setPen(QtGui.QPen(perspective_color))
|
||||
painter.drawText(perspective_rect, perspective_icon)
|
||||
|
||||
# Draw checkbox
|
||||
pen = QtGui.QPen(check_color, 1)
|
||||
painter.setPen(pen)
|
||||
|
||||
if index.data(Roles.IsOptionalRole):
|
||||
painter.drawRect(toggle_rect)
|
||||
|
||||
if index.data(QtCore.Qt.CheckStateRole):
|
||||
painter.fillRect(toggle_rect, check_color)
|
||||
|
||||
elif (
|
||||
index.data(QtCore.Qt.CheckStateRole)
|
||||
):
|
||||
painter.fillRect(toggle_rect, check_color)
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_MouseOver:
|
||||
painter.fillRect(body_rect, colors["hover"])
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_Selected:
|
||||
painter.fillRect(body_rect, colors["selected"])
|
||||
|
||||
painter.setPen(colors["outline"])
|
||||
painter.drawRect(body_rect)
|
||||
|
||||
# Ok, we're done, tidy up.
|
||||
painter.restore()
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
return QtCore.QSize(option.rect.width(), 80)
|
||||
|
||||
|
||||
class TerminalItem(QtWidgets.QStyledItemDelegate):
|
||||
"""Delegate used exclusively for the Terminal"""
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
super(TerminalItem, self).paint(painter, option, index)
|
||||
item_type = index.data(Roles.TypeRole)
|
||||
if item_type == model.TerminalDetailType:
|
||||
return
|
||||
|
||||
hover = QtGui.QPainterPath()
|
||||
hover.addRect(QtCore.QRectF(option.rect).adjusted(0, 0, -1, -1))
|
||||
if option.state & QtWidgets.QStyle.State_Selected:
|
||||
painter.fillPath(hover, colors["selected"])
|
||||
|
||||
if option.state & QtWidgets.QStyle.State_MouseOver:
|
||||
painter.fillPath(hover, colors["hover"])
|
||||
BIN
pype/tools/pyblish_pype/font/fontawesome/fontawesome-webfont.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/fontawesome/fontawesome-webfont.ttf
Normal file
Binary file not shown.
202
pype/tools/pyblish_pype/font/opensans/LICENSE.txt
Normal file
202
pype/tools/pyblish_pype/font/opensans/LICENSE.txt
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Bold.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Bold.ttf
Normal file
Binary file not shown.
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-BoldItalic.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-ExtraBold.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-ExtraBold.ttf
Normal file
Binary file not shown.
Binary file not shown.
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Italic.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Italic.ttf
Normal file
Binary file not shown.
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Light.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Light.ttf
Normal file
Binary file not shown.
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-LightItalic.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-LightItalic.ttf
Normal file
Binary file not shown.
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Regular.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Regular.ttf
Normal file
Binary file not shown.
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Semibold.ttf
Normal file
BIN
pype/tools/pyblish_pype/font/opensans/OpenSans-Semibold.ttf
Normal file
Binary file not shown.
Binary file not shown.
2
pype/tools/pyblish_pype/i18n/pyblish_lite.pro
Normal file
2
pype/tools/pyblish_pype/i18n/pyblish_lite.pro
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SOURCES = ../window.py
|
||||
TRANSLATIONS = zh_CN.ts
|
||||
BIN
pype/tools/pyblish_pype/i18n/zh_CN.qm
Normal file
BIN
pype/tools/pyblish_pype/i18n/zh_CN.qm
Normal file
Binary file not shown.
96
pype/tools/pyblish_pype/i18n/zh_CN.ts
Normal file
96
pype/tools/pyblish_pype/i18n/zh_CN.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS><TS version="1.1" language="zh_CN">
|
||||
<context>
|
||||
<name>Window</name>
|
||||
<message>
|
||||
<location filename="../window.py" line="763"/>
|
||||
<source>Finishing up reset..</source>
|
||||
<translation>完成重置..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="228"/>
|
||||
<source>Comment..</source>
|
||||
<translation>备注..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="722"/>
|
||||
<source>Processing</source>
|
||||
<translation>处理</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="877"/>
|
||||
<source>Stopped due to error(s), see Terminal.</source>
|
||||
<translation>因错误终止, 请查看终端。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="879"/>
|
||||
<source>Finished successfully!</source>
|
||||
<translation>成功完成!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="889"/>
|
||||
<source>About to reset..</source>
|
||||
<translation>即将重置..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="911"/>
|
||||
<source>Preparing validate..</source>
|
||||
<translation>准备校验..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="919"/>
|
||||
<source>Preparing publish..</source>
|
||||
<translation>准备发布..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="928"/>
|
||||
<source>Preparing</source>
|
||||
<translation>准备</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="951"/>
|
||||
<source>Action prepared.</source>
|
||||
<translation>动作已就绪。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="969"/>
|
||||
<source>Cleaning up models..</source>
|
||||
<translation>清理数据模型..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="974"/>
|
||||
<source>Cleaning up terminal..</source>
|
||||
<translation>清理终端..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="978"/>
|
||||
<source>Cleaning up controller..</source>
|
||||
<translation>清理控制器..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="981"/>
|
||||
<source>All clean!</source>
|
||||
<translation>清理完成!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="982"/>
|
||||
<source>Good bye</source>
|
||||
<translation>再见</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="993"/>
|
||||
<source>..as soon as processing is finished..</source>
|
||||
<translation>..处理即将完成..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="1008"/>
|
||||
<source>Stopping..</source>
|
||||
<translation>正在停止..</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../window.py" line="985"/>
|
||||
<source>Closing..</source>
|
||||
<translation>正在关闭..</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
BIN
pype/tools/pyblish_pype/img/down_arrow.png
Normal file
BIN
pype/tools/pyblish_pype/img/down_arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 165 B |
BIN
pype/tools/pyblish_pype/img/logo-extrasmall.png
Normal file
BIN
pype/tools/pyblish_pype/img/logo-extrasmall.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
pype/tools/pyblish_pype/img/tab-home.png
Normal file
BIN
pype/tools/pyblish_pype/img/tab-home.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 313 B |
BIN
pype/tools/pyblish_pype/img/tab-overview.png
Normal file
BIN
pype/tools/pyblish_pype/img/tab-overview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 207 B |
BIN
pype/tools/pyblish_pype/img/tab-terminal.png
Normal file
BIN
pype/tools/pyblish_pype/img/tab-terminal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 197 B |
732
pype/tools/pyblish_pype/mock.py
Normal file
732
pype/tools/pyblish_pype/mock.py
Normal file
|
|
@ -0,0 +1,732 @@
|
|||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
import pyblish.api
|
||||
|
||||
|
||||
class MyAction(pyblish.api.Action):
|
||||
label = "My Action"
|
||||
on = "processed"
|
||||
|
||||
def process(self, context, plugin):
|
||||
self.log.info("Running!")
|
||||
|
||||
|
||||
class MyOtherAction(pyblish.api.Action):
|
||||
label = "My Other Action"
|
||||
|
||||
def process(self, context, plugin):
|
||||
self.log.info("Running!")
|
||||
|
||||
|
||||
class CollectComment(pyblish.api.ContextPlugin):
|
||||
"""This collector has a very long comment.
|
||||
|
||||
The idea is that this comment should either be elided, or word-
|
||||
wrapped in the corresponding view.
|
||||
|
||||
"""
|
||||
|
||||
order = pyblish.api.CollectorOrder
|
||||
|
||||
def process(self, context):
|
||||
context.data["comment"] = ""
|
||||
|
||||
|
||||
class MyCollector(pyblish.api.ContextPlugin):
|
||||
label = "My Collector"
|
||||
order = pyblish.api.CollectorOrder
|
||||
|
||||
def process(self, context):
|
||||
context.create_instance("MyInstance 1", families=["myFamily"])
|
||||
context.create_instance("MyInstance 2", families=["myFamily 2"])
|
||||
context.create_instance(
|
||||
"MyInstance 3",
|
||||
families=["myFamily 2"],
|
||||
publish=False
|
||||
)
|
||||
|
||||
|
||||
class MyValidator(pyblish.api.InstancePlugin):
|
||||
order = pyblish.api.ValidatorOrder
|
||||
active = False
|
||||
label = "My Validator"
|
||||
actions = [MyAction,
|
||||
MyOtherAction]
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Validating: %s" % instance)
|
||||
|
||||
|
||||
class MyExtractor(pyblish.api.InstancePlugin):
|
||||
order = pyblish.api.ExtractorOrder
|
||||
families = ["myFamily"]
|
||||
label = "My Extractor"
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Extracting: %s" % instance)
|
||||
|
||||
|
||||
class CollectRenamed(pyblish.api.Collector):
|
||||
def process(self, context):
|
||||
i = context.create_instance("MyInstanceXYZ", family="MyFamily")
|
||||
i.set_data("name", "My instance")
|
||||
|
||||
|
||||
class CollectNegatron(pyblish.api.Collector):
|
||||
"""Negative collector adds Negatron"""
|
||||
|
||||
order = pyblish.api.Collector.order - 0.49
|
||||
|
||||
def process_context(self, context):
|
||||
self.log.info("Collecting Negatron")
|
||||
context.create_instance("Negatron", family="MyFamily")
|
||||
|
||||
|
||||
class CollectPositron(pyblish.api.Collector):
|
||||
"""Positive collector adds Positron"""
|
||||
|
||||
order = pyblish.api.Collector.order + 0.49
|
||||
|
||||
def process_context(self, context):
|
||||
self.log.info("Collecting Positron")
|
||||
context.create_instance("Positron", family="MyFamily")
|
||||
|
||||
|
||||
class SelectInstances(pyblish.api.Selector):
|
||||
"""Select debugging instances
|
||||
|
||||
These instances are part of the evil plan to destroy the world.
|
||||
Be weary, be vigilant, be sexy.
|
||||
|
||||
"""
|
||||
|
||||
def process_context(self, context):
|
||||
self.log.info("Selecting instances..")
|
||||
|
||||
for instance in instances[:-1]:
|
||||
name, data = instance["name"], instance["data"]
|
||||
self.log.info("Selecting: %s" % name)
|
||||
instance = context.create_instance(name)
|
||||
|
||||
for key, value in data.items():
|
||||
instance.set_data(key, value)
|
||||
|
||||
|
||||
class SelectDiInstances(pyblish.api.Selector):
|
||||
"""Select DI instances"""
|
||||
|
||||
name = "Select Dependency Instances"
|
||||
|
||||
def process(self, context):
|
||||
name, data = instances[-1]["name"], instances[-1]["data"]
|
||||
self.log.info("Selecting: %s" % name)
|
||||
instance = context.create_instance(name)
|
||||
|
||||
for key, value in data.items():
|
||||
instance.set_data(key, value)
|
||||
|
||||
|
||||
class SelectInstancesFailure(pyblish.api.Selector):
|
||||
"""Select some instances, but fail before adding anything to the context.
|
||||
|
||||
That's right. I'm programmed to fail. Try me.
|
||||
|
||||
"""
|
||||
|
||||
__fail__ = True
|
||||
|
||||
def process_context(self, context):
|
||||
self.log.warning("I'm about to fail")
|
||||
raise AssertionError("I was programmed to fail")
|
||||
|
||||
|
||||
class SelectInstances2(pyblish.api.Selector):
|
||||
def process(self, context):
|
||||
self.log.warning("I'm good")
|
||||
|
||||
|
||||
class ValidateNamespace(pyblish.api.Validator):
|
||||
"""Namespaces must be orange
|
||||
|
||||
In case a namespace is not orange, report immediately to
|
||||
your officer in charge, ask for a refund, do a backflip.
|
||||
|
||||
This has been an example of:
|
||||
|
||||
- A long doc-string
|
||||
- With a list
|
||||
- And plenty of newlines and tabs.
|
||||
|
||||
"""
|
||||
|
||||
families = ["B"]
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Validating the namespace of %s" % instance.data("name"))
|
||||
self.log.info("""And here's another message, quite long, in fact it's
|
||||
too long to be displayed in a single row of text.
|
||||
But that's how we roll down here. It's got \nnew lines\nas well.
|
||||
|
||||
- And lists
|
||||
- And more lists
|
||||
|
||||
""")
|
||||
|
||||
|
||||
class ValidateContext(pyblish.api.Validator):
|
||||
families = ["A", "B"]
|
||||
|
||||
def process_context(self, context):
|
||||
self.log.info("Processing context..")
|
||||
|
||||
|
||||
class ValidateContextFailure(pyblish.api.Validator):
|
||||
optional = True
|
||||
families = ["C"]
|
||||
__fail__ = True
|
||||
|
||||
def process_context(self, context):
|
||||
self.log.info("About to fail..")
|
||||
raise AssertionError("""I was programmed to fail
|
||||
|
||||
The reason I failed was because the sun was not aligned with the tides,
|
||||
and the moon is gray; not yellow. Try again when the moon is yellow.""")
|
||||
|
||||
|
||||
class Validator1(pyblish.api.Validator):
|
||||
"""Test of the order attribute"""
|
||||
order = pyblish.api.Validator.order + 0.1
|
||||
families = ["A"]
|
||||
|
||||
def process_instance(self, instance):
|
||||
pass
|
||||
|
||||
|
||||
class Validator2(pyblish.api.Validator):
|
||||
order = pyblish.api.Validator.order + 0.2
|
||||
families = ["B"]
|
||||
|
||||
def process_instance(self, instance):
|
||||
pass
|
||||
|
||||
|
||||
class Validator3(pyblish.api.Validator):
|
||||
order = pyblish.api.Validator.order + 0.3
|
||||
families = ["B"]
|
||||
|
||||
def process_instance(self, instance):
|
||||
pass
|
||||
|
||||
|
||||
class ValidateFailureMock(pyblish.api.Validator):
|
||||
"""Plug-in that always fails"""
|
||||
optional = True
|
||||
order = pyblish.api.Validator.order + 0.1
|
||||
families = ["C"]
|
||||
__fail__ = True
|
||||
|
||||
def process_instance(self, instance):
|
||||
self.log.debug("e = mc^2")
|
||||
self.log.info("About to fail..")
|
||||
self.log.warning("Failing.. soooon..")
|
||||
self.log.critical("Ok, you're done.")
|
||||
raise AssertionError("""ValidateFailureMock was destined to fail..
|
||||
|
||||
Here's some extended information about what went wrong.
|
||||
|
||||
It has quite the long string associated with it, including
|
||||
a few newlines and a list.
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
|
||||
""")
|
||||
|
||||
|
||||
class ValidateIsIncompatible(pyblish.api.Validator):
|
||||
"""This plug-in should never appear.."""
|
||||
requires = False # This is invalid
|
||||
|
||||
|
||||
class ValidateWithRepair(pyblish.api.Validator):
|
||||
"""A validator with repair functionality"""
|
||||
optional = True
|
||||
families = ["C"]
|
||||
__fail__ = True
|
||||
|
||||
def process_instance(self, instance):
|
||||
raise AssertionError(
|
||||
"%s is invalid, try repairing it!" % instance.name
|
||||
)
|
||||
|
||||
def repair_instance(self, instance):
|
||||
self.log.info("Attempting to repair..")
|
||||
self.log.info("Success!")
|
||||
|
||||
|
||||
class ValidateWithRepairFailure(pyblish.api.Validator):
|
||||
"""A validator with repair functionality that fails"""
|
||||
optional = True
|
||||
families = ["C"]
|
||||
__fail__ = True
|
||||
|
||||
def process_instance(self, instance):
|
||||
raise AssertionError(
|
||||
"%s is invalid, try repairing it!" % instance.name
|
||||
)
|
||||
|
||||
def repair_instance(self, instance):
|
||||
self.log.info("Attempting to repair..")
|
||||
raise AssertionError("Could not repair due to X")
|
||||
|
||||
|
||||
class ValidateWithVeryVeryVeryLongLongNaaaaame(pyblish.api.Validator):
|
||||
"""A validator with repair functionality that fails"""
|
||||
families = ["A"]
|
||||
|
||||
|
||||
class ValidateWithRepairContext(pyblish.api.Validator):
|
||||
"""A validator with repair functionality that fails"""
|
||||
optional = True
|
||||
families = ["C"]
|
||||
__fail__ = True
|
||||
|
||||
def process_context(self, context):
|
||||
raise AssertionError("Could not validate context, try repairing it")
|
||||
|
||||
def repair_context(self, context):
|
||||
self.log.info("Attempting to repair..")
|
||||
raise AssertionError("Could not repair")
|
||||
|
||||
|
||||
class ExtractAsMa(pyblish.api.Extractor):
|
||||
"""Extract contents of each instance into .ma
|
||||
|
||||
Serialise scene using Maya's own facilities and then put
|
||||
it on the hard-disk. Once complete, this plug-in relies
|
||||
on a Conformer to put it in it's final location, as this
|
||||
extractor merely positions it in the users local temp-
|
||||
directory.
|
||||
|
||||
"""
|
||||
|
||||
optional = True
|
||||
__expected__ = {
|
||||
"logCount": ">=4"
|
||||
}
|
||||
|
||||
def process_instance(self, instance):
|
||||
self.log.info("About to extract scene to .ma..")
|
||||
self.log.info("Extraction went well, now verifying the data..")
|
||||
|
||||
if instance.name == "Richard05":
|
||||
self.log.warning("You're almost running out of disk space!")
|
||||
|
||||
self.log.info("About to finish up")
|
||||
self.log.info("Finished successfully")
|
||||
|
||||
|
||||
class ConformAsset(pyblish.api.Conformer):
|
||||
"""Conform the world
|
||||
|
||||
Step 1: Conform all humans and Step 2: Conform all non-humans.
|
||||
Once conforming has completed, rinse and repeat.
|
||||
|
||||
"""
|
||||
|
||||
optional = True
|
||||
|
||||
def process_instance(self, instance):
|
||||
self.log.info("About to conform all humans..")
|
||||
|
||||
if instance.name == "Richard05":
|
||||
self.log.warning("Richard05 is a conformist!")
|
||||
|
||||
self.log.info("About to conform all non-humans..")
|
||||
self.log.info("Conformed Successfully")
|
||||
|
||||
|
||||
class ValidateInstancesDI(pyblish.api.Validator):
|
||||
"""Validate using the DI interface"""
|
||||
families = ["diFamily"]
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Validating %s.." % instance.data("name"))
|
||||
|
||||
|
||||
class ValidateDIWithRepair(pyblish.api.Validator):
|
||||
families = ["diFamily"]
|
||||
optional = True
|
||||
__fail__ = True
|
||||
|
||||
def process(self, instance):
|
||||
raise AssertionError("I was programmed to fail, for repair")
|
||||
|
||||
def repair(self, instance):
|
||||
self.log.info("Repairing %s" % instance.data("name"))
|
||||
|
||||
|
||||
class ExtractInstancesDI(pyblish.api.Extractor):
|
||||
"""Extract using the DI interface"""
|
||||
families = ["diFamily"]
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Extracting %s.." % instance.data("name"))
|
||||
|
||||
|
||||
class ValidateWithLabel(pyblish.api.Validator):
|
||||
"""Validate using the DI interface"""
|
||||
label = "Validate with Label"
|
||||
|
||||
|
||||
class ValidateWithLongLabel(pyblish.api.Validator):
|
||||
"""Validate using the DI interface"""
|
||||
label = "Validate with Loooooooooooooooooooooong Label"
|
||||
|
||||
|
||||
class SimplePlugin1(pyblish.api.Plugin):
|
||||
"""Validate using the simple-plugin interface"""
|
||||
|
||||
def process(self):
|
||||
self.log.info("I'm a simple plug-in, only processed once")
|
||||
|
||||
|
||||
class SimplePlugin2(pyblish.api.Plugin):
|
||||
"""Validate using the simple-plugin interface
|
||||
|
||||
It doesn't have an order, and will likely end up *before* all
|
||||
other plug-ins. (due to how sorted([1, 2, 3, None]) works)
|
||||
|
||||
"""
|
||||
|
||||
def process(self, context):
|
||||
self.log.info("Processing the context, simply: %s" % context)
|
||||
|
||||
|
||||
class SimplePlugin3(pyblish.api.Plugin):
|
||||
"""Simply process every instance"""
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Processing the instance, simply: %s" % instance)
|
||||
|
||||
|
||||
class ContextAction(pyblish.api.Action):
|
||||
label = "Context action"
|
||||
|
||||
def process(self, context):
|
||||
self.log.info("I have access to the context")
|
||||
self.log.info("Context.instances: %s" % str(list(context)))
|
||||
|
||||
|
||||
class FailingAction(pyblish.api.Action):
|
||||
label = "Failing action"
|
||||
|
||||
def process(self):
|
||||
self.log.info("About to fail..")
|
||||
raise Exception("I failed")
|
||||
|
||||
|
||||
class LongRunningAction(pyblish.api.Action):
|
||||
label = "Long-running action"
|
||||
|
||||
def process(self):
|
||||
self.log.info("Sleeping for 2 seconds..")
|
||||
time.sleep(2)
|
||||
self.log.info("Ah, that's better")
|
||||
|
||||
|
||||
class IconAction(pyblish.api.Action):
|
||||
label = "Icon action"
|
||||
icon = "crop"
|
||||
|
||||
def process(self):
|
||||
self.log.info("I have an icon")
|
||||
|
||||
|
||||
class PluginAction(pyblish.api.Action):
|
||||
label = "Plugin action"
|
||||
|
||||
def process(self, plugin):
|
||||
self.log.info("I have access to my parent plug-in")
|
||||
self.log.info("Which is %s" % plugin.id)
|
||||
|
||||
|
||||
class LaunchExplorerAction(pyblish.api.Action):
|
||||
label = "Open in Explorer"
|
||||
icon = "folder-open"
|
||||
|
||||
def process(self, context):
|
||||
cwd = os.getcwd()
|
||||
self.log.info("Opening %s in Explorer" % cwd)
|
||||
result = subprocess.call("start .", cwd=cwd, shell=True)
|
||||
self.log.debug(result)
|
||||
|
||||
|
||||
class ProcessedAction(pyblish.api.Action):
|
||||
label = "Success action"
|
||||
icon = "check"
|
||||
on = "processed"
|
||||
|
||||
def process(self):
|
||||
self.log.info("I am only available on a successful plug-in")
|
||||
|
||||
|
||||
class FailedAction(pyblish.api.Action):
|
||||
label = "Failure action"
|
||||
icon = "close"
|
||||
on = "failed"
|
||||
|
||||
|
||||
class SucceededAction(pyblish.api.Action):
|
||||
label = "Success action"
|
||||
icon = "check"
|
||||
on = "succeeded"
|
||||
|
||||
def process(self):
|
||||
self.log.info("I am only available on a successful plug-in")
|
||||
|
||||
|
||||
class LongLabelAction(pyblish.api.Action):
|
||||
label = "An incredibly, incredicly looooon label. Very long."
|
||||
icon = "close"
|
||||
|
||||
|
||||
class BadEventAction(pyblish.api.Action):
|
||||
label = "Bad event action"
|
||||
on = "not exist"
|
||||
|
||||
|
||||
class InactiveAction(pyblish.api.Action):
|
||||
active = False
|
||||
|
||||
|
||||
class PluginWithActions(pyblish.api.Validator):
|
||||
optional = True
|
||||
actions = [
|
||||
pyblish.api.Category("General"),
|
||||
ContextAction,
|
||||
FailingAction,
|
||||
LongRunningAction,
|
||||
IconAction,
|
||||
PluginAction,
|
||||
pyblish.api.Category("Empty"),
|
||||
pyblish.api.Category("OS"),
|
||||
LaunchExplorerAction,
|
||||
pyblish.api.Separator,
|
||||
FailedAction,
|
||||
SucceededAction,
|
||||
pyblish.api.Category("Debug"),
|
||||
BadEventAction,
|
||||
InactiveAction,
|
||||
LongLabelAction,
|
||||
pyblish.api.Category("Empty"),
|
||||
]
|
||||
|
||||
def process(self):
|
||||
self.log.info("Ran PluginWithActions")
|
||||
|
||||
|
||||
class FailingPluginWithActions(pyblish.api.Validator):
|
||||
optional = True
|
||||
actions = [
|
||||
FailedAction,
|
||||
SucceededAction,
|
||||
]
|
||||
|
||||
def process(self):
|
||||
raise Exception("I was programmed to fail")
|
||||
|
||||
|
||||
class ValidateDefaultOff(pyblish.api.Validator):
|
||||
families = ["A", "B"]
|
||||
active = False
|
||||
optional = True
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Processing instance..")
|
||||
|
||||
|
||||
class ValidateWithHyperlinks(pyblish.api.Validator):
|
||||
"""To learn about Pyblish
|
||||
|
||||
<a href="http://pyblish.com">click here</a> (http://pyblish.com)
|
||||
|
||||
"""
|
||||
|
||||
families = ["A", "B"]
|
||||
|
||||
def process(self, instance):
|
||||
self.log.info("Processing instance..")
|
||||
|
||||
msg = "To learn about Pyblish, <a href='http://pyblish.com'>"
|
||||
msg += "click here</a> (http://pyblish.com)"
|
||||
|
||||
self.log.info(msg)
|
||||
|
||||
|
||||
class LongRunningCollector(pyblish.api.Collector):
|
||||
"""I will take at least 2 seconds..."""
|
||||
def process(self, context):
|
||||
self.log.info("Sleeping for 2 seconds..")
|
||||
time.sleep(2)
|
||||
self.log.info("Good morning")
|
||||
|
||||
|
||||
class LongRunningValidator(pyblish.api.Validator):
|
||||
"""I will take at least 2 seconds..."""
|
||||
def process(self, context):
|
||||
self.log.info("Sleeping for 2 seconds..")
|
||||
time.sleep(2)
|
||||
self.log.info("Good morning")
|
||||
|
||||
|
||||
class RearrangingPlugin(pyblish.api.ContextPlugin):
|
||||
"""Sort plug-ins by family, and then reverse it"""
|
||||
order = pyblish.api.CollectorOrder + 0.2
|
||||
|
||||
def process(self, context):
|
||||
self.log.info("Reversing instances in the context..")
|
||||
context[:] = sorted(
|
||||
context,
|
||||
key=lambda i: i.data["family"],
|
||||
reverse=True
|
||||
)
|
||||
self.log.info("Reversed!")
|
||||
|
||||
|
||||
class InactiveInstanceCollectorPlugin(pyblish.api.InstancePlugin):
|
||||
"""Special case of an InstancePlugin running as a Collector"""
|
||||
order = pyblish.api.CollectorOrder + 0.1
|
||||
active = False
|
||||
|
||||
def process(self, instance):
|
||||
raise TypeError("I shouldn't have run in the first place")
|
||||
|
||||
|
||||
class CollectWithIcon(pyblish.api.ContextPlugin):
|
||||
order = pyblish.api.CollectorOrder
|
||||
|
||||
def process(self, context):
|
||||
instance = context.create_instance("With Icon")
|
||||
instance.data["icon"] = "play"
|
||||
|
||||
|
||||
instances = [
|
||||
{
|
||||
"name": "Peter01",
|
||||
"data": {
|
||||
"family": "A",
|
||||
"publish": False
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Richard05",
|
||||
"data": {
|
||||
"family": "A",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Steven11",
|
||||
"data": {
|
||||
"family": "B",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Piraya12",
|
||||
"data": {
|
||||
"family": "B",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Marcus",
|
||||
"data": {
|
||||
"family": "C",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Extra1",
|
||||
"data": {
|
||||
"family": "C",
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DependencyInstance",
|
||||
"data": {
|
||||
"family": "diFamily"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "NoFamily",
|
||||
"data": {}
|
||||
},
|
||||
{
|
||||
"name": "Failure 1",
|
||||
"data": {
|
||||
"family": "failure",
|
||||
"fail": False
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Failure 2",
|
||||
"data": {
|
||||
"family": "failure",
|
||||
"fail": True
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
plugins = [
|
||||
MyCollector,
|
||||
MyValidator,
|
||||
MyExtractor,
|
||||
|
||||
CollectRenamed,
|
||||
CollectNegatron,
|
||||
CollectPositron,
|
||||
SelectInstances,
|
||||
SelectInstances2,
|
||||
SelectDiInstances,
|
||||
SelectInstancesFailure,
|
||||
ValidateFailureMock,
|
||||
ValidateNamespace,
|
||||
# ValidateIsIncompatible,
|
||||
ValidateWithVeryVeryVeryLongLongNaaaaame,
|
||||
ValidateContext,
|
||||
ValidateContextFailure,
|
||||
Validator1,
|
||||
Validator2,
|
||||
Validator3,
|
||||
ValidateWithRepair,
|
||||
ValidateWithRepairFailure,
|
||||
ValidateWithRepairContext,
|
||||
ValidateWithLabel,
|
||||
ValidateWithLongLabel,
|
||||
ValidateDefaultOff,
|
||||
ValidateWithHyperlinks,
|
||||
ExtractAsMa,
|
||||
ConformAsset,
|
||||
|
||||
SimplePlugin1,
|
||||
SimplePlugin2,
|
||||
SimplePlugin3,
|
||||
|
||||
ValidateInstancesDI,
|
||||
ExtractInstancesDI,
|
||||
ValidateDIWithRepair,
|
||||
|
||||
PluginWithActions,
|
||||
FailingPluginWithActions,
|
||||
|
||||
# LongRunningCollector,
|
||||
# LongRunningValidator,
|
||||
|
||||
RearrangingPlugin,
|
||||
InactiveInstanceCollectorPlugin,
|
||||
|
||||
CollectComment,
|
||||
CollectWithIcon,
|
||||
]
|
||||
|
||||
pyblish.api.sort_plugins(plugins)
|
||||
1232
pype/tools/pyblish_pype/model.py
Normal file
1232
pype/tools/pyblish_pype/model.py
Normal file
File diff suppressed because it is too large
Load diff
19
pype/tools/pyblish_pype/settings.py
Normal file
19
pype/tools/pyblish_pype/settings.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
WindowTitle = "Pyblish" # Customize the window of the pyblish-lite window.
|
||||
UseLabel = True # Customize whether to show label names for plugins.
|
||||
|
||||
# Customize which tab to start on. Possible choices are: "artist", "overview"
|
||||
# and "terminal".
|
||||
InitialTab = "artist"
|
||||
|
||||
# Customize the window size.
|
||||
WindowSize = (430, 600)
|
||||
|
||||
TerminalFilters = {
|
||||
"info": True,
|
||||
"log_debug": True,
|
||||
"log_info": True,
|
||||
"log_warning": True,
|
||||
"log_error": True,
|
||||
"log_critical": True,
|
||||
"traceback": True,
|
||||
}
|
||||
311
pype/tools/pyblish_pype/util.py
Normal file
311
pype/tools/pyblish_pype/util.py
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
from __future__ import (absolute_import, division, print_function,
|
||||
unicode_literals)
|
||||
|
||||
import os
|
||||
import sys
|
||||
import numbers
|
||||
import copy
|
||||
import collections
|
||||
|
||||
from .vendor.Qt import QtCore
|
||||
from .vendor.six import text_type
|
||||
import pyblish.api
|
||||
|
||||
root = os.path.dirname(__file__)
|
||||
|
||||
|
||||
def get_asset(*path):
|
||||
"""Return path to asset, relative the install directory
|
||||
|
||||
Usage:
|
||||
>>> path = get_asset("dir", "to", "asset.png")
|
||||
>>> path == os.path.join(root, "dir", "to", "asset.png")
|
||||
True
|
||||
|
||||
Arguments:
|
||||
path (str): One or more paths, to be concatenated
|
||||
|
||||
"""
|
||||
|
||||
return os.path.join(root, *path)
|
||||
|
||||
|
||||
def defer(delay, func):
|
||||
"""Append artificial delay to `func`
|
||||
|
||||
This aids in keeping the GUI responsive, but complicates logic
|
||||
when producing tests. To combat this, the environment variable ensures
|
||||
that every operation is synchonous.
|
||||
|
||||
Arguments:
|
||||
delay (float): Delay multiplier; default 1, 0 means no delay
|
||||
func (callable): Any callable
|
||||
|
||||
"""
|
||||
|
||||
delay *= float(os.getenv("PYBLISH_DELAY", 1))
|
||||
if delay > 0:
|
||||
return QtCore.QTimer.singleShot(delay, func)
|
||||
else:
|
||||
return func()
|
||||
|
||||
|
||||
def u_print(msg, **kwargs):
|
||||
"""`print` with encoded unicode.
|
||||
|
||||
`print` unicode may cause UnicodeEncodeError
|
||||
or non-readable result when `PYTHONIOENCODING` is not set.
|
||||
this will fix it.
|
||||
|
||||
Arguments:
|
||||
msg (unicode): Message to print.
|
||||
**kwargs: Keyword argument for `print` function.
|
||||
"""
|
||||
|
||||
if isinstance(msg, text_type):
|
||||
encoding = None
|
||||
try:
|
||||
encoding = os.getenv('PYTHONIOENCODING', sys.stdout.encoding)
|
||||
except AttributeError:
|
||||
# `sys.stdout.encoding` may not exists.
|
||||
pass
|
||||
msg = msg.encode(encoding or 'utf-8', 'replace')
|
||||
print(msg, **kwargs)
|
||||
|
||||
|
||||
def collect_families_from_instances(instances, only_active=False):
|
||||
all_families = set()
|
||||
for instance in instances:
|
||||
if only_active:
|
||||
if instance.data.get("publish") is False:
|
||||
continue
|
||||
family = instance.data.get("family")
|
||||
if family:
|
||||
all_families.add(family)
|
||||
|
||||
families = instance.data.get("families") or tuple()
|
||||
for family in families:
|
||||
all_families.add(family)
|
||||
|
||||
return list(all_families)
|
||||
|
||||
|
||||
class OrderGroups:
|
||||
# Validator order can be set with environment "PYBLISH_VALIDATION_ORDER"
|
||||
# - this variable sets when validation button will hide and proecssing
|
||||
# of validation will end with ability to continue in process
|
||||
default_validation_order = pyblish.api.ValidatorOrder + 0.5
|
||||
|
||||
# Group range can be set with environment "PYBLISH_GROUP_RANGE"
|
||||
default_group_range = 1
|
||||
|
||||
# Group string can be set with environment "PYBLISH_GROUP_SETTING"
|
||||
default_groups = {
|
||||
pyblish.api.CollectorOrder + 0.5: "Collect",
|
||||
pyblish.api.ValidatorOrder + 0.5: "Validate",
|
||||
pyblish.api.ExtractorOrder + 0.5: "Extract",
|
||||
pyblish.api.IntegratorOrder + 0.5: "Integrate",
|
||||
None: "Other"
|
||||
}
|
||||
|
||||
# *** This example should have same result as is `default_groups` if
|
||||
# `group_range` is set to "1"
|
||||
__groups_str_example__ = (
|
||||
# half of `group_range` is added to 0 because number means it is Order
|
||||
"0=Collect"
|
||||
# if `<` is before than it means group range is not used
|
||||
# but is expected that number is already max
|
||||
",<1.5=Validate"
|
||||
# "Extractor" will be used in range `<1.5; 2.5)`
|
||||
",<2.5=Extract"
|
||||
",<3.5=Integrate"
|
||||
# "Other" if number is not set than all remaining plugins are in
|
||||
# - in this case Other's range is <3.5; infinity)
|
||||
",Other"
|
||||
)
|
||||
|
||||
_groups = None
|
||||
_validation_order = None
|
||||
_group_range = None
|
||||
|
||||
def __init__(
|
||||
self, group_str=None, group_range=None, validation_order=None
|
||||
):
|
||||
super(OrderGroups, self).__init__()
|
||||
# Override class methods with object methods
|
||||
self.groups = self._object_groups
|
||||
self.validation_order = self._object_validation_order
|
||||
self.group_range = self._object_group_range
|
||||
self.reset = self._object_reset
|
||||
|
||||
# set
|
||||
if group_range is not None:
|
||||
self._group_range = self.parse_group_range(
|
||||
group_range
|
||||
)
|
||||
|
||||
if group_str is not None:
|
||||
self._groups = self.parse_group_str(
|
||||
group_str
|
||||
)
|
||||
|
||||
if validation_order is not None:
|
||||
self._validation_order = self.parse_validation_order(
|
||||
validation_order
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _groups_method(obj):
|
||||
if obj._groups is None:
|
||||
obj._groups = obj.parse_group_str(
|
||||
group_range=obj.group_range()
|
||||
)
|
||||
return obj._groups
|
||||
|
||||
@staticmethod
|
||||
def _reset_method(obj):
|
||||
obj._groups = None
|
||||
obj._validation_order = None
|
||||
obj._group_range = None
|
||||
|
||||
@classmethod
|
||||
def reset(cls):
|
||||
return cls._reset_method(cls)
|
||||
|
||||
def _object_reset(self):
|
||||
return self._reset_method(self)
|
||||
|
||||
@classmethod
|
||||
def groups(cls):
|
||||
return cls._groups_method(cls)
|
||||
|
||||
def _object_groups(self):
|
||||
return self._groups_method(self)
|
||||
|
||||
@staticmethod
|
||||
def _validation_order_method(obj):
|
||||
if obj._validation_order is None:
|
||||
obj._validation_order = obj.parse_validation_order(
|
||||
group_range=obj.group_range()
|
||||
)
|
||||
return obj._validation_order
|
||||
|
||||
@classmethod
|
||||
def validation_order(cls):
|
||||
return cls._validation_order_method(cls)
|
||||
|
||||
def _object_validation_order(self):
|
||||
return self._validation_order_method(self)
|
||||
|
||||
@staticmethod
|
||||
def _group_range_method(obj):
|
||||
if obj._group_range is None:
|
||||
obj._group_range = obj.parse_group_range()
|
||||
return obj._group_range
|
||||
|
||||
@classmethod
|
||||
def group_range(cls):
|
||||
return cls._group_range_method(cls)
|
||||
|
||||
def _object_group_range(self):
|
||||
return self._group_range_method(self)
|
||||
|
||||
@staticmethod
|
||||
def sort_groups(_groups_dict):
|
||||
sorted_dict = collections.OrderedDict()
|
||||
|
||||
# make sure wont affect any dictionary as pointer
|
||||
groups_dict = copy.deepcopy(_groups_dict)
|
||||
last_order = None
|
||||
if None in groups_dict:
|
||||
last_order = groups_dict.pop(None)
|
||||
|
||||
for key in sorted(groups_dict):
|
||||
sorted_dict[key] = groups_dict[key]
|
||||
|
||||
if last_order is not None:
|
||||
sorted_dict[None] = last_order
|
||||
|
||||
return sorted_dict
|
||||
|
||||
@staticmethod
|
||||
def parse_group_str(groups_str=None, group_range=None):
|
||||
if groups_str is None:
|
||||
groups_str = os.environ.get("PYBLISH_GROUP_SETTING")
|
||||
|
||||
if groups_str is None:
|
||||
return OrderGroups.sort_groups(OrderGroups.default_groups)
|
||||
|
||||
items = groups_str.split(",")
|
||||
groups = {}
|
||||
for item in items:
|
||||
if "=" not in item:
|
||||
order = None
|
||||
label = item
|
||||
else:
|
||||
order, label = item.split("=")
|
||||
order = order.strip()
|
||||
if not order:
|
||||
order = None
|
||||
elif order.startswith("<"):
|
||||
order = float(order.replace("<", ""))
|
||||
else:
|
||||
if group_range is None:
|
||||
group_range = OrderGroups.default_group_range
|
||||
print(
|
||||
"Using default Plugin group range \"{}\".".format(
|
||||
OrderGroups.default_group_range
|
||||
)
|
||||
)
|
||||
order = float(order) + float(group_range) / 2
|
||||
|
||||
if order in groups:
|
||||
print((
|
||||
"Order \"{}\" is registered more than once."
|
||||
" Using first found."
|
||||
).format(str(order)))
|
||||
continue
|
||||
|
||||
groups[order] = label
|
||||
|
||||
return OrderGroups.sort_groups(groups)
|
||||
|
||||
@staticmethod
|
||||
def parse_validation_order(validation_order_value=None, group_range=None):
|
||||
if validation_order_value is None:
|
||||
validation_order_value = os.environ.get("PYBLISH_VALIDATION_ORDER")
|
||||
|
||||
if validation_order_value is None:
|
||||
return OrderGroups.default_validation_order
|
||||
|
||||
if group_range is None:
|
||||
group_range = OrderGroups.default_group_range
|
||||
|
||||
group_range_half = float(group_range) / 2
|
||||
|
||||
if isinstance(validation_order_value, numbers.Integral):
|
||||
return validation_order_value + group_range_half
|
||||
|
||||
if validation_order_value.startswith("<"):
|
||||
validation_order_value = float(
|
||||
validation_order_value.replace("<", "")
|
||||
)
|
||||
else:
|
||||
validation_order_value = (
|
||||
float(validation_order_value)
|
||||
+ group_range_half
|
||||
)
|
||||
return validation_order_value
|
||||
|
||||
@staticmethod
|
||||
def parse_group_range(group_range=None):
|
||||
if group_range is None:
|
||||
group_range = os.environ.get("PYBLISH_GROUP_RANGE")
|
||||
|
||||
if group_range is None:
|
||||
return OrderGroups.default_group_range
|
||||
|
||||
if isinstance(group_range, numbers.Integral):
|
||||
return group_range
|
||||
|
||||
return float(group_range)
|
||||
1827
pype/tools/pyblish_pype/vendor/Qt.py
vendored
Normal file
1827
pype/tools/pyblish_pype/vendor/Qt.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
0
pype/tools/pyblish_pype/vendor/__init__.py
vendored
Normal file
0
pype/tools/pyblish_pype/vendor/__init__.py
vendored
Normal file
39
pype/tools/pyblish_pype/vendor/qtawesome/__init__.py
vendored
Normal file
39
pype/tools/pyblish_pype/vendor/qtawesome/__init__.py
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
"""
|
||||
qtawesome - use font-awesome in PyQt / PySide applications
|
||||
|
||||
This is a port to Python of the C++ QtAwesome library by Rick Blommers
|
||||
"""
|
||||
from .iconic_font import IconicFont, set_global_defaults
|
||||
from .animation import Pulse, Spin
|
||||
from ._version import version_info, __version__
|
||||
|
||||
_resource = {'iconic': None, }
|
||||
|
||||
|
||||
def _instance():
|
||||
if _resource['iconic'] is None:
|
||||
_resource['iconic'] = IconicFont(('fa', 'fontawesome-webfont.ttf', 'fontawesome-webfont-charmap.json'),
|
||||
('ei', 'elusiveicons-webfont.ttf', 'elusiveicons-webfont-charmap.json'))
|
||||
return _resource['iconic']
|
||||
|
||||
|
||||
def icon(*args, **kwargs):
|
||||
return _instance().icon(*args, **kwargs)
|
||||
|
||||
|
||||
def load_font(*args, **kwargs):
|
||||
return _instance().load_font(*args, **kwargs)
|
||||
|
||||
|
||||
def charmap(prefixed_name):
|
||||
prefix, name = prefixed_name.split('.')
|
||||
return _instance().charmap[prefix][name]
|
||||
|
||||
|
||||
def font(*args, **kwargs):
|
||||
return _instance().font(*args, **kwargs)
|
||||
|
||||
|
||||
def set_defaults(**kwargs):
|
||||
return set_global_defaults(**kwargs)
|
||||
|
||||
2
pype/tools/pyblish_pype/vendor/qtawesome/_version.py
vendored
Normal file
2
pype/tools/pyblish_pype/vendor/qtawesome/_version.py
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
version_info = (0, 3, 0, 'dev')
|
||||
__version__ = '.'.join(map(str, version_info))
|
||||
41
pype/tools/pyblish_pype/vendor/qtawesome/animation.py
vendored
Normal file
41
pype/tools/pyblish_pype/vendor/qtawesome/animation.py
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
from ..Qt import QtCore
|
||||
|
||||
|
||||
class Spin:
|
||||
|
||||
def __init__(self, parent_widget, interval=10, step=1):
|
||||
self.parent_widget = parent_widget
|
||||
self.interval, self.step = interval, step
|
||||
self.info = {}
|
||||
|
||||
def _update(self, parent_widget):
|
||||
if self.parent_widget in self.info:
|
||||
timer, angle, step = self.info[self.parent_widget]
|
||||
|
||||
if angle >= 360:
|
||||
angle = 0
|
||||
|
||||
angle += step
|
||||
self.info[parent_widget] = timer, angle, step
|
||||
parent_widget.update()
|
||||
|
||||
def setup(self, icon_painter, painter, rect):
|
||||
|
||||
if self.parent_widget not in self.info:
|
||||
timer = QtCore.QTimer()
|
||||
timer.timeout.connect(lambda: self._update(self.parent_widget))
|
||||
self.info[self.parent_widget] = [timer, 0, self.step]
|
||||
timer.start(self.interval)
|
||||
else:
|
||||
timer, angle, self.step = self.info[self.parent_widget]
|
||||
x_center = rect.width() * 0.5
|
||||
y_center = rect.height() * 0.5
|
||||
painter.translate(x_center, y_center)
|
||||
painter.rotate(angle)
|
||||
painter.translate(-x_center, -y_center)
|
||||
|
||||
|
||||
class Pulse(Spin):
|
||||
|
||||
def __init__(self, parent_widget):
|
||||
Spin.__init__(self, parent_widget, interval=300, step=45)
|
||||
306
pype/tools/pyblish_pype/vendor/qtawesome/fonts/elusiveicons-webfont-charmap.json
vendored
Normal file
306
pype/tools/pyblish_pype/vendor/qtawesome/fonts/elusiveicons-webfont-charmap.json
vendored
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
{
|
||||
"address-book": "0xf102",
|
||||
"address-book-alt": "0xf101",
|
||||
"adjust": "0xf104",
|
||||
"adjust-alt": "0xf103",
|
||||
"adult": "0xf105",
|
||||
"align-center": "0xf106",
|
||||
"align-justify": "0xf107",
|
||||
"align-left": "0xf108",
|
||||
"align-right": "0xf109",
|
||||
"arrow-down": "0xf10a",
|
||||
"arrow-left": "0xf10b",
|
||||
"arrow-right": "0xf10c",
|
||||
"arrow-up": "0xf10d",
|
||||
"asl": "0xf10e",
|
||||
"asterisk": "0xf10f",
|
||||
"backward": "0xf110",
|
||||
"ban-circle": "0xf111",
|
||||
"barcode": "0xf112",
|
||||
"behance": "0xf113",
|
||||
"bell": "0xf114",
|
||||
"blind": "0xf115",
|
||||
"blogger": "0xf116",
|
||||
"bold": "0xf117",
|
||||
"book": "0xf118",
|
||||
"bookmark": "0xf11a",
|
||||
"bookmark-empty": "0xf119",
|
||||
"braille": "0xf11b",
|
||||
"briefcase": "0xf11c",
|
||||
"broom": "0xf11d",
|
||||
"brush": "0xf11e",
|
||||
"bulb": "0xf11f",
|
||||
"bullhorn": "0xf120",
|
||||
"calendar": "0xf122",
|
||||
"calendar-sign": "0xf121",
|
||||
"camera": "0xf123",
|
||||
"car": "0xf124",
|
||||
"caret-down": "0xf125",
|
||||
"caret-left": "0xf126",
|
||||
"caret-right": "0xf127",
|
||||
"caret-up": "0xf128",
|
||||
"cc": "0xf129",
|
||||
"certificate": "0xf12a",
|
||||
"check": "0xf12c",
|
||||
"check-empty": "0xf12b",
|
||||
"chevron-down": "0xf12d",
|
||||
"chevron-left": "0xf12e",
|
||||
"chevron-right": "0xf12f",
|
||||
"chevron-up": "0xf130",
|
||||
"child": "0xf131",
|
||||
"circle-arrow-down": "0xf132",
|
||||
"circle-arrow-left": "0xf133",
|
||||
"circle-arrow-right": "0xf134",
|
||||
"circle-arrow-up": "0xf135",
|
||||
"cloud": "0xf137",
|
||||
"cloud-alt": "0xf136",
|
||||
"cog": "0xf139",
|
||||
"cog-alt": "0xf138",
|
||||
"cogs": "0xf13a",
|
||||
"comment": "0xf13c",
|
||||
"comment-alt": "0xf13b",
|
||||
"compass": "0xf13e",
|
||||
"compass-alt": "0xf13d",
|
||||
"credit-card": "0xf13f",
|
||||
"css": "0xf140",
|
||||
"dashboard": "0xf141",
|
||||
"delicious": "0xf142",
|
||||
"deviantart": "0xf143",
|
||||
"digg": "0xf144",
|
||||
"download": "0xf146",
|
||||
"download-alt": "0xf145",
|
||||
"dribbble": "0xf147",
|
||||
"edit": "0xf148",
|
||||
"eject": "0xf149",
|
||||
"envelope": "0xf14b",
|
||||
"envelope-alt": "0xf14a",
|
||||
"error": "0xf14d",
|
||||
"error-alt": "0xf14c",
|
||||
"eur": "0xf14e",
|
||||
"exclamation-sign": "0xf14f",
|
||||
"eye-close": "0xf150",
|
||||
"eye-open": "0xf151",
|
||||
"facebook": "0xf152",
|
||||
"facetime-video": "0xf153",
|
||||
"fast-backward": "0xf154",
|
||||
"fast-forward": "0xf155",
|
||||
"female": "0xf156",
|
||||
"file": "0xf15c",
|
||||
"file-alt": "0xf157",
|
||||
"file-edit": "0xf159",
|
||||
"file-edit-alt": "0xf158",
|
||||
"file-new": "0xf15b",
|
||||
"file-new-alt": "0xf15a",
|
||||
"film": "0xf15d",
|
||||
"filter": "0xf15e",
|
||||
"fire": "0xf15f",
|
||||
"flag": "0xf161",
|
||||
"flag-alt": "0xf160",
|
||||
"flickr": "0xf162",
|
||||
"folder": "0xf166",
|
||||
"folder-close": "0xf163",
|
||||
"folder-open": "0xf164",
|
||||
"folder-sign": "0xf165",
|
||||
"font": "0xf167",
|
||||
"fontsize": "0xf168",
|
||||
"fork": "0xf169",
|
||||
"forward": "0xf16b",
|
||||
"forward-alt": "0xf16a",
|
||||
"foursquare": "0xf16c",
|
||||
"friendfeed": "0xf16e",
|
||||
"friendfeed-rect": "0xf16d",
|
||||
"fullscreen": "0xf16f",
|
||||
"gbp": "0xf170",
|
||||
"gift": "0xf171",
|
||||
"github": "0xf173",
|
||||
"github-text": "0xf172",
|
||||
"glass": "0xf174",
|
||||
"glasses": "0xf175",
|
||||
"globe": "0xf177",
|
||||
"globe-alt": "0xf176",
|
||||
"googleplus": "0xf178",
|
||||
"graph": "0xf17a",
|
||||
"graph-alt": "0xf179",
|
||||
"group": "0xf17c",
|
||||
"group-alt": "0xf17b",
|
||||
"guidedog": "0xf17d",
|
||||
"hand-down": "0xf17e",
|
||||
"hand-left": "0xf17f",
|
||||
"hand-right": "0xf180",
|
||||
"hand-up": "0xf181",
|
||||
"hdd": "0xf182",
|
||||
"headphones": "0xf183",
|
||||
"hearing-impaired": "0xf184",
|
||||
"heart": "0xf187",
|
||||
"heart-alt": "0xf185",
|
||||
"heart-empty": "0xf186",
|
||||
"home": "0xf189",
|
||||
"home-alt": "0xf188",
|
||||
"hourglass": "0xf18a",
|
||||
"idea": "0xf18c",
|
||||
"idea-alt": "0xf18b",
|
||||
"inbox": "0xf18f",
|
||||
"inbox-alt": "0xf18d",
|
||||
"inbox-box": "0xf18e",
|
||||
"indent-left": "0xf190",
|
||||
"indent-right": "0xf191",
|
||||
"info-circle": "0xf192",
|
||||
"instagram": "0xf193",
|
||||
"iphone-home": "0xf194",
|
||||
"italic": "0xf195",
|
||||
"key": "0xf196",
|
||||
"laptop": "0xf198",
|
||||
"laptop-alt": "0xf197",
|
||||
"lastfm": "0xf199",
|
||||
"leaf": "0xf19a",
|
||||
"lines": "0xf19b",
|
||||
"link": "0xf19c",
|
||||
"linkedin": "0xf19d",
|
||||
"list": "0xf19f",
|
||||
"list-alt": "0xf19e",
|
||||
"livejournal": "0xf1a0",
|
||||
"lock": "0xf1a2",
|
||||
"lock-alt": "0xf1a1",
|
||||
"magic": "0xf1a3",
|
||||
"magnet": "0xf1a4",
|
||||
"male": "0xf1a5",
|
||||
"map-marker": "0xf1a7",
|
||||
"map-marker-alt": "0xf1a6",
|
||||
"mic": "0xf1a9",
|
||||
"mic-alt": "0xf1a8",
|
||||
"minus": "0xf1ab",
|
||||
"minus-sign": "0xf1aa",
|
||||
"move": "0xf1ac",
|
||||
"music": "0xf1ad",
|
||||
"myspace": "0xf1ae",
|
||||
"network": "0xf1af",
|
||||
"off": "0xf1b0",
|
||||
"ok": "0xf1b3",
|
||||
"ok-circle": "0xf1b1",
|
||||
"ok-sign": "0xf1b2",
|
||||
"opensource": "0xf1b4",
|
||||
"paper-clip": "0xf1b6",
|
||||
"paper-clip-alt": "0xf1b5",
|
||||
"path": "0xf1b7",
|
||||
"pause": "0xf1b9",
|
||||
"pause-alt": "0xf1b8",
|
||||
"pencil": "0xf1bb",
|
||||
"pencil-alt": "0xf1ba",
|
||||
"person": "0xf1bc",
|
||||
"phone": "0xf1be",
|
||||
"phone-alt": "0xf1bd",
|
||||
"photo": "0xf1c0",
|
||||
"photo-alt": "0xf1bf",
|
||||
"picasa": "0xf1c1",
|
||||
"picture": "0xf1c2",
|
||||
"pinterest": "0xf1c3",
|
||||
"plane": "0xf1c4",
|
||||
"play": "0xf1c7",
|
||||
"play-alt": "0xf1c5",
|
||||
"play-circle": "0xf1c6",
|
||||
"plurk": "0xf1c9",
|
||||
"plurk-alt": "0xf1c8",
|
||||
"plus": "0xf1cb",
|
||||
"plus-sign": "0xf1ca",
|
||||
"podcast": "0xf1cc",
|
||||
"print": "0xf1cd",
|
||||
"puzzle": "0xf1ce",
|
||||
"qrcode": "0xf1cf",
|
||||
"question": "0xf1d1",
|
||||
"question-sign": "0xf1d0",
|
||||
"quote-alt": "0xf1d2",
|
||||
"quote-right": "0xf1d4",
|
||||
"quote-right-alt": "0xf1d3",
|
||||
"quotes": "0xf1d5",
|
||||
"random": "0xf1d6",
|
||||
"record": "0xf1d7",
|
||||
"reddit": "0xf1d8",
|
||||
"redux": "0xf1d9",
|
||||
"refresh": "0xf1da",
|
||||
"remove": "0xf1dd",
|
||||
"remove-circle": "0xf1db",
|
||||
"remove-sign": "0xf1dc",
|
||||
"repeat": "0xf1df",
|
||||
"repeat-alt": "0xf1de",
|
||||
"resize-full": "0xf1e0",
|
||||
"resize-horizontal": "0xf1e1",
|
||||
"resize-small": "0xf1e2",
|
||||
"resize-vertical": "0xf1e3",
|
||||
"return-key": "0xf1e4",
|
||||
"retweet": "0xf1e5",
|
||||
"reverse-alt": "0xf1e6",
|
||||
"road": "0xf1e7",
|
||||
"rss": "0xf1e8",
|
||||
"scissors": "0xf1e9",
|
||||
"screen": "0xf1eb",
|
||||
"screen-alt": "0xf1ea",
|
||||
"screenshot": "0xf1ec",
|
||||
"search": "0xf1ee",
|
||||
"search-alt": "0xf1ed",
|
||||
"share": "0xf1f0",
|
||||
"share-alt": "0xf1ef",
|
||||
"shopping-cart": "0xf1f2",
|
||||
"shopping-cart-sign": "0xf1f1",
|
||||
"signal": "0xf1f3",
|
||||
"skype": "0xf1f4",
|
||||
"slideshare": "0xf1f5",
|
||||
"smiley": "0xf1f7",
|
||||
"smiley-alt": "0xf1f6",
|
||||
"soundcloud": "0xf1f8",
|
||||
"speaker": "0xf1f9",
|
||||
"spotify": "0xf1fa",
|
||||
"stackoverflow": "0xf1fb",
|
||||
"star": "0xf1fe",
|
||||
"star-alt": "0xf1fc",
|
||||
"star-empty": "0xf1fd",
|
||||
"step-backward": "0xf1ff",
|
||||
"step-forward": "0xf200",
|
||||
"stop": "0xf202",
|
||||
"stop-alt": "0xf201",
|
||||
"stumbleupon": "0xf203",
|
||||
"tag": "0xf204",
|
||||
"tags": "0xf205",
|
||||
"tasks": "0xf206",
|
||||
"text-height": "0xf207",
|
||||
"text-width": "0xf208",
|
||||
"th": "0xf20b",
|
||||
"th-large": "0xf209",
|
||||
"th-list": "0xf20a",
|
||||
"thumbs-down": "0xf20c",
|
||||
"thumbs-up": "0xf20d",
|
||||
"time": "0xf20f",
|
||||
"time-alt": "0xf20e",
|
||||
"tint": "0xf210",
|
||||
"torso": "0xf211",
|
||||
"trash": "0xf213",
|
||||
"trash-alt": "0xf212",
|
||||
"tumblr": "0xf214",
|
||||
"twitter": "0xf215",
|
||||
"universal-access": "0xf216",
|
||||
"unlock": "0xf218",
|
||||
"unlock-alt": "0xf217",
|
||||
"upload": "0xf219",
|
||||
"usd": "0xf21a",
|
||||
"user": "0xf21b",
|
||||
"viadeo": "0xf21c",
|
||||
"video": "0xf21f",
|
||||
"video-alt": "0xf21d",
|
||||
"video-chat": "0xf21e",
|
||||
"view-mode": "0xf220",
|
||||
"vimeo": "0xf221",
|
||||
"vkontakte": "0xf222",
|
||||
"volume-down": "0xf223",
|
||||
"volume-off": "0xf224",
|
||||
"volume-up": "0xf225",
|
||||
"w3c": "0xf226",
|
||||
"warning-sign": "0xf227",
|
||||
"website": "0xf229",
|
||||
"website-alt": "0xf228",
|
||||
"wheelchair": "0xf22a",
|
||||
"wordpress": "0xf22b",
|
||||
"wrench": "0xf22d",
|
||||
"wrench-alt": "0xf22c",
|
||||
"youtube": "0xf22e",
|
||||
"zoom-in": "0xf22f",
|
||||
"zoom-out": "0xf230"
|
||||
}
|
||||
BIN
pype/tools/pyblish_pype/vendor/qtawesome/fonts/elusiveicons-webfont.ttf
vendored
Normal file
BIN
pype/tools/pyblish_pype/vendor/qtawesome/fonts/elusiveicons-webfont.ttf
vendored
Normal file
Binary file not shown.
696
pype/tools/pyblish_pype/vendor/qtawesome/fonts/fontawesome-webfont-charmap.json
vendored
Normal file
696
pype/tools/pyblish_pype/vendor/qtawesome/fonts/fontawesome-webfont-charmap.json
vendored
Normal file
|
|
@ -0,0 +1,696 @@
|
|||
{
|
||||
"500px": "f26e",
|
||||
"adjust": "f042",
|
||||
"adn": "f170",
|
||||
"align-center": "f037",
|
||||
"align-justify": "f039",
|
||||
"align-left": "f036",
|
||||
"align-right": "f038",
|
||||
"amazon": "f270",
|
||||
"ambulance": "f0f9",
|
||||
"anchor": "f13d",
|
||||
"android": "f17b",
|
||||
"angellist": "f209",
|
||||
"angle-double-down": "f103",
|
||||
"angle-double-left": "f100",
|
||||
"angle-double-right": "f101",
|
||||
"angle-double-up": "f102",
|
||||
"angle-down": "f107",
|
||||
"angle-left": "f104",
|
||||
"angle-right": "f105",
|
||||
"angle-up": "f106",
|
||||
"apple": "f179",
|
||||
"archive": "f187",
|
||||
"area-chart": "f1fe",
|
||||
"arrow-circle-down": "f0ab",
|
||||
"arrow-circle-left": "f0a8",
|
||||
"arrow-circle-o-down": "f01a",
|
||||
"arrow-circle-o-left": "f190",
|
||||
"arrow-circle-o-right": "f18e",
|
||||
"arrow-circle-o-up": "f01b",
|
||||
"arrow-circle-right": "f0a9",
|
||||
"arrow-circle-up": "f0aa",
|
||||
"arrow-down": "f063",
|
||||
"arrow-left": "f060",
|
||||
"arrow-right": "f061",
|
||||
"arrow-up": "f062",
|
||||
"arrows": "f047",
|
||||
"arrows-alt": "f0b2",
|
||||
"arrows-h": "f07e",
|
||||
"arrows-v": "f07d",
|
||||
"asterisk": "f069",
|
||||
"at": "f1fa",
|
||||
"automobile": "f1b9",
|
||||
"backward": "f04a",
|
||||
"balance-scale": "f24e",
|
||||
"ban": "f05e",
|
||||
"bank": "f19c",
|
||||
"bar-chart": "f080",
|
||||
"bar-chart-o": "f080",
|
||||
"barcode": "f02a",
|
||||
"bars": "f0c9",
|
||||
"battery-0": "f244",
|
||||
"battery-1": "f243",
|
||||
"battery-2": "f242",
|
||||
"battery-3": "f241",
|
||||
"battery-4": "f240",
|
||||
"battery-empty": "f244",
|
||||
"battery-full": "f240",
|
||||
"battery-half": "f242",
|
||||
"battery-quarter": "f243",
|
||||
"battery-three-quarters": "f241",
|
||||
"bed": "f236",
|
||||
"beer": "f0fc",
|
||||
"behance": "f1b4",
|
||||
"behance-square": "f1b5",
|
||||
"bell": "f0f3",
|
||||
"bell-o": "f0a2",
|
||||
"bell-slash": "f1f6",
|
||||
"bell-slash-o": "f1f7",
|
||||
"bicycle": "f206",
|
||||
"binoculars": "f1e5",
|
||||
"birthday-cake": "f1fd",
|
||||
"bitbucket": "f171",
|
||||
"bitbucket-square": "f172",
|
||||
"bitcoin": "f15a",
|
||||
"black-tie": "f27e",
|
||||
"bluetooth": "f293",
|
||||
"bluetooth-b": "f294",
|
||||
"bold": "f032",
|
||||
"bolt": "f0e7",
|
||||
"bomb": "f1e2",
|
||||
"book": "f02d",
|
||||
"bookmark": "f02e",
|
||||
"bookmark-o": "f097",
|
||||
"briefcase": "f0b1",
|
||||
"btc": "f15a",
|
||||
"bug": "f188",
|
||||
"building": "f1ad",
|
||||
"building-o": "f0f7",
|
||||
"bullhorn": "f0a1",
|
||||
"bullseye": "f140",
|
||||
"bus": "f207",
|
||||
"buysellads": "f20d",
|
||||
"cab": "f1ba",
|
||||
"calculator": "f1ec",
|
||||
"calendar": "f073",
|
||||
"calendar-check-o": "f274",
|
||||
"calendar-minus-o": "f272",
|
||||
"calendar-o": "f133",
|
||||
"calendar-plus-o": "f271",
|
||||
"calendar-times-o": "f273",
|
||||
"camera": "f030",
|
||||
"camera-retro": "f083",
|
||||
"car": "f1b9",
|
||||
"caret-down": "f0d7",
|
||||
"caret-left": "f0d9",
|
||||
"caret-right": "f0da",
|
||||
"caret-square-o-down": "f150",
|
||||
"caret-square-o-left": "f191",
|
||||
"caret-square-o-right": "f152",
|
||||
"caret-square-o-up": "f151",
|
||||
"caret-up": "f0d8",
|
||||
"cart-arrow-down": "f218",
|
||||
"cart-plus": "f217",
|
||||
"cc": "f20a",
|
||||
"cc-amex": "f1f3",
|
||||
"cc-diners-club": "f24c",
|
||||
"cc-discover": "f1f2",
|
||||
"cc-jcb": "f24b",
|
||||
"cc-mastercard": "f1f1",
|
||||
"cc-paypal": "f1f4",
|
||||
"cc-stripe": "f1f5",
|
||||
"cc-visa": "f1f0",
|
||||
"certificate": "f0a3",
|
||||
"chain": "f0c1",
|
||||
"chain-broken": "f127",
|
||||
"check": "f00c",
|
||||
"check-circle": "f058",
|
||||
"check-circle-o": "f05d",
|
||||
"check-square": "f14a",
|
||||
"check-square-o": "f046",
|
||||
"chevron-circle-down": "f13a",
|
||||
"chevron-circle-left": "f137",
|
||||
"chevron-circle-right": "f138",
|
||||
"chevron-circle-up": "f139",
|
||||
"chevron-down": "f078",
|
||||
"chevron-left": "f053",
|
||||
"chevron-right": "f054",
|
||||
"chevron-up": "f077",
|
||||
"child": "f1ae",
|
||||
"chrome": "f268",
|
||||
"circle": "f111",
|
||||
"circle-o": "f10c",
|
||||
"circle-o-notch": "f1ce",
|
||||
"circle-thin": "f1db",
|
||||
"clipboard": "f0ea",
|
||||
"clock-o": "f017",
|
||||
"clone": "f24d",
|
||||
"close": "f00d",
|
||||
"cloud": "f0c2",
|
||||
"cloud-download": "f0ed",
|
||||
"cloud-upload": "f0ee",
|
||||
"cny": "f157",
|
||||
"code": "f121",
|
||||
"code-fork": "f126",
|
||||
"codepen": "f1cb",
|
||||
"codiepie": "f284",
|
||||
"coffee": "f0f4",
|
||||
"cog": "f013",
|
||||
"cogs": "f085",
|
||||
"columns": "f0db",
|
||||
"comment": "f075",
|
||||
"comment-o": "f0e5",
|
||||
"commenting": "f27a",
|
||||
"commenting-o": "f27b",
|
||||
"comments": "f086",
|
||||
"comments-o": "f0e6",
|
||||
"compass": "f14e",
|
||||
"compress": "f066",
|
||||
"connectdevelop": "f20e",
|
||||
"contao": "f26d",
|
||||
"copy": "f0c5",
|
||||
"copyright": "f1f9",
|
||||
"creative-commons": "f25e",
|
||||
"credit-card": "f09d",
|
||||
"credit-card-alt": "f283",
|
||||
"crop": "f125",
|
||||
"crosshairs": "f05b",
|
||||
"css3": "f13c",
|
||||
"cube": "f1b2",
|
||||
"cubes": "f1b3",
|
||||
"cut": "f0c4",
|
||||
"cutlery": "f0f5",
|
||||
"dashboard": "f0e4",
|
||||
"dashcube": "f210",
|
||||
"database": "f1c0",
|
||||
"dedent": "f03b",
|
||||
"delicious": "f1a5",
|
||||
"desktop": "f108",
|
||||
"deviantart": "f1bd",
|
||||
"diamond": "f219",
|
||||
"digg": "f1a6",
|
||||
"dollar": "f155",
|
||||
"dot-circle-o": "f192",
|
||||
"download": "f019",
|
||||
"dribbble": "f17d",
|
||||
"dropbox": "f16b",
|
||||
"drupal": "f1a9",
|
||||
"edge": "f282",
|
||||
"edit": "f044",
|
||||
"eject": "f052",
|
||||
"ellipsis-h": "f141",
|
||||
"ellipsis-v": "f142",
|
||||
"empire": "f1d1",
|
||||
"envelope": "f0e0",
|
||||
"envelope-o": "f003",
|
||||
"envelope-square": "f199",
|
||||
"eraser": "f12d",
|
||||
"eur": "f153",
|
||||
"euro": "f153",
|
||||
"exchange": "f0ec",
|
||||
"exclamation": "f12a",
|
||||
"exclamation-circle": "f06a",
|
||||
"exclamation-triangle": "f071",
|
||||
"expand": "f065",
|
||||
"expeditedssl": "f23e",
|
||||
"external-link": "f08e",
|
||||
"external-link-square": "f14c",
|
||||
"eye": "f06e",
|
||||
"eye-slash": "f070",
|
||||
"eyedropper": "f1fb",
|
||||
"facebook": "f09a",
|
||||
"facebook-f": "f09a",
|
||||
"facebook-official": "f230",
|
||||
"facebook-square": "f082",
|
||||
"fast-backward": "f049",
|
||||
"fast-forward": "f050",
|
||||
"fax": "f1ac",
|
||||
"feed": "f09e",
|
||||
"female": "f182",
|
||||
"fighter-jet": "f0fb",
|
||||
"file": "f15b",
|
||||
"file-archive-o": "f1c6",
|
||||
"file-audio-o": "f1c7",
|
||||
"file-code-o": "f1c9",
|
||||
"file-excel-o": "f1c3",
|
||||
"file-image-o": "f1c5",
|
||||
"file-movie-o": "f1c8",
|
||||
"file-o": "f016",
|
||||
"file-pdf-o": "f1c1",
|
||||
"file-photo-o": "f1c5",
|
||||
"file-picture-o": "f1c5",
|
||||
"file-powerpoint-o": "f1c4",
|
||||
"file-sound-o": "f1c7",
|
||||
"file-text": "f15c",
|
||||
"file-text-o": "f0f6",
|
||||
"file-video-o": "f1c8",
|
||||
"file-word-o": "f1c2",
|
||||
"file-zip-o": "f1c6",
|
||||
"files-o": "f0c5",
|
||||
"film": "f008",
|
||||
"filter": "f0b0",
|
||||
"fire": "f06d",
|
||||
"fire-extinguisher": "f134",
|
||||
"firefox": "f269",
|
||||
"flag": "f024",
|
||||
"flag-checkered": "f11e",
|
||||
"flag-o": "f11d",
|
||||
"flash": "f0e7",
|
||||
"flask": "f0c3",
|
||||
"flickr": "f16e",
|
||||
"floppy-o": "f0c7",
|
||||
"folder": "f07b",
|
||||
"folder-o": "f114",
|
||||
"folder-open": "f07c",
|
||||
"folder-open-o": "f115",
|
||||
"font": "f031",
|
||||
"fonticons": "f280",
|
||||
"fort-awesome": "f286",
|
||||
"forumbee": "f211",
|
||||
"forward": "f04e",
|
||||
"foursquare": "f180",
|
||||
"frown-o": "f119",
|
||||
"futbol-o": "f1e3",
|
||||
"gamepad": "f11b",
|
||||
"gavel": "f0e3",
|
||||
"gbp": "f154",
|
||||
"ge": "f1d1",
|
||||
"gear": "f013",
|
||||
"gears": "f085",
|
||||
"genderless": "f22d",
|
||||
"get-pocket": "f265",
|
||||
"gg": "f260",
|
||||
"gg-circle": "f261",
|
||||
"gift": "f06b",
|
||||
"git": "f1d3",
|
||||
"git-square": "f1d2",
|
||||
"github": "f09b",
|
||||
"github-alt": "f113",
|
||||
"github-square": "f092",
|
||||
"gittip": "f184",
|
||||
"glass": "f000",
|
||||
"globe": "f0ac",
|
||||
"google": "f1a0",
|
||||
"google-plus": "f0d5",
|
||||
"google-plus-square": "f0d4",
|
||||
"google-wallet": "f1ee",
|
||||
"graduation-cap": "f19d",
|
||||
"gratipay": "f184",
|
||||
"group": "f0c0",
|
||||
"h-square": "f0fd",
|
||||
"hacker-news": "f1d4",
|
||||
"hand-grab-o": "f255",
|
||||
"hand-lizard-o": "f258",
|
||||
"hand-o-down": "f0a7",
|
||||
"hand-o-left": "f0a5",
|
||||
"hand-o-right": "f0a4",
|
||||
"hand-o-up": "f0a6",
|
||||
"hand-paper-o": "f256",
|
||||
"hand-peace-o": "f25b",
|
||||
"hand-pointer-o": "f25a",
|
||||
"hand-rock-o": "f255",
|
||||
"hand-scissors-o": "f257",
|
||||
"hand-spock-o": "f259",
|
||||
"hand-stop-o": "f256",
|
||||
"hashtag": "f292",
|
||||
"hdd-o": "f0a0",
|
||||
"header": "f1dc",
|
||||
"headphones": "f025",
|
||||
"heart": "f004",
|
||||
"heart-o": "f08a",
|
||||
"heartbeat": "f21e",
|
||||
"history": "f1da",
|
||||
"home": "f015",
|
||||
"hospital-o": "f0f8",
|
||||
"hotel": "f236",
|
||||
"hourglass": "f254",
|
||||
"hourglass-1": "f251",
|
||||
"hourglass-2": "f252",
|
||||
"hourglass-3": "f253",
|
||||
"hourglass-end": "f253",
|
||||
"hourglass-half": "f252",
|
||||
"hourglass-o": "f250",
|
||||
"hourglass-start": "f251",
|
||||
"houzz": "f27c",
|
||||
"html5": "f13b",
|
||||
"i-cursor": "f246",
|
||||
"ils": "f20b",
|
||||
"image": "f03e",
|
||||
"inbox": "f01c",
|
||||
"indent": "f03c",
|
||||
"industry": "f275",
|
||||
"info": "f129",
|
||||
"info-circle": "f05a",
|
||||
"inr": "f156",
|
||||
"instagram": "f16d",
|
||||
"institution": "f19c",
|
||||
"internet-explorer": "f26b",
|
||||
"intersex": "f224",
|
||||
"ioxhost": "f208",
|
||||
"italic": "f033",
|
||||
"joomla": "f1aa",
|
||||
"jpy": "f157",
|
||||
"jsfiddle": "f1cc",
|
||||
"key": "f084",
|
||||
"keyboard-o": "f11c",
|
||||
"krw": "f159",
|
||||
"language": "f1ab",
|
||||
"laptop": "f109",
|
||||
"lastfm": "f202",
|
||||
"lastfm-square": "f203",
|
||||
"leaf": "f06c",
|
||||
"leanpub": "f212",
|
||||
"legal": "f0e3",
|
||||
"lemon-o": "f094",
|
||||
"level-down": "f149",
|
||||
"level-up": "f148",
|
||||
"life-bouy": "f1cd",
|
||||
"life-buoy": "f1cd",
|
||||
"life-ring": "f1cd",
|
||||
"life-saver": "f1cd",
|
||||
"lightbulb-o": "f0eb",
|
||||
"line-chart": "f201",
|
||||
"link": "f0c1",
|
||||
"linkedin": "f0e1",
|
||||
"linkedin-square": "f08c",
|
||||
"linux": "f17c",
|
||||
"list": "f03a",
|
||||
"list-alt": "f022",
|
||||
"list-ol": "f0cb",
|
||||
"list-ul": "f0ca",
|
||||
"location-arrow": "f124",
|
||||
"lock": "f023",
|
||||
"long-arrow-down": "f175",
|
||||
"long-arrow-left": "f177",
|
||||
"long-arrow-right": "f178",
|
||||
"long-arrow-up": "f176",
|
||||
"magic": "f0d0",
|
||||
"magnet": "f076",
|
||||
"mail-forward": "f064",
|
||||
"mail-reply": "f112",
|
||||
"mail-reply-all": "f122",
|
||||
"male": "f183",
|
||||
"map": "f279",
|
||||
"map-marker": "f041",
|
||||
"map-o": "f278",
|
||||
"map-pin": "f276",
|
||||
"map-signs": "f277",
|
||||
"mars": "f222",
|
||||
"mars-double": "f227",
|
||||
"mars-stroke": "f229",
|
||||
"mars-stroke-h": "f22b",
|
||||
"mars-stroke-v": "f22a",
|
||||
"maxcdn": "f136",
|
||||
"meanpath": "f20c",
|
||||
"medium": "f23a",
|
||||
"medkit": "f0fa",
|
||||
"meh-o": "f11a",
|
||||
"mercury": "f223",
|
||||
"microphone": "f130",
|
||||
"microphone-slash": "f131",
|
||||
"minus": "f068",
|
||||
"minus-circle": "f056",
|
||||
"minus-square": "f146",
|
||||
"minus-square-o": "f147",
|
||||
"mixcloud": "f289",
|
||||
"mobile": "f10b",
|
||||
"mobile-phone": "f10b",
|
||||
"modx": "f285",
|
||||
"money": "f0d6",
|
||||
"moon-o": "f186",
|
||||
"mortar-board": "f19d",
|
||||
"motorcycle": "f21c",
|
||||
"mouse-pointer": "f245",
|
||||
"music": "f001",
|
||||
"navicon": "f0c9",
|
||||
"neuter": "f22c",
|
||||
"newspaper-o": "f1ea",
|
||||
"object-group": "f247",
|
||||
"object-ungroup": "f248",
|
||||
"odnoklassniki": "f263",
|
||||
"odnoklassniki-square": "f264",
|
||||
"opencart": "f23d",
|
||||
"openid": "f19b",
|
||||
"opera": "f26a",
|
||||
"optin-monster": "f23c",
|
||||
"outdent": "f03b",
|
||||
"pagelines": "f18c",
|
||||
"paint-brush": "f1fc",
|
||||
"paper-plane": "f1d8",
|
||||
"paper-plane-o": "f1d9",
|
||||
"paperclip": "f0c6",
|
||||
"paragraph": "f1dd",
|
||||
"paste": "f0ea",
|
||||
"pause": "f04c",
|
||||
"pause-circle": "f28b",
|
||||
"pause-circle-o": "f28c",
|
||||
"paw": "f1b0",
|
||||
"paypal": "f1ed",
|
||||
"pencil": "f040",
|
||||
"pencil-square": "f14b",
|
||||
"pencil-square-o": "f044",
|
||||
"percent": "f295",
|
||||
"phone": "f095",
|
||||
"phone-square": "f098",
|
||||
"photo": "f03e",
|
||||
"picture-o": "f03e",
|
||||
"pie-chart": "f200",
|
||||
"pied-piper": "f1a7",
|
||||
"pied-piper-alt": "f1a8",
|
||||
"pinterest": "f0d2",
|
||||
"pinterest-p": "f231",
|
||||
"pinterest-square": "f0d3",
|
||||
"plane": "f072",
|
||||
"play": "f04b",
|
||||
"play-circle": "f144",
|
||||
"play-circle-o": "f01d",
|
||||
"plug": "f1e6",
|
||||
"plus": "f067",
|
||||
"plus-circle": "f055",
|
||||
"plus-square": "f0fe",
|
||||
"plus-square-o": "f196",
|
||||
"power-off": "f011",
|
||||
"print": "f02f",
|
||||
"product-hunt": "f288",
|
||||
"puzzle-piece": "f12e",
|
||||
"qq": "f1d6",
|
||||
"qrcode": "f029",
|
||||
"question": "f128",
|
||||
"question-circle": "f059",
|
||||
"quote-left": "f10d",
|
||||
"quote-right": "f10e",
|
||||
"ra": "f1d0",
|
||||
"random": "f074",
|
||||
"rebel": "f1d0",
|
||||
"recycle": "f1b8",
|
||||
"reddit": "f1a1",
|
||||
"reddit-alien": "f281",
|
||||
"reddit-square": "f1a2",
|
||||
"refresh": "f021",
|
||||
"registered": "f25d",
|
||||
"remove": "f00d",
|
||||
"renren": "f18b",
|
||||
"reorder": "f0c9",
|
||||
"repeat": "f01e",
|
||||
"reply": "f112",
|
||||
"reply-all": "f122",
|
||||
"retweet": "f079",
|
||||
"rmb": "f157",
|
||||
"road": "f018",
|
||||
"rocket": "f135",
|
||||
"rotate-left": "f0e2",
|
||||
"rotate-right": "f01e",
|
||||
"rouble": "f158",
|
||||
"rss": "f09e",
|
||||
"rss-square": "f143",
|
||||
"rub": "f158",
|
||||
"ruble": "f158",
|
||||
"rupee": "f156",
|
||||
"safari": "f267",
|
||||
"save": "f0c7",
|
||||
"scissors": "f0c4",
|
||||
"scribd": "f28a",
|
||||
"search": "f002",
|
||||
"search-minus": "f010",
|
||||
"search-plus": "f00e",
|
||||
"sellsy": "f213",
|
||||
"send": "f1d8",
|
||||
"send-o": "f1d9",
|
||||
"server": "f233",
|
||||
"share": "f064",
|
||||
"share-alt": "f1e0",
|
||||
"share-alt-square": "f1e1",
|
||||
"share-square": "f14d",
|
||||
"share-square-o": "f045",
|
||||
"shekel": "f20b",
|
||||
"sheqel": "f20b",
|
||||
"shield": "f132",
|
||||
"ship": "f21a",
|
||||
"shirtsinbulk": "f214",
|
||||
"shopping-bag": "f290",
|
||||
"shopping-basket": "f291",
|
||||
"shopping-cart": "f07a",
|
||||
"sign-in": "f090",
|
||||
"sign-out": "f08b",
|
||||
"signal": "f012",
|
||||
"simplybuilt": "f215",
|
||||
"sitemap": "f0e8",
|
||||
"skyatlas": "f216",
|
||||
"skype": "f17e",
|
||||
"slack": "f198",
|
||||
"sliders": "f1de",
|
||||
"slideshare": "f1e7",
|
||||
"smile-o": "f118",
|
||||
"soccer-ball-o": "f1e3",
|
||||
"sort": "f0dc",
|
||||
"sort-alpha-asc": "f15d",
|
||||
"sort-alpha-desc": "f15e",
|
||||
"sort-amount-asc": "f160",
|
||||
"sort-amount-desc": "f161",
|
||||
"sort-asc": "f0de",
|
||||
"sort-desc": "f0dd",
|
||||
"sort-down": "f0dd",
|
||||
"sort-numeric-asc": "f162",
|
||||
"sort-numeric-desc": "f163",
|
||||
"sort-up": "f0de",
|
||||
"soundcloud": "f1be",
|
||||
"space-shuttle": "f197",
|
||||
"spinner": "f110",
|
||||
"spoon": "f1b1",
|
||||
"spotify": "f1bc",
|
||||
"square": "f0c8",
|
||||
"square-o": "f096",
|
||||
"stack-exchange": "f18d",
|
||||
"stack-overflow": "f16c",
|
||||
"star": "f005",
|
||||
"star-half": "f089",
|
||||
"star-half-empty": "f123",
|
||||
"star-half-full": "f123",
|
||||
"star-half-o": "f123",
|
||||
"star-o": "f006",
|
||||
"steam": "f1b6",
|
||||
"steam-square": "f1b7",
|
||||
"step-backward": "f048",
|
||||
"step-forward": "f051",
|
||||
"stethoscope": "f0f1",
|
||||
"sticky-note": "f249",
|
||||
"sticky-note-o": "f24a",
|
||||
"stop": "f04d",
|
||||
"stop-circle": "f28d",
|
||||
"stop-circle-o": "f28e",
|
||||
"street-view": "f21d",
|
||||
"strikethrough": "f0cc",
|
||||
"stumbleupon": "f1a4",
|
||||
"stumbleupon-circle": "f1a3",
|
||||
"subscript": "f12c",
|
||||
"subway": "f239",
|
||||
"suitcase": "f0f2",
|
||||
"sun-o": "f185",
|
||||
"superscript": "f12b",
|
||||
"support": "f1cd",
|
||||
"table": "f0ce",
|
||||
"tablet": "f10a",
|
||||
"tachometer": "f0e4",
|
||||
"tag": "f02b",
|
||||
"tags": "f02c",
|
||||
"tasks": "f0ae",
|
||||
"taxi": "f1ba",
|
||||
"television": "f26c",
|
||||
"tencent-weibo": "f1d5",
|
||||
"terminal": "f120",
|
||||
"text-height": "f034",
|
||||
"text-width": "f035",
|
||||
"th": "f00a",
|
||||
"th-large": "f009",
|
||||
"th-list": "f00b",
|
||||
"thumb-tack": "f08d",
|
||||
"thumbs-down": "f165",
|
||||
"thumbs-o-down": "f088",
|
||||
"thumbs-o-up": "f087",
|
||||
"thumbs-up": "f164",
|
||||
"ticket": "f145",
|
||||
"times": "f00d",
|
||||
"times-circle": "f057",
|
||||
"times-circle-o": "f05c",
|
||||
"tint": "f043",
|
||||
"toggle-down": "f150",
|
||||
"toggle-left": "f191",
|
||||
"toggle-off": "f204",
|
||||
"toggle-on": "f205",
|
||||
"toggle-right": "f152",
|
||||
"toggle-up": "f151",
|
||||
"trademark": "f25c",
|
||||
"train": "f238",
|
||||
"transgender": "f224",
|
||||
"transgender-alt": "f225",
|
||||
"trash": "f1f8",
|
||||
"trash-o": "f014",
|
||||
"tree": "f1bb",
|
||||
"trello": "f181",
|
||||
"tripadvisor": "f262",
|
||||
"trophy": "f091",
|
||||
"truck": "f0d1",
|
||||
"try": "f195",
|
||||
"tty": "f1e4",
|
||||
"tumblr": "f173",
|
||||
"tumblr-square": "f174",
|
||||
"turkish-lira": "f195",
|
||||
"tv": "f26c",
|
||||
"twitch": "f1e8",
|
||||
"twitter": "f099",
|
||||
"twitter-square": "f081",
|
||||
"umbrella": "f0e9",
|
||||
"underline": "f0cd",
|
||||
"undo": "f0e2",
|
||||
"university": "f19c",
|
||||
"unlink": "f127",
|
||||
"unlock": "f09c",
|
||||
"unlock-alt": "f13e",
|
||||
"unsorted": "f0dc",
|
||||
"upload": "f093",
|
||||
"usb": "f287",
|
||||
"usd": "f155",
|
||||
"user": "f007",
|
||||
"user-md": "f0f0",
|
||||
"user-plus": "f234",
|
||||
"user-secret": "f21b",
|
||||
"user-times": "f235",
|
||||
"users": "f0c0",
|
||||
"venus": "f221",
|
||||
"venus-double": "f226",
|
||||
"venus-mars": "f228",
|
||||
"viacoin": "f237",
|
||||
"video-camera": "f03d",
|
||||
"vimeo": "f27d",
|
||||
"vimeo-square": "f194",
|
||||
"vine": "f1ca",
|
||||
"vk": "f189",
|
||||
"volume-down": "f027",
|
||||
"volume-off": "f026",
|
||||
"volume-up": "f028",
|
||||
"warning": "f071",
|
||||
"wechat": "f1d7",
|
||||
"weibo": "f18a",
|
||||
"weixin": "f1d7",
|
||||
"whatsapp": "f232",
|
||||
"wheelchair": "f193",
|
||||
"wifi": "f1eb",
|
||||
"wikipedia-w": "f266",
|
||||
"windows": "f17a",
|
||||
"won": "f159",
|
||||
"wordpress": "f19a",
|
||||
"wrench": "f0ad",
|
||||
"xing": "f168",
|
||||
"xing-square": "f169",
|
||||
"y-combinator": "f23b",
|
||||
"y-combinator-square": "f1d4",
|
||||
"yahoo": "f19e",
|
||||
"yc": "f23b",
|
||||
"yc-square": "f1d4",
|
||||
"yelp": "f1e9",
|
||||
"yen": "f157",
|
||||
"youtube": "f167",
|
||||
"youtube-play": "f16a",
|
||||
"youtube-square": "f166"
|
||||
}
|
||||
BIN
pype/tools/pyblish_pype/vendor/qtawesome/fonts/fontawesome-webfont.ttf
vendored
Normal file
BIN
pype/tools/pyblish_pype/vendor/qtawesome/fonts/fontawesome-webfont.ttf
vendored
Normal file
Binary file not shown.
287
pype/tools/pyblish_pype/vendor/qtawesome/iconic_font.py
vendored
Normal file
287
pype/tools/pyblish_pype/vendor/qtawesome/iconic_font.py
vendored
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
"""Classes handling iconic fonts"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from .. import six
|
||||
from ..Qt import QtCore, QtGui
|
||||
|
||||
|
||||
_default_options = {
|
||||
'color': QtGui.QColor(50, 50, 50),
|
||||
'color_disabled': QtGui.QColor(150, 150, 150),
|
||||
'opacity': 1.0,
|
||||
'scale_factor': 1.0,
|
||||
}
|
||||
|
||||
|
||||
def set_global_defaults(**kwargs):
|
||||
"""Set global defaults for all icons"""
|
||||
valid_options = ['active', 'animation', 'color', 'color_active',
|
||||
'color_disabled', 'color_selected', 'disabled', 'offset',
|
||||
'scale_factor', 'selected']
|
||||
for kw in kwargs:
|
||||
if kw in valid_options:
|
||||
_default_options[kw] = kwargs[kw]
|
||||
else:
|
||||
error = "Invalid option '{0}'".format(kw)
|
||||
raise KeyError(error)
|
||||
|
||||
|
||||
class CharIconPainter:
|
||||
|
||||
"""Char icon painter"""
|
||||
|
||||
def paint(self, iconic, painter, rect, mode, state, options):
|
||||
"""Main paint method"""
|
||||
for opt in options:
|
||||
self._paint_icon(iconic, painter, rect, mode, state, opt)
|
||||
|
||||
def _paint_icon(self, iconic, painter, rect, mode, state, options):
|
||||
"""Paint a single icon"""
|
||||
painter.save()
|
||||
color, char = options['color'], options['char']
|
||||
|
||||
if mode == QtGui.QIcon.Disabled:
|
||||
color = options.get('color_disabled', color)
|
||||
char = options.get('disabled', char)
|
||||
elif mode == QtGui.QIcon.Active:
|
||||
color = options.get('color_active', color)
|
||||
char = options.get('active', char)
|
||||
elif mode == QtGui.QIcon.Selected:
|
||||
color = options.get('color_selected', color)
|
||||
char = options.get('selected', char)
|
||||
|
||||
painter.setPen(QtGui.QColor(color))
|
||||
# A 16 pixel-high icon yields a font size of 14, which is pixel perfect
|
||||
# for font-awesome. 16 * 0.875 = 14
|
||||
# The reason for not using full-sized glyphs is the negative bearing of
|
||||
# fonts.
|
||||
draw_size = 0.875 * round(rect.height() * options['scale_factor'])
|
||||
prefix = options['prefix']
|
||||
|
||||
# Animation setup hook
|
||||
animation = options.get('animation')
|
||||
if animation is not None:
|
||||
animation.setup(self, painter, rect)
|
||||
|
||||
painter.setFont(iconic.font(prefix, draw_size))
|
||||
if 'offset' in options:
|
||||
rect = QtCore.QRect(rect)
|
||||
rect.translate(options['offset'][0] * rect.width(),
|
||||
options['offset'][1] * rect.height())
|
||||
|
||||
painter.setOpacity(options.get('opacity', 1.0))
|
||||
|
||||
painter.drawText(rect,
|
||||
QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter,
|
||||
char)
|
||||
painter.restore()
|
||||
|
||||
|
||||
class CharIconEngine(QtGui.QIconEngine):
|
||||
|
||||
"""Specialization of QtGui.QIconEngine used to draw font-based icons"""
|
||||
|
||||
def __init__(self, iconic, painter, options):
|
||||
super(CharIconEngine, self).__init__()
|
||||
self.iconic = iconic
|
||||
self.painter = painter
|
||||
self.options = options
|
||||
|
||||
def paint(self, painter, rect, mode, state):
|
||||
self.painter.paint(
|
||||
self.iconic, painter, rect, mode, state, self.options)
|
||||
|
||||
def pixmap(self, size, mode, state):
|
||||
pm = QtGui.QPixmap(size)
|
||||
pm.fill(QtCore.Qt.transparent)
|
||||
self.paint(QtGui.QPainter(pm),
|
||||
QtCore.QRect(QtCore.QPoint(0, 0), size),
|
||||
mode,
|
||||
state)
|
||||
return pm
|
||||
|
||||
|
||||
class IconicFont(QtCore.QObject):
|
||||
|
||||
"""Main class for managing iconic fonts"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""Constructor
|
||||
|
||||
:param *args: tuples
|
||||
Each positional argument is a tuple of 3 or 4 values
|
||||
- The prefix string to be used when accessing a given font set
|
||||
- The ttf font filename
|
||||
- The json charmap filename
|
||||
- Optionally, the directory containing these files. When not
|
||||
provided, the files will be looked up in ./fonts/
|
||||
"""
|
||||
super(IconicFont, self).__init__()
|
||||
self.painter = CharIconPainter()
|
||||
self.painters = {}
|
||||
self.fontname = {}
|
||||
self.charmap = {}
|
||||
for fargs in args:
|
||||
self.load_font(*fargs)
|
||||
|
||||
def load_font(self,
|
||||
prefix,
|
||||
ttf_filename,
|
||||
charmap_filename,
|
||||
directory=None):
|
||||
"""Loads a font file and the associated charmap
|
||||
|
||||
If `directory` is None, the files will be looked up in ./fonts/
|
||||
|
||||
Arguments
|
||||
---------
|
||||
prefix: str
|
||||
prefix string to be used when accessing a given font set
|
||||
ttf_filename: str
|
||||
ttf font filename
|
||||
charmap_filename: str
|
||||
charmap filename
|
||||
directory: str or None, optional
|
||||
directory for font and charmap files
|
||||
"""
|
||||
|
||||
def hook(obj):
|
||||
result = {}
|
||||
for key in obj:
|
||||
result[key] = six.unichr(int(obj[key], 16))
|
||||
return result
|
||||
|
||||
if directory is None:
|
||||
directory = os.path.join(
|
||||
os.path.dirname(os.path.realpath(__file__)), 'fonts')
|
||||
|
||||
with open(os.path.join(directory, charmap_filename), 'r') as codes:
|
||||
self.charmap[prefix] = json.load(codes, object_hook=hook)
|
||||
|
||||
id_ = QtGui.QFontDatabase.addApplicationFont(
|
||||
os.path.join(directory, ttf_filename))
|
||||
|
||||
loadedFontFamilies = QtGui.QFontDatabase.applicationFontFamilies(id_)
|
||||
|
||||
if(loadedFontFamilies):
|
||||
self.fontname[prefix] = loadedFontFamilies[0]
|
||||
else:
|
||||
print('Font is empty')
|
||||
|
||||
def icon(self, *names, **kwargs):
|
||||
"""Returns a QtGui.QIcon object corresponding to the provided icon name
|
||||
(including prefix)
|
||||
|
||||
Arguments
|
||||
---------
|
||||
names: list of str
|
||||
icon name, of the form PREFIX.NAME
|
||||
|
||||
options: dict
|
||||
options to be passed to the icon painter
|
||||
"""
|
||||
options_list = kwargs.pop('options', [{}] * len(names))
|
||||
general_options = kwargs
|
||||
|
||||
if len(options_list) != len(names):
|
||||
error = '"options" must be a list of size {0}'.format(len(names))
|
||||
raise Exception(error)
|
||||
|
||||
parsed_options = []
|
||||
for i in range(len(options_list)):
|
||||
specific_options = options_list[i]
|
||||
parsed_options.append(self._parse_options(specific_options,
|
||||
general_options,
|
||||
names[i]))
|
||||
|
||||
# Process high level API
|
||||
api_options = parsed_options
|
||||
|
||||
return self._icon_by_painter(self.painter, api_options)
|
||||
|
||||
def _parse_options(self, specific_options, general_options, name):
|
||||
""" """
|
||||
options = dict(_default_options, **general_options)
|
||||
options.update(specific_options)
|
||||
|
||||
# Handle icons for states
|
||||
icon_kw = ['disabled', 'active', 'selected', 'char']
|
||||
names = [options.get(kw, name) for kw in icon_kw]
|
||||
prefix, chars = self._get_prefix_chars(names)
|
||||
options.update(dict(zip(*(icon_kw, chars))))
|
||||
options.update({'prefix': prefix})
|
||||
|
||||
# Handle colors for states
|
||||
color_kw = ['color_active', 'color_selected']
|
||||
colors = [options.get(kw, options['color']) for kw in color_kw]
|
||||
options.update(dict(zip(*(color_kw, colors))))
|
||||
|
||||
return options
|
||||
|
||||
def _get_prefix_chars(self, names):
|
||||
""" """
|
||||
chars = []
|
||||
for name in names:
|
||||
if '.' in name:
|
||||
prefix, n = name.split('.')
|
||||
if prefix in self.charmap:
|
||||
if n in self.charmap[prefix]:
|
||||
chars.append(self.charmap[prefix][n])
|
||||
else:
|
||||
error = 'Invalid icon name "{0}" in font "{1}"'.format(
|
||||
n, prefix)
|
||||
raise Exception(error)
|
||||
else:
|
||||
error = 'Invalid font prefix "{0}"'.format(prefix)
|
||||
raise Exception(error)
|
||||
else:
|
||||
raise Exception('Invalid icon name')
|
||||
|
||||
return prefix, chars
|
||||
|
||||
def font(self, prefix, size):
|
||||
"""Returns QtGui.QFont corresponding to the given prefix and size
|
||||
|
||||
Arguments
|
||||
---------
|
||||
prefix: str
|
||||
prefix string of the loaded font
|
||||
size: int
|
||||
size for the font
|
||||
"""
|
||||
font = QtGui.QFont(self.fontname[prefix])
|
||||
font.setPixelSize(size)
|
||||
return font
|
||||
|
||||
def set_custom_icon(self, name, painter):
|
||||
"""Associates a user-provided CharIconPainter to an icon name
|
||||
The custom icon can later be addressed by calling
|
||||
icon('custom.NAME') where NAME is the provided name for that icon.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
name: str
|
||||
name of the custom icon
|
||||
painter: CharIconPainter
|
||||
The icon painter, implementing
|
||||
`paint(self, iconic, painter, rect, mode, state, options)`
|
||||
"""
|
||||
self.painters[name] = painter
|
||||
|
||||
def _custom_icon(self, name, **kwargs):
|
||||
"""Returns the custom icon corresponding to the given name"""
|
||||
options = dict(_default_options, **kwargs)
|
||||
if name in self.painters:
|
||||
painter = self.painters[name]
|
||||
return self._icon_by_painter(painter, options)
|
||||
else:
|
||||
return QtGui.QIcon()
|
||||
|
||||
def _icon_by_painter(self, painter, options):
|
||||
"""Returns the icon corresponding to the given painter"""
|
||||
engine = CharIconEngine(self, painter, options)
|
||||
return QtGui.QIcon(engine)
|
||||
868
pype/tools/pyblish_pype/vendor/six.py
vendored
Normal file
868
pype/tools/pyblish_pype/vendor/six.py
vendored
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
"""Utilities for writing code that runs on Python 2 and 3"""
|
||||
|
||||
# Copyright (c) 2010-2015 Benjamin Peterson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import functools
|
||||
import itertools
|
||||
import operator
|
||||
import sys
|
||||
import types
|
||||
|
||||
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
||||
__version__ = "1.10.0"
|
||||
|
||||
|
||||
# Useful for very coarse version differentiation.
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY3 = sys.version_info[0] == 3
|
||||
PY34 = sys.version_info[0:2] >= (3, 4)
|
||||
|
||||
if PY3:
|
||||
string_types = str,
|
||||
integer_types = int,
|
||||
class_types = type,
|
||||
text_type = str
|
||||
binary_type = bytes
|
||||
|
||||
MAXSIZE = sys.maxsize
|
||||
else:
|
||||
string_types = basestring,
|
||||
integer_types = (int, long)
|
||||
class_types = (type, types.ClassType)
|
||||
text_type = unicode
|
||||
binary_type = str
|
||||
|
||||
if sys.platform.startswith("java"):
|
||||
# Jython always uses 32 bits.
|
||||
MAXSIZE = int((1 << 31) - 1)
|
||||
else:
|
||||
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
||||
class X(object):
|
||||
|
||||
def __len__(self):
|
||||
return 1 << 31
|
||||
try:
|
||||
len(X())
|
||||
except OverflowError:
|
||||
# 32-bit
|
||||
MAXSIZE = int((1 << 31) - 1)
|
||||
else:
|
||||
# 64-bit
|
||||
MAXSIZE = int((1 << 63) - 1)
|
||||
del X
|
||||
|
||||
|
||||
def _add_doc(func, doc):
|
||||
"""Add documentation to a function."""
|
||||
func.__doc__ = doc
|
||||
|
||||
|
||||
def _import_module(name):
|
||||
"""Import module, returning the module after the last dot."""
|
||||
__import__(name)
|
||||
return sys.modules[name]
|
||||
|
||||
|
||||
class _LazyDescr(object):
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj, tp):
|
||||
result = self._resolve()
|
||||
setattr(obj, self.name, result) # Invokes __set__.
|
||||
try:
|
||||
# This is a bit ugly, but it avoids running this again by
|
||||
# removing this descriptor.
|
||||
delattr(obj.__class__, self.name)
|
||||
except AttributeError:
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
class MovedModule(_LazyDescr):
|
||||
|
||||
def __init__(self, name, old, new=None):
|
||||
super(MovedModule, self).__init__(name)
|
||||
if PY3:
|
||||
if new is None:
|
||||
new = name
|
||||
self.mod = new
|
||||
else:
|
||||
self.mod = old
|
||||
|
||||
def _resolve(self):
|
||||
return _import_module(self.mod)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
_module = self._resolve()
|
||||
value = getattr(_module, attr)
|
||||
setattr(self, attr, value)
|
||||
return value
|
||||
|
||||
|
||||
class _LazyModule(types.ModuleType):
|
||||
|
||||
def __init__(self, name):
|
||||
super(_LazyModule, self).__init__(name)
|
||||
self.__doc__ = self.__class__.__doc__
|
||||
|
||||
def __dir__(self):
|
||||
attrs = ["__doc__", "__name__"]
|
||||
attrs += [attr.name for attr in self._moved_attributes]
|
||||
return attrs
|
||||
|
||||
# Subclasses should override this
|
||||
_moved_attributes = []
|
||||
|
||||
|
||||
class MovedAttribute(_LazyDescr):
|
||||
|
||||
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
||||
super(MovedAttribute, self).__init__(name)
|
||||
if PY3:
|
||||
if new_mod is None:
|
||||
new_mod = name
|
||||
self.mod = new_mod
|
||||
if new_attr is None:
|
||||
if old_attr is None:
|
||||
new_attr = name
|
||||
else:
|
||||
new_attr = old_attr
|
||||
self.attr = new_attr
|
||||
else:
|
||||
self.mod = old_mod
|
||||
if old_attr is None:
|
||||
old_attr = name
|
||||
self.attr = old_attr
|
||||
|
||||
def _resolve(self):
|
||||
module = _import_module(self.mod)
|
||||
return getattr(module, self.attr)
|
||||
|
||||
|
||||
class _SixMetaPathImporter(object):
|
||||
|
||||
"""
|
||||
A meta path importer to import six.moves and its submodules.
|
||||
|
||||
This class implements a PEP302 finder and loader. It should be compatible
|
||||
with Python 2.5 and all existing versions of Python3
|
||||
"""
|
||||
|
||||
def __init__(self, six_module_name):
|
||||
self.name = six_module_name
|
||||
self.known_modules = {}
|
||||
|
||||
def _add_module(self, mod, *fullnames):
|
||||
for fullname in fullnames:
|
||||
self.known_modules[self.name + "." + fullname] = mod
|
||||
|
||||
def _get_module(self, fullname):
|
||||
return self.known_modules[self.name + "." + fullname]
|
||||
|
||||
def find_module(self, fullname, path=None):
|
||||
if fullname in self.known_modules:
|
||||
return self
|
||||
return None
|
||||
|
||||
def __get_module(self, fullname):
|
||||
try:
|
||||
return self.known_modules[fullname]
|
||||
except KeyError:
|
||||
raise ImportError("This loader does not know module " + fullname)
|
||||
|
||||
def load_module(self, fullname):
|
||||
try:
|
||||
# in case of a reload
|
||||
return sys.modules[fullname]
|
||||
except KeyError:
|
||||
pass
|
||||
mod = self.__get_module(fullname)
|
||||
if isinstance(mod, MovedModule):
|
||||
mod = mod._resolve()
|
||||
else:
|
||||
mod.__loader__ = self
|
||||
sys.modules[fullname] = mod
|
||||
return mod
|
||||
|
||||
def is_package(self, fullname):
|
||||
"""
|
||||
Return true, if the named module is a package.
|
||||
|
||||
We need this method to get correct spec objects with
|
||||
Python 3.4 (see PEP451)
|
||||
"""
|
||||
return hasattr(self.__get_module(fullname), "__path__")
|
||||
|
||||
def get_code(self, fullname):
|
||||
"""Return None
|
||||
|
||||
Required, if is_package is implemented"""
|
||||
self.__get_module(fullname) # eventually raises ImportError
|
||||
return None
|
||||
get_source = get_code # same as get_code
|
||||
|
||||
_importer = _SixMetaPathImporter(__name__)
|
||||
|
||||
|
||||
class _MovedItems(_LazyModule):
|
||||
|
||||
"""Lazy loading of moved objects"""
|
||||
__path__ = [] # mark as package
|
||||
|
||||
|
||||
_moved_attributes = [
|
||||
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
|
||||
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
|
||||
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
|
||||
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
|
||||
MovedAttribute("intern", "__builtin__", "sys"),
|
||||
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
|
||||
MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
|
||||
MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
|
||||
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
|
||||
MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
|
||||
MovedAttribute("reduce", "__builtin__", "functools"),
|
||||
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
|
||||
MovedAttribute("StringIO", "StringIO", "io"),
|
||||
MovedAttribute("UserDict", "UserDict", "collections"),
|
||||
MovedAttribute("UserList", "UserList", "collections"),
|
||||
MovedAttribute("UserString", "UserString", "collections"),
|
||||
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
|
||||
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
|
||||
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
|
||||
MovedModule("builtins", "__builtin__"),
|
||||
MovedModule("configparser", "ConfigParser"),
|
||||
MovedModule("copyreg", "copy_reg"),
|
||||
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
|
||||
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
|
||||
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
|
||||
MovedModule("http_cookies", "Cookie", "http.cookies"),
|
||||
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
|
||||
MovedModule("html_parser", "HTMLParser", "html.parser"),
|
||||
MovedModule("http_client", "httplib", "http.client"),
|
||||
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
|
||||
MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
|
||||
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
|
||||
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
|
||||
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
|
||||
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
|
||||
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
|
||||
MovedModule("cPickle", "cPickle", "pickle"),
|
||||
MovedModule("queue", "Queue"),
|
||||
MovedModule("reprlib", "repr"),
|
||||
MovedModule("socketserver", "SocketServer"),
|
||||
MovedModule("_thread", "thread", "_thread"),
|
||||
MovedModule("tkinter", "Tkinter"),
|
||||
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
|
||||
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
|
||||
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
|
||||
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
|
||||
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
|
||||
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
|
||||
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
|
||||
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
|
||||
MovedModule("tkinter_colorchooser", "tkColorChooser",
|
||||
"tkinter.colorchooser"),
|
||||
MovedModule("tkinter_commondialog", "tkCommonDialog",
|
||||
"tkinter.commondialog"),
|
||||
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
|
||||
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
|
||||
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
||||
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
|
||||
"tkinter.simpledialog"),
|
||||
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
|
||||
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
|
||||
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
|
||||
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
||||
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
|
||||
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
|
||||
]
|
||||
# Add windows specific modules.
|
||||
if sys.platform == "win32":
|
||||
_moved_attributes += [
|
||||
MovedModule("winreg", "_winreg"),
|
||||
]
|
||||
|
||||
for attr in _moved_attributes:
|
||||
setattr(_MovedItems, attr.name, attr)
|
||||
if isinstance(attr, MovedModule):
|
||||
_importer._add_module(attr, "moves." + attr.name)
|
||||
del attr
|
||||
|
||||
_MovedItems._moved_attributes = _moved_attributes
|
||||
|
||||
moves = _MovedItems(__name__ + ".moves")
|
||||
_importer._add_module(moves, "moves")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_parse(_LazyModule):
|
||||
|
||||
"""Lazy loading of moved objects in six.moves.urllib_parse"""
|
||||
|
||||
|
||||
_urllib_parse_moved_attributes = [
|
||||
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("quote", "urllib", "urllib.parse"),
|
||||
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
|
||||
MovedAttribute("unquote", "urllib", "urllib.parse"),
|
||||
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
|
||||
MovedAttribute("urlencode", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splitquery", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splittag", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splituser", "urllib", "urllib.parse"),
|
||||
MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_params", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_query", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
|
||||
]
|
||||
for attr in _urllib_parse_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_parse, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
|
||||
"moves.urllib_parse", "moves.urllib.parse")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_error(_LazyModule):
|
||||
|
||||
"""Lazy loading of moved objects in six.moves.urllib_error"""
|
||||
|
||||
|
||||
_urllib_error_moved_attributes = [
|
||||
MovedAttribute("URLError", "urllib2", "urllib.error"),
|
||||
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
|
||||
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
|
||||
]
|
||||
for attr in _urllib_error_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_error, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
|
||||
"moves.urllib_error", "moves.urllib.error")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_request(_LazyModule):
|
||||
|
||||
"""Lazy loading of moved objects in six.moves.urllib_request"""
|
||||
|
||||
|
||||
_urllib_request_moved_attributes = [
|
||||
MovedAttribute("urlopen", "urllib2", "urllib.request"),
|
||||
MovedAttribute("install_opener", "urllib2", "urllib.request"),
|
||||
MovedAttribute("build_opener", "urllib2", "urllib.request"),
|
||||
MovedAttribute("pathname2url", "urllib", "urllib.request"),
|
||||
MovedAttribute("url2pathname", "urllib", "urllib.request"),
|
||||
MovedAttribute("getproxies", "urllib", "urllib.request"),
|
||||
MovedAttribute("Request", "urllib2", "urllib.request"),
|
||||
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
|
||||
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
|
||||
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
|
||||
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
|
||||
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
||||
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
|
||||
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
|
||||
]
|
||||
for attr in _urllib_request_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_request, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
|
||||
"moves.urllib_request", "moves.urllib.request")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_response(_LazyModule):
|
||||
|
||||
"""Lazy loading of moved objects in six.moves.urllib_response"""
|
||||
|
||||
|
||||
_urllib_response_moved_attributes = [
|
||||
MovedAttribute("addbase", "urllib", "urllib.response"),
|
||||
MovedAttribute("addclosehook", "urllib", "urllib.response"),
|
||||
MovedAttribute("addinfo", "urllib", "urllib.response"),
|
||||
MovedAttribute("addinfourl", "urllib", "urllib.response"),
|
||||
]
|
||||
for attr in _urllib_response_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_response, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
|
||||
"moves.urllib_response", "moves.urllib.response")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_robotparser(_LazyModule):
|
||||
|
||||
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
|
||||
|
||||
|
||||
_urllib_robotparser_moved_attributes = [
|
||||
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
|
||||
]
|
||||
for attr in _urllib_robotparser_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
|
||||
"moves.urllib_robotparser", "moves.urllib.robotparser")
|
||||
|
||||
|
||||
class Module_six_moves_urllib(types.ModuleType):
|
||||
|
||||
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
|
||||
__path__ = [] # mark as package
|
||||
parse = _importer._get_module("moves.urllib_parse")
|
||||
error = _importer._get_module("moves.urllib_error")
|
||||
request = _importer._get_module("moves.urllib_request")
|
||||
response = _importer._get_module("moves.urllib_response")
|
||||
robotparser = _importer._get_module("moves.urllib_robotparser")
|
||||
|
||||
def __dir__(self):
|
||||
return ['parse', 'error', 'request', 'response', 'robotparser']
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
|
||||
"moves.urllib")
|
||||
|
||||
|
||||
def add_move(move):
|
||||
"""Add an item to six.moves."""
|
||||
setattr(_MovedItems, move.name, move)
|
||||
|
||||
|
||||
def remove_move(name):
|
||||
"""Remove item from six.moves."""
|
||||
try:
|
||||
delattr(_MovedItems, name)
|
||||
except AttributeError:
|
||||
try:
|
||||
del moves.__dict__[name]
|
||||
except KeyError:
|
||||
raise AttributeError("no such move, %r" % (name,))
|
||||
|
||||
|
||||
if PY3:
|
||||
_meth_func = "__func__"
|
||||
_meth_self = "__self__"
|
||||
|
||||
_func_closure = "__closure__"
|
||||
_func_code = "__code__"
|
||||
_func_defaults = "__defaults__"
|
||||
_func_globals = "__globals__"
|
||||
else:
|
||||
_meth_func = "im_func"
|
||||
_meth_self = "im_self"
|
||||
|
||||
_func_closure = "func_closure"
|
||||
_func_code = "func_code"
|
||||
_func_defaults = "func_defaults"
|
||||
_func_globals = "func_globals"
|
||||
|
||||
|
||||
try:
|
||||
advance_iterator = next
|
||||
except NameError:
|
||||
def advance_iterator(it):
|
||||
return it.next()
|
||||
next = advance_iterator
|
||||
|
||||
|
||||
try:
|
||||
callable = callable
|
||||
except NameError:
|
||||
def callable(obj):
|
||||
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
||||
|
||||
|
||||
if PY3:
|
||||
def get_unbound_function(unbound):
|
||||
return unbound
|
||||
|
||||
create_bound_method = types.MethodType
|
||||
|
||||
def create_unbound_method(func, cls):
|
||||
return func
|
||||
|
||||
Iterator = object
|
||||
else:
|
||||
def get_unbound_function(unbound):
|
||||
return unbound.im_func
|
||||
|
||||
def create_bound_method(func, obj):
|
||||
return types.MethodType(func, obj, obj.__class__)
|
||||
|
||||
def create_unbound_method(func, cls):
|
||||
return types.MethodType(func, None, cls)
|
||||
|
||||
class Iterator(object):
|
||||
|
||||
def next(self):
|
||||
return type(self).__next__(self)
|
||||
|
||||
callable = callable
|
||||
_add_doc(get_unbound_function,
|
||||
"""Get the function out of a possibly unbound function""")
|
||||
|
||||
|
||||
get_method_function = operator.attrgetter(_meth_func)
|
||||
get_method_self = operator.attrgetter(_meth_self)
|
||||
get_function_closure = operator.attrgetter(_func_closure)
|
||||
get_function_code = operator.attrgetter(_func_code)
|
||||
get_function_defaults = operator.attrgetter(_func_defaults)
|
||||
get_function_globals = operator.attrgetter(_func_globals)
|
||||
|
||||
|
||||
if PY3:
|
||||
def iterkeys(d, **kw):
|
||||
return iter(d.keys(**kw))
|
||||
|
||||
def itervalues(d, **kw):
|
||||
return iter(d.values(**kw))
|
||||
|
||||
def iteritems(d, **kw):
|
||||
return iter(d.items(**kw))
|
||||
|
||||
def iterlists(d, **kw):
|
||||
return iter(d.lists(**kw))
|
||||
|
||||
viewkeys = operator.methodcaller("keys")
|
||||
|
||||
viewvalues = operator.methodcaller("values")
|
||||
|
||||
viewitems = operator.methodcaller("items")
|
||||
else:
|
||||
def iterkeys(d, **kw):
|
||||
return d.iterkeys(**kw)
|
||||
|
||||
def itervalues(d, **kw):
|
||||
return d.itervalues(**kw)
|
||||
|
||||
def iteritems(d, **kw):
|
||||
return d.iteritems(**kw)
|
||||
|
||||
def iterlists(d, **kw):
|
||||
return d.iterlists(**kw)
|
||||
|
||||
viewkeys = operator.methodcaller("viewkeys")
|
||||
|
||||
viewvalues = operator.methodcaller("viewvalues")
|
||||
|
||||
viewitems = operator.methodcaller("viewitems")
|
||||
|
||||
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
|
||||
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
|
||||
_add_doc(iteritems,
|
||||
"Return an iterator over the (key, value) pairs of a dictionary.")
|
||||
_add_doc(iterlists,
|
||||
"Return an iterator over the (key, [values]) pairs of a dictionary.")
|
||||
|
||||
|
||||
if PY3:
|
||||
def b(s):
|
||||
return s.encode("latin-1")
|
||||
|
||||
def u(s):
|
||||
return s
|
||||
unichr = chr
|
||||
import struct
|
||||
int2byte = struct.Struct(">B").pack
|
||||
del struct
|
||||
byte2int = operator.itemgetter(0)
|
||||
indexbytes = operator.getitem
|
||||
iterbytes = iter
|
||||
import io
|
||||
StringIO = io.StringIO
|
||||
BytesIO = io.BytesIO
|
||||
_assertCountEqual = "assertCountEqual"
|
||||
if sys.version_info[1] <= 1:
|
||||
_assertRaisesRegex = "assertRaisesRegexp"
|
||||
_assertRegex = "assertRegexpMatches"
|
||||
else:
|
||||
_assertRaisesRegex = "assertRaisesRegex"
|
||||
_assertRegex = "assertRegex"
|
||||
else:
|
||||
def b(s):
|
||||
return s
|
||||
# Workaround for standalone backslash
|
||||
|
||||
def u(s):
|
||||
return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
|
||||
unichr = unichr
|
||||
int2byte = chr
|
||||
|
||||
def byte2int(bs):
|
||||
return ord(bs[0])
|
||||
|
||||
def indexbytes(buf, i):
|
||||
return ord(buf[i])
|
||||
iterbytes = functools.partial(itertools.imap, ord)
|
||||
import StringIO
|
||||
StringIO = BytesIO = StringIO.StringIO
|
||||
_assertCountEqual = "assertItemsEqual"
|
||||
_assertRaisesRegex = "assertRaisesRegexp"
|
||||
_assertRegex = "assertRegexpMatches"
|
||||
_add_doc(b, """Byte literal""")
|
||||
_add_doc(u, """Text literal""")
|
||||
|
||||
|
||||
def assertCountEqual(self, *args, **kwargs):
|
||||
return getattr(self, _assertCountEqual)(*args, **kwargs)
|
||||
|
||||
|
||||
def assertRaisesRegex(self, *args, **kwargs):
|
||||
return getattr(self, _assertRaisesRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
def assertRegex(self, *args, **kwargs):
|
||||
return getattr(self, _assertRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
if PY3:
|
||||
exec_ = getattr(moves.builtins, "exec")
|
||||
|
||||
def reraise(tp, value, tb=None):
|
||||
if value is None:
|
||||
value = tp()
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
|
||||
else:
|
||||
def exec_(_code_, _globs_=None, _locs_=None):
|
||||
"""Execute code in a namespace."""
|
||||
if _globs_ is None:
|
||||
frame = sys._getframe(1)
|
||||
_globs_ = frame.f_globals
|
||||
if _locs_ is None:
|
||||
_locs_ = frame.f_locals
|
||||
del frame
|
||||
elif _locs_ is None:
|
||||
_locs_ = _globs_
|
||||
exec("""exec _code_ in _globs_, _locs_""")
|
||||
|
||||
exec_("""def reraise(tp, value, tb=None):
|
||||
raise tp, value, tb
|
||||
""")
|
||||
|
||||
|
||||
if sys.version_info[:2] == (3, 2):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
if from_value is None:
|
||||
raise value
|
||||
raise value from from_value
|
||||
""")
|
||||
elif sys.version_info[:2] > (3, 2):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
raise value from from_value
|
||||
""")
|
||||
else:
|
||||
def raise_from(value, from_value):
|
||||
raise value
|
||||
|
||||
|
||||
print_ = getattr(moves.builtins, "print", None)
|
||||
if print_ is None:
|
||||
def print_(*args, **kwargs):
|
||||
"""The new-style print function for Python 2.4 and 2.5."""
|
||||
fp = kwargs.pop("file", sys.stdout)
|
||||
if fp is None:
|
||||
return
|
||||
|
||||
def write(data):
|
||||
if not isinstance(data, basestring):
|
||||
data = str(data)
|
||||
# If the file has an encoding, encode unicode with it.
|
||||
if (isinstance(fp, file) and
|
||||
isinstance(data, unicode) and
|
||||
fp.encoding is not None):
|
||||
errors = getattr(fp, "errors", None)
|
||||
if errors is None:
|
||||
errors = "strict"
|
||||
data = data.encode(fp.encoding, errors)
|
||||
fp.write(data)
|
||||
want_unicode = False
|
||||
sep = kwargs.pop("sep", None)
|
||||
if sep is not None:
|
||||
if isinstance(sep, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(sep, str):
|
||||
raise TypeError("sep must be None or a string")
|
||||
end = kwargs.pop("end", None)
|
||||
if end is not None:
|
||||
if isinstance(end, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(end, str):
|
||||
raise TypeError("end must be None or a string")
|
||||
if kwargs:
|
||||
raise TypeError("invalid keyword arguments to print()")
|
||||
if not want_unicode:
|
||||
for arg in args:
|
||||
if isinstance(arg, unicode):
|
||||
want_unicode = True
|
||||
break
|
||||
if want_unicode:
|
||||
newline = unicode("\n")
|
||||
space = unicode(" ")
|
||||
else:
|
||||
newline = "\n"
|
||||
space = " "
|
||||
if sep is None:
|
||||
sep = space
|
||||
if end is None:
|
||||
end = newline
|
||||
for i, arg in enumerate(args):
|
||||
if i:
|
||||
write(sep)
|
||||
write(arg)
|
||||
write(end)
|
||||
if sys.version_info[:2] < (3, 3):
|
||||
_print = print_
|
||||
|
||||
def print_(*args, **kwargs):
|
||||
fp = kwargs.get("file", sys.stdout)
|
||||
flush = kwargs.pop("flush", False)
|
||||
_print(*args, **kwargs)
|
||||
if flush and fp is not None:
|
||||
fp.flush()
|
||||
|
||||
_add_doc(reraise, """Reraise an exception.""")
|
||||
|
||||
if sys.version_info[0:2] < (3, 4):
|
||||
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
|
||||
updated=functools.WRAPPER_UPDATES):
|
||||
def wrapper(f):
|
||||
f = functools.wraps(wrapped, assigned, updated)(f)
|
||||
f.__wrapped__ = wrapped
|
||||
return f
|
||||
return wrapper
|
||||
else:
|
||||
wraps = functools.wraps
|
||||
|
||||
|
||||
def with_metaclass(meta, *bases):
|
||||
"""Create a base class with a metaclass."""
|
||||
# This requires a bit of explanation: the basic idea is to make a dummy
|
||||
# metaclass for one level of class instantiation that replaces itself with
|
||||
# the actual metaclass.
|
||||
class metaclass(meta):
|
||||
|
||||
def __new__(cls, name, this_bases, d):
|
||||
return meta(name, bases, d)
|
||||
return type.__new__(metaclass, 'temporary_class', (), {})
|
||||
|
||||
|
||||
def add_metaclass(metaclass):
|
||||
"""Class decorator for creating a class with a metaclass."""
|
||||
def wrapper(cls):
|
||||
orig_vars = cls.__dict__.copy()
|
||||
slots = orig_vars.get('__slots__')
|
||||
if slots is not None:
|
||||
if isinstance(slots, str):
|
||||
slots = [slots]
|
||||
for slots_var in slots:
|
||||
orig_vars.pop(slots_var)
|
||||
orig_vars.pop('__dict__', None)
|
||||
orig_vars.pop('__weakref__', None)
|
||||
return metaclass(cls.__name__, cls.__bases__, orig_vars)
|
||||
return wrapper
|
||||
|
||||
|
||||
def python_2_unicode_compatible(klass):
|
||||
"""
|
||||
A decorator that defines __unicode__ and __str__ methods under Python 2.
|
||||
Under Python 3 it does nothing.
|
||||
|
||||
To support Python 2 and 3 with a single code base, define a __str__ method
|
||||
returning text and apply this decorator to the class.
|
||||
"""
|
||||
if PY2:
|
||||
if '__str__' not in klass.__dict__:
|
||||
raise ValueError("@python_2_unicode_compatible cannot be applied "
|
||||
"to %s because it doesn't define __str__()." %
|
||||
klass.__name__)
|
||||
klass.__unicode__ = klass.__str__
|
||||
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
|
||||
return klass
|
||||
|
||||
|
||||
# Complete the moves implementation.
|
||||
# This code is at the end of this module to speed up module loading.
|
||||
# Turn this module into a package.
|
||||
__path__ = [] # required for PEP 302 and PEP 451
|
||||
__package__ = __name__ # see PEP 366 @ReservedAssignment
|
||||
if globals().get("__spec__") is not None:
|
||||
__spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
|
||||
# Remove other six meta path importers, since they cause problems. This can
|
||||
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
|
||||
# this for some reason.)
|
||||
if sys.meta_path:
|
||||
for i, importer in enumerate(sys.meta_path):
|
||||
# Here's some real nastiness: Another "instance" of the six module might
|
||||
# be floating around. Therefore, we can't use isinstance() to check for
|
||||
# the six meta path importer, since the other six instance will have
|
||||
# inserted an importer with different class.
|
||||
if (type(importer).__name__ == "_SixMetaPathImporter" and
|
||||
importer.name == __name__):
|
||||
del sys.meta_path[i]
|
||||
break
|
||||
del i, importer
|
||||
# Finally, add the importer to the meta path import hook.
|
||||
sys.meta_path.append(_importer)
|
||||
11
pype/tools/pyblish_pype/version.py
Normal file
11
pype/tools/pyblish_pype/version.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
VERSION_MAJOR = 2
|
||||
VERSION_MINOR = 9
|
||||
VERSION_PATCH = 0
|
||||
|
||||
|
||||
version_info = (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)
|
||||
version = '%i.%i.%i' % version_info
|
||||
__version__ = version
|
||||
|
||||
__all__ = ['version', 'version_info', '__version__']
|
||||
212
pype/tools/pyblish_pype/view.py
Normal file
212
pype/tools/pyblish_pype/view.py
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
from .vendor.Qt import QtCore, QtWidgets
|
||||
from . import model
|
||||
from .constants import Roles
|
||||
|
||||
|
||||
class ArtistView(QtWidgets.QListView):
|
||||
# An item is requesting to be toggled, with optional forced-state
|
||||
toggled = QtCore.Signal(QtCore.QModelIndex, object)
|
||||
show_perspective = QtCore.Signal(QtCore.QModelIndex)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(ArtistView, self).__init__(parent)
|
||||
|
||||
self.horizontalScrollBar().hide()
|
||||
self.viewport().setAttribute(QtCore.Qt.WA_Hover, True)
|
||||
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.setResizeMode(QtWidgets.QListView.Adjust)
|
||||
self.setVerticalScrollMode(QtWidgets.QListView.ScrollPerPixel)
|
||||
|
||||
def event(self, event):
|
||||
if not event.type() == QtCore.QEvent.KeyPress:
|
||||
return super(ArtistView, self).event(event)
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Space:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.toggled.emit(index, None)
|
||||
|
||||
return True
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Backspace:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.toggled.emit(index, False)
|
||||
|
||||
return True
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Return:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.toggled.emit(index, True)
|
||||
|
||||
return True
|
||||
|
||||
return super(ArtistView, self).event(event)
|
||||
|
||||
def focusOutEvent(self, event):
|
||||
self.selectionModel().clear()
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == QtCore.Qt.LeftButton:
|
||||
indexes = self.selectionModel().selectedIndexes()
|
||||
if len(indexes) <= 1 and event.pos().x() < 20:
|
||||
for index in indexes:
|
||||
self.toggled.emit(index, None)
|
||||
if len(indexes) == 1 and event.pos().x() > self.width() - 40:
|
||||
for index in indexes:
|
||||
self.show_perspective.emit(index)
|
||||
|
||||
return super(ArtistView, self).mouseReleaseEvent(event)
|
||||
|
||||
|
||||
class OverviewView(QtWidgets.QTreeView):
|
||||
# An item is requesting to be toggled, with optional forced-state
|
||||
toggled = QtCore.Signal(QtCore.QModelIndex, object)
|
||||
show_perspective = QtCore.Signal(QtCore.QModelIndex)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(OverviewView, self).__init__(parent)
|
||||
|
||||
self.horizontalScrollBar().hide()
|
||||
self.viewport().setAttribute(QtCore.Qt.WA_Hover, True)
|
||||
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.setItemsExpandable(True)
|
||||
self.setVerticalScrollMode(QtWidgets.QTreeView.ScrollPerPixel)
|
||||
self.setHeaderHidden(True)
|
||||
self.setRootIsDecorated(False)
|
||||
self.setIndentation(0)
|
||||
|
||||
self.clicked.connect(self.item_expand)
|
||||
|
||||
def event(self, event):
|
||||
if not event.type() == QtCore.QEvent.KeyPress:
|
||||
return super(OverviewView, self).event(event)
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Space:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.toggled.emit(index, None)
|
||||
|
||||
return True
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Backspace:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.toggled.emit(index, False)
|
||||
|
||||
return True
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Return:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.toggled.emit(index, True)
|
||||
|
||||
return True
|
||||
|
||||
return super(OverviewView, self).event(event)
|
||||
|
||||
def focusOutEvent(self, event):
|
||||
self.selectionModel().clear()
|
||||
|
||||
def item_expand(self, index):
|
||||
if index.data(Roles.TypeRole) == model.GroupType:
|
||||
if self.isExpanded(index):
|
||||
self.collapse(index)
|
||||
else:
|
||||
self.expand(index)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == QtCore.Qt.LeftButton:
|
||||
indexes = self.selectionModel().selectedIndexes()
|
||||
if len(indexes) == 1:
|
||||
index = indexes[0]
|
||||
# If instance or Plugin
|
||||
if index.data(Roles.TypeRole) in (
|
||||
model.InstanceType, model.PluginType
|
||||
):
|
||||
if event.pos().x() < 20:
|
||||
self.toggled.emit(index, None)
|
||||
elif event.pos().x() > self.width() - 20:
|
||||
self.show_perspective.emit(index)
|
||||
|
||||
# Deselect all group labels
|
||||
for index in indexes:
|
||||
if index.data(Roles.TypeRole) == model.GroupType:
|
||||
self.selectionModel().select(
|
||||
index, QtCore.QItemSelectionModel.Deselect
|
||||
)
|
||||
|
||||
return super(OverviewView, self).mouseReleaseEvent(event)
|
||||
|
||||
|
||||
class TerminalView(QtWidgets.QTreeView):
|
||||
# An item is requesting to be toggled, with optional forced-state
|
||||
def __init__(self, parent=None):
|
||||
super(TerminalView, self).__init__(parent)
|
||||
self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.setAutoScroll(False)
|
||||
self.setHeaderHidden(True)
|
||||
self.setIndentation(0)
|
||||
self.setVerticalScrollMode(QtWidgets.QTreeView.ScrollPerPixel)
|
||||
self.verticalScrollBar().setSingleStep(10)
|
||||
self.setRootIsDecorated(False)
|
||||
|
||||
self.clicked.connect(self.item_expand)
|
||||
|
||||
def event(self, event):
|
||||
if not event.type() == QtCore.QEvent.KeyPress:
|
||||
return super(TerminalView, self).event(event)
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Space:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
if self.isExpanded(index):
|
||||
self.collapse(index)
|
||||
else:
|
||||
self.expand(index)
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Backspace:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.collapse(index)
|
||||
|
||||
elif event.key() == QtCore.Qt.Key_Return:
|
||||
for index in self.selectionModel().selectedIndexes():
|
||||
self.expand(index)
|
||||
|
||||
return super(TerminalView, self).event(event)
|
||||
|
||||
def focusOutEvent(self, event):
|
||||
self.selectionModel().clear()
|
||||
|
||||
def item_expand(self, index):
|
||||
if index.data(Roles.TypeRole) == model.TerminalLabelType:
|
||||
if self.isExpanded(index):
|
||||
self.collapse(index)
|
||||
else:
|
||||
self.expand(index)
|
||||
self.model().layoutChanged.emit()
|
||||
self.updateGeometry()
|
||||
|
||||
def rowsInserted(self, parent, start, end):
|
||||
"""Automatically scroll to bottom on each new item added."""
|
||||
super(TerminalView, self).rowsInserted(parent, start, end)
|
||||
self.updateGeometry()
|
||||
self.scrollToBottom()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(self.__class__, self).resizeEvent(event)
|
||||
self.model().layoutChanged.emit()
|
||||
|
||||
def sizeHint(self):
|
||||
size = super(TerminalView, self).sizeHint()
|
||||
height = (
|
||||
self.contentsMargins().top()
|
||||
+ self.contentsMargins().bottom()
|
||||
)
|
||||
for idx_i in range(self.model().rowCount()):
|
||||
index = self.model().index(idx_i, 0)
|
||||
height += self.rowHeight(index)
|
||||
if self.isExpanded(index):
|
||||
for idx_j in range(index.model().rowCount(index)):
|
||||
child_index = index.child(idx_j, 0)
|
||||
height += self.rowHeight(child_index)
|
||||
|
||||
size.setHeight(height)
|
||||
return size
|
||||
558
pype/tools/pyblish_pype/widgets.py
Normal file
558
pype/tools/pyblish_pype/widgets.py
Normal file
|
|
@ -0,0 +1,558 @@
|
|||
import sys
|
||||
from .vendor.Qt import QtCore, QtWidgets, QtGui
|
||||
from . import model, delegate, view, awesome
|
||||
from .constants import PluginStates, InstanceStates, Roles
|
||||
|
||||
|
||||
class EllidableLabel(QtWidgets.QLabel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
self.setObjectName("EllidableLabel")
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QtGui.QPainter(self)
|
||||
|
||||
metrics = QtGui.QFontMetrics(self.font())
|
||||
elided = metrics.elidedText(
|
||||
self.text(), QtCore.Qt.ElideRight, self.width()
|
||||
)
|
||||
painter.drawText(self.rect(), self.alignment(), elided)
|
||||
|
||||
|
||||
class PerspectiveLabel(QtWidgets.QTextEdit):
|
||||
def __init__(self, parent=None):
|
||||
super(self.__class__, self).__init__(parent)
|
||||
self.setObjectName("PerspectiveLabel")
|
||||
|
||||
size_policy = self.sizePolicy()
|
||||
size_policy.setHeightForWidth(True)
|
||||
size_policy.setVerticalPolicy(QtWidgets.QSizePolicy.Preferred)
|
||||
self.setSizePolicy(size_policy)
|
||||
|
||||
self.textChanged.connect(self.on_text_changed)
|
||||
|
||||
def on_text_changed(self, *args, **kwargs):
|
||||
self.updateGeometry()
|
||||
|
||||
def hasHeightForWidth(self):
|
||||
return True
|
||||
|
||||
def heightForWidth(self, width):
|
||||
margins = self.contentsMargins()
|
||||
|
||||
document_width = 0
|
||||
if width >= margins.left() + margins.right():
|
||||
document_width = width - margins.left() - margins.right()
|
||||
|
||||
document = self.document().clone()
|
||||
document.setTextWidth(document_width)
|
||||
|
||||
return margins.top() + document.size().height() + margins.bottom()
|
||||
|
||||
def sizeHint(self):
|
||||
width = super(self.__class__, self).sizeHint().width()
|
||||
return QtCore.QSize(width, self.heightForWidth(width))
|
||||
|
||||
|
||||
class PerspectiveWidget(QtWidgets.QWidget):
|
||||
l_doc = "Documentation"
|
||||
l_rec = "Records"
|
||||
l_path = "Path"
|
||||
|
||||
def __init__(self, parent):
|
||||
super(PerspectiveWidget, self).__init__(parent)
|
||||
|
||||
self.parent_widget = parent
|
||||
main_layout = QtWidgets.QVBoxLayout(self)
|
||||
|
||||
header_widget = QtWidgets.QWidget()
|
||||
toggle_button = QtWidgets.QPushButton(parent=header_widget)
|
||||
toggle_button.setObjectName("PerspectiveToggleBtn")
|
||||
toggle_button.setText(delegate.icons["angle-left"])
|
||||
toggle_button.setMinimumHeight(50)
|
||||
toggle_button.setFixedWidth(40)
|
||||
|
||||
indicator = QtWidgets.QLabel("", parent=header_widget)
|
||||
indicator.setFixedWidth(30)
|
||||
indicator.setAlignment(QtCore.Qt.AlignCenter)
|
||||
indicator.setObjectName("PerspectiveIndicator")
|
||||
|
||||
name = EllidableLabel('*Name of inspected', parent=header_widget)
|
||||
|
||||
header_layout = QtWidgets.QHBoxLayout(header_widget)
|
||||
header_layout.setAlignment(QtCore.Qt.AlignLeft)
|
||||
header_layout.addWidget(toggle_button)
|
||||
header_layout.addWidget(indicator)
|
||||
header_layout.addWidget(name)
|
||||
header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
header_layout.setSpacing(10)
|
||||
header_widget.setLayout(header_layout)
|
||||
|
||||
main_layout.setAlignment(QtCore.Qt.AlignTop)
|
||||
main_layout.addWidget(header_widget)
|
||||
|
||||
scroll_widget = QtWidgets.QScrollArea(self)
|
||||
scroll_widget.setObjectName("PerspectiveScrollContent")
|
||||
|
||||
contents_widget = QtWidgets.QWidget(scroll_widget)
|
||||
contents_widget.setObjectName("PerspectiveWidgetContent")
|
||||
|
||||
layout = QtWidgets.QVBoxLayout()
|
||||
layout.setAlignment(QtCore.Qt.AlignTop)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
documentation = ExpandableWidget(self, self.l_doc)
|
||||
doc_label = PerspectiveLabel()
|
||||
documentation.set_content(doc_label)
|
||||
layout.addWidget(documentation)
|
||||
|
||||
path = ExpandableWidget(self, self.l_path)
|
||||
path_label = PerspectiveLabel()
|
||||
path.set_content(path_label)
|
||||
layout.addWidget(path)
|
||||
|
||||
records = ExpandableWidget(self, self.l_rec)
|
||||
layout.addWidget(records)
|
||||
|
||||
contents_widget.setLayout(layout)
|
||||
|
||||
terminal_view = view.TerminalView()
|
||||
terminal_view.setObjectName("TerminalView")
|
||||
terminal_model = model.TerminalModel()
|
||||
terminal_proxy = model.TerminalProxy(terminal_view)
|
||||
terminal_proxy.setSourceModel(terminal_model)
|
||||
|
||||
terminal_view.setModel(terminal_proxy)
|
||||
terminal_delegate = delegate.TerminalItem()
|
||||
terminal_view.setItemDelegate(terminal_delegate)
|
||||
records.set_content(terminal_view)
|
||||
|
||||
scroll_widget.setWidgetResizable(True)
|
||||
scroll_widget.setWidget(contents_widget)
|
||||
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
main_layout.setSpacing(0)
|
||||
main_layout.addWidget(scroll_widget)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
self.terminal_view = terminal_view
|
||||
self.terminal_model = terminal_model
|
||||
self.terminal_proxy = terminal_proxy
|
||||
|
||||
self.indicator = indicator
|
||||
self.scroll_widget = scroll_widget
|
||||
self.contents_widget = contents_widget
|
||||
self.toggle_button = toggle_button
|
||||
self.name_widget = name
|
||||
self.documentation = documentation
|
||||
self.path = path
|
||||
self.records = records
|
||||
|
||||
self.toggle_button.clicked.connect(self.toggle_me)
|
||||
|
||||
self.last_type = None
|
||||
self.last_item_id = None
|
||||
self.last_id = None
|
||||
|
||||
def trim(self, docstring):
|
||||
if not docstring:
|
||||
return ""
|
||||
# Convert tabs to spaces (following the normal Python rules)
|
||||
# and split into a list of lines:
|
||||
lines = docstring.expandtabs().splitlines()
|
||||
# Determine minimum indentation (first line doesn't count):
|
||||
try:
|
||||
indent = sys.maxint
|
||||
max = sys.maxint
|
||||
except Exception:
|
||||
indent = sys.maxsize
|
||||
max = sys.maxsize
|
||||
|
||||
for line in lines[1:]:
|
||||
stripped = line.lstrip()
|
||||
if stripped:
|
||||
indent = min(indent, len(line) - len(stripped))
|
||||
# Remove indentation (first line is special):
|
||||
trimmed = [lines[0].strip()]
|
||||
if indent < max:
|
||||
for line in lines[1:]:
|
||||
trimmed.append(line[indent:].rstrip())
|
||||
# Strip off trailing and leading blank lines:
|
||||
while trimmed and not trimmed[-1]:
|
||||
trimmed.pop()
|
||||
while trimmed and not trimmed[0]:
|
||||
trimmed.pop(0)
|
||||
# Return a single string:
|
||||
return "\n".join(trimmed)
|
||||
|
||||
def set_indicator_state(self, state):
|
||||
self.indicator.setProperty("state", state)
|
||||
self.indicator.style().polish(self.indicator)
|
||||
|
||||
def reset(self):
|
||||
self.last_id = None
|
||||
self.set_records(list())
|
||||
self.set_indicator_state(None)
|
||||
|
||||
def update_context(self, plugin_item, instance_item):
|
||||
if not self.last_item_id or not self.last_type:
|
||||
return
|
||||
|
||||
if self.last_type == model.PluginType:
|
||||
if not self.last_id:
|
||||
_item_id = plugin_item.data(Roles.ObjectUIdRole)
|
||||
if _item_id != self.last_item_id:
|
||||
return
|
||||
self.last_id = plugin_item.plugin.id
|
||||
|
||||
elif self.last_id != plugin_item.plugin.id:
|
||||
return
|
||||
|
||||
self.set_context(plugin_item.index())
|
||||
return
|
||||
|
||||
if self.last_type == model.InstanceType:
|
||||
if not self.last_id:
|
||||
_item_id = instance_item.data(Roles.ObjectUIdRole)
|
||||
if _item_id != self.last_item_id:
|
||||
return
|
||||
self.last_id = instance_item.instance.id
|
||||
|
||||
elif self.last_id != instance_item.instance.id:
|
||||
return
|
||||
|
||||
self.set_context(instance_item.index())
|
||||
return
|
||||
|
||||
def set_context(self, index):
|
||||
if not index or not index.isValid():
|
||||
index_type = None
|
||||
else:
|
||||
index_type = index.data(Roles.TypeRole)
|
||||
|
||||
if index_type == model.InstanceType:
|
||||
item_id = index.data(Roles.ObjectIdRole)
|
||||
publish_states = index.data(Roles.PublishFlagsRole)
|
||||
if publish_states & InstanceStates.ContextType:
|
||||
type_indicator = "C"
|
||||
else:
|
||||
type_indicator = "I"
|
||||
|
||||
if publish_states & InstanceStates.InProgress:
|
||||
self.set_indicator_state("active")
|
||||
|
||||
elif publish_states & InstanceStates.HasError:
|
||||
self.set_indicator_state("error")
|
||||
|
||||
elif publish_states & InstanceStates.HasWarning:
|
||||
self.set_indicator_state("warning")
|
||||
|
||||
elif publish_states & InstanceStates.HasFinished:
|
||||
self.set_indicator_state("ok")
|
||||
else:
|
||||
self.set_indicator_state(None)
|
||||
|
||||
self.documentation.setVisible(False)
|
||||
self.path.setVisible(False)
|
||||
|
||||
elif index_type == model.PluginType:
|
||||
item_id = index.data(Roles.ObjectIdRole)
|
||||
type_indicator = "P"
|
||||
|
||||
doc = index.data(Roles.DocstringRole)
|
||||
doc_str = ""
|
||||
if doc:
|
||||
doc_str = self.trim(doc)
|
||||
|
||||
publish_states = index.data(Roles.PublishFlagsRole)
|
||||
if publish_states & PluginStates.InProgress:
|
||||
self.set_indicator_state("active")
|
||||
|
||||
elif publish_states & PluginStates.HasError:
|
||||
self.set_indicator_state("error")
|
||||
|
||||
elif publish_states & PluginStates.HasWarning:
|
||||
self.set_indicator_state("warning")
|
||||
|
||||
elif publish_states & PluginStates.WasProcessed:
|
||||
self.set_indicator_state("ok")
|
||||
|
||||
else:
|
||||
self.set_indicator_state(None)
|
||||
|
||||
self.documentation.toggle_content(bool(doc_str))
|
||||
self.documentation.content.setText(doc_str)
|
||||
|
||||
path = index.data(Roles.PathModuleRole) or ""
|
||||
self.path.toggle_content(path.strip() != "")
|
||||
self.path.content.setText(path)
|
||||
|
||||
self.documentation.setVisible(True)
|
||||
self.path.setVisible(True)
|
||||
|
||||
else:
|
||||
self.last_type = None
|
||||
self.last_id = None
|
||||
self.indicator.setText("?")
|
||||
self.set_indicator_state(None)
|
||||
self.documentation.setVisible(False)
|
||||
self.path.setVisible(False)
|
||||
self.records.setVisible(False)
|
||||
return
|
||||
|
||||
self.last_type = index_type
|
||||
self.last_id = item_id
|
||||
self.last_item_id = index.data(Roles.ObjectUIdRole)
|
||||
|
||||
self.indicator.setText(type_indicator)
|
||||
|
||||
label = index.data(QtCore.Qt.DisplayRole)
|
||||
self.name_widget.setText(label)
|
||||
self.records.setVisible(True)
|
||||
|
||||
records = index.data(Roles.LogRecordsRole) or []
|
||||
self.set_records(records)
|
||||
|
||||
def set_records(self, records):
|
||||
len_records = 0
|
||||
if records:
|
||||
len_records += len(records)
|
||||
|
||||
data = {"records": records}
|
||||
self.terminal_model.reset()
|
||||
self.terminal_model.update_with_result(data)
|
||||
while not self.terminal_model.items_to_set_widget.empty():
|
||||
item = self.terminal_model.items_to_set_widget.get()
|
||||
widget = TerminalDetail(item.data(QtCore.Qt.DisplayRole))
|
||||
index = self.terminal_proxy.mapFromSource(item.index())
|
||||
self.terminal_view.setIndexWidget(index, widget)
|
||||
|
||||
self.records.button_toggle_text.setText(
|
||||
"{} ({})".format(self.l_rec, len_records)
|
||||
)
|
||||
self.records.toggle_content(len_records > 0)
|
||||
|
||||
def toggle_me(self):
|
||||
self.parent_widget.toggle_perspective_widget()
|
||||
|
||||
|
||||
class ClickableWidget(QtWidgets.QLabel):
|
||||
clicked = QtCore.Signal()
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == QtCore.Qt.LeftButton:
|
||||
self.clicked.emit()
|
||||
super(ClickableWidget, self).mouseReleaseEvent(event)
|
||||
|
||||
|
||||
class ExpandableWidget(QtWidgets.QWidget):
|
||||
|
||||
content = None
|
||||
|
||||
def __init__(self, parent, title):
|
||||
super(ExpandableWidget, self).__init__(parent)
|
||||
|
||||
top_part = ClickableWidget(parent=self)
|
||||
top_part.setObjectName("ExpandableHeader")
|
||||
|
||||
button_size = QtCore.QSize(5, 5)
|
||||
button_toggle = QtWidgets.QToolButton(parent=top_part)
|
||||
button_toggle.setIconSize(button_size)
|
||||
button_toggle.setArrowType(QtCore.Qt.RightArrow)
|
||||
button_toggle.setCheckable(True)
|
||||
button_toggle.setChecked(False)
|
||||
|
||||
button_toggle_text = QtWidgets.QLabel(title, parent=top_part)
|
||||
|
||||
layout = QtWidgets.QHBoxLayout(top_part)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(5)
|
||||
layout.addWidget(button_toggle)
|
||||
layout.addWidget(button_toggle_text)
|
||||
top_part.setLayout(layout)
|
||||
|
||||
main_layout = QtWidgets.QVBoxLayout(self)
|
||||
main_layout.setContentsMargins(9, 9, 9, 0)
|
||||
|
||||
content = QtWidgets.QFrame(self)
|
||||
content.setObjectName("ExpandableWidgetContent")
|
||||
content.setVisible(False)
|
||||
|
||||
content_layout = QtWidgets.QVBoxLayout(content)
|
||||
|
||||
main_layout.addWidget(top_part)
|
||||
main_layout.addWidget(content)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
self.setAttribute(QtCore.Qt.WA_StyledBackground)
|
||||
|
||||
self.top_part = top_part
|
||||
self.button_toggle = button_toggle
|
||||
self.button_toggle_text = button_toggle_text
|
||||
|
||||
self.content_widget = content
|
||||
self.content_layout = content_layout
|
||||
|
||||
self.top_part.clicked.connect(self.top_part_clicked)
|
||||
self.button_toggle.clicked.connect(self.toggle_content)
|
||||
|
||||
def top_part_clicked(self):
|
||||
self.toggle_content(not self.button_toggle.isChecked())
|
||||
|
||||
def toggle_content(self, *args):
|
||||
if len(args) > 0:
|
||||
checked = args[0]
|
||||
else:
|
||||
checked = self.button_toggle.isChecked()
|
||||
arrow_type = QtCore.Qt.RightArrow
|
||||
if checked:
|
||||
arrow_type = QtCore.Qt.DownArrow
|
||||
self.button_toggle.setChecked(checked)
|
||||
self.button_toggle.setArrowType(arrow_type)
|
||||
self.content_widget.setVisible(checked)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(self.__class__, self).resizeEvent(event)
|
||||
self.content.updateGeometry()
|
||||
|
||||
def set_content(self, in_widget):
|
||||
if self.content:
|
||||
self.content.hide()
|
||||
self.content_layout.removeWidget(self.content)
|
||||
self.content_layout.addWidget(in_widget)
|
||||
self.content = in_widget
|
||||
|
||||
|
||||
class ButtonWithMenu(QtWidgets.QWidget):
|
||||
def __init__(self, button_title, parent=None):
|
||||
super(ButtonWithMenu, self).__init__(parent=parent)
|
||||
self.setSizePolicy(QtWidgets.QSizePolicy(
|
||||
QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum
|
||||
))
|
||||
|
||||
self.layout = QtWidgets.QHBoxLayout(self)
|
||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.layout.setSpacing(0)
|
||||
|
||||
self.menu = QtWidgets.QMenu()
|
||||
# TODO move to stylesheets
|
||||
self.menu.setStyleSheet("""
|
||||
*{color: #fff; background-color: #555; border: 1px solid #222;}
|
||||
::item {background-color: transparent;padding: 5px;
|
||||
padding-left: 10px;padding-right: 10px;}
|
||||
::item:selected {background-color: #666;}
|
||||
""")
|
||||
|
||||
self.button = QtWidgets.QPushButton(button_title)
|
||||
self.button.setObjectName("ButtonWithMenu")
|
||||
|
||||
self.layout.addWidget(self.button)
|
||||
|
||||
self.button.clicked.connect(self.btn_clicked)
|
||||
|
||||
def btn_clicked(self):
|
||||
self.menu.popup(self.button.mapToGlobal(
|
||||
QtCore.QPoint(0, self.button.height())
|
||||
))
|
||||
|
||||
def addItem(self, text, callback):
|
||||
self.menu.addAction(text, callback)
|
||||
self.button.setToolTip("Select to apply predefined presets")
|
||||
|
||||
def clearMenu(self):
|
||||
self.menu.clear()
|
||||
self.button.setToolTip("Presets not found")
|
||||
|
||||
|
||||
class CommentBox(QtWidgets.QLineEdit):
|
||||
|
||||
def __init__(self, placeholder_text, parent=None):
|
||||
super(CommentBox, self).__init__(parent=parent)
|
||||
self.placeholder = QtWidgets.QLabel(placeholder_text, self)
|
||||
self.placeholder.move(2, 2)
|
||||
|
||||
def focusInEvent(self, event):
|
||||
self.placeholder.setVisible(False)
|
||||
return super(CommentBox, self).focusInEvent(event)
|
||||
|
||||
def focusOutEvent(self, event):
|
||||
current_text = self.text()
|
||||
current_text = current_text.strip(" ")
|
||||
self.setText(current_text)
|
||||
if not self.text():
|
||||
self.placeholder.setVisible(True)
|
||||
return super(CommentBox, self).focusOutEvent(event)
|
||||
|
||||
|
||||
class TerminalDetail(QtWidgets.QTextEdit):
|
||||
def __init__(self, text, *args, **kwargs):
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
self.setReadOnly(True)
|
||||
self.setHtml(text)
|
||||
self.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
|
||||
self.setWordWrapMode(
|
||||
QtGui.QTextOption.WrapAtWordBoundaryOrAnywhere
|
||||
)
|
||||
|
||||
def sizeHint(self):
|
||||
content_margins = (
|
||||
self.contentsMargins().top()
|
||||
+ self.contentsMargins().bottom()
|
||||
)
|
||||
size = self.document().documentLayout().documentSize().toSize()
|
||||
size.setHeight(size.height() + content_margins)
|
||||
return size
|
||||
|
||||
|
||||
class FilterButton(QtWidgets.QPushButton):
|
||||
def __init__(self, name, *args, **kwargs):
|
||||
self.filter_name = name
|
||||
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
self.toggled.connect(self.on_toggle)
|
||||
|
||||
self.setProperty("type", name)
|
||||
self.setObjectName("TerminalFilerBtn")
|
||||
self.setCheckable(True)
|
||||
self.setChecked(
|
||||
model.TerminalProxy.filter_buttons_checks[name]
|
||||
)
|
||||
|
||||
def on_toggle(self, toggle_state):
|
||||
model.TerminalProxy.change_filter(self.filter_name, toggle_state)
|
||||
|
||||
|
||||
class TerminalFilterWidget(QtWidgets.QWidget):
|
||||
# timer.timeout.connect(lambda: self._update(self.parent_widget))
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
self.filter_changed = QtCore.Signal()
|
||||
|
||||
info_icon = awesome.tags["info"]
|
||||
log_icon = awesome.tags["circle"]
|
||||
error_icon = awesome.tags["exclamation-triangle"]
|
||||
|
||||
filter_buttons = (
|
||||
FilterButton("info", info_icon),
|
||||
FilterButton("log_debug", log_icon),
|
||||
FilterButton("log_info", log_icon),
|
||||
FilterButton("log_warning", log_icon),
|
||||
FilterButton("log_error", log_icon),
|
||||
FilterButton("log_critical", log_icon),
|
||||
FilterButton("error", error_icon)
|
||||
)
|
||||
|
||||
layout = QtWidgets.QHBoxLayout()
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
# Add spacers
|
||||
layout.addWidget(QtWidgets.QWidget(), 1)
|
||||
|
||||
for btn in filter_buttons:
|
||||
layout.addWidget(btn)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
self.filter_buttons = filter_buttons
|
||||
1055
pype/tools/pyblish_pype/window.py
Normal file
1055
pype/tools/pyblish_pype/window.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue