def __init__(self, *args, **kwargs): '''Initialise widget.''' super(ThumbnailDropZone, self).__init__(*args, **kwargs) self.setObjectName('ftrack-connect-pipeline-thumbnail-drop-zone') layout = QtWidgets.QHBoxLayout() layout.addSpacing(0) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.setAcceptDrops(True) self.setProperty('ftrackDropZone', True) self._filePath = None self._imageWidth = 200 self._imageHeight = 50 self.thumbnail_button = QtWidgets.QPushButton('Import') self.setDropZoneText() layout.addWidget(self.thumbnail_button, 10) # TODO: Add theme support. removeIcon = QtGui.QIcon(QtGui.QPixmap(':/ftrack/image/light/trash')) self.removeButton = QtWidgets.QPushButton() self.removeButton.setVisible(False) self.removeButton.setFlat(True) self.removeButton.setIcon(removeIcon) self.removeButton.clicked.connect(self.removeThumbnail) layout.addWidget(self.removeButton, 0) self.thumbnail_button.clicked.connect(self.on_button_clicked)
def __init__(self, *args, **kwargs): '''Instantiate the entity selector widget.''' super(EntitySelector, self).__init__(*args, **kwargs) self._entity = None # Create widget used to select an entity. selectionWidget = QtWidgets.QFrame() selectionWidget.setLayout(QtWidgets.QHBoxLayout()) selectionWidget.layout().setContentsMargins(0, 0, 0, 0) self.insertWidget(0, selectionWidget) self.entityBrowser = _entity_browser.EntityBrowser(parent=self) self.entityBrowser.setMinimumSize(600, 400) self.entityBrowser.selectionChanged.connect( self._onEntityBrowserSelectionChanged) self.entityBrowseButton = QtWidgets.QPushButton('Browse') # TODO: Once the link is available through the API change this to a # combo with assigned tasks. self.assignedContextSelector = QtWidgets.QLineEdit() self.assignedContextSelector.setReadOnly(True) selectionWidget.layout().addWidget(self.assignedContextSelector) selectionWidget.layout().addWidget(self.entityBrowseButton) # Create widget used to present current selection. presentationWidget = QtWidgets.QFrame() presentationWidget.setLayout(QtWidgets.QHBoxLayout()) presentationWidget.layout().setContentsMargins(0, 0, 0, 0) self.insertWidget(1, presentationWidget) self.entityPath = _entity_path.EntityPath() presentationWidget.layout().addWidget(self.entityPath) self.discardEntityButton = QtWidgets.QPushButton() removeIcon = QtGui.QIcon(QtGui.QPixmap(':/ftrack/image/light/remove')) self.discardEntityButton.setIconSize(QtCore.QSize(20, 20)) self.discardEntityButton.setIcon(removeIcon) self.discardEntityButton.setFixedWidth(20) self.discardEntityButton.clicked.connect( self._onDiscardEntityButtonClicked) presentationWidget.layout().addWidget(self.discardEntityButton) self.entityChanged.connect(self.entityPath.setEntity) self.entityChanged.connect(self._updateIndex) self.entityBrowseButton.clicked.connect( self._onEntityBrowseButtonClicked)
def __init__(self, parent=None): '''Initialise widget with *parent*''' super(Notification, self).__init__(parent=parent) self._context = defaultdict(list) layout = QtWidgets.QVBoxLayout() toolbar = QtWidgets.QHBoxLayout() self.setLayout(layout) reloadIcon = QtGui.QIcon(QtGui.QPixmap(':/ftrack/image/dark/reload')) self.reloadButton = QtWidgets.QPushButton(reloadIcon, '') self.reloadButton.clicked.connect(self.reload) toolbar.addWidget(QtWidgets.QWidget(), stretch=1) toolbar.addWidget(self.reloadButton, stretch=0) layout.addLayout(toolbar) self._list = NotificationList(self) self._list.setObjectName('notification-list') layout.addWidget(self._list, stretch=1) self.overlay = ftrack_connect.ui.widget.overlay.BusyOverlay( self, message='Loading') self.overlay.hide() self.loadStarted.connect(self._onLoadStarted) self.loadEnded.connect(self._onLoadEnded)
def refresh(self): '''Refresh content.''' layout = self._list_instances_layout general_options = self.publish_asset.get_options() if general_options: settings_widget = self.settings_provider( label=None, options=general_options, store=self.general_options_store) self._list_items_settings_layout.insertWidget(0, settings_widget) items = self.publish_asset.get_publish_items() self.list_items_view = ListItemsWidget(items) self.list_items_view.itemChanged.connect(self.on_selection_changed) scene_select_button = QtWidgets.QPushButton('Scene selection') scene_select_button.clicked.connect(self._on_sync_scene_selection) layout.addWidget(scene_select_button) layout.addWidget(self.list_items_view, stretch=0) for item in items: if item.get('value') is True: self.add_instance_settings(item) self.list_items_view.setFocus()
def __init__(self, currentEntity, parent=None): '''Initialise with the *currentEntity* and *parent* widget.''' super(ContextSelector, self).__init__(parent=parent) self.setObjectName('context-selector-widget') self._entity = currentEntity self.entityBrowser = EntityBrowser() self.entityBrowser.setMinimumWidth(600) self.entityPath = EntityPath() self.entityBrowseButton = QtWidgets.QPushButton('Change') self.entityBrowseButton.setFixedWidth(110) self.entityBrowseButton.setFixedHeight(35) layout = QtWidgets.QHBoxLayout() layout.setContentsMargins(10, 0, 10, 0) self.setMinimumHeight(50) self.setLayout(layout) layout.addWidget(self.entityPath) layout.addWidget(self.entityBrowseButton) self.entityBrowseButton.clicked.connect( self._onEntityBrowseButtonClicked ) self.entityChanged.connect(self.entityPath.setEntity) self.entityBrowser.selectionChanged.connect( self._onEntityBrowserSelectionChanged ) self.setEntity(self._entity)
def __init__(self, *args, **kwargs): '''Initialise DataDropZone widget.''' super(DataDropZone, self).__init__(*args, **kwargs) self.log = logging.getLogger(__name__ + '.' + self.__class__.__name__) self.setAcceptDrops(True) self.setObjectName('ftrack-connect-publisher-browse-button') self.setProperty('ftrackDropZone', True) layout = QtWidgets.QVBoxLayout() self.setLayout(layout) bottomCenterAlignment = QtCore.Qt.AlignBottom | QtCore.Qt.AlignHCenter topCenterAlignment = QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter self._label = QtWidgets.QLabel('Drop files here or') layout.addWidget(self._label, alignment=bottomCenterAlignment) self._browseButton = QtWidgets.QPushButton('Browse') self._browseButton.setToolTip('Browse for file(s).') layout.addWidget(self._browseButton, alignment=topCenterAlignment) self._setupConnections() homeFolder = os.path.expanduser('~') if os.path.isdir(homeFolder): self._currentLocation = homeFolder
def __init__(self, parent=None): '''Initiate chat widget with *chatHub*.''' super(Chat, self).__init__(parent) self.setLayout(QtWidgets.QVBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(0) self.setObjectName('chat-widget') self._chatFeed = Feed(parent) self.layout().addWidget(self._chatFeed, stretch=1) self._messageArea = ChatTextEdit(self) self._messageArea.setMinimumHeight(30) self._messageArea.setMaximumHeight(75) self._messageArea.returnPressed.connect(self.onReturnPressed) self.layout().addWidget(self._messageArea, stretch=0) self._sendMessageButton = QtWidgets.QPushButton('Submit') self.layout().addWidget(self._sendMessageButton, stretch=0) self._sendMessageButton.clicked.connect(self.onReturnPressed) self.busyOverlay = ftrack_connect.ui.widget.overlay.BusyOverlay( self, message='Loading') self.hideOverlay()
def create_overlay_widgets(self, congrat_text, success_text): '''Create overlay widgets to report publish result.''' self.activeWidget = QtWidgets.QWidget() self.activeWidget.setLayout(QtWidgets.QVBoxLayout()) self.layout().addWidget(self.activeWidget) main_layout = self.activeWidget.layout() icon = QtGui.QPixmap(':ftrack/image/default/ftrackLogoLabelNew') icon = icon.scaled(QtCore.QSize(85, 85), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) self.ftrack_icon = QtWidgets.QLabel() self.ftrack_icon.setPixmap(icon) main_layout.addStretch(1) main_layout.insertWidget(1, self.ftrack_icon, alignment=QtCore.Qt.AlignCenter) congrat_label = QtWidgets.QLabel(congrat_text) congrat_label.setAlignment(QtCore.Qt.AlignCenter) success_label = QtWidgets.QLabel(success_text) success_label.setAlignment(QtCore.Qt.AlignCenter) main_layout.addWidget(congrat_label) main_layout.addWidget(success_label) main_layout.addStretch(1) buttons_layout = QtWidgets.QHBoxLayout() main_layout.addLayout(buttons_layout) self.details_button = QtWidgets.QPushButton('Details') buttons_layout.addWidget(self.details_button) self.details_button.clicked.connect(self.on_show_details) if self.details_window_callback is None: self.details_button.setDisabled(True) self.open_in_ftrack = QtWidgets.QPushButton('Open in ftrack') buttons_layout.addWidget(self.open_in_ftrack) self.open_in_ftrack.clicked.connect(self.on_open_in_ftrack) if self.asset_version is None: self.open_in_ftrack.setDisabled(True)
def __init__(self, parent, message=''): super(PublisherBlockingOverlay, self).__init__(parent, message=message) self.confirmButton = QtWidgets.QPushButton('Ok') self.contentLayout.insertWidget(3, self.confirmButton, alignment=QtCore.Qt.AlignCenter, stretch=0) self.confirmButton.hide() self.confirmButton.clicked.connect(self.hide) self.content.setMinimumWidth(350)
def __init__( self, parent, icon=':ftrack/image/default/ftrackLogoColor' ): super(AboutDialog, self).__init__(parent) layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(20, 20, 20, 20) layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize) self.setLayout(layout) self.icon = QtWidgets.QLabel() pixmap = QtGui.QPixmap(icon) self.icon.setPixmap( pixmap.scaledToHeight(36, mode=QtCore.Qt.SmoothTransformation) ) self.icon.setAlignment(QtCore.Qt.AlignCenter) layout.addWidget(self.icon) self.messageLabel = QtWidgets.QLabel() self.messageLabel.setWordWrap(True) self.messageLabel.setAlignment(QtCore.Qt.AlignLeft) layout.addWidget(self.messageLabel) layout.addSpacing(25) self.debugButton = QtWidgets.QPushButton('More info') self.debugButton.clicked.connect(self._onDebugButtonClicked) layout.addWidget(self.debugButton) self.loggingButton = QtWidgets.QPushButton('Open log directory') self.loggingButton.clicked.connect(self._onLoggingButtonClicked) layout.addWidget(self.loggingButton) self.debugTextEdit = QtWidgets.QTextEdit() self.debugTextEdit.setReadOnly(True) self.debugTextEdit.setFontPointSize(10) self.debugTextEdit.hide() layout.addWidget(self.debugTextEdit)
def __init__(self, parent, message='Processing'): '''Initialise with *parent* and busy *message*.''' super(CancelOverlay, self).__init__(parent, message=message) self.contentLayout.addSpacing(10) loginButton = QtWidgets.QPushButton(text='Cancel') loginButton.clicked.connect(self.hide) self.contentLayout.addWidget( loginButton, alignment=QtCore.Qt.AlignCenter )
def __init__(self, title=None, description=None, data=None, parent=None): '''Initialise time log. *title* should be the title entry to display for the time log whilst *description* can provide an optional longer description. *data* is optional data that can be stored for future reference (for example a link to an ftrack task that the time log represents). *parent* should be the optional parent of this widget. ''' super(TimeLog, self).__init__(parent=parent) self.setObjectName('time-log') self._data = None layout = QtWidgets.QHBoxLayout() self.setLayout(layout) self.labelLayout = QtWidgets.QVBoxLayout() layout.addLayout(self.labelLayout, stretch=1) self.titleLabel = ftrack_connect.ui.widget.label.Label() self.titleLabel.setProperty('title', True) self.labelLayout.addWidget(self.titleLabel) self.descriptionLabel = ftrack_connect.ui.widget.label.Label() self.labelLayout.addWidget(self.descriptionLabel) # TODO: Add theme support. playIcon = QtGui.QIcon( QtGui.QPixmap(':/ftrack/image/light/play') ) self.playButton = QtWidgets.QPushButton(playIcon, '') self.playButton.setFlat(True) self.playButton.clicked.connect(self._onPlayButtonClicked) layout.addWidget(self.playButton) self.setSizePolicy( QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed ) # Set initial values. self.setValue({ 'title': title, 'description': description, 'data': data })
def __init__(self, *args, **kwargs): '''Instantiate the time tracker.''' super(TimeTracker, self).__init__(*args, **kwargs) self.setObjectName('timeTracker') self._activeEntity = None layout = QtWidgets.QVBoxLayout() self.setLayout(layout) self.activeLabel = QtWidgets.QLabel('Currently running') self.activeLabel.setProperty('title', True) layout.addWidget(self.activeLabel) self._timerEnabled = False self.timer = ftrack_connect.ui.widget.timer.Timer() layout.addWidget(self.timer) self.timerPlaceholder = TimerOverlay(self.timer) # TODO: Add theme support. reloadIcon = QtGui.QIcon(QtGui.QPixmap(':/ftrack/image/light/reload')) assignedTimeLogUpdateButton = QtWidgets.QPushButton(reloadIcon, '') assignedTimeLogUpdateButton.setFlat(True) assignedTimeLogUpdateButton.setToolTip('Refresh list') assignedTimeLogUpdateButton.clicked.connect(self._updateAssignedList) self.assignedTimeLogList = _TimeLogList( title='Assigned', headerWidgets=[assignedTimeLogUpdateButton]) layout.addWidget(self.assignedTimeLogList, stretch=1) # Connect events. self.timer.stopped.connect(self._onCommitTime) self.timer.timeEdited.connect(self._onCommitTime) self.assignedTimeLogList.itemSelected.connect(self._onSelectTimeLog) self.blockingOverlay = TimeTrackerBlockingOverlay( self, 'Time tracker is currently disabled during beta.') self.blockingOverlay.show() self._updateAssignedList()
def __init__(self, results): '''Instantiate and show results.''' super(Dialog, self).__init__() self.setObjectName('ftrack-result-dialog') self.setMinimumSize(1080, 720) main_layout = QtWidgets.QVBoxLayout(self) self.setLayout(main_layout) filter_layout = QtWidgets.QHBoxLayout() filter_label = QtWidgets.QLabel('Filter log') self.filter_field = QtWidgets.QLineEdit() self.filter_field.setObjectName('ftrack-log-filter-field') self.filter_field.textChanged.connect(self.on_search) filter_layout.addWidget(filter_label) filter_layout.addWidget(self.filter_field) main_layout.addLayout(filter_layout) log_list = QtWidgets.QTableView() log_list.verticalHeader().hide() log_list.setObjectName('ftrack-log-view') log_list.setAlternatingRowColors(True) log_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) log_list.horizontalHeader().setStretchLastSection(True) log_items = self._parse_results(results) log_model = ftrack_connect_pipeline.ui.model.log_table.LogTableModel( self, log_items) self.log_sort_model = ftrack_connect_pipeline.ui.model.log_table.FilterProxyModel( ) self.log_sort_model.setDynamicSortFilter(True) self.log_sort_model.setSourceModel(log_model) log_list.setModel(self.log_sort_model) main_layout.addWidget(log_list) open_log_folder_button = QtWidgets.QPushButton('Open log directory') open_log_folder_button.clicked.connect(self._on_logging_button_clicked) main_layout.addWidget(open_log_folder_button)
def __init__(self, currentEntity, parent=None): '''Initialise with the *currentEntity* and *parent* widget.''' super(ContextSelector, self).__init__(parent=parent) self._entity = currentEntity self.entityBrowser = entityBrowser.EntityBrowser() self.entityBrowser.setMinimumWidth(600) self.entityPath = entityPath.EntityPath() self.entityBrowseButton = QtWidgets.QPushButton('Browse') applyTheme(self.entityBrowser, 'integration') layout = QtWidgets.QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) layout.addWidget(self.entityPath) layout.addWidget(self.entityBrowseButton) self.entityBrowseButton.clicked.connect( self._onEntityBrowseButtonClicked) self.entityChanged.connect(self.entityPath.setEntity) self.entityBrowser.selectionChanged.connect( self._onEntityBrowserSelectionChanged)
def build(self): '''Build widgets and layout.''' self.setLayout(QtWidgets.QVBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.optionsLayout = QtWidgets.QHBoxLayout() self.assetTypeSelector = QtWidgets.QComboBox() self.optionsLayout.addWidget(self.assetTypeSelector) self.refreshButton = QtWidgets.QPushButton(self.tr('Refresh')) self.optionsLayout.addWidget(self.refreshButton) self.optionsLayout.addStretch(1) self.layout().addLayout(self.optionsLayout) self.assetTable = QtWidgets.QTableWidget() self.assetTable.setEditTriggers( QtWidgets.QAbstractItemView.NoEditTriggers) self.assetTable.setSelectionMode( QtWidgets.QAbstractItemView.SingleSelection) self.assetTable.setSelectionBehavior( QtWidgets.QAbstractItemView.SelectRows) self.assetTable.setColumnCount(len(self.assetTableColumns)) self.assetTable.setRowCount(0) self.assetTable.verticalHeader().hide() self.assetTable.setHorizontalHeaderLabels(self.assetTableColumns) horizontalHeader = self.assetTable.horizontalHeader() horizontalHeader.setResizeMode(QtWidgets.QHeaderView.Fixed) self.assetTable.horizontalHeader().setDefaultSectionSize(100) self.assetTable.setColumnWidth(1, 63) self.assetTable.horizontalHeader().setResizeMode( 0, QtWidgets.QHeaderView.Stretch) self.layout().addWidget(self.assetTable)
def _construct(self): '''Construct widget.''' self.setLayout(QtWidgets.QVBoxLayout()) self.headerLayout = QtWidgets.QHBoxLayout() self.navigationBar = QtWidgets.QTabBar() self.navigationBar.setExpanding(False) self.navigationBar.setDrawBase(False) self.headerLayout.addWidget(self.navigationBar, stretch=1) self.navigateUpButton = QtWidgets.QToolButton() self.navigateUpButton.setObjectName('entity-browser-up-button') self.navigateUpButton.setIcon( QtGui.QIcon(':ftrack/image/light/upArrow') ) self.navigateUpButton.setToolTip('Navigate up a level.') self.headerLayout.addWidget(self.navigateUpButton) self.reloadButton = QtWidgets.QToolButton() self.reloadButton.setObjectName('entity-browser-reload-button') self.reloadButton.setIcon( QtGui.QIcon(':ftrack/image/light/reload') ) self.reloadButton.setToolTip('Reload listing from server.') self.headerLayout.addWidget(self.reloadButton) self.layout().addLayout(self.headerLayout) self.contentSplitter = QtWidgets.QSplitter() self.bookmarksList = QtWidgets.QListView() self.contentSplitter.addWidget(self.bookmarksList) self.view = QtWidgets.QTableView() self.view.setSelectionBehavior(self.view.SelectRows) self.view.setSelectionMode(self.view.SingleSelection) self.view.verticalHeader().hide() self.contentSplitter.addWidget(self.view) proxy = ftrack_connect_pipeline.ui.model.entity_tree.EntityTreeProxyModel(self) model = ftrack_connect_pipeline.ui.model.entity_tree.EntityTreeModel( root=ftrack_connect_pipeline.ui.model.entity_tree.ItemFactory( self._session, self._root ), parent=self ) proxy.setSourceModel(model) proxy.setDynamicSortFilter(True) self.view.setModel(proxy) self.view.setSortingEnabled(True) self.contentSplitter.setStretchFactor(1, 1) self.layout().addWidget(self.contentSplitter) self.footerLayout = QtWidgets.QHBoxLayout() self.footerLayout.addStretch(1) self.cancelButton = QtWidgets.QPushButton('Cancel') self.footerLayout.addWidget(self.cancelButton) self.acceptButton = QtWidgets.QPushButton('Choose') self.footerLayout.addWidget(self.acceptButton) self.layout().addLayout(self.footerLayout) self.overlay = ftrack_connect_pipeline.ui.widget.overlay.BusyOverlay( self.view, message='Loading' )
def refreshAssetManager(self): '''Refresh assets in asset manager.''' assets = self.connector.getAssets() self.ui.AssertManagerTableWidget.setSortingEnabled(False) self.ui.AssertManagerTableWidget.setRowCount(0) self.ui.AssertManagerTableWidget.setRowCount(len(assets)) component_ids = [] for component_id, _ in assets: if component_id: component_ids.append(component_id) if component_ids: query_string = ( 'select name, version.asset.type.short, version.asset.name, ' 'version.asset.type.name, version.asset.versions.version, ' 'version.id, version.version, version.asset.versions, ' 'version.date, version.comment, version.asset.name, version, ' 'version_id, version.user.first_name, version.user.last_name ' 'from Component where id in ({0})'.format( ','.join(component_ids))) components = self.connector.session.query(query_string).all() asset_ids = set() for component in components: asset_ids.add(component['version']['asset']['id']) if asset_ids: # Because of bug in 3.3.X backend we need to divide the query. The # memory cache will allow using entities without caring about this. preload_string = ( 'select components.name from AssetVersion where ' 'asset_id in ({0})').format(', '.join(list(asset_ids))) self.connector.session.query(preload_string).all() component_map = dict( (component['id'], component) for component in components) else: component_map = {} for i in range(len(assets)): if assets[i][0]: component = component_map[assets[i][0]] asset_version = component['version'] componentNameStr = component['name'] assetVersionNr = asset_version['version'] asset = asset_version['asset'] asset_versions_with_same_component_name = [] for related_version in asset['versions']: for other_component in related_version['components']: if other_component['name'] == componentNameStr: asset_versions_with_same_component_name.append( related_version) asset_versions_with_same_component_name = sorted( asset_versions_with_same_component_name, key=lambda x: x['version']) latest_version_number = ( asset_versions_with_same_component_name[-1]['version']) versionIndicatorButton = QtWidgets.QPushButton('') if assetVersionNr == latest_version_number: versionIndicatorButton.setStyleSheet(''' QPushButton { background-color: #1CBC90; border: none; } ''') self.connector.setNodeColor(applicationObject=assets[i][1], latest=True) else: versionIndicatorButton.setStyleSheet(''' QPushButton { background-color: #E36316; border: none; } ''') self.connector.setNodeColor(applicationObject=assets[i][1], latest=False) self.ui.AssertManagerTableWidget.setCellWidget( i, 0, versionIndicatorButton) componentName = QtWidgets.QTableWidgetItem(componentNameStr) self.ui.AssertManagerTableWidget.setItem(i, 1, componentName) componentId = QtWidgets.QTableWidgetItem(component['id']) self.ui.AssertManagerTableWidget.setItem(i, 2, componentId) assetType = QtWidgets.QTableWidgetItem(asset['type']['short']) self.ui.AssertManagerTableWidget.setItem(i, 3, assetType) assetTypeLong = QtWidgets.QTableWidgetItem( asset['type']['name']) self.ui.AssertManagerTableWidget.setItem(i, 4, assetTypeLong) versionNumberComboBox = QtWidgets.QComboBox() for version in reversed( asset_versions_with_same_component_name): versionNumberComboBox.addItem(str(version['version'])) conName = self.connector.getConnectorName() if conName in self.notVersionable: if componentNameStr in self.notVersionable[conName]: versionNumberComboBox.setEnabled(False) result = versionNumberComboBox.findText(str(assetVersionNr)) versionNumberComboBox.setCurrentIndex(result) self.ui.AssertManagerTableWidget.setCellWidget( i, 5, versionNumberComboBox) versionNumberComboBox.currentIndexChanged.connect( self.changeVersion) latestVersionNumberWidget = QtWidgets.QTableWidgetItem( str(latest_version_number)) self.ui.AssertManagerTableWidget.setItem( i, 6, latestVersionNumberWidget) assetName = QtWidgets.QTableWidgetItem(asset['name']) assetName.setToolTip(asset['name']) self.ui.AssertManagerTableWidget.setItem(i, 7, assetName) assetNameInScene = QtWidgets.QTableWidgetItem(assets[i][1]) assetNameInScene.setToolTip(assets[i][1]) self.ui.AssertManagerTableWidget.setItem( i, 8, assetNameInScene) selectButton = QtWidgets.QPushButton('S') selectButton.setToolTip('Select asset in scene') self.ui.AssertManagerTableWidget.setCellWidget( i, 9, selectButton) selectButton.clicked.connect(self.signalMapperSelect.map) self.signalMapperSelect.setMapping(selectButton, assets[i][1]) replaceButton = QtWidgets.QPushButton('R') self.ui.AssertManagerTableWidget.setCellWidget( i, 10, replaceButton) removeButton = QtWidgets.QPushButton() removeButton.setToolTip('Remove asset from scene') icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(':ftrack/image/integration/trash'), QtGui.QIcon.Normal, QtGui.QIcon.Off) removeButton.setIcon(icon) self.ui.AssertManagerTableWidget.setCellWidget( i, 11, removeButton) removeButton.clicked.connect(self.signalMapperRemove.map) self.signalMapperRemove.setMapping(removeButton, assets[i][1]) assetId = QtWidgets.QTableWidgetItem(str(asset['id'])) self.ui.AssertManagerTableWidget.setItem(i, 12, assetId) assetVersionId = QtWidgets.QTableWidgetItem( str(asset_version['id'])) self.ui.AssertManagerTableWidget.setItem(i, 13, assetVersionId) currentVersionFallback = QtWidgets.QTableWidgetItem( str(assetVersionNr)) self.ui.AssertManagerTableWidget.setItem( i, 14, currentVersionFallback) commentButton = QtWidgets.QPushButton() commentButton.setText('') icon = QtGui.QIcon() icon.addPixmap( QtGui.QPixmap(':ftrack/image/integration/comment'), QtGui.QIcon.Normal, QtGui.QIcon.Off) commentButton.setIcon(icon) fullUserName = (asset_version['user']['first_name'] + ' ' + asset_version['user']['last_name']) pubDate = str(asset_version['date']) comment = asset_version['comment'] tooltipText = '\n'.join([fullUserName, pubDate, comment]) commentButton.setToolTip(tooltipText) self.ui.AssertManagerTableWidget.setCellWidget( i, 15, commentButton) commentButton.clicked.connect(self.signalMapperComment.map) self.signalMapperComment.setMapping(commentButton, str(asset_version['id'])) commentButton.setEnabled(has_webwidgets) self.ui.AssertManagerTableWidget.setHorizontalHeaderLabels( self.columnHeaders)
def onActionButtonClicked(self, row): '''Handle transfer request.''' column = self.columns.index actionItem = self.cellWidget(row, column('Action')) # TODO: Make more robust test. if actionItem.text() == 'Import': self.importComponentSignal.emit(row) elif actionItem.text() == 'Transfer': locationItem = self.cellWidget(row, column('Location')) locationItem.setEnabled(False) location = locationItem.itemData(locationItem.currentIndex()) componentItem = self.item(row, column('Component')) component_id = componentItem.data(self.COMPONENT_ROLE) ftrack_component = self.session.get('Component', component_id) # Unfortunately, this will destroy the push button, so have to # recreate it afterwards. If Qt adds a takeCellWidget this can be # improved. transferProgressItem = QtWidgets.QProgressBar() transferProgressItem.setTextVisible(False) self.setCellWidget(row, self.columns.index('Action'), transferProgressItem) transferProgressItem.setRange(0, 0) try: worker = Worker( self.transfer, [ftrack_component, None, location], parent=self ) worker.start() while worker.isRunning(): app = QtWidgets.QApplication.instance() app.processEvents() if worker.error: raise worker.error[1], None, worker.error[2] except Exception as error: traceback.print_exc() QtWidgets.QMessageBox.critical( None, 'Transfer Failed', 'Could not transfer to location!' '\n{0}'.format(error) ) finally: transferProgressItem.setMaximum(1) transferProgressItem.reset() locationItem.setEnabled(True) # Have to recreate action button actionItem = QtWidgets.QPushButton() self.setCellWidget(row, column('Action'), actionItem) actionItem.clicked.connect(self.actionSignalMapper.map) self.actionSignalMapper.setMapping(actionItem, row) self.onLocationSelected(row)
def setAssetVersion(self, assetVersionId): '''Update list of components for asset version with *assetVersionId*.''' self.clear() query = ( 'select id, asset, asset.type, asset.type.short, components' ' from AssetVersion where id is "{0}"'.format(assetVersionId) ) asset_version = self.session.query(query).one() self.assetType = asset_version['asset']['type']['short'] asset_version_components = asset_version['components'] connectorName = self.connector.getConnectorName() # Temporary alias column = self.columns.index for component in asset_version_components: componentName = component['name'] if ( connectorName == 'nuke' and 'proxy' in componentName ): pass else: rowCount = self.rowCount() self.insertRow(rowCount) componentItem = QtWidgets.QTableWidgetItem(componentName) componentItem.setData(self.COMPONENT_ROLE, component['id']) self.setItem( rowCount, column('Component'), componentItem ) pathItem = QtWidgets.QTableWidgetItem('') self.setItem(rowCount, column('Path'), pathItem) availabilityItem = QtWidgets.QTableWidgetItem('') self.setItem( rowCount, column('Availability'), availabilityItem ) actionItem = QtWidgets.QPushButton() self.setCellWidget(rowCount, column('Action'), actionItem) actionItem.clicked.connect(self.actionSignalMapper.map) self.actionSignalMapper.setMapping(actionItem, rowCount) locationItem = QtWidgets.QComboBox() self.setCellWidget(rowCount, column('Location'), locationItem) # Map version widget to row number to enable simple lookup locationItem.currentIndexChanged[int].connect( self.locationSignalMapper.map ) self.locationSignalMapper.setMapping( locationItem, rowCount ) available_locations = [] for location in self.locations: accessor = location.accessor # Don't show inaccessible locations if accessor is symbol.NOT_SET: continue name = location['name'] location_id = location['id'] locationItem.addItem(name, location_id) available_locations.append(location) picked_location = self.session.pick_location(component) try: location_index = available_locations.index(picked_location) except ValueError: location_index = 0 locationItem.setCurrentIndex(location_index)
def __init__(self, label, description, publish_asset, session, settings_provider=None, parent=None): '''Display instances that can be published.''' super(Workflow, self).__init__() self.setObjectName('ftrack-workflow-widget') self.session = session self._label_text = label self.publish_asset = publish_asset plugin = ftrack_connect_pipeline.get_plugin() plugin_information = plugin.get_plugin_information() event_metadata = { 'workflow_label': self._label_text, } if isinstance(plugin_information, dict): event_metadata.update(plugin_information) send_usage('USED-FTRACK-CONNECT-PIPELINE-PUBLISH', event_metadata) self.publish_asset.prepare_publish() self.item_options_store = {} self.general_options_store = {} self.settings_provider = settings_provider if self.settings_provider is None: self.settings_provider = BaseSettingsProvider() self.settings_map = {} list_instances_widget = QtWidgets.QFrame() list_instances_widget.setObjectName('ftrack-instances-widget') self._list_instances_layout = QtWidgets.QVBoxLayout() list_instances_widget.setLayout(self._list_instances_layout) self._list_instances_layout.setContentsMargins(5, 5, 5, 5) list_instance_settings_widget = QtWidgets.QFrame() list_instance_settings_widget.setObjectName( 'ftrack-instances-settings-widget') self._list_items_settings_layout = QtWidgets.QVBoxLayout() self._list_items_settings_layout.addStretch(1) list_instance_settings_widget.setLayout( self._list_items_settings_layout) self._list_items_settings_layout.setContentsMargins(5, 5, 5, 5) configuration_layout = QtWidgets.QHBoxLayout() configuration_layout.addWidget(list_instances_widget, stretch=1) configuration_layout.addWidget(list_instance_settings_widget, stretch=1) configuration = QtWidgets.QFrame() configuration.setObjectName('ftrack-configuration-widget') configuration.setLayout(configuration_layout) configuration_layout.setContentsMargins(0, 0, 0, 0) information_layout = QtWidgets.QHBoxLayout() information_layout.addWidget( QtWidgets.QLabel('<h3>{0}</h3>'.format(self._label_text))) information_layout.addWidget(QtWidgets.QLabel( '<i>{0}</i>'.format(description)), stretch=1) information = QtWidgets.QFrame() information.setObjectName('ftrack-information-widget') information.setLayout(information_layout) information_layout.setContentsMargins(0, 0, 0, 0) publish_button = QtWidgets.QPushButton('Publish') publish_button.clicked.connect(self.on_publish_clicked) main_layout = QtWidgets.QVBoxLayout(self) self.setLayout(main_layout) self.layout().setContentsMargins(0, 0, 0, 0) scroll = QtWidgets.QScrollArea(self) scroll.setWidgetResizable(True) scroll.setLineWidth(0) scroll.setFrameShape(QtWidgets.QFrame.NoFrame) scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) scroll.setWidget(configuration) self._list_instances_layout.addWidget(information) main_layout.addWidget(scroll, stretch=1) self._list_items_settings_layout.addWidget(publish_button) self._publish_overlay = BusyOverlay(self, message='Publishing Assets...') self._publish_overlay.setStyleSheet(OVERLAY_DARK_STYLE) self._publish_overlay.setVisible(False) self.result_win = PublishResult(self.session, self) self.result_win.setStyleSheet(OVERLAY_DARK_STYLE) self.result_win.setVisible(False) self.refresh()
def __init__(self, session, parent): '''Instantiate with *session*.''' super(CreateAssetTypeOverlay, self).__init__(parent=parent) self.session = session self.main_layout = QtWidgets.QVBoxLayout() self.setLayout(self.main_layout) icon = QtGui.QPixmap(':ftrack/image/default/ftrackLogoColor') icon = icon.scaled(QtCore.QSize(85, 85), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) self.ftrack_icon = QtWidgets.QLabel() self.ftrack_icon.setPixmap(icon) self.main_layout.addStretch(1) self.main_layout.insertWidget(1, self.ftrack_icon, alignment=QtCore.Qt.AlignCenter) self.main_layout.addStretch(1) self.main_layout.setContentsMargins(20, 20, 20, 20) # create asset type widget self.create_asset_widget = QtWidgets.QFrame() self.create_asset_widget.setVisible(False) create_asset_layout = QtWidgets.QVBoxLayout() create_asset_layout.setContentsMargins(20, 20, 20, 20) create_asset_layout.addStretch(1) buttons_layout = QtWidgets.QHBoxLayout() self.create_asset_widget.setLayout(create_asset_layout) self.create_asset_label_top = QtWidgets.QLabel() self.create_asset_label_bottom = QtWidgets.QLabel( '<h4>Do you want to create one ?</h4>') create_asset_layout.insertWidget(1, self.create_asset_label_top, alignment=QtCore.Qt.AlignCenter) create_asset_layout.insertWidget(2, self.create_asset_label_bottom, alignment=QtCore.Qt.AlignCenter) self.create_asset_button = QtWidgets.QPushButton('Create') self.cancel_asset_button = QtWidgets.QPushButton('Cancel') create_asset_layout.addLayout(buttons_layout) buttons_layout.addWidget(self.create_asset_button) buttons_layout.addWidget(self.cancel_asset_button) # result create asset type self.create_asset_widget_result = QtWidgets.QFrame() self.create_asset_widget_result.setVisible(False) create_asset_layout_result = QtWidgets.QVBoxLayout() create_asset_layout_result.setContentsMargins(20, 20, 20, 20) create_asset_layout_result.addStretch(1) self.create_asset_widget_result.setLayout(create_asset_layout_result) self.create_asset_label_result = QtWidgets.QLabel() self.continue_button = QtWidgets.QPushButton('Continue') create_asset_layout_result.insertWidget( 1, self.create_asset_label_result, alignment=QtCore.Qt.AlignCenter) create_asset_layout_result.insertWidget( 2, self.continue_button, alignment=QtCore.Qt.AlignCenter) # error on create asset self.create_asset_widget_error = QtWidgets.QFrame() self.create_asset_widget_error.setVisible(False) create_asset_layout_error = QtWidgets.QVBoxLayout() create_asset_layout_error.setContentsMargins(20, 20, 20, 20) create_asset_layout_error.addStretch(1) self.create_asset_widget_error.setLayout(create_asset_layout_error) self.create_asset_label_error = QtWidgets.QLabel() self.close_button = QtWidgets.QPushButton('Close') create_asset_layout_error.insertWidget(1, self.create_asset_label_error, alignment=QtCore.Qt.AlignCenter) create_asset_layout_error.insertWidget(2, self.close_button, alignment=QtCore.Qt.AlignCenter) # parent all. self.main_layout.addWidget(self.create_asset_widget) self.main_layout.addWidget(self.create_asset_widget_result) self.main_layout.addWidget(self.create_asset_widget_error) self.main_layout.addStretch(1) # signals self.create_asset_button.clicked.connect(self.on_create_asset) self.continue_button.clicked.connect(self.on_continue) self.close_button.clicked.connect(self.on_fail) self.cancel_asset_button.clicked.connect(self.on_fail)
def __init__(self, parent=None, connector=None): '''Instantiate widget with *connector*.''' if not connector: raise ValueError( 'Please provide a connector object for {0}'.format( self.__class__.__name__)) super(FtrackImportAssetDialog, self).__init__(parent=parent) applyTheme(self, 'integration') #---------------------------------------------------------------------------# # Add for proper hou colors try: import hou self.stylesheet = '%s; background-color: #3a3a3a; color: #FFFFFF;' % hou.qt.styleSheet( ) self.setStyleSheet(self.stylesheet) except: pass #---------------------------------------------------------------------------# self.connector = connector self.currentEntity = ftrack.Task( os.getenv('FTRACK_TASKID', os.getenv('FTRACK_SHOTID'))) self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.setMinimumWidth(600) self.mainLayout = QtWidgets.QVBoxLayout(self) self.setLayout(self.mainLayout) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.scrollArea = QtWidgets.QScrollArea(self) self.mainLayout.addWidget(self.scrollArea) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollArea.setLineWidth(0) self.scrollArea.setFrameShape(QtWidgets.QFrame.NoFrame) self.scrollArea.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) self.mainWidget = QtWidgets.QWidget(self) self.scrollArea.setWidget(self.mainWidget) self.verticalLayout = QtWidgets.QVBoxLayout() self.mainWidget.setLayout(self.verticalLayout) self.headerWidget = header.Header(getpass.getuser(), self) self.verticalLayout.addWidget(self.headerWidget, stretch=0) self.browseTasksWidget = ContextSelector( currentEntity=self.currentEntity, parent=self) self.verticalLayout.addWidget(self.browseTasksWidget, stretch=0) self.listAssetsTableWidget = ListAssetsTableWidget(self) self.verticalLayout.addWidget(self.listAssetsTableWidget, stretch=4) # Horizontal line self.divider = QtWidgets.QFrame() self.divider.setFrameShape(QtWidgets.QFrame.HLine) self.divider.setFrameShadow(QtWidgets.QFrame.Sunken) self.divider.setLineWidth(2) self.verticalLayout.addWidget(self.divider) self.assetVersionDetailsWidget = AssetVersionDetailsWidget( self, connector=self.connector) self.verticalLayout.addWidget(self.assetVersionDetailsWidget, stretch=0) self.componentTableWidget = ComponentTableWidget( self, connector=self.connector) self.verticalLayout.addWidget(self.componentTableWidget, stretch=3) self.horizontalLayout = QtWidgets.QHBoxLayout() self.verticalLayout.addLayout(self.horizontalLayout) self.importAllButton = QtWidgets.QPushButton("Import All") self.importAllButton.setFixedWidth(120) self.importAllButton.setObjectName('ftrack-import-btn') self.importSelectedButton = QtWidgets.QPushButton("Import Selected") self.importSelectedButton.setFixedWidth(120) self.importAllButton.setObjectName('ftrack-import-btn') self.horizontalLayout.addWidget(self.importSelectedButton) self.horizontalLayout.addWidget(self.importAllButton) self.horizontalLayout.setAlignment(QtCore.Qt.AlignRight) self.importOptionsWidget = ImportOptionsWidget( parent=self, connector=self.connector) self.verticalLayout.addWidget(self.importOptionsWidget, stretch=0) self.messageLabel = QtWidgets.QLabel(self) self.messageLabel.setText(' \n ') self.verticalLayout.addWidget(self.messageLabel, stretch=0) self.setObjectName('ftrackImportAsset') self.setWindowTitle("ftrackImportAsset") panelComInstance = PanelComInstance.instance() panelComInstance.addSwitchedShotListener(self.reset_context_browser) self.browseTasksWidget.entityChanged.connect(self.clickedIdSignal) self.importAllButton.clicked.connect(self.importAllComponents) self.importSelectedButton.clicked.connect( self.importSelectedComponents) self.listAssetsTableWidget.assetVersionSelectedSignal[str].connect( self.clickedAssetVSignal) self.listAssetsTableWidget.assetTypeSelectedSignal[str].connect( self.importOptionsWidget.setStackedWidget) self.importSignal.connect(panelComInstance.refreshListeners) self.componentTableWidget.importComponentSignal.connect( self.onImportComponent) self.browseTasksWidget.reset()
def __init__(self, title=None, description=None, time=0, parent=None): '''Initialise timer. *title* should be the title entry to display for the time log whilst *description* can provide an optional longer description. *time* should be the initial value to set elapsed time to. *parent* should be the optional parent of this widget. ''' super(Timer, self).__init__(parent=parent) self.setObjectName('timer') self._state = self.STOPPED self._timer = None self._tick = None self._tickInterval = 50 self._elapsed = 0 layout = QtWidgets.QHBoxLayout() self.setLayout(layout) self.labelLayout = QtWidgets.QVBoxLayout() layout.addLayout(self.labelLayout, stretch=1) self.titleLabel = ftrack_connect.ui.widget.label.Label() self.titleLabel.setProperty('title', True) self.labelLayout.addWidget(self.titleLabel) self.descriptionLabel = ftrack_connect.ui.widget.label.Label() self.labelLayout.addWidget(self.descriptionLabel) self.timeField = ftrack_connect.ui.widget.line_edit.LineEdit() self.timeField.setObjectName('timeField') self.timeField.setAlignment(QtCore.Qt.AlignCenter) layout.addWidget(self.timeField) self.toggleButton = QtWidgets.QPushButton('Start') self.toggleButton.setObjectName('primary') self.toggleButton.setProperty('mode', 'start') layout.addWidget(self.toggleButton) self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) # Install event filter at application level in order to manage focus # behaviour correctly. application = QtCore.QCoreApplication.instance() application.installEventFilter(self) # Connect events. self.toggleButton.clicked.connect(self.toggle) # Set initial values. self.setValue({ 'title': title, 'description': description, 'time': time })
def populateUI(self, widget, exportTemplate): if exportTemplate: self._exportTemplate = exportTemplate properties = self._preset.properties() layout = QtWidgets.QFormLayout() self._readList = QtWidgets.QListView() self._writeList = QtWidgets.QListView() self._readList.setMinimumHeight(50) self._writeList.setMinimumHeight(50) self._readList.resize(200, 50) self._writeList.resize(200, 50) self._readModel = QtWidgets.QStandardItemModel() self._writeModel = QtWidgets.QStandardItemModel() # Default to the empty item unless the preset has a value set. for model, presetValue in ((self._readModel, properties["readPaths"]), (self._writeModel, properties["writePaths"])): for path, preset in exportTemplate.flatten(): if model is self._writeModel: if not hasattr(preset._parentType, 'nukeWriteNode'): continue item = QtWidgets.QStandardItem(path) item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) item.setData(QtCore.Qt.Unchecked, QtCore.Qt.CheckStateRole) if path in presetValue: item.setData(QtCore.Qt.Checked, QtCore.Qt.CheckStateRole) model.appendRow(item) self._readList.setModel(self._readModel) self._writeList.setModel(self._writeModel) readNodeListToolTip = """Select multiple entries within the shot template to be used as inputs for the read nodes (i.e. symlink, transcode.. etc).\n No selection will mean that read nodes are created in the nuke script pointing directly at the source media.\n""" writeNodeListToolTip = """Add one or more "Nuke Write Node" tasks to your export structure to define the path and codec settings for the nuke script.\nIf no write paths are selected, no write node will be added to the nuke script.""" self._readList.setToolTip(readNodeListToolTip) self._writeList.setToolTip(writeNodeListToolTip) self._readModel.dataChanged.connect(self.readPresetChanged) publishScriptTip = """When enabled, if there is a known shot in the asset that matches the shot in Hiero, the Nuke script will be published there.""" key, value, label = "publishScript", True, FnAssetAPI.l( "{publish} Script") uiProperty = UIPropertyFactory.create( type(value), key=key, value=value, dictionary=self._preset._properties, label=label, tooltip=publishScriptTip) self._uiProperties.append(uiProperty) layout.addRow(uiProperty._label + ":", uiProperty) ## @todo Think of a better name useAssetsTip = """If enabled, any Clips that point to managed Assets will reference the Asset, rather than their files.""" key, value, label = "useAssets", True, "Use Assets" uiProperty = UIPropertyFactory.create( type(value), key=key, value=value, dictionary=self._preset._properties, label=label, tooltip=useAssetsTip) self._uiProperties.append(uiProperty) layout.addRow(uiProperty._label + ":", uiProperty) layout.addRow("Read Nodes:", self._readList) self._writeModel.dataChanged.connect(self.writePresetChanged) layout.addRow("Write Nodes:", self._writeList) retimeToolTip = """Sets the retime method used if retimes are enabled.\n-Motion - Motion Estimation.\n-Blend - Frame Blending.\n-Frame - Nearest Frame""" key, value = "method", ("None", "Motion", "Frame", "Blend") uiProperty = UIPropertyFactory.create( type(value), key=key, value=value, dictionary=self._preset._properties, label="Retime Method", tooltip=retimeToolTip) self._uiProperties.append(uiProperty) layout.addRow(uiProperty._label + ":", uiProperty) collateTracksToolTip = """Enable this to include other shots which overlap the sequence time of each shot within the script. Cannot be enabled when Read Node overrides are set.""" key, value, label = "collateTracks", False, "Collate Shot Timings" uiProperty = UIPropertyFactory.create( type(value), key=key, value=value, dictionary=self._preset.properties(), label=label + ":", tooltip=collateTracksToolTip) layout.addRow(label + ":", uiProperty) self._uiProperties.append(uiProperty) self._collateTimeProperty = uiProperty collateShotNameToolTip = """Enable this to include other shots which have the same name in the Nuke script. Cannot be enabled when Read Node overrides are set.""" key, value, label = "collateShotNames", False, "Collate Shot Name" uiProperty = UIPropertyFactory.create( type(value), key=key, value=value, dictionary=self._preset.properties(), label=label + ":", tooltip=collateShotNameToolTip) layout.addRow(label + ":", uiProperty) self._collateNameProperty = uiProperty self._uiProperties.append(uiProperty) self.readPresetChanged(None, None) additionalNodesToolTip = """When enabled, allows custom Nuke nodes to be added into Nuke Scripts.\n Click Edit to add nodes on a per Shot, Track or Sequence basis.\n Additional Nodes can also optionally be filtered by Tag.""" additionalNodesLayout = QtWidgets.QHBoxLayout() additionalNodesCheckbox = QtWidgets.QCheckBox() additionalNodesCheckbox.setToolTip(additionalNodesToolTip) additionalNodesCheckbox.stateChanged.connect( self._additionalNodesEnableClicked) if self._preset.properties()["additionalNodesEnabled"]: additionalNodesCheckbox.setCheckState(QtCore.Qt.Checked) additionalNodesButton = QtWidgets.QPushButton("Edit") additionalNodesButton.setToolTip(additionalNodesToolTip) additionalNodesButton.clicked.connect( self._additionalNodesEditClicked) additionalNodesLayout.addWidget(additionalNodesCheckbox) additionalNodesLayout.addWidget(additionalNodesButton) layout.addRow("Additional Nodes:", additionalNodesLayout) widget.setLayout(layout)
def __init__(self, session, error_data, missing_assets_types, duplicated_components): '''Return a validator widget for the given *error_data* and *missing_assets_types*.''' super(FtrackSettingsValidator, self).__init__() self.setWindowTitle('Validation error') self._session = session self.logger = logging.getLogger(__name__ + '.' + self.__class__.__name__) ftrack_icon = QtGui.QIcon(':/ftrack/image/default/ftrackLogoLight') self.setWindowIcon(ftrack_icon) layout = QtWidgets.QVBoxLayout() self.setLayout(layout) box = QtWidgets.QGroupBox( 'An error occured in the current schema configuration.') self.layout().addWidget(box) box_layout = QtWidgets.QVBoxLayout() box.setLayout(box_layout) form_layout = TaskUIFormLayout() box_layout.addLayout(form_layout) if duplicated_components: form_layout.addDivider( '{} Duplicated components name have been found'.format( len(duplicated_components))) for component_name, task in duplicated_components: ui_property = UIPropertyFactory.create( type(component_name), key='component_name', value=component_name, dictionary=task._preset.properties()['ftrack'], label='Component ' + ':', tooltip='Duplicated component name') ui_property.update(True) form_layout.addRow('Duplicated component' + ':', ui_property) if component_name != task.component_name(): component_index = duplicated_components.index( (task.component_name(), task)) duplicated_components.pop(component_index) for processor, values in error_data.items(): form_layout.addDivider('Wrong {0} presets'.format( processor.__class__.__name__)) for attribute, valid_values in values.items(): valid_values.insert(0, '- select a value -') key, value, label = attribute, valid_values, ' '.join( attribute.split('_')) tooltip = 'Set {0} value'.format(attribute) ui_property = UIPropertyFactory.create( type(value), key=key, value=value, dictionary=processor._preset.properties()['ftrack'], label=label + ':', tooltip=tooltip) form_layout.addRow(label + ':', ui_property) ui_property.update(True) if missing_assets_types: form_layout.addDivider('Missing asset types') for missing_asset in missing_assets_types: create_asset_button = QtWidgets.QPushButton( missing_asset.capitalize()) create_asset_button.clicked.connect(self.create_missing_asset) form_layout.addRow('Create asset: ', create_asset_button) buttons = QtWidgets.QDialogButtonBox() buttons.setOrientation(QtCore.Qt.Horizontal) buttons.addButton('Cancel', QtWidgets.QDialogButtonBox.RejectRole) buttons.addButton('Accept', QtWidgets.QDialogButtonBox.AcceptRole) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) self.layout().addWidget(buttons)
def setupUi(self, ExportOptions): ExportOptions.setObjectName("ExportOptions") ExportOptions.resize(339, 266) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( ExportOptions.sizePolicy().hasHeightForWidth()) ExportOptions.setSizePolicy(sizePolicy) self.verticalLayout = QtWidgets.QVBoxLayout(ExportOptions) self.verticalLayout.setSpacing(3) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setObjectName("verticalLayout") self.optionsPlaceHolderLayout = QtWidgets.QHBoxLayout() self.optionsPlaceHolderLayout.setObjectName("optionsPlaceHolderLayout") self.verticalLayout.addLayout(self.optionsPlaceHolderLayout) self.label_4 = QtWidgets.QLabel(ExportOptions) self.label_4.setObjectName("label_4") self.verticalLayout.addWidget(self.label_4) self.gridLayout_4 = QtWidgets.QGridLayout() self.gridLayout_4.setObjectName("gridLayout_4") self.thumbnailLineEdit = QtWidgets.QLineEdit(ExportOptions) self.thumbnailLineEdit.setObjectName("thumbnailLineEdit") self.gridLayout_4.addWidget(self.thumbnailLineEdit, 2, 0, 1, 1) self.pushButton = QtWidgets.QPushButton(ExportOptions) self.pushButton.setObjectName("pushButton") self.gridLayout_4.addWidget(self.pushButton, 2, 1, 1, 1) self.screenshotButton = QtWidgets.QPushButton(ExportOptions) self.screenshotButton.setObjectName("screenshotButton") self.gridLayout_4.addWidget(self.screenshotButton, 2, 2, 1, 1) self.verticalLayout.addLayout(self.gridLayout_4) self.label_5 = QtWidgets.QLabel(ExportOptions) self.label_5.setObjectName("label_5") self.verticalLayout.addWidget(self.label_5) self.commentTextEdit = QtWidgets.QPlainTextEdit(ExportOptions) self.commentTextEdit.setMaximumSize(QtCore.QSize(16777215, 80)) self.commentTextEdit.setObjectName("commentTextEdit") self.verticalLayout.addWidget(self.commentTextEdit) self.publishButton = QtWidgets.QPushButton(ExportOptions) self.publishButton.setObjectName("publishButton") self.verticalLayout.addWidget(self.publishButton) self.progressBar = QtWidgets.QProgressBar(ExportOptions) self.progressBar.setProperty("value", 24) self.progressBar.setObjectName("progressBar") self.verticalLayout.addWidget(self.progressBar) self.publishMessageLabel = QtWidgets.QLabel(ExportOptions) self.publishMessageLabel.setText("") self.publishMessageLabel.setObjectName("publishMessageLabel") self.verticalLayout.addWidget(self.publishMessageLabel) spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) self.retranslateUi(ExportOptions) QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked()"), ExportOptions.setThumbnailFilename) QtCore.QObject.connect(self.screenshotButton, QtCore.SIGNAL("clicked()"), ExportOptions.takeScreenshot) QtCore.QMetaObject.connectSlotsByName(ExportOptions)
def create_validate_failed_overlay_widgets(self, label, failed_validators): '''Create overlay widgets to report validation failures.''' congrat_text = '<h2>Validation Failed!</h2>' success_text = 'Your <b>{0}</b> failed to validate.'.format(label) self.activeWidget = QtWidgets.QWidget() self.activeWidget.setLayout(QtWidgets.QVBoxLayout()) self.layout().addWidget(self.activeWidget) main_layout = self.activeWidget.layout() main_layout.addStretch(1) congrat_label = QtWidgets.QLabel(congrat_text) congrat_label.setAlignment(QtCore.Qt.AlignCenter) success_label = QtWidgets.QLabel(success_text) success_label.setAlignment(QtCore.Qt.AlignCenter) main_layout.addWidget(congrat_label) main_layout.addWidget(success_label) validators_table_container = QtWidgets.QWidget() table_layout = QtWidgets.QVBoxLayout() table_layout.setContentsMargins(15, 10, 15, 10) validators_table_container.setLayout(table_layout) validators_table = QtWidgets.QTableWidget() validators_table.setSelectionBehavior( QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) validators_table.setSelectionMode(QtWidgets.QTableWidget.NoSelection) validators_table.setColumnCount(2) validators_table.setHorizontalHeaderLabels(['Validation', 'Error']) validators_table.horizontalHeader().setResizeMode( 0, QtWidgets.QHeaderView.ResizeToContents) validators_table.horizontalHeader().setSectionResizeMode( QtWidgets.QHeaderView.Stretch) validators_table.horizontalHeader().setVisible(True) validators_table.setRowCount(len(failed_validators)) validators_table.verticalHeader().setVisible(False) icon = QtGui.QIcon(':ftrack/image/dark/remove') font = QtGui.QFont() font.setBold(True) for row, validator in enumerate(failed_validators): item = QtWidgets.QTableWidgetItem(icon, validator[0]) item.setFont(font) validators_table.setItem(row, 0, item) error_msg = validator[1] # Remove quotes from error message, if present. if ((error_msg[0] == error_msg[-1]) and error_msg.startswith( ("'", '"'))): error_msg = error_msg[1:-1] item = QtWidgets.QTableWidgetItem(error_msg) validators_table.setItem(row, 1, item) table_layout.addWidget(validators_table) main_layout.addWidget(validators_table_container) main_layout.addStretch(1) label = QtWidgets.QLabel('See details for more information.') label.setAlignment(QtCore.Qt.AlignCenter) main_layout.addWidget(label) buttons_layout = QtWidgets.QHBoxLayout() main_layout.addLayout(buttons_layout) self.details_button = QtWidgets.QPushButton('Details') buttons_layout.addWidget(self.details_button) self.details_button.clicked.connect(self.on_show_details) self.close_button = QtWidgets.QPushButton('Close') buttons_layout.addWidget(self.close_button) self.close_button.clicked.connect(self.close_window_callback) if self.details_window_callback is None: self.details_button.setDisabled(True)
def __init__(self, session): '''Instantiate the configure scenario widget.''' super(ConfigureScenario, self).__init__() # Check if user has permissions to configure scenario. # TODO: Update this with an actual permission check once available in # the API. try: session.query('Setting where name is "storage_scenario" and ' 'group is "STORAGE"').one() can_configure_scenario = True except ftrack_api.exception.NoResultFoundError: can_configure_scenario = False layout = QtWidgets.QVBoxLayout() layout.addSpacing(0) layout.setContentsMargins(50, 0, 50, 0) self.setLayout(layout) layout.addSpacing(100) svg_renderer = QtSvg.QSvgRenderer(':ftrack/image/default/cloud-done') image = QtWidgets.QImage(50, 50, QtWidgets.QImage.Format_ARGB32) # Set the ARGB to 0 to prevent rendering artifacts. image.fill(0x00000000) svg_renderer.render(QtGui.QPainter(image)) icon = QtWidgets.QLabel() icon.setPixmap(QtGui.QPixmap.fromImage(image)) icon.setAlignment(QtCore.Qt.AlignCenter) icon.setObjectName('icon-label') layout.addWidget(icon) layout.addSpacing(50) label = QtWidgets.QLabel() label.setObjectName('regular-label') text = ('Hi there, Connect needs to be configured so that ftrack can ' 'store and track your files for you.') if can_configure_scenario is False: text += ( '<br><br> You do not have the required permission, please ask ' 'someone with access to system settings in ftrack to ' 'configure it before you proceed.') label.setText(text) label.setContentsMargins(0, 0, 0, 0) label.setAlignment(QtCore.Qt.AlignCenter) label.setWordWrap(True) # Min height is required due to issue when word wrap is True and window # being resized which cases text to dissapear. label.setMinimumHeight(120) label.setMinimumWidth(300) layout.addWidget(label, alignment=QtCore.Qt.AlignCenter) layout.addSpacing(20) configure_button = QtWidgets.QPushButton(text='Configure now') configure_button.setObjectName('primary') configure_button.clicked.connect(self._configure_storage_scenario) configure_button.setMinimumHeight(40) configure_button.setMaximumWidth(125) dismiss_button = QtWidgets.QPushButton(text='Do it later') dismiss_button.clicked.connect(self._complete_configuration) dismiss_button.setMinimumHeight(40) dismiss_button.setMaximumWidth(125) hbox = QtWidgets.QHBoxLayout() hbox.addWidget(dismiss_button) if can_configure_scenario: hbox.addSpacing(10) hbox.addWidget(configure_button) layout.addLayout(hbox) layout.addSpacing(20) label = QtWidgets.QLabel() label.setObjectName('lead-label') label.setText( 'If you decide to do this later, some of the functionality in ' 'ftrack connect and applications started from connect may not ' 'work as expected until configured.') label.setAlignment(QtCore.Qt.AlignCenter) label.setWordWrap(True) # Min height is required due to issue when word wrap is True and window # being resized which cases text to dissapear. label.setMinimumHeight(100) label.setMinimumWidth(300) layout.addWidget(label, alignment=QtCore.Qt.AlignCenter) layout.addStretch(1) label = QtWidgets.QLabel() label.setObjectName('green-link') label.setText( '<a style="color: #1CBC90;" ' 'href="{0}/doc/using/managing_versions/storage_scenario.html"> ' 'Learn more about storage scenarios.'.format(session.server_url)) label.setAlignment(QtCore.Qt.AlignCenter) label.setOpenExternalLinks(True) layout.addWidget(label, alignment=QtCore.Qt.AlignCenter) layout.addSpacing(20) self._subscriber_identifier = session.event_hub.subscribe( 'topic=ftrack.storage-scenario.configure-done', self._complete_configuration) self._session = session
def __init__(self, *args, **kwargs): '''Instantiate the login widget.''' super(Login, self).__init__(*args, **kwargs) layout = QtWidgets.QVBoxLayout() layout.addSpacing(100) layout.setContentsMargins(50, 0, 50, 0) layout.setSpacing(15) self.setLayout(layout) label = QtWidgets.QLabel() label.setText('Sign in') label.setObjectName('login-label') layout.addWidget(label, alignment=QtCore.Qt.AlignCenter) self.server = QtWidgets.QLineEdit() self.server.setPlaceholderText('Site name or custom domain URL') layout.addWidget(self.server) self.username = QtWidgets.QLineEdit() self.username.setPlaceholderText('User name') self.username.hide() layout.addWidget(self.username) self.apiKey = QtWidgets.QLineEdit() self.apiKey.setPlaceholderText('API key') self.apiKey.hide() layout.addWidget(self.apiKey) loginButton = QtWidgets.QPushButton(text='SIGN IN') loginButton.setObjectName('primary') loginButton.clicked.connect(self.handleLogin) loginButton.setMinimumHeight(35) layout.addWidget(loginButton) label = QtWidgets.QLabel() label.setObjectName('lead-label') label.setContentsMargins(0, 0, 0, 0) label.setText( 'Your site name is your ftrackapp.com web address ' '(e.g https://sitename.ftrackapp.com OR your custom domain URL).') label.setAlignment(QtCore.Qt.AlignCenter) label.setWordWrap(True) # Min height is required due to issue when word wrap is True and window # being resized which cases text to dissapear. label.setMinimumHeight(50) label.setMinimumWidth(300) layout.addWidget(label, alignment=QtCore.Qt.AlignCenter) self.errorLabel = QtWidgets.QLabel() self.errorLabel.setWordWrap(True) layout.addWidget(self.errorLabel) self.loginError.connect(self.on_set_error) layout.addStretch(1) self.toggle_api_label = label = ClickableLabel() self.toggle_api_label.setObjectName('lead-label') self.toggle_api_label.setText( 'Trouble signing in? ' '<a href="#" style="color: #1CBC90;">Sign in with username and API key</a>' ) self.toggle_api_label.clicked.connect(self._toggle_credentials) layout.addWidget(self.toggle_api_label, alignment=QtCore.Qt.AlignCenter) layout.addSpacing(20)