• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
MarbleLegendBrowser.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Project.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2006-2007 Torsten Rahn <tackat@kde.org>
9 // Copyright 2007 Inge Wallin <ingwa@kde.org>
10 // Copyright 2012 Illya Kovalevskyy <illya.kovalevskyy@gmail.com>
11 // Copyright 2013 Yazeed Zoabi <yazeedz.zoabi@gmail.com>
12 //
13 
14 
15 #include "MarbleLegendBrowser.h"
16 
17 #include <QTime>
18 #include <QUrl>
19 #include <QDesktopServices>
20 #include <QEvent>
21 #include <QFile>
22 #include <QFileInfo>
23 #include <QMouseEvent>
24 #include <QPainter>
25 #include <QTextFrame>
26 #include <QScrollBar>
27 #include <QStyle>
28 #include <QStyleOptionButton>
29 #include <QDesktopServices>
30 #include <QRegExp>
31 #include <QWebFrame>
32 #include <QWebElement>
33 #include <QTextDocument>
34 
35 #include "GeoSceneDocument.h"
36 #include "GeoSceneHead.h"
37 #include "GeoSceneLegend.h"
38 #include "GeoSceneSection.h"
39 #include "GeoSceneIcon.h"
40 #include "GeoSceneItem.h"
41 #include "GeoSceneProperty.h"
42 #include "GeoSceneSettings.h"
43 #include "MarbleModel.h"
44 #include "MarbleDebug.h"
45 #include "TemplateDocument.h"
46 #include "MarbleDirs.h"
47 
48 namespace Marble
49 {
50 
51 class MarbleLegendBrowserPrivate
52 {
53  public:
54  MarbleModel *m_marbleModel;
55  QMap<QString, bool> m_checkBoxMap;
56  QMap<QString, QPixmap> m_symbolMap;
57  bool m_isLegendLoaded;
58 #ifdef Q_WS_MAEMO_5
59  bool m_suppressSelection;
60 #endif // Q_WS_MAEMO_5
61 };
62 
63 
64 // ================================================================
65 
66 
67 MarbleLegendBrowser::MarbleLegendBrowser( QWidget *parent )
68  : MarbleWebView( parent ),
69  d( new MarbleLegendBrowserPrivate )
70 {
71  d->m_isLegendLoaded = false;
72  d->m_marbleModel = 0;
73 #ifdef Q_WS_MAEMO_5
74  d->m_suppressSelection = false;
75 #endif // Q_WS_MAEMO_5
76 
77  QWebFrame *frame = page()->mainFrame();
78  connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
79  this, SLOT(injectCheckBoxChecker()));
80  page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
81  connect( this, SIGNAL(linkClicked(QUrl)), this, SLOT(openLinkExternally(QUrl)) );
82 }
83 
84 MarbleLegendBrowser::~MarbleLegendBrowser()
85 {
86  delete d;
87 }
88 
89 void MarbleLegendBrowser::setMarbleModel( MarbleModel *marbleModel )
90 {
91  // We need this to be able to get to the MapTheme.
92  d->m_marbleModel = marbleModel;
93 
94  if ( d->m_marbleModel ) {
95  connect ( d->m_marbleModel, SIGNAL(themeChanged(QString)),
96  this, SLOT(initTheme()) );
97  }
98 }
99 
100 QSize MarbleLegendBrowser::sizeHint() const
101 {
102  return QSize( 180, 320 );
103 }
104 
105 void MarbleLegendBrowser::initTheme()
106 {
107  // Check for a theme specific legend.html first
108  if ( d->m_marbleModel != 0 && d->m_marbleModel->mapTheme() != 0 )
109  {
110  const GeoSceneDocument *currentMapTheme = d->m_marbleModel->mapTheme();
111 
112  d->m_checkBoxMap.clear();
113 
114  foreach ( const GeoSceneProperty *property, currentMapTheme->settings()->allProperties() ) {
115  if ( property->available() ) {
116  d->m_checkBoxMap[ property->name() ] = property->value();
117  }
118  }
119 
120  disconnect ( currentMapTheme, SIGNAL(valueChanged(QString,bool)), 0, 0 );
121  connect ( currentMapTheme, SIGNAL(valueChanged(QString,bool)),
122  this, SLOT(setCheckedProperty(QString,bool)) );
123  }
124 
125  if ( isVisible() ) {
126  loadLegend();
127  }
128  else {
129  d->m_isLegendLoaded = false;
130  }
131 }
132 
133 void MarbleLegendBrowser::loadLegend()
134 {
135 
136  // Read the html string.
137  QString legendPath;
138 
139  // Check for a theme specific legend.html first
140  if ( d->m_marbleModel != 0 && d->m_marbleModel->mapTheme() != 0 )
141  {
142  const GeoSceneDocument *currentMapTheme = d->m_marbleModel->mapTheme();
143 
144  legendPath = MarbleDirs::path( "maps/" +
145  currentMapTheme->head()->target() + '/' +
146  currentMapTheme->head()->theme() + "/legend.html" );
147  }
148  if ( legendPath.isEmpty() ) {
149  legendPath = MarbleDirs::path( "legend.html" );
150  }
151 
152  QString finalHtml = readHtml( QUrl::fromLocalFile( legendPath ) );
153 
154  TemplateDocument doc(finalHtml);
155  finalHtml = doc.finalText();
156 
157  reverseSupportCheckboxes(finalHtml);
158 
159  // Generate some parts of the html from the MapTheme <Legend> tag.
160  const QString sectionsHtml = generateSectionsHtml();
161 
162  // And then create the final html from these two parts.
163  finalHtml.replace( QString( "<!-- ##customLegendEntries:all## -->" ), sectionsHtml );
164 
165  translateHtml( finalHtml );
166 
167  QUrl baseUrl = QUrl::fromLocalFile( legendPath );
168 
169  // Set the html string in the QTextBrowser.
170  setHtml(finalHtml, baseUrl);
171 
172  if ( d->m_marbleModel ) {
173  QTextDocument *document = new QTextDocument(page()->mainFrame()->toHtml());
174  d->m_marbleModel->setLegend( document );
175  }
176 }
177 
178 void MarbleLegendBrowser::injectCheckBoxChecker()
179 {
180  QWebFrame *frame = page()->mainFrame();
181  frame->addToJavaScriptWindowObject( "Marble", this );
182 }
183 
184 void MarbleLegendBrowser::openLinkExternally( const QUrl &url )
185 {
186  if ( url.scheme() == "tour" ) {
187  emit tourLinkClicked( "maps/"+url.host() + url.path() );
188  } else {
189  QDesktopServices::openUrl( url );
190  }
191 }
192 
193 bool MarbleLegendBrowser::event( QEvent * event )
194 {
195  // "Delayed initialization": legend gets created only
196  if ( event->type() == QEvent::Show ) {
197  if ( !d->m_isLegendLoaded ) {
198  loadLegend();
199  return true;
200  }
201  }
202 #ifdef Q_WS_MAEMO_5
203  else if ( event->type() == QEvent::MouseButtonPress ) {
204  if ( static_cast<QMouseEvent *>( event )->button() == Qt::LeftButton ) {
205  d->m_suppressSelection = true;
206  }
207  }
208  else if ( event->type() == QEvent::MouseButtonRelease ) {
209  if ( static_cast<QMouseEvent *>( event )->button() == Qt::LeftButton ) {
210  d->m_suppressSelection = false;
211  }
212  }
213  else if ( event->type() == QEvent::MouseMove ) {
214  if ( d->m_suppressSelection ) {
215  // eat event to suppress text selection under Maemo5
216  return true;
217  }
218  }
219 #endif // Q_WS_MAEMO_5
220 
221  return MarbleWebView::event( event );
222 }
223 
224 QString MarbleLegendBrowser::readHtml( const QUrl & name )
225 {
226  QString html;
227 
228  QFile data( name.toLocalFile() );
229  if ( data.open( QFile::ReadOnly ) ) {
230  QTextStream in( &data );
231  html = in.readAll();
232  data.close();
233  }
234 
235  return html;
236 }
237 
238 void MarbleLegendBrowser::translateHtml( QString & html )
239 {
240  // must match string extraction in Messages.sh
241  QString s = html.remove( 0, html.indexOf( "<body>" ) );
242  QRegExp rx( "</?\\w+((\\s+\\w+(\\s*=\\s*(?:\".*\"|'.*'|[^'\">\\s]+))?)+\\s*|\\s*)/?>" );
243  rx.setMinimal( true );
244  s.replace( rx, "\n" );
245  s.replace( QRegExp( "\\s*\n\\s*" ), "\n" );
246  QStringList words = s.split( '\n', QString::SkipEmptyParts );
247 
248  QStringList::const_iterator i = words.constBegin();
249  QStringList::const_iterator const end = words.constEnd();
250  for (; i != end; ++i )
251  html.replace( *i, tr( (*i).toUtf8() ) );
252 }
253 
254 void MarbleLegendBrowser::reverseSupportCheckboxes(QString &html)
255 {
256  const QString old = "<a href=\"checkbox:cities\"/>";
257 
258  QString checked = "";
259  if (d->m_checkBoxMap["cities"])
260  checked = "checked";
261 
262  const QString repair = ""
263  "<input type=\"checkbox\" "
264  "onchange=\"Marble.setCheckedProperty(this.name, this.checked);\" " + checked + " name=\"cities\"/>";
265 
266  html.replace(old, repair);
267 }
268 
269 QString MarbleLegendBrowser::generateSectionsHtml()
270 {
271  // Generate HTML to include into legend.html here.
272 
273  QString customLegendString;
274 
275  if ( d->m_marbleModel == 0 || d->m_marbleModel->mapTheme() == 0 )
276  return QString();
277 
278  const GeoSceneDocument *currentMapTheme = d->m_marbleModel->mapTheme();
279 
280  d->m_symbolMap.clear();
281 
282  /* Okay, if you are reading it now, be ready for hell!
283  * We can't optimize this part of Legend Browser, but we will
284  * do it, anyway. It's complicated a lot, the most important
285  * thing is to understand everything.
286  */
287  foreach ( const GeoSceneSection *section, currentMapTheme->legend()->sections() ) {
288  // Each section is divided into the "well"
289  // Well is like a block of data with rounded corners
290  customLegendString += "<div class=\"well well-small well-legend\">";
291 
292 
293  QString checkBoxString;
294  if (section->checkable()) {
295  // If it's needed to make a checkbox here, we will
296  QString const checked = d->m_checkBoxMap[section->connectTo()] ? "checked" : "";
297  /* Important comment:
298  * We inject Marble object into JavaScript of each legend html file
299  * This is only one way to handle checkbox changes we see, so
300  * Marble.setCheckedProperty is a function that does it
301  */
302  if(section->radio()!="") {
303  checkBoxString = ""
304  "<label class=\"section-head\">"
305  "<input type=\"radio\" "
306  "onchange=\"Marble.setRadioCheckedProperty(this.value, this.name ,this.checked);\" " +
307  checked + " value=\"" + section->connectTo() + "\" name=\"" + section->radio() + "\" /><span>"
308  + section->heading() +
309  "</span></label>";
310 
311  } else {
312  checkBoxString = ""
313  "<label class=\"section-head\">"
314  "<input type=\"checkbox\" "
315  "onchange=\"Marble.setCheckedProperty(this.name, this.checked);\" "+checked+" name=\"" + section->connectTo() + "\" /><span>"
316  + section->heading() +
317  "</span></label>";
318 
319  }
320  customLegendString += checkBoxString;
321 
322  } else {
323  customLegendString += "<h4 class=\"section-head\">"+section->heading()+"</h4>";
324  }
325 
326  foreach (const GeoSceneItem *item, section->items()) {
327 
328  // checkbox for item
329  QString checkBoxString;
330  if (item->checkable()) {
331  QString const checked = d->m_checkBoxMap[item->connectTo()] ? "checked" : "";
332  checkBoxString = ""
333  "<input type=\"checkbox\" "
334  "onchange=\"Marble.setCheckedProperty(this.name, this.checked);\" "
335  + checked + " name=\"" + item->connectTo() + "\" />";
336 
337  }
338 
339  // pixmap and text
340  QString path = "";
341  int pixmapWidth = 24;
342  int pixmapHeight = 12;
343  // NOTICE. There are some pixmaps without image, so we should
344  // create just a plain rectangle with set color
345  if (!item->icon()->pixmap().isEmpty()) {
346  path = MarbleDirs::path( item->icon()->pixmap() );
347  const QPixmap oncePixmap(path);
348  pixmapWidth = oncePixmap.width();
349  pixmapHeight = oncePixmap.height();
350  }
351  QColor color = item->icon()->color();
352  QString styleDiv = "";
353  if (color != Qt::transparent) {
354  styleDiv = "width: " + QString::number(pixmapWidth) + "px; height: " +
355  QString::number(pixmapHeight) + "px; background-color: "
356  + color.name() + ';';
357  } else {
358  styleDiv = "width: " + QString::number(pixmapWidth) + "px; height: " +
359  QString::number(pixmapHeight) + "px;";
360  }
361  QString src = QUrl::fromLocalFile( path ).toString();
362  QString html = ""
363  "<div class=\"legend-entry\">"
364  " <label>" + checkBoxString +
365  " <img class=\"image-pic\" src=\"" + src + "\" style=\"" + styleDiv + "\"/>"
366  " <span class=\"notation\">" + item->text() + "</span>"
367  " </label>"
368  "</div>";
369  customLegendString += html;
370  }
371  customLegendString += "</div>"; // <div class="well">
372  }
373 
374  return customLegendString;
375 }
376 
377 void MarbleLegendBrowser::setCheckedProperty( const QString& name, bool checked )
378 {
379  QWebElement box = page()->mainFrame()->findFirstElement("input[name="+name+']');
380  if (!box.isNull()) {
381  if (checked != d->m_checkBoxMap[name]) {
382  d->m_checkBoxMap[name] = checked;
383  emit toggledShowProperty( name, checked );
384  }
385  }
386 
387  update();
388 }
389 
390 void MarbleLegendBrowser::setRadioCheckedProperty( const QString& value, const QString& name , bool checked )
391 {
392  QWebElement box = page()->mainFrame()->findFirstElement("input[value="+value+']');
393  QWebElementCollection boxes = page()->mainFrame()->findAllElements("input[name="+name+']');
394  QString currentValue="";
395  for(int i=0; i<boxes.count(); ++i) {
396  currentValue = boxes.at(i).attribute("value");
397  d->m_checkBoxMap[currentValue]=false;
398  emit toggledShowProperty( currentValue, false );
399  }
400  if (!box.isNull()) {
401  if (checked != d->m_checkBoxMap[value]) {
402  d->m_checkBoxMap[value] = checked;
403  emit toggledShowProperty( value, checked );
404  }
405  }
406 
407  update();
408 }
409 
410 }
411 
412 #include "MarbleLegendBrowser.moc"
GeoSceneHead.h
Marble::GeoSceneItem
The section item in a legend of a GeoScene document.
Definition: GeoSceneItem.h:38
GeoSceneProperty.h
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QEvent
QWidget
Marble::MarbleLegendBrowser::toggledShowProperty
void toggledShowProperty(QString, bool)
QEvent::type
Type type() const
QWebFrame
Marble::GeoSceneSection::radio
QString radio() const
Definition: GeoSceneSection.cpp:144
Marble::GeoSceneProperty
Settings property within a GeoScene document.
Definition: GeoSceneProperty.h:39
Marble::MarbleDirs::path
static QString path(const QString &relativePath)
Definition: MarbleDirs.cpp:59
Marble::GeoSceneItem::icon
const GeoSceneIcon * icon() const
Definition: GeoSceneItem.cpp:50
GeoSceneItem.h
QWebElementCollection::at
QWebElement at(int i) const
Marble::MarbleLegendBrowser::sizeHint
QSize sizeHint() const
Definition: MarbleLegendBrowser.cpp:100
QColor::name
QString name() const
QRegExp::setMinimal
void setMinimal(bool minimal)
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
MarbleModel.h
This file contains the headers for MarbleModel.
QMap< QString, bool >
QUrl::host
QString host() const
QWebView::linkClicked
void linkClicked(const QUrl &url)
QWidget::isVisible
bool isVisible() const
MarbleWebView
Definition: MarbleWebView.h:18
Marble::GeoSceneItem::text
QString text() const
Definition: GeoSceneItem.cpp:65
GeoSceneDocument.h
Marble::GeoSceneSection::checkable
bool checkable() const
Definition: GeoSceneSection.cpp:114
QString::remove
QString & remove(int position, int n)
Marble::MarbleLegendBrowser::setRadioCheckedProperty
void setRadioCheckedProperty(const QString &value, const QString &name, bool checked)
Definition: MarbleLegendBrowser.cpp:390
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
MarbleDebug.h
QUrl::toString
QString toString(QFlags< QUrl::FormattingOption > options) const
QObject::tr
QString tr(const char *sourceText, const char *disambiguation, int n)
QList::const_iterator
QFile
QWidget::update
void update()
QTextStream
QWebView::event
virtual bool event(QEvent *e)
QWebElementCollection::count
int count() const
QWebFrame::addToJavaScriptWindowObject
void addToJavaScriptWindowObject(const QString &name, QObject *object)
QRegExp
Marble::GeoSceneDocument::legend
const GeoSceneLegend * legend() const
Definition: GeoSceneDocument.cpp:116
QObject::name
const char * name() const
QWebPage::setLinkDelegationPolicy
void setLinkDelegationPolicy(LinkDelegationPolicy policy)
QString::number
QString number(int n, int base)
Marble::MarbleLegendBrowser::translateHtml
void translateHtml(QString &html)
Definition: MarbleLegendBrowser.cpp:238
QObject::property
QVariant property(const char *name) const
Marble::MarbleLegendBrowser::setCheckedProperty
void setCheckedProperty(const QString &name, bool checked)
Definition: MarbleLegendBrowser.cpp:377
TemplateDocument.h
Marble::GeoSceneSection::connectTo
QString connectTo() const
Definition: GeoSceneSection.cpp:124
QWebElement
MarbleDirs.h
QString::isEmpty
bool isEmpty() const
QWebPage::mainFrame
QWebFrame * mainFrame() const
QWebView::setHtml
void setHtml(const QString &html, const QUrl &baseUrl)
QUrl::path
QString path() const
QWebFrame::findAllElements
QWebElementCollection findAllElements(const QString &selectorQuery) const
QString
QColor
QUrl::scheme
QString scheme() const
Marble::MarbleLegendBrowser::MarbleLegendBrowser
MarbleLegendBrowser(QWidget *parent)
Definition: MarbleLegendBrowser.cpp:67
QStringList
QWebElement::isNull
bool isNull() const
QPixmap
QUrl::toLocalFile
QString toLocalFile() const
QWebElement::attribute
QString attribute(const QString &name, const QString &defaultValue) const
QSize
Marble::GeoSceneSection::heading
QString heading() const
Definition: GeoSceneSection.cpp:104
QUrl
Marble::GeoSceneDocument
A container for features parsed from the DGML file.
Definition: GeoSceneDocument.h:44
QWebFrame::findFirstElement
QWebElement findFirstElement(const QString &selectorQuery) const
Marble::MarbleLegendBrowser::~MarbleLegendBrowser
~MarbleLegendBrowser()
Definition: MarbleLegendBrowser.cpp:84
QString::replace
QString & replace(int position, int n, QChar after)
Marble::MarbleModel
The data model (not based on QAbstractModel) for a MarbleWidget.
Definition: MarbleModel.h:97
Marble::GeoSceneSection
Section of a GeoScene document.
Definition: GeoSceneSection.h:39
GeoSceneSettings.h
GeoSceneSection.h
Marble::MarbleLegendBrowser::readHtml
QString readHtml(const QUrl &name)
Definition: MarbleLegendBrowser.cpp:224
Marble::GeoSceneItem::connectTo
QString connectTo() const
Definition: GeoSceneItem.cpp:85
Marble::GeoSceneIcon::pixmap
QString pixmap() const
Definition: GeoSceneIcon.cpp:37
QTextDocument
MarbleLegendBrowser.h
Marble::MarbleLegendBrowser::generateSectionsHtml
QString generateSectionsHtml()
Definition: MarbleLegendBrowser.cpp:269
QWebView::page
QWebPage * page() const
Marble::GeoSceneLegend::sections
QVector< const GeoSceneSection * > sections() const
Definition: GeoSceneLegend.cpp:86
GeoSceneLegend.h
Marble::GeoSceneItem::checkable
bool checkable() const
Definition: GeoSceneItem.cpp:75
Marble::GeoSceneSection::items
QVector< GeoSceneItem * > items() const
Definition: GeoSceneSection.cpp:94
QList::constEnd
const_iterator constEnd() const
Marble::GeoSceneProperty::available
bool available() const
Definition: GeoSceneProperty.cpp:48
QList::constBegin
const_iterator constBegin() const
QDesktopServices::openUrl
bool openUrl(const QUrl &url)
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
GeoSceneIcon.h
QTextStream::readAll
QString readAll()
Marble::MarbleLegendBrowser::tourLinkClicked
void tourLinkClicked(const QString &url)
Marble::MarbleLegendBrowser::setMarbleModel
void setMarbleModel(MarbleModel *marbleModel)
Definition: MarbleLegendBrowser.cpp:89
Marble::GeoSceneSettings::allProperties
QVector< GeoSceneProperty * > allProperties()
Get the whole list of properties stored in the settings.
Definition: GeoSceneSettings.cpp:143
Marble::GeoSceneIcon::color
QColor color() const
Definition: GeoSceneIcon.cpp:47
Marble::GeoSceneDocument::settings
const GeoSceneSettings * settings() const
Definition: GeoSceneDocument.cpp:106
QUrl::fromLocalFile
QUrl fromLocalFile(const QString &localFile)
QWebElementCollection
Marble::MarbleLegendBrowser::event
bool event(QEvent *event)
Definition: MarbleLegendBrowser.cpp:193
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:40 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal