Add basic support for multiple windows

This commit is contained in:
Nicolas Werner 2022-05-06 00:36:38 +02:00
parent 19642bc7ab
commit b75ef07896
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
11 changed files with 109 additions and 41 deletions

View File

@ -232,13 +232,7 @@ Item {
} }
} }
Connections { Window.onActiveChanged: readTimer.running = Window.active
function onFocusChanged() {
readTimer.running = TimelineManager.isWindowFocused;
}
target: TimelineManager
}
Timer { Timer {
id: readTimer id: readTimer

View File

@ -64,6 +64,41 @@ Page {
target: Rooms target: Rooms
} }
Component {
id: roomWindowComponent
ApplicationWindow {
id: roomWindowW
property var room: null
property var roomPreview: null
onActiveChanged: if (active) {MainWindow.activeRoom = (room.roomId || roomPreview.roomid)}
height: 650
width: 420
minimumWidth: 150
minimumHeight: 150
palette: Nheko.colors
color: Nheko.colors.window
title: room.roomName
modality: Qt.NonModal
flags: Qt.Window | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
Shortcut {
sequence: StandardKey.Cancel
onActivated: roomWindowW.close()
}
TimelineView {
anchors.fill: parent
room: roomWindowW.room
roomPreview: roomWindowW.roomPreview.roomid ? roomWindowW.roomPreview : null
}
}
}
Platform.Menu { Platform.Menu {
id: roomContextMenu id: roomContextMenu
@ -86,6 +121,18 @@ Page {
} }
} }
Platform.MenuItem {
text: qsTr("Open separately")
onTriggered: {
var roomWindow = roomWindowComponent.createObject(null, {
"room": Rooms.getRoomById(roomContextMenu.roomid),
"roomPreview": Rooms.getRoomPreviewById(roomContextMenu.roomid)
});
roomWindow.showNormal();
destroyOnClose(roomWindow);
}
}
Platform.MenuItem { Platform.MenuItem {
text: qsTr("Leave room") text: qsTr("Leave room")
onTriggered: TimelineManager.openLeaveRoomDialog(roomContextMenu.roomid) onTriggered: TimelineManager.openLeaveRoomDialog(roomContextMenu.roomid)
@ -97,7 +144,7 @@ Page {
Instantiator { Instantiator {
model: Communities.tagsWithDefault model: Communities.tagsWithDefault
onObjectAdded: roomContextMenu.insertItem(index + 2, object) onObjectAdded: roomContextMenu.insertItem(index + 3, object)
onObjectRemoved: roomContextMenu.removeItem(object) onObjectRemoved: roomContextMenu.removeItem(object)
delegate: Platform.MenuItem { delegate: Platform.MenuItem {

View File

@ -25,6 +25,8 @@ Pane {
background: null background: null
padding: 0 padding: 0
Window.onActiveChanged: if (Window.active) {MainWindow.activeRoom = Qt.binding(function() { return Rooms.currentRoom.roomId || Rooms.currentRoomPreview.roomid })}
FontMetrics { FontMetrics {
id: fontMetrics id: fontMetrics
} }

View File

@ -813,7 +813,7 @@ ChatPage::changeRoom(const QString &room_id)
void void
ChatPage::inviteUser(QString userid, QString reason) ChatPage::inviteUser(QString userid, QString reason)
{ {
auto room = currentRoom(); auto room = MainWindow::instance()->activeRoom();
if (QMessageBox::question(nullptr, if (QMessageBox::question(nullptr,
tr("Confirm invite"), tr("Confirm invite"),
@ -839,7 +839,7 @@ ChatPage::inviteUser(QString userid, QString reason)
void void
ChatPage::kickUser(QString userid, QString reason) ChatPage::kickUser(QString userid, QString reason)
{ {
auto room = currentRoom(); auto room = MainWindow::instance()->activeRoom();
bool confirmed; bool confirmed;
reason = reason =
@ -870,7 +870,7 @@ ChatPage::kickUser(QString userid, QString reason)
void void
ChatPage::banUser(QString userid, QString reason) ChatPage::banUser(QString userid, QString reason)
{ {
auto room = currentRoom(); auto room = MainWindow::instance()->activeRoom();
bool confirmed; bool confirmed;
reason = reason =
@ -901,7 +901,7 @@ ChatPage::banUser(QString userid, QString reason)
void void
ChatPage::unbanUser(QString userid, QString reason) ChatPage::unbanUser(QString userid, QString reason)
{ {
auto room = currentRoom(); auto room = MainWindow::instance()->activeRoom();
if (QMessageBox::question(nullptr, if (QMessageBox::question(nullptr,
tr("Confirm unban"), tr("Confirm unban"),
@ -1398,9 +1398,11 @@ ChatPage::handleMatrixUri(QString uri)
if (sigil1 == u"u") { if (sigil1 == u"u") {
if (action.isEmpty()) { if (action.isEmpty()) {
auto t = view_manager_->rooms()->currentRoom(); auto t = MainWindow::instance()->activeRoom();
if (t && cache::isRoomMember(mxid1.toStdString(), t->roomId().toStdString())) { if (!t.isEmpty() && cache::isRoomMember(mxid1.toStdString(), t.toStdString())) {
t->openUserProfile(mxid1); auto rm = view_manager_->rooms()->getRoomById(t);
if (rm)
rm->openUserProfile(mxid1);
return true; return true;
} }
emit view_manager_->openGlobalUserProfile(mxid1); emit view_manager_->openGlobalUserProfile(mxid1);
@ -1466,14 +1468,5 @@ ChatPage::handleMatrixUri(const QUrl &uri)
bool bool
ChatPage::isRoomActive(const QString &room_id) ChatPage::isRoomActive(const QString &room_id)
{ {
return MainWindow::instance()->isActive() && currentRoom() == room_id; return QGuiApplication::focusWindow() && MainWindow::instance()->activeRoom() == room_id;
}
QString
ChatPage::currentRoom() const
{
if (view_manager_->rooms()->currentRoom())
return view_manager_->rooms()->currentRoom()->roomId();
else
return QString();
} }

View File

@ -72,8 +72,6 @@ public:
mtx::presence::PresenceState currentPresence() const; mtx::presence::PresenceState currentPresence() const;
// TODO(Nico): Get rid of this!
QString currentRoom() const;
void startChat(QString userid, std::optional<bool> encryptionEnabled); void startChat(QString userid, std::optional<bool> encryptionEnabled);
public slots: public slots:

View File

@ -40,6 +40,7 @@ class ReCaptcha;
class MainWindow : public QQuickView class MainWindow : public QQuickView
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString activeRoom READ activeRoom WRITE updateActiveRoom NOTIFY activeRoomChanged)
public: public:
explicit MainWindow(QWindow *parent = nullptr); explicit MainWindow(QWindow *parent = nullptr);
@ -58,6 +59,15 @@ public:
bool dbusAvailable() const { return dbusAvailable_; } bool dbusAvailable() const { return dbusAvailable_; }
#endif #endif
QString activeRoom() const { return activeRoom_; }
void updateActiveRoom(QString r)
{
if (activeRoom_ != r) {
activeRoom_ = std::move(r);
emit activeRoomChanged();
}
}
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
bool event(QEvent *event) override; bool event(QEvent *event) override;
@ -78,6 +88,8 @@ signals:
void switchToWelcomePage(); void switchToWelcomePage();
void switchToLoginPage(QString error); void switchToLoginPage(QString error);
void activeRoomChanged();
private: private:
void showDialog(QWidget *dialog); void showDialog(QWidget *dialog);
bool hasActiveUser(); bool hasActiveUser();
@ -101,6 +113,8 @@ private:
MxcImageProvider *imgProvider = nullptr; MxcImageProvider *imgProvider = nullptr;
QString activeRoom_;
#ifdef NHEKO_DBUS_SYS #ifdef NHEKO_DBUS_SYS
bool dbusAvailable_{false}; bool dbusAvailable_{false};
#endif #endif

View File

@ -692,6 +692,34 @@ RoomlistModel::leave(QString roomid, QString reason)
} }
} }
RoomPreview
RoomlistModel::getRoomPreviewById(QString roomid) const
{
RoomPreview preview{};
if (invites.contains(roomid) || previewedRooms.contains(roomid)) {
std::optional<RoomInfo> i;
if (invites.contains(roomid)) {
i = invites.value(roomid);
preview.isInvite_ = true;
} else {
i = previewedRooms.value(roomid);
preview.isInvite_ = false;
}
if (i) {
preview.roomid_ = roomid;
preview.roomName_ = QString::fromStdString(i->name);
preview.roomTopic_ = QString::fromStdString(i->topic);
preview.roomAvatarUrl_ = QString::fromStdString(i->avatar_url);
} else {
preview.roomid_ = roomid;
}
}
return preview;
}
void void
RoomlistModel::setCurrentRoom(QString roomid) RoomlistModel::setCurrentRoom(QString roomid)
{ {

View File

@ -89,6 +89,7 @@ public:
else else
return {}; return {};
} }
RoomPreview getRoomPreviewById(QString roomid) const;
public slots: public slots:
void initializeRooms(); void initializeRooms();
@ -185,6 +186,10 @@ public slots:
{ {
return roomlistmodel->getRoomById(id).data(); return roomlistmodel->getRoomById(id).data();
} }
RoomPreview getRoomPreviewById(QString roomid) const
{
return roomlistmodel->getRoomPreviewById(roomid);
}
void nextRoomWithActivity(); void nextRoomWithActivity();
void nextRoom(); void nextRoom();

View File

@ -1072,7 +1072,7 @@ TimelineModel::setCurrentIndex(int index)
if (index != oldIndex) if (index != oldIndex)
emit currentIndexChanged(index); emit currentIndexChanged(index);
if (MainWindow::instance() != QGuiApplication::focusWindow()) if (MainWindow::instance()->activeRoom() != roomId())
return; return;
if (!currentId.startsWith('m')) { if (!currentId.startsWith('m')) {

View File

@ -138,10 +138,6 @@ TimelineViewManager::TimelineViewManager(CallManager *, ChatPage *parent)
isInitialSync_ = true; isInitialSync_ = true;
emit initialSyncChanged(true); emit initialSyncChanged(true);
}); });
connect(qobject_cast<QApplication *>(QApplication::instance()),
&QApplication::focusWindowChanged,
this,
&TimelineViewManager::focusChanged);
connect(parent, &ChatPage::connectionLost, this, [this] { connect(parent, &ChatPage::connectionLost, this, [this] {
isConnected_ = false; isConnected_ = false;
emit isConnectedChanged(false); emit isConnectedChanged(false);
@ -152,12 +148,6 @@ TimelineViewManager::TimelineViewManager(CallManager *, ChatPage *parent)
}); });
} }
bool
TimelineViewManager::isWindowFocused() const
{
return MainWindow::instance() == QApplication::focusWindow();
}
void void
TimelineViewManager::openRoomMembers(TimelineModel *room) TimelineViewManager::openRoomMembers(TimelineModel *room)
{ {

View File

@ -41,7 +41,6 @@ class TimelineViewManager : public QObject
Q_PROPERTY( Q_PROPERTY(
bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged) bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
Q_PROPERTY(bool isWindowFocused READ isWindowFocused NOTIFY focusChanged)
Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged) Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged)
public: public:
@ -54,7 +53,6 @@ public:
void clearAll() { rooms_->clear(); } void clearAll() { rooms_->clear(); }
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; } Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
bool isWindowFocused() const;
bool isConnected() const { return isConnected_; } bool isConnected() const { return isConnected_; }
Q_INVOKABLE void openImageOverlay(TimelineModel *room, QString mxcUrl, QString eventId); Q_INVOKABLE void openImageOverlay(TimelineModel *room, QString mxcUrl, QString eventId);
Q_INVOKABLE void openImagePackSettings(QString roomid); Q_INVOKABLE void openImagePackSettings(QString roomid);
@ -82,7 +80,6 @@ signals:
void inviteUsers(QString roomId, QStringList users); void inviteUsers(QString roomId, QStringList users);
void showRoomList(); void showRoomList();
void narrowViewChanged(); void narrowViewChanged();
void focusChanged();
void focusInput(); void focusInput();
void openRoomMembersDialog(MemberList *members, TimelineModel *room); void openRoomMembersDialog(MemberList *members, TimelineModel *room);
void openRoomSettingsDialog(RoomSettings *settings); void openRoomSettingsDialog(RoomSettings *settings);