aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix (xq) Queißner <git@mq32.de>2021-03-06 15:26:07 +0100
committerFelix (xq) Queißner <git@mq32.de>2021-03-06 15:26:07 +0100
commit9457e720f24d8365ed6a1e82b016078b0bc17eb6 (patch)
treed810dcd8189ce508a9a0e666f7d819f3c63bcbca /src
parente16c85887a58381f225d706a8d740bf96a5fdf6a (diff)
downloadkristall-9457e720f24d8365ed6a1e82b016078b0bc17eb6.tar.gz
Implements proper multi-window support.
Diffstat (limited to 'src')
-rw-r--r--src/about/updates.gemini5
-rw-r--r--src/kristall.hpp15
-rw-r--r--src/main.cpp98
-rw-r--r--src/mainwindow.cpp56
-rw-r--r--src/mainwindow.hpp7
-rw-r--r--src/mainwindow.ui54
6 files changed, 178 insertions, 57 deletions
diff --git a/src/about/updates.gemini b/src/about/updates.gemini
index c0d3f1f..46a9445 100644
--- a/src/about/updates.gemini
+++ b/src/about/updates.gemini
@@ -16,7 +16,10 @@
-- There's a lot missing here still
-* Adds single-session mode so opening links will open them in the currently focuse kristall window instead of a new instance every time.
+* Adds single-session mode so opening links will open them in the currently focused window instead of a new instance every time.
+* Adds the option to open multiple kristall windows in one session.
+* Adds --new-window command line option to open urls into a new kristall window instead of opening them as a new tab
+* Adds --isolated command line option to start a separated instance of kristall
## 0.3 - TLS and security
* Adds support for transient client certificates
diff --git a/src/kristall.hpp b/src/kristall.hpp
index 88ae95d..f9d1c15 100644
--- a/src/kristall.hpp
+++ b/src/kristall.hpp
@@ -148,6 +148,10 @@ namespace kristall
extern QDir styles;
}
+ //! Forwards the current settings to all windows
+ void applySettings();
+
+ //! Saves the current settings to disk
void saveSettings();
void setTheme(Theme theme);
@@ -162,6 +166,17 @@ namespace kristall
//! that can be tracked by the application.
void registerAppWindow(MainWindow * window);
+ //! Opens a new window with the default page open.
+ //! @param load_default Loads the default/start page instead of about:blank
+ MainWindow * openNewWindow(bool load_default);
+
+ //! Opens a new window with the given url.
+ MainWindow * openNewWindow(QUrl const & url);
+
+ //! Opens a new window with the given list of urls.
+ //! If the list is empty, no new tab will spawned.
+ MainWindow * openNewWindow(QVector<QUrl> const & urls);
+
extern QString default_font_family, default_font_family_fixed;
//! Whether emojis are supprted in current build configuration
diff --git a/src/main.cpp b/src/main.cpp
index 5bc2426..e1098bd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -115,10 +115,27 @@ void forAllAppWindows(F const & f)
MainWindow * getFocusedAppWindow()
{
assert(qApp != nullptr);
+ // first, check if we have currently active window:
auto * main_window = qobject_cast<MainWindow *>(qApp->activeWindow());
if(main_window != nullptr)
return main_window;
- return last_focused_window;
+
+ // if not, fall back to the window we focused last:
+ if(::last_focused_window != nullptr)
+ return ::last_focused_window;
+
+ // and if we have none, we just take the first window we can find if
+ // any:
+ forAllAppWindows([&main_window](MainWindow * w) {
+ if(main_window == nullptr)
+ main_window = w;
+ });
+ if(main_window != nullptr)
+ return main_window;
+
+ qCritical() << "could not find a focused/foreground window!";
+
+ return main_window;
}
@@ -234,18 +251,17 @@ namespace ipc
break;
}
case Message::open_in_window: {
- auto * const window = getFocusedAppWindow();
+ QVector<QUrl> urls;
for(auto const & data : payload.split('\n'))
{
QUrl url { QString::fromUtf8(data) };
if(url.isValid()) {
- // TODO: Implement opening these urls in a new
- // window instead of a new tab!
- if(window != nullptr) {
- window->addNewTab(true, url);
- }
+ urls.append(url);
}
}
+ if(urls.size() > 0) {
+ kristall::openNewWindow(urls);
+ }
break;
}
@@ -311,6 +327,36 @@ void kristall::registerAppWindow(MainWindow * window)
});
}
+MainWindow * kristall::openNewWindow(bool load_default)
+{
+ auto * const window = openNewWindow(QVector<QUrl>{});
+ window->addEmptyTab(true, load_default);
+ return window;
+}
+
+//! Opens a new window with the given url.
+MainWindow * kristall::openNewWindow(QUrl const & url)
+{
+ return openNewWindow(QVector<QUrl>{url});
+}
+
+//! Opens a new window with the given list of urls.
+//! If the list is empty, no new tab will spawned.
+MainWindow * kristall::openNewWindow(QVector<QUrl> const & urls)
+{
+ MainWindow * const window = new MainWindow(qApp);
+
+ for(int i = 0; i < urls.length(); i++)
+ {
+ window->addNewTab((i == 0), urls.at(i));
+ }
+
+ window->show();
+
+ return window;
+}
+
+
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
@@ -461,7 +507,7 @@ int main(int argc, char *argv[])
QSettings app_settings {
kristall::dirs::config_root.absoluteFilePath("config.ini"),
- QSettings::IniFormat
+ QSettings::IniFormat
};
app_settings_ptr = &app_settings;
@@ -613,8 +659,6 @@ int main(int argc, char *argv[])
kristall::setTheme(kristall::options.theme);
- MainWindow w(&app);
-
if(ipc_server != nullptr) {
QObject::connect(ipc_server.get(), &QLocalServer::newConnection, [&ipc_server]() {
auto * const socket = ipc_server->nextPendingConnection();
@@ -632,24 +676,20 @@ int main(int argc, char *argv[])
// Open all URLs in the new window
if(urls.size() > 0) {
- for(const auto & url : urls) {
- w.addNewTab(false, url);
- }
+ kristall::openNewWindow(urls);
}
else {
- w.addEmptyTab(true, true);
+ kristall::openNewWindow(true);
}
- app_settings.beginGroup("Window State");
- if(app_settings.contains("geometry")) {
- w.restoreGeometry(app_settings.value("geometry").toByteArray());
- }
- if(app_settings.contains("state")) {
- w.restoreState(app_settings.value("state").toByteArray());
- }
- app_settings.endGroup();
-
- w.show();
+ //app_settings.beginGroup("Window State");
+ //if(app_settings.contains("geometry")) {
+ // w.restoreGeometry(app_settings.value("geometry").toByteArray());
+ //}
+ //if(app_settings.contains("state")) {
+ // w.restoreState(app_settings.value("state").toByteArray());
+ //}
+ //app_settings.endGroup();
int exit_code = app.exec();
@@ -780,6 +820,16 @@ void GenericSettings::save(QSettings &settings) const
}
}
+void kristall::applySettings()
+{
+ kristall::setTheme(kristall::options.theme);
+ kristall::setUiDensity(kristall::options.ui_density, false);
+
+ forAllAppWindows([](MainWindow * window)
+ {
+ window->applySettings();
+ });
+}
void kristall::saveSettings()
{
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index bd33153..6f39b42 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -253,7 +253,8 @@ void MainWindow::setUiDensity(UIDensity density, bool previewing)
if (previewing)
{
- if (!this->curTab()) return;
+ if (not this->curTab())
+ return;
this->curTab()->setUiDensity(density);
}
else
@@ -278,6 +279,27 @@ QString MainWindow::newGroupDialog()
return dialog.textValue();
}
+void MainWindow::applySettings()
+{
+ // Flag open tabs for re-render so theme
+ // changes are instantly applied.
+ for (int i = 0; i < this->ui->browser_tabs->count(); ++i)
+ {
+ BrowserTab *t = this->tabAt(i);
+ t->refreshOptionalToolbarItems();
+ t->refreshToolbarIcons();
+ t->needs_rerender = true;
+ }
+
+ // Re-render the currently-open tab if we have one.
+ BrowserTab * tab = this->curTab();
+ if (tab)
+ tab->rerenderPage();
+
+ // Update new-tab button visibility.
+ this->ui->browser_tabs->tab_bar->new_tab_btn->setVisible(kristall::options.enable_newtab_btn);
+}
+
void MainWindow::mousePressEvent(QMouseEvent *event)
{
QMainWindow::mousePressEvent(event);
@@ -439,27 +461,9 @@ void MainWindow::on_actionSettings_triggered()
kristall::protocols = dialog.protocols();
kristall::document_style = dialog.geminiStyle();
- kristall::saveSettings();
-
- kristall::setTheme(kristall::options.theme);
- this->setUiDensity(kristall::options.ui_density, false);
+ kristall::applySettings();
- // Flag open tabs for re-render so theme
- // changes are instantly applied.
- for (int i = 0; i < this->ui->browser_tabs->count(); ++i)
- {
- BrowserTab *t = this->tabAt(i);
- t->refreshOptionalToolbarItems();
- t->refreshToolbarIcons();
- t->needs_rerender = true;
- }
- // Re-render the currently-open tab if we have one.
- BrowserTab * tab = this->curTab();
- if (tab) tab->rerenderPage();
-
- // Update new-tab button visibility.
- this->ui->browser_tabs->tab_bar->new_tab_btn
- ->setVisible(kristall::options.enable_newtab_btn);
+ kristall::saveSettings();
}
void MainWindow::on_actionNew_Tab_triggered()
@@ -777,3 +781,13 @@ void MainWindow::on_actionShow_document_source_triggered()
{
this->viewPageSource();
}
+
+void MainWindow::on_actionNew_window_triggered()
+{
+ kristall::openNewWindow(false);
+}
+
+void MainWindow::on_actionClose_Window_triggered()
+{
+ this->deleteLater();
+}
diff --git a/src/mainwindow.hpp b/src/mainwindow.hpp
index 7113587..a268ec7 100644
--- a/src/mainwindow.hpp
+++ b/src/mainwindow.hpp
@@ -45,6 +45,9 @@ public:
QString newGroupDialog();
+ //! Applies setting changes to the window.
+ void applySettings();
+
void mousePressEvent(QMouseEvent *event) override;
void closeEvent(QCloseEvent *event) override;
@@ -100,6 +103,10 @@ private slots:
void on_actionShow_document_source_triggered();
+ void on_actionNew_window_triggered();
+
+ void on_actionClose_Window_triggered();
+
private: // slots
void on_tab_fileLoaded(DocumentStats const & stats);
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 48c6bfc..2659a65 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -189,6 +189,7 @@
<string>File</string>
</property>
<addaction name="actionNew_Tab"/>
+ <addaction name="actionNew_window"/>
<addaction name="separator"/>
<addaction name="actionSave_as"/>
<addaction name="actionClose_Tab"/>
@@ -196,6 +197,7 @@
<addaction name="actionManage_Certificates"/>
<addaction name="actionSettings"/>
<addaction name="separator"/>
+ <addaction name="actionClose_Window"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuHelp">
@@ -236,7 +238,8 @@
</widget>
<action name="actionAbout">
<property name="icon">
- <iconset theme="help-about"/>
+ <iconset theme="help-about">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>About...</string>
@@ -244,7 +247,8 @@
</action>
<action name="actionQuit">
<property name="icon">
- <iconset theme="application-exit"/>
+ <iconset theme="application-exit">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Quit</string>
@@ -263,7 +267,8 @@
</action>
<action name="actionClose_Tab">
<property name="icon">
- <iconset theme="window-close"/>
+ <iconset theme="window-close">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Close Tab</string>
@@ -286,7 +291,8 @@
</action>
<action name="actionBackward">
<property name="icon">
- <iconset theme="go-previous"/>
+ <iconset theme="go-previous">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Back</string>
@@ -300,7 +306,8 @@
</action>
<action name="actionForward">
<property name="icon">
- <iconset theme="go-next"/>
+ <iconset theme="go-next">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Forward</string>
@@ -314,7 +321,8 @@
</action>
<action name="actionRoot">
<property name="icon">
- <iconset theme="go-top"/>
+ <iconset theme="go-top">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Root</string>
@@ -328,7 +336,8 @@
</action>
<action name="actionParent">
<property name="icon">
- <iconset theme="go-up"/>
+ <iconset theme="go-up">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Parent</string>
@@ -342,7 +351,8 @@
</action>
<action name="actionRefresh">
<property name="icon">
- <iconset theme="view-refresh"/>
+ <iconset theme="view-refresh">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Refresh</string>
@@ -362,7 +372,8 @@
</action>
<action name="actionSave_as">
<property name="icon">
- <iconset theme="document-save-as"/>
+ <iconset theme="document-save-as">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Save as...</string>
@@ -388,7 +399,8 @@
</action>
<action name="actionGo_to_home">
<property name="icon">
- <iconset theme="go-home"/>
+ <iconset theme="go-home">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Go to home</string>
@@ -420,7 +432,8 @@
</action>
<action name="actionManage_Certificates">
<property name="icon">
- <iconset theme="view-certificate"/>
+ <iconset theme="view-certificate">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Manage Certificates…</string>
@@ -434,6 +447,25 @@
<string>Ctrl+U</string>
</property>
</action>
+ <action name="actionNew_window">
+ <property name="text">
+ <string>New Window</string>
+ </property>
+ <property name="toolTip">
+ <string>Opens a new window</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <action name="actionClose_Window">
+ <property name="text">
+ <string>Close Window</string>
+ </property>
+ <property name="shortcut">
+ <string>Alt+F4</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>