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

parley

  • sources
  • kde-4.12
  • kdeedu
  • parley
  • src
  • settings
languagepropertiespage.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  Copyright 2008 Frederik Gladhorn <gladhorn@kde.org>
3  ***************************************************************************/
4 
5 /***************************************************************************
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  ***************************************************************************/
13 
14 #include "languagepropertiespage.h"
15 
16 #include "languagesettings.h"
17 
18 #include <kinputdialog.h>
19 #include <kmessagebox.h>
20 
21 #include <KDebug>
22 #include <KLocale>
23 #include <KStandardDirs>
24 #include <KLineEdit>
25 #include <QCheckBox>
26 #include <QLabel>
27 #include <QtDBus>
28 #include <sonnet/speller.h>
29 
30 #include "practice/testentrymanager.h"
31 #include <keduvocdocument.h>
32 #include <keduvoclesson.h>
33 
34 #include <parleydocument.h>
35 
36 #define TENSE_TAG ". "
37 
38 LanguagePropertiesPage::LanguagePropertiesPage(KEduVocDocument *doc, int identifierIndex, QWidget *parent)
39  :QWidget(parent), m_doc(doc), m_identifierIndex(identifierIndex)
40 {
41  setupUi(this);
42 
43  connect(localeComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(localeChanged(const QString&)));
44  connect(downloadGrammarButton, SIGNAL(clicked()), this, SLOT(downloadGrammar()));
45 
46  QStringList languageCodes = KGlobal::locale()->allLanguagesList();
47 
48  // qmap automatically sorts by keys
49  QMap<QString, QString> languageCodeMap;
50  foreach (const QString &code, languageCodes){
51  languageCodeMap[KGlobal::locale()->languageCodeToName(code)] = code;
52  }
53  // add the language, but also it's code as data
54  foreach (const QString &language, languageCodeMap.keys()) {
55  localeComboBox->addItem(language, languageCodeMap.value(language));
56  }
57 
58  if (m_identifierIndex < m_doc->identifierCount()) {
59  localeComboBox->setCurrentIndex(localeComboBox->findData(
60  m_doc->identifier(m_identifierIndex).locale()));
61 
62  identifierNameLineEdit->setText(m_doc->identifier(m_identifierIndex).name());
63  }
64 
65  int index = (m_identifierIndex < m_doc->identifierCount() ? m_identifierIndex : 0);
66  LanguageSettings settings(m_doc->identifier(index).locale());
67  settings.readConfig();
68 
69  // fonts
70  editorFont->setFont(settings.editorFont());
71  practiceFont->setFont(settings.practiceFont());
72 
73  // keyboard layout
74  // try to talk to kxbk - get a list of keyboard layouts
75  QDBusInterface kxbk("org.kde.keyboard", "/Layouts", "org.kde.KeyboardLayouts");
76  QDBusReply<QStringList> reply = kxbk.call("getLayoutsList");
77  if (reply.isValid()) {
78  QStringList layouts = reply;
79  layouts.prepend(QString());
80  keyboardLayoutComboBox->clear();
81  keyboardLayoutComboBox->addItems(layouts);
82  keyboardLayoutComboBox->setEnabled(true);
83 
84  QDBusReply<QString> currentLayout = kxbk.call("getCurrentLayout");
85  keyboardLayoutComboBox->setCurrentIndex(keyboardLayoutComboBox->findText(currentLayout));
86  if (m_identifierIndex < m_doc->identifierCount()) {
87  if (!settings.keyboardLayout().isEmpty()) {
88  keyboardLayoutComboBox->setCurrentIndex(keyboardLayoutComboBox->findText(settings.keyboardLayout()));
89  }
90  }
91  } else {
92  kDebug() << "kxkb dbus error";
93  keyboardLayoutComboBox->setEnabled(false);
94  keyboardLayoutComboBox->addItem(i18n("No KDE keyboard selector found."));
95  }
96 
97  Sonnet::Speller speller;
98  QMap<QString, QString> dicts = speller.availableDictionaries();
99  QMap<QString, QString>::const_iterator iter = dicts.constBegin();
100  while (iter != dicts.constEnd()) {
101  spellcheckerComboBox->addItem(iter.key(), iter.value());
102  ++iter;
103  }
104  spellcheckerComboBox->model()->sort(0);
105  spellcheckerComboBox->setCurrentIndex(spellcheckerComboBox->findData(settings.spellChecker()));
106  loadGrammarFromDocument();
107 }
108 
109 void LanguagePropertiesPage::setLanguageIdentifierIndex(int newIndex)
110 {
111  m_identifierIndex = newIndex;
112 }
113 
114 namespace DocumentHelper {
115  void fetchGrammar(KEduVocDocument* doc, int languageIndex);
116 }
117 
118 void LanguagePropertiesPage::downloadGrammar()
119 {
120  DocumentHelper::fetchGrammar(m_doc, m_identifierIndex);
121  loadGrammarFromDocument();
122 }
123 
124 void LanguagePropertiesPage::loadGrammarFromDocument()
125 {
126  if (m_identifierIndex < m_doc->identifierCount()) {
127  // articles
128  KEduVocArticle articles = m_doc->identifier(m_identifierIndex).article();
129 
130  def_male->setText(articles.article( KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Masculine ));
131  indef_male->setText(articles.article( KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Masculine ));
132 
133  def_female->setText(articles.article( KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Feminine ));
134  indef_female->setText(articles.article( KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Feminine ));
135 
136  def_natural->setText(articles.article( KEduVocWordFlag::Singular | KEduVocWordFlag::Definite | KEduVocWordFlag::Neuter ));
137  indef_natural->setText(articles.article( KEduVocWordFlag::Singular | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Neuter ));
138 
139 
140  def_male_plural->setText(articles.article( KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Masculine ));
141  indef_male_plural->setText(articles.article( KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Masculine ));
142 
143  def_female_plural->setText(articles.article( KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Feminine ));
144  indef_female_plural->setText(articles.article( KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Feminine ));
145 
146  def_natural_plural->setText(articles.article( KEduVocWordFlag::Plural | KEduVocWordFlag::Definite | KEduVocWordFlag::Neuter ));
147  indef_natural_plural->setText(articles.article( KEduVocWordFlag::Plural | KEduVocWordFlag::Indefinite | KEduVocWordFlag::Neuter ));
148 
149  // personal pronouns
150  const KEduVocWordFlags numS = KEduVocWordFlag::Singular;
151  const KEduVocWordFlags numD = KEduVocWordFlag::Dual;
152  const KEduVocWordFlags numP = KEduVocWordFlag::Plural;
153 
154  KEduVocPersonalPronoun pronoun = m_doc->identifier(m_identifierIndex).personalPronouns();
155 
156  first_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numS));
157  second_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numS));
158  thirdM_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numS));
159  thirdF_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numS));
160  thirdN_singular->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS));
161 
162  dualFirstLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numD));
163  dualSecondLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numD));
164  dualThirdMaleLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numD));
165  dualThirdFemaleLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numD));
166  dualThirdNeutralLineEdit->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numD));
167 
168  first_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::First | numP));
169  second_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Second | numP));
170  thirdM_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numP));
171  thirdF_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numP));
172  thirdN_plural->setText(pronoun.personalPronoun(KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP));
173 
174  maleFemaleDifferCheckBox->setChecked(pronoun.maleFemaleDifferent());
175  neutralCheckBox->setChecked(pronoun.neutralExists());
176  dualCheckBox->setChecked(pronoun.dualExists());
177  }
178 
179  // update shown labels etc...
180  updateCheckBoxes();
181 
182  connect(maleFemaleDifferCheckBox, SIGNAL(toggled(bool)), SLOT(updateCheckBoxes()));
183  connect(neutralCheckBox, SIGNAL(toggled(bool)), SLOT(updateCheckBoxes()));
184  connect(dualCheckBox, SIGNAL(toggled(bool)), SLOT(updateCheckBoxes()));
185 
186  // tenses
187  connect(tenseList, SIGNAL(currentRowChanged(int)), this, SLOT(slotTenseChosen(int)));
188  connect(deleteButton, SIGNAL(clicked()), this, SLOT(slotDeleteTense()));
189  connect(modifyButton, SIGNAL(clicked()), this, SLOT(slotModifyTense()));
190  connect(newButton, SIGNAL(clicked()), this, SLOT(slotNewTense()));
191 
192  if (m_identifierIndex < m_doc->identifierCount()) {
193  int i = 1;
194  foreach(const QString &tenseName, m_doc->identifier(m_identifierIndex).tenseList()) {
195  tenseList->addItem(QString("%1").arg(i++, 2).append(TENSE_TAG).append(tenseName));
196  tenseIndex.append(i);
197  }
198  }
199 
200  m_currentTense = 0;
201  if (tenseList->count() > 0) {
202  tenseList->setCurrentRow(m_currentTense);
203  }
204 
205  modifyButton->setEnabled(tenseList->count() > 0);
206  deleteButton->setEnabled(tenseList->count() > 0);
207  tenseList->setFocus();
208 }
209 
210 void LanguagePropertiesPage::accept()
211 {
212  if (!isEnabled()) {
213  // disabled pages are deleted languages
214  return;
215  }
216 
217  // general
218  QString locale = localeComboBox->itemData(localeComboBox->currentIndex()).toString();
219 
220  // if no locales are found (kdebase not installed?) at least fall back to using the language name as locale.
221  if (locale.isEmpty()) {
222  locale = identifierNameLineEdit->text();
223  }
224  m_doc->identifier(m_identifierIndex).setLocale( locale );
225  m_doc->identifier(m_identifierIndex).setName( identifierNameLineEdit->text() );
226 
227  LanguageSettings settings(locale);
228 
229  settings.setEditorFont(editorFont->font());
230  settings.setPracticeFont(practiceFont->font());
231 
232  if ( keyboardLayoutComboBox->isEnabled() ) {
233  settings.setKeyboardLayout( keyboardLayoutComboBox->currentText() );
234  }
235  int index = spellcheckerComboBox->currentIndex();
236  settings.setSpellChecker(spellcheckerComboBox->itemData(index).toString());
237  settings.writeConfig();
238 
239  // articles
240  const KEduVocWordFlag::Flags artSing = KEduVocWordFlag::Singular;
241 // const KEduVocWordFlag::Flags artDual = KEduVocWordFlag::Dual;
242  const KEduVocWordFlag::Flags artPlur = KEduVocWordFlag::Plural;
243 
244  const KEduVocWordFlag::Flags artDef = KEduVocWordFlag::Definite;
245  const KEduVocWordFlag::Flags artIndef = KEduVocWordFlag::Indefinite;
246 
247  KEduVocArticle article;
248 
249  article.setArticle( def_male->text(), artSing | artDef | KEduVocWordFlag::Masculine );
250  article.setArticle( indef_male->text(), artSing | artIndef | KEduVocWordFlag::Masculine );
251  article.setArticle( def_female->text(), artSing | artDef | KEduVocWordFlag::Feminine );
252  article.setArticle( indef_female->text(), artSing | artIndef | KEduVocWordFlag::Feminine );
253  article.setArticle( def_natural->text(), artSing | artDef | KEduVocWordFlag::Neuter );
254  article.setArticle( indef_natural->text(), artSing | artIndef | KEduVocWordFlag::Neuter );
255 
256 
257  article.setArticle( def_male_plural->text(), artPlur | artDef | KEduVocWordFlag::Masculine );
258  article.setArticle( indef_male_plural->text(), artPlur | artIndef | KEduVocWordFlag::Masculine );
259  article.setArticle( def_female_plural->text(), artPlur | artDef | KEduVocWordFlag::Feminine );
260  article.setArticle( indef_female_plural->text(), artPlur | artIndef | KEduVocWordFlag::Feminine );
261  article.setArticle( def_natural_plural->text(), artPlur | artDef | KEduVocWordFlag::Neuter );
262  article.setArticle( indef_natural_plural->text(), artPlur | artIndef | KEduVocWordFlag::Neuter );
263 
264  m_doc->identifier(m_identifierIndex).setArticle( article );
265 
266  // personal pronouns
267  KEduVocPersonalPronoun pronoun;
268  const KEduVocWordFlags numS = KEduVocWordFlag::Singular;
269  const KEduVocWordFlags numD = KEduVocWordFlag::Dual;
270  const KEduVocWordFlags numP = KEduVocWordFlag::Plural;
271 
272  pronoun.setPersonalPronoun(first_singular->text(), KEduVocWordFlag::First | numS);
273  pronoun.setPersonalPronoun(second_singular->text(), KEduVocWordFlag::Second| numS);
274  pronoun.setPersonalPronoun(thirdM_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numS);
275  pronoun.setPersonalPronoun(thirdF_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numS);
276  pronoun.setPersonalPronoun(thirdN_singular->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numS);
277 
278  pronoun.setPersonalPronoun(dualFirstLineEdit->text(), KEduVocWordFlag::First | numD);
279  pronoun.setPersonalPronoun(dualSecondLineEdit->text(), KEduVocWordFlag::Second | numD);
280  pronoun.setPersonalPronoun(dualThirdMaleLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numD);
281  pronoun.setPersonalPronoun(dualThirdFemaleLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numD);
282  pronoun.setPersonalPronoun(dualThirdNeutralLineEdit->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter| numD);
283 
284  pronoun.setPersonalPronoun(first_plural->text(), KEduVocWordFlag::First | numP);
285  pronoun.setPersonalPronoun(second_plural->text(), KEduVocWordFlag::Second | numP);
286  pronoun.setPersonalPronoun(thirdM_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Masculine | numP);
287  pronoun.setPersonalPronoun(thirdF_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Feminine | numP);
288  pronoun.setPersonalPronoun(thirdN_plural->text(), KEduVocWordFlag::Third | KEduVocWordFlag::Neuter | numP);
289 
290  pronoun.setMaleFemaleDifferent(maleFemaleDifferCheckBox->isChecked());
291  pronoun.setNeutralExists(neutralCheckBox->isChecked());
292  pronoun.setDualExists(dualCheckBox->isChecked());
293 
294  m_doc->identifier(m_identifierIndex).setPersonalPronouns( pronoun );
295 
296 
297  // tenses
298  QList<int> tenseIndex;
299  QStringList tenses;
300 
301  QString str;
302  for (int i = 0; i < (int) tenseList->count(); i++) {
303  str = tenseList->item(i)->text();
304  tenses.append(str.mid(str.indexOf(TENSE_TAG) + QString(TENSE_TAG).length()));
305  }
306 
307  m_doc->identifier(m_identifierIndex).setTenseList(tenses);
308 }
309 
310 
311 void LanguagePropertiesPage::updateCheckBoxes()
312 {
313  bool maleFemale = maleFemaleDifferCheckBox->isChecked();
314  bool neutral = neutralCheckBox->isChecked();
315  bool dual = dualCheckBox->isChecked();
316 
317  neutralCheckBox->setVisible(maleFemale);
318  male_c_label->setVisible(maleFemale);
319  female_c_label->setVisible(maleFemale);
320  thirdM_singular->setVisible(maleFemale);
321  thirdF_singular->setVisible(maleFemale);
322  thirdM_plural->setVisible(maleFemale);
323  thirdF_plural->setVisible(maleFemale);
324 
325  dualLabel->setVisible(dual);
326  dualFirstLineEdit->setVisible(dual);
327  dualSecondLineEdit->setVisible(dual);
328 
329  dualThirdMaleLineEdit->setVisible(dual && maleFemale);
330  dualThirdFemaleLineEdit->setVisible(dual && maleFemale);
331 
332  if ( !maleFemale ) {
333  natural_c_label->setVisible(false);
334  thirdN_singular->setVisible(true);
335  thirdN_plural->setVisible(true);
336  dualThirdNeutralLineEdit->setVisible(dual);
337  } else {
338  natural_c_label->setVisible(neutral);
339  thirdN_singular->setVisible(neutral);
340  thirdN_plural->setVisible(neutral);
341  dualThirdNeutralLineEdit->setVisible(dual && neutral);
342  }
343 }
344 
345 void LanguagePropertiesPage::localeChanged(const QString & locale)
346 {
347  identifierNameLineEdit->setText( locale );
348 }
349 
350 
351 // ************** TENSES *********************
352 
353 void LanguagePropertiesPage::slotTenseChosen(int index)
354 {
355  m_currentTense = index;
356 }
357 
358 void LanguagePropertiesPage::slotNewTense()
359 {
360  bool ok;
361  QString getTense = KInputDialog::getText(i18n("Tense Name"), i18n("Enter name of tense:"), QString(), &ok, this);
362  if (!ok)
363  return;
364 
365  QString str;
366  int i = tenseList->count() + 1;
367  tenseList->addItem(QString("%1").arg(i, 2).append(TENSE_TAG).append(getTense.simplified()));
368  tenseIndex.append(-(i - 1));
369 
370  m_currentTense = tenseList->count();
371  tenseList->setCurrentRow(i - 1);
372  modifyButton->setEnabled(true);
373  deleteButton->setEnabled(true);
374 }
375 
376 void LanguagePropertiesPage::slotModifyTense()
377 {
378  if (tenseList->count() != 0 && (int) tenseList->count() > m_currentTense) {
379  QString str = tenseList->item(m_currentTense)->text();
380  str = str.mid(str.indexOf(TENSE_TAG) + QString(TENSE_TAG).length());
381 
382  bool ok;
383  QString getTense = KInputDialog::getText(i18n("Tense Name"), i18n("Enter name of tense:"), str, &ok, this);
384  if (!ok)
385  return;
386 
387  int i = m_currentTense + 1;
388  tenseList->item(m_currentTense)->setText(QString("%1").arg(i, 2).append(TENSE_TAG).append(getTense.simplified()));
389  }
390 }
391 
392 void LanguagePropertiesPage::updateListBox(int start)
393 {
394  QString str;
395  for (int i = start; i < (int) tenseList->count(); i++) {
396  str = tenseList->item(i)->text();
397  str = str.mid(str.indexOf(TENSE_TAG) + QString(TENSE_TAG).length());
398  tenseList->item(i)->setText(QString("%1").arg(i + 1, 2).append(TENSE_TAG).append(str));
399  }
400 }
401 
402 void LanguagePropertiesPage::slotDeleteTense()
403 {
404  int act = m_currentTense;
405  if (tenseList->count() > 0 && (int) tenseList->count() > act) {
406 
407  QString t = tenseList->item(act)->text();
408 
409  foreach (KEduVocExpression *exp, m_doc->lesson()->entries(KEduVocLesson::Recursive)) {
410  for (int lang = 0; lang < m_doc->identifierCount(); lang++) {
411  if ( exp->translation(lang)->conjugationTenses().contains(t)) {
412  KMessageBox::information(this, i18n("The selected user defined tense could not be deleted\nbecause it is in use."), i18n("Deleting Tense Description"));
413  return;
414  }
415  }
416  }
417 
418  delete tenseList->takeItem(act);
419  tenseIndex.erase(tenseIndex.begin() + act);
420 
421  if ((int) tenseList->count() <= act)
422  act = tenseList->count() - 1;
423  else
424  updateListBox(act); // update items after current
425 
426  if (act >= 0)
427  tenseList->setCurrentRow(act);
428  }
429  modifyButton->setEnabled(tenseList->count() > 0);
430  deleteButton->setEnabled(tenseList->count() > 0);
431 }
432 
433 #include "languagepropertiespage.moc"
TENSE_TAG
#define TENSE_TAG
Definition: languagepropertiespage.cpp:36
LanguageSettings::setKeyboardLayout
void setKeyboardLayout(const QString &v)
Set Keyboard layout for this locale.
Definition: languagesettings.h:20
LanguageSettings::setSpellChecker
void setSpellChecker(const QString &v)
Set Spell checker for this language.
Definition: languagesettings.h:45
languagesettings.h
LanguagePropertiesPage::LanguagePropertiesPage
LanguagePropertiesPage(KEduVocDocument *doc, int identifierIndex, QWidget *parent=0)
Definition: languagepropertiespage.cpp:38
languagepropertiespage.h
LanguagePropertiesPage::setLanguageIdentifierIndex
void setLanguageIdentifierIndex(int newIndex)
Definition: languagepropertiespage.cpp:109
testentrymanager.h
QWidget
DocumentHelper::fetchGrammar
void fetchGrammar(KEduVocDocument *doc, int languageIndex)
Definition: parleydocument.cpp:61
LanguagePropertiesPage::downloadGrammar
void downloadGrammar()
Definition: languagepropertiespage.cpp:118
parleydocument.h
LanguageSettings
Definition: languagesettings.h:10
LanguageSettings::setPracticeFont
void setPracticeFont(const QFont &v)
Set The font used during practice.
Definition: languagesettings.h:120
LanguageSettings::setEditorFont
void setEditorFont(const QFont &v)
Set The font used in the editor.
Definition: languagesettings.h:145
LanguagePropertiesPage::accept
void accept()
Definition: languagepropertiespage.cpp:210
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:42:06 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

parley

Skip menu "parley"
  • 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