aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix (xq) Queißner <git@mq32.de>2020-06-18 20:10:20 +0200
committerFelix (xq) Queißner <git@mq32.de>2020-06-18 20:10:20 +0200
commit75bbab5fcc0260ac765b216b8b3d989f88dac159 (patch)
tree0713aff62c08bb3cff7691c252279c6a8baf6c3d /src
parent151323b0c75464318881c3f96f2c3f558e63ca99 (diff)
downloadkristall-75bbab5fcc0260ac765b216b8b3d989f88dac159.tar.gz
Reworks global settings handling, improves redirection configuration.
Diffstat (limited to 'src')
-rw-r--r--src/about/updates.gemini1
-rw-r--r--src/browsertab.cpp25
-rw-r--r--src/geminirenderer.cpp2
-rw-r--r--src/gophermaprenderer.cpp2
-rw-r--r--src/kristall.hpp34
-rw-r--r--src/main.cpp44
-rw-r--r--src/mainwindow.cpp28
-rw-r--r--src/settingsdialog.cpp183
-rw-r--r--src/settingsdialog.hpp36
-rw-r--r--src/settingsdialog.ui12
10 files changed, 264 insertions, 103 deletions
diff --git a/src/about/updates.gemini b/src/about/updates.gemini
index 56d5452..f2ac095 100644
--- a/src/about/updates.gemini
+++ b/src/about/updates.gemini
@@ -10,6 +10,7 @@
* Reworked internal network structure. Makes room for future improvements
* Pressing escape now resets search bar to current location
* Client certificates are disabled when doing a host switch
+* Redirection handling is now configurable and contains some warning messages for potentially malicious redirects.
## 0.2
* Implement Ctrl+D/*Add to favourites* menu item
diff --git a/src/browsertab.cpp b/src/browsertab.cpp
index 456af37..a69c33c 100644
--- a/src/browsertab.cpp
+++ b/src/browsertab.cpp
@@ -256,7 +256,7 @@ void BrowserTab::on_requestComplete(const QByteArray &data, const QString &mime)
this->ui->text_browser->setStyleSheet(QString("QTextBrowser { background-color: %1; }").arg(doc_style.background_color.name()));
- bool plaintext_only = (global_settings.value("text_display").toString() == "plain");
+ bool plaintext_only = (global_options.text_display == GenericSettings::PlainText);
if (not plaintext_only and mime.startsWith("text/gemini"))
{
@@ -400,9 +400,9 @@ void BrowserTab::on_redirected(const QUrl &uri, bool is_permanent)
Q_UNUSED(is_permanent);
// TODO: Make this a setting
- if (redirection_count >= 5)
+ if (redirection_count >= global_options.max_redirections)
{
- setErrorMessage("Too many redirections!");
+ setErrorMessage(QString("Too many consecutive redirections. The last redirection would have redirected you to:\r\n%1").arg(uri.toString(QUrl::FullyEncoded)));
return;
}
else
@@ -410,8 +410,17 @@ void BrowserTab::on_redirected(const QUrl &uri, bool is_permanent)
bool is_cross_protocol = (this->current_location.scheme() != uri.scheme());
bool is_cross_host = (this->current_location.host() != uri.host());
+
QString question;
- if(is_cross_protocol and is_cross_host)
+ if(global_options.redirection_policy == GenericSettings::WarnAlways)
+ {
+ question = QString(
+ "The location you visited wants to redirect you to another location:\r\n"
+ "%1\r\n"
+ "Do you want to allow the redirection?"
+ ).arg(uri.toString(QUrl::FullyEncoded));
+ }
+ else if((global_options.redirection_policy & (GenericSettings::WarnOnHostChange | GenericSettings::WarnOnSchemeChange)) and is_cross_protocol and is_cross_host)
{
question = QString(
"The location you visited wants to redirect you to another host and switch the protocol.\r\n"
@@ -420,7 +429,7 @@ void BrowserTab::on_redirected(const QUrl &uri, bool is_permanent)
"Do you want to allow the redirection?"
).arg(uri.scheme()).arg(uri.host());
}
- else if(is_cross_protocol)
+ else if((global_options.redirection_policy & GenericSettings::WarnOnSchemeChange) and is_cross_protocol)
{
question = QString(
"The location you visited wants to switch the protocol.\r\n"
@@ -428,7 +437,7 @@ void BrowserTab::on_redirected(const QUrl &uri, bool is_permanent)
"Do you want to allow the redirection?"
).arg(uri.scheme());
}
- else if(is_cross_host)
+ else if((global_options.redirection_policy & GenericSettings::WarnOnHostChange) and is_cross_host)
{
question = QString(
"The location you visited wants to redirect you to another host.\r\n"
@@ -507,9 +516,7 @@ void BrowserTab::on_text_browser_anchorClicked(const QUrl &url)
}
else
{
- bool use_os_proxy = global_settings.value("use_os_scheme_handler").toBool();
-
- if (use_os_proxy)
+ if (global_options.use_os_scheme_handler)
{
if (not QDesktopServices::openUrl(url))
{
diff --git a/src/geminirenderer.cpp b/src/geminirenderer.cpp
index d497a6c..9e7dcd6 100644
--- a/src/geminirenderer.cpp
+++ b/src/geminirenderer.cpp
@@ -66,7 +66,7 @@ std::unique_ptr<GeminiDocument> GeminiRenderer::render(
result->background_color = themed_style.background_color;
result->setIndentWidth(20);
- bool emit_fancy_text = global_settings.value("text_decoration").toBool();
+ bool emit_fancy_text = global_options.enable_text_decoration;
QTextCursor cursor{result.get()};
diff --git a/src/gophermaprenderer.cpp b/src/gophermaprenderer.cpp
index e2fe434..6779a9a 100644
--- a/src/gophermaprenderer.cpp
+++ b/src/gophermaprenderer.cpp
@@ -26,7 +26,7 @@ std::unique_ptr<QTextDocument> GophermapRenderer::render(const QByteArray &input
external_link.setFont(themed_style.standard_font);
external_link.setForeground(QBrush(themed_style.external_link_color));
- bool emit_text_only = (global_settings.value("gophermap_display").toString() == "text");
+ bool emit_text_only = (global_options.gophermap_display == GenericSettings::PlainText);
std::unique_ptr<QTextDocument> result = std::make_unique<QTextDocument>();
result->setDocumentMargin(themed_style.margin);
diff --git a/src/kristall.hpp b/src/kristall.hpp
index face253..dd83498 100644
--- a/src/kristall.hpp
+++ b/src/kristall.hpp
@@ -8,10 +8,44 @@
#include "ssltrust.hpp"
#include "favouritecollection.hpp"
+enum class Theme : int
+{
+ light = 0,
+ dark = 1,
+};
+
+struct GenericSettings
+{
+ enum TextDisplay {
+ FormattedText,
+ PlainText,
+ };
+
+ enum RedirectionWarning {
+ WarnNever = 0,
+ WarnOnSchemeChange = 1,
+ WarnOnHostChange = 2,
+ WarnAlways = -1,
+ };
+
+ QString start_page = "about:favourites";
+ Theme theme = Theme::light;
+ TextDisplay text_display = FormattedText;
+ bool enable_text_decoration = false;
+ bool use_os_scheme_handler = false;
+ TextDisplay gophermap_display = FormattedText;
+ int max_redirections = 5;
+ RedirectionWarning redirection_policy = WarnOnHostChange;
+
+ void load(QSettings & settings);
+ void save(QSettings & settings) const;
+};
+
extern QSettings global_settings;
extern IdentityCollection global_identities;
extern QClipboard * global_clipboard;
extern SslTrust global_trust;
extern FavouriteCollection global_favourites;
+extern GenericSettings global_options;
#endif // KRISTALL_HPP
diff --git a/src/main.cpp b/src/main.cpp
index d2f56da..2902bfb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -12,6 +12,7 @@ QSettings global_settings { "xqTechnologies", "Kristall" };
QClipboard * global_clipboard;
SslTrust global_trust;
FavouriteCollection global_favourites;
+GenericSettings global_options;
int main(int argc, char *argv[])
{
@@ -22,9 +23,7 @@ int main(int argc, char *argv[])
QCommandLineParser cli_parser;
cli_parser.parse(app.arguments());
- if(not global_settings.contains("start_page")) {
- global_settings.setValue("start_page", "about:favourites");
- }
+ global_options.load(global_settings);
global_settings.beginGroup("Client Identities");
global_identities.load(global_settings);
@@ -56,3 +55,42 @@ int main(int argc, char *argv[])
return app.exec();
}
+
+void GenericSettings::load(QSettings &settings)
+{
+ start_page = settings.value("start_page", "about:favourites").toString();
+
+ if(settings.value("text_display", "fancy").toString() == "plain")
+ text_display = PlainText;
+ else
+ text_display = FormattedText;
+
+ enable_text_decoration = settings.value("text_decoration", false).toBool();
+
+ if(settings.value("theme", "light").toString() == "dark")
+ theme = Theme::dark;
+ else
+ theme = Theme::light;
+
+ if(settings.value("gophermap_display", "rendered").toString() == "rendered")
+ gophermap_display = FormattedText;
+ else
+ gophermap_display = PlainText;
+
+ use_os_scheme_handler = settings.value("use_os_scheme_handler", false).toBool();
+
+ max_redirections = settings.value("max_redirections", 5).toInt();
+ redirection_policy = RedirectionWarning(settings.value("redirection_policy ", WarnOnHostChange).toInt());
+}
+
+void GenericSettings::save(QSettings &settings) const
+{
+ settings.setValue("start_page", "about:favourites");
+ settings.setValue("text_display", (text_display == FormattedText) ? "fancy" : "plain");
+ settings.setValue("text_decoration", enable_text_decoration);
+ settings.setValue("theme", (theme == Theme::dark) ? "dark" : "light");
+ settings.setValue("gophermap_display", (gophermap_display == FormattedText) ? "rendered" : "text");
+ settings.setValue("use_os_scheme_handler", use_os_scheme_handler);
+ settings.setValue("max_redirections", max_redirections);
+ settings.setValue("redirection_policy", int(redirection_policy));
+}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index eb4806f..48405db 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -111,7 +111,7 @@ BrowserTab * MainWindow::addEmptyTab(bool focus_new, bool load_default)
}
if(load_default) {
- tab->navigateTo(QUrl(global_settings.value("start_page").toString()), BrowserTab::DontPush);
+ tab->navigateTo(QUrl(global_options.start_page), BrowserTab::DontPush);
}
return tab;
@@ -164,6 +164,8 @@ void MainWindow::saveSettings()
global_settings.endGroup();
}
+ global_options.save(global_settings);
+
global_settings.sync();
}
@@ -244,23 +246,19 @@ void MainWindow::on_actionSettings_triggered()
SettingsDialog dialog;
dialog.setGeminiStyle(this->current_style);
- dialog.setStartPage(global_settings.value("start_page").toString());
dialog.setProtocols(this->protocols);
- dialog.setUiTheme(global_settings.value("theme").toString());
+ dialog.setOptions(global_options);
dialog.setSslTrust(global_trust);
if(dialog.exec() != QDialog::Accepted)
return;
- if(auto url = dialog.startPage(); url.isValid()) {
- global_settings.setValue("start_page", url.toString());
- }
-
global_trust = dialog.sslTrust();
- global_settings.setValue("theme", dialog.uiTheme());
+ global_options = dialog.options();
this->protocols = dialog.protocols();
this->current_style = dialog.geminiStyle();
+
this->saveSettings();
this->reloadTheme();
@@ -327,23 +325,23 @@ void MainWindow::on_actionAbout_Qt_triggered()
void MainWindow::reloadTheme()
{
- QString theme = global_settings.value("theme").toString();
- if(theme.isEmpty())
- theme = "light";
-
- if(theme == "light")
+ if(global_options.theme == Theme::light)
{
QFile file(":/light.qss");
file.open(QFile::ReadOnly | QFile::Text);
QTextStream stream(&file);
application->setStyleSheet(stream.readAll());
+
+ QIcon::setThemeName("light");
}
- else if(theme == "dark")
+ else if(global_options.theme == Theme::dark)
{
QFile file(":/dark.qss");
file.open(QFile::ReadOnly | QFile::Text);
QTextStream stream(&file);
application->setStyleSheet(stream.readAll());
+
+ QIcon::setThemeName("dark");
}
}
@@ -377,7 +375,7 @@ void MainWindow::on_actionGo_to_home_triggered()
{
BrowserTab * tab = qobject_cast<BrowserTab*>(this->ui->browser_tabs->currentWidget());
if(tab != nullptr) {
- tab->navigateTo(QUrl(global_settings.value("start_page").toString()), BrowserTab::PushImmediate);
+ tab->navigateTo(QUrl(global_options.start_page), BrowserTab::PushImmediate);
}
}
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index 838d17c..eb9858b 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -28,35 +28,11 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
this->ui->auto_theme->addItem("Light Theme", QVariant::fromValue<int>(DocumentStyle::AutoLightTheme));
this->ui->ui_theme->clear();
- this->ui->ui_theme->addItem("Light", QVariant::fromValue<QString>("light"));
- this->ui->ui_theme->addItem("Dark", QVariant::fromValue<QString>("dark"));
+ this->ui->ui_theme->addItem("Light", QVariant::fromValue<int>(int(Theme::light)));
+ this->ui->ui_theme->addItem("Dark", QVariant::fromValue<int>(int(Theme::dark)));
setGeminiStyle(DocumentStyle { });
- if(global_settings.value("gophermap_display").toString() == "text") {
- this->ui->gophermap_text->setChecked(true);
- } else {
- this->ui->gophermap_icon->setChecked(true);
- }
-
- if(global_settings.value("text_display").toString() == "plain") {
- this->ui->fancypants_off->setChecked(true);
- } else {
- this->ui->fancypants_on->setChecked(true);
- }
-
- if(global_settings.value("text_decoration").toBool()) {
- this->ui->texthl_on->setChecked(true);
- } else {
- this->ui->texthl_off->setChecked(true);
- }
-
- if(global_settings.value("use_os_scheme_handler").toBool()) {
- this->ui->scheme_os_default->setChecked(true);
- } else {
- this->ui->scheme_error->setChecked(true);
- }
-
int items = global_settings.beginReadArray("Themes");
this->predefined_styles.clear();
@@ -104,11 +80,11 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
&SettingsDialog::on_trusted_server_selection);
this->ui->redirection_mode->clear();
- this->ui->redirection_mode->addItem("Ask for cross-scheme or cross-host redirection");
- this->ui->redirection_mode->addItem("Ask for cross-scheme redirection");
- this->ui->redirection_mode->addItem("Ask for cross-host redirection");
- this->ui->redirection_mode->addItem("Ask for all redirection");
- this->ui->redirection_mode->addItem("Silently redirect everything");
+ this->ui->redirection_mode->addItem("Ask for cross-scheme or cross-host redirection", int(GenericSettings::WarnOnHostChange | GenericSettings::WarnOnSchemeChange));
+ this->ui->redirection_mode->addItem("Ask for cross-scheme redirection", int(GenericSettings::WarnOnSchemeChange));
+ this->ui->redirection_mode->addItem("Ask for cross-host redirection", int(GenericSettings::WarnOnHostChange));
+ this->ui->redirection_mode->addItem("Ask for all redirection", int(GenericSettings::WarnAlways));
+ this->ui->redirection_mode->addItem("Silently redirect everything", int(GenericSettings::WarnNever));
}
SettingsDialog::~SettingsDialog()
@@ -181,16 +157,6 @@ void SettingsDialog::setGeminiStyle(DocumentStyle const &style)
this->reloadStylePreview();
}
-QUrl SettingsDialog::startPage() const
-{
- return QUrl(this->ui->start_page->text());
-}
-
-void SettingsDialog::setStartPage(const QUrl &url)
-{
- this->ui->start_page->setText(url.toString());
-}
-
ProtocolSetup SettingsDialog::protocols() const
{
ProtocolSetup protocols;
@@ -209,22 +175,6 @@ void SettingsDialog::setProtocols(ProtocolSetup const & protocols)
#undef M
}
-QString SettingsDialog::uiTheme() const
-{
- return this->ui->ui_theme->currentData().toString();
-}
-
-void SettingsDialog::setUiTheme(const QString &theme)
-{
- if(theme == "light")
- this->ui->ui_theme->setCurrentIndex(0);
- else if(theme == "dark")
- this->ui->ui_theme->setCurrentIndex(1);
- else
- this->ui->ui_theme->setCurrentIndex(0);
-
-}
-
SslTrust SettingsDialog::sslTrust() const
{
return this->current_trust;
@@ -246,6 +196,60 @@ void SettingsDialog::setSslTrust(const SslTrust &trust)
this->ui->trusted_hosts->resizeColumnsToContents();
}
+void SettingsDialog::setOptions(const GenericSettings &options)
+{
+ this->current_options = options;
+
+ if(this->current_options.theme == Theme::light)
+ this->ui->ui_theme->setCurrentIndex(0);
+ else if(this->current_options.theme == Theme::dark)
+ this->ui->ui_theme->setCurrentIndex(1);
+ else
+ this->ui->ui_theme->setCurrentIndex(0);
+
+ this->ui->start_page->setText(this->current_options.start_page);
+
+ if(this->current_options.gophermap_display == GenericSettings::PlainText) {
+ this->ui->gophermap_text->setChecked(true);
+ } else {
+ this->ui->gophermap_icon->setChecked(true);
+ }
+
+ if(this->current_options.text_display == GenericSettings::PlainText) {
+ this->ui->fancypants_off->setChecked(true);
+ } else {
+ this->ui->fancypants_on->setChecked(true);
+ }
+
+ if(this->current_options.enable_text_decoration) {
+ this->ui->texthl_on->setChecked(true);
+ } else {
+ this->ui->texthl_off->setChecked(true);
+ }
+
+ if(this->current_options.use_os_scheme_handler) {
+ this->ui->scheme_os_default->setChecked(true);
+ } else {
+ this->ui->scheme_error->setChecked(true);
+ }
+
+ this->ui->max_redirects->setValue(this->current_options.max_redirections);
+
+ this->ui->redirection_mode->setCurrentIndex(0);
+ for(int i = 0; i < this->ui->redirection_mode->count(); i++)
+ {
+ if(this->ui->redirection_mode->itemData(i).toInt() == this->current_options.redirection_policy) {
+ this->ui->redirection_mode->setCurrentIndex(i);
+ break;
+ }
+ }
+}
+
+GenericSettings SettingsDialog::options() const
+{
+ return this->current_options;
+}
+
void SettingsDialog::reloadStylePreview()
{
QFile document_src { ":/about/style-preview.gemini" };
@@ -479,11 +483,6 @@ void SettingsDialog::on_preset_load_clicked()
void SettingsDialog::on_SettingsDialog_accepted()
{
- global_settings.setValue("gophermap_display", this->ui->gophermap_text->isChecked() ? "text" : "rendered");
- global_settings.setValue("text_display", this->ui->fancypants_off->isChecked() ? "plain" : "fancy");
- global_settings.setValue("text_decoration", this->ui->texthl_on->isChecked());
- global_settings.setValue("use_os_scheme_handler", this->ui->scheme_os_default->isChecked());
-
global_settings.beginWriteArray("Themes", this->predefined_styles.size());
int index = 0;
@@ -589,3 +588,63 @@ void SettingsDialog::on_trust_revoke_selected_clicked()
{
this->current_trust.trusted_hosts.remove(this->ui->trusted_hosts->currentIndex());
}
+
+void SettingsDialog::on_start_page_textChanged(const QString &start_page)
+{
+ this->current_options.start_page = start_page;
+}
+
+void SettingsDialog::on_ui_theme_currentIndexChanged(int index)
+{
+ this->current_options.theme = Theme(this->ui->ui_theme->itemData(index).toInt());
+}
+
+void SettingsDialog::on_fancypants_on_clicked()
+{
+ this->current_options.text_display = GenericSettings::FormattedText;
+}
+
+void SettingsDialog::on_fancypants_off_clicked()
+{
+ this->current_options.text_display = GenericSettings::PlainText;
+}
+
+void SettingsDialog::on_texthl_on_clicked()
+{
+ this->current_options.enable_text_decoration = true;
+}
+
+void SettingsDialog::on_texthl_off_clicked()
+{
+ this->current_options.enable_text_decoration = false;
+}
+
+void SettingsDialog::on_gophermap_icon_clicked()
+{
+ this->current_options.gophermap_display = GenericSettings::FormattedText;
+}
+
+void SettingsDialog::on_gophermap_text_clicked()
+{
+ this->current_options.gophermap_display = GenericSettings::PlainText;
+}
+
+void SettingsDialog::on_scheme_os_default_clicked()
+{
+ this->current_options.use_os_scheme_handler = true;
+}
+
+void SettingsDialog::on_scheme_error_clicked()
+{
+ this->current_options.use_os_scheme_handler = false;
+}
+
+void SettingsDialog::on_redirection_mode_currentIndexChanged(int index)
+{
+ this->current_options.redirection_policy = GenericSettings::RedirectionWarning(this->ui->redirection_mode->itemData(index).toInt());
+}
+
+void SettingsDialog::on_max_redirects_valueChanged(int max_redirections)
+{
+ this->current_options.max_redirections = max_redirections;
+}
diff --git a/src/settingsdialog.hpp b/src/settingsdialog.hpp
index 0b96a55..1be2e68 100644
--- a/src/settingsdialog.hpp
+++ b/src/settingsdialog.hpp
@@ -7,6 +7,7 @@
#include "protocolsetup.hpp"
#include "documentstyle.hpp"
#include "ssltrust.hpp"
+#include "kristall.hpp"
namespace Ui {
class SettingsDialog;
@@ -26,18 +27,15 @@ public:
return current_style;
}
- QUrl startPage() const;
- void setStartPage(QUrl const & url);
-
ProtocolSetup protocols() const;
void setProtocols(ProtocolSetup const & proto);
- QString uiTheme() const;
- void setUiTheme(QString const & theme);
-
SslTrust sslTrust() const;
void setSslTrust(SslTrust const & trust);
+ GenericSettings options() const;
+ void setOptions(GenericSettings const & options);
+
private slots:
void on_std_change_font_clicked();
@@ -101,6 +99,30 @@ private slots:
void on_trust_revoke_selected_clicked();
+ void on_start_page_textChanged(const QString &arg1);
+
+ void on_ui_theme_currentIndexChanged(int index);
+
+ void on_fancypants_on_clicked();
+
+ void on_fancypants_off_clicked();
+
+ void on_texthl_on_clicked();
+
+ void on_texthl_off_clicked();
+
+ void on_gophermap_icon_clicked();
+
+ void on_gophermap_text_clicked();
+
+ void on_scheme_os_default_clicked();
+
+ void on_scheme_error_clicked();
+
+ void on_redirection_mode_currentIndexChanged(int index);
+
+ void on_max_redirects_valueChanged(int arg1);
+
private:
void reloadStylePreview();
@@ -119,6 +141,8 @@ private:
QMap<QString, DocumentStyle> predefined_styles;
SslTrust current_trust;
+
+ GenericSettings current_options;
};
#endif // SETTINGSDIALOG_HPP
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index b8665c2..c8dbb7b 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -255,9 +255,6 @@
</property>
</widget>
</item>
- <item row="8" column="1">
- <widget class="QComboBox" name="redirection_mode"/>
- </item>
<item row="8" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
@@ -265,6 +262,9 @@
</property>
</widget>
</item>
+ <item row="8" column="1">
+ <widget class="QComboBox" name="redirection_mode"/>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="style_tab">
@@ -975,10 +975,10 @@
</connection>
</connections>
<buttongroups>
- <buttongroup name="textHighlightsBtnGroup"/>
- <buttongroup name="gophermapBtnGroup"/>
- <buttongroup name="textRenderingBtnGroup"/>
<buttongroup name="buttonGroup_2"/>
<buttongroup name="buttonGroup"/>
+ <buttongroup name="textRenderingBtnGroup"/>
+ <buttongroup name="textHighlightsBtnGroup"/>
+ <buttongroup name="gophermapBtnGroup"/>
</buttongroups>
</ui>