Icon view can be renamed
This commit is contained in:
parent
655fff6e7a
commit
5618819563
7 changed files with 118 additions and 19 deletions
|
@ -123,8 +123,9 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
|
||||||
return m_selectionModel->isSelected(index);
|
return m_selectionModel->isSelected(index);
|
||||||
case UrlRole:
|
case UrlRole:
|
||||||
return item.url();
|
return item.url();
|
||||||
case FileNameRole:
|
case FileNameRole: {
|
||||||
return item.url().fileName();
|
return item.url().fileName();
|
||||||
|
}
|
||||||
case IconNameRole:
|
case IconNameRole:
|
||||||
return item.iconName();
|
return item.iconName();
|
||||||
case ThumbnailRole: {
|
case ThumbnailRole: {
|
||||||
|
@ -932,7 +933,7 @@ bool FolderModel::isSupportThumbnails(const QString &mimeType) const
|
||||||
{
|
{
|
||||||
const QStringList supportsMimetypes = {"image/bmp", "image/png", "image/gif", "image/jpeg", "image/web",
|
const QStringList supportsMimetypes = {"image/bmp", "image/png", "image/gif", "image/jpeg", "image/web",
|
||||||
"application/pdf", "application/rtf", "application/doc", "application/odf",
|
"application/pdf", "application/rtf", "application/doc", "application/odf",
|
||||||
"audio/mpeg"};
|
"audio/mpeg", "video/mp4"};
|
||||||
|
|
||||||
if (supportsMimetypes.contains(mimeType))
|
if (supportsMimetypes.contains(mimeType))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -87,7 +87,6 @@ PlacesModel::PlacesModel(QObject *parent)
|
||||||
trashItem->setIconPath("qrc:/images/user-trash.svg");
|
trashItem->setIconPath("qrc:/images/user-trash.svg");
|
||||||
m_items.append(trashItem);
|
m_items.append(trashItem);
|
||||||
|
|
||||||
Solid::Predicate predicate;
|
|
||||||
QString predicateStr(
|
QString predicateStr(
|
||||||
QString::fromLatin1("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
|
QString::fromLatin1("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
|
||||||
" OR "
|
" OR "
|
||||||
|
@ -96,14 +95,14 @@ PlacesModel::PlacesModel(QObject *parent)
|
||||||
"OpticalDisc.availableContent & 'Audio' ]"
|
"OpticalDisc.availableContent & 'Audio' ]"
|
||||||
" OR "
|
" OR "
|
||||||
"StorageAccess.ignored == false ]"));
|
"StorageAccess.ignored == false ]"));
|
||||||
predicate = Solid::Predicate::fromString(predicateStr);
|
m_predicate = Solid::Predicate::fromString(predicateStr);
|
||||||
|
|
||||||
Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance();
|
Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance();
|
||||||
connect(notifier, &Solid::DeviceNotifier::deviceAdded, this, &PlacesModel::onDeviceAdded);
|
connect(notifier, &Solid::DeviceNotifier::deviceAdded, this, &PlacesModel::onDeviceAdded);
|
||||||
connect(notifier, &Solid::DeviceNotifier::deviceRemoved, this, &PlacesModel::onDeviceRemoved);
|
connect(notifier, &Solid::DeviceNotifier::deviceRemoved, this, &PlacesModel::onDeviceRemoved);
|
||||||
|
|
||||||
// Init devices
|
// Init devices
|
||||||
const QList<Solid::Device> &deviceList = Solid::Device::listFromQuery(predicate);
|
const QList<Solid::Device> &deviceList = Solid::Device::listFromQuery(m_predicate);
|
||||||
for (const Solid::Device &device : deviceList) {
|
for (const Solid::Device &device : deviceList) {
|
||||||
PlacesItem *deviceItem = new PlacesItem;
|
PlacesItem *deviceItem = new PlacesItem;
|
||||||
deviceItem->setUdi(device.udi());
|
deviceItem->setUdi(device.udi());
|
||||||
|
@ -239,12 +238,14 @@ void PlacesModel::requestEject(const int &index)
|
||||||
|
|
||||||
void PlacesModel::onDeviceAdded(const QString &udi)
|
void PlacesModel::onDeviceAdded(const QString &udi)
|
||||||
{
|
{
|
||||||
|
if (m_predicate.matches(Solid::Device(udi))) {
|
||||||
beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
||||||
PlacesItem *deviceItem = new PlacesItem;
|
PlacesItem *deviceItem = new PlacesItem;
|
||||||
deviceItem->setUdi(udi);
|
deviceItem->setUdi(udi);
|
||||||
m_items.append(deviceItem);
|
m_items.append(deviceItem);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PlacesModel::onDeviceRemoved(const QString &udi)
|
void PlacesModel::onDeviceRemoved(const QString &udi)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define PLACESMODEL_H
|
#define PLACESMODEL_H
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
#include <Solid/Predicate>
|
||||||
#include "placesitem.h"
|
#include "placesitem.h"
|
||||||
|
|
||||||
class PlacesModel : public QAbstractItemModel
|
class PlacesModel : public QAbstractItemModel
|
||||||
|
@ -61,6 +62,7 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<PlacesItem *> m_items;
|
QList<PlacesItem *> m_items;
|
||||||
|
Solid::Predicate m_predicate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,15 +24,14 @@ Item {
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: _background
|
id: _background
|
||||||
width: Math.max(_iconItem.width + Meui.Units.smallSpacing,
|
width: Math.max(_iconItem.width, _label.paintedWidth)
|
||||||
_label.paintedWidth + Meui.Units.largeSpacing)
|
|
||||||
height: _iconItem.height + _label.paintedHeight + Meui.Units.largeSpacing
|
height: _iconItem.height + _label.paintedHeight + Meui.Units.largeSpacing
|
||||||
x: (parent.width - width) / 2
|
x: (parent.width - width) / 2
|
||||||
y: _iconItem.y
|
y: _iconItem.y
|
||||||
color: selected || hovered ? Meui.Theme.highlightColor : "transparent"
|
color: selected || hovered ? Meui.Theme.highlightColor : "transparent"
|
||||||
radius: Meui.Theme.mediumRadius
|
radius: Meui.Theme.mediumRadius
|
||||||
visible: selected || hovered
|
visible: selected || hovered
|
||||||
opacity: selected ? 0.9 : 0.4
|
opacity: selected ? 1.0 : 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -45,7 +44,6 @@ Item {
|
||||||
|
|
||||||
width: parent.width - Meui.Units.largeSpacing * 2
|
width: parent.width - Meui.Units.largeSpacing * 2
|
||||||
height: control.GridView.view.iconSize
|
height: control.GridView.view.iconSize
|
||||||
opacity: selected || !hovered ? 1.0 : 0.95
|
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: _icon
|
id: _icon
|
||||||
|
|
|
@ -41,6 +41,25 @@ GridView {
|
||||||
|
|
||||||
signal keyPress(var event)
|
signal keyPress(var event)
|
||||||
|
|
||||||
|
function rename() {
|
||||||
|
if (control.currentIndex != -1) {
|
||||||
|
var renameAction = control.model.action("rename")
|
||||||
|
if (renameAction && !renameAction.enabled)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (!editor)
|
||||||
|
editor = editorComponent.createObject(control)
|
||||||
|
|
||||||
|
editor.targetItem = control.currentItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelRename() {
|
||||||
|
if (editor) {
|
||||||
|
editor.targetItem = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
highlightMoveDuration: 0
|
highlightMoveDuration: 0
|
||||||
keyNavigationEnabled : true
|
keyNavigationEnabled : true
|
||||||
keyNavigationWraps : true
|
keyNavigationWraps : true
|
||||||
|
@ -115,6 +134,9 @@ GridView {
|
||||||
onPressed: {
|
onPressed: {
|
||||||
control.forceActiveFocus()
|
control.forceActiveFocus()
|
||||||
|
|
||||||
|
if (control.editor && childAt(mouse.x, mouse.y) !== control.editor)
|
||||||
|
control.editor.commit()
|
||||||
|
|
||||||
pressX = mouse.x
|
pressX = mouse.x
|
||||||
pressY = mouse.y
|
pressY = mouse.y
|
||||||
|
|
||||||
|
@ -353,4 +375,68 @@ GridView {
|
||||||
}
|
}
|
||||||
return Math.floor(extraSpacing)
|
return Math.floor(extraSpacing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: editorComponent
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: _editor
|
||||||
|
visible: false
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
horizontalAlignment: TextEdit.AlignHCenter
|
||||||
|
z: 999
|
||||||
|
|
||||||
|
property Item targetItem: null
|
||||||
|
|
||||||
|
onTargetItemChanged: {
|
||||||
|
if (targetItem != null) {
|
||||||
|
var pos = control.mapFromItem(targetItem, targetItem.textArea.x, targetItem.textArea.y)
|
||||||
|
x = targetItem.x + Math.abs(Math.min(control.contentX, control.originX))
|
||||||
|
y = pos.y + Meui.Units.smallSpacing
|
||||||
|
width = targetItem.width - Meui.Units.smallSpacing
|
||||||
|
height = Meui.Units.fontMetrics.height * 2
|
||||||
|
text = targetItem.textArea.text
|
||||||
|
targetItem.textArea.visible = false
|
||||||
|
_editor.select(0, folderModel.fileExtensionBoundary(targetItem.index))
|
||||||
|
visible = true
|
||||||
|
} else {
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: {
|
||||||
|
switch (event.key) {
|
||||||
|
case Qt.Key_Return:
|
||||||
|
case Qt.Key_Enter:
|
||||||
|
commit()
|
||||||
|
break
|
||||||
|
case Qt.Key_Escape:
|
||||||
|
if (targetItem) {
|
||||||
|
targetItem.textArea.visible = true
|
||||||
|
targetItem = null
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible)
|
||||||
|
_editor.forceActiveFocus()
|
||||||
|
else
|
||||||
|
control.forceActiveFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
function commit() {
|
||||||
|
if (targetItem) {
|
||||||
|
targetItem.textArea.visible = true
|
||||||
|
folderModel.rename(targetItem.index, text)
|
||||||
|
control.currentIndex = targetItem.index
|
||||||
|
targetItem = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,14 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rename() {
|
||||||
|
_viewLoader.item.rename()
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
folderModel.requestRename.connect(rename)
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: _statusBar
|
id: _statusBar
|
||||||
|
|
||||||
|
@ -121,6 +129,10 @@ Item {
|
||||||
onCountChanged: {
|
onCountChanged: {
|
||||||
_fileTips.visible = count === 0
|
_fileTips.visible = count === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Component.onCompleted: {
|
||||||
|
// folderModel.requestRename.connect(rename)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,10 +152,6 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: FolderListItem {}
|
delegate: FolderListItem {}
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
folderModel.requestRename.connect(rename)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,12 @@ ListView {
|
||||||
|
|
||||||
leftMargin: Meui.Units.smallSpacing
|
leftMargin: Meui.Units.smallSpacing
|
||||||
rightMargin: Meui.Units.smallSpacing
|
rightMargin: Meui.Units.smallSpacing
|
||||||
|
bottomMargin: Meui.Units.smallSpacing
|
||||||
spacing: Meui.Units.largeSpacing
|
spacing: Meui.Units.largeSpacing
|
||||||
|
|
||||||
ScrollBar.vertical: ScrollBar {}
|
ScrollBar.vertical: ScrollBar {
|
||||||
|
bottomPadding: Meui.Units.smallSpacing
|
||||||
|
}
|
||||||
|
|
||||||
highlightFollowsCurrentItem: true
|
highlightFollowsCurrentItem: true
|
||||||
highlightMoveDuration: 0
|
highlightMoveDuration: 0
|
||||||
|
|
Loading…
Reference in a new issue