Alter code structure && change room list filtering mechanics && add

sorting && init categoriy for rooms.
This commit is contained in:
Black Hat 2018-07-13 12:06:27 +08:00
parent a1941784eb
commit d44383545a
18 changed files with 146 additions and 142 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "matrix/libqmatrixclient"]
path = matrix/libqmatrixclient
url = https://github.com/QMatrixClient/libqmatrixclient

View File

@ -1,7 +1,9 @@
QT += quick QT += quick
CONFIG += c++14 CONFIG += c++14
CONFIG += object_parallel_to_source
include(matrix/libqmatrixclient/libqmatrixclient.pri) include(include/SortFilterProxyModel/SortFilterProxyModel.pri)
include(include/libqmatrixclient/libqmatrixclient.pri)
# The following define makes your compiler emit warnings if you use # The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings # any feature of Qt which as been marked deprecated (the exact warnings
@ -14,12 +16,12 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also select to disable deprecated APIs only up to a certain version of Qt. # You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp \ SOURCES += src/main.cpp \
matrix/controller.cpp \ src/controller.cpp \
matrix/roomlistmodel.cpp \ src/roomlistmodel.cpp \
matrix/imageprovider.cpp \ src/imageprovider.cpp \
matrix/messageeventmodel.cpp \ src/messageeventmodel.cpp \
matrix/imageproviderconnection.cpp src/imageproviderconnection.cpp
RESOURCES += \ RESOURCES += \
res.qrc res.qrc
@ -51,8 +53,8 @@ DISTFILES += \
qml/js/md.js qml/js/md.js
HEADERS += \ HEADERS += \
matrix/controller.h \ src/controller.h \
matrix/roomlistmodel.h \ src/roomlistmodel.h \
matrix/imageprovider.h \ src/imageprovider.h \
matrix/messageeventmodel.h \ src/messageeventmodel.h \
matrix/imageproviderconnection.h src/imageproviderconnection.h

@ -1 +0,0 @@
Subproject commit e66cae5fd3e74c5839804e560332e5690709931a

View File

