gui: support multiple windows in single instance

Running ollie-gui a second time now opens a new window in the
existing process (via NewWindow D-Bus method) instead of just
raising the existing window. The single-instance guard remains.

Each window gets its own ChatBlockModel via QML instantiation
(ChatPane.qml), so windows can display independent sessions.
This commit is contained in:
Levi Neely 2026-07-27 09:05:14 +02:00
parent fad8baaa1b
commit 325870e38c
1 changed files with 18 additions and 15 deletions

View File

@ -30,13 +30,15 @@ public:
{
}
void setWindowUrl(const QUrl &url) { m_url = url; }
public slots:
void Activate()
{
const auto roots = m_engine->rootObjects();
if (roots.isEmpty())
return;
auto *window = qobject_cast<QWindow *>(roots.first());
auto *window = qobject_cast<QWindow *>(roots.last());
if (!window)
return;
window->show();
@ -44,6 +46,13 @@ public slots:
window->requestActivate();
}
void NewWindow()
{
if (m_url.isEmpty())
return;
m_engine->load(m_url);
}
void SelectSession(const QString &id)
{
auto *dbus = qobject_cast<OllieDBusClient *>(
@ -55,6 +64,7 @@ public slots:
private:
QQmlApplicationEngine *m_engine;
QUrl m_url;
};
static QIcon makeBrainIcon()
@ -125,7 +135,7 @@ int main(int argc, char *argv[])
sessionBus.registerObject(guiPath, &activator, QDBusConnection::ExportAllSlots);
if (!sessionBus.registerService(guiService)) {
QDBusInterface runningGui(guiService, guiPath, guiService, sessionBus);
runningGui.call(QDBus::NoBlock, QStringLiteral("Activate"));
runningGui.call(QDBus::NoBlock, QStringLiteral("NewWindow"));
return 0;
}
@ -153,6 +163,7 @@ int main(int argc, char *argv[])
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
activator.setWindowUrl(url);
engine.load(url);
// --- System tray icon (shown when close-to-tray is enabled) ---
@ -168,30 +179,22 @@ int main(int argc, char *argv[])
// Toggle window visibility on tray icon activation
QObject::connect(trayIcon, &QSystemTrayIcon::activated,
[&engine](QSystemTrayIcon::ActivationReason reason) {
[&engine, &activator](QSystemTrayIcon::ActivationReason reason) {
if (reason != QSystemTrayIcon::Trigger)
return;
auto roots = engine.rootObjects();
if (roots.isEmpty()) return;
auto *window = qobject_cast<QWindow *>(roots.first());
auto *window = qobject_cast<QWindow *>(roots.last());
if (!window) return;
if (window->isVisible()) {
window->hide();
} else {
window->show();
window->raise();
window->requestActivate();
activator.Activate();
}
});
QObject::connect(showAction, &QAction::triggered, [&engine]() {
auto roots = engine.rootObjects();
if (roots.isEmpty()) return;
auto *window = qobject_cast<QWindow *>(roots.first());
if (!window) return;
window->show();
window->raise();
window->requestActivate();
QObject::connect(showAction, &QAction::triggered, [&activator]() {
activator.Activate();
});
QObject::connect(quitAction, &QAction::triggered, &app, &QApplication::quit);