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

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • kstars
  • fitsviewer
fitsviewer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  FITSViewer.cpp - A FITSViewer for KStars
3  -------------------
4  begin : Thu Jan 22 2004
5  copyright : (C) 2004 by Jasem Mutlaq
6  email : mutlaqja@ikarustech.com
7 
8  2006-03-03 Using CFITSIO, Porting to Qt4
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #include "fitsviewer.h"
21 
22 #include <klocale.h>
23 #include <kmessagebox.h>
24 #include <kfiledialog.h>
25 #include <kaction.h>
26 
27 #include <kstandardaction.h>
28 
29 #include <kdebug.h>
30 #include <ktoolbar.h>
31 #include <ktemporaryfile.h>
32 #include <kmenubar.h>
33 #include <kstatusbar.h>
34 #include <klineedit.h>
35 #include <kicon.h>
36 
37 #include <KUndoStack>
38 #include <KTabWidget>
39 #include <KAction>
40 #include <KActionCollection>
41 
42 #include <QFile>
43 #include <QCursor>
44 #include <QRadioButton>
45 #include <QClipboard>
46 #include <QImage>
47 #include <QRegExp>
48 #include <QKeyEvent>
49 #include <QCloseEvent>
50 #include <QTreeWidget>
51 #include <QHeaderView>
52 #include <QApplication>
53 #include <QUndoStack>
54 #include <QUndoGroup>
55 #include <QSignalMapper>
56 
57 #include <cmath>
58 #ifndef __MINGW32__
59  #include <unistd.h>
60 #endif
61 #include <cstdlib>
62 #include <string.h>
63 #include <errno.h>
64 #ifndef __MINGW32__
65  #include <netinet/in.h>
66 #endif
67 
68 #include "fitstab.h"
69 #include "fitsview.h"
70 #include "fitshistogram.h"
71 #include "ksutils.h"
72 #include "Options.h"
73 
74 QStringList FITSViewer::filterTypes = QStringList() << I18N_NOOP("Auto Stretch") << I18N_NOOP("High Contrast")
75  << I18N_NOOP("Equalize") << I18N_NOOP("High Pass");
76 
77 FITSViewer::FITSViewer (QWidget *parent)
78  : KXmlGuiWindow (parent)
79 {
80  fitsTab = new KTabWidget(this);
81  undoGroup = new QUndoGroup(this);
82 
83  fitsID = 0;
84  markStars = false;
85 
86  fitsTab->setTabsClosable(true);
87 
88  setCentralWidget(fitsTab);
89 
90  connect(fitsTab, SIGNAL(currentChanged(int)), this, SLOT(tabFocusUpdated(int)));
91  connect(fitsTab, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
92 
93  statusBar()->insertItem(QString(), FITS_POSITION);
94  statusBar()->setItemFixed(FITS_POSITION, 100);
95  statusBar()->insertItem(QString(), FITS_VALUE);
96  statusBar()->setItemFixed(FITS_VALUE, 100);
97  statusBar()->insertItem(QString(), FITS_RESOLUTION);
98  statusBar()->setItemFixed(FITS_RESOLUTION, 100);
99  statusBar()->insertItem(QString(), FITS_ZOOM);
100  statusBar()->setItemFixed(FITS_ZOOM, 50);
101  statusBar()->insertItem(QString(), FITS_WCS);
102  statusBar()->setItemFixed(FITS_WCS, 200);
103  statusBar()->insertPermanentItem(i18n("Welcome to KStars FITS Viewer"), FITS_MESSAGE, 1);
104  statusBar()->setItemAlignment(FITS_MESSAGE , Qt::AlignLeft);
105 
106  KAction *action;
107  QFile tempFile;
108 
109  action = actionCollection()->addAction("image_histogram");
110  action->setText(i18n("Histogram"));
111  connect(action, SIGNAL(triggered(bool)), SLOT (histoFITS()));
112  action->setShortcuts(KShortcut( Qt::CTRL+Qt::Key_H ));
113 
114  if (KSUtils::openDataFile( tempFile, "histogram.png" ) )
115  {
116  action->setIcon(KIcon(tempFile.fileName()));
117  tempFile.close();
118  }
119  else
120  action->setIcon(KIcon("tools-wizard"));
121 
122  KStandardAction::open(this, SLOT(openFile()), actionCollection());
123  saveFileAction = KStandardAction::save(this, SLOT(saveFile()), actionCollection());
124  saveFileAsAction = KStandardAction::saveAs(this, SLOT(saveFileAs()), actionCollection());
125 
126  action = actionCollection()->addAction("fits_header");
127  action->setIcon(KIcon("document-properties"));
128  action->setText(i18n( "FITS Header"));
129  connect(action, SIGNAL(triggered(bool) ), SLOT(headerFITS()));
130 
131  KStandardAction::close(this, SLOT(slotClose()), actionCollection());
132 
133  KStandardAction::copy(this, SLOT(copyFITS()), actionCollection());
134 
135  KStandardAction::zoomIn(this, SLOT(ZoomIn()), actionCollection());
136  KStandardAction::zoomOut(this, SLOT(ZoomOut()), actionCollection());
137  KStandardAction::actualSize(this, SLOT(ZoomDefault()), actionCollection());
138 
139  KAction *kundo = KStandardAction::undo(undoGroup, SLOT(undo()), actionCollection());
140  KAction *kredo = KStandardAction::redo(undoGroup, SLOT(redo()), actionCollection());
141 
142  connect(undoGroup, SIGNAL(canUndoChanged(bool)), kundo, SLOT(setEnabled(bool)));
143  connect(undoGroup, SIGNAL(canRedoChanged(bool)), kredo, SLOT(setEnabled(bool)));
144 
145  action = actionCollection()->addAction("image_stats");
146  action->setIcon(KIcon("view-statistics"));
147  action->setText(i18n( "Statistics"));
148  connect(action, SIGNAL(triggered(bool)), SLOT(statFITS()));
149 
150  action = actionCollection()->addAction("mark_stars");
151  action->setText(i18n( "Mark Stars"));
152  connect(action, SIGNAL(triggered(bool)), SLOT(toggleStars()));
153 
154  QSignalMapper *filterMapper = new QSignalMapper(this);
155 
156  int filterCounter=1;
157 
158  foreach(QString filter, FITSViewer::filterTypes)
159  {
160 
161  action = actionCollection()->addAction(QString("filter%1").arg(filterCounter));
162  action->setText(filter);
163  filterMapper->setMapping(action, filterCounter++);
164  connect(action, SIGNAL(triggered()), filterMapper, SLOT(map()));
165 
166 
167  }
168 
169  connect(filterMapper, SIGNAL(mapped(int)), this, SLOT(applyFilter(int)));
170 
171 /* action = actionCollection()->addAction("low_pass_filter");
172  action->setText(i18n( "Low Pass Filter"));
173  connect(action, SIGNAL(triggered(bool)), SLOT(lowPassFilter()));
174 
175  action = actionCollection()->addAction("equalize");
176  action->setText(i18n( "Equalize"));
177  connect(action, SIGNAL(triggered(bool)), SLOT(equalize()));*/
178 
179 
180  /* Create GUI */
181  createGUI("fitsviewer.rc");
182 
183  setWindowTitle(i18n("KStars FITS Viewer"));
184 
185  /* initially resize in accord with KDE rules */
186  resize(INITIAL_W, INITIAL_H);
187 }
188 
189 FITSViewer::~FITSViewer()
190 {
191  fitsTab->disconnect();
192 
193  qDeleteAll(fitsImages);
194 }
195 
196 int FITSViewer::addFITS(const KUrl *imageName, FITSMode mode, FITSScale filter)
197 {
198 
199  FITSTab *tab = new FITSTab(this);
200 
201  if (tab->loadFITS(imageName,mode, filter) == false)
202  {
203  if (fitsImages.size() == 0)
204  {
205 
206  // Close FITS Viewer and let KStars know it is no longer needed in memory.
207  close();
208  return -2;
209  }
210 
211  return -1;
212  }
213 
214  switch (mode)
215  {
216  case FITS_NORMAL:
217  fitsTab->addTab(tab, imageName->fileName());
218  break;
219 
220  case FITS_CALIBRATE:
221  fitsTab->addTab(tab, i18n("Calibrate"));
222  break;
223 
224  case FITS_FOCUS:
225  fitsTab->addTab(tab, i18n("Focus"));
226  break;
227 
228  case FITS_GUIDE:
229  fitsTab->addTab(tab, i18n("Guide"));
230  break;
231 
232  default:
233  break;
234 
235  }
236 
237  connect(tab, SIGNAL(newStatus(QString,FITSBar)), this, SLOT(updateStatusBar(QString,FITSBar)));
238  connect(tab->getImage(), SIGNAL(actionUpdated(QString,bool)), this, SLOT(updateAction(QString,bool)));
239  connect(tab, SIGNAL(changeStatus(bool)), this, SLOT(updateTabStatus(bool)));
240 
241  saveFileAction->setEnabled(true);
242  saveFileAsAction->setEnabled(true);
243 
244  undoGroup->addStack(tab->getUndoStack());
245  tab->tabPositionUpdated();
246 
247  fitsImages.push_back(tab);
248 
249  fitsMap[fitsID] = tab;
250 
251  fitsTab->setCurrentWidget(tab);
252 
253  tab->setUID(fitsID);
254 
255  return (fitsID++);
256 }
257 
258 bool FITSViewer::updateFITS(const KUrl *imageName, int fitsUID, FITSScale filter)
259 {
260  /*foreach (FITSTab *tab, fitsImages)
261  {
262  if (tab->getUID() == fitsUID)
263  return tab->loadFITS(imageName, tab->getImage()->getMode(), filter);
264  }*/
265 
266  FITSTab *tab = fitsMap.value(fitsUID);
267 
268  if (tab)
269  return tab->loadFITS(imageName, tab->getImage()->getMode(), filter);
270 
271  return false;
272 }
273 
274 void FITSViewer::tabFocusUpdated(int currentIndex)
275 {
276  if (currentIndex < 0 || fitsImages.empty())
277  return;
278 
279  fitsImages[currentIndex]->tabPositionUpdated();
280 
281  fitsImages[currentIndex]->getImage()->toggleStars(markStars);
282 
283  if (isVisible())
284  fitsImages[currentIndex]->getImage()->updateFrame();
285 
286  if (markStars)
287  updateStatusBar(i18np("%1 star detected.", "%1 stars detected.",fitsImages[currentIndex]->getImage()->getImageData()->getDetectedStars(),
288  fitsImages[currentIndex]->getImage()->getImageData()->getDetectedStars()), FITS_MESSAGE);
289  else
290  updateStatusBar("", FITS_MESSAGE);
291 
292  updateStatusBar("", FITS_WCS);
293 
294 }
295 
296 void FITSViewer::slotClose()
297 {
298 
299  int rc=0;
300  fitsTab->disconnect();
301 
302  if (undoGroup->isClean())
303  close();
304  else
305  {
306  for (int i=0; i < fitsImages.size(); i++)
307  if ( (rc=saveUnsaved(i)) == 2)
308  return;
309  }
310 }
311 
312 void FITSViewer::closeEvent(QCloseEvent *ev)
313 {
314 
315  int rc=0;
316  fitsTab->disconnect();
317 
318 
319  for (int i=0; i < fitsImages.size(); i++)
320  if ( (rc=saveUnsaved(i)) == 2)
321  {
322  ev->ignore();
323  return;
324  }
325 
326  if( undoGroup->isClean() )
327  ev->accept();
328  else
329  ev->ignore();
330 }
331 
332 void FITSViewer::openFile()
333 {
334  KUrl fileURL = KFileDialog::getOpenUrl( QDir::homePath(), "*.fits *.fit *.fts|Flexible Image Transport System");
335  if (fileURL.isEmpty())
336  return;
337 
338  QString fpath = fileURL.path();
339  QString cpath;
340 
341 
342  // Make sure we don't have it open already, if yes, switch to it
343  foreach (FITSTab *tab, fitsImages)
344  {
345  cpath = tab->getCurrentURL()->path();
346  if (fpath == cpath)
347  {
348  fitsTab->setCurrentWidget(tab);
349  return;
350  }
351  }
352 
353  addFITS(&fileURL);
354 
355 }
356 
357 void FITSViewer::saveFile()
358 {
359  fitsImages[fitsTab->currentIndex()]->saveFile();
360 }
361 
362 void FITSViewer::saveFileAs()
363 {
364  //currentURL.clear();
365 
366  if (fitsImages.empty())
367  return;
368 
369  fitsImages[fitsTab->currentIndex()]->saveFileAs();
370 
371 }
372 
373 void FITSViewer::copyFITS()
374 {
375  if (fitsImages.empty())
376  return;
377 
378  fitsImages[fitsTab->currentIndex()]->copyFITS();
379 }
380 
381 void FITSViewer::histoFITS()
382 {
383  if (fitsImages.empty())
384  return;
385 
386  fitsImages[fitsTab->currentIndex()]->histoFITS();
387 }
388 
389 void FITSViewer::statFITS()
390 {
391  if (fitsImages.empty())
392  return;
393 
394  fitsImages[fitsTab->currentIndex()]->statFITS();
395 }
396 
397 void FITSViewer::headerFITS()
398 {
399  if (fitsImages.empty())
400  return;
401 
402  fitsImages[fitsTab->currentIndex()]->headerFITS();
403 }
404 
405 int FITSViewer::saveUnsaved(int index)
406 {
407  FITSTab *targetTab = NULL;
408 
409  if (index < 0 || index >= fitsImages.size())
410  return -1;
411  targetTab = fitsImages[index];
412 
413  if (targetTab->getImage()->getMode() != FITS_NORMAL)
414  targetTab->getUndoStack()->clear();
415 
416  if (targetTab->getUndoStack()->isClean())
417  return -1;
418 
419  QString caption = i18n( "Save Changes to FITS?" );
420  QString message = i18n( "%1 has unsaved changes. Would you like to save before closing it?", targetTab->getCurrentURL()->fileName());
421  int ans = KMessageBox::warningYesNoCancel( 0, message, caption, KStandardGuiItem::save(), KStandardGuiItem::discard() );
422  if( ans == KMessageBox::Yes )
423  {
424  targetTab->saveFile();
425  return 0;
426  }
427  else if( ans == KMessageBox::No )
428  {
429  targetTab->getUndoStack()->clear();
430  return 1;
431  }
432  else if ( ans == KMessageBox::Cancel)
433  {
434  return 2;
435  }
436 
437 
438  return -1;
439 }
440 
441 void FITSViewer::updateStatusBar(const QString &msg, FITSBar id)
442 {
443  statusBar()->changeItem(msg, id);
444 }
445 
446 void FITSViewer::ZoomIn()
447 {
448  if (fitsImages.empty())
449  return;
450 
451  fitsImages[fitsTab->currentIndex()]->ZoomIn();
452 }
453 
454 void FITSViewer::ZoomOut()
455 {
456  if (fitsImages.empty())
457  return;
458 
459  fitsImages[fitsTab->currentIndex()]->ZoomOut();
460 }
461 
462 void FITSViewer::ZoomDefault()
463 {
464  if (fitsImages.empty())
465  return;
466 
467  fitsImages[fitsTab->currentIndex()]->ZoomDefault();
468 }
469 
470 void FITSViewer::updateAction(const QString &name, bool enable)
471 {
472  QAction *toolAction = NULL;
473 
474  toolAction = actionCollection()->action(name);
475  if (toolAction != NULL)
476  toolAction->setEnabled (enable);
477 }
478 
479 void FITSViewer::updateTabStatus(bool clean)
480 {
481  if (fitsImages.empty() || (fitsTab->currentIndex() >= fitsImages.size()))
482  return;
483 
484  if (fitsImages[fitsTab->currentIndex()]->getImage()->getMode() != FITS_NORMAL)
485  return;
486 
487  QString tabText = fitsImages[fitsTab->currentIndex()]->getCurrentURL()->fileName();
488 
489  fitsTab->setTabText(fitsTab->currentIndex(), clean ? tabText : tabText + '*');
490 }
491 
492 void FITSViewer::closeTab(int index)
493 {
494  if (fitsImages.empty())
495  return;
496 
497  FITSTab *tab = fitsImages[index];
498 
499  if (tab->getImage()->getMode() != FITS_NORMAL)
500  return;
501 
502  int rc = saveUnsaved(index);
503 
504  if (rc == 2)
505  return;
506 
507  fitsMap.remove(tab->getUID());
508  fitsImages.removeOne(tab);
509  delete tab;
510 
511  if (fitsImages.empty())
512  {
513  saveFileAction->setEnabled(false);
514  saveFileAsAction->setEnabled(false);
515  }
516 }
517 
518 void FITSViewer::toggleStars()
519 {
520 
521 
522  if (markStars)
523  {
524  markStars = false;
525  actionCollection()->action("mark_stars")->setText( i18n( "Mark Stars" ) );
526  }
527  else
528  {
529  markStars = true;
530  actionCollection()->action("mark_stars")->setText( i18n( "Unmark Stars" ) );
531  }
532 
533  foreach(FITSTab *tab, fitsImages)
534  {
535  tab->getImage()->toggleStars(markStars);
536  tab->getImage()->updateFrame();
537  }
538 
539  //updateStatusBar(i18np("%1 star detected.", "%1 stars detected.", fitsImages[fitsTab->currentIndex()]->getImage()->getDetectedStars()), FITS_MESSAGE);
540 
541 }
542 
543 void FITSViewer::applyFilter(int ftype)
544 {
545 
546  if (fitsImages.empty())
547  return;
548 
549  fitsImages[fitsTab->currentIndex()]->getHistogram()->applyFilter((FITSScale) ftype);
550  fitsImages[fitsTab->currentIndex()]->getImage()->updateFrame();
551 
552 
553 }
554 
555 FITSView * FITSViewer::getImage(int fitsUID)
556 {
557  FITSTab *tab = fitsMap.value(fitsUID);
558 
559  if (tab)
560  return tab->getImage();
561  else
562  return NULL;
563 }
564 
565 #include "fitsviewer.moc"
FITSViewer::ZoomIn
void ZoomIn()
Definition: fitsviewer.cpp:446
FITSTab::saveFile
void saveFile()
Definition: fitstab.cpp:227
fitstab.h
FITSViewer::ZoomDefault
void ZoomDefault()
Definition: fitsviewer.cpp:462
FITSTab::getImage
FITSView * getImage()
Definition: fitstab.h:43
FITSViewer::closeEvent
virtual void closeEvent(QCloseEvent *ev)
Definition: fitsviewer.cpp:312
FITSViewer::histoFITS
void histoFITS()
Definition: fitsviewer.cpp:381
FITSViewer::updateTabStatus
void updateTabStatus(bool clean)
Definition: fitsviewer.cpp:479
QWidget
FITS_NORMAL
Definition: fitscommon.h:20
FITSViewer::ZoomOut
void ZoomOut()
Definition: fitsviewer.cpp:454
FITSTab::setUID
void setUID(int newID)
Definition: fitstab.h:54
FITSViewer::saveFileAs
void saveFileAs()
Definition: fitsviewer.cpp:362
FITSView
Definition: fitsview.h:81
FITS_MESSAGE
Definition: fitscommon.h:21
FITS_WCS
Definition: fitscommon.h:21
INITIAL_H
#define INITIAL_H
Definition: fitsimage.h:48
FITSViewer::slotClose
void slotClose()
Definition: fitsviewer.cpp:296
fitsview.h
FITSViewer::FITSViewer
FITSViewer(QWidget *parent)
Constructor.
Definition: fitsviewer.cpp:77
KSUtils::openDataFile
bool openDataFile(QFile &file, const QString &filename)
Attempt to open the data file named filename, using the QFile object "file".
fitshistogram.h
KXmlGuiWindow
FITSViewer::copyFITS
void copyFITS()
Definition: fitsviewer.cpp:373
FITSScale
FITSScale
Definition: fitscommon.h:22
FITSView::toggleStars
void toggleStars(bool enable)
Definition: fitsview.cpp:458
FITSViewer::statFITS
void statFITS()
Definition: fitsviewer.cpp:389
FITSTab::loadFITS
bool loadFITS(const KUrl *imageURL, FITSMode mode=FITS_NORMAL, FITSScale filter=FITS_NONE)
Definition: fitstab.cpp:80
FITS_FOCUS
Definition: fitscommon.h:20
FITSTab::getUID
int getUID()
Definition: fitstab.h:55
FITSTab::getUndoStack
QUndoStack * getUndoStack()
Definition: fitstab.h:41
FITSViewer::closeTab
void closeTab(int index)
Definition: fitsviewer.cpp:492
FITS_RESOLUTION
Definition: fitscommon.h:21
FITS_VALUE
Definition: fitscommon.h:21
FITSTab::getCurrentURL
KUrl * getCurrentURL()
Definition: fitstab.h:42
FITS_POSITION
Definition: fitscommon.h:21
FITSViewer::addFITS
int addFITS(const KUrl *imageName, FITSMode mode=FITS_NORMAL, FITSScale filter=FITS_NONE)
Definition: fitsviewer.cpp:196
Options.h
FITSViewer::headerFITS
void headerFITS()
Definition: fitsviewer.cpp:397
FITSViewer::updateFITS
bool updateFITS(const KUrl *imageName, int fitsUID, FITSScale filter=FITS_NONE)
Definition: fitsviewer.cpp:258
FITSTab::tabPositionUpdated
void tabPositionUpdated()
Definition: fitstab.cpp:309
INITIAL_W
#define INITIAL_W
Definition: fitsimage.h:47
FITS_CALIBRATE
Definition: fitscommon.h:20
FITSViewer::toggleStars
void toggleStars()
Definition: fitsviewer.cpp:518
FITSViewer::saveUnsaved
int saveUnsaved(int index)
Definition: fitsviewer.cpp:405
FITSViewer::~FITSViewer
~FITSViewer()
Definition: fitsviewer.cpp:189
FITSViewer::applyFilter
void applyFilter(int ftype)
Definition: fitsviewer.cpp:543
FITSViewer::openFile
void openFile()
Definition: fitsviewer.cpp:332
FITSBar
FITSBar
Definition: fitscommon.h:21
FITS_ZOOM
Definition: fitscommon.h:21
FITSViewer::updateStatusBar
void updateStatusBar(const QString &msg, FITSBar id)
Definition: fitsviewer.cpp:441
fitsviewer.h
FITSViewer::tabFocusUpdated
void tabFocusUpdated(int currentIndex)
Definition: fitsviewer.cpp:274
FITSView::updateFrame
void updateFrame()
Definition: fitsview.cpp:352
FITSTab
Definition: fitstab.h:31
FITSViewer::saveFile
void saveFile()
Definition: fitsviewer.cpp:357
FITSViewer::filterTypes
static QStringList filterTypes
Definition: fitsviewer.h:71
ksutils.h
FITSViewer::getImage
FITSView * getImage(int fitsUID)
Definition: fitsviewer.cpp:555
FITSViewer::updateAction
void updateAction(const QString &name, bool enable)
Definition: fitsviewer.cpp:470
FITSView::getMode
FITSMode getMode()
Definition: fitsview.h:101
FITSMode
FITSMode
Definition: fitscommon.h:20
FITS_GUIDE
Definition: fitscommon.h:20
FITSLabel::newStatus
void newStatus(const QString &msg, FITSBar id)
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:19 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • 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
  • kstars
  • libkdeedu
  •   keduvocdocument
  • 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