First commit.

square-messages
Black Hat 2018-02-23 22:39:14 +08:00
commit c2f01ec1c4
20 changed files with 988 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

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

BIN
asset/font/material.ttf Normal file

Binary file not shown.

BIN
asset/img/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
asset/img/background.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 KiB

37
main.cpp Normal file
View File

@ -0,0 +1,37 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "connection.h"
#include "room.h"
#include "user.h"
#include "jobs/syncjob.h"
#include "settings.h"
using namespace QMatrixClient;
// https://forum.qt.io/topic/57809
Q_DECLARE_METATYPE(SyncJob*)
Q_DECLARE_METATYPE(Room*)
int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
qmlRegisterType<SyncJob>(); qRegisterMetaType<SyncJob*> ("SyncJob*");
qmlRegisterType<Room>(); qRegisterMetaType<Room*> ("Room*");
qmlRegisterType<User>(); qRegisterMetaType<User*> ("User*");
qmlRegisterType<Connection> ("Matrique", 0, 1, "Connection");
// qmlRegisterType<MessageEventModel> ("Matrique", 0, 1, "MessageEventModel");
// qmlRegisterType<RoomListModel> ("Matrique", 0, 1, "RoomListModel");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}

45
matrique.pro Normal file
View File

@ -0,0 +1,45 @@
QT += quick
CONFIG += c++14
include(matrix/libqmatrixclient/libqmatrixclient.pri)
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# 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
SOURCES += main.cpp
RESOURCES += \
res.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
ChatForm.qml \
LoginForm.qml \
main.qml \
Home.qml \
Login.qml \
ImageStatus.qml \
ButtonDelegate.qml \
SideNav.qml \
ContactListForm.qml \
ContactDetailForm.qml \
Contact.qml \
Setting.qml

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

17
qml/Contact.qml Normal file
View File

@ -0,0 +1,17 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import "qrc:/qml/form"
Page {
ContactListForm {
id: contactListForm
height: parent.height
width: 320
}
ContactDetailForm {
id: contactDetailForm
anchors.fill: parent
anchors.leftMargin: contactListForm.width
}
}

17
qml/Home.qml Normal file
View File

@ -0,0 +1,17 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import "qrc:/qml/form"
Page {
ContactListForm {
id: contactListForm
height: parent.height
width: 320
}
ChatForm {
id: chatForm
anchors.fill: parent
anchors.leftMargin: contactListForm.width
}
}

130
qml/Login.qml Normal file
View File

@ -0,0 +1,130 @@
import QtQuick 2.10
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.3
import "qrc:/qml/component"
Page {
property var window
property alias username: usernameField.text
property alias password: passwordField.text
Row {
anchors.fill: parent
Pane {
width: parent.width / 2
height: parent.height
background: Item {
Image {
id: background
anchors.fill: parent
source: "qrc:/asset/img/background.jpg"
fillMode: Image.PreserveAspectCrop
}
ColorOverlay {
anchors.fill: background
source: background
color: "#b000796b"
}
}
Column {
x: 32
anchors.verticalCenter: parent.verticalCenter
Label {
text: "MATRIX LOGIN."
font.pointSize: 36
font.bold: true
color: "white"
}
Label {
text: "A NEW METHOD OF MESSAGING"
font.pointSize: 12
color: "white"
}
}
}
Pane {
width: parent.width / 2
height: parent.height
padding: 64
Column {
id: main_col
spacing: 8
anchors.fill: parent
ImageStatus {
width: 96
height: width
source: "qrc:/asset/img/avatar.png"
anchors.horizontalCenter: parent.horizontalCenter
}
TextField {
id: serverField
width: parent.width
height: 48
placeholderText: "Server"
leftPadding: 16
topPadding: 0
bottomPadding: 0
background: Rectangle {
color: "#eaeaea"
border.color: parent.activeFocus ? Material.accent : "transparent"
border.width: 2
}
}
TextField {
id: usernameField
width: parent.width
height: 48
placeholderText: "Username"
leftPadding: 16
topPadding: 0
bottomPadding: 0
background: Rectangle {
color: "#eaeaea"
border.color: parent.activeFocus ? Material.accent : "transparent"
border.width: 2
}
}
TextField {
id: passwordField
width: parent.width
height: 48
placeholderText: "Password"
leftPadding: 16
topPadding: 0
bottomPadding: 0
background: Rectangle {
color: "#eaeaea"
border.color: parent.activeFocus ? Material.accent : "transparent"
border.width: 2
}
}
Button {
id: loginButton
text: "LOGIN"
highlighted: true
width: parent.width
onClicked: window.login()
}
}
}
}
}

40
qml/Setting.qml Normal file
View File

@ -0,0 +1,40 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
Page {
TabBar {
id: settingBar
width: parent.width
z: 10
currentIndex: settingBar.currentIndex
TabButton {
text: qsTr("Overview")
}
TabButton {
text: qsTr("Network")
}
TabButton {
text: qsTr("Sync")
}
}
SwipeView {
id: settingSwipe
currentIndex: settingBar.currentIndex
anchors.fill: parent
Page {
}
Page {
}
Page {
}
}
}