@ -18,7 +18,7 @@ Page {
anchors.fill: parent anchors.fill: parent
spacing: 0 spacing: 0
ListForm { RoomListForm {
id: roomListForm id: roomListForm
Layout.fillHeight: true Layout.fillHeight: true

View File

@ -19,12 +19,9 @@ Item {
background: Item { background: Item {
anchors.fill: parent anchors.fill: parent
visible: !currentRoom visible: !currentRoom
Pane { Pane { anchors.fill: parent }
anchors.fill: parent
}
Label { Label {
z: 10
text: "Please choose a room." text: "Please choose a room."
anchors.centerIn: parent anchors.centerIn: parent
} }
@ -43,9 +40,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 80 Layout.preferredHeight: 80
background: Rectangle { background: Rectangle { color: Material.theme == Material.Light ? "#eaeaea" : "#242424" }
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
@ -97,14 +92,12 @@ Item {
id: messageEventModel id: messageEventModel
room: currentRoom room: currentRoom
onRoomChanged: { onRoomChanged: room.timelineSize === 0 ? room.getPreviousContent(50) : {}
if (room.timelineSize === 0) room.getPreviousContent(50)
}
} }
delegate: MessageDelegate {} delegate: MessageDelegate {}
onAtYBeginningChanged: if (atYBeginning && currentRoom) currentRoom.getPreviousContent(50) onAtYBeginningChanged: atYBeginning && currentRoom ? currentRoom.getPreviousContent(50) : {}
ScrollBar.vertical: ScrollBar {} ScrollBar.vertical: ScrollBar {}
@ -128,9 +121,7 @@ Item {
onClicked: parent.positionViewAtBeginning() onClicked: parent.positionViewAtBeginning()
Behavior on opacity { Behavior on opacity { NumberAnimation { duration: 200 } }
PropertyAnimation { easing.type: Easing.Linear; duration: 200 }
}
} }
} }
@ -174,9 +165,7 @@ Item {
bottomPadding: 0 bottomPadding: 0
selectByMouse: true selectByMouse: true
background: Rectangle { background: Rectangle { color: Material.theme == Material.Light ? "#eaeaea" : "#242424" }
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
Keys.onReturnPressed: { Keys.onReturnPressed: {
if (inputField.text) { if (inputField.text) {
@ -240,9 +229,7 @@ Item {
contentItem: MaterialIcon { icon: "\ue24e" } contentItem: MaterialIcon { icon: "\ue24e" }
background: Rectangle { background: Rectangle { color: Material.theme == Material.Light ? "#eaeaea" : "#242424" }
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
} }
} }
} }

View File

@ -5,22 +5,127 @@ import QtGraphicalEffects 1.0
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
import QtQml.Models 2.3 import QtQml.Models 2.3
import Matrique 0.1 import Matrique 0.1
import SortFilterProxyModel 0.2
import "qrc:/qml/component" import "qrc:/qml/component"
Item { Item {
property alias listModel: delegateModel.model property alias listModel: roomListProxyModel.sourceModel
property alias currentIndex: listView.currentIndex property alias currentIndex: listView.currentIndex
readonly property bool mini: width <= 80 // Used as an indicator of whether the listform should be displayed as "Mini mode". readonly property bool mini: width <= 80 // Used as an indicator of whether the listform should be displayed as "Mini mode".
DelegateModel { ColumnLayout {
id: delegateModel anchors.fill: parent
groups: [ spacing: 0
DelegateModelGroup {
name: "filterGroup"; includeByDefault: true Pane {
z: 10
Layout.fillWidth: true
Layout.preferredHeight: 80
background: Rectangle {
color: Qt.tint(Material.accent, "#20FFFFFF")
} }
TextField {
id: searchField
width: parent.width
height: 36
leftPadding: mini ? 4 : 16
topPadding: 0
bottomPadding: 0
anchors.verticalCenter: parent.verticalCenter
background: Item {
Row {
anchors.fill: parent
MaterialIcon {
icon: "\ue8b6"
color: "white"
width: mini ? parent.width : parent.height
height: parent.height
}
Label {
height: parent.height
visible: !mini
text: "Search"
color: "white"
font.pointSize: 12
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
width: searchField.activeFocus || searchField.text ? parent.width : 0
height: parent.height
color: "white"
Behavior on width {
PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 }
}
}
}
}
}
Pane {
Layout.fillWidth: true
Layout.fillHeight: true
padding: 0
background: Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
Label {
z: 10
text: mini ? "Empty" : "Here? No, not here."
anchors.centerIn: parent
visible: listView.count === 0
}
}
SortFilterProxyModel {
id: roomListProxyModel
filters: RegExpFilter {
roleName: "name"
pattern: searchField.text
caseSensitivity: Qt.CaseInsensitive
}
proxyRoles: [
ExpressionRole { name: "isFavorite"; expression: category === "Favorites" },
ExpressionRole { name: "isLowPriority"; expression: category === "Low Priorities" }
] ]
filterOnGroup: "filterGroup" sorters: [
RoleSorter { roleName: "isFavorite"; sortOrder: Qt.DescendingOrder },
RoleSorter { roleName: "isLowPriority" },
StringSorter { roleName: "name" }
]
}
ListView {
id: listView
width: parent.width
height: parent.height
model: roomListProxyModel
highlight: Rectangle {
color: Material.accent
opacity: 0.2
}
highlightMoveDuration: 250
currentIndex: -1
ScrollBar.vertical: ScrollBar { id: scrollBar }
delegate: ItemDelegate { delegate: ItemDelegate {
width: parent.width width: parent.width
@ -81,114 +186,12 @@ Item {
} }
} }
function applyFilter(filterName){ section.property: "category"
var roomCount = listModel.rowCount(); section.criteria: ViewSection.FullString
for (var i = 0; i < roomCount; i++){ section.delegate: Rectangle {
var roomName = listModel.roomAt(i).displayName;
if (roomName.toLowerCase().indexOf(filterName.toLowerCase()) !== -1) {
items.addGroups(i, 1, "filterGroup");
} else {items.removeGroups(i, 1, "filterGroup");}
}
}
}
ColumnLayout {
anchors.fill: parent
spacing: 0
Pane {
z: 10
Layout.fillWidth: true
Layout.preferredHeight: 80
background: Rectangle {
color: Qt.tint(Material.accent, "#20FFFFFF")
}
TextField {
id: searchField
width: parent.width width: parent.width
height: 36 height: 16
leftPadding: mini ? 4 : 16
topPadding: 0
bottomPadding: 0
anchors.verticalCenter: parent.verticalCenter
background: Item {
Row {
anchors.fill: parent
MaterialIcon {
icon: "\ue8b6"
color: "white"
width: mini ? parent.width : parent.height
height: parent.height
} }
Label {
height: parent.height
visible: !mini
text: "Search"
color: "white"
font.pointSize: 12
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
width: searchField.activeFocus || searchField.text ? parent.width : 0
height: parent.height
color: "white"
Behavior on width {
PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 }
}
}
}
onTextChanged: {
delegateModel.applyFilter(text);
}
}
}
Pane {
Layout.fillWidth: true
Layout.fillHeight: true
padding: 0
background: Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: Material.theme == Material.Light ? "#eaeaea" : "#242424"
}
Label {
z: 10
text: mini ? "Empty" : "Here? No, not here."
anchors.centerIn: parent
visible: listView.count === 0
}
}
ListView {
id: listView
width: parent.width
height: parent.height
highlight: Rectangle {
color: Material.accent
opacity: 0.2
}
highlightMoveDuration: 250
currentIndex: -1
ScrollBar.vertical: ScrollBar { id: scrollBar }
model: delegateModel
} }
} }
} }

View File

@ -12,7 +12,6 @@
<file>qml/form/RoomForm.qml</file> <file>qml/form/RoomForm.qml</file>
<file>qml/Room.qml</file> <file>qml/Room.qml</file>
<file>qml/form/DetailForm.qml</file> <file>qml/form/DetailForm.qml</file>
<file>qml/form/ListForm.qml</file>
<file>qml/component/SideNavButton.qml</file> <file>qml/component/SideNavButton.qml</file>
<file>qml/component/MaterialIcon.qml</file> <file>qml/component/MaterialIcon.qml</file>
<file>asset/img/icon.png</file> <file>asset/img/icon.png</file>
@ -24,5 +23,6 @@
<file>qml/component/DownloadableContent.qml</file> <file>qml/component/DownloadableContent.qml</file>
<file>qml/component/FileBubble.qml</file> <file>qml/component/FileBubble.qml</file>
<file>qml/component/AvatarContainer.qml</file> <file>qml/component/AvatarContainer.qml</file>
<file>qml/form/RoomListForm.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -3,10 +3,10 @@
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQmlContext> #include <QQmlContext>
#include "matrix/controller.h" #include "controller.h"
#include "matrix/imageprovider.h" #include "imageprovider.h"
#include "matrix/messageeventmodel.h" #include "messageeventmodel.h"
#include "matrix/roomlistmodel.h" #include "roomlistmodel.h"
#include "room.h" #include "room.h"
using namespace QMatrixClient; using namespace QMatrixClient;

View File

@ -17,11 +17,12 @@ void RoomListModel::setConnection(QMatrixClient::Connection* connection) {
m_connection = connection; m_connection = connection;
connect(connection, &Connection::loggedOut, this, connect(connection, &Connection::loggedOut, this,
[=] { setConnection(connection); }); [=] { setConnection(connection); });
// connect(connection, &Connection::invitedRoom, this, // connect(connection, &Connection::invitedRoom, this,
// &RoomListModel::updateRoom); // &RoomListModel::updateRoom);
// connect(connection, &Connection::joinedRoom, this, // connect(connection, &Connection::joinedRoom, this,
// &RoomListModel::updateRoom); // &RoomListModel::updateRoom);
// connect(connection, &Connection::leftRoom, this, &RoomListModel::updateRoom); // connect(connection, &Connection::leftRoom, this,
// &RoomListModel::updateRoom);
connect(connection, &Connection::aboutToDeleteRoom, this, connect(connection, &Connection::aboutToDeleteRoom, this,
&RoomListModel::deleteRoom); &RoomListModel::deleteRoom);
@ -61,22 +62,27 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const {
return QVariant(); return QVariant();
} }
QMatrixClient::Room* room = m_rooms.at(index.row()); QMatrixClient::Room* room = m_rooms.at(index.row());
if (role == Qt::DisplayRole) { if (role == NameRole) {
return room->displayName(); return room->displayName();
} }
if (role == Qt::ForegroundRole) { if (role == AvatarRole) {
if (room->highlightCount() > 0) return QBrush(QColor("orange"));
return QVariant();
}
if (role == Qt::DecorationRole) {
if (room->avatarUrl().toString() != "") { if (room->avatarUrl().toString() != "") {
return room->avatarUrl(); return room->avatarUrl();
} }
return QVariant(); return QVariant();
} }
if (role == Qt::StatusTipRole) { if (role == TopicRole) {
return room->topic(); return room->topic();
} }
if (role == CategoryRole) {
if (room->isFavourite()) return "Favorites";
if (room->isLowPriority()) return "Low Priorities";
return "Rooms";
}
if (role == HighlightRole) {
if (room->highlightCount() > 0) return QBrush(QColor("orange"));
return QVariant();
}
return QVariant(); return QVariant();
} }
@ -92,8 +98,10 @@ void RoomListModel::unreadMessagesChanged(QMatrixClient::Room* room) {
QHash<int, QByteArray> RoomListModel::roleNames() const { QHash<int, QByteArray> RoomListModel::roleNames() const {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "name"; roles[NameRole] = "name";
roles[Qt::DecorationRole] = "avatar"; roles[AvatarRole] = "avatar";
roles[Qt::StatusTipRole] = "topic"; roles[TopicRole] = "topic";
roles[CategoryRole] = "category";
roles[HighlightRole] = "highlight";
return roles; return roles;
} }

View File

@ -11,6 +11,14 @@ class RoomListModel : public QAbstractListModel {
setConnection) setConnection)
public: public:
enum EventRoles {
NameRole = Qt::UserRole + 1,
AvatarRole,
TopicRole,
CategoryRole,
HighlightRole,
};
RoomListModel(QObject* parent = 0); RoomListModel(QObject* parent = 0);
virtual ~RoomListModel(); virtual ~RoomListModel();