Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Room list in demo client #32

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,15 @@ quotient_ispushruleenabledjob_wrapper.h
quotient_redirecttoidpjob_wrapper.cpp
pyquotient_module_wrapper.cpp
quotient_getprotocolmetadatajob_wrapper.h
quotient_settingsgroup_wrapper.h
quotient_requesttokentoresetpasswordemailjob_wrapper.h
quotient_getroomeventsjob_wrapper.cpp
quotient_getversionsjob_wrapper.cpp
quotient_querypublicroomsjob_wrapper.cpp
quotient_querykeysjob_deviceinformation_wrapper.cpp
quotient_bind3pidjob_wrapper.cpp
quotient_pushruleset_wrapper.cpp
quotient_accountsettings_wrapper.h
quotient_user_wrapper.cpp
quotient_searchjob_groupings_wrapper.h
quotient_requestopenidtokenjob_wrapper.h
Expand Down Expand Up @@ -171,9 +173,11 @@ quotient_setaccountdataperroomjob_wrapper.cpp
quotient_getuserprofilejob_wrapper.cpp
quotient_gettokenownerjob_wrapper.cpp
quotient_getpublicroomsjob_wrapper.cpp
quotient_settingsgroup_wrapper.cpp
quotient_geturlpreviewjob_wrapper.h
quotient_getpushersjob_pusherdata_wrapper.h
quotient_getpushruleactionsjob_wrapper.cpp
quotient_accountsettings_wrapper.cpp
quotient_querykeysjob_unsigneddeviceinfo_wrapper.cpp
quotient_getroomtagsjob_wrapper.cpp
quotient_getmembersbyroomjob_wrapper.h
Expand Down
19 changes: 1 addition & 18 deletions PyQuotient/typesystems/typesystem_connection.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,6 @@
<load-typesystem name="csapi/login.xml" generate="no" />

<namespace-type name="Quotient">
<object-type name="Connection">
<!-- syncLoop() -->
<!-- int timeout = 30000 -->
<!-- <property name="localUser" type="User" get="user" />
<property name="localUserId" type="QString" get="userId" />
<property name="domain" type="QString" get="domain" />
<property name="deviceId" type="QString" get="deviceId" />
<property name="accessToken" type="QByteArray" get="accessToken" />
<property name="isLoggedIn" type="bool" get="isLoggedIn" />
<property name="defaultRoomVersion" type="QString" get="defaultRoomVersion" />
<property name="homeserver" type="QUrl" get="homeserver" set="setHomeserver" /> -->
<!-- <property name="loginFlows" type="QVector&lt;Quotient::GetLoginFlowsJob::LoginFlow&gt;" get="loginFlows" /> -->
<!-- <property name="isUsable" type="bool" get="isUsable" />
<property name="supportsSso" type="bool" get="supportsSso" />
<property name="supportsPasswordAuth" type="bool" get="supportsPasswordAuth" />
<property name="cacheState" type="bool" get="cacheState" />
<property name="lazyLoading" type="bool" get="lazyLoading" /> -->
</object-type>
<object-type name="Connection" />
</namespace-type>
</typesystem>
6 changes: 6 additions & 0 deletions PyQuotient/typesystems/typesystem_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@

<namespace-type name="Quotient">
<object-type name="Settings" />
<object-type name="SettingsGroup">
<declare-function signature="SettingsGroup(QString)" />
</object-type>
<object-type name="AccountSettings">
<declare-function signature="AccountSettings(QString)" />
</object-type>
</namespace-type>
</typesystem>
37 changes: 37 additions & 0 deletions demo/accountregistry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from typing import List
from PySide6 import QtCore
from PyQuotient import Quotient
from __feature__ import snake_case, true_property


class Account(Quotient.Connection):
...


class AccountRegistry(QtCore.QObject):
addedAccount = QtCore.Signal(Account)
aboutToDropAccount = QtCore.Signal(Account)

def __init__(self) -> None:
super().__init__()
self.accounts: List[Account] = []

def __len__(self):
return len(self.accounts)

def __getitem__(self, position):
return self.accounts[position]

def add(self, account: Account) -> None:
if (account in self.accounts):
return

self.accounts.append(account)
self.addedAccount.emit(account)

def drop(self, account: Account) -> None:
self.aboutToDropAccount.emit(account)
self.accounts.remove(account)

def is_logged_in(self, user_id: str) -> bool:
return next((user for user in self.accounts if user.user_id == user_id), None) is not None
7 changes: 4 additions & 3 deletions demo/logindialog.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from PySide6 import QtCore, QtWidgets, QtGui
from PyQuotient import Quotient
from __feature__ import snake_case, true_property

from PyQuotient import Quotient
from .dialog import Dialog


Expand Down Expand Up @@ -157,8 +157,9 @@ def on_user_edit_editing_finished(self):
self.buttons.button(QtWidgets.QDialogButtonBox.Ok).enabled = False
self.connection.resolve_server(user_id)

@QtCore.Slot(str)
def on_server_edit_editing_finished(self, server: str):
@QtCore.Slot()
def on_server_edit_editing_finished(self):
server = self.server_edit.text
hs_url = QtCore.QUrl(server)
if hs_url.is_valid():
self.connection.homerserver = server
Expand Down
88 changes: 83 additions & 5 deletions demo/mainwindow.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,72 @@
import math

from PySide6 import QtCore, QtWidgets, QtGui
from __feature__ import snake_case, true_property