View File

@ -0,0 +1,36 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
Item {
property int index
property alias contentItem: itemDelegate.contentItem
signal clicked
id: buttonDelegate
Layout.fillWidth: true
Layout.preferredHeight: width
Rectangle {
width: swipeView.currentIndex === index ? parent.width : 0
height: parent.height
anchors.bottom: itemDelegate.bottom
color: Qt.lighter(Material.accent)
Behavior on width {
PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 }
}
}
ItemDelegate {
id: itemDelegate
anchors.fill: parent
onClicked: {
swipeView.currentIndex = index
buttonDelegate.clicked()
}
}
}

View File

@ -0,0 +1,34 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtGraphicalEffects 1.0
Image {
id: avatar
mipmap: true
layer.enabled: true
fillMode: Image.PreserveAspectCrop
layer.effect: OpacityMask {
maskSource: Item {
width: avatar.width
height: avatar.width
Rectangle {
anchors.centerIn: parent
width: avatar.width
height: avatar.width
radius: avatar.width / 2
}
}
}
Rectangle {
id: circle
width: avatar.width
height: avatar.width
radius: avatar.width / 2
color: "transparent"
border.color: "#4caf50"
border.width: 4
}
}

17
qml/component/SideNav.qml Normal file
View File

@ -0,0 +1,17 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
Drawer {
property SwipeView swipeView
interactive: false
position: 1.0
visible: true
modal: false
background: Rectangle {
color: Material.accent
}
}

125
qml/form/ChatForm.qml Normal file
View File

