summaryrefslogtreecommitdiff
path: root/extra/kdeplasma-addons
diff options
context:
space:
mode:
authorroot <root@rshg054.dnsready.net>2012-11-01 01:47:44 -0700
committerroot <root@rshg054.dnsready.net>2012-11-01 01:47:44 -0700
commit83a318800db22408628e60c9e1730578efcfee37 (patch)
tree9f1c330c5019dd940e41c44a7c1db13d337058a6 /extra/kdeplasma-addons
parent5827948456201df72a1bd73e87977c569129fb27 (diff)
Thu Nov 1 01:47:04 PDT 2012
Diffstat (limited to 'extra/kdeplasma-addons')
-rw-r--r--extra/kdeplasma-addons/PKGBUILD14
-rw-r--r--extra/kdeplasma-addons/fix-spell-crash.patch267
2 files changed, 277 insertions, 4 deletions
diff --git a/extra/kdeplasma-addons/PKGBUILD b/extra/kdeplasma-addons/PKGBUILD
index e3fa6d221..da60347b4 100644
--- a/extra/kdeplasma-addons/PKGBUILD
+++ b/extra/kdeplasma-addons/PKGBUILD
@@ -1,4 +1,4 @@
-# $Id: PKGBUILD 167845 2012-10-03 14:46:47Z andrea $
+# $Id: PKGBUILD 170053 2012-10-31 10:13:04Z andrea $
# Maintainer: Andrea Scarpino <andrea@archlinux.org>
# Contributor: Pierre Schmitz <pierre@archlinux.de>
@@ -76,17 +76,23 @@ pkgname=('kdeplasma-addons-applets-bball'
'kdeplasma-addons-wallpapers-virus'
'kdeplasma-addons-wallpapers-weather')
pkgver=4.9.2
-pkgrel=1
+pkgrel=3
arch=('i686' 'x86_64')
url='http://www.kde.org'
license=('GPL' 'LGPL')
groups=('kde' 'kdeplasma-addons')
makedepends=('cmake' 'automoc4' 'kdebase-workspace' 'kdeedu-marble' 'eigen'
'scim' 'qwt' 'boost' 'libkexiv2' 'ibus' 'qoauth' 'qjson')
-source=("http://download.kde.org/stable/${pkgver}/src/${pkgbase}-${pkgver}.tar.xz")
-sha1sums=('9f6493d52beb2ed723038e60f5f9ab53beec4e44')
+source=("http://download.kde.org/stable/${pkgver}/src/${pkgbase}-${pkgver}.tar.xz"
+ 'fix-spell-crash.patch')
+sha1sums=('9f6493d52beb2ed723038e60f5f9ab53beec4e44'
+ '1ff0e61d73a4fce8ee7f585504a129ff50405ae6')
build() {
+ cd ${pkgbase}-${pkgver}
+ patch -p1 -i "${srcdir}"/fix-spell-crash.patch
+ cd ../
+
mkdir build
cd build
cmake ../${pkgbase}-${pkgver} \
diff --git a/extra/kdeplasma-addons/fix-spell-crash.patch b/extra/kdeplasma-addons/fix-spell-crash.patch
new file mode 100644
index 000000000..75c26c6ad
--- /dev/null
+++ b/extra/kdeplasma-addons/fix-spell-crash.patch
@@ -0,0 +1,267 @@
+commit 124e35885b8cd1b593b7b83a070bd0bdb5758661
+Author: Simeon Bird <bladud@gmail.com>
+Date: Fri Oct 19 21:16:34 2012 -0400
+
+ Fix the plasma spellchecker's 'foreign language' support.
+ Previously this caused segfaults (even if not used) because
+ it called setLanguage(), which is not thread-safe, in match().
+
+ Instead, this patch constructs a new speller safely for each new
+ language, without deleting the old one. Old spellers are instead
+ deleted on the teardown() signal.
+
+ While we're at it, amend the language detection so that the user
+ can type natural language names (eg, 'german') and have the
+ spell-checker find the right language.
+
+ REVIEW: 106244
+ BUG: 303831
+ BUG: 264779
+ FIXED-IN: 4.9.3
+
+diff --git a/runners/spellchecker/spellcheck.cpp b/runners/spellchecker/spellcheck.cpp
+index 672732d..cc6aeb2 100644
+--- a/runners/spellchecker/spellcheck.cpp
++++ b/runners/spellchecker/spellcheck.cpp
+@@ -24,6 +24,7 @@
+ // #include <KDebug>
+ #include <KGlobal>
+ #include <KIcon>
++#include <QSet>
+
+ SpellCheckRunner::SpellCheckRunner(QObject* parent, const QVariantList &args)
+ : Plasma::AbstractRunner(parent, args)
+@@ -43,13 +44,64 @@ void SpellCheckRunner::init()
+ {
+ Plasma::AbstractRunner::init();
+
+- //store all language names, makes it posible to type "spell german TERM" if english locale is set
++ //Connect prepare and teardown signals
++ connect(this, SIGNAL(prepare()), this, SLOT(loaddata()));
++ connect(this, SIGNAL(teardown()), this, SLOT(destroydata()));
++}
++
++//Load a default dictionary and some locale names
++void SpellCheckRunner::loaddata()
++{
++ //Load the default speller, with the default language
++ if (!m_spellers.contains("")) {
++ m_spellers[""] = QSharedPointer<Sonnet::Speller> (new Sonnet::Speller(""));
++ }
++ //store all language names, makes it possible to type "spell german TERM" if english locale is set
++ //Need to construct a map between natual language names and names the spell-check recognises.
+ KLocale *locale = KGlobal::locale();
+- QStringList codes = locale->allLanguagesList();
+- foreach (const QString &code, codes) {
+- const QString name = locale->languageCodeToName(code);
+- m_languages[name.toLower()] = code;
++ const QStringList avail = m_spellers[""]->availableLanguages();
++ //We need to filter the available languages so that we associate the natural language
++ //name (eg. 'german') with one sub-code.
++ QSet<QString> families;
++ //First get the families
++ foreach (const QString &code, avail) {
++ families +=code.left(2);
++ }
++ //Now for each family figure out which is the main code.
++ foreach (const QString &fcode,families) {
++ QStringList family = avail.filter(fcode);
++ QString code;
++ //If we only have one code, use it.
++ //If a string is the default language, use it
++ if (family.contains(m_spellers[""]->language())) {
++ code = m_spellers[""]->language();
++ } else if (fcode == QLatin1String("en")) {
++ //If the family is english, default to en_US.
++ if (family.contains("en_US")) {
++ code = QLatin1String("en_US");
++ }
++ } else if (family.contains(fcode+QLatin1String("_")+fcode.toUpper())) {
++ //If we have a speller of the form xx_XX, try that.
++ //This gets us most European languages with more than one spelling.
++ code = fcode+QLatin1String("_")+fcode.toUpper();
++ } else {
++ //Otherwise, pick the first value as it is highest priority.
++ code = family.first();
++ }
++ //Finally, add code to the map.
++ const QString name = locale->languageCodeToName(fcode);
++ if (!name.isEmpty()) {
++ m_languages[name.toLower()] = code;
++ }
++// kDebug() << "SPELL lang: " << fcode<< "::"<< name << " : " << code;
+ }
++
++}
++
++void SpellCheckRunner::destroydata()
++{
++ //Clear the data arrays to save memory
++ m_spellers.clear();
+ }
+
+ void SpellCheckRunner::reloadConfiguration()
+@@ -73,13 +125,52 @@ void SpellCheckRunner::reloadConfiguration()
+ setSyntaxes(syns);
+ }
+
++/* Take the input query, split into a list, and see if it contains a language to spell in.
++ * Return the empty string if we can't match a language. */
++QString SpellCheckRunner::findlang(const QStringList& terms)
++{
++ //If first term is a language code (like en_GB), set it as the spell-check language
++ if (terms.count() >= 1 && m_spellers[""]->availableLanguages().contains(terms[0])) {
++ return terms[0];
++ }
++ //If we have two terms and the first is a language name (eg 'french'),
++ //set it as the available language
++ else if (terms.count() >=2) {
++ QString code;
++ {
++ //Is this a descriptive language name?
++ QMap<QString, QString>::const_iterator it = m_languages.constFind(terms[0].toLower());
++ if (it != m_languages.constEnd()) {
++ code = *it;
++ }
++ //Maybe it is a subset of a language code?
++ else {
++ QStringList codes = QStringList(m_languages.values()).filter(terms[0]);
++ if (!codes.isEmpty()) {
++ code = codes.first();
++ }
++ }
++ }
++
++ if (!code.isEmpty()) {
++ //We found a valid language! Check still available
++ const QStringList avail = m_spellers[""]->availableLanguages();
++ //Does the spell-checker like it?
++ if (avail.contains(code)) {
++ return code;
++ }
++ }
++ //FIXME: Support things like 'british english' or 'canadian french'
++ }
++ return QLatin1String("");
++}
++
+ void SpellCheckRunner::match(Plasma::RunnerContext &context)
+ {
+ if (!context.isValid()) {
+ return;
+ }
+
+-
+ const QString term = context.query();
+ QString query = term;
+
+@@ -88,53 +179,46 @@ void SpellCheckRunner::match(Plasma::RunnerContext &context)
+ if (query.left(len) != m_triggerWord) {
+ return;
+ }
+-
+- QString language = m_speller.defaultLanguage();
+ query = query.mid(len).trimmed();
+- QStringList terms = query.split(' ');
+-
+- //two terms specified, check if first is a language
+- QString customLanguage;
+- if (terms.count() == 2) {
+- customLanguage = terms[0];
+- query = terms[1];
+- }
+- //three terms specified, check if first two are a language, e.g. "american english"
+- if (terms.count() == 3) {
+- customLanguage = terms[0] + ' ' + terms[1];
+- query = terms[2];
+- }
+-
+- if (!customLanguage.isEmpty()) {
+- language = customLanguage;
+- m_speller.setLanguage(language);
++ }
+
+- //not valid, maybe it is a language name, not a code
+- if (!m_speller.isValid()) {
+- QHash<QString, QString>::const_iterator it = m_languages.constFind(language.toLower());
+- //is a valid language name
+- if (it != m_languages.constEnd()) {
+- language = *it;
++ //Pointer to speller object with our chosen language
++ QSharedPointer<Sonnet::Speller> speller = m_spellers[""];
++
++ if (speller->isValid()) {
++ QStringList terms = query.split(' ', QString::SkipEmptyParts);
++ QString lang = findlang(terms);
++ //If we found a language, create a new speller object using it.
++ if (!lang.isEmpty()) {
++ //First term is the language
++ terms.removeFirst();
++ //New speller object if we don't already have one
++ if (!m_spellers.contains(lang)) {
++ QMutexLocker lock (&m_spellLock);
++ //Check nothing happened while we were acquiring the lock
++ if (!m_spellers.contains(lang)) {
++ m_spellers[lang] = QSharedPointer<Sonnet::Speller>(new Sonnet::Speller(lang));
+ }
+ }
++ speller = m_spellers[lang];
++ //Rejoin the strings
++ query = terms.join(QLatin1String(" "));
+ }
+-
+- m_speller.setLanguage(language);
+ }
+
+- if (query.size() < 3) {
++ if (query.size() < 2) {
+ return;
+ }
+
+ Plasma::QueryMatch match(this);
+ match.setType(Plasma::QueryMatch::InformationalMatch);
+
+- if (m_speller.isValid()) {
++ if (speller->isValid()) {
+ QStringList suggestions;
+- const bool correct = m_speller.checkAndSuggest(query,suggestions);
++ const bool correct = speller->checkAndSuggest(query,suggestions);
+ if (correct) {
+ match.setIcon(KIcon(QLatin1String( "checkbox" )));
+- match.setText(i18n("Correct"));
++ match.setText(i18n("Correct")+QLatin1String(": ")+query);
+ } else {
+ match.setIcon(KIcon(QLatin1String( "edit-delete" )));
+ const QString recommended = i18n("Suggested words: %1", suggestions.join(i18nc("seperator for a list of words", ", ")));
+diff --git a/runners/spellchecker/spellcheck.h b/runners/spellchecker/spellcheck.h
+index 492c370..ca65452 100644
+--- a/runners/spellchecker/spellcheck.h
++++ b/runners/spellchecker/spellcheck.h
+@@ -22,6 +22,7 @@
+ #include <sonnet/speller.h>
+
+ #include <plasma/abstractrunner.h>
++#include <QSharedPointer>
+
+ /**
+ * This checks the spelling of query
+@@ -41,12 +42,17 @@ public:
+
+ protected slots:
+ void init();
++ void loaddata();
++ void destroydata();
+
+ private:
++ QString findlang(const QStringList &terms);
++
+ QString m_triggerWord;
+- QHash<QString, QString> m_languages;//key=language name, value=language code
++ QMap<QString, QString> m_languages;//key=language name, value=language code
+ bool m_requireTriggerWord;
+- Sonnet::Speller m_speller;
++ QMap<QString, QSharedPointer<Sonnet::Speller> > m_spellers; //spellers
++ QMutex m_spellLock; //Lock held when constructing a new speller
+ };
+
+ K_EXPORT_PLASMA_RUNNER(spellcheckrunner, SpellCheckRunner)