from PyQuotient import Quotient
from demo.accountregistry import AccountRegistry
from demo.logindialog import LoginDialog
from demo.roomlistdock import RoomListDock
from demo.pyquaternionroom import PyquaternionRoom
from __feature__ import snake_case, true_property


class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()

self.text_label = QtWidgets.QLabel("Welcome to PyQuotient demo!")
self.login_dialog = None
self.connection_menu = None
self.logout_menu = None
# FIXME: This will be a problem when we get ability to show
# several rooms at once.
self.current_room = None

self.set_central_widget(self.text_label)
self.account_registry = AccountRegistry()
self.room_list_dock = RoomListDock(self)
self.room_list_dock.roomSelected.connect(self.select_room)
self.add_dock_widget(QtCore.Qt.LeftDockWidgetArea, self.room_list_dock)

self.create_menu()
# Only GUI, account settings will be loaded in invoke_login
self.load_settings()

timer = QtCore.QTimer(self)
timer.single_shot = True
timer.timeout.connect(self.invoke_login)
timer.start(0)

def __del__(self):
self.save_settings()

def load_settings(self):
sg = Quotient.SettingsGroup("UI/MainWindow")
# TODO: fix rect value, is None
# if sg.contains("normal_geometry"):
# self.geometry = sg.value("normal_geometry")
if sg.value("maximized"):

self.show_maximized()
# TODO: fix value, is None
# if sg.contains("window_parts_state"):
# self.restore_state(sg.value("window_parts_state"))

def save_settings(self):
sg = Quotient.SettingsGroup("UI/MainWindow")
sg.set_value("normal_geometry", self.normal_geometry)
sg.set_value("maximized", self.maximized)
sg.set_value("window_parts_state", self.save_state())
sg.sync()

@QtCore.Slot()
def invoke_login(self):
accounts = Quotient.SettingsGroup("Accounts").child_groups()
auto_logged_in = False
for account_id in accounts:
account = Quotient.AccountSettings()
if account.homeserver:
access_token = self.load_access_token(account)

def load_access_token(self, account: Quotient.AccountSettings):
...

@QtCore.Slot()
def open_login_window(self):
Expand All @@ -44,6 +92,8 @@ def quit(self):

def add_connection(self, connection: Quotient.Connection, device_name: str):
connection.lazy_loading = True
self.account_registry.add(connection)
self.room_list_dock.add_connection(connection)
connection.syncLoop(30000)

logout_action = self.logout_menu.add_action(connection.local_user_id, lambda: self.logout(connection))
Expand Down Expand Up @@ -148,6 +198,7 @@ def on_reconnection_timer_timeout(self, connection: Quotient.Connection):

def on_logged_out(self, connection: Quotient.Connection):
self.status_bar().show_message(f'Logged out as {connection.local_user_id}', 3000)
self.account_registry.drop(connection)
self.drop_connection(connection)

def create_menu(self):
Expand All @@ -166,4 +217,31 @@ def show_millis_to_recon(self, connection: Quotient.Connection):
"""
self.status_bar().show_message('Couldn\'t connect to the server as {user}; will retry within {seconds} seconds'.format(
user=connection.local_user_id, seconds=math.ceil(connection.millis_to_reconnect)
))
))

@QtCore.Slot(PyquaternionRoom)
def select_room(self, room: PyquaternionRoom) -> None:
if room is not None:
print(f'Opening room {room.object_name()}')
elif self.current_room is not None:
print(f'Closing room {self.current_room.object_name()}')

if self.current_room is not None:
self.current_room.displaynameChanged.disconnect(self.current_room_displayname_changed)

self.current_room = room
new_window_title = ''
if self.current_room:
new_window_title = self.current_room.display_name()
self.current_room.displaynameChanged.connect(self.current_room_displayname_changed)

self.window_title = new_window_title
self.room_list_dock.set_selected_room(self.current_room)

if room is not None and not self.is_active_window():
self.show()
self.activate_window()

@QtCore.Slot()
def current_room_displayname_changed(self):
self.window_title = self.current_room.displayName()
43 changes: 43 additions & 0 deletions demo/models/abstractroomordering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from __future__ import annotations
from typing import List, Optional, TYPE_CHECKING


from PySide6 import QtCore
from PyQuotient import Quotient
if TYPE_CHECKING:
from demo.models.roomlistmodel import RoomListModel
from __feature__ import snake_case, true_property


class RoomGroup:
SystemPrefix = "im.quotient."
LegacyPrefix = "org.qmatrixclient."

def __init__(self, key: str, rooms: Optional[List[Quotient.Room]] = None):
Aksem marked this conversation as resolved.
Show resolved Hide resolved
self.key = key
self.rooms: List[Quotient.Room] = []
if rooms is not None:
self.rooms = rooms

def __eq__(self, o: object) -> bool:
if isinstance(o, RoomGroup):
return self.key == o.key
return self.key == o

def __repr__(self) -> str:
return f"RoomGroup(key='{self.key}', len(rooms)={len(self.rooms)})"


RoomGroups = List[RoomGroup]


class AbstractRoomOrdering(QtCore.QObject):
def __init__(self, model: RoomListModel) -> None:
super().__init__(model)
self.model = model

def room_groups(self, room: Quotient.Room) -> RoomGroups:
return []

def update_groups(self, room: Quotient.Room) -> None:
self.model.update_groups(room)
Loading