8#include "MarbleLegendBrowser.h"
10#include <QCoreApplication>
11#include <QDesktopServices>
16#include <QRegularExpression>
19#ifndef MARBLE_NO_WEBKITWIDGETS
21#include <QWebEnginePage>
24#include <QTextDocument>
26#include "GeoSceneDocument.h"
27#include "GeoSceneHead.h"
28#include "GeoSceneIcon.h"
29#include "GeoSceneItem.h"
30#include "GeoSceneLegend.h"
31#include "GeoSceneProperty.h"
32#include "GeoSceneSection.h"
33#include "GeoSceneSettings.h"
34#include "MarbleDebug.h"
35#include "MarbleDirs.h"
37#include "TemplateDocument.h"
42class MarbleLegendBrowserPrivate
45 MarbleModel *m_marbleModel;
49 MarbleJsWrapper *m_jsWrapper;
54MarbleLegendBrowser::MarbleLegendBrowser(
QWidget *parent)
55 : MarbleWebView(parent)
56 , d(new MarbleLegendBrowserPrivate)
58 d->m_marbleModel =
nullptr;
59 d->m_jsWrapper =
new MarbleJsWrapper(
this);
62MarbleLegendBrowser::~MarbleLegendBrowser()
67void MarbleLegendBrowser::setMarbleModel(MarbleModel *marbleModel)
70 d->m_marbleModel = marbleModel;
72 if (d->m_marbleModel) {
73 connect(d->m_marbleModel, &MarbleModel::themeChanged,
this, &MarbleLegendBrowser::initTheme);
77QSize MarbleLegendBrowser::sizeHint()
const
82void MarbleLegendBrowser::initTheme()
85 if (d->m_marbleModel !=
nullptr && d->m_marbleModel->mapTheme() !=
nullptr) {
86 const GeoSceneDocument *currentMapTheme = d->m_marbleModel->mapTheme();
88 d->m_checkBoxMap.clear();
90 for (
const GeoSceneProperty *property : currentMapTheme->settings()->allProperties()) {
91 if (property->available()) {
92 d->m_checkBoxMap[
property->name()] =
property->value();
96 disconnect(currentMapTheme, SIGNAL(valueChanged(
QString,
bool)),
nullptr,
nullptr);
97 connect(currentMapTheme, SIGNAL(valueChanged(
QString,
bool)),
this, SLOT(setCheckedProperty(
QString,
bool)));
105void MarbleLegendBrowser::loadLegend()
107 if (!d->m_marbleModel) {
111#ifndef MARBLE_NO_WEBKITWIDGETS
112 if (d->m_currentThemeId != d->m_marbleModel->mapThemeId()) {
113 d->m_currentThemeId = d->m_marbleModel->mapThemeId();
122 if (d->m_marbleModel->mapTheme() !=
nullptr) {
123 const GeoSceneDocument *currentMapTheme = d->m_marbleModel->mapTheme();
125 legendPath = MarbleDirs::path(
QLatin1StringView(
"maps/") + currentMapTheme->head()->target() +
QLatin1Char(
'/') + currentMapTheme->head()->theme()
129 legendPath = MarbleDirs::path(QStringLiteral(
"legend.html"));
134 TemplateDocument doc(finalHtml);
135 finalHtml = doc.finalText();
137 injectWebChannel(finalHtml);
138 reverseSupportCheckboxes(finalHtml);
141 const QString sectionsHtml = generateSectionsHtml();
144 finalHtml.
replace(QStringLiteral(
"<!-- ##customLegendEntries:all## -->"), sectionsHtml);
146 translateHtml(finalHtml);
151 auto page =
new MarbleWebPage(
this);
152 connect(page, SIGNAL(linkClicked(
QUrl)),
this, SLOT(openLinkExternally(
QUrl)));
153 page->setHtml(finalHtml, baseUrl);
157 channel->registerObject(QStringLiteral(
"Marble"), d->m_jsWrapper);
158 page->setWebChannel(channel);
160 if (d->m_marbleModel) {
161 page->toHtml([=](
QString document) {
168void MarbleLegendBrowser::openLinkExternally(
const QUrl &url)
177bool MarbleLegendBrowser::event(
QEvent *event)
187QString MarbleLegendBrowser::readHtml(
const QUrl &name)
201void MarbleLegendBrowser::translateHtml(
QString &html)
205 QRegularExpression rx(QStringLiteral(R
"(</?\w+((\s+\w+(\s*=\s*(?:".*"|'.*'|[^'">\s]+))?)+\s*|\s*)/?>)"),
217 for (; i !=
end; ++i)
221void MarbleLegendBrowser::injectWebChannel(
QString &html)
223 QString webChannelCode = QStringLiteral(R
"(<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>)");
224 webChannelCode += QStringLiteral(
225 "<script> document.addEventListener(\"DOMContentLoaded\", function() {"
226 "new QWebChannel(qt.webChannelTransport, function (channel) {"
227 "Marble = channel.objects.Marble;"
231 html.
replace(QStringLiteral(
"</head>"), webChannelCode);
234void MarbleLegendBrowser::reverseSupportCheckboxes(
QString &html)
236 const QString old = QStringLiteral(
"<a href=\"checkbox:cities\"/>");
239 if (d->m_checkBoxMap[QStringLiteral(
"cities")])
240 checked = QStringLiteral(
"checked");
243 "<input style=\"position: relative; top: -4px;\" type=\"checkbox\" "
244 "onchange=\"Marble.setCheckedProperty(this.name, this.checked);\" ")
250QString MarbleLegendBrowser::generateSectionsHtml()
256 if (d->m_marbleModel ==
nullptr || d->m_marbleModel->mapTheme() ==
nullptr)
259 const GeoSceneDocument *currentMapTheme = d->m_marbleModel->mapTheme();
261 d->m_symbolMap.
clear();
268 for (
const GeoSceneSection *section : currentMapTheme->legend()->sections()) {
271 customLegendString +=
QLatin1StringView(
"<div class=\"well well-small well-legend\">");
275 if (section->checkable()) {
277 QString const checked = d->m_checkBoxMap[section->connectTo()] ? QStringLiteral(
"checked") :
QString();
283 if (!section->radio().isEmpty()) {
284 checkBoxString = QLatin1StringView(
285 "<label class=\"section-head\">"
286 "<input style=\"position: relative; top: -4px;\" type=\"radio\" "
287 "onchange=\"Marble.setRadioCheckedProperty(this.value, this.name ,this.checked);\" ")
288 + checked + QLatin1StringView(
" value=\"") + section->connectTo() + QLatin1StringView(
"\" name=\"") + section->radio()
289 + QLatin1StringView(
"\" /><span>") + heading + QLatin1StringView(
"</span></label>");
292 checkBoxString = QLatin1StringView(
293 "<label class=\"section-head\">"
294 "<input style=\"position: relative; top: -4px;\" type=\"checkbox\" "
295 "onchange=\"Marble.setCheckedProperty(this.name, this.checked);\" ")
296 + checked + QLatin1StringView(
" name=\"") + section->connectTo() + QLatin1StringView(
"\" /><span>") + heading
297 + QLatin1StringView(
"</span></label>");
299 customLegendString += checkBoxString;
305 for (
const GeoSceneItem *item : section->items()) {
308 if (item->checkable()) {
309 QString const checked = d->m_checkBoxMap[item->connectTo()] ? QStringLiteral(
"checked") :
QString();
311 "<input type=\"checkbox\" "
312 "onchange=\"Marble.setCheckedProperty(this.name, this.checked);\" ")
319 int pixmapWidth = 24;
320 int pixmapHeight = 12;
321 if (!item->icon()->pixmap().isEmpty()) {
322 QString path = MarbleDirs::path(item->icon()->pixmap());
323 const QPixmap oncePixmap(path);
324 pixmapWidth = oncePixmap.width();
325 pixmapHeight = oncePixmap.height();
331 src = QStringLiteral(
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
336 const QColor color = item->icon()->color();
340 styleDiv += QStringLiteral(
" position: relative; top: -3px;");
343 "<div class=\"legend-entry\">"
348 " <span class=\"kotation\" >")
354 customLegendString += html;
359 return customLegendString;
362void MarbleLegendBrowser::setCheckedProperty(
const QString &name,
bool checked)
364 if (checked != d->m_checkBoxMap[name]) {
365 d->m_checkBoxMap[
name] = checked;
366 Q_EMIT toggledShowProperty(name, checked);
370void MarbleLegendBrowser::setRadioCheckedProperty(
const QString &value,
const QString &name,
bool checked)
373 if (checked != d->m_checkBoxMap[name]) {
374 d->m_checkBoxMap[
name] = checked;
375 Q_EMIT toggledShowProperty(name, checked);
381#include "moc_MarbleLegendBrowser.cpp"
This file contains the headers for MarbleModel.
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
QString name(GameStandardAction id)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
QString path(const QString &relativePath)
Binds a QML item to a specific geodetic location in screen coordinates.
bool isValid() const const
QString name(NameFormat format) const const
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
bool openUrl(const QUrl &url)
const_iterator constBegin() const const
const_iterator constEnd() const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QUrl fromLocalFile(const QString &localFile)
QString host(ComponentFormattingOptions options) const const
QString path(ComponentFormattingOptions options) const const
QString scheme() const const
QString toString(FormattingOptions options) const const