Reorganize sidePane, accounts and rooms

- Accordion design for accounts and rooms (not finished)
- Toolbar and account/room lists reduce correctly, buttons become
  hamburger menu if not enough width
- Can set status using the "Set status message" account fields
- Uniformized avatar sizes for sidePane, roomHeader and SendBox
This commit is contained in:
miruka 2019-03-26 03:19:55 -04:00
parent 16aa6142bb
commit cccc43a9ae
19 changed files with 219 additions and 129 deletions

View File

@ -2,53 +2,83 @@ import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.4
Row {
readonly property string displayName:
Backend.getUser(section).display_name
ColumnLayout {
id: "accountDelegate"
spacing: 0
width: parent.width
id: row
width: roomListView.width
height: Math.max(accountLabel.height + statusEdit.height, avatar.height)
RowLayout {
id: "row"
spacing: 0
Avatar { id: avatar; username: displayName; dimmension: 32 }
Rectangle {
color: "#111"
width: parent.width - avatar.width
height: parent.height
Avatar { id: "avatar"; username: display_name; dimmension: 36 }
ColumnLayout {
anchors.fill: parent
spacing: 1
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
PlainLabel {
id: accountLabel
text: displayName
color: "#CCC"
id: "accountLabel"
text: display_name
elide: Text.ElideRight
maximumLineCount: 1
Layout.fillWidth: true
topPadding: -2
bottomPadding: -2
leftPadding: 5
rightPadding: 5
leftPadding: 6
rightPadding: leftPadding
}
TextField {
id: statusEdit
id: "statusEdit"
text: status_message || ""
placeholderText: qsTr("Set status message")
background: Rectangle { color: "#333" }
color: "#CCC"
background: null
color: "black"
selectByMouse: true
font.family: "Roboto"
font.pixelSize: 12
Layout.fillWidth: true
padding: 0
leftPadding: accountLabel.leftPadding
rightPadding: leftPadding
topPadding: 0
bottomPadding: 0
leftPadding: 5
rightPadding: 5
onEditingFinished: {
Backend.setStatusMessage(user_id, text)
pageStack.forceActiveFocus()
}
}
}
HButton {
id: "toggleExpand"
iconName: roomList.visible ? "up" : "down"
Layout.maximumWidth: 28
Layout.maximumHeight: Layout.maximumWidth
onClicked: {
toggleExpand.ToolTip.hide()
roomList.visible = ! roomList.visible
}
}
}
RoomList {
id: "roomList"
visible: true
user: Backend.getUser(user_id)
Layout.minimumHeight:
roomList.visible ?
roomList.contentHeight + roomList.anchors.margins * 2 :
0
Layout.maximumHeight: Layout.minimumHeight
Layout.minimumWidth: parent.width - Layout.leftMargin * 2
Layout.maximumWidth: Layout.minimumWidth
Layout.margins: accountList.spacing
Layout.leftMargin:
sidePane.width < 36 + Layout.margins ? 0 : Layout.margins
Layout.rightMargin: Layout.leftMargin
}
}

View File

@ -0,0 +1,11 @@
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.4
ListView {
id: "accountList"
spacing: 8
model: Backend.accountsModel
delegate: AccountDelegate {}
clip: true
}

View File

@ -2,41 +2,15 @@ import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.4
ToolButton {
property string tooltip: ""
property string iconName: ""
property string targetPage: ""
HButton {
function toolBarIsBig() {
return roomPane.width >
return sidePane.width >
Layout.minimumWidth * (toolBar.children.length - 2)
}
id: "button"
display: ToolButton.IconOnly
icon.source: "icons/" + iconName + ".svg"
background: Rectangle { color: "transparent" }
visible: toolBarIsBig()
Layout.fillHeight: true
Layout.fillWidth: true
Layout.minimumWidth: height
onClicked: { toolTip.hide(); pageStack.show_page(targetPage) }
ToolTip {
id: "toolTip"
text: tooltip
delay: Qt.styleHints.mousePressAndHoldInterval
visible: text ? toolTipZone.containsMouse : false
}
MouseArea {
id: toolTipZone
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton // Make button receive clicks normally
onEntered: button.background.color = "#656565"
onExited: button.background.color = "transparent"
}
}

View File

@ -17,13 +17,11 @@ RowLayout {
ActionButton {
iconName: "settings"
tooltip: "Settings"
targetPage: "SettingsPage"
}
ActionButton {
iconName: "add_account"
tooltip: "Add new account"
targetPage: "AddAccountPage"
}
ActionButton {
@ -33,7 +31,7 @@ RowLayout {
ActionButton {
iconName: "search"
tooltip: "Filter rooms and people"
tooltip: "Filter rooms"
}

View File

@ -3,6 +3,7 @@ import QtQuick.Controls 2.2
import QtQuick.Layouts 1.4
ColumnLayout {
property var user: null
property var room: null
id: chatPage

31
harmonyqml/HButton.qml Normal file
View File

@ -0,0 +1,31 @@
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.4
ToolButton {
property string tooltip: ""
property string iconName: ""
id: "button"
display: ToolButton.IconOnly
icon.source: "icons/" + iconName + ".svg"
background: Rectangle { color: "transparent" }
onClicked: toolTip.hide()
ToolTip {
id: "toolTip"
text: tooltip
delay: Qt.styleHints.mousePressAndHoldInterval
visible: text ? toolTipZone.containsMouse : false
}
MouseArea {
id: "toolTipZone"
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton // Make button receive clicks normally
onEntered: button.background.color = "#656565"
onExited: button.background.color = "transparent"
}
}

View File

@ -1,5 +0,0 @@
import QtQuick 2.7
MouseArea {
cursorShape: Qt.PointingHandCursor
}

View File

@ -13,7 +13,7 @@ Column {
Backend.getUser(sender_id).display_name
readonly property bool isOwn:
chatPage.room.account_id === sender_id
chatPage.user.user_id === sender_id
readonly property var previousData:
index > 0 ? messageListView.model.get(index - 1) : null

View File

@ -2,17 +2,22 @@ import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.4
Item {
MouseArea {
id: "root"
width: roomListView.width
width: roomList.width
height: Math.max(roomLabel.height + subtitleLabel.height, avatar.height)
onClicked: pageStack.show_room(
roomList.user,
roomList.model.get(index)
)
RowLayout {
anchors.fill: parent
id: row
spacing: 1
Avatar { id: avatar; username: display_name; dimmension: 32 }
Avatar { id: avatar; username: display_name; dimmension: 36 }
ColumnLayout {
spacing: 0
@ -48,9 +53,4 @@ Item {
Item { Layout.fillWidth: true }
}
HMouseArea {
anchors.fill: parent
onClicked: pageStack.show_room(roomListView.model.get(index))
}
}

View File

@ -5,7 +5,7 @@ import QtQuick.Layouts 1.4
Rectangle {
id: root
Layout.fillWidth: true
Layout.minimumHeight: 32
Layout.minimumHeight: 36
Layout.maximumHeight: Layout.minimumHeight
color: "#BBB"

25
harmonyqml/RoomList.qml Normal file
View File

@ -0,0 +1,25 @@
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.4
ListView {
property var user: null
property int contentHeight: 0
onCountChanged: {
var children = roomList.children
var childrenHeight = 0
for (var i = 0; i < children.length; i++) {
childrenHeight += children[i].height
}
contentHeight = childrenHeight + spacing * (children.length - 1)
}
id: "roomList"
spacing: 8
model: Backend.roomsModel[user.user_id]
delegate: RoomDelegate {}
}

View File

@ -1,30 +0,0 @@
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.4
Rectangle {
id: roomPane
color: "gray"
clip: true // Avoid artifacts when resizing pane width to minimum
ColumnLayout {
anchors.fill: parent
spacing: 0
TopBar {}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
id: roomListView
spacing: 0
model: Backend.roomsModel
delegate: RoomDelegate {}
//highlight: Rectangle {color: "lightsteelblue"; radius: 5}
section.property: "account_id"
section.delegate: AccountDelegate {}
}
}
}

View File

@ -19,9 +19,10 @@ Rectangle {
Avatar {
id: "avatar"
username: Backend.getUser(chatPage.room.account_id).display_name
username: chatPage.user.display_name
dimmension: root.Layout.minimumHeight
visible: textArea.text === ""
//visible: textArea.text === ""
visible: textArea.height <= root.Layout.minimumHeight
}
ScrollView {
@ -49,7 +50,7 @@ Rectangle {
return
}
Backend.sendMessage(chatPage.room.account_id,
Backend.sendMessage(chatPage.user.user_id,
chatPage.room.room_id,
textArea.text)
textArea.clear()

21
harmonyqml/SidePane.qml Normal file
View File

@ -0,0 +1,21 @@
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.4
Rectangle {
id: sidePane
color: "gray"
clip: true // Avoid artifacts when resizing pane width to minimum
ColumnLayout {
anchors.fill: parent
spacing: 0
AccountList {
Layout.fillWidth: true
Layout.fillHeight: true
}
ButtonsBar {}
}
}

View File

@ -6,21 +6,26 @@ import QtQuick.Layouts 1.4
Controls1.SplitView {
anchors.fill: parent
RoomPane {
Layout.minimumWidth: 32
width: 180
SidePane {
Layout.minimumWidth: 36
width: 200
}
StackView {
function show_page(componentName) {
pageStack.replace(componentName + ".qml")
}
function show_room(room_obj) {
pageStack.replace("ChatPage.qml", { room: room_obj })
function show_room(user_obj, room_obj) {
pageStack.replace(
"ChatPage.qml", { user: user_obj, room: room_obj }
)
}
id: "pageStack"
initialItem: ChatPage { room: Backend.roomsModel.get(0) }
initialItem: ChatPage {
user: Backend.accountsModel.get(0)
room: Backend.roomsModel[Backend.accountsModel.get(0).user_id].get(0)
}
onCurrentItemChanged: currentItem.forceActiveFocus()

View File

@ -14,10 +14,10 @@ class User(NamedTuple):
user_id: str
display_name: str
avatar_url: Optional[str] = None
status_message: Optional[str] = None
class Room(NamedTuple):
account_id: str
room_id: str
display_name: str
subtitle: str = ""
@ -41,13 +41,19 @@ class Backend(QObject):
super().__init__()
self._known_users: Dict[str, User] = {}
self.rooms: ListModel = ListModel()
self.accounts: ListModel = ListModel()
self.rooms: DefaultDict[str, ListModel] = DefaultDict(ListModel)
self.messages: DefaultDict[str, ListModel] = DefaultDict(ListModel)
@pyqtProperty(_QtListModel, constant=True)
def roomsModel(self) -> _QtListModel:
return self.rooms.qt_model
def accountsModel(self) -> _QtListModel:
return self.accounts.qt_model
@pyqtProperty("QVariantMap", constant=True)
def roomsModel(self) -> Dict[str, _QtListModel]:
return {account_id: l.qt_model for account_id, l in self.rooms.items()}
@pyqtProperty("QVariantMap", constant=True)
@ -73,6 +79,10 @@ class Backend(QObject):
@pyqtSlot(str, result="QVariantMap")
def getUser(self, user_id: str) -> Dict[str, Any]:
for user in self.accounts:
if user.user_id == user_id:
return user._asdict()
try:
return self._known_users[user_id]._asdict()
except KeyError:
@ -87,3 +97,13 @@ class Backend(QObject):
# pylint: disable=no-self-use
md5 = hashlib.md5(bytes(string, "utf-8")).hexdigest()
return float("0.%s" % int(md5[-10:], 16))
@pyqtSlot(str, str)
def setStatusMessage(self, user_id: str, to: str) -> None:
for user in self.accounts:
if user.user_id == user_id:
user.status_message = to
break
else:
raise ValueError(f"{user_id} not found in Backend.accounts")

View File

@ -3,7 +3,7 @@
from PyQt5.QtCore import QDateTime, Qt
from .base import Backend, Message, Room
from .base import Backend, Message, Room, User
class DummyBackend(Backend):
@ -15,16 +15,22 @@ class DummyBackend(Backend):
db = lambda t: QDateTime.fromString(f"2019-03-20T{t}.456",
Qt.ISODateWithMs)
self.rooms.extend([
Room("@renko:matrix.org", "!test:matrix.org", "Test", "Test room"),
Room("@renko:matrix.org", "!mary:matrix.org", "Mary",
self.accounts.extend([
User("@renko:matrix.org", "Renko", None, "Sleeping, zzz..."),
User("@mary:matrix.org", "Mary"),
])
self.rooms["@renko:matrix.org"].extend([
Room("!test:matrix.org", "Test", "Test room"),
Room("!mary:matrix.org", "Mary",
"Lorem ipsum sit dolor amet this is a long text to test "
"wrapping of room subtitle etc 1234 example foo bar abc", 2),
Room("@renko:matrix.org", "!foo:matrix.org", "Another room"),
Room("!foo:matrix.org", "Another room"),
])
Room("@mary:matrix.org", "!test:matrix.org", "Test", "Test room"),
Room("@mary:matrix.org", "!mary:matrix.org", "Renko",
"Lorem ipsum sit dolor amet"),
self.rooms["@mary:matrix.org"].extend([
Room("!test:matrix.org", "Test", "Test room"),
Room("!mary:matrix.org", "Renko", "Lorem ipsum sit dolor amet"),
])
self.messages["!test:matrix.org"].extend([

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 7.33l2.829-2.83 9.175 9.339 9.167-9.339 2.829 2.83-11.996 12.17z"/></svg>

After

Width:  |  Height:  |  Size: 168 B

1
harmonyqml/icons/up.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 16.67l2.829 2.83 9.175-9.339 9.167 9.339 2.829-2.83-11.996-12.17z"/></svg>

After

Width:  |  Height:  |  Size: 169 B