Organize project files
Put QML components into folders, remove unused ones, split __init__.py with engine.py.
This commit is contained in:
parent
cccc43a9ae
commit
76b699ad64
@ -1,54 +0,0 @@
|
||||
import QtQuick 2.7
|
||||
|
||||
ListModel {
|
||||
ListElement {
|
||||
user_id: "@runi:matrix.org"
|
||||
name: "Runi"
|
||||
content: "Lorem ipsum"
|
||||
date: "2019-03-10"
|
||||
time: "19:41:10"
|
||||
}
|
||||
ListElement {
|
||||
user_id: "@runi:matrix.org"
|
||||
name: "Runi"
|
||||
content: "Combine test?"
|
||||
date: "2019-03-10"
|
||||
time: "19:41:12"
|
||||
}
|
||||
ListElement {
|
||||
user_id: "@mary:matrix.org"
|
||||
name: "Mary"
|
||||
content: "sit dolor amet"
|
||||
date: "2019-03-10"
|
||||
time: "19:42:10"
|
||||
}
|
||||
ListElement {
|
||||
user_id: "@runi:matrix.org"
|
||||
name: "Runi but a very long name test lorem ipsum foo bar flour orange water test"
|
||||
content: "blah blah"
|
||||
date: "2019-03-10"
|
||||
time: "19:43:57"
|
||||
}
|
||||
ListElement {
|
||||
user_id: "@runi:matrix.org"
|
||||
name: "Runi"
|
||||
content: "Long message text <b>wxall of text</b> jsqdjlfjlsdjf 1234 zaekfpozekf lorem ipsum foo bar 123 zfjhozj aazaazazaz fdefzef"
|
||||
date: "2019-03-10"
|
||||
time: "19:44:10"
|
||||
}
|
||||
ListElement {
|
||||
user_id: "@renko:matrix.org"
|
||||
name: "Renko"
|
||||
content: "Baaaar."
|
||||
date: "2019-03-10"
|
||||
time: "19:44:22"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
user_id: "@runi:matrix.org"
|
||||
name: "Runi"
|
||||
content: "Test new day"
|
||||
date: "2019-03-11"
|
||||
time: "10:10:47"
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
import QtQuick 2.7
|
||||
|
||||
ListModel {
|
||||
ListElement {
|
||||
account: "Runi"
|
||||
room_name: "Maribel"
|
||||
description: "This is a test ellide"
|
||||
}
|
||||
ListElement {
|
||||
account: "Runi"
|
||||
room_name: "Renko"
|
||||
description: "Away"
|
||||
}
|
||||
ListElement {
|
||||
account: "Runi"
|
||||
room_name: "Moonlight"
|
||||
description: "lorem ispum"
|
||||
}
|
||||
ListElement {
|
||||
account: "Runi"
|
||||
room_name: "test long abc def"
|
||||
description: "WWWWWW WWWWWW WWWW WWWWWW WWWW"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
account: "Maribel"
|
||||
room_name: "Maribel"
|
||||
description: "This is a test ellide"
|
||||
}
|
||||
ListElement {
|
||||
account: "Maribel"
|
||||
room_name: "Moonlight"
|
||||
description: "lorem ispum"
|
||||
}
|
||||
}
|
@ -1,63 +1,16 @@
|
||||
# Copyright 2019 miruka
|
||||
# This file is part of harmonyqml, licensed under GPLv3.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QFileSystemWatcher, QMetaObject, QObject, QTimer, pyqtSlot
|
||||
)
|
||||
from PyQt5.QtGui import QGuiApplication
|
||||
from PyQt5.QtQml import QQmlApplicationEngine, qmlRegisterType
|
||||
|
||||
from .__about__ import __doc__
|
||||
from .backend import DummyBackend
|
||||
from .engine import Engine
|
||||
|
||||
# logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
class Engine(QQmlApplicationEngine):
|
||||
def __init__(self, app: QGuiApplication, parent: Optional[QObject] = None
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self.app = app
|
||||
self.backend = DummyBackend()
|
||||
self.program_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
|
||||
# Set QML properties
|
||||
self.rootContext().setContextProperty("Engine", self)
|
||||
self.rootContext().setContextProperty("Backend", self.backend)
|
||||
|
||||
# Connect Qt signals
|
||||
self.quit.connect(self.app.quit)
|
||||
|
||||
# Make SIGINT (ctrl-c) work
|
||||
self._sigint_timer = QTimer()
|
||||
self._sigint_timer.timeout.connect(lambda: None)
|
||||
self._sigint_timer.start(100)
|
||||
|
||||
# Setup UI live-reloading when a file is edited
|
||||
self.file_watcher = QFileSystemWatcher()
|
||||
self.file_watcher.directoryChanged.connect(lambda _: self.reload_qml())
|
||||
self.file_watcher.addPath(self.program_dir)
|
||||
|
||||
# Load QML page and show window
|
||||
self.load(os.path.join(self.program_dir, "Window.qml"))
|
||||
self.rootObjects()[0].show()
|
||||
sys.exit(self.app.exec())
|
||||
|
||||
|
||||
def reload_qml(self) -> None:
|
||||
self.clearComponentCache()
|
||||
loader = self.rootObjects()[0].findChild(QObject, "UILoader")
|
||||
source = loader.property("source")
|
||||
loader.setProperty("source", None)
|
||||
loader.setProperty("source", source)
|
||||
logging.info("Reloaded: %s", source)
|
||||
|
||||
|
||||
def run() -> None:
|
||||
app = QGuiApplication(sys.argv)
|
||||
_ = Engine(app) # need to keep a reference
|
||||
engine = Engine(app)
|
||||
engine.show_window()
|
||||
|
@ -1,12 +1,14 @@
|
||||
import QtQuick.Controls 1.4 as Controls1
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "side_pane" as SidePane
|
||||
import "chat" as Chat
|
||||
|
||||
//https://doc.qt.io/qt-5/qml-qtquick-controls-splitview.html
|
||||
Controls1.SplitView {
|
||||
anchors.fill: parent
|
||||
|
||||
SidePane {
|
||||
SidePane.Root {
|
||||
Layout.minimumWidth: 36
|
||||
width: 200
|
||||
}
|
||||
@ -17,12 +19,12 @@ Controls1.SplitView {
|
||||
}
|
||||
function show_room(user_obj, room_obj) {
|
||||
pageStack.replace(
|
||||
"ChatPage.qml", { user: user_obj, room: room_obj }
|
||||
"chat/Root.qml", { user: user_obj, room: room_obj }
|
||||
)
|
||||
}
|
||||
|
||||
id: "pageStack"
|
||||
initialItem: ChatPage {
|
||||
initialItem: Chat.Root {
|
||||
user: Backend.accountsModel.get(0)
|
||||
room: Backend.roomsModel[Backend.accountsModel.get(0).user_id].get(0)
|
||||
}
|
@ -18,7 +18,7 @@ Item {
|
||||
visible: ! invisible && imageSource === null
|
||||
color: Qt.hsla(Backend.hueFromString(username), 0.22, 0.5, 1)
|
||||
|
||||
PlainLabel {
|
||||
HLabel {
|
||||
anchors.centerIn: parent
|
||||
text: username.charAt(0)
|
||||
color: "white"
|
@ -8,7 +8,7 @@ ToolButton {
|
||||
|
||||
id: "button"
|
||||
display: ToolButton.IconOnly
|
||||
icon.source: "icons/" + iconName + ".svg"
|
||||
icon.source: "../../icons/" + iconName + ".svg"
|
||||
background: Rectangle { color: "transparent" }
|
||||
|
||||
onClicked: toolTip.hide()
|
@ -1,7 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
PlainLabel {
|
||||
HLabel {
|
||||
id: text
|
||||
ToolTip {
|
||||
delay: Qt.styleHints.mousePressAndHoldInterval
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import "../base" as Base
|
||||
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
text: date_time.toLocaleDateString()
|
||||
width: rootCol.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Column {
|
||||
id: rootCol
|
||||
@ -46,7 +47,7 @@ Column {
|
||||
combine ? standardSpacing / 2 :
|
||||
standardSpacing * 1.2
|
||||
|
||||
DaybreakDelegate { visible: dayBreak }
|
||||
Daybreak { visible: dayBreak }
|
||||
|
||||
|
||||
Row {
|
||||
@ -55,12 +56,12 @@ Column {
|
||||
layoutDirection: isOwn ? Qt.RightToLeft : Qt.LeftToRight
|
||||
anchors.right: isOwn ? parent.right : undefined
|
||||
|
||||
Avatar { id: avatar; invisible: combine; username: displayName }
|
||||
Base.Avatar { id: avatar; invisible: combine; username: displayName }
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
visible: ! combine
|
||||
id: nameLabel
|
||||
text: displayName
|
||||
@ -76,7 +77,7 @@ Column {
|
||||
topPadding: verticalPadding
|
||||
}
|
||||
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
id: contentLabel
|
||||
//text: (isOwn ? "" : content + " ") +
|
||||
//"<font size=" + smallSize + "px color=gray>" +
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
@ -14,14 +15,14 @@ Rectangle {
|
||||
spacing: 12
|
||||
anchors.fill: parent
|
||||
|
||||
Avatar {
|
||||
Base.Avatar {
|
||||
id: "avatar"
|
||||
Layout.alignment: Qt.AlignTop
|
||||
dimmension: root.Layout.minimumHeight
|
||||
username: chatPage.room.display_name
|
||||
}
|
||||
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
id: "roomName"
|
||||
text: chatPage.room.display_name
|
||||
font.pixelSize: bigSize
|
||||
@ -30,13 +31,17 @@ Rectangle {
|
||||
Layout.maximumWidth: row.width - row.spacing * (row.children.length - 1) - avatar.width
|
||||
}
|
||||
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
id: "roomSubtitle"
|
||||
text: chatPage.room.subtitle
|
||||
font.pixelSize: smallSize
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
Layout.maximumWidth: row.width - row.spacing * (row.children.length - 1) - avatar.width - roomName.width
|
||||
Layout.maximumWidth:
|
||||
row.width -
|
||||
row.spacing * (row.children.length - 1) -
|
||||
avatar.width -
|
||||
roomName.width
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
@ -11,6 +11,6 @@ ColumnLayout {
|
||||
onFocusChanged: sendBox.setFocus()
|
||||
|
||||
RoomHeader {}
|
||||
MessageDisplay {}
|
||||
MessageList {}
|
||||
SendBox { id: sendBox }
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
function setFocus() { textArea.forceActiveFocus() }
|
||||
@ -17,7 +18,7 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Avatar {
|
||||
Base.Avatar {
|
||||
id: "avatar"
|
||||
username: chatPage.user.display_name
|
||||
dimmension: root.Layout.minimumHeight
|
@ -1,7 +1,8 @@
|
||||
import QtQuick 2.7
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
anchors.centerIn: parent
|
||||
text: "Add account page"
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import QtQuick 2.7
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
anchors.centerIn: parent
|
||||
text: "Add room page"
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import QtQuick 2.7
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
anchors.centerIn: parent
|
||||
text: "Home page"
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import QtQuick 2.7
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
anchors.centerIn: parent
|
||||
text: "Settings page"
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
ColumnLayout {
|
||||
id: "accountDelegate"
|
||||
@ -11,14 +12,14 @@ ColumnLayout {
|
||||
id: "row"
|
||||
spacing: 0
|
||||
|
||||
Avatar { id: "avatar"; username: display_name; dimmension: 36 }
|
||||
Base.Avatar { id: "avatar"; username: display_name; dimmension: 36 }
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
spacing: 0
|
||||
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
id: "accountLabel"
|
||||
text: display_name
|
||||
elide: Text.ElideRight
|
||||
@ -49,7 +50,7 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
HButton {
|
||||
Base.HToolButton {
|
||||
id: "toggleExpand"
|
||||
iconName: roomList.visible ? "up" : "down"
|
||||
Layout.maximumWidth: 28
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
RowLayout {
|
||||
id: "toolBar"
|
||||
@ -8,28 +9,28 @@ RowLayout {
|
||||
Layout.maximumHeight: 32
|
||||
spacing: 0
|
||||
|
||||
ActionButton {
|
||||
HToolButton {
|
||||
visible: ! toolBarIsBig()
|
||||
iconName: "reduced_menu"
|
||||
tooltip: "Menu"
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
HToolButton {
|
||||
iconName: "settings"
|
||||
tooltip: "Settings"
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
HToolButton {
|
||||
iconName: "add_account"
|
||||
tooltip: "Add new account"
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
HToolButton {
|
||||
iconName: "set_status"
|
||||
tooltip: "Set status for all accounts"
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
HToolButton {
|
||||
iconName: "search"
|
||||
tooltip: "Filter rooms"
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
HButton {
|
||||
Base.HToolButton {
|
||||
function toolBarIsBig() {
|
||||
return sidePane.width >
|
||||
Layout.minimumWidth * (toolBar.children.length - 2)
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
MouseArea {
|
||||
id: "root"
|
||||
@ -17,12 +18,12 @@ MouseArea {
|
||||
id: row
|
||||
spacing: 1
|
||||
|
||||
Avatar { id: avatar; username: display_name; dimmension: 36 }
|
||||
Base.Avatar { id: avatar; username: display_name; dimmension: 36 }
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
id: roomLabel
|
||||
text: display_name
|
||||
elide: Text.ElideRight
|
||||
@ -35,7 +36,7 @@ MouseArea {
|
||||
leftPadding: 5
|
||||
rightPadding: leftPadding
|
||||
}
|
||||
PlainLabel {
|
||||
Base.HLabel {
|
||||
id: subtitleLabel
|
||||
visible: text !== ""
|
||||
text: subtitle
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
ListView {
|
||||
property var user: null
|
@ -1,6 +1,7 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.4
|
||||
import "../base" as Base
|
||||
|
||||
Rectangle {
|
||||
id: sidePane
|
||||
@ -16,6 +17,6 @@ Rectangle {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
ButtonsBar {}
|
||||
HToolBar {}
|
||||
}
|
||||
}
|
59
harmonyqml/engine.py
Normal file
59
harmonyqml/engine.py
Normal file
@ -0,0 +1,59 @@
|
||||
# Copyright 2019 miruka
|
||||
# This file is part of harmonyqml, licensed under GPLv3.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from PyQt5.QtCore import QFileSystemWatcher, QObject, QTimer
|
||||
from PyQt5.QtGui import QGuiApplication
|
||||
from PyQt5.QtQml import QQmlApplicationEngine
|
||||
|
||||
from .__about__ import __doc__
|
||||
from .backend import DummyBackend
|
||||
|
||||
# logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
class Engine(QQmlApplicationEngine):
|
||||
def __init__(self, app: QGuiApplication, parent: Optional[QObject] = None
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self.app = app
|
||||
self.backend = DummyBackend()
|
||||
self.app_dir = Path(sys.argv[0]).resolve().parent
|
||||
|
||||
# Set QML properties
|
||||
self.rootContext().setContextProperty("Engine", self)
|
||||
self.rootContext().setContextProperty("Backend", self.backend)
|
||||
|
||||
# Connect Qt signals
|
||||
self.quit.connect(self.app.quit)
|
||||
|
||||
# Make SIGINT (ctrl-c) work
|
||||
self._sigint_timer = QTimer()
|
||||
self._sigint_timer.timeout.connect(lambda: None)
|
||||
self._sigint_timer.start(100)
|
||||
|
||||
# Setup UI live-reloading when a file is edited
|
||||
self.file_watcher = QFileSystemWatcher()
|
||||
self.file_watcher.directoryChanged.connect(lambda _: self.reload_qml())
|
||||
self.file_watcher.addPath(str(self.app_dir / "components"))
|
||||
|
||||
# Load QML page and show window
|
||||
self.load(str(self.app_dir / "components" / "Window.qml"))
|
||||
|
||||
|
||||
def show_window(self) -> None:
|
||||
self.rootObjects()[0].show()
|
||||
sys.exit(self.app.exec())
|
||||
|
||||
|
||||
def reload_qml(self) -> None:
|
||||
self.clearComponentCache()
|
||||
loader = self.rootObjects()[0].findChild(QObject, "UILoader")
|
||||
source = loader.property("source")
|
||||
loader.setProperty("source", None)
|
||||
loader.setProperty("source", source)
|
||||
logging.info("Reloaded: %s", source)
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user