@ -0,0 +1,125 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
import QtGraphicalEffects 1.0
import "qrc:/qml/component"
Item {
ColumnLayout {
anchors.fill: parent
Pane {
z: 10
padding: 16
Layout.fillWidth: true
Layout.preferredHeight: 80
background: Rectangle {
color: "#eaeaea"
}
Row {
anchors.fill: parent
spacing: 16
ImageStatus {
width: parent.height
height: parent.height
source: "qrc:/asset/img/avatar.png"
}
Column {
height: parent.height
Text {
text: "Astolfo"
font.pointSize: 18
color: "#424242"
}
Text {
text: "Rider of Black"
color: "#424242"
}
}
}
}
Pane {
Layout.fillWidth: true
Layout.fillHeight: true
}
Pane {
z: 10
padding: 16
Layout.fillWidth: true
Layout.preferredHeight: 80
RowLayout {
anchors.fill: parent
spacing: 0
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
contentItem: Text {
text: "\ue226"
color: "#424242"
font.pointSize: 16
font.family: materialFont.name
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
TextField {
Layout.fillWidth: true
Layout.fillHeight: true
placeholderText: "Send a Message"
leftPadding: 16
topPadding: 0
bottomPadding: 0
background: Rectangle {
color: "#eaeaea"
}
}
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
contentItem: Text {
text: "\ue24e"
color: parent.pressed ? Material.accent : "#424242"
font.pointSize: 16
font.family: materialFont.name
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: "#eaeaea"
}
}
ItemDelegate {
Layout.preferredWidth: height
Layout.fillHeight: true
contentItem: Text {
text: "\ue163"
color: "#424242"
font.pointSize: 16
font.family: materialFont.name
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}

View File

@ -0,0 +1,112 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
import "qrc:/qml/component"
Item {
ColumnLayout {
anchors.fill: parent
Pane {
Layout.fillWidth: true
Layout.preferredHeight: 250
padding: 32
background: Rectangle {
color: Material.accent
}
Column {
anchors.fill: parent
ImageStatus {
z: 10
width: 96
height: width
source: "qrc:/asset/img/avatar.png"
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Astolfo"
color: "white"
font.pointSize: 28
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Rider of Black"
color: "#cdcdcd"
font.pointSize: 12
anchors.horizontalCenter: parent.horizontalCenter
}
Row {
height: 48
anchors.horizontalCenter: parent.horizontalCenter
ItemDelegate {
width: parent.height
height: parent.height
contentItem: Text {
text: "\ue0b7"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
ItemDelegate {
width: parent.height
height: parent.height
contentItem: Text {
text: "\ue62e"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
Pane {
Layout.fillWidth: true
Layout.fillHeight: true
leftPadding: 96
rightPadding: 96
GridLayout {
width: parent.width
columns: 2
flow: GridLayout.LeftToRight
anchors.horizontalCenter: parent.horizontalCenter
columnSpacing: 32
Text {
text: "Matrix ID"
}
Text {
Layout.fillWidth: true
text: "Welcome"
}
Text {
text: "Status"
}
Text {
text: "Overline"
}
}
}
}
}

View File

@ -0,0 +1,174 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import QtQuick.Controls.Material 2.3
import "qrc:/qml/component"
Item {
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: serverField
width: parent.width
height: 36
leftPadding: 16
topPadding: 0
bottomPadding: 0
anchors.verticalCenter: parent.verticalCenter
background: Item {
Row {
anchors.fill: parent
Text {
width: parent.height
height: parent.height
text: "\ue8b6"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Text {
height: parent.height
text: "Search"
color: "white"
font.pointSize: 12
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
Rectangle {
width: serverField.activeFocus || serverField.text != "" ? parent.width : 0
height: parent.height
color: "white"
Behavior on width {
PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 }
}
}
}
}
}
Pane {
Layout.fillWidth: true
Layout.fillHeight: true
padding: 0
background: Rectangle {
color: "#eaeaea"
}
ListModel {
id: listModel
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
ListElement {
name: "Bill Smith"
number: "555 3264"
}
ListElement {
name: "John Brown"
number: "555 8426"
}
ListElement {
name: "Sam Wise"
number: "555 0473"
}
}
ListView {
id: listView
width: parent.width
height: parent.height
model: listModel
highlight: Rectangle {
color: Material.accent
opacity: 0.2
}
ScrollBar.vertical: ScrollBar { id: scrollBar }
delegate: ItemDelegate {
width: parent.width
height: 80
onClicked: listView.currentIndex = index
contentItem: Item {
Row {
spacing: 16
ImageStatus {
width: parent.height
height: parent.height
source: "qrc:/asset/img/avatar.png"
}
Column {
Text {
text: name
color: "#424242"
}
Text {
text: number
color: "#424242"
}
}
}
}
}
}
}
}
}

168
qml/main.qml Normal file
View File

@ -0,0 +1,168 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.2
import QtGraphicalEffects 1.0
import Qt.labs.settings 1.0
import "qrc:/qml/component"
import "qrc:/qml/form"
import Matrique 0.1
ApplicationWindow {
id: window
visible: true
width: 960
height: 640
title: qsTr("Matrique")
Connection { id: connection }
Settings {
id: settings
property alias user: loginPage.username
property alias pass: loginPage.password
property var token
}
FontLoader { id: materialFont; source: "qrc:/asset/font/material.ttf" }
function login() {
console.info("Login is invoked.")
var connect = connection.connectToServer
connection.connected.connect(function() {
settings.user = connection.userId()
settings.token = connection.accessToken
connection.connectionError.connect(connection.reconnect)
connection.syncDone.connect(resync)
connection.reconnected.connect(resync)
connection.sync()
})
var userParts = settings.user.split(':')
if(userParts.length === 1 || userParts[1] === "matrix.org") { // If this user uses default server.
console.info("Matrix server is used.")
connect(settings.user, settings.pass, "Device")
} else {
connection.resolved.connect(function() {
connect(settings.user, settings.pass, "Device")
})
connection.resolveError.connect(function() {
console.info("Couldn't resolve server!")
})
connection.resolveServer(userParts[1])
}
}
SideNav {
id: sideNav
width: 80
height: window.height
ColumnLayout {
anchors.fill: parent
spacing: 0
ButtonDelegate {
index: 0
contentItem: ImageStatus {
width: parent.width
height: parent.width
source: "qrc:/asset/img/avatar.png"
anchors.horizontalCenter: parent.horizontalCenter
}
}
Rectangle {
color: "transparent"
Layout.fillHeight: true
}
ButtonDelegate {
index: 1
contentItem: Text {
text: "\ue853"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
ButtonDelegate {
index: 2
contentItem: Text {
text: "\ue5d2"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
ButtonDelegate {
index: 3
contentItem: Text {
text: "\ue8b8"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
ButtonDelegate {
index: 4
contentItem: Text {
text: "\ue879"
font.pointSize: 16
font.family: materialFont.name
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: Qt.quit()
}
}
}
SwipeView {
id: swipeView
anchors.fill: parent
anchors.leftMargin: sideNav.width
interactive: false
orientation: Qt.Vertical
Home {
}
Login {
id: loginPage
window: window
}
Contact {
}
Setting {
}
}
}

13
qtquickcontrols2.conf Normal file
View File

@ -0,0 +1,13 @@
; This file can be edited to change the style of the application
; Read "Qt Quick Controls 2 Configuration File" for details:
; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
[Controls]
Style=Material
[Material]
Theme=Light
Primary=#00695c
Accent=#00695c
;Foreground=Black
;Background=#161616

19
res.qrc Normal file
View File

@ -0,0 +1,19 @@
<RCC>
<qresource prefix="/">
<file>qtquickcontrols2.conf</file>
<file>asset/img/avatar.png</file>
<file>asset/img/background.jpg</file>
<file>asset/font/material.ttf</file>
<file>qml/Contact.qml</file>
<file>qml/Home.qml</file>
<file>qml/Login.qml</file>
<file>qml/main.qml</file>
<file>qml/Setting.qml</file>
<file>qml/component/ButtonDelegate.qml</file>
<file>qml/component/ImageStatus.qml</file>
<file>qml/component/SideNav.qml</file>
<file>qml/form/ChatForm.qml</file>
<file>qml/form/ContactDetailForm.qml</file>
<file>qml/form/ContactListForm.qml</file>
</qresource>
</RCC>