diff options
author | Tobias Markmann <tm@ayena.de> | 2017-06-26 03:58:09 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2017-06-26 09:13:57 (GMT) |
commit | 38b577abe56c76805e2f2bebb5194bee28359145 (patch) | |
tree | cb05fdfd725936c1fbe42e9245220befeadc8f6f | |
parent | 96528818b201c5a250701b58bb9c4d11048b237e (diff) | |
download | swift-38b577abe56c76805e2f2bebb5194bee28359145.zip swift-38b577abe56c76805e2f2bebb5194bee28359145.tar.bz2 |
Use size_t instead of int in SpellParser::PositionPair
Use of int required a lot of casts when using the indices
with std::string methods. Furthermore code used -1 as
error code, which should have used std::optional for invalid
PoistionPair instnaces.
Test-Information:
All tests pass on Debian Stretch with clang-3.9.
Change-Id: Ic5c44ed606deb58b6123d654f25fc50f047dfbc8
-rw-r--r-- | SwifTools/MacOSXChecker.mm | 2 | ||||
-rw-r--r-- | SwifTools/SpellParser.h | 2 | ||||
-rw-r--r-- | SwifTools/UnitTest/SpellParserTest.cpp | 24 | ||||
-rw-r--r-- | Swift/QtUI/QtTextEdit.cpp | 26 | ||||
-rw-r--r-- | Swift/QtUI/QtTextEdit.h | 6 |
5 files changed, 32 insertions, 28 deletions
diff --git a/SwifTools/MacOSXChecker.mm b/SwifTools/MacOSXChecker.mm index 519f06c..aefe3e7 100644 --- a/SwifTools/MacOSXChecker.mm +++ b/SwifTools/MacOSXChecker.mm @@ -42,38 +42,38 @@ void MacOSXChecker::setActiveLanguage(const std::string& /*language*/) { assert(false); } std::string MacOSXChecker::activeLanguage() const { assert(false); } std::vector<std::string> MacOSXChecker::supportedLanguages() const { assert(false); } void MacOSXChecker::getSuggestions(const std::string& word, std::vector<std::string>& list) { NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker]; NSString* wordString = [[NSString alloc] initWithUTF8String: word.c_str()]; NSArray* suggestions = [spellChecker guessesForWordRange:NSMakeRange(0, [wordString length]) inString:wordString language:nil inSpellDocumentWithTag:0]; for(unsigned int i = 0; i < [suggestions count]; ++i) { list.push_back(std::string([[suggestions objectAtIndex:i] UTF8String])); } [wordString release]; } void MacOSXChecker::checkFragment(const std::string& fragment, PositionPairList& misspelledPositions) { NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker]; size_t nextLocation = 0; NSRange range; NSString *fragmentString = [[NSString alloc] initWithUTF8String: fragment.c_str()]; do { range = [spellChecker checkSpellingOfString:fragmentString startingAt:static_cast<long>(nextLocation)]; if (range.location != NSNotFound) { if (range.location < nextLocation) break; - misspelledPositions.push_back(PositionPair(static_cast<int>(range.location), static_cast<int>(range.location + range.length))); + misspelledPositions.push_back(PositionPair(range.location, range.location + range.length)); nextLocation = range.location + range.length + 1; } } while (range.location != NSNotFound); [fragmentString release]; } } diff --git a/SwifTools/SpellParser.h b/SwifTools/SpellParser.h index 5b057c9..3c1cf8b 100644 --- a/SwifTools/SpellParser.h +++ b/SwifTools/SpellParser.h @@ -1,36 +1,36 @@ /* * Copyright (c) 2011 Vlad Voicu * Licensed under the Simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ /* * Copyright (c) 2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <vector> #include <boost/algorithm/string.hpp> #include <boost/tuple/tuple.hpp> namespace Swift { enum token_ids { ID_WWW = 1, ID_HTTP = 2, ID_WORD = 3, ID_CHAR = 4 }; - typedef boost::tuple<int, int> PositionPair; + typedef boost::tuple<size_t, size_t> PositionPair; typedef std::vector<PositionPair > PositionPairList; class SpellParser{ public: void check(const std::string& fragment, PositionPairList& wordPositions); }; } diff --git a/SwifTools/UnitTest/SpellParserTest.cpp b/SwifTools/UnitTest/SpellParserTest.cpp index ccfd7e5..bf974ec 100644 --- a/SwifTools/UnitTest/SpellParserTest.cpp +++ b/SwifTools/UnitTest/SpellParserTest.cpp @@ -7,52 +7,52 @@ /* * Copyright (c) 2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <memory> #include <boost/algorithm/string.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <SwifTools/SpellParser.h> using namespace Swift; class SpellParserTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SpellParserTest); CPPUNIT_TEST(testSimpleCheckFragment); CPPUNIT_TEST(testWWWCheckFragment); CPPUNIT_TEST_SUITE_END(); public: SpellParserTest() { } void tearDown() { position_.clear(); } void testSimpleCheckFragment() { parser_->check("fragment test", position_); - int size = position_.size(); - CPPUNIT_ASSERT_EQUAL(2, size); - CPPUNIT_ASSERT_EQUAL(0, boost::get<0>(position_.front())); - CPPUNIT_ASSERT_EQUAL(8, boost::get<1>(position_.front())); - CPPUNIT_ASSERT_EQUAL(9, boost::get<0>(position_.back())); - CPPUNIT_ASSERT_EQUAL(13, boost::get<1>(position_.back())); + auto size = position_.size(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), size); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), boost::get<0>(position_.front())); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(8), boost::get<1>(position_.front())); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(9), boost::get<0>(position_.back())); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(13), boost::get<1>(position_.back())); } void testWWWCheckFragment() { parser_->check("www.link.com fragment test", position_); - int size = position_.size(); - CPPUNIT_ASSERT_EQUAL(2, size); - CPPUNIT_ASSERT_EQUAL(13, boost::get<0>(position_.front())); - CPPUNIT_ASSERT_EQUAL(21, boost::get<1>(position_.front())); - CPPUNIT_ASSERT_EQUAL(22, boost::get<0>(position_.back())); - CPPUNIT_ASSERT_EQUAL(26, boost::get<1>(position_.back())); + auto size = position_.size(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), size); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(13), boost::get<0>(position_.front())); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(21), boost::get<1>(position_.front())); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(22), boost::get<0>(position_.back())); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(26), boost::get<1>(position_.back())); } private: const std::unique_ptr<SpellParser> parser_ = std::unique_ptr<SpellParser>(new SpellParser()); PositionPairList position_; }; CPPUNIT_TEST_SUITE_REGISTRATION(SpellParserTest); diff --git a/Swift/QtUI/QtTextEdit.cpp b/Swift/QtUI/QtTextEdit.cpp index 168e6fc..e63cd4f 100644 --- a/Swift/QtUI/QtTextEdit.cpp +++ b/Swift/QtUI/QtTextEdit.cpp @@ -104,132 +104,134 @@ void QtTextEdit::updateStyleSheet() { if (emphasiseFocus_) { if (hasFocus()) { newStyleSheet += "border: 2px solid palette(highlight);"; } } setStyleSheet(newStyleSheet); handleTextChanged(); } void QtTextEdit::focusInEvent(QFocusEvent* event) { receivedFocus(); QTextEdit::focusInEvent(event); updateStyleSheet(); } void QtTextEdit::focusOutEvent(QFocusEvent* event) { lostFocus(); QTextEdit::focusOutEvent(event); updateStyleSheet(); } void QtTextEdit::handleTextChanged() { QSize previous(maximumSize()); setMaximumSize(QSize(maximumWidth(), sizeHint().height())); if (previous != maximumSize()) { updateGeometry(); } } -void QtTextEdit::replaceMisspelledWord(const QString& word, int cursorPosition) { +void QtTextEdit::replaceMisspelledWord(const QString& word, size_t cursorPosition) { QTextCursor cursor = textCursor(); - PositionPair wordPosition = getWordFromCursor(cursorPosition); - cursor.setPosition(boost::get<0>(wordPosition), QTextCursor::MoveAnchor); - cursor.setPosition(boost::get<1>(wordPosition), QTextCursor::KeepAnchor); - QTextCharFormat normalFormat; - cursor.insertText(word, normalFormat); + auto wordPosition = getWordFromCursor(cursorPosition); + if (wordPosition) { + cursor.setPosition(boost::get<0>(*wordPosition), QTextCursor::MoveAnchor); + cursor.setPosition(boost::get<1>(*wordPosition), QTextCursor::KeepAnchor); + QTextCharFormat normalFormat; + cursor.insertText(word, normalFormat); + } } -PositionPair QtTextEdit::getWordFromCursor(int cursorPosition) { +boost::optional<PositionPair> QtTextEdit::getWordFromCursor(size_t cursorPosition) { PositionPairList misspelledPositions = highlighter_->getMisspelledPositions(); for (auto& misspelledPosition : misspelledPositions) { if (cursorPosition >= boost::get<0>(misspelledPosition) && cursorPosition <= boost::get<1>(misspelledPosition)) { return misspelledPosition; } } - return boost::make_tuple(-1,-1); + return boost::optional<PositionPair>(boost::make_tuple(-1,-1)); } QSize QtTextEdit::sizeHint() const { QSize hint = document()->size().toSize(); QMargins margins = contentsMargins(); return hint + QSize(margins.left() + margins.right(), margins.top() + margins.bottom()); } void QtTextEdit::contextMenuEvent(QContextMenuEvent* event) { QMenu* menu = createStandardContextMenu(); QTextCursor cursor = cursorForPosition(event->pos()); #ifdef HAVE_SPELLCHECKER QAction* insertPoint = menu->actions().first(); QAction* settingsAction = new QAction(tr("Spell Checker Options"), menu); menu->insertAction(insertPoint, settingsAction); menu->insertAction(insertPoint, menu->addSeparator()); addSuggestions(menu, event); QAction* result = menu->exec(event->globalPos()); if (result == settingsAction) { spellCheckerSettingsWindow(); } for (auto& replaceWordAction : replaceWordActions_) { if (replaceWordAction == result) { replaceMisspelledWord(replaceWordAction->text(), cursor.position()); } } #else menu->exec(event->globalPos()); #endif delete menu; } void QtTextEdit::dropEvent(QDropEvent* event) { if (event->mimeData()->hasUrls()) { itemDropped(event); } else { QTextEdit::dropEvent(event); } } void QtTextEdit::addSuggestions(QMenu* menu, QContextMenuEvent* event) { replaceWordActions_.clear(); if (checker_ && highlighter_) { QAction* insertPoint = menu->actions().first(); QTextCursor cursor = cursorForPosition(event->pos()); - PositionPair wordPosition = getWordFromCursor(cursor.position()); - if (boost::get<0>(wordPosition) < 0) { + auto wordPosition = getWordFromCursor(cursor.position()); + if (!wordPosition) { // The click was executed outside a spellable word so no // suggestions are necessary return; } - cursor.setPosition(boost::get<0>(wordPosition), QTextCursor::MoveAnchor); - cursor.setPosition(boost::get<1>(wordPosition), QTextCursor::KeepAnchor); + cursor.setPosition(boost::get<0>(*wordPosition), QTextCursor::MoveAnchor); + cursor.setPosition(boost::get<1>(*wordPosition), QTextCursor::KeepAnchor); std::vector<std::string> wordList; checker_->getSuggestions(Q2PSTRING(cursor.selectedText()), wordList); if (wordList.size() == 0) { QAction* noSuggestions = new QAction(tr("No Suggestions"), menu); noSuggestions->setDisabled(true); menu->insertAction(insertPoint, noSuggestions); } else { for (auto& word : wordList) { QAction* wordAction = new QAction(word.c_str(), menu); menu->insertAction(insertPoint, wordAction); replaceWordActions_.push_back(wordAction); } } menu->insertAction(insertPoint, menu->addSeparator()); } } #ifdef HAVE_SPELLCHECKER void QtTextEdit::setUpSpellChecker() { delete highlighter_; highlighter_ = nullptr; delete checker_; checker_ = nullptr; if (settings_->getSetting(QtUISettingConstants::SPELL_CHECKER)) { checker_ = SpellCheckerFactory().createSpellChecker(); if (checker_) { if (!checker_->isAutomaticallyDetectingLanguage()) { checker_->setActiveLanguage(settings_->getSetting(QtUISettingConstants::SPELL_CHECKER_LANGUAGE)); diff --git a/Swift/QtUI/QtTextEdit.h b/Swift/QtUI/QtTextEdit.h index 7ce5d88..178f258 100644 --- a/Swift/QtUI/QtTextEdit.h +++ b/Swift/QtUI/QtTextEdit.h @@ -1,70 +1,72 @@ /* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <boost/optional.hpp> + #include <QPointer> #include <QTextEdit> #include <Swift/Controllers/Settings/SettingsProvider.h> #include <SwifTools/SpellParser.h> #include <Swift/QtUI/QtSpellCheckHighlighter.h> namespace Swift { class SpellChecker; class QtSpellCheckerWindow; class QtTextEdit : public QTextEdit { Q_OBJECT public: QtTextEdit(SettingsProvider* settings, QWidget* parent = nullptr); virtual ~QtTextEdit(); virtual QSize sizeHint() const; void setEmphasiseFocus(bool emphasise); void setCorrectionHighlight(bool coorectionHighlight); signals: void wordCorrected(QString& word); void returnPressed(); void unhandledKeyPressEvent(QKeyEvent* event); void receivedFocus(); void lostFocus(); void itemDropped(QDropEvent* event); public slots: void handleSettingChanged(const std::string& settings); protected: virtual void keyPressEvent(QKeyEvent* event); virtual void focusInEvent(QFocusEvent* event); virtual void focusOutEvent(QFocusEvent* event); virtual void contextMenuEvent(QContextMenuEvent* event); virtual void dropEvent(QDropEvent* event); private slots: void handleTextChanged(); private: void addSuggestions(QMenu* menu, QContextMenuEvent* event); - void replaceMisspelledWord(const QString& word, int cursorPosition); + void replaceMisspelledWord(const QString& word, size_t cursorPosition); void setUpSpellChecker(); void spellCheckerSettingsWindow(); - PositionPair getWordFromCursor(int cursorPosition); + boost::optional<PositionPair> getWordFromCursor(size_t cursorPosition); void updateStyleSheet(); private: SpellChecker* checker_; QtSpellCheckHighlighter* highlighter_; std::vector<QAction*> replaceWordActions_; SettingsProvider* settings_; QPointer<QtSpellCheckerWindow> spellCheckerWindow_; bool emphasiseFocus_ = false; bool correctionHighlight_ = false; }; } |