Merge lp:~michael-sheldon/ubuntu-keyboard/word-ribbon-tidy-up into lp:ubuntu-keyboard
- word-ribbon-tidy-up
- Merge into trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Łukasz Zemczak | ||||||||
Approved revision: | 197 | ||||||||
Merged at revision: | 196 | ||||||||
Proposed branch: | lp:~michael-sheldon/ubuntu-keyboard/word-ribbon-tidy-up | ||||||||
Merge into: | lp:ubuntu-keyboard | ||||||||
Diff against target: |
522 lines (+139/-38) 19 files modified
plugins/pinyin/src/pinyinplugin.cpp (+1/-1) plugins/pinyin/src/pinyinplugin.h (+1/-1) plugins/westernsupport/predictivetextworker.cpp (+1/-1) plugins/westernsupport/predictivetextworker.h (+1/-1) plugins/westernsupport/spellcheckerworker.cpp (+1/-1) plugins/westernsupport/spellcheckerworker.h (+1/-1) plugins/westernsupport/westernlanguagesplugin.cpp (+2/-2) plugins/westernsupport/westernlanguagesplugin.h (+2/-2) qml/WordRibbon.qml (+1/-1) src/lib/logic/abstractlanguageplugin.h (+2/-2) src/lib/logic/abstractwordengine.cpp (+7/-0) src/lib/logic/abstractwordengine.h (+1/-0) src/lib/logic/wordengine.cpp (+84/-16) src/lib/logic/wordengine.h (+7/-2) src/lib/models/wordcandidate.cpp (+12/-0) src/lib/models/wordcandidate.h (+4/-0) src/lib/models/wordribbon.cpp (+4/-0) src/lib/models/wordribbon.h (+2/-1) src/view/abstracttexteditor.cpp (+5/-6) |
||||||||
To merge this branch: | bzr merge lp:~michael-sheldon/ubuntu-keyboard/word-ribbon-tidy-up | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Łukasz Zemczak | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Bill Filler (community) | Needs Fixing | ||
Review via email:
|
Commit message
Merge user input and primary prediction when they match, highlight auto-completion word instead of user input.
Description of the change
Merge user input and primary prediction when they match, highlight auto-completion word instead of user input.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Sheldon (michael-sheldon) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:194
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Bill Filler (bfiller) wrote : | # |
Seems to break a few cases that used to work, or possibly I don't understand the new changes. I have all the switches turned on.
- If I type the word "do", I'm presented with "do" and "don" both bold on the word ribbon. I expected pressing space would insert "do" but it inserts "don".
- Seeing the same thing with "that". It's showing "that" and "than" both highlighted and space selects "than".
It doesn't always do this. Seems to be related to the context of what I'm typing. But I think the bug is there should never be two highlighted words?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Sheldon (michael-sheldon) wrote : | # |
It sounds like maybe there's a race condition with the spell checker and presage both claiming the first candidate, I'll have a look into this when I get back on Friday.
- 195. By Michael Sheldon
-
Merge from trunk
- 196. By Michael Sheldon
-
Use mutex when receiving new candidates asynchronously from spell checker and word predictor
- 197. By Michael Sheldon
-
Keep track of the word that suggestions have been generated for and don't report suggestions that no longer match the current pre-edit text
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:197
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Łukasz Zemczak (sil2100) wrote : | # |
Code-wise everything looks fine, all cases seem to be handled pretty nicely. From the testing side everything looks good as well. For a moment I thought pinyin is a bit crashy, but then I checked that the same happens with the old code-base as well (bug will follow). So in overall, a green light from me! A great improvement I must say. Just hope I didn't miss anything, I'm not a big user of auto-completion and preedit ;)
+1.
Preview Diff
1 | === modified file 'plugins/pinyin/src/pinyinplugin.cpp' |
2 | --- plugins/pinyin/src/pinyinplugin.cpp 2014-05-07 13:30:05 +0000 |
3 | +++ plugins/pinyin/src/pinyinplugin.cpp 2014-08-01 15:45:12 +0000 |
4 | @@ -18,7 +18,7 @@ |
5 | { |
6 | Q_UNUSED(surroundingLeft); |
7 | pinyinAdapter->parse(preedit); |
8 | - Q_EMIT newPredictionSuggestions(pinyinAdapter->getWordCandidates()); |
9 | + Q_EMIT newPredictionSuggestions(preedit, pinyinAdapter->getWordCandidates()); |
10 | } |
11 | |
12 | void PinyinPlugin::wordCandidateSelected(QString word) |
13 | |
14 | === modified file 'plugins/pinyin/src/pinyinplugin.h' |
15 | --- plugins/pinyin/src/pinyinplugin.h 2014-05-07 13:30:05 +0000 |
16 | +++ plugins/pinyin/src/pinyinplugin.h 2014-08-01 15:45:12 +0000 |
17 | @@ -35,7 +35,7 @@ |
18 | virtual bool setSpellCheckerLanguage(const QString& languageId) { Q_UNUSED(languageId); return false; } |
19 | |
20 | signals: |
21 | - void newPredictionSuggestions(QStringList suggestions); |
22 | + void newPredictionSuggestions(QString word, QStringList suggestions); |
23 | |
24 | public slots: |
25 | |
26 | |
27 | === modified file 'plugins/westernsupport/predictivetextworker.cpp' |
28 | --- plugins/westernsupport/predictivetextworker.cpp 2014-05-15 14:10:15 +0000 |
29 | +++ plugins/westernsupport/predictivetextworker.cpp 2014-08-01 15:45:12 +0000 |
30 | @@ -66,7 +66,7 @@ |
31 | qWarning() << "An exception was thrown in libpresage when calling predict(), exception nr: " << error; |
32 | } |
33 | |
34 | - Q_EMIT newSuggestions(list); |
35 | + Q_EMIT newSuggestions(preedit, list); |
36 | } |
37 | |
38 | void PredictiveTextWorker::setPredictionLanguage(QString locale) |
39 | |
40 | === modified file 'plugins/westernsupport/predictivetextworker.h' |
41 | --- plugins/westernsupport/predictivetextworker.h 2014-05-15 14:10:15 +0000 |
42 | +++ plugins/westernsupport/predictivetextworker.h 2014-08-01 15:45:12 +0000 |
43 | @@ -51,7 +51,7 @@ |
44 | void updateSpellCheckWord(QString word); |
45 | |
46 | signals: |
47 | - void newSuggestions(QStringList suggestions); |
48 | + void newSuggestions(QString word, QStringList suggestions); |
49 | |
50 | private: |
51 | std::string m_candidatesContext; |
52 | |
53 | === modified file 'plugins/westernsupport/spellcheckerworker.cpp' |
54 | --- plugins/westernsupport/spellcheckerworker.cpp 2014-05-15 14:10:15 +0000 |
55 | +++ plugins/westernsupport/spellcheckerworker.cpp 2014-08-01 15:45:12 +0000 |
56 | @@ -40,7 +40,7 @@ |
57 | void SpellCheckerWorker::suggest(const QString& word, int limit) |
58 | { |
59 | QStringList suggestions = m_spellChecker.suggest(word, limit); |
60 | - Q_EMIT newSuggestions(suggestions); |
61 | + Q_EMIT newSuggestions(word, suggestions); |
62 | } |
63 | |
64 | void SpellCheckerWorker::newSpellCheckWord(QString word) |
65 | |
66 | === modified file 'plugins/westernsupport/spellcheckerworker.h' |
67 | --- plugins/westernsupport/spellcheckerworker.h 2014-05-15 14:10:15 +0000 |
68 | +++ plugins/westernsupport/spellcheckerworker.h 2014-08-01 15:45:12 +0000 |
69 | @@ -48,7 +48,7 @@ |
70 | void updateSpellCheckWord(QString word); |
71 | |
72 | signals: |
73 | - void newSuggestions(QStringList suggestions); |
74 | + void newSuggestions(QString word, QStringList suggestions); |
75 | |
76 | private: |
77 | SpellChecker m_spellChecker; |
78 | |
79 | === modified file 'plugins/westernsupport/westernlanguagesplugin.cpp' |
80 | --- plugins/westernsupport/westernlanguagesplugin.cpp 2014-05-19 11:53:27 +0000 |
81 | +++ plugins/westernsupport/westernlanguagesplugin.cpp 2014-08-01 15:45:12 +0000 |
82 | @@ -15,7 +15,7 @@ |
83 | SpellCheckerWorker *spellWorker = new SpellCheckerWorker(); |
84 | spellWorker->moveToThread(m_spellCheckThread); |
85 | |
86 | - connect(spellWorker, SIGNAL(newSuggestions(QStringList)), this, SIGNAL(newSpellingSuggestions(QStringList))); |
87 | + connect(spellWorker, SIGNAL(newSuggestions(QString, QStringList)), this, SIGNAL(newSpellingSuggestions(QString, QStringList))); |
88 | connect(this, SIGNAL(newSpellCheckWord(QString)), spellWorker, SLOT(newSpellCheckWord(QString))); |
89 | connect(this, SIGNAL(setSpellCheckLanguage(QString)), spellWorker, SLOT(setLanguage(QString))); |
90 | connect(this, SIGNAL(setSpellCheckLimit(int)), spellWorker, SLOT(setLimit(int))); |
91 | @@ -27,7 +27,7 @@ |
92 | PredictiveTextWorker *predictiveWorker = new PredictiveTextWorker(); |
93 | predictiveWorker->moveToThread(m_predictiveTextThread); |
94 | |
95 | - connect(predictiveWorker, SIGNAL(newSuggestions(QStringList)), this, SIGNAL(newPredictionSuggestions(QStringList))); |
96 | + connect(predictiveWorker, SIGNAL(newSuggestions(QString, QStringList)), this, SIGNAL(newPredictionSuggestions(QString, QStringList))); |
97 | connect(this, SIGNAL(parsePredictionText(QString, QString)), predictiveWorker, SLOT(parsePredictionText(QString, QString))); |
98 | connect(this, SIGNAL(setPredictionLanguage(QString)), predictiveWorker, SLOT(setPredictionLanguage(QString))); |
99 | connect(this, SIGNAL(updateSpellCheckWord(QString)), predictiveWorker, SLOT(updateSpellCheckWord(QString))); |
100 | |
101 | === modified file 'plugins/westernsupport/westernlanguagesplugin.h' |
102 | --- plugins/westernsupport/westernlanguagesplugin.h 2014-05-19 11:53:27 +0000 |
103 | +++ plugins/westernsupport/westernlanguagesplugin.h 2014-08-01 15:45:12 +0000 |
104 | @@ -36,8 +36,8 @@ |
105 | virtual bool setSpellCheckerLanguage(const QString& languageId); |
106 | |
107 | signals: |
108 | - void newSpellingSuggestions(QStringList suggestions); |
109 | - void newPredictionSuggestions(QStringList suggestions); |
110 | + void newSpellingSuggestions(QString word, QStringList suggestions); |
111 | + void newPredictionSuggestions(QString word, QStringList suggestions); |
112 | void newSpellCheckWord(QString word); |
113 | void setSpellCheckLimit(int limit); |
114 | void setSpellCheckLanguage(QString language); |
115 | |
116 | === modified file 'qml/WordRibbon.qml' |
117 | --- qml/WordRibbon.qml 2014-05-20 06:49:39 +0000 |
118 | +++ qml/WordRibbon.qml 2014-08-01 15:45:12 +0000 |
119 | @@ -57,7 +57,7 @@ |
120 | font.pixelSize: units.gu(2); |
121 | font.family: "Ubuntu Medium" |
122 | color: "#999999" |
123 | - font.bold: isUserInput |
124 | + font.bold: isPrimaryCandidate |
125 | text: word; |
126 | } |
127 | } |
128 | |
129 | === modified file 'src/lib/logic/abstractlanguageplugin.h' |
130 | --- src/lib/logic/abstractlanguageplugin.h 2014-05-07 13:30:05 +0000 |
131 | +++ src/lib/logic/abstractlanguageplugin.h 2014-08-01 15:45:12 +0000 |
132 | @@ -54,8 +54,8 @@ |
133 | virtual bool setSpellCheckerLanguage(const QString& languageId); |
134 | |
135 | signals: |
136 | - void newSpellingSuggestions(QStringList suggestions); |
137 | - void newPredictionSuggestions(QStringList suggestions); |
138 | + void newSpellingSuggestions(QString word, QStringList suggestions); |
139 | + void newPredictionSuggestions(QString word, QStringList suggestions); |
140 | }; |
141 | |
142 | #endif // ABSTRACTLANGUAGEPLUGIN_H |
143 | |
144 | === modified file 'src/lib/logic/abstractwordengine.cpp' |
145 | --- src/lib/logic/abstractwordengine.cpp 2014-04-24 13:18:54 +0000 |
146 | +++ src/lib/logic/abstractwordengine.cpp 2014-08-01 15:45:12 +0000 |
147 | @@ -172,6 +172,13 @@ |
148 | Q_UNUSED(on); |
149 | qDebug() << Q_FUNC_INFO << "should be implemented by inherited class"; |
150 | } |
151 | + |
152 | +void AbstractWordEngine::setAutoCorrectEnabled(bool on) |
153 | +{ |
154 | + Q_UNUSED(on); |
155 | + qDebug() << Q_FUNC_INFO << "should be implemented by inherited class"; |
156 | +} |
157 | + |
158 | /* |
159 | AbstractLanguageFeature* AbstractWordEngine::languageFeature() |
160 | { |
161 | |
162 | === modified file 'src/lib/logic/abstractwordengine.h' |
163 | --- src/lib/logic/abstractwordengine.h 2014-05-01 14:40:09 +0000 |
164 | +++ src/lib/logic/abstractwordengine.h 2014-08-01 15:45:12 +0000 |
165 | @@ -64,6 +64,7 @@ |
166 | |
167 | Q_SLOT virtual void setWordPredictionEnabled(bool on); |
168 | Q_SLOT virtual void setSpellcheckerEnabled(bool on); |
169 | + Q_SLOT virtual void setAutoCorrectEnabled(bool on); |
170 | |
171 | void clearCandidates(); |
172 | void computeCandidates(Model::Text *text); |
173 | |
174 | === modified file 'src/lib/logic/wordengine.cpp' |
175 | --- src/lib/logic/wordengine.cpp 2014-07-23 11:21:23 +0000 |
176 | +++ src/lib/logic/wordengine.cpp 2014-08-01 15:45:12 +0000 |
177 | @@ -56,12 +56,16 @@ |
178 | |
179 | bool correct_spelling; |
180 | |
181 | + bool auto_correct_enabled; |
182 | + |
183 | LanguagePluginInterface* languagePlugin; |
184 | |
185 | QPluginLoader pluginLoader; |
186 | |
187 | WordCandidateList* candidates; |
188 | |
189 | + QString currentPreedit; |
190 | + |
191 | explicit WordEnginePrivate(); |
192 | |
193 | QString currentPlugin; |
194 | @@ -105,6 +109,7 @@ |
195 | , use_spell_checker(false) |
196 | , is_preedit_capitalized(false) |
197 | , correct_spelling(false) |
198 | + , auto_correct_enabled(false) |
199 | , languagePlugin(0) |
200 | { |
201 | loadPlugin(DEFAULT_PLUGIN); |
202 | @@ -200,6 +205,13 @@ |
203 | Q_EMIT enabledChanged(isEnabled()); |
204 | } |
205 | |
206 | +void WordEngine::setAutoCorrectEnabled(bool enabled) |
207 | +{ |
208 | + Q_D(WordEngine); |
209 | + |
210 | + d->auto_correct_enabled = enabled; |
211 | +} |
212 | + |
213 | void WordEngine::onWordCandidateSelected(QString word) |
214 | { |
215 | Q_D(WordEngine); |
216 | @@ -211,6 +223,8 @@ |
217 | { |
218 | Q_D(WordEngine); |
219 | |
220 | + d->currentPreedit = text->preedit(); |
221 | + |
222 | d->candidates = new WordCandidateList(); |
223 | const QString &preedit(text->preedit()); |
224 | d->is_preedit_capitalized = not preedit.isEmpty() && preedit.at(0).isUpper(); |
225 | @@ -240,10 +254,19 @@ |
226 | } |
227 | } |
228 | |
229 | -void WordEngine::newSpellingSuggestions(QStringList suggestions) |
230 | +void WordEngine::newSpellingSuggestions(QString word, QStringList suggestions) |
231 | { |
232 | Q_D(WordEngine); |
233 | |
234 | + if (word != d->currentPreedit) { |
235 | + // Don't add suggestions coming in for a previous word |
236 | + return; |
237 | + } |
238 | + |
239 | + // Spelling and prediction suggestions arrive asynchronously |
240 | + // So we need to ensure only one primary candidate is selected |
241 | + suggestionMutex.lock(); |
242 | + |
243 | // Only append candidates if we don't have the correct spelling, as these |
244 | // might be candidates from an earlier version of the word, before it was |
245 | // spelt correctly |
246 | @@ -252,41 +275,86 @@ |
247 | appendToCandidates(d->candidates, WordCandidate::SourceSpellChecking, correction); |
248 | } |
249 | |
250 | - Q_EMIT candidatesChanged(*d->candidates); |
251 | - |
252 | - // Candidates always has at least one entry from the user input candidate |
253 | - Q_EMIT primaryCandidateChanged(d->candidates->size() == 1 ? QString() |
254 | - : d->candidates->at(1).label()); |
255 | + calculatePrimaryCandidate(); |
256 | } |
257 | |
258 | Q_EMIT preeditFaceChanged(d->candidates->size() == 1 ? (d->correct_spelling ? Model::Text::PreeditDefault |
259 | : Model::Text::PreeditNoCandidates) |
260 | : Model::Text::PreeditDefault); |
261 | + |
262 | + suggestionMutex.unlock(); |
263 | } |
264 | |
265 | -void WordEngine::newPredictionSuggestions(QStringList suggestions) |
266 | +void WordEngine::newPredictionSuggestions(QString word, QStringList suggestions) |
267 | { |
268 | Q_D(WordEngine); |
269 | |
270 | + if (word != d->currentPreedit) { |
271 | + // Don't add suggestions coming in for a previous word |
272 | + return; |
273 | + } |
274 | + |
275 | + // Spelling and prediction suggestions arrive asynchronously |
276 | + // So we need to ensure only one primary candidate is selected |
277 | + suggestionMutex.lock(); |
278 | + |
279 | // If the current user entry is a valid word, add this as the first prediction |
280 | if(d->correct_spelling) { |
281 | appendToCandidates(d->candidates, WordCandidate::SourceSpellChecking, d->candidates->at(0).word()); |
282 | } |
283 | |
284 | Q_FOREACH(const QString &correction, suggestions) { |
285 | - if(correction != d->candidates->at(0).word()) { // Don't repeat correctly spelt user word |
286 | - appendToCandidates(d->candidates, WordCandidate::SourceSpellChecking, correction); |
287 | - } |
288 | + appendToCandidates(d->candidates, WordCandidate::SourceSpellChecking, correction); |
289 | } |
290 | |
291 | - Q_EMIT candidatesChanged(*d->candidates); |
292 | - |
293 | - Q_EMIT primaryCandidateChanged(d->candidates->size() == 1 ? QString() |
294 | - : d->candidates->at(1).label()); |
295 | + calculatePrimaryCandidate(); |
296 | |
297 | Q_EMIT preeditFaceChanged(d->candidates->size() == 1 ? (d->correct_spelling ? Model::Text::PreeditDefault |
298 | : Model::Text::PreeditNoCandidates) |
299 | : Model::Text::PreeditDefault); |
300 | + |
301 | + suggestionMutex.unlock(); |
302 | +} |
303 | + |
304 | +void WordEngine::calculatePrimaryCandidate() |
305 | +{ |
306 | + Q_D(WordEngine); |
307 | + |
308 | + if (!d->auto_correct_enabled) { |
309 | + if (d->candidates->size() > 1 && d->candidates->at(0).word() == d->candidates->at(1).word()) { |
310 | + // Avoid duplicating the user input if the first prediction matches |
311 | + d->candidates->removeAt(1); |
312 | + } |
313 | + Q_EMIT candidatesChanged(*d->candidates); |
314 | + return; |
315 | + } |
316 | + |
317 | + if (d->candidates->size() == 0) { |
318 | + // We should always have at least one entry due to the user input |
319 | + qWarning() << __PRETTY_FUNCTION__ << "User candidate missing"; |
320 | + } else if (d->candidates->size() == 1) { |
321 | + // We don't have any predictions, so the user input is the primary candidate |
322 | + WordCandidate primary = d->candidates->value(0); |
323 | + Q_EMIT primaryCandidateChanged(primary.word()); |
324 | + } else if (d->candidates->at(0).word() == d->candidates->at(1).word()) { |
325 | + // The user candidate matches the first prediction; remove the prediction |
326 | + // and make the user input the primary candidate so as not to duplicate |
327 | + // the word. |
328 | + d->candidates->removeAt(1); |
329 | + WordCandidate primary = d->candidates->value(0); |
330 | + primary.setPrimary(true); |
331 | + d->candidates->replace(0, primary); |
332 | + Q_EMIT primaryCandidateChanged(primary.word()); |
333 | + } else { |
334 | + // The first prediction is the primary candidate |
335 | + WordCandidate primary = d->candidates->value(1); |
336 | + primary.setPrimary(true); |
337 | + d->candidates->replace(1, primary); |
338 | + Q_EMIT primaryCandidateChanged(primary.word()); |
339 | + } |
340 | + |
341 | + Q_EMIT candidatesChanged(*d->candidates); |
342 | + |
343 | } |
344 | |
345 | void WordEngine::addToUserDictionary(const QString &word) |
346 | @@ -342,8 +410,8 @@ |
347 | if (ok) |
348 | d->languagePlugin->setSpellCheckerEnabled(d->use_spell_checker); |
349 | |
350 | - connect((AbstractLanguagePlugin *) d->languagePlugin, SIGNAL(newSpellingSuggestions(QStringList)), this, SLOT(newSpellingSuggestions(QStringList))); |
351 | - connect((AbstractLanguagePlugin *) d->languagePlugin, SIGNAL(newPredictionSuggestions(QStringList)), this, SLOT(newPredictionSuggestions(QStringList))); |
352 | + connect((AbstractLanguagePlugin *) d->languagePlugin, SIGNAL(newSpellingSuggestions(QString, QStringList)), this, SLOT(newSpellingSuggestions(QString, QStringList))); |
353 | + connect((AbstractLanguagePlugin *) d->languagePlugin, SIGNAL(newPredictionSuggestions(QString, QStringList)), this, SLOT(newPredictionSuggestions(QString, QStringList))); |
354 | } |
355 | |
356 | AbstractLanguageFeatures* WordEngine::languageFeature() |
357 | |
358 | === modified file 'src/lib/logic/wordengine.h' |
359 | --- src/lib/logic/wordengine.h 2014-06-30 11:31:44 +0000 |
360 | +++ src/lib/logic/wordengine.h 2014-08-01 15:45:12 +0000 |
361 | @@ -38,6 +38,7 @@ |
362 | #include "languageplugininterface.h" |
363 | |
364 | #include <QtCore> |
365 | +#include <QMutex> |
366 | |
367 | namespace MaliitKeyboard { |
368 | namespace Logic { |
369 | @@ -61,6 +62,7 @@ |
370 | |
371 | virtual void addToUserDictionary(const QString &word); |
372 | virtual void setSpellcheckerEnabled(bool enabled); |
373 | + virtual void setAutoCorrectEnabled(bool enabled); |
374 | //! \reimp_end |
375 | |
376 | void appendToCandidates(WordCandidateList *candidates, |
377 | @@ -69,8 +71,8 @@ |
378 | |
379 | Q_SLOT void onWordCandidateSelected(QString word); |
380 | Q_SLOT void onLanguageChanged(const QString& languageId); |
381 | - Q_SLOT void newSpellingSuggestions(QStringList suggestions); |
382 | - Q_SLOT void newPredictionSuggestions(QStringList suggestions); |
383 | + Q_SLOT void newSpellingSuggestions(QString word, QStringList suggestions); |
384 | + Q_SLOT void newPredictionSuggestions(QString word, QStringList suggestions); |
385 | |
386 | virtual AbstractLanguageFeatures* languageFeature(); |
387 | |
388 | @@ -78,8 +80,11 @@ |
389 | //! \reimp |
390 | virtual void fetchCandidates(Model::Text *text); |
391 | //! \reimp_end |
392 | + void calculatePrimaryCandidate(); |
393 | |
394 | const QScopedPointer<WordEnginePrivate> d_ptr; |
395 | + |
396 | + QMutex suggestionMutex; |
397 | }; |
398 | |
399 | }} // namespace Logic, MaliitKeyboard |
400 | |
401 | === modified file 'src/lib/models/wordcandidate.cpp' |
402 | --- src/lib/models/wordcandidate.cpp 2013-11-07 17:43:22 +0000 |
403 | +++ src/lib/models/wordcandidate.cpp 2014-08-01 15:45:12 +0000 |
404 | @@ -39,6 +39,7 @@ |
405 | , m_label() |
406 | , m_source(SourceUnknown) |
407 | , m_word() |
408 | + , m_primary(false) |
409 | {} |
410 | |
411 | WordCandidate::WordCandidate(Source source, const QString &word) |
412 | @@ -47,6 +48,7 @@ |
413 | , m_label() |
414 | , m_source(source) |
415 | , m_word(word) |
416 | + , m_primary(false) |
417 | { |
418 | if (source == WordCandidate::SourceUser) { |
419 | m_label = QString(QT_TR_NOOP("Add '%1' to user dictionary")).arg(word); |
420 | @@ -126,6 +128,16 @@ |
421 | m_word = word; |
422 | } |
423 | |
424 | +bool WordCandidate::primary() const |
425 | +{ |
426 | + return m_primary; |
427 | +} |
428 | + |
429 | +void WordCandidate::setPrimary(const bool primary) |
430 | +{ |
431 | + m_primary = primary; |
432 | +} |
433 | + |
434 | bool operator==(const WordCandidate &lhs, |
435 | const WordCandidate &rhs) |
436 | { |
437 | |
438 | === modified file 'src/lib/models/wordcandidate.h' |
439 | --- src/lib/models/wordcandidate.h 2013-11-07 17:43:22 +0000 |
440 | +++ src/lib/models/wordcandidate.h 2014-08-01 15:45:12 +0000 |
441 | @@ -54,6 +54,7 @@ |
442 | QString m_label; |
443 | Source m_source; |
444 | QString m_word; |
445 | + bool m_primary; |
446 | |
447 | public: |
448 | explicit WordCandidate(); |
449 | @@ -79,6 +80,9 @@ |
450 | |
451 | QString word() const; |
452 | void setWord(const QString &word); |
453 | + |
454 | + bool primary() const; |
455 | + void setPrimary(const bool primary); |
456 | }; |
457 | |
458 | typedef QList<WordCandidate> WordCandidateList; |
459 | |
460 | === modified file 'src/lib/models/wordribbon.cpp' |
461 | --- src/lib/models/wordribbon.cpp 2014-05-15 14:10:15 +0000 |
462 | +++ src/lib/models/wordribbon.cpp 2014-08-01 15:45:12 +0000 |
463 | @@ -42,6 +42,7 @@ |
464 | { |
465 | m_roles.insert(WordRole, "word"); |
466 | m_roles.insert(IsUserInputRole, "isUserInput"); |
467 | + m_roles.insert(IsPrimaryCandidateRole, "isPrimaryCandidate"); |
468 | } |
469 | |
470 | bool WordRibbon::valid() const |
471 | @@ -128,6 +129,9 @@ |
472 | case WordRibbon::IsUserInputRole: |
473 | return m_candidates.at(index.row()).source() == WordCandidate::SourceUser; |
474 | break; |
475 | + case WordRibbon::IsPrimaryCandidateRole: |
476 | + return m_candidates.at(index.row()).primary(); |
477 | + break; |
478 | default: |
479 | break; |
480 | } |
481 | |
482 | === modified file 'src/lib/models/wordribbon.h' |
483 | --- src/lib/models/wordribbon.h 2014-05-14 15:48:09 +0000 |
484 | +++ src/lib/models/wordribbon.h 2014-08-01 15:45:12 +0000 |
485 | @@ -58,7 +58,8 @@ |
486 | |
487 | enum WordRibbonRoles { |
488 | WordRole = Qt::UserRole + 1, |
489 | - IsUserInputRole |
490 | + IsUserInputRole, |
491 | + IsPrimaryCandidateRole |
492 | }; |
493 | |
494 | virtual QVariant data(const QModelIndex &index, int role) const; |
495 | |
496 | === modified file 'src/view/abstracttexteditor.cpp' |
497 | --- src/view/abstracttexteditor.cpp 2014-07-25 10:15:16 +0000 |
498 | +++ src/view/abstracttexteditor.cpp 2014-08-01 15:45:12 +0000 |
499 | @@ -360,6 +360,9 @@ |
500 | |
501 | connect(word_engine, SIGNAL(primaryCandidateChanged(QString)), |
502 | this, SLOT(setPrimaryCandidate(QString))); |
503 | + |
504 | + connect(this, SIGNAL(autoCorrectEnabledChanged(bool)), |
505 | + word_engine, SLOT(setAutoCorrectEnabled(bool))); |
506 | |
507 | setPreeditEnabled(word_engine->isEnabled()); |
508 | } |
509 | @@ -899,12 +902,8 @@ |
510 | d->text->removeFromPreedit(1); |
511 | textOnLeft += d->text->preedit(); |
512 | |
513 | - // Don't find word candidates if the user is holding down backspace |
514 | - if(!d->repeating_backspace) { |
515 | - d->word_engine->computeCandidates(d->text.data()); |
516 | - } else { |
517 | - Q_EMIT wordCandidatesChanged(WordCandidateList()); |
518 | - } |
519 | + // Clear previous word candidates |
520 | + Q_EMIT wordCandidatesChanged(WordCandidateList()); |
521 | sendPreeditString(d->text->preedit(), d->text->preeditFace(), |
522 | Replacement()); |
523 |
Are there any related MPs required for this MP to build/function as expected? Please list.
* No
Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes)
* Yes
Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator?
* Yes
Did you successfully run all tests found in your component's Test Plan (https:/ /wiki.ubuntu. com/Process/ Merges/ TestPlan/ ubuntu- keyboard) on device or emulator?
* Yes
If you changed the UI, was the change specified/approved by design?
* Yes, change to word ribbon UI requested at fit and finish sprint.
If you changed the packaging (debian), did you add a core-dev as a reviewer to this MP?
* No change