diff options
author | ZackaryWelch <welch.zackary@gmail.com> | 2018-06-04 15:00:10 -0400 |
---|---|---|
committer | ZackaryWelch <welch.zackary@gmail.com> | 2018-06-04 15:00:10 -0400 |
commit | 16d2012168e175502520831cc8ae9e1cc146ca3e (patch) | |
tree | 8a550e99b4b89507829f7391235a4038c40ff5c8 | |
parent | Create README.md (diff) | |
download | lumina-16d2012168e175502520831cc8ae9e1cc146ca3e.tar.gz lumina-16d2012168e175502520831cc8ae9e1cc146ca3e.tar.bz2 lumina-16d2012168e175502520831cc8ae9e1cc146ca3e.zip |
Added spellchecking per Hunspell, which is currently disabled.
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/MainUI.cpp | 111 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/MainUI.h | 16 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/MainUI.ui | 26 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp | 44 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h | 8 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/Word.h | 20 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro | 5 | ||||
-rw-r--r-- | src-qt5/desktop-utils/lumina-textedit/wordMenu.h | 6 |
8 files changed, 224 insertions, 12 deletions
diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp index 71c4d173..d3b0338f 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp @@ -20,8 +20,12 @@ #include <QActionGroup> #include <QPrinter> #include <QPrintDialog> +#include <QClipboard> +#include <QInputDialog> #include "PlainTextEditor.h" +#define DEBUG 0 + MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ ui->setupUi(this); fontbox = new QFontComboBox(this); @@ -95,6 +99,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ ui->actionLine_Numbers->setChecked( settings->value("showLineNumbers",true).toBool() ); ui->actionWrap_Lines->setChecked( settings->value("wrapLines",true).toBool() ); ui->actionShow_Popups->setChecked( settings->value("showPopupWarnings",true).toBool() ); + ui->actionEnable_Spellcheck->setChecked( settings->value("enableSpellcheck",true).toBool() ); QString tabLoc = settings->value("tabsLocation","top").toString().toLower(); if(tabLoc=="bottom"){ ui->action_tabsBottom->setChecked(true); tabWidget->setTabPosition(QTabWidget::South);} else if(tabLoc=="left"){ ui->action_tabsLeft->setChecked(true); tabWidget->setTabPosition(QTabWidget::West);} @@ -120,7 +125,9 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ connect(ui->actionLine_Numbers, SIGNAL(toggled(bool)), this, SLOT(showLineNumbers(bool)) ); connect(ui->actionWrap_Lines, SIGNAL(toggled(bool)), this, SLOT(wrapLines(bool)) ); connect(ui->actionShow_Popups, SIGNAL(toggled(bool)), this, SLOT(showPopupWarnings(bool)) ); + connect(ui->actionEnable_Spellcheck, SIGNAL(toggled(bool)), this, SLOT(enableSpellcheck(bool)) ); connect(ui->actionCustomize_Colors, SIGNAL(triggered()), this, SLOT(ModifyColors()) ); + connect(ui->actionSet_Language, SIGNAL(triggered()), this, SLOT(SetLanguage()) ); connect(ui->actionFind, SIGNAL(triggered()), this, SLOT(openFind()) ); connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(openReplace()) ); connect(ui->tool_find_next, SIGNAL(clicked()), this, SLOT(findNext()) ); @@ -140,6 +147,11 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ if(lastSize.width() > this->sizeHint().width() && lastSize.height() > this->sizeHint().height() ){ this->resize(lastSize); } + + ui->actionEnable_Spellcheck->setEnabled(DEBUG); + ui->actionSet_Language->setEnabled(DEBUG); + ui->actionEnable_Spellcheck->setVisible(DEBUG); + ui->actionSet_Language->setVisible(DEBUG); } MainUI::~MainUI(){ @@ -201,6 +213,7 @@ QString MainUI::currentFile(){ } return ""; } + QString MainUI::currentFileDir(){ PlainTextEditor* cur = currentEditor(); QString dir; @@ -252,6 +265,8 @@ void MainUI::OpenFile(QString file){ edit = new PlainTextEditor(settings, this); connect(edit, SIGNAL(FileLoaded(QString)), this, SLOT(updateTab(QString)) ); connect(edit, SIGNAL(UnsavedChanges(QString)), this, SLOT(updateTab(QString)) ); + if(DEBUG) + connect(edit, SIGNAL(CheckSpelling(int, int)), this, SLOT(checkSpelling(int, int))); connect(edit, SIGNAL(statusTipChanged()), this, SLOT(updateStatusTip()) ); tabWidget->addTab(edit, files[i].section("/",-1)); edit->showLineNumbers(ui->actionLine_Numbers->isChecked()); @@ -260,9 +275,22 @@ void MainUI::OpenFile(QString file){ QFont font = fontbox->currentFont(); font.setPointSize( fontSizes->value() ); edit->document()->setDefaultFont(font); + /*QStringList applicationDirs = LXDG::systemApplicationDirs();*/ + if(ui->actionEnable_Spellcheck->isChecked()) { + QStringList dirs = QString(getenv("XDG_DATA_DIRS")).split(":"); + foreach(QString dir, dirs) { + if(QDir(dir).exists("hunspell")) { + //Default to US English Dictionary + hunspellPath = dir+"/hunspell/"; + hunspell = new Hunspell(QString(hunspellPath + "en_US.aff").toLocal8Bit(), QString(hunspellPath + "en_US.dic").toLocal8Bit()); + } + } + } } tabWidget->setCurrentWidget(edit); edit->LoadFile(files[i]); + if(DEBUG) + checkSpelling(-1); edit->setFocus(); QApplication::processEvents(); //to catch the fileLoaded() signal } @@ -370,7 +398,7 @@ void MainUI::showLineNumbers(bool show){ void MainUI::wrapLines(bool wrap){ settings->setValue("wrapLines",wrap); - if(currentEditor() == 0){ return; } + if(currentEditor() == NULL){ return; } currentEditor()->setLineWrapMode( wrap ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap); /*for(int i=0; i<tabWidget->count(); i++){ PlainTextEditor *edit = static_cast<PlainTextEditor*>(tabWidget->widget(i)); @@ -383,10 +411,42 @@ void MainUI::ModifyColors(){ colorDLG->showNormal(); } +void MainUI::SetLanguage() { + QDir dir(hunspellPath); + QStringList files = dir.entryList(QStringList() << "*.dic", QDir::Files); + QStringList items; + int defaultDic = 0; + for(int i = 0; i < files.size(); i++) { + QString item = files[i].split('.')[0]; + if(item == settings->value("language/").toString()) { + defaultDic = i; + } + items.append(item); + } + QString dic = QInputDialog::getItem(this, "Set Language for Document", "Language:", items, defaultDic); + settings->setValue("language/", dic); + if(hunspell) + delete hunspell; + + hunspell = new Hunspell(QString(hunspellPath+dic+".aff").toLocal8Bit(), QString(hunspellPath+dic+".dic").toLocal8Bit()); + + checkSpelling(-1); +} + void MainUI::showPopupWarnings(bool show){ settings->setValue("showPopupWarnings",show); } +void MainUI::enableSpellcheck(bool show){ + qDebug() << "Enabling Spellcheck"; + settings->setValue("enableSpellcheck",show); + if(currentEditor() != NULL and hunspell == NULL) { + /*QStringList applicationDirs = LXDG::systemApplicationDirs();*/ + hunspell = new Hunspell(QString(hunspellPath + "en_US.aff").toLocal8Bit(), QString(hunspellPath + "en_US.dic").toLocal8Bit()); + qDebug() << "Hunspell Created"; + } +} + void MainUI::showToolbar(bool show){ settings->setValue("showToolbar",show); ui->toolBar->setHidden(!show); @@ -559,6 +619,55 @@ PlainTextEditor *cur = currentEditor(); } } +void MainUI::checkWord(QTextBlock block) { + PlainTextEditor *cur = currentEditor(); + if(cur==0){ return; } + + foreach(Word *word, wordList) { + if(word->blockNum == block.blockNumber()) + wordList.removeOne(word); + } + + QStringList words = block.text().split(QRegExp("\\W+")); + QTextCursor cursor(block); + + foreach(QString word, words) { + if(!hunspell->spell(word.toStdString())) { + QList<QString> suggestions; + foreach(std::string newWord, hunspell->suggest(word.toStdString())) + suggestions.append(QString::fromStdString(newWord)); + QTextEdit::ExtraSelection sel; + sel.format.setBackground(QColor("Red")); + sel.cursor = cur->document()->find(word, cursor.position()); + Word *wordC = new Word(word, suggestions, sel, block.blockNumber(), cursor.positionInBlock()); + wordList.append(wordC); + } + cursor.movePosition(QTextCursor::NextWord, QTextCursor::MoveAnchor); + } +} + +void MainUI::checkSpelling(int bpos, int epos) { + //qDebug() << "Checking spelling on"; + PlainTextEditor *cur = currentEditor(); + if(cur==0){ return; } + static int numBlocks = cur->blockCount(); + + if(bpos == -1 or numBlocks != cur->blockCount()) { //When opening a file or loading a new dictionary + for(QTextBlock block = cur->document()->begin(); block != cur->document()->end(); block = block.next()) + checkWord(block); + numBlocks = cur->blockCount(); + }else if(epos == -1){ //Normal checking of one block from typing + QTextBlock block = cur->document()->findBlock(bpos); + checkWord(block); + }else { //Check blocks after copy/paste + for(QTextBlock block = cur->document()->findBlock(0); block != cur->document()->findBlock(epos); block = block.next()) { + checkWord(block); + } + } + + cur->setWordList(wordList); +} + //============= // PROTECTED //============= diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.h b/src-qt5/desktop-utils/lumina-textedit/MainUI.h index 600cd917..90222cb3 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.h +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.h @@ -19,6 +19,9 @@ #include "PlainTextEditor.h" #include "ColorDialog.h" #include "DnDTabBar.h" +#include "Word.h" + +#include <hunspell/hunspell.hxx> namespace Ui{ class MainUI; @@ -43,12 +46,16 @@ private: QShortcut *closeFindS, *nextTabS, *prevTabS; QSpinBox *fontSizes; QAction *label_readonly; + Hunspell *hunspell; + QList<Word*> wordList; + QString hunspellPath; //Simplification functions PlainTextEditor* currentEditor(); - QString currentFile(); + QString currentFile(); QString currentFileDir(); QStringList unsavedFiles(); + void checkWord(QTextBlock); private slots: //Main Actions @@ -63,12 +70,15 @@ private slots: void updateStatusTip(); void changeFontSize(int newFontSize); void changeTabsLocation(QAction*); + void checkSpelling(int bpos, int epos = -1); + void SetLanguage(); //Other Menu Actions void UpdateHighlighting(QAction *act = 0); void showToolbar(bool); void showLineNumbers(bool); void wrapLines(bool); + void enableSpellcheck(bool); void ModifyColors(); void showPopupWarnings(bool); @@ -78,8 +88,8 @@ private slots: void tabClosed(int); void tabDetached(int); void tabDraggedOut(int, Qt::DropAction); - void nextTab(); - void prevTab(); + void nextTab(); + void prevTab(); //Find/Replace functions void closeFindReplace(); diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.ui b/src-qt5/desktop-utils/lumina-textedit/MainUI.ui index f88f3976..7a43d74c 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.ui @@ -182,7 +182,7 @@ <x>0</x> <y>0</y> <width>505</width> - <height>24</height> + <height>23</height> </rect> </property> <property name="contextMenuPolicy"> @@ -228,8 +228,10 @@ <addaction name="actionLine_Numbers"/> <addaction name="actionWrap_Lines"/> <addaction name="actionShow_Popups"/> + <addaction name="actionEnable_Spellcheck"/> <addaction name="separator"/> <addaction name="actionCustomize_Colors"/> + <addaction name="actionSet_Language"/> </widget> <widget class="QMenu" name="menuEdit"> <property name="title"> @@ -448,6 +450,28 @@ <string>Show Toolbar</string> </property> </action> + <action name="actionEnable_Spellcheck"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Enable Spellcheck</string> + </property> + <property name="statusTip"> + <string>Enable Spellchecking</string> + </property> + </action> + <action name="actionSet_Language"> + <property name="text"> + <string>Set Language</string> + </property> + </action> </widget> <tabstops> <tabstop>line_find</tabstop> diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp index 69dc2eab..3c775851 100644 --- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp @@ -13,6 +13,9 @@ #include <QDebug> #include <QApplication> #include <QMessageBox> +#include <QMenu> +#include <QClipboard> +#include <QTimer> #include <LUtils.h> @@ -53,22 +56,21 @@ void PlainTextEditor::showLineNumbers(bool show){ } void PlainTextEditor::LoadSyntaxRule(QString type){ - //qDebug() << "Load SyntaxRule"; QList<SyntaxFile> files = SyntaxFile::availableFiles(settings); for(int i=0; i<files.length(); i++){ if(files[i].name() == type){ files[i].SetupDocument(this); SYNTAX->loadRules(files[i]); break; - }else if(i==files.length()-1){ - SyntaxFile dummy; SYNTAX->loadRules(dummy); + }else if(i==files.length()-1){ + SyntaxFile dummy; + SYNTAX->loadRules(dummy); } } SYNTAX->rehighlight(); } void PlainTextEditor::updateSyntaxColors(){ - //qDebug() << "Update Syntax Colors"; SYNTAX->reloadRules(); SYNTAX->rehighlight(); } @@ -288,6 +290,8 @@ void PlainTextEditor::LNW_updateWidth(){ } void PlainTextEditor::LNW_highlightLine(){ + QList<QTextEdit::ExtraSelection> sels; + foreach(Word *word, wordList) { sels.append(word->sel); }; if(this->isReadOnly()){ return; } QColor highC = QColor(0,0,0,50); //just darken the line a bit QTextEdit::ExtraSelection sel; @@ -295,7 +299,7 @@ void PlainTextEditor::LNW_highlightLine(){ sel.format.setProperty(QTextFormat::FullWidthSelection, true); sel.cursor = this->textCursor(); sel.cursor.clearSelection(); //just in case it already has one - setExtraSelections( QList<QTextEdit::ExtraSelection>() << sel ); + setExtraSelections( sels << sel); } void PlainTextEditor::LNW_update(const QRect &rect, int dy){ @@ -337,6 +341,7 @@ void PlainTextEditor::checkMatchChar(){ void PlainTextEditor::textChanged(){ //qDebug() << " - Got Text Changed signal"; bool changed = (lastSaveContents != this->toPlainText()); + emit CheckSpelling(this->textCursor().position(), -1); if(changed == hasChanges){ return; } //no change hasChanges = changed; //save for reading later if(hasChanges){ emit UnsavedChanges( this->whatsThis() ); } @@ -382,3 +387,32 @@ void PlainTextEditor::resizeEvent(QResizeEvent *ev){ void PlainTextEditor::updateLNW(){ LNW_updateWidth(); } + +void PlainTextEditor::contextMenuEvent(QContextMenuEvent *ev){ + QMenu *menu = createStandardContextMenu(); + qDebug() << this->textCursor().blockNumber() << this->textCursor().columnNumber() << this->textCursor().position(); + /*QMenu *menu = new QMenu(); + QString word = ""; + foreach(Word *word, wordList) { + foreach(QString word, word->suggestions) { + QAction *suggestionAction = menu->addAction(word); + } + } + menu->addSeparator(); + QAction *ignoreAll = menu->addAction(tr("Ignore All")); + QAction *addToDictionary = menu->addAction(tr("Add to Dictionary"));*/ + menu->exec(ev->globalPos()); + delete menu; +} + +void PlainTextEditor::keyPressEvent(QKeyEvent *ev) { + //Check spelling when copy/paste + if(ev->matches(QKeySequence::Paste) or ev->matches(QKeySequence::Cut)) { + QClipboard *clipboard = QGuiApplication::clipboard(); + int epos = this->textCursor().position() + clipboard->text().size(); + qDebug() << this->textCursor().position() << epos; + QTimer::singleShot(100, this, [=]() { emit CheckSpelling(this->textCursor().position(), epos); }); + } + + QPlainTextEdit::keyPressEvent(ev); +} diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h index b0a6cbc7..353f4d40 100644 --- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h +++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h @@ -14,6 +14,7 @@ #include <QFileSystemWatcher> #include "syntaxSupport.h" +#include "Word.h" //QPlainTextEdit subclass for providing the actual text editor functionality class PlainTextEditor : public QPlainTextEdit{ @@ -39,8 +40,9 @@ public: int LNWWidth(); //replacing the LNW size hint detection void paintLNW(QPaintEvent *ev); //forwarded from the LNW paint event void updateLNW(); + void setWordList(QList<Word*> _wordList) { wordList = _wordList; } - QFontMetrics *metrics; + QFontMetrics *metrics; private: QWidget *LNW; //Line Number Widget @@ -48,6 +50,7 @@ private: QSettings *settings; QString lastSaveContents; QFileSystemWatcher *watcher; + QList<Word*> wordList; //Syntax Highlighting class Custom_Syntax *SYNTAX; @@ -74,10 +77,13 @@ private slots: protected: void resizeEvent(QResizeEvent *ev); + void contextMenuEvent(QContextMenuEvent *ev); + void keyPressEvent(QKeyEvent *ev); signals: void UnsavedChanges(QString); //filename void FileLoaded(QString); + void CheckSpelling(int, int); void statusTipChanged(); }; diff --git a/src-qt5/desktop-utils/lumina-textedit/Word.h b/src-qt5/desktop-utils/lumina-textedit/Word.h new file mode 100644 index 00000000..7dd29257 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-textedit/Word.h @@ -0,0 +1,20 @@ +#include <QTextEdit> + +#pragma once + +class Word { + public: + Word(QString _word, QStringList _sugg, QTextEdit::ExtraSelection _sel, int _blockNum, int _position) : word(_word), suggestions(_sugg), sel(_sel), blockNum(_blockNum), position(_position) { + ignored = false; + } + + void ignore() { ignored = true; } + bool isIgnored() { return ignored; } + + QString word; + QStringList suggestions; + QTextEdit::ExtraSelection sel; + bool ignored; + int blockNum; + int position; +}; diff --git a/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro b/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro index 77cd8798..bbfc455b 100644 --- a/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro +++ b/src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro @@ -15,7 +15,8 @@ HEADERS += MainUI.h \ PlainTextEditor.h \ syntaxSupport.h \ ColorDialog.h \ - DnDTabBar.h + DnDTabBar.h \ + Word.h SOURCES += main.cpp \ MainUI.cpp \ @@ -26,6 +27,8 @@ SOURCES += main.cpp \ FORMS += MainUI.ui \ ColorDialog.ui +LIBS += -lhunspell-1.6 + TRANSLATIONS = i18n/l-te_af.ts \ i18n/l-te_ar.ts \ i18n/l-te_az.ts \ diff --git a/src-qt5/desktop-utils/lumina-textedit/wordMenu.h b/src-qt5/desktop-utils/lumina-textedit/wordMenu.h new file mode 100644 index 00000000..dfffcedd --- /dev/null +++ b/src-qt5/desktop-utils/lumina-textedit/wordMenu.h @@ -0,0 +1,6 @@ +class WordMenu : public QMenu { + WordMenu() { + ignoreAll = this->addAction(tr("Ignore All")); + + } +} |