Source code for cgl.ui.widgets.widgets

import logging
import os
import webbrowser

from PySide6 import QtCore, QtGui, QtWidgets
from cgl.ui.widgets.button import LJButton

try:
    from PySide6.QtSvg import QSvgRenderer
except ImportError:
    from PySide6.QtSvg import QSvgRenderer


from cgl.apps.alchemy.data.filedialogcontextmanager import FPContextMgr
from cgl.core import path
from cgl.core.config.query import AlchemyConfigManager, get_task_source
from cgl.core.utils.general import cgl_copy
from cgl.ui.util import define_palettes
from cgl.ui.widgets.containers.model import ListItemModel
from cgl.ui.widgets.containers.table import LJTableWidget

CFG = AlchemyConfigManager()


[docs] class LJTag(QtWidgets.QFrame): close_clicked = QtCore.Signal() def __init__(self, parent=None, text="Tab Text", height=30): QtWidgets.QFrame.__init__(self, parent) self.setMinimumHeight(height) self.setProperty("role", "tag") self.setMaximumHeight(height + 0) self.text = text close_width = height / 2 layout = QtWidgets.QHBoxLayout(self) layout.setContentsMargins(6, 0, 0, 0) label = QtWidgets.QLabel(text) close_button = QtWidgets.QToolButton() close_button.setText("x") close_button.setMaximumWidth(close_width) close_button.setMaximumHeight(close_width) layout.addWidget(label) layout.addWidget(close_button) # Shape of the button is a "Frame" with an hlayout # close button is a "tool button" with an 'x' close_button.clicked.connect(self.delete_tag)
[docs] def delete_tag(self): logging.info(self.text) self.close_clicked.emit()
[docs] class TagWidget(QtWidgets.QWidget): def __init__(self, parent=None, entry_type="line_edit", validation_list=None): QtWidgets.QWidget.__init__(self, parent) layout = QtWidgets.QVBoxLayout(self) layout.setContentsMargins(0, 5, 0, 5) layout.setSpacing(0) self.frame = TagFrame(entry_type=entry_type, validation_list=validation_list) layout.addWidget(self.frame)
[docs] class TagFrame(QtWidgets.QFrame): tags_changed = QtCore.Signal(object) def __init__( self, parent=None, tag_height=34, entry_type="line_edit", validation_list=None ): QtWidgets.QFrame.__init__(self, parent) self.entry_type = entry_type self.validation_list = validation_list if validation_list: self.validation_list.insert(0, "") self.tag_height = tag_height # self.setProperty("surface", "1") self.setMinimumHeight(tag_height + 4) self.layout = QtWidgets.QHBoxLayout(self) self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.tags_layout = QtWidgets.QHBoxLayout() self.tags_layout.setContentsMargins(0, 0, 0, 0) self.tags_layout.setSpacing(5) if entry_type == "line_edit": self.text_entry = QtWidgets.QLineEdit() self.text_entry.setProperty("tone", "transparent") self.text_entry.setMinimumHeight(tag_height + 10) self.text_entry.setMinimumWidth(300) self.text_entry.textEdited.connect(self.on_text_entry_changed) self.text_entry.returnPressed.connect(self.on_text_entry_return) elif entry_type == "combo": self.text_entry = QtWidgets.QComboBox() self.text_entry.setEditable(True) if self.validation_list: self.text_entry.addItems(self.validation_list) self.text_entry.currentIndexChanged.connect(self.on_text_entry_changed) # self.text_entry.setProperty("class", "tag_entry") self.tag_dict = {} self.tags = [] self.layout.addLayout(self.tags_layout) self.layout.addWidget(self.text_entry)
[docs] def on_text_entry_changed(self): if self.entry_type == "line_edit": text = self.sender().text() if "," in text: text = text.replace(",", "") self.add_tag(tag_text=text) self.sender().setText("") else: text = self.sender().currentText() self.sender().setCurrentIndex(0) if text: self.add_tag(tag_text=text)
[docs] def on_text_entry_return(self): """ Adds a tag to the tag widget Returns: """ if self.entry_type == "line_edit": text = self.sender().text() self.add_tag(tag_text=text) self.sender().setText("")
[docs] def add_tag(self, tag_text): if self.validate_tag(tag_text): tag = LJTag(text=tag_text, height=self.tag_height) tag.close_clicked.connect(self.remove_tag) self.tag_dict["tag_text"] = tag self.tags.append(tag_text) self.tags_layout.addWidget(tag) self.tags_changed.emit(self.tags) else: print( "{} not found in validation list {}".format( tag_text, self.validation_list ) ) self.tags_changed.emit(self.tags)
[docs] def remove_tag(self, tag_text=None): if not tag_text: tag_text = self.sender().text widget = self.sender() self.sender().deleteLater() else: widget = self.find_tag_widget(tag_text) if tag_text in self.tags: self.tags.remove(tag_text) if widget: widget.deleteLater() self.layout.removeWidget(widget) self.tags_changed.emit(self.tags)
[docs] def remove_all_tags(self): """ Removes all tags from the tag widget """ for i in range(self.tags_layout.count()): widget = self.tags_layout.itemAt(i).widget() widget.deleteLater() self.layout.removeWidget(widget) self.tags = [] self.tags_changed.emit(self.tags)
[docs] def find_tag_widget(self, tag_text): # iterate over the widgets in the self.layout and find the tag with the tag_text for i in range(self.tags_layout.count()): widget = self.tags_layout.itemAt(i).widget() if widget.text == tag_text: return widget
[docs] def validate_tag(self, tag_text): """ Validates the tag against the validation list Returns: """ if self.validation_list: if tag_text in self.validation_list: return True else: return False else: return True
[docs] def get_tags(self): return self.tags
[docs] class HelpMenu(LJButton): """ This is the the hat menu that appears on the UI """ def __init__(self, parent): LJButton.__init__(self, parent) print(parent) self.parent = parent self.parent.report_bug_dialog = None self.parent.request_a_feature_dialog = None self.menu = QtWidgets.QMenu() self.setText("") self.setup_menu() self.setToolTip("Help")
[docs] def setup_menu(self): self.tutorials_act = self.menu.addAction(self.tr("Tutorials")) self.documentation_act = self.menu.addAction(self.tr("Code Docs")) self.report_bug_act = self.menu.addAction(self.tr("Report a Bug")) self.request_a_feature_act = self.menu.addAction(self.tr("Request a Feature")) self.IT_request_act = self.menu.addAction(self.tr("Pipeline IT Request")) self.clear_widget = self.menu.addAction(self.tr("Clear table widget")) self.load_msd = self.menu.addAction(self.tr("Load MSD")) self.tutorials_act.triggered.connect(self.tutorials_clicked) self.documentation_act.triggered.connect(self.documentation_clicked) self.report_bug_act.triggered.connect(self.report_bug_clicked) self.request_a_feature_act.triggered.connect(self.request_feature_clicked) self.IT_request_act.triggered.connect(self.IT_request_clicked) self.clear_widget.triggered.connect(self.clear_widget_clicked) self.load_msd.triggered.connect(self.load_msd_clicked) # remove the sub menu arrow from the menu self.menu.setToolTipsVisible(True) self.setMenu(self.menu)
[docs] def load_msd_clicked(self): """ Loads the msd from the filesystem Returns: """ print("loading msd")
[docs] def clear_widget_clicked(self): """ Clears the table widget Returns: """ print("clearing table widget") print(self.parent())
[docs] def tutorials_clicked(self): """ Returns: """ url = r"conflence url for cglumberjack's tutorials" print(url)
# webbrowser.open_new_tab(url)
[docs] def documentation_clicked(self): """ sends the user to alchemy's code documentation. Returns: """ url = r"http://docs.alchemystudio.io" webbrowser.open_new_tab(url)
[docs] def report_bug_clicked(self): from cgl.ui.widgets.help import ReportBugDialog self.parent.report_bug_dialog = ReportBugDialog(parent=None) self.parent.report_bug_dialog.show() self.parent.report_bug_dialog.raise_()
[docs] def request_feature_clicked(self): from cgl.ui.widgets.help import ReportBugDialog self.request_a_feature_dialog = ReportBugDialog(title="Request A Feature").exec() self.request_a_feature_dialog.show() self.request_a_feature_dialog.raise_()
[docs] def IT_request_clicked(self): from cgl.ui.widgets.help import ReportBugDialog ReportBugDialog(title="Pipeline IT Request").exec()
[docs] class LoginMenu(LJButton): def __init__(self, parent): LJButton.__init__(self, parent) self.user = "tom.m" self.menu = QtWidgets.QMenu() self.setObjectName("login") # self.setText(self.tr("login")) self.setup_menu()
[docs] def get_current_user(self): # TODO - get the current user from the config self.user = "tom.m" self.setup_menu()
[docs] def setup_menu(self): self.menu.clear() self.selected_act = self.menu.addAction(self.tr(self.user)) self.settings_act = self.menu.addAction(self.tr("Settings")) self.menu.addSeparator() if not self.user: self.log_in_act = self.menu.addAction(self.tr("Log In")) self.log_in_act.triggered.connect(self.login_clicked) else: self.log_out_act = self.menu.addAction(self.tr("Log Out")) self.log_out_act.triggered.connect(self.logout_clicked) self.settings_act.triggered.connect(self.settings_clicked) self.setMenu(self.menu)
[docs] def login_clicked(self): from cgl.apps.magic_browser.to_delete.config import ConfigDialog dialog = ConfigDialog() dialog.exec()
[docs] def logout_clicked(self): from cgl.apps.magic_browser.to_delete.config import ConfigDialog # TODO - delete the user data in the user config dialog = ConfigDialog() dialog.exec()
[docs] def settings_clicked(self): from cgl.apps.magic_browser.to_delete.config import ConfigDialog dialog = ConfigDialog() dialog.exec()
[docs] class VersionButton(LJButton): def __init__(self, parent): LJButton.__init__(self, parent) self.menu = QtWidgets.QMenu() self.setText(self.tr("Version Up")) self.selected_act = self.menu.addAction(self.tr("New Version From Selected")) self.empty_act = self.menu.addAction(self.tr("New Empty Version")) self.empty_act.setToolTip(self.tr("Create a new empty version")) self.empty_act.triggered.connect( lambda: self.parent().create_empty_version.emit() ) self.selected_act.triggered.connect( lambda: self.parent().copy_selected_version.emit() ) self.selected_act.setToolTip( self.tr("Create a new version copying from current version") ) # self.latest_act = self.menu.addAction(self.tr("Copy Latest Version")) # self.latest_act.triggered.connect(lambda: self.parent().copy_latest_version.emit()) # self.latest_act.setToolTip(self.tr("Create a new version copying from the latest version")) self.setMenu(self.menu)
[docs] def set_new_version(self): self.selected_act.setVisible(False) self.latest_act.setVisible(False) self.setEnabled(True)
[docs] def set_version_selected(self): self.selected_act.setVisible(True) self.latest_act.setVisible(True) self.setEnabled(True)
[docs] class EmptyStateWidget(QtWidgets.QPushButton): files_added = QtCore.Signal() def __init__( self, parent=None, path_object=None, text="Drag/Drop to Add Files", files=False ): QtWidgets.QPushButton.__init__(self, parent) self.files = files self.path_object = path_object self.setAcceptDrops(True) self.setMinimumWidth(300) self.setMinimumHeight(100) self.setText(text) self.setProperty("class", "empty_state") self.to_path = "" self.to_object = None
[docs] def mouseReleaseEvent(self, e): super(EmptyStateWidget, self).mouseReleaseEvent(e)
[docs] def dragEnterEvent(self, e): if e.mimeData().hasUrls: e.accept() else: e.ignore()
[docs] def dragMoveEvent(self, e): if e.mimeData().hasUrls: e.setDropAction(QtCore.Qt.CopyAction) e.accept() else: e.ignore()
[docs] def dropEvent(self, e): if e.mimeData().hasUrls(): e.accept() urls = e.mimeData().urls() self.handle_dropped_files(urls) elif e.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"): e.accept() self.handle_table_drag_drop(e) else: e.ignore()
[docs] def handle_dropped_files(self, urls): for url in urls: file_path = url.toLocalFile() print("FILE PATH::::::::::::::", file_path) file_name = os.path.basename(file_path) extension = os.path.splitext(file_path)[-1] directory = os.path.dirname(file_path) # Get the icon for the dropped file path_object = FPContextMgr.get_current_po() destination_path = path_object.copy( filename=file_name, ext=extension ).get_source_path() print("DESTINATION PATH", destination_path) destination_path = destination_path.replace("render", "source") directory = os.path.dirname(destination_path) if not os.path.exists(directory): os.makedirs(directory) print("MOVING FROM ", file_path, "TO", destination_path) cgl_copy(file_path, destination_path) self.files_added.emit()
[docs] class FileTableModel(ListItemModel):
[docs] def data(self, index, role): row = index.row() col = index.column() if role == QtCore.Qt.DisplayRole: return self.data_[row][col] if role == QtCore.Qt.DecorationRole: data = self.data_[row][col] if "." not in data: return QtGui.QIcon(CFG.get_icon_path("folder2.png"))
[docs] class QHLine(QtWidgets.QFrame): def __init__(self): super(QHLine, self).__init__() self.setFrameShape(QtWidgets.QFrame.HLine) self.setFrameShadow(QtWidgets.QFrame.Sunken)
[docs] class QVLine(QtWidgets.QFrame): def __init__(self): super(QVLine, self).__init__() self.setFrameShape(QtWidgets.QFrame.VLine) self.setFrameShadow(QtWidgets.QFrame.Sunken)
[docs] class AssetWidget(QtWidgets.QWidget): """ GUI Element for Displaying shots, assets, and "my tasks" """ button_clicked = QtCore.Signal(object) filter_changed = QtCore.Signal() add_clicked = QtCore.Signal() assign_clicked = QtCore.Signal(object) def __init__( self, parent, title, filter_string=None, search_box=None, ): QtWidgets.QWidget.__init__(self, parent) self.right_click = False self.v_layout = QtWidgets.QVBoxLayout(self) v_list = QtWidgets.QVBoxLayout() self.scope_layout = QtWidgets.QHBoxLayout() self.shots_icon = QtGui.QPixmap(CFG.get_icon_path("shots24px.png")) self.assets_icon = QtGui.QPixmap(CFG.get_icon_path("assets24px.png")) self.worlds_icon = QtGui.QPixmap(CFG.get_icon_path("unreal-engine24px.png")) self.tool_button_layout = QtWidgets.QHBoxLayout() self.sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding, ) self.setSizePolicy(self.sizePolicy) self.filter_string = filter_string self.label = title self.task = None self.user = None min_width = 340 self.message = QtWidgets.QLabel("") self.message.setMinimumWidth(min_width) try: self.message.setSizePolicy( QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding ) except AttributeError: logging.info("PySide6 Natively does not have QtWidgets.QSizePolicy") self.message.setAlignment(QtCore.Qt.AlignCenter) self.search_box = search_box self.add_button = QtWidgets.QToolButton() self.add_button.setText("add") self.add_button.setProperty("class", "add_button") self.data_table = LJTableWidget(self, path_object=self.path_object) self.data_table.title = title self.data_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.data_table.setMinimumWidth(min_width) # self.setProperty('class', 'basic') # tasks the filter options row self.world_radio = QtWidgets.QRadioButton("World") self.assets_radio = QtWidgets.QRadioButton("Assets") self.shots_radio = QtWidgets.QRadioButton("Shots") self.tasks_radio = QtWidgets.QRadioButton("My Tasks") self.radio_group_scope = QtWidgets.QButtonGroup(self) self.radio_group_scope.addButton(self.shots_radio) self.radio_group_scope.addButton(self.assets_radio) self.radio_group_scope.addButton(self.tasks_radio) self.radio_group_scope.addButton(self.world_radio) self.shot_icon = QtWidgets.QLabel() self.shot_icon.setPixmap(self.shots_icon) self.asset_icon = QtWidgets.QLabel() self.asset_icon.setPixmap(self.assets_icon) self.world_icon = QtWidgets.QLabel() self.world_icon.setPixmap(self.worlds_icon) self.scope_layout.addWidget(self.tasks_radio) self.scope_layout.addWidget(self.world_icon) self.scope_layout.addWidget(self.world_radio) self.scope_layout.addWidget(self.shot_icon) self.scope_layout.addWidget(self.shots_radio) self.scope_layout.addWidget(self.asset_icon) self.scope_layout.addWidget(self.assets_radio) self.scope_layout.addStretch(1) self.scope_layout.addWidget(self.add_button) v_list.addItem( QtWidgets.QSpacerItem( 0, 3, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum ) ) v_list.addWidget(self.data_table, 1) self.v_layout.addLayout(self.scope_layout) self.v_layout.addWidget(self.message) self.v_layout.addLayout(v_list) self.v_layout.setContentsMargins(0, 12, 0, 0) self.add_button.clicked.connect(self.on_add_button_clicked)
[docs] def set_icon(self, scope="assets"): if scope == "assets": self.shot_icon.setPixmap(self.assets_icon) self.add_button.setText("add asset") elif scope == "shots": self.shot_icon.setPixmap(self.shots_icon) self.add_button.setText("add shot")
[docs] def setup(self, mdl): self.data_table.set_item_model(mdl) self.data_table.set_search_box(self.search_box)
[docs] def on_add_button_clicked(self): self.add_clicked.emit()
[docs] def on_show_button_clicked(self): self.show_combos() self.hide_button.show() self.show_button.hide()
[docs] def on_hide_button_clicked(self): self.hide_combos() self.hide_button.hide() self.show_button.show()
[docs] def on_assign_button_clicked(self): self.assign_clicked.emit(self.path_object)
[docs] def set_title(self, new_title): self.title.setText("<h2>Project: %s</h2>" % new_title.title_label())
[docs] class LJListWidget(QtWidgets.QWidget): def __init__( self, label, pixmap, empty_state_text="", empty_state_icon=None, search_box=None ): QtWidgets.QWidget.__init__(self) self.setSizePolicy( QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum ) layout = QtWidgets.QVBoxLayout(self) self.label = QtWidgets.QLabel(label) self.label.setProperty("class", "ultra_title") self.add_button = QtWidgets.QToolButton() self.add_button.setText("+") self.add_button.setProperty("class", "add_button") self.h_layout = QtWidgets.QHBoxLayout() self.search_box = search_box layout.setContentsMargins(0, 0, 0, 0) if pixmap: self.icon = QtWidgets.QLabel() self.icon.setPixmap(pixmap) self.h_layout.addWidget(self.icon) self.h_layout.addWidget(self.label) self.h_layout.addStretch(1) self.h_layout.addWidget(self.add_button) self.list = QtWidgets.QListWidget() self.list.setProperty("class", "basic") self.empty_state = QtWidgets.QPushButton(empty_state_text) if empty_state_icon: self.set_icon(empty_state_icon) self.empty_state.setSizePolicy( QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding, ) self.empty_state.setProperty("class", "empty_state2") self.empty_state.hide() layout.addLayout(self.h_layout) layout.addWidget(self.list) layout.addWidget(self.empty_state)
[docs] def set_icon(self, icon): self.empty_state.setIcon(icon)
[docs] def hide(self): self.label.hide() self.add_button.hide() self.list.hide()
# self.combo.hide()
[docs] def show(self): self.label.show() self.add_button.show() self.list.show()
[docs] class CreateProjectDialog(QtWidgets.QDialog): path_object = None def __init__(self, parent, company, variable): QtWidgets.QDialog.__init__(self, parent=parent) self.variable = variable self.company = company self.project_management = get_task_source() self.proj_management_label = QtWidgets.QLabel("Project Management") layout = QtWidgets.QVBoxLayout(self) self.proj_management_combo = QtWidgets.QComboBox() self.proj_management_combo.addItems( ["magic_browser", "ftrack", "shotgrid", "google_docs"] ) self.red_palette, self.green_palette, self.black_palette = define_palettes() self.server_label = QtWidgets.QLabel("server url:") self.api_key_label = QtWidgets.QLabel("api key:") self.api_user = QtWidgets.QLabel("api user:") self.server_line_edit = QtWidgets.QLineEdit() self.api_key_line_edit = QtWidgets.QLineEdit() self.api_user_line_edit = QtWidgets.QLineEdit() self.cancel_button = QtWidgets.QPushButton("Cancel") self.ok_button = QtWidgets.QPushButton("Ok") self.button = "" button_layout = QtWidgets.QHBoxLayout() button_layout.addStretch(1) button_layout.addWidget(self.cancel_button) button_layout.addWidget(self.ok_button) proj_label = QtWidgets.QLabel("%s Name" % self.variable.title_label()) self.proj_line_edit = QtWidgets.QLineEdit("") self.message = QtWidgets.QLabel() self.grid_layout = QtWidgets.QGridLayout() self.grid_layout.addWidget(proj_label, 0, 0) self.grid_layout.addWidget(self.proj_line_edit, 0, 1) self.grid_layout.addWidget(self.proj_management_label, 2, 0) self.grid_layout.addWidget(self.proj_management_combo, 2, 1) self.grid_layout.addWidget(self.server_label, 3, 0) self.grid_layout.addWidget(self.server_line_edit, 3, 1) self.grid_layout.addWidget(self.api_key_label, 4, 0) self.grid_layout.addWidget(self.api_key_line_edit, 4, 1) self.grid_layout.addWidget(self.api_user, 5, 0) self.grid_layout.addWidget(self.api_user_line_edit, 5, 1) layout.addLayout(self.grid_layout) layout.addWidget(self.message) layout.addLayout(button_layout) self.proj_line_edit.textChanged.connect(self.on_project_text_changed) self.ok_button.clicked.connect(self.on_ok_clicked) self.cancel_button.clicked.connect(self.on_cancel_clicked) self.proj_management_combo.currentIndexChanged.connect(self.on_pm_changed) self.adjust_to_variable() self.set_project_management() self.set_colors()
[docs] def set_colors(self): APP_COLORS = CFG.project_config["colors"] self.setStyleSheet("background: {};".format(APP_COLORS["text"])) self.proj_management_combo.setStyleSheet( "background: {}; color: {};".format( APP_COLORS["secondary"], APP_COLORS["text"] ) )
[docs] def set_project_management(self, proj_man=None): self.proj_management_combo.setCurrentIndex(0) self.hide_api_info()
# if not proj_man: # proj_man = self.project_management # index = self.proj_management_combo.findText(proj_man) # self.proj_management_combo.setCurrentIndex(index)
[docs] def adjust_to_variable(self): if self.variable.lower() == "project": self.setWindowTitle("Create a Project") self.hide_api_info() # self.proj_management_combo.hide() # self.proj_management_label.hide() elif self.variable.lower() == "company": self.setWindowTitle("Create a Company") self.hide_api_info() self.proj_management_combo.show() self.proj_management_label.show()
[docs] def hide_api_info(self): self.server_label.hide() self.api_key_label.hide() self.api_user.hide() self.server_line_edit.hide() self.api_key_line_edit.hide() self.api_user_line_edit.hide()
[docs] def show_api_info(self): self.server_label.show() self.api_key_label.show() self.api_user.show() self.server_line_edit.show() self.api_key_line_edit.show() self.api_user_line_edit.show()
[docs] def on_pm_changed(self): if self.proj_management_combo.currentText() == "magic_browser": self.hide_api_info() else: self.hide_api_info()
[docs] def on_project_text_changed(self): input_text = self.proj_line_edit.text() message = CFG.test_string_against_rules(input_text, self.variable, self.message) if input_text: if message: self.message.setText(message) self.message.setPalette(self.red_palette) else: self.message.setText("Creating %s: %s" % (self.variable, input_text)) else: self.message.setText("")
[docs] def on_ok_clicked(self): d = {} if self.variable.lower() == "project": d = { "company": self.company, "project": self.proj_line_edit.text(), "context": "source", "branch": "master", } elif self.variable.lower() == "company": d = {"company": self.proj_line_edit.text()} self.path_object = path.PathObject().from_dict(d) self.button = "Ok" self.accept()
[docs] def on_cancel_clicked(self): self.accept()
[docs] class AdvComboBoxLabeled(QtWidgets.QVBoxLayout): def __init__(self, label): QtWidgets.QVBoxLayout.__init__(self) self.label = QtWidgets.QLabel("<b>%s</b>" % label)
[docs] class AdvComboBox(QtWidgets.QComboBox): def __init__(self, parent=None, editable=True): super(AdvComboBox, self).__init__(parent) self.user_selected = False self.setFocusPolicy(QtCore.Qt.StrongFocus) self.setEditable(editable) self.SizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents) self.setSizePolicy( QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum ) # add a filter model to filter matching items self.pFilterModel = QtCore.QSortFilterProxyModel(self) self.pFilterModel.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive) self.pFilterModel.setSourceModel(self.model()) # set the indicator icon # add a completer self.completer = QtWidgets.QCompleter(self) # Set the model that the QCompleter uses # - in PySide doing this as a separate step worked better self.completer.setModel(self.pFilterModel) # always show all (filtered) completions self.completer.setCompletionMode(QtWidgets.QCompleter.UnfilteredPopupCompletion) self.setCompleter(self.completer) self.setProperty("class", "basic") self.setMinimumWidth(130) def filter_(text): self.pFilterModel.setFilterFixedString(str(text)) self.lineEdit().textEdited.connect(filter_) self.completer.activated.connect(self.on_completer_activated) # on selection of an item from the completer, select the corresponding item from combobox
[docs] def on_completer_activated(self, text): if text: index = self.findText(str(text)) self.setCurrentIndex(index)
# on model change, update the models of the filter and completer as well
[docs] def setModel(self, model): super(AdvComboBox, self).setModel(model) self.pFilterModel.setSourceModel(model) self.completer.setModel(self.pFilterModel)
# on model column change, update the model column of the filter and completer as well
[docs] def setModelColumn(self, column): self.completer.setCompletionColumn(column) self.pFilterModel.setFilterKeyColumn(column) super(AdvComboBox, self).setModelColumn(column)
[docs] def populate_from_project(self, keys): self.clear() # load the shading/texture assets from the library # clear duplicates obj_list = [] for key in keys: if str(key) not in obj_list: obj_list.append(str(key)) for item in obj_list: self.addItem(item)
[docs] def find_text(self, text): index = self.findText(text) if index != -1: self.setCurrentIndex(index) else: self.setCurrentIndex(0)
[docs] class GifWidget(QtWidgets.QWidget): def __init__(self, parent=None, gif_path=None, animated=True): QtWidgets.QWidget.__init__(self, parent=parent) self.setProperty("class", "gif_widget") self.animated = animated layout = QtWidgets.QHBoxLayout() self.image = QtWidgets.QLabel() self.label_1 = QtWidgets.QLabel("") # QtWidgets.QLabel("Working...") self.label_2 = QtWidgets.QLabel("") self.label_1.setProperty("class", "feedback") self.label_2.setProperty("class", "feedback") self.label_1.setSizePolicy( QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum ) self.label_2.setSizePolicy( QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum ) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) # Create the Actual Gif Thingy if animated: self.gif = QtGui.QMovie(gif_path) self.image.setMovie(self.gif) else: self.gif = QtGui.QPixmap(gif_path) self.image.setPixmap(self.gif) self.gif.setScaledSize(QtCore.QSize(120, 120)) layout.addWidget(self.label_1) layout.addWidget(self.image) layout.addWidget(self.label_2) self.setLayout(layout)
[docs] def start(self): if self.animated: self.show() self.gif.start()
[docs] def stop(self): self.gif.stop() self.hide()
[docs] class LJToolButton(QtWidgets.QToolButton): def __init__( self, svg_path, default_color="black", hover_color="blue", width=40, height=40, parent=None, ): super().__init__(parent) self.svg_path = svg_path self.default_color = QtGui.QColor(default_color) self.hover_color = QtGui.QColor(hover_color) self.icon_size = QtCore.QSize(width, height) self.is_hovered = False # Set the initial icon with the default color self.set_svg_icon_color(self.default_color)
[docs] def set_svg_icon_color(self, color=None): """ Set the SVG icon with the given color. """ if color is None: color = self.default_color # Create a QtSvg.QSvgRenderer to load the SVG file renderer = QSvgRenderer(self.svg_path) # Create a QtGui.QPixmap to render the SVG pixmap = QtGui.QPixmap(self.icon_size) pixmap.fill(QtCore.Qt.transparent) # Start with a transparent pixmap # Create a QPainter to paint on the pixmap painter = QtGui.QPainter(pixmap) # Render the SVG onto the pixmap renderer.render(painter) # Apply the color using CompositionMode_SourceIn painter.setCompositionMode(QtGui.QPainter.CompositionMode_SourceIn) painter.fillRect(pixmap.rect(), color) # Finish painting painter.end() # Set the pixmap as an icon for the button icon = QtGui.QIcon(pixmap) self.setIcon(icon) self.setIconSize(self.icon_size)
[docs] def set_color(self, color): """ Convenience method to change the color of the SVG icon. """ self.set_svg_icon_color(QtGui.QColor(color))
[docs] def enterEvent(self, event): """ Event handler for mouse hover enter. """ self.is_hovered = True self.set_svg_icon_color(self.hover_color) super().enterEvent(event)
[docs] def leaveEvent(self, event): """ Event handler for mouse hover leave. """ self.is_hovered = False self.set_svg_icon_color(self.default_color) super().leaveEvent(event)
[docs] def svg_icon(svg_path, color=None, size=16): """ Set the SVG icon with the given color. """ icon_size = QtCore.QSize(size, size) if color is None: color = self.default_color # Create a QtSvg.QSvgRenderer to load the SVG file renderer = QSvgRenderer(svg_path) # Create a QtGui.QPixmap to render the SVG pixmap = QtGui.QPixmap(icon_size) pixmap.fill(QtCore.Qt.transparent) # Start with a transparent pixmap # Create a QPainter to paint on the pixmap painter = QtGui.QPainter(pixmap) # Render the SVG onto the pixmap renderer.render(painter) # Apply the color using CompositionMode_SourceIn painter.setCompositionMode(QtGui.QPainter.CompositionMode_SourceIn) painter.fillRect(pixmap.rect(), color) # Finish painting painter.end() # Set the pixmap as an icon for the button icon = QtGui.QIcon(pixmap) return icon