aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZackaryWelch <welch.zackary@gmail.com>2018-06-04 15:00:10 -0400
committerZackaryWelch <welch.zackary@gmail.com>2018-06-04 15:00:10 -0400
commit16d2012168e175502520831cc8ae9e1cc146ca3e (patch)
tree8a550e99b4b89507829f7391235a4038c40ff5c8
parentCreate README.md (diff)
downloadlumina-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.cpp111
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/MainUI.h16
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/MainUI.ui26
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp44
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.h8
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/Word.h20
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/lumina-textedit.pro5
-rw-r--r--src-qt5/desktop-utils/lumina-textedit/wordMenu.h6
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"));
+
+ }
+}
bgstack15