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 HelperWidgets 2.0
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
import QtQuickDesignerTheme 1.0
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls 2.5
RowLayout { RowLayout {
id: urlChooser id: urlChooser
@@ -50,6 +52,58 @@ RowLayout {
StudioControls.ComboBox { StudioControls.ComboBox {
id: 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.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show() actionIndicator.onClicked: extFuncLogic.show()
@@ -78,7 +132,9 @@ RowLayout {
if (urlChooser.backendValue.isBound) if (urlChooser.backendValue.isBound)
return urlChooser.backendValue.expression 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) onTextValueChanged: comboBox.setCurrentText(comboBox.textValue)
@@ -87,7 +143,7 @@ RowLayout {
editable: true editable: true
model: fileModel.fileModel model: fileModel.fileNameModel
onModelChanged: { onModelChanged: {
if (!comboBox.isComplete) if (!comboBox.isComplete)
@@ -115,19 +171,17 @@ RowLayout {
function handleActivate(index) function handleActivate(index)
{ {
var cText = comboBox.textAt(index)
if (index === -1)
cText = comboBox.editText
if (urlChooser.backendValue === undefined) if (urlChooser.backendValue === undefined)
return return
if (!comboBox.isComplete) if (!comboBox.isComplete)
return return
if (urlChooser.backendValue.value !== cText) if (index === -1) // select first item if index is invalid
urlChooser.backendValue.value = cText index = 0
if (urlChooser.backendValue.value !== fileModel.fullPathModel[index])
urlChooser.backendValue.value = fileModel.fullPathModel[index]
comboBox.dirty = false 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 { StudioControls.AbstractButton {
buttonIcon: StudioTheme.Constants.addFile buttonIcon: StudioTheme.Constants.addFile
iconColor: urlChooser.textColor iconColor: urlChooser.textColor
onClicked: { onClicked: {
fileModel.openFileDialog() fileModel.openFileDialog()
if (fileModel.fileName !== "") if (fileModel.path !== "")
urlChooser.backendValue.value = fileModel.fileName urlChooser.backendValue.value = fileModel.path
} }
} }
} }

View File

@@ -42,7 +42,6 @@ FileResourcesModel::FileResourcesModel(QObject *parent) :
void FileResourcesModel::setModelNodeBackend(const QVariant &modelNodeBackend) void FileResourcesModel::setModelNodeBackend(const QVariant &modelNodeBackend)
{ {
auto modelNodeBackendObject = modelNodeBackend.value<QObject *>(); auto modelNodeBackendObject = modelNodeBackend.value<QObject *>();
const auto backendObjectCasted = const auto backendObjectCasted =
@@ -64,6 +63,7 @@ void FileResourcesModel::setFileNameStr(const QString &fileName)
{ {
setFileName(QUrl(fileName)); setFileName(QUrl(fileName));
} }
void FileResourcesModel::setFileName(const QUrl &fileName) void FileResourcesModel::setFileName(const QUrl &fileName)
{ {
if (fileName == m_fileName) if (fileName == m_fileName)
@@ -103,26 +103,25 @@ QString FileResourcesModel::filter() const
return m_filter; return m_filter;
} }
QStringList FileResourcesModel::fileModel() const QStringList FileResourcesModel::fullPathModel() const
{ {
if (m_model.isEmpty()) return m_fullPathModel;
return QStringList(QString()); }
return m_model; QStringList FileResourcesModel::fileNameModel() const
{
return m_fileNameModel;
} }
void FileResourcesModel::openFileDialog() void FileResourcesModel::openFileDialog()
{ {
QString modelPath; QString modelPath = m_path.toLocalFile();
modelPath = m_path.toLocalFile();
m_lastModelPath = modelPath; m_lastModelPath = modelPath;
bool documentChanged = m_lastModelPath == modelPath; bool documentChanged = m_lastModelPath == modelPath;
//First we try the last path this browser widget was opened with //First we try the last path this browser widget was opened with if the document was not changed
//if the document was not changed
QString path = documentChanged ? QString() : m_currentPath; QString path = documentChanged ? QString() : m_currentPath;
@@ -167,8 +166,7 @@ bool filterMetaIcons(const QString &fileName)
QFileInfo info(fileName); QFileInfo info(fileName);
if (info.dir().path().split("/").contains("designer")) { if (info.dir().path().split('/').contains("designer")) {
QDir currentDir = info.dir(); QDir currentDir = info.dir();
int i = 0; int i = 0;
@@ -192,7 +190,8 @@ bool filterMetaIcons(const QString &fileName)
void FileResourcesModel::setupModel() void FileResourcesModel::setupModel()
{ {
m_lock = true; m_lock = true;
m_model.clear(); m_fullPathModel.clear();
m_fileNameModel.clear();
m_dirPath = QFileInfo(m_path.toLocalFile()).dir(); m_dirPath = QFileInfo(m_path.toLocalFile()).dir();
@@ -201,11 +200,15 @@ void FileResourcesModel::setupModel()
QDirIterator it(m_dirPath.absolutePath(), filterList, QDir::Files, QDirIterator::Subdirectories); QDirIterator it(m_dirPath.absolutePath(), filterList, QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) { while (it.hasNext()) {
QString absolutePath = it.next(); QString absolutePath = it.next();
if (filterMetaIcons(absolutePath)) if (filterMetaIcons(absolutePath)) {
m_model.append(m_dirPath.relativeFilePath(absolutePath)); QString filePath = m_dirPath.relativeFilePath(absolutePath);
m_fullPathModel.append(filePath);
m_fileNameModel.append(filePath.mid(filePath.lastIndexOf('/') + 1));
}
} }
m_lock = false; 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(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
Q_PROPERTY(QUrl path READ path WRITE setPath) Q_PROPERTY(QUrl path READ path WRITE setPath)
Q_PROPERTY(QUrl dirPath READ dirPath) 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: public:
explicit FileResourcesModel(QObject *parent = nullptr); explicit FileResourcesModel(QObject *parent = nullptr);
@@ -56,7 +57,8 @@ public:
QUrl dirPath() const; QUrl dirPath() const;
void setFilter(const QString &filter); void setFilter(const QString &filter);
QString filter() const; QString filter() const;
QStringList fileModel() const; QStringList fullPathModel() const;
QStringList fileNameModel() const;
void setupModel(); void setupModel();
Q_INVOKABLE void openFileDialog(); Q_INVOKABLE void openFileDialog();
@@ -66,7 +68,8 @@ public:
signals: signals:
void fileNameChanged(const QUrl &fileName); void fileNameChanged(const QUrl &fileName);
void modelNodeBackendChanged(); void modelNodeBackendChanged();
void fileModelChanged(); void fullPathModelChanged();
void fileNameModelChanged();
private: private:
QVariant modelNodeBackend() const; QVariant modelNodeBackend() const;
@@ -79,7 +82,8 @@ private:
bool m_lock; bool m_lock;
QString m_currentPath; QString m_currentPath;
QString m_lastModelPath; QString m_lastModelPath;
QStringList m_model; QStringList m_fullPathModel;
QStringList m_fileNameModel;
}; };