forked from qt-creator/qt-creator
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:
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,8 +42,7 @@ 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 =
|
||||||
qobject_cast<const QmlDesigner::QmlModelNodeProxy *>(modelNodeBackendObject);
|
qobject_cast<const QmlDesigner::QmlModelNodeProxy *>(modelNodeBackendObject);
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ void FileResourcesModel::openFileDialog()
|
|||||||
|
|
||||||
void FileResourcesModel::registerDeclarativeType()
|
void FileResourcesModel::registerDeclarativeType()
|
||||||
{
|
{
|
||||||
qmlRegisterType<FileResourcesModel>("HelperWidgets",2,0,"FileResourcesModel");
|
qmlRegisterType<FileResourcesModel>("HelperWidgets", 2, 0, "FileResourcesModel");
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant FileResourcesModel::modelNodeBackend() const
|
QVariant FileResourcesModel::modelNodeBackend() const
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user