• 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
  • plugins
  • render
  • elevationprofilefloatitem
ElevationProfileFloatItem.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
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 2011-2012 Florian Eßer <f.esser@rwth-aachen.de>
9 // Copyright 2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
10 //
11 
12 #include "ElevationProfileFloatItem.h"
13 
14 #include <QContextMenuEvent>
15 #include <QRect>
16 #include <QPainter>
17 #include <QPushButton>
18 #include <QMenu>
19 #include <QMouseEvent>
20 
21 #include "ui_ElevationProfileConfigWidget.h"
22 #include "MarbleLocale.h"
23 #include "MarbleModel.h"
24 #include "MarbleWidget.h"
25 #include "GeoDataPlacemark.h"
26 #include "GeoDataTreeModel.h"
27 #include "ViewportParams.h"
28 #include "routing/RoutingModel.h"
29 #include "routing/RoutingManager.h"
30 #include "MarbleDirs.h"
31 #include "ElevationModel.h"
32 #include "MarbleGraphicsGridLayout.h"
33 #include "MarbleMath.h"
34 
35 namespace Marble
36 {
37 
38 ElevationProfileFloatItem::ElevationProfileFloatItem( const MarbleModel *marbleModel )
39  : AbstractFloatItem( marbleModel, QPointF( 220, 10.5 ), QSizeF( 0.0, 50.0 ) ),
40  m_configDialog( 0 ),
41  ui_configWidget( 0 ),
42  m_leftGraphMargin( 0 ),
43  m_eleGraphWidth( 0 ),
44  m_viewportWidth( 0 ),
45  m_shrinkFactorY( 1.2 ),
46  m_fontHeight( 10 ),
47  m_markerPlacemark( new GeoDataPlacemark ),
48  m_documentIndex( -1 ),
49  m_cursorPositionX( 0 ),
50  m_isInitialized( false ),
51  m_contextMenu( 0 ),
52  m_marbleWidget( 0 ),
53  m_routingModel( 0 ),
54  m_routeAvailable( false ),
55  m_firstVisiblePoint( 0 ),
56  m_lastVisiblePoint( 0 ),
57  m_zoomToViewport( false )
58 {
59  setVisible( false );
60  bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
61  if ( smallScreen ) {
62  setPosition( QPointF( 10.5, 10.5 ) );
63  }
64  bool const highRes = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::HighResolution;
65  m_eleGraphHeight = highRes ? 100 : 50;
66 
67  setPadding( 1 );
68 
69  m_markerDocument.setDocumentRole( UnknownDocument );
70  m_markerDocument.setName( "Elevation Profile" );
71 
72  m_markerPlacemark->setName( "Elevation Marker" );
73  m_markerPlacemark->setVisible( false );
74  m_markerDocument.append( m_markerPlacemark );
75 }
76 
77 ElevationProfileFloatItem::~ElevationProfileFloatItem()
78 {
79 }
80 
81 QStringList ElevationProfileFloatItem::backendTypes() const
82 {
83  return QStringList( "elevationprofile" );
84 }
85 
86 qreal ElevationProfileFloatItem::zValue() const
87 {
88  return 3.0;
89 }
90 
91 QString ElevationProfileFloatItem::name() const
92 {
93  return tr("Elevation Profile");
94 }
95 
96 QString ElevationProfileFloatItem::guiString() const
97 {
98  return tr("&Elevation Profile");
99 }
100 
101 QString ElevationProfileFloatItem::nameId() const
102 {
103  return QString( "elevationprofile" );
104 }
105 
106 QString ElevationProfileFloatItem::version() const
107 {
108  return "1.2";
109 }
110 
111 QString ElevationProfileFloatItem::description() const
112 {
113  return tr( "A float item that shows the elevation profile of the current route." );
114 }
115 
116 QString ElevationProfileFloatItem::copyrightYears() const
117 {
118  return "2011, 2012";
119 }
120 
121 QList<PluginAuthor> ElevationProfileFloatItem::pluginAuthors() const
122 {
123  return QList<PluginAuthor>()
124  << PluginAuthor( QString::fromUtf8 ( "Florian Eßer" ), "f.esser@rwth-aachen.de" )
125  << PluginAuthor( "Bernhard Beschow", "bbeschow@cs.tu-berlin.de" );
126 }
127 
128 QIcon ElevationProfileFloatItem::icon () const
129 {
130  return QIcon(":/icons/elevationprofile.png");
131 }
132 
133 void ElevationProfileFloatItem::initialize ()
134 {
135  connect( marbleModel()->elevationModel(), SIGNAL(updateAvailable()), SLOT(updateData()) );
136 
137  m_routingModel = marbleModel()->routingManager()->routingModel();
138  connect( m_routingModel, SIGNAL(currentRouteChanged()), this, SLOT(updateData()) );
139 
140  m_fontHeight = QFontMetricsF( font() ).ascent() + 1;
141  m_leftGraphMargin = QFontMetricsF( font() ).width( "0000 m" ); // TODO make this dynamic according to actual need
142  connect( this, SIGNAL(dataUpdated()), SLOT(forceRepaint()) );
143 
144  updateData();
145 
146  m_isInitialized = true;
147 }
148 
149 bool ElevationProfileFloatItem::isInitialized () const
150 {
151  return m_isInitialized;
152 }
153 
154 void ElevationProfileFloatItem::setProjection( const ViewportParams *viewport )
155 {
156  if ( !( viewport->width() == m_viewportWidth && m_isInitialized ) ) {
157  bool const highRes = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::HighResolution;
158  int const widthRatio = highRes ? 2 : 3;
159  setContentSize( QSizeF( viewport->width() / widthRatio,
160  m_eleGraphHeight + m_fontHeight * 2.5 ) );
161  m_eleGraphWidth = contentSize().width() - m_leftGraphMargin;
162  m_axisX.setLength( m_eleGraphWidth );
163  m_axisY.setLength( m_eleGraphHeight );
164  m_axisX.setTickCount( 3, m_eleGraphWidth / ( m_leftGraphMargin * 1.5 ) );
165  m_axisY.setTickCount( 2, m_eleGraphHeight / m_fontHeight );
166  m_viewportWidth = viewport->width();
167  bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
168  if ( !m_isInitialized && !smallScreen ) {
169  setPosition( QPointF( (viewport->width() - contentSize().width()) / 2 , 10.5 ) );
170  }
171  }
172 
173  update();
174 
175  AbstractFloatItem::setProjection( viewport );
176 }
177 
178 void ElevationProfileFloatItem::paintContent( QPainter *painter )
179 {
180  painter->save();
181  painter->setRenderHint( QPainter::Antialiasing, true );
182  painter->setFont( font() );
183 
184  if ( ! ( m_routeAvailable && m_isInitialized && m_eleData.size() > 0 ) ) {
185  painter->setPen( QColor( Qt::black ) );
186  QString text = tr( "Create a route to view its elevation profile." );
187  painter->drawText( contentRect().toRect(), Qt::TextWordWrap | Qt::AlignCenter, text );
188  painter->restore();
189  return;
190  }
191  if ( m_zoomToViewport && ( m_lastVisiblePoint - m_firstVisiblePoint < 5 ) ) {
192  painter->setPen( QColor( Qt::black ) );
193  QString text = tr( "Not enough points in the current viewport.\nTry to disable 'Zoom to viewport'." );
194  painter->drawText( contentRect().toRect(), Qt::TextWordWrap | Qt::AlignCenter, text );
195  painter->restore();
196  return;
197  }
198 
199  QString intervalStr;
200  int lastStringEnds;
201 
202  // draw viewport bounds
203  if ( ! m_zoomToViewport && ( m_firstVisiblePoint > 0 || m_lastVisiblePoint < m_eleData.size() - 1 ) ) {
204  QColor color( Qt::black );
205  color.setAlpha( 64 );
206  QRect rect;
207  rect.setLeft( m_leftGraphMargin + m_eleData.value( m_firstVisiblePoint ).x() * m_eleGraphWidth / m_axisX.range() );
208  rect.setTop( 0 );
209  rect.setWidth( ( m_eleData.value( m_lastVisiblePoint ).x() - m_eleData.value( m_firstVisiblePoint ).x() ) * m_eleGraphWidth / m_axisX.range() );
210  rect.setHeight( m_eleGraphHeight );
211  painter->fillRect( rect, color );
212  }
213 
214  // draw X and Y axis
215  painter->setPen( Oxygen::aluminumGray4 );
216  painter->drawLine( m_leftGraphMargin, m_eleGraphHeight, contentSize().width(), m_eleGraphHeight );
217  painter->drawLine( m_leftGraphMargin, m_eleGraphHeight, m_leftGraphMargin, 0 );
218 
219  // draw Y grid and labels
220  painter->setPen( QColor( Qt::black ) );
221  QPen dashedPen( Qt::DashLine );
222  dashedPen.setColor( Oxygen::aluminumGray4 );
223  QRect labelRect( 0, 0, m_leftGraphMargin - 1, m_fontHeight + 2 );
224  lastStringEnds = m_eleGraphHeight + m_fontHeight;
225 // painter->drawText( m_leftGraphMargin + 1, m_fontHeight, "[" + m_axisY.unit() + "]" );
226  foreach ( const AxisTick &tick, m_axisY.ticks() ) {
227  const int posY = m_eleGraphHeight - tick.position;
228  painter->setPen( dashedPen );
229  painter->drawLine( m_leftGraphMargin, posY, contentSize().width(), posY );
230 
231  labelRect.moveCenter( QPoint( labelRect.center().x(), posY ) );
232  if ( labelRect.top() < 0 ) {
233  // don't cut off uppermost label
234  labelRect.moveTop( 0 );
235  }
236  if ( labelRect.bottom() >= lastStringEnds ) {
237  // Don't print overlapping labels
238  continue;
239  }
240  lastStringEnds = labelRect.top();
241  painter->setPen( QColor( Qt::black ) );
242  intervalStr.setNum( tick.value * m_axisY.scale() );
243  painter->drawText( labelRect, Qt::AlignRight, intervalStr );
244  }
245 
246  // draw X grid and labels
247  painter->setPen( QColor( Qt::black ) );
248  labelRect.moveTop( m_eleGraphHeight + 1 );
249  lastStringEnds = 0;
250  foreach ( const AxisTick &tick, m_axisX.ticks() ) {
251  const int posX = m_leftGraphMargin + tick.position;
252  painter->setPen( dashedPen );
253  painter->drawLine( posX, 0, posX, m_eleGraphHeight );
254 
255  intervalStr.setNum( tick.value * m_axisX.scale() );
256  if ( tick.position == m_axisX.ticks().last().position ) {
257  intervalStr += ' ' + m_axisX.unit();
258  }
259  labelRect.setWidth( QFontMetricsF( font() ).width( intervalStr ) * 1.5 );
260  labelRect.moveCenter( QPoint( posX, labelRect.center().y() ) );
261  if ( labelRect.right() > m_leftGraphMargin + m_eleGraphWidth ) {
262  // don't cut off rightmost label
263  labelRect.moveRight( m_leftGraphMargin + m_eleGraphWidth );
264  }
265  if ( labelRect.left() <= lastStringEnds ) {
266  // Don't print overlapping labels
267  continue;
268  }
269  lastStringEnds = labelRect.right();
270  painter->setPen( QColor( Qt::black ) );
271  painter->drawText( labelRect, Qt::AlignCenter, intervalStr );
272  }
273 
274  // display elevation gain/loss data
275  painter->setPen( QColor( Qt::black ) );
276  intervalStr = tr( "Difference: %1 %2" )
277  .arg( QString::number( m_gain - m_loss, 'f', 0 ) )
278  .arg( m_axisY.unit() );
279  intervalStr += QString::fromUtf8( " (↗ %1 %3 ↘ %2 %3)" )
280  .arg( QString::number( m_gain, 'f', 0 ) )
281  .arg( QString::number( m_loss, 'f', 0 ) )
282  .arg( m_axisY.unit() );
283  painter->drawText( contentRect().toRect(), Qt::AlignBottom | Qt::AlignCenter, intervalStr );
284 
285  // draw elevation profile
286  painter->setPen( QColor( Qt::black ) );
287  bool const highRes = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::HighResolution;
288  QPen pen = painter->pen();
289  pen.setWidth( highRes ? 2 : 1 );
290  painter->setPen( pen );
291 
292  QLinearGradient fillGradient( 0, 0, 0, m_eleGraphHeight );
293  QColor startColor = Oxygen::forestGreen4;
294  QColor endColor = Oxygen::hotOrange4;
295  startColor.setAlpha( 200 );
296  endColor.setAlpha( 32 );
297  fillGradient.setColorAt( 0.0, startColor );
298  fillGradient.setColorAt( 1.0, endColor );
299  QBrush brush = QBrush( fillGradient );
300  painter->setBrush( brush );
301 
302  QPoint oldPos;
303  oldPos.setX( m_leftGraphMargin );
304  oldPos.setY( ( m_axisY.minValue() - m_axisY.minValue() )
305  * m_eleGraphHeight / ( m_axisY.range() / m_shrinkFactorY ) );
306  oldPos.setY( m_eleGraphHeight - oldPos.y() );
307  QPainterPath path;
308  path.moveTo( oldPos.x(), m_eleGraphHeight );
309  path.lineTo( oldPos.x(), oldPos.y() );
310 
311  const int start = m_zoomToViewport ? m_firstVisiblePoint : 0;
312  const int end = m_zoomToViewport ? m_lastVisiblePoint : m_eleData.size() - 1;
313  for ( int i = start; i <= end; ++i ) {
314  QPoint newPos;
315  if ( i == start ) {
316  // make sure the plot always starts at the y-axis
317  newPos.setX( 0 );
318  } else {
319  newPos.setX( ( m_eleData.value(i).x() - m_axisX.minValue() ) * m_eleGraphWidth / m_axisX.range() );
320  }
321  newPos.rx() += m_leftGraphMargin;
322  if ( newPos.x() != oldPos.x() || newPos.y() != oldPos.y() ) {
323  newPos.setY( ( m_eleData.value(i).y() - m_axisY.minValue() )
324  * m_eleGraphHeight / ( m_axisY.range() * m_shrinkFactorY ) );
325  newPos.setY( m_eleGraphHeight - newPos.y() );
326  path.lineTo( newPos.x(), newPos.y() );
327  oldPos = newPos;
328  }
329  }
330  path.lineTo( oldPos.x(), m_eleGraphHeight );
331  // fill
332  painter->setPen( QPen( Qt::NoPen ) );
333  painter->drawPath( path );
334  // contour
335  // "remove" the first and last path element first, they are only used to fill down to the bottom
336  painter->setBrush( QBrush( Qt::NoBrush ) );
337  path.setElementPositionAt( 0, path.elementAt( 1 ).x, path.elementAt( 1 ).y );
338  path.setElementPositionAt( path.elementCount()-1,
339  path.elementAt( path.elementCount()-2 ).x,
340  path.elementAt( path.elementCount()-2 ).y );
341  painter->setPen( pen );
342  painter->drawPath( path );
343 
344  pen.setWidth( 1 );
345  painter->setPen( pen );
346 
347  // draw interactive cursor
348  const GeoDataCoordinates currentPoint = m_markerPlacemark->coordinate();
349  if ( currentPoint.isValid() ) {
350  painter->setPen( QColor( Qt::white ) );
351  painter->drawLine( m_leftGraphMargin + m_cursorPositionX, 0,
352  m_leftGraphMargin + m_cursorPositionX, m_eleGraphHeight );
353  qreal xpos = m_axisX.minValue() + ( m_cursorPositionX / m_eleGraphWidth ) * m_axisX.range();
354  qreal ypos = m_eleGraphHeight - ( ( currentPoint.altitude() - m_axisY.minValue() ) / ( qMax<qreal>( 1.0, m_axisY.range() ) * m_shrinkFactorY ) ) * m_eleGraphHeight;
355 
356  painter->drawLine( m_leftGraphMargin + m_cursorPositionX - 5, ypos,
357  m_leftGraphMargin + m_cursorPositionX + 5, ypos );
358  intervalStr.setNum( xpos * m_axisX.scale(), 'f', 2 );
359  intervalStr += ' ' + m_axisX.unit();
360  int currentStringBegin = m_leftGraphMargin + m_cursorPositionX
361  - QFontMetricsF( font() ).width( intervalStr ) / 2;
362  painter->drawText( currentStringBegin, contentSize().height() - 1.5 * m_fontHeight, intervalStr );
363 
364  intervalStr.setNum( currentPoint.altitude(), 'f', 1 );
365  intervalStr += ' ' + m_axisY.unit();
366  if ( m_cursorPositionX + QFontMetricsF( font() ).width( intervalStr ) + m_leftGraphMargin
367  < m_eleGraphWidth ) {
368  currentStringBegin = ( m_leftGraphMargin + m_cursorPositionX + 5 + 2 );
369  } else {
370  currentStringBegin = m_leftGraphMargin + m_cursorPositionX - 5
371  - QFontMetricsF( font() ).width( intervalStr ) * 1.5;
372  }
373  // Make sure the text still fits into the window
374  while ( ypos < m_fontHeight ) {
375  ypos++;
376  }
377  painter->drawText( currentStringBegin, ypos + m_fontHeight / 2, intervalStr );
378  }
379 
380  painter->restore();
381 }
382 
383 QDialog *ElevationProfileFloatItem::configDialog() //FIXME TODO Make a config dialog?
384 {
385  if ( !m_configDialog ) {
386  // Initializing configuration dialog
387  m_configDialog = new QDialog();
388  ui_configWidget = new Ui::ElevationProfileConfigWidget;
389  ui_configWidget->setupUi( m_configDialog );
390 
391  readSettings();
392 
393  connect( ui_configWidget->m_buttonBox, SIGNAL(accepted()), SLOT(writeSettings()) );
394  connect( ui_configWidget->m_buttonBox, SIGNAL(rejected()), SLOT(readSettings()) );
395  QPushButton *applyButton = ui_configWidget->m_buttonBox->button( QDialogButtonBox::Apply );
396  connect( applyButton, SIGNAL(clicked()), this, SLOT(writeSettings()) );
397  }
398  return m_configDialog;
399 }
400 
401 void ElevationProfileFloatItem::contextMenuEvent( QWidget *w, QContextMenuEvent *e )
402 {
403  if ( !m_contextMenu ) {
404  m_contextMenu = contextMenu();
405 
406  foreach( QAction *action, m_contextMenu->actions() ) {
407  if ( action->text() == tr( "&Configure..." ) ) {
408  m_contextMenu->removeAction( action );
409  break;
410  }
411  }
412 
413  QAction *toggleAction = m_contextMenu->addAction( tr("&Zoom to viewport"), this,
414  SLOT(toggleZoomToViewport()) );
415  toggleAction->setCheckable( true );
416  toggleAction->setChecked( m_zoomToViewport );
417  }
418 
419  Q_ASSERT( m_contextMenu );
420  m_contextMenu->exec( w->mapToGlobal( e->pos() ) );
421 }
422 
423 bool ElevationProfileFloatItem::eventFilter( QObject *object, QEvent *e )
424 {
425  if ( !enabled() || !visible() ) {
426  return false;
427  }
428 
429  MarbleWidget *widget = dynamic_cast<MarbleWidget*>( object );
430  if ( !widget ) {
431  return AbstractFloatItem::eventFilter(object,e);
432  }
433 
434  if ( widget && !m_marbleWidget ) {
435  m_marbleWidget = widget;
436  connect( this, SIGNAL(dataUpdated()), this, SLOT(updateVisiblePoints()) );
437  connect( m_marbleWidget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
438  this, SLOT(updateVisiblePoints()) );
439  connect( this, SIGNAL(settingsChanged(QString)), this, SLOT(updateVisiblePoints()) );
440  }
441 
442  if ( e->type() == QEvent::MouseButtonDblClick || e->type() == QEvent::MouseMove ) {
443  GeoDataTreeModel *const treeModel = const_cast<MarbleModel *>( marbleModel() )->treeModel();
444 
445  QMouseEvent *event = static_cast<QMouseEvent*>( e );
446  QRectF plotRect = QRectF ( m_leftGraphMargin, 0, m_eleGraphWidth, contentSize().height() );
447  plotRect.translate( positivePosition() );
448  plotRect.translate( padding(), padding() );
449 
450  // for antialiasing: increase size by 1 px to each side
451  plotRect.translate(-1, -1);
452  plotRect.setSize(plotRect.size() + QSize(2, 2) );
453 
454  const bool cursorAboveFloatItem = plotRect.contains(event->pos());
455 
456  if ( cursorAboveFloatItem ) {
457  const int start = m_zoomToViewport ? m_firstVisiblePoint : 0;
458  const int end = m_zoomToViewport ? m_lastVisiblePoint : m_eleData.size();
459 
460  // Double click triggers recentering the map at the specified position
461  if ( e->type() == QEvent::MouseButtonDblClick ) {
462  const QPointF mousePosition = event->pos() - plotRect.topLeft();
463  const int xPos = mousePosition.x();
464  for ( int i = start; i < end; ++i) {
465  const int plotPos = ( m_eleData.value(i).x() - m_axisX.minValue() ) * m_eleGraphWidth / m_axisX.range();
466  if ( plotPos >= xPos ) {
467  widget->centerOn( m_points[i], true );
468  break;
469  }
470  }
471  return true;
472  }
473 
474  if ( e->type() == QEvent::MouseMove && !(event->buttons() & Qt::LeftButton) ) {
475  // Cross hair cursor when moving above the float item
476  // and mark the position on the graph
477  widget->setCursor(QCursor(Qt::CrossCursor));
478  if ( m_cursorPositionX != event->pos().x() - plotRect.left() ) {
479  m_cursorPositionX = event->pos().x() - plotRect.left();
480  const qreal xpos = m_axisX.minValue() + ( m_cursorPositionX / m_eleGraphWidth ) * m_axisX.range();
481  GeoDataCoordinates currentPoint; // invalid coordinates
482  for ( int i = start; i < end; ++i) {
483  if ( m_eleData.value(i).x() >= xpos ) {
484  currentPoint = m_points[i];
485  currentPoint.setAltitude( m_eleData.value(i).y() );
486  break;
487  }
488  }
489  m_markerPlacemark->setCoordinate( currentPoint );
490  if ( m_documentIndex < 0 ) {
491  m_documentIndex = treeModel->addDocument( &m_markerDocument );
492  }
493  emit repaintNeeded();
494  }
495 
496  return true;
497  }
498  }
499  else {
500  if ( m_documentIndex >= 0 ) {
501  m_markerPlacemark->setCoordinate( GeoDataCoordinates() ); // set to invalid
502  treeModel->removeDocument( &m_markerDocument );
503  m_documentIndex = -1;
504  emit repaintNeeded();
505  }
506  }
507  }
508 
509  return AbstractFloatItem::eventFilter(object,e);
510 }
511 
512 void ElevationProfileFloatItem::updateData()
513 {
514  m_routeAvailable = m_routingModel && m_routingModel->rowCount() > 0;
515  m_points = m_routeAvailable ? m_routingModel->route().path() : GeoDataLineString();
516  m_eleData = calculateElevationData( m_points );
517 
518  calculateStatistics( m_eleData );
519  if ( m_eleData.length() >= 2 ) {
520  m_axisX.setRange( m_eleData.first().x(), m_eleData.last().x() );
521  m_axisY.setRange( qMin( m_minElevation, qreal( 0.0 ) ), m_maxElevation );
522  }
523  emit dataUpdated();
524 
525  forceRepaint();
526 }
527 
528 void ElevationProfileFloatItem::updateVisiblePoints()
529 {
530  if ( ! ( m_routeAvailable && m_routingModel ) ) {
531  return;
532  }
533  GeoDataLineString points = m_routingModel->route().path();
534  if ( points.size() < 2 ) {
535  return;
536  }
537 
538  // find the longest visible route section on screen
539  QList<QList<int> > routeSegments;
540  QList<int> currentRouteSegment;
541  for ( int i = 0; i < m_eleData.count(); i++ ) {
542  qreal lon = points[i].longitude(GeoDataCoordinates::Degree);
543  qreal lat = points[i].latitude (GeoDataCoordinates::Degree);
544  qreal x = 0;
545  qreal y = 0;
546 
547  if ( m_marbleWidget->screenCoordinates(lon, lat, x, y) ) {
548  // on screen --> add point to list
549  currentRouteSegment.append(i);
550  } else {
551  // off screen --> start new list
552  if ( !currentRouteSegment.isEmpty() ) {
553  routeSegments.append( currentRouteSegment );
554  currentRouteSegment.clear();
555  }
556  }
557  }
558  routeSegments.append( currentRouteSegment ); // in case the route ends on screen
559 
560  int maxLenght = 0;
561  foreach ( const QList<int> &currentRouteSegment, routeSegments ) {
562  if ( currentRouteSegment.size() > maxLenght ) {
563  maxLenght = currentRouteSegment.size() ;
564  m_firstVisiblePoint = currentRouteSegment.first();
565  m_lastVisiblePoint = currentRouteSegment.last();
566  }
567  }
568  if ( m_firstVisiblePoint < 0 ) {
569  m_firstVisiblePoint = 0;
570  }
571  if ( m_lastVisiblePoint < 0 || m_lastVisiblePoint >= m_eleData.count() ) {
572  m_lastVisiblePoint = m_eleData.count() - 1;
573  }
574 
575  if ( m_zoomToViewport ) {
576  calculateStatistics( m_eleData );
577  m_axisX.setRange( m_eleData.value( m_firstVisiblePoint ).x(),
578  m_eleData.value( m_lastVisiblePoint ).x() );
579  m_axisY.setRange( m_minElevation, m_maxElevation );
580  }
581 
582  return;
583 }
584 
585 QList<QPointF> ElevationProfileFloatItem::calculateElevationData( const GeoDataLineString &lineString ) const
586 {
587  // TODO: Don't re-calculate the whole route if only a small part of it was changed
588  QList<QPointF> result;
589 
590  GeoDataLineString path;
591  for ( int i = 0; i < lineString.size(); i++ ) {
592  path.append( lineString[i] );
593 
594  const qreal lat = lineString[i].latitude ( GeoDataCoordinates::Degree );
595  const qreal lon = lineString[i].longitude( GeoDataCoordinates::Degree );
596  qreal ele = marbleModel()->elevationModel()->height( lon, lat );
597  if ( ele == invalidElevationData ) { // no data
598  ele = 0;
599  }
600 
601  // result.append( QPointF( path.length( EARTH_RADIUS ), ele ) );
602  // The code below does the same as the line above, but is much faster - O(1) instead of O(n)
603  if ( i ) {
604  Q_ASSERT( !result.isEmpty() ); // The else part below appended something in the first run
605  qreal const distance = EARTH_RADIUS * distanceSphere( lineString[i-1], lineString[i] );
606  result.append( QPointF( result.last().x() + distance, ele ) );
607  } else {
608  result.append( QPointF( 0, ele ) );
609  }
610  }
611 
612  return result;
613 }
614 
615 void ElevationProfileFloatItem::calculateStatistics( const QList<QPointF> &eleData )
616 {
617  const int averageOrder = 5;
618 
619  qreal lastAverage = 0;
620  m_maxElevation = 0.0;
621  m_minElevation = invalidElevationData;
622  m_gain = 0;
623  m_loss = 0;
624  const int start = m_zoomToViewport ? m_firstVisiblePoint : 0;
625  const int end = m_zoomToViewport ? m_lastVisiblePoint : eleData.size();
626  for ( int i = start; i < end; ++i ) {
627  m_maxElevation = qMax( m_maxElevation, eleData.value( i ).y() );
628  m_minElevation = qMin( m_minElevation, eleData.value( i ).y() );
629 
630  // Low-pass filtering (moving average) of the elevation profile to calculate gain and loss values
631  // not always the best method, see for example
632  // http://www.ikg.uni-hannover.de/fileadmin/ikg/staff/thesis/finished/documents/StudArb_Schulze.pdf
633  // (German), chapter 4.2
634 
635  if ( i >= averageOrder ) {
636  qreal average = 0;
637  for( int j = 0; j < averageOrder; j++ ) {
638  average += eleData.value( i-j ).y();
639  }
640  average /= averageOrder;
641  if ( i == averageOrder ) {
642  lastAverage = average; // else the initial elevation would be counted as gain
643  }
644  if ( average > lastAverage ) {
645  m_gain += average - lastAverage;
646  } else {
647  m_loss += lastAverage - average;
648  }
649  lastAverage = average;
650  }
651  }
652 }
653 
654 void ElevationProfileFloatItem::forceRepaint()
655 {
656  // We add one pixel as antialiasing could result into painting on these pixels to.
657  QRectF floatItemRect = QRectF( positivePosition() - QPoint( 1, 1 ),
658  size() + QSize( 2, 2 ) );
659  update();
660  emit repaintNeeded( floatItemRect.toRect() );
661 }
662 
663 void ElevationProfileFloatItem::readSettings()
664 {
665  if ( !m_configDialog )
666  return;
667 
668  if ( m_zoomToViewport ) {
669  ui_configWidget->m_zoomToViewportCheckBox->setCheckState( Qt::Checked );
670  }
671  else {
672  ui_configWidget->m_zoomToViewportCheckBox->setCheckState( Qt::Unchecked );
673  }
674 }
675 
676 void ElevationProfileFloatItem::writeSettings()
677 {
678  if ( ui_configWidget->m_zoomToViewportCheckBox->checkState() == Qt::Checked ) {
679  m_zoomToViewport = true;
680  } else {
681  m_zoomToViewport = false;
682  }
683 
684  emit settingsChanged( nameId() );
685 }
686 
687 void ElevationProfileFloatItem::toggleZoomToViewport()
688 {
689  m_zoomToViewport = ! m_zoomToViewport;
690  calculateStatistics( m_eleData );
691  if ( ! m_zoomToViewport ) {
692  m_axisX.setRange( m_eleData.first().x(), m_eleData.last().x() );
693  m_axisY.setRange( qMin( m_minElevation, qreal( 0.0 ) ), m_maxElevation );
694  }
695  readSettings();
696  emit settingsChanged( nameId() );
697 }
698 
699 
700 }
701 
702 Q_EXPORT_PLUGIN2(ElevationProfileFloatItem, Marble::ElevationProfileFloatItem)
703 
704 #include "ElevationProfileFloatItem.moc"
QAction::text
text
Marble::AxisTick::position
int position
Definition: ElevationProfilePlotAxis.h:22
Marble::ElevationProfilePlotAxis::setTickCount
void setTickCount(const int min, const int max)
Definition: ElevationProfilePlotAxis.cpp:46
QList::clear
void clear()
QEvent
Marble::ElevationProfileFloatItem::backendTypes
virtual QStringList backendTypes() const
Returns the name(s) of the backend that the plugin can render This method should return the name of t...
Definition: ElevationProfileFloatItem.cpp:81
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
QWidget
RoutingModel.h
Marble::ElevationProfilePlotAxis::minValue
qreal minValue() const
Definition: ElevationProfilePlotAxis.cpp:58
Marble::AbstractFloatItem::visible
bool visible() const
Check visibility of the float item.
Definition: AbstractFloatItem.cpp:137
QEvent::type
Type type() const
QPoint::rx
int & rx()
Marble::ElevationProfileFloatItem::nameId
virtual QString nameId() const
Returns the unique name of the plugin.
Definition: ElevationProfileFloatItem.cpp:101
QRectF::toRect
QRect toRect() const
QWidget::setCursor
void setCursor(const QCursor &)
Marble::GeoDataTreeModel
The representation of GeoData in a model This class represents all available data given by kml-data f...
Definition: GeoDataTreeModel.h:32
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
Marble::GeoDataDocument::setDocumentRole
void setDocumentRole(DocumentRole role)
Definition: GeoDataDocument.cpp:86
Marble::MarbleGlobal::HighResolution
Definition: MarbleGlobal.h:288
Marble::GeoDataCoordinates::setAltitude
void setAltitude(const qreal altitude)
set the altitude of the Point in meters
Definition: GeoDataCoordinates.cpp:1191
QPainter::setRenderHint
void setRenderHint(RenderHint hint, bool on)
Marble::ElevationProfileFloatItem::pluginAuthors
virtual QList< PluginAuthor > pluginAuthors() const
Definition: ElevationProfileFloatItem.cpp:121
MarbleMath.h
Marble::RenderPlugin::repaintNeeded
void repaintNeeded(QRegion dirtyRegion=QRegion())
This signal is emitted if an update of the view is needed.
QRect::right
int right() const
Marble::MarbleWidget::screenCoordinates
bool screenCoordinates(qreal lon, qreal lat, qreal &x, qreal &y) const
Get the screen coordinates corresponding to geographical coordinates in the widget.
Definition: MarbleWidget.cpp:662
Marble::ElevationProfilePlotAxis::unit
QString unit() const
Definition: ElevationProfilePlotAxis.cpp:78
QList::length
int length() const
QGradient::setColorAt
void setColorAt(qreal position, const QColor &color)
QAction::setChecked
void setChecked(bool)
Marble::ElevationProfileFloatItem::zValue
virtual qreal zValue() const
Returns the z value of the layer (default: 0.0).
Definition: ElevationProfileFloatItem.cpp:86
MarbleModel.h
This file contains the headers for MarbleModel.
Marble::ElevationProfilePlotAxis::setRange
void setRange(const qreal &minValue, const qreal &maxValue)
Definition: ElevationProfilePlotAxis.cpp:33
QRectF::size
QSizeF size() const
Marble::PluginAuthor
Definition: PluginInterface.h:28
Marble::AbstractFloatItem::pen
QPen pen() const
current pen for rendering
Definition: AbstractFloatItem.cpp:98
QMenu::addAction
void addAction(QAction *action)
Marble::AbstractFloatItem::eventFilter
virtual bool eventFilter(QObject *object, QEvent *e)
Definition: AbstractFloatItem.cpp:163
Marble::FrameGraphicsItem::contentSize
QSizeF contentSize() const
Returns the size of the content of the MarbleGraphicsItem.
Definition: FrameGraphicsItem.cpp:180
QWidget::mapToGlobal
QPoint mapToGlobal(const QPoint &pos) const
QPainter::save
void save()
Marble::GeoDataPlacemark::coordinate
GeoDataCoordinates coordinate(const QDateTime &dateTime=QDateTime(), bool *iconAtCoordinates=0) const
Return the coordinates of the placemark at time dateTime as a GeoDataCoordinates. ...
Definition: GeoDataPlacemark.cpp:172
QPainterPath::elementAt
const QPainterPath::Element & elementAt(int index) const
QColor::setAlpha
void setAlpha(int alpha)
QPainterPath::moveTo
void moveTo(const QPointF &point)
QBrush
Marble::distanceSphere
qreal distanceSphere(qreal lon1, qreal lat1, qreal lon2, qreal lat2)
This method calculates the shortest distance between two points on a sphere.
Definition: MarbleMath.h:52
Marble::MarbleGraphicsItem::size
QSizeF size() const
Returns the size of the item.
Definition: MarbleGraphicsItem.cpp:136
Marble::RoutingModel::route
const Route & route() const
Definition: RoutingModel.cpp:434
QPoint
Marble::RenderPlugin::action
QAction * action() const
Plugin's menu action.
Definition: RenderPlugin.cpp:88
QMouseEvent
Marble::RoutingModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const
Overload of QAbstractListModel.
Definition: RoutingModel.cpp:158
Marble::GeoDataPlacemark::setCoordinate
void setCoordinate(qreal longitude, qreal latitude, qreal altitude=0, GeoDataCoordinates::Unit _unit=GeoDataCoordinates::Radian)
Set the coordinate of the placemark in longitude and latitude.
Definition: GeoDataPlacemark.cpp:215
QPainter::drawLine
void drawLine(const QLineF &line)
Marble::ElevationProfileFloatItem::setProjection
virtual void setProjection(const ViewportParams *viewport)
Definition: ElevationProfileFloatItem.cpp:154
QLinearGradient
QObject::tr
QString tr(const char *sourceText, const char *disambiguation, int n)
QPainterPath::elementCount
int elementCount() const
QFontMetricsF::width
qreal width(const QString &text) const
Marble::GeoDataTreeModel::addDocument
int addDocument(GeoDataDocument *document)
Definition: GeoDataTreeModel.cpp:821
QRectF::left
qreal left() const
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
QPoint::x
int x() const
QPoint::y
int y() const
Marble::Oxygen::hotOrange4
QColor const hotOrange4
Definition: MarbleColors.h:86
Marble::UnknownDocument
Definition: GeoDataDocument.h:40
QList::size
int size() const
Marble::ElevationProfilePlotAxis::range
qreal range() const
Definition: ElevationProfilePlotAxis.cpp:68
QPointF
QList::value
T value(int i) const
Marble::MarbleWidget
A widget class that displays a view of the earth.
Definition: MarbleWidget.h:104
QObject::event
virtual bool event(QEvent *e)
Marble::RoutingManager::routingModel
RoutingModel * routingModel()
Provides access to the routing model which contains a list of routing instructions describing steps t...
Definition: RoutingManager.cpp:261
Marble::GeoDataCoordinates::altitude
qreal altitude() const
return the altitude of the Point in meters
Definition: GeoDataCoordinates.cpp:1197
QRect
QPainter::setFont
void setFont(const QFont &font)
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
Marble::AxisTick::value
qreal value
Definition: ElevationProfilePlotAxis.h:23
RoutingManager.h
Marble::ElevationProfileFloatItem::paintContent
virtual void paintContent(QPainter *painter)
Here the items paint their content.
Definition: ElevationProfileFloatItem.cpp:178
QPointF::x
qreal x() const
QRectF::translate
void translate(qreal dx, qreal dy)
QList::append
void append(const T &value)
QString::fromUtf8
QString fromUtf8(const char *str, int size)
Marble::ViewportParams::width
int width() const
Definition: ViewportParams.cpp:250
Marble::EARTH_RADIUS
const qreal EARTH_RADIUS
Definition: MarbleGlobal.h:257
Marble::ElevationProfileFloatItem::contextMenuEvent
virtual void contextMenuEvent(QWidget *w, QContextMenuEvent *e)
Definition: ElevationProfileFloatItem.cpp:401
Marble::GeoDataFeature::setName
void setName(const QString &value)
Set a new name for this feature.
Definition: GeoDataFeature.cpp:549
Marble::Oxygen::aluminumGray4
QColor const aluminumGray4
Definition: MarbleColors.h:92
Marble::MarbleModel::routingManager
RoutingManager * routingManager()
Definition: MarbleModel.cpp:675
Marble::ElevationProfileFloatItem::copyrightYears
virtual QString copyrightYears() const
Definition: ElevationProfileFloatItem.cpp:116
QRect::top
int top() const
Marble::ElevationProfileFloatItem::description
virtual QString description() const
Returns a user description of the plugin.
Definition: ElevationProfileFloatItem.cpp:111
Marble::ElevationProfileFloatItem::ElevationProfileFloatItem
ElevationProfileFloatItem(const MarbleModel *marbleModel=0)
Definition: ElevationProfileFloatItem.cpp:38
QContextMenuEvent
Marble::GeoDataTreeModel::removeDocument
void removeDocument(int index)
Definition: GeoDataTreeModel.cpp:872
QObject
QPainter::setPen
void setPen(const QColor &color)
Marble::RenderPlugin::settingsChanged
void settingsChanged(QString nameId)
This signal is emitted if the settings of the RenderPlugin changed.
QPainterPath::lineTo
void lineTo(const QPointF &endPoint)
QRect::setTop
void setTop(int y)
Marble::AbstractFloatItem
The abstract class for float item plugins.
Definition: AbstractFloatItem.h:45
QRect::left
int left() const
QList::isEmpty
bool isEmpty() const
QPainter
Marble::FrameGraphicsItem::contentRect
QRectF contentRect() const
Returns the rect of the content in item coordinates.
Definition: FrameGraphicsItem.cpp:167
MarbleDirs.h
QRectF::topLeft
QPointF topLeft() const
QRect::setWidth
void setWidth(int width)
QPainter::setBrush
void setBrush(const QBrush &brush)
QPainter::drawText
void drawText(const QPointF &position, const QString &text)
QRect::center
QPoint center() const
QPainterPath::setElementPositionAt
void setElementPositionAt(int index, qreal x, qreal y)
QList::first
T & first()
QString
QList
QColor
MarbleLocale.h
Marble::ElevationModel::height
qreal height(qreal lon, qreal lat) const
Definition: ElevationModel.cpp:83
QPen::setColor
void setColor(const QColor &color)
QRect::moveTop
void moveTop(int y)
GeoDataPlacemark.h
Marble::MarbleModel::elevationModel
ElevationModel * elevationModel()
Definition: MarbleModel.cpp:853
QMenu::exec
QAction * exec()
GeoDataTreeModel.h
Marble::GeoDataLineString
A LineString that allows to store a contiguous set of line segments.
Definition: GeoDataLineString.h:75
Marble::FrameGraphicsItem::padding
qreal padding() const
Returns the padding of the item.
Definition: FrameGraphicsItem.cpp:121
QStringList
Marble::ViewportParams
A public class that controls what is visible in the viewport of a Marble map.
Definition: ViewportParams.h:44
Marble::GeoDataContainer::append
void append(GeoDataFeature *other)
add an element
Definition: GeoDataContainer.cpp:272
Marble::ScreenGraphicsItem::positivePosition
QPointF positivePosition() const
Return the positive position of the ScreenGraphicsItem.
Definition: ScreenGraphicsItem.cpp:49
Q_EXPORT_PLUGIN2
#define Q_EXPORT_PLUGIN2(a, b)
Definition: marble_export.h:34
QSize
Marble::MarbleWidget::centerOn
void centerOn(const qreal lon, const qreal lat, bool animated=false)
Center the view on a geographical point.
Definition: MarbleWidget.cpp:549
MarbleGraphicsGridLayout.h
ViewportParams.h
This file contains the headers for ViewportParams.
Marble::AxisTick
Definition: ElevationProfilePlotAxis.h:21
Marble::MarbleGlobal::SmallScreen
Definition: MarbleGlobal.h:287
QAction::setCheckable
void setCheckable(bool)
Marble::ElevationProfilePlotAxis::scale
qreal scale() const
Definition: ElevationProfilePlotAxis.cpp:73
Marble::MarbleGlobal::getInstance
static MarbleGlobal * getInstance()
Definition: MarbleGlobal.cpp:37
Marble::ElevationProfileFloatItem::eventFilter
bool eventFilter(QObject *object, QEvent *e)
Definition: ElevationProfileFloatItem.cpp:423
Marble::GeoDataFeature::setVisible
void setVisible(bool value)
Set a new value for visibility.
Definition: GeoDataFeature.cpp:661
QPainter::restore
void restore()
ElevationProfileFloatItem.h
Marble::MarbleModel
The data model (not based on QAbstractModel) for a MarbleWidget.
Definition: MarbleModel.h:97
QPainterPath
QContextMenuEvent::pos
const QPoint & pos() const
ElevationModel.h
Marble::ElevationProfileFloatItem::initialize
virtual void initialize()
Definition: ElevationProfileFloatItem.cpp:133
QPainter::drawPath
void drawPath(const QPainterPath &path)
QSizeF
QPen::setWidth
void setWidth(int width)
QFontMetricsF::ascent
qreal ascent() const
QRectF
QString::setNum
QString & setNum(short n, int base)
QRect::setHeight
void setHeight(int height)
Marble::ScreenGraphicsItem::setPosition
void setPosition(const QPointF &position)
Set the position of the ScreenGraphicsItem.
Definition: ScreenGraphicsItem.cpp:44
QAction
QList::last
T & last()
QWidget::removeAction
void removeAction(QAction *action)
Marble::MarbleGlobal::profiles
Profiles profiles() const
Definition: MarbleGlobal.cpp:48
QRect::bottom
int bottom() const
Marble::Oxygen::forestGreen4
QColor const forestGreen4
Definition: MarbleColors.h:74
QPoint::setX
void setX(int x)
QPoint::setY
void setY(int y)
Marble::MarbleGraphicsItem::update
void update()
Marks the item and all parent items as invalid.
Definition: MarbleGraphicsItem.cpp:167
QPen
QDialog
MarbleWidget.h
This file contains the headers for MarbleWidget.
Marble::ElevationProfileFloatItem::version
virtual QString version() const
Definition: ElevationProfileFloatItem.cpp:106
Marble::AbstractFloatItem::font
QFont font() const
current font for rendering
Definition: AbstractFloatItem.cpp:109
QPushButton
QRectF::contains
bool contains(const QPointF &point) const
Marble::RenderPlugin::enabled
bool enabled() const
is enabled
QRectF::setSize
void setSize(const QSizeF &size)
Marble::ElevationProfileFloatItem::isInitialized
virtual bool isInitialized() const
Definition: ElevationProfileFloatItem.cpp:149
Marble::ElevationProfileFloatItem::dataUpdated
void dataUpdated()
Marble::ElevationProfilePlotAxis::setLength
void setLength(const int &length)
Definition: ElevationProfilePlotAxis.cpp:40
QRect::moveRight
void moveRight(int x)
Marble::Route::path
const GeoDataLineString & path() const
Definition: Route.cpp:66
Marble::GeoDataCoordinates::isValid
bool isValid() const
Returns.
Definition: GeoDataCoordinates.cpp:624
QRect::moveCenter
void moveCenter(const QPoint &position)
Marble::ElevationProfileFloatItem::name
virtual QString name() const
Returns the user-visible name of the plugin.
Definition: ElevationProfileFloatItem.cpp:91
Marble::ElevationProfilePlotAxis::ticks
AxisTickList ticks() const
Definition: ElevationProfilePlotAxis.cpp:83
Marble::RenderPlugin::marbleModel
const MarbleModel * marbleModel() const
Access to the MarbleModel.
Definition: RenderPlugin.cpp:83
Marble::FrameGraphicsItem::setPadding
void setPadding(qreal width)
Set the padding of the item.
Definition: FrameGraphicsItem.cpp:126
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QWidget::actions
QList< QAction * > actions() const
Marble::FrameGraphicsItem::setContentSize
void setContentSize(const QSizeF &size)
Sets the size of the content of the item.
Definition: FrameGraphicsItem.cpp:200
Marble::ElevationProfileFloatItem::~ElevationProfileFloatItem
~ElevationProfileFloatItem()
Definition: ElevationProfileFloatItem.cpp:77
Marble::AbstractFloatItem::contextMenu
QMenu * contextMenu()
Definition: AbstractFloatItem.cpp:225
Marble::ElevationProfileFloatItem::configDialog
QDialog * configDialog()
Returns a pointer to the configuration dialog of the plugin.
Definition: ElevationProfileFloatItem.cpp:383
QCursor
QPainter::pen
const QPen & pen() const
Marble::ElevationProfileFloatItem::icon
virtual QIcon icon() const
Returns an icon for the plugin.
Definition: ElevationProfileFloatItem.cpp:128
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QRect::setLeft
void setLeft(int x)
Marble::GeoDataPlacemark
a class representing a point of interest on the map
Definition: GeoDataPlacemark.h:54
Marble::GeoDataLatLonAltBox
A class that defines a 3D bounding box for geographic data.
Definition: GeoDataLatLonAltBox.h:49
QSizeF::width
qreal width() const
Marble::ElevationProfileFloatItem::guiString
virtual QString guiString() const
String that should be displayed in GUI.
Definition: ElevationProfileFloatItem.cpp:96
Marble::ElevationProfileFloatItem
The class that creates an interactive elvation profile.
Definition: ElevationProfileFloatItem.h:43
QIcon
Marble::MarbleGraphicsItem::setProjection
virtual void setProjection(const ViewportParams *viewport)
Definition: MarbleGraphicsItem.cpp:272
QFontMetricsF
Marble::AbstractFloatItem::setVisible
void setVisible(bool visible)
Set visibility of the float item.
Definition: AbstractFloatItem.cpp:130
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:39 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