#
# Copyright 2018 DreamWorks Animation L.L.C.
#
# 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.
#
import os
from Qt import QtCore, QtWidgets
from Qt.QtCore import Signal, Slot
from Qt.QtGui import QIcon
from .utils import expandPath, overrideCursor
[docs]class IncludePanel(QtWidgets.QWidget):
"""
File browsing panel for the left side of the main UI.
"""
openFile = Signal(str)
def __init__(self, path="", filter="", selectedFilter="", parent=None):
""" Initialize the panel.
:Parameters:
path : `str`
default path to look in when creating or choosing the file.
filter : `list`
A list of strings denoting filename match filters. These strings
are displayed in a user-selectable combobox. When selected,
the file list is filtered by the pattern
The format must follow:
["Descriptive text (pattern1 pattern2 ...)", ...]
The glob matching pattern is in parens, and the entire string is
displayed for the user.
selectedFilter : `str`
Set the current filename filter. Needs to be one of the entries
specified in the "filter" parameter.
parent : `QObject`
Parent for this widget.
"""
super(IncludePanel, self).__init__(parent)
# Setup UI.
self.lookInCombo = QtWidgets.QComboBox(self)
self.toParentButton = QtWidgets.QToolButton(self)
self.buttonHome = QtWidgets.QToolButton(self)
self.buttonOriginal = QtWidgets.QPushButton("Original", self)
self.fileNameEdit = QtWidgets.QLineEdit(self)
self.fileNameLabel = QtWidgets.QLabel("File:", self)
self.fileTypeCombo = QtWidgets.QComboBox(self)
self.fileTypeLabel = QtWidgets.QLabel("Type:", self)
self.stackedWidget = QtWidgets.QStackedWidget(self)
self.listView = QtWidgets.QListView(self)
self.fileTypeLabelFiller = QtWidgets.QLabel(self)
self.fileTypeComboFiller = QtWidgets.QLabel(self)
self.buttonOpen = QtWidgets.QPushButton(QIcon.fromTheme("document-open"), "Open", self)
# Item settings.
self.buttonHome.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_DirHomeIcon))
self.buttonHome.setToolTip("User's home directory")
self.buttonHome.setAutoRaise(True)
self.buttonOriginal.setToolTip("Original directory")
self.lookInCombo.setMinimumSize(50,0)
self.toParentButton.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_FileDialogToParent))
self.toParentButton.setAutoRaise(True)
self.toParentButton.setToolTip("Parent directory")
self.listView.setDragEnabled(True)
self.fileNameLabel.setToolTip("Selected file or directory")
self.fileTypeLabel.setBuddy(self.fileTypeCombo)
self.fileTypeLabel.setToolTip("File type filter")
self.buttonOpen.setToolTip("Open selected file")
# Focus policies.
self.lookInCombo.setFocusPolicy(QtCore.Qt.NoFocus)
self.toParentButton.setFocusPolicy(QtCore.Qt.NoFocus)
self.buttonHome.setFocusPolicy(QtCore.Qt.NoFocus)
self.buttonOriginal.setFocusPolicy(QtCore.Qt.NoFocus)
self.buttonOpen.setFocusPolicy(QtCore.Qt.NoFocus)
# Item size policies.
self.lookInCombo.setSizePolicy (QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Fixed)
self.toParentButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
self.buttonHome.setSizePolicy (QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
self.buttonOriginal.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
self.fileNameLabel.setSizePolicy (QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.fileTypeCombo.setSizePolicy (QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Fixed)
self.fileTypeLabel.setSizePolicy (QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.buttonOpen.setSizePolicy (QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
# Layouts.
self.include1Layout = QtWidgets.QHBoxLayout()
self.include1Layout.setContentsMargins(0, 0, 0, 0)
self.include1Layout.setSpacing(5)
self.include1Layout.addWidget(self.buttonHome)
self.include1Layout.addWidget(self.lookInCombo)
self.include1Layout.addWidget(self.toParentButton)
self.include2Layout = QtWidgets.QHBoxLayout()
self.include2Layout.setContentsMargins(0, 0, 0, 0)
self.include2Layout.setSpacing(5)
self.include2Layout.addWidget(self.stackedWidget)
self.include4Layout = QtWidgets.QGridLayout()
self.include4Layout.setContentsMargins(0, 0, 0, 0)
self.include4Layout.setSpacing(5)
self.include4Layout.addWidget(self.fileNameLabel, 0, 0, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.include4Layout.addWidget(self.fileNameEdit, 0, 1)
self.include4Layout.addWidget(self.fileTypeLabel, 1, 0, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.include4Layout.addWidget(self.fileTypeCombo, 1, 1)
self.include4Layout.addWidget(self.fileTypeLabelFiller, 2, 0)
self.include4Layout.addWidget(self.fileTypeComboFiller, 2, 1)
self.include5Layout = QtWidgets.QHBoxLayout()
self.include5Layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.include5Layout.setContentsMargins(0, 0, 0, 0)
self.include5Layout.setSpacing(5)
self.include5Layout.addWidget(self.buttonOriginal)
spacer = QtWidgets.QSpacerItem(5, 0, QtWidgets.QSizePolicy.MinimumExpanding)
self.include5Layout.addSpacerItem(spacer)
self.include5Layout.addWidget(self.buttonOpen)
self.includeLayout = QtWidgets.QVBoxLayout()
self.includeLayout.setContentsMargins(0, 0, 0, 0)
self.includeLayout.setSpacing(5)
self.includeLayout.addLayout(self.include1Layout)
self.includeLayout.addLayout(self.include2Layout)
self.includeLayout.addLayout(self.include4Layout)
line1 = QtWidgets.QFrame()
line1.setFrameStyle(QtWidgets.QFrame.HLine | QtWidgets.QFrame.Sunken)
self.includeLayout.addWidget(line1)
self.includeLayout.addLayout(self.include5Layout)
self.setLayout(self.includeLayout)
self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.buttonHome.clicked.connect(self.onHome)
self.buttonOriginal.clicked.connect(self.onOriginal)
self.lookInCombo.activated[int].connect(self.onPathComboChanged)
self.fileTypeCombo.activated[int].connect(self._useNameFilter)
self.fileModel = QtWidgets.QFileSystemModel(parent)
self.fileModel.setReadOnly(True)
self.fileModel.setNameFilterDisables(False)
self.fileModel.setResolveSymlinks(True)
self.fileModel.rootPathChanged.connect(self.pathChanged)
self.listView.setModel(self.fileModel)
self.listView.activated[QtCore.QModelIndex].connect(self.enterDirectory)
# Set selection mode and behavior.
self.listView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.listView.setWrapping(False)
self.listView.setResizeMode(QtWidgets.QListView.Adjust)
selectionMode = QtWidgets.QAbstractItemView.SingleSelection
self.listView.setSelectionMode(selectionMode)
# Setup the completer.
completer = QtWidgets.QCompleter(self.fileModel, self.fileNameEdit)
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.fileNameEdit.setCompleter(completer)
self.fileNameEdit.textChanged.connect(self.autoCompleteFileName)
self.fileNameEdit.returnPressed.connect(self.accept)
pathFile = None
if not path:
self.__path = os.getcwd()
elif os.path.isfile(path):
self.__path, pathFile = os.path.split(path)
else:
self.__path = path
self.setPath(self.__path)
if filter:
self.setNameFilters(filter)
if selectedFilter:
self.selectNameFilter(selectedFilter)
self.listPage = QtWidgets.QWidget(self.stackedWidget)
self.stackedWidget.addWidget(self.listPage)
listLayout = QtWidgets.QGridLayout(self.listPage)
#listLayout.setMargin(0)
listLayout.setContentsMargins(0, 0, 0, 0)
listLayout.addWidget(self.listView, 0, 0, 1, 1)
self.fileTypeLabelFiller.hide()
self.fileTypeComboFiller.hide()
# Selections
selections = self.listView.selectionModel()
selections.selectionChanged.connect(self.fileSelectionChanged)
if pathFile is not None:
idx = self.fileModel.index(self.fileModel.rootPath() + QtCore.QDir.separator() + pathFile)
self.select(idx)
self.fileNameEdit.setText(pathFile)
# Connect signals.
self.toParentButton.clicked.connect(self.onUp)
self.buttonOpen.clicked.connect(self.accept)
self.listView.scheduleDelayedItemsLayout()
self.stackedWidget.setCurrentWidget(self.listPage)
self.fileNameEdit.setFocus()
[docs] def setNameFilters(self, filters):
self._nameFilters = filters
self.fileTypeCombo.clear()
if len(self._nameFilters) == 0:
return
for filter in self._nameFilters:
self.fileTypeCombo.addItem(filter)
self.selectNameFilter(filters[0])
[docs] def selectNameFilter(self, filter):
i = self.fileTypeCombo.findText(filter)
if i >= 0:
self.fileTypeCombo.setCurrentIndex(i)
self._useNameFilter(i)
@Slot(int)
def _useNameFilter(self, index):
filter = self.fileTypeCombo.itemText(index)
filter = [f.strip() for f in filter.split(" (", 1)[1][:-1].split(" ")]
self.fileModel.setNameFilters(filter)
[docs] def setDirectory(self, directory):
with overrideCursor():
if not directory.endswith('/'):
directory += '/'
self.fileNameEdit.completer().setCompletionPrefix(directory)
root = self.fileModel.setRootPath(directory)
self.listView.setRootIndex(root)
self.fileNameEdit.setText('')
self.fileNameEdit.clear()
self.listView.selectionModel().clear()
[docs] @Slot(str)
def pathChanged(self, path):
pass
[docs] @Slot(QtCore.QModelIndex)
def enterDirectory(self, index):
fname = str(index.data(QtWidgets.QFileSystemModel.FileNameRole))
isDirectory = self.fileModel.isDir(index)
if isDirectory:
self.appendToPath(fname, isDirectory)
else:
self.accept()
[docs] def showAll(self, checked):
""" Show hidden files
:Parameters:
checked : `bool`
If True, show hidden files
"""
dirFilters = self.fileModel.filter()
if checked:
dirFilters |= QtCore.QDir.Hidden
else:
dirFilters &= ~QtCore.QDir.Hidden
self.fileModel.setFilter(dirFilters)
[docs] @Slot(bool)
def onUp(self, *args):
path = os.path.abspath(self.path)
if not os.path.isdir(path):
path = os.path.dirname(path)
dirName = os.path.dirname(path)
self.setPath(dirName)
[docs] @Slot(bool)
def onHome(self, *args):
self.setPath(QtCore.QDir.homePath())
self.setFileDisplay()
[docs] @Slot(bool)
def onOriginal(self, *args):
self.setPath(self.__path)
self.setFileDisplay()
[docs] @Slot(int)
def onPathComboChanged(self, index):
self.setPath(str(self.lookInCombo.itemData(index)))
[docs] def setPath(self, path):
self.setDirectory(expandPath(path))
self.path = path
self.lookInCombo.clear()
p = path
dirs = []
while True:
p1, p2 = os.path.split(p)
if not p2:
break
dirs.insert(0, (p2, p))
p = p1
for d, dp in dirs:
self.lookInCombo.addItem("%s%s" % (self.lookInCombo.count()*" ", d), dp)
self.lookInCombo.setCurrentIndex(self.lookInCombo.count() - 1)
[docs] def appendToPath(self, filename, isDirectory):
"""
:Parameters:
filename : `str`
isDirectory : `bool`
"""
self.path = os.path.join(self.path, filename)
if isDirectory:
self.setDirectory(expandPath(self.path))
self.lookInCombo.addItem("%s%s" % (self.lookInCombo.count()*" ", filename), self.path)
self.lookInCombo.setCurrentIndex(self.lookInCombo.count() - 1)
return self.path
[docs] def getPath(self):
return self.path
[docs] def setFileDisplay(self):
self.stackedWidget.setCurrentWidget(self.listPage)
self.fileNameLabel.show()
self.fileNameEdit.show()
self.fileNameEdit.setFocus()
self.fileTypeLabel.show()
self.fileTypeCombo.show()
self.fileTypeLabelFiller.hide()
self.fileTypeComboFiller.hide()
self.toParentButton.setEnabled(True)
[docs] @Slot()
@Slot(bool)
def accept(self, *args):
indexes = self.listView.selectionModel().selectedRows()
if indexes:
index = indexes[0]
if self.fileModel.isDir(index):
self.enterDirectory(index)
return
fname = str(index.data())
else:
fname = self.fileNameEdit.text().strip()
if not fname:
return
info = QtCore.QFileInfo(fname)
if info.isDir():
self.setPath(info.absoluteFilePath())
return
self.openFile.emit(os.path.join(self.getPath(), fname))
[docs] @Slot(str)
def autoCompleteFileName(self, text):
if not text.strip():
return
if text.strip().startswith("/"):
self.listView.selectionModel().clearSelection()
return
idx = self.fileModel.index(self.fileModel.rootPath() + QtCore.QDir.separator() + text)
if self.fileNameEdit.hasFocus():
self.listView.selectionModel().clear()
self.select(idx)
[docs] def select(self, index):
if index.isValid():
self.listView.selectionModel().select(index,
QtCore.QItemSelectionModel.Select | QtCore.QItemSelectionModel.Rows)
self.listView.scrollTo(index, self.listView.EnsureVisible)
return index
[docs] @Slot(QtCore.QItemSelection, QtCore.QItemSelection)
def fileSelectionChanged(self, one, two):
indexes = self.listView.selectionModel().selectedRows()
if indexes:
idx = indexes[0]
self.fileNameEdit.setText(str(idx.data()))