New ListView style

This commit is contained in:
cutefishd 2021-04-01 16:05:15 +08:00
parent cffa47cf6e
commit 37b0b93d56
8 changed files with 151 additions and 84 deletions

View file

@ -9,6 +9,7 @@
#include <QMenu> #include <QMenu>
#include <QAction> #include <QAction>
#include <QCollator> #include <QCollator>
#include <QDBusInterface>
#include <QStandardPaths> #include <QStandardPaths>
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
@ -16,7 +17,7 @@
#include <QClipboard> #include <QClipboard>
#include <QPainter> #include <QPainter>
#include <QDrag> #include <QDrag>
#include <QDBusInterface> #include <QDir>
// Qt Quick // Qt Quick
#include <QQuickItem> #include <QQuickItem>
@ -70,9 +71,9 @@ FolderModel::FolderModel(QObject *parent)
sort(m_sortMode, m_sortDesc ? Qt::DescendingOrder : Qt::AscendingOrder); sort(m_sortMode, m_sortDesc ? Qt::DescendingOrder : Qt::AscendingOrder);
createActions(); createActions();
connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(statusTextChanged())); connect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), SIGNAL(countChanged()));
connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(statusTextChanged())); connect(this, SIGNAL(rowsRemoved(QModelIndex, int, int)), SIGNAL(countChanged()));
connect(this, SIGNAL(modelReset()), SIGNAL(statusTextChanged())); connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
} }
FolderModel::~FolderModel() FolderModel::~FolderModel()
@ -106,8 +107,10 @@ QHash<int, QByteArray> FolderModel::staticRoleNames()
roleNames[IsDirRole] = "isDir"; roleNames[IsDirRole] = "isDir";
roleNames[UrlRole] = "url"; roleNames[UrlRole] = "url";
roleNames[FileNameRole] = "fileName"; roleNames[FileNameRole] = "fileName";
roleNames[FileSizeRole] = "fileSize";
roleNames[IconNameRole] = "iconName"; roleNames[IconNameRole] = "iconName";
roleNames[ThumbnailRole] = "thumbnail"; roleNames[ThumbnailRole] = "thumbnail";
roleNames[ModifiedRole] = "modified";
return roleNames; return roleNames;
} }
@ -128,6 +131,14 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
case FileNameRole: { case FileNameRole: {
return item.url().fileName(); return item.url().fileName();
} }
case FileSizeRole: {
if (item.isDir()) {
uint count = QDir(item.url().toLocalFile()).count();
return count == 1 ? tr("%1 item").arg(count) : tr("%1 items").arg(count);
}
return KIO::convertSize(item.size());
}
case IconNameRole: case IconNameRole:
return item.iconName(); return item.iconName();
case ThumbnailRole: { case ThumbnailRole: {
@ -144,6 +155,9 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const
return QVariant(); return QVariant();
} }
case ModifiedRole: {
return item.timeString(KFileItem::ModificationTime);
}
default: default:
break; break;
} }
@ -405,23 +419,9 @@ KFileItem FolderModel::rootItem() const
return m_dirModel->dirLister()->rootItem(); return m_dirModel->dirLister()->rootItem();
} }
QString FolderModel::statusText() int FolderModel::count() const
{ {
if (m_selectionModel && m_selectionModel->hasSelection()) { return rowCount();
if (m_selectionModel->selectedIndexes().size() == 1) {
KFileItem item = itemForIndex(m_selectionModel->selectedIndexes().first());
return item.name();
}
return tr("%1 selected").arg(m_selectionModel->selectedIndexes().size());
}
if (m_dirModel->rowCount() == 1) {
return tr("%1 item").arg(m_dirModel->rowCount());
} else if (m_dirModel->rowCount() <= 0)
return "";
return tr("%1 items").arg(m_dirModel->rowCount());
} }
int FolderModel::selectionCound() const int FolderModel::selectionCound() const
@ -909,8 +909,6 @@ void FolderModel::selectionChanged(const QItemSelection &selected, const QItemSe
updateActions(); updateActions();
// 选中状态信息
emit statusTextChanged();
emit selectionCoundChanged(); emit selectionCoundChanged();
} }

View file

@ -25,8 +25,9 @@ class FolderModel : public QSortFilterProxyModel, public QQmlParserStatus
Q_PROPERTY(bool sortDirsFirst READ sortDirsFirst WRITE setSortDirsFirst NOTIFY sortDirsFirstChanged) Q_PROPERTY(bool sortDirsFirst READ sortDirsFirst WRITE setSortDirsFirst NOTIFY sortDirsFirstChanged)
Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
Q_PROPERTY(QObject *viewAdapter READ viewAdapter WRITE setViewAdapter NOTIFY viewAdapterChanged) Q_PROPERTY(QObject *viewAdapter READ viewAdapter WRITE setViewAdapter NOTIFY viewAdapterChanged)
Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged)
Q_PROPERTY(bool isDesktop READ isDesktop WRITE setIsDesktop NOTIFY isDesktopChanged) Q_PROPERTY(bool isDesktop READ isDesktop WRITE setIsDesktop NOTIFY isDesktopChanged)
Q_PROPERTY(int selectionCound READ selectionCound NOTIFY selectionCoundChanged)
Q_PROPERTY(int count READ count NOTIFY countChanged)
public: public:
enum DataRole { enum DataRole {
@ -35,8 +36,10 @@ public:
IsDirRole, IsDirRole,
UrlRole, UrlRole,
FileNameRole, FileNameRole,
FileSizeRole,
IconNameRole, IconNameRole,
ThumbnailRole ThumbnailRole,
ModifiedRole
}; };
enum FilterMode { enum FilterMode {
@ -103,7 +106,7 @@ public:
KFileItem rootItem() const; KFileItem rootItem() const;
QString statusText(); int count() const;
int selectionCound() const; int selectionCound() const;
Q_INVOKABLE QString homePath() const; Q_INVOKABLE QString homePath() const;
@ -164,9 +167,9 @@ signals:
void requestRename(); void requestRename();
void draggingChanged(); void draggingChanged();
void viewAdapterChanged(); void viewAdapterChanged();
void statusTextChanged();
void isDesktopChanged(); void isDesktopChanged();
void selectionCoundChanged(); void selectionCoundChanged();
void countChanged();
private slots: private slots:
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);

View file

@ -13,7 +13,7 @@ Item {
height: GridView.view.cellHeight height: GridView.view.cellHeight
property Item iconArea: _image.visible ? _image : _icon property Item iconArea: _image.visible ? _image : _icon
property Item textArea: _label property Item labelArea: _label
property Item background: _background property Item background: _background
property int index: model.index property int index: model.index
@ -96,7 +96,7 @@ Item {
anchors.topMargin: Meui.Units.smallSpacing anchors.topMargin: Meui.Units.smallSpacing
maximumLineCount: 2 maximumLineCount: 2
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
width: parent.width - Meui.Units.largeSpacing * 2 width: parent.width - Meui.Units.largeSpacing * 2 - Meui.Units.smallSpacing
textFormat: Text.PlainText textFormat: Text.PlainText
elide: Qt.ElideRight elide: Qt.ElideRight
wrapMode: Text.Wrap wrapMode: Text.Wrap

View file

@ -58,6 +58,7 @@ GridView {
function cancelRename() { function cancelRename() {
if (editor) { if (editor) {
editor.cancel()
editor.targetItem = null; editor.targetItem = null;
} }
} }
@ -113,6 +114,14 @@ GridView {
cPress = mapToItem(control.contentItem, pressX, pressY) cPress = mapToItem(control.contentItem, pressX, pressY)
} }
onContentXChanged: {
cancelRename()
}
onContentYChanged: {
cancelRename()
}
onCachedRectangleSelectionChanged: { onCachedRectangleSelectionChanged: {
if (cachedRectangleSelection === null) if (cachedRectangleSelection === null)
return return
@ -360,8 +369,8 @@ GridView {
continue continue
} }
var labelRect = Qt.rect(itemX + item.textArea.x, itemY + item.textArea.y, var labelRect = Qt.rect(itemX + item.labelArea.x, itemY + item.labelArea.y,
item.textArea.width, item.textArea.height) item.labelArea.width, item.labelArea.height)
if (control.rubberBand.intersects(labelRect)) { if (control.rubberBand.intersects(labelRect)) {
indices.push(index) indices.push(index)
@ -421,18 +430,20 @@ GridView {
onTargetItemChanged: { onTargetItemChanged: {
if (targetItem != null) { if (targetItem != null) {
var pos = control.mapFromItem(targetItem, targetItem.textArea.x, targetItem.textArea.y) var pos = control.mapFromItem(targetItem, targetItem.labelArea.x, targetItem.labelArea.y)
x = targetItem.x + Math.abs(Math.min(control.contentX, control.originX))
y = pos.y + Meui.Units.smallSpacing
width = targetItem.width - Meui.Units.smallSpacing width = targetItem.width - Meui.Units.smallSpacing
height = Meui.Units.fontMetrics.height * 2 height = targetItem.labelArea.paintedHeight + Meui.Units.largeSpacing * 2
text = targetItem.textArea.text x = targetItem.x + Math.abs(Math.min(control.contentX, control.originX))
targetItem.textArea.visible = false y = pos.y - Meui.Units.largeSpacing
text = targetItem.labelArea.text
targetItem.labelArea.visible = false
_editor.select(0, folderModel.fileExtensionBoundary(targetItem.index)) _editor.select(0, folderModel.fileExtensionBoundary(targetItem.index))
visible = true visible = true
} else { } else {
x: 0 x = 0
y: 0 y = 0
width = 0
height = 0
visible = false visible = false
} }
} }
@ -444,11 +455,7 @@ GridView {
commit() commit()
break break
case Qt.Key_Escape: case Qt.Key_Escape:
if (targetItem) { cancel()
targetItem.textArea.visible = true
targetItem = null
event.accepted = true
}
break break
} }
} }
@ -462,12 +469,19 @@ GridView {
function commit() { function commit() {
if (targetItem) { if (targetItem) {
targetItem.textArea.visible = true targetItem.labelArea.visible = true
folderModel.rename(targetItem.index, text) folderModel.rename(targetItem.index, text)
control.currentIndex = targetItem.index control.currentIndex = targetItem.index
targetItem = null targetItem = null
} }
} }
function cancel() {
if (targetItem) {
targetItem.labelArea.visible = true
targetItem = null
}
}
} }
} }
} }

View file

@ -6,13 +6,14 @@ import MeuiKit 1.0 as Meui
Item { Item {
id: _listItem id: _listItem
width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin
height: 40 height: Meui.Units.fontMetrics.height * 2 + Meui.Units.largeSpacing
Accessible.name: fileName Accessible.name: fileName
Accessible.role: Accessible.Canvas Accessible.role: Accessible.Canvas
property Item iconArea: _image.visible ? _image : _icon property Item iconArea: _image.visible ? _image : _icon
property Item textArea: _label property Item labelArea: _label
property Item labelArea2: _label2
property int index: model.index property int index: model.index
property bool hovered: ListView.view.hoveredItem === _listItem property bool hovered: ListView.view.hoveredItem === _listItem
@ -80,12 +81,28 @@ Item {
} }
} }
ColumnLayout {
spacing: 0
Label {
id: _label
text: model.fileName
Layout.fillWidth: true
color: Meui.Theme.textColor
elide: Qt.ElideMiddle
}
Label {
id: _label2
text: model.fileSize
color: Meui.Theme.disabledTextColor
Layout.fillWidth: true
}
}
Label { Label {
id: _label text: model.modified
text: model.fileName color: Meui.Theme.disabledTextColor
Layout.fillWidth: true
color: Meui.Theme.textColor
elide: Qt.ElideMiddle
} }
} }
} }

View file

@ -88,8 +88,10 @@ ListView {
} }
function cancelRename() { function cancelRename() {
if (control.editor) if (control.editor) {
control.editor.cancel()
control.editor = null control.editor = null
}
} }
MouseArea { MouseArea {
@ -303,6 +305,7 @@ ListView {
wrapMode: Text.NoWrap wrapMode: Text.NoWrap
textMargin: 0 textMargin: 0
verticalAlignment: TextEdit.AlignVCenter verticalAlignment: TextEdit.AlignVCenter
leftPadding: 0
property Item targetItem: null property Item targetItem: null
@ -310,13 +313,14 @@ ListView {
onTargetItemChanged: { onTargetItemChanged: {
if (targetItem != null) { if (targetItem != null) {
var pos = control.mapFromItem(targetItem, targetItem.textArea.x, control.contentY) var pos = control.mapFromItem(targetItem, targetItem.labelArea.x, targetItem.labelArea.y)
width = targetItem.width - targetItem.iconArea.width * 2 width = targetItem.width - targetItem.iconArea.width * 2
height = targetItem.height height = targetItem.height
x = pos.x x = control.mapFromItem(targetItem.labelArea, 0, 0).x
y = pos.y y = pos.y
text = targetItem.textArea.text text = targetItem.labelArea.text
targetItem.textArea.visible = false targetItem.labelArea.visible = false
targetItem.labelArea2.visible = false
_editor.select(0, folderModel.fileExtensionBoundary(targetItem.index)) _editor.select(0, folderModel.fileExtensionBoundary(targetItem.index))
visible = true visible = true
} else { } else {
@ -333,11 +337,7 @@ ListView {
commit() commit()
break break
case Qt.Key_Escape: case Qt.Key_Escape:
if (targetItem) { cancel()
targetItem.textArea.visible = true
targetItem = null
event.accepted = true
}
break break
} }
} }
@ -351,12 +351,21 @@ ListView {
function commit() { function commit() {
if (targetItem) { if (targetItem) {
targetItem.textArea.visible = true targetItem.labelArea.visible = true
targetItem.labelArea2.visible = true
folderModel.rename(targetItem.index, text) folderModel.rename(targetItem.index, text)
control.currentIndex = targetItem.index control.currentIndex = targetItem.index
targetItem = null targetItem = null
} }
} }
function cancel() {
if (targetItem) {
targetItem.labelArea.visible = true
targetItem.labelArea2.visible = true
targetItem = null
}
}
} }
} }
} }

View file

@ -98,11 +98,22 @@ Item {
anchors.leftMargin: Meui.Units.largeSpacing anchors.leftMargin: Meui.Units.largeSpacing
anchors.rightMargin: Meui.Units.largeSpacing anchors.rightMargin: Meui.Units.largeSpacing
anchors.bottomMargin: 1 anchors.bottomMargin: 1
spacing: Meui.Units.largeSpacing
Label { Label {
text: folderModel.statusText
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
elide: Text.ElideMiddle text: folderModel.count == 1 ? qsTr("%1 item").arg(folderModel.count)
: qsTr("%1 items").arg(folderModel.count)
}
Label {
Layout.alignment: Qt.AlignLeft
text: qsTr("%1 selected").arg(folderModel.selectionCound)
visible: folderModel.selectionCound >= 1
}
Item {
Layout.fillWidth: true
} }
Button { Button {
@ -147,6 +158,7 @@ Item {
id: _folderListView id: _folderListView
model: folderModel model: folderModel
topMargin: Meui.Units.largeSpacing
leftMargin: Meui.Units.largeSpacing leftMargin: Meui.Units.largeSpacing
rightMargin: Meui.Units.largeSpacing + Meui.Theme.smallRadius rightMargin: Meui.Units.largeSpacing + Meui.Theme.smallRadius
spacing: Meui.Units.largeSpacing spacing: Meui.Units.largeSpacing

View file

@ -14,12 +14,12 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qml/Dialogs/CreateFolderDialog.qml" line="48"/> <location filename="../qml/Dialogs/CreateFolderDialog.qml" line="49"/>
<source>Cancel</source> <source>Cancel</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qml/Dialogs/CreateFolderDialog.qml" line="54"/> <location filename="../qml/Dialogs/CreateFolderDialog.qml" line="55"/>
<source>OK</source> <source>OK</source>
<translation></translation> <translation></translation>
</message> </message>
@ -35,82 +35,81 @@
<context> <context>
<name>FolderModel</name> <name>FolderModel</name>
<message> <message>
<location filename="../model/foldermodel.cpp" line="415"/>
<source>%1 selected</source> <source>%1 selected</source>
<translation> %1 </translation> <translation type="vanished"> %1 </translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="419"/> <location filename="../model/foldermodel.cpp" line="137"/>
<source>%1 item</source> <source>%1 item</source>
<translation>%1 </translation> <translation>%1 </translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="423"/> <location filename="../model/foldermodel.cpp" line="137"/>
<source>%1 items</source> <source>%1 items</source>
<translation>%1 </translation> <translation>%1 </translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="791"/> <location filename="../model/foldermodel.cpp" line="805"/>
<source>Select All</source> <source>Select All</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="984"/> <location filename="../model/foldermodel.cpp" line="1007"/>
<source>Open</source> <source>Open</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="987"/> <location filename="../model/foldermodel.cpp" line="1010"/>
<source>Cut</source> <source>Cut</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="990"/> <location filename="../model/foldermodel.cpp" line="1013"/>
<source>Copy</source> <source>Copy</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="993"/> <location filename="../model/foldermodel.cpp" line="1016"/>
<source>Paste</source> <source>Paste</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="996"/> <location filename="../model/foldermodel.cpp" line="1019"/>
<source>New Folder</source> <source>New Folder</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="999"/> <location filename="../model/foldermodel.cpp" line="1022"/>
<source>Move To Trash</source> <source>Move To Trash</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="1002"/> <location filename="../model/foldermodel.cpp" line="1025"/>
<source>Empty Trash</source> <source>Empty Trash</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="1005"/> <location filename="../model/foldermodel.cpp" line="1028"/>
<source>Delete</source> <source>Delete</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="1008"/> <location filename="../model/foldermodel.cpp" line="1031"/>
<source>Rename</source> <source>Rename</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="1011"/> <location filename="../model/foldermodel.cpp" line="1034"/>
<source>Open in Terminal</source> <source>Open in Terminal</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="1014"/> <location filename="../model/foldermodel.cpp" line="1037"/>
<source>Set as Wallpaper</source> <source>Set as Wallpaper</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../model/foldermodel.cpp" line="1017"/> <location filename="../model/foldermodel.cpp" line="1040"/>
<source>Properties</source> <source>Properties</source>
<translation></translation> <translation></translation>
</message> </message>
@ -123,7 +122,22 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../qml/FolderPage.qml" line="108"/> <location filename="../qml/FolderPage.qml" line="105"/>
<source>%1 item</source>
<translation>%1 </translation>
</message>
<message>
<location filename="../qml/FolderPage.qml" line="106"/>
<source>%1 items</source>
<translation>%1 </translation>
</message>
<message>
<location filename="../qml/FolderPage.qml" line="111"/>
<source>%1 selected</source>
<translation> %1 </translation>
</message>
<message>
<location filename="../qml/FolderPage.qml" line="122"/>
<source>Empty Trash</source> <source>Empty Trash</source>
<translation></translation> <translation></translation>
</message> </message>