QmlDesigner: Display only file names in comboboxes

Full paths are displayed in tooltips. Also add a check mark to
the selected item in the combobox's pop up.

Task-number: QDS-2405
Change-Id: I69cbd4200a73183b4e747c87e9dd8197fc650ed7
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2020-08-25 21:05:55 +03:00
parent 0773a0fb66
commit 29bc4801e3
3 changed files with 110 additions and 33 deletions

View File

@@ -27,7 +27,9 @@ import QtQuick 2.1
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
import QtQuickDesignerTheme 1.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.5
RowLayout {
id: urlChooser
@@ -50,6 +52,58 @@ RowLayout {
StudioControls.ComboBox {
id: comboBox
// Note: highlightedIndex property isn't used because it has no setter and it doesn't reset
// when the combobox is closed by focusing on some other control.
property int hoverIndex: -1
ToolTip {
visible: comboBox.hovered
text: urlChooser.backendValue.valueToString
delay: 1000
}
delegate: ItemDelegate {
id: delegateItem
width: parent.width
height: 20
highlighted: comboBox.hoverIndex === index
indicator: Label { // selected item check mark
padding: 5
y: (parent.height - height) / 2
text: StudioTheme.Constants.tickIcon
font.pixelSize: 10
font.family: StudioTheme.Constants.iconFont.family
color: Theme.color(comboBox.hoverIndex === index ? Theme.PanelTextColorLight
: Theme.QmlDesigner_HighlightColor)
visible: comboBox.currentIndex === index
}
contentItem: Label {
leftPadding: 10
text: modelData
anchors.top: parent.top
color: Theme.color(Theme.PanelTextColorLight)
font.pixelSize: 13
}
background: Rectangle {
anchors.fill: parent
color: parent.highlighted ? Theme.color(Theme.QmlDesigner_HighlightColor) : "transparent"
}
ToolTip {
visible: delegateItem.hovered && comboBox.highlightedIndex === index
text: fileModel.fullPathModel[index]
delay: 1000
}
onHoveredChanged: {
if (hovered)
comboBox.hoverIndex = index
}
}
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
@@ -78,7 +132,9 @@ RowLayout {
if (urlChooser.backendValue.isBound)
return urlChooser.backendValue.expression
return urlChooser.backendValue.valueToString
var fullPath = urlChooser.backendValue.valueToString;
var fileName = fullPath.substr(fullPath.lastIndexOf('/') + 1);
return fileName;
}
onTextValueChanged: comboBox.setCurrentText(comboBox.textValue)
@@ -87,7 +143,7 @@ RowLayout {
editable: true
model: fileModel.fileModel
model: fileModel.fileNameModel
onModelChanged: {
if (!comboBox.isComplete)
@@ -115,19 +171,17 @@ RowLayout {
function handleActivate(index)
{
var cText = comboBox.textAt(index)
if (index === -1)
cText = comboBox.editText
if (urlChooser.backendValue === undefined)
return
if (!comboBox.isComplete)
return
if (urlChooser.backendValue.value !== cText)
urlChooser.backendValue.value = cText
if (index === -1) // select first item if index is invalid
index = 0
if (urlChooser.backendValue.value !== fileModel.fullPathModel[index])
urlChooser.backendValue.value = fileModel.fullPathModel[index]
comboBox.dirty = false
}
@@ -145,13 +199,29 @@ RowLayout {
}
}
Connections {
target: comboBox
function onStateChanged(state)
{
// update currentIndex when the popup opens to override the default behavior in super classes
// that selects currentIndex based on values in the combo box.
if (comboBox.popup.opened) {
var index = fileModel.fullPathModel.indexOf(urlChooser.backendValue.value)
if (index !== -1) {
comboBox.currentIndex = index
comboBox.hoverIndex = index
}
}
}
}
StudioControls.AbstractButton {
buttonIcon: StudioTheme.Constants.addFile
iconColor: urlChooser.textColor
onClicked: {
fileModel.openFileDialog()
if (fileModel.fileName !== "")
urlChooser.backendValue.value = fileModel.fileName
if (fileModel.path !== "")
urlChooser.backendValue.value = fileModel.path
}
}
}

View File

@@ -42,8 +42,7 @@ FileResourcesModel::FileResourcesModel(QObject *parent) :
void FileResourcesModel::setModelNodeBackend(const QVariant &modelNodeBackend)
{
auto modelNodeBackendObject = modelNodeBackend.value<QObject*>();
auto modelNodeBackendObject = modelNodeBackend.value<QObject *>();
const auto backendObjectCasted =
qobject_cast<const QmlDesigner::QmlModelNodeProxy *>(modelNodeBackendObject);
@@ -64,6 +63,7 @@ void FileResourcesModel::setFileNameStr(const QString &fileName)
{
setFileName(QUrl(fileName));
}
void FileResourcesModel::setFileName(const QUrl &fileName)
{
if (fileName == m_fileName)
@@ -103,26 +103,25 @@ QString FileResourcesModel::filter() const
return m_filter;
}
QStringList FileResourcesModel::fileModel() const
QStringList FileResourcesModel::fullPathModel() const
{
if (m_model.isEmpty())
return QStringList(QString());
return m_fullPathModel;
}
return m_model;
QStringList FileResourcesModel::fileNameModel() const
{
return m_fileNameModel;
}
void FileResourcesModel::openFileDialog()
{
QString modelPath;
modelPath = m_path.toLocalFile();
QString modelPath = m_path.toLocalFile();
m_lastModelPath = modelPath;
bool documentChanged = m_lastModelPath == modelPath;
//First we try the last path this browser widget was opened with
//if the document was not changed
//First we try the last path this browser widget was opened with if the document was not changed
QString path = documentChanged ? QString() : m_currentPath;
@@ -154,7 +153,7 @@ void FileResourcesModel::openFileDialog()
void FileResourcesModel::registerDeclarativeType()
{
qmlRegisterType<FileResourcesModel>("HelperWidgets",2,0,"FileResourcesModel");
qmlRegisterType<FileResourcesModel>("HelperWidgets", 2, 0, "FileResourcesModel");
}
QVariant FileResourcesModel::modelNodeBackend() const
@@ -167,8 +166,7 @@ bool filterMetaIcons(const QString &fileName)
QFileInfo info(fileName);
if (info.dir().path().split("/").contains("designer")) {
if (info.dir().path().split('/').contains("designer")) {
QDir currentDir = info.dir();
int i = 0;
@@ -192,7 +190,8 @@ bool filterMetaIcons(const QString &fileName)
void FileResourcesModel::setupModel()
{
m_lock = true;
m_model.clear();
m_fullPathModel.clear();
m_fileNameModel.clear();
m_dirPath = QFileInfo(m_path.toLocalFile()).dir();
@@ -201,11 +200,15 @@ void FileResourcesModel::setupModel()
QDirIterator it(m_dirPath.absolutePath(), filterList, QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) {
QString absolutePath = it.next();
if (filterMetaIcons(absolutePath))
m_model.append(m_dirPath.relativeFilePath(absolutePath));
if (filterMetaIcons(absolutePath)) {
QString filePath = m_dirPath.relativeFilePath(absolutePath);
m_fullPathModel.append(filePath);
m_fileNameModel.append(filePath.mid(filePath.lastIndexOf('/') + 1));
}
}
m_lock = false;
emit fileModelChanged();
emit fullPathModelChanged();
emit fileNameModelChanged();
}

View File

@@ -42,7 +42,8 @@ class FileResourcesModel : public QObject
Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
Q_PROPERTY(QUrl path READ path WRITE setPath)
Q_PROPERTY(QUrl dirPath READ dirPath)
Q_PROPERTY(QStringList fileModel READ fileModel NOTIFY fileModelChanged)
Q_PROPERTY(QStringList fullPathModel READ fullPathModel NOTIFY fullPathModelChanged)
Q_PROPERTY(QStringList fileNameModel READ fileNameModel NOTIFY fileNameModelChanged)
public:
explicit FileResourcesModel(QObject *parent = nullptr);
@@ -56,7 +57,8 @@ public:
QUrl dirPath() const;
void setFilter(const QString &filter);
QString filter() const;
QStringList fileModel() const;
QStringList fullPathModel() const;
QStringList fileNameModel() const;
void setupModel();
Q_INVOKABLE void openFileDialog();
@@ -66,7 +68,8 @@ public:
signals:
void fileNameChanged(const QUrl &fileName);
void modelNodeBackendChanged();
void fileModelChanged();
void fullPathModelChanged();
void fileNameModelChanged();
private:
QVariant modelNodeBackend() const;
@@ -79,7 +82,8 @@ private:
bool m_lock;
QString m_currentPath;
QString m_lastModelPath;
QStringList m_model;
QStringList m_fullPathModel;
QStringList m_fileNameModel;
};