Warning, file /sdk/cervisia/logmessageedit.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2004 Jason Kivlighn <mizunoami44@users.sourceforge.net> 0003 * Copyright (c) 2005-2007 Christian Loose <christian.loose@kdemail.net> 0004 * 0005 * based on work by Jason Kivlighn (krecipes/src/widgets/kretextedit.cpp) 0006 * 0007 * This program is free software; you can redistribute it and/or modify 0008 * it under the terms of the GNU General Public License as published by 0009 * the Free Software Foundation; either version 2 of the License, or 0010 * (at your option) any later version. 0011 * 0012 * This program is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public License 0018 * along with this program; if not, write to the Free Software 0019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "logmessageedit.h" 0023 using Cervisia::LogMessageEdit; 0024 0025 #include <QKeyEvent> 0026 0027 #include <KStandardShortcut> 0028 0029 LogMessageEdit::LogMessageEdit(QWidget *parent) 0030 : KTextEdit(parent) 0031 , KCompletionBase() 0032 , m_completing(false) 0033 , m_completionStartPos(0) 0034 , m_checkSpellingEnabledBeforeCompletion(false) 0035 { 0036 setAcceptRichText(false); 0037 0038 // create the completion object 0039 completionObject(); 0040 } 0041 0042 void LogMessageEdit::mousePressEvent(QMouseEvent *event) 0043 { 0044 // a mouse click stops the completion process 0045 QTextEdit::mousePressEvent(event); 0046 stopCompletion(); 0047 } 0048 0049 void LogMessageEdit::setCompletedText(const QString &match) 0050 { 0051 QTextCursor cursor = this->textCursor(); 0052 0053 int pos = cursor.position(); 0054 QString text = toPlainText(); 0055 0056 // retrieve the part of the match that's missing 0057 int length = pos - m_completionStartPos; 0058 QString word = match.right(match.length() - length); 0059 0060 // insert the match 0061 cursor.insertText(word); 0062 0063 // move cursor back and select the match 0064 cursor.setPosition(pos, QTextCursor::KeepAnchor); 0065 setTextCursor(cursor); 0066 0067 m_completing = true; 0068 0069 m_checkSpellingEnabledBeforeCompletion = checkSpellingEnabled(); 0070 // disable spellchecker during completion process. Otherwise we lose the 0071 // text selection. 0072 setCheckSpellingEnabled(false); 0073 } 0074 0075 void LogMessageEdit::setCompletedItems(const QStringList &, bool) 0076 { 0077 } 0078 0079 void LogMessageEdit::keyPressEvent(QKeyEvent *event) 0080 { 0081 // handle normal key 0082 Qt::KeyboardModifiers modifiers = event->modifiers(); 0083 bool noModifier = (modifiers == Qt::NoModifier || modifiers == Qt::ShiftModifier || modifiers == Qt::KeypadModifier); 0084 0085 if (noModifier) { 0086 QString keyCode = event->text(); 0087 if (!keyCode.isEmpty() && keyCode.unicode()->isPrint()) { 0088 KTextEdit::keyPressEvent(event); 0089 tryCompletion(); 0090 event->accept(); 0091 return; 0092 } 0093 } 0094 0095 // get shortcut for text completion key 0096 QList<QKeySequence> shortcut = keyBinding(TextCompletion); 0097 if (shortcut.isEmpty()) 0098 shortcut = KStandardShortcut::shortcut(KStandardShortcut::TextCompletion); 0099 0100 int key = event->key() | event->modifiers(); 0101 0102 // handle text completion key 0103 if (m_completing && shortcut.contains(key)) { 0104 // accept the suggested completion 0105 QTextCursor cursor = this->textCursor(); 0106 cursor.setPosition(cursor.selectionEnd()); 0107 setTextCursor(cursor); 0108 0109 stopCompletion(); 0110 0111 return; 0112 } 0113 0114 // handle previous match key 0115 shortcut = keyBinding(PrevCompletionMatch); 0116 if (shortcut.isEmpty()) 0117 shortcut = KStandardShortcut::shortcut(KStandardShortcut::PrevCompletion); 0118 0119 if (shortcut.contains(key)) { 0120 rotateMatches(PrevCompletionMatch); 0121 return; 0122 } 0123 0124 // handle next match key 0125 shortcut = keyBinding(NextCompletionMatch); 0126 if (shortcut.isEmpty()) 0127 shortcut = KStandardShortcut::shortcut(KStandardShortcut::NextCompletion); 0128 0129 if (shortcut.contains(key)) { 0130 rotateMatches(NextCompletionMatch); 0131 return; 0132 } 0133 0134 // any other key (except modifiers) will end the text completion 0135 if (event->key() != Qt::Key_Shift && event->key() != Qt::Key_Control && event->key() != Qt::Key_Alt && event->key() != Qt::Key_Meta) { 0136 stopCompletion(); 0137 } 0138 0139 KTextEdit::keyPressEvent(event); 0140 } 0141 0142 void LogMessageEdit::stopCompletion() 0143 { 0144 if (m_completing) { 0145 m_completing = false; 0146 setCheckSpellingEnabled(m_checkSpellingEnabledBeforeCompletion); 0147 } 0148 } 0149 0150 void LogMessageEdit::tryCompletion() 0151 { 0152 int pos = textCursor().position(); 0153 QString text = toPlainText(); 0154 0155 // space or tab starts completion 0156 if (text.at(pos - 1).isSpace()) { 0157 // if we already did complete this word and the user types another space, 0158 // don't complete again, since the user can otherwise not enter the word 0159 // without the completion. In this case, also remove the previous completion 0160 // which is still selected 0161 if (m_completing) { 0162 textCursor().removeSelectedText(); 0163 stopCompletion(); 0164 return; 0165 } 0166 0167 if (!m_completing) 0168 m_completionStartPos = text.lastIndexOf(' ', pos - 2) + 1; 0169 0170 // retrieve current word 0171 int length = pos - m_completionStartPos - 1; 0172 QString word = text.mid(m_completionStartPos, length); 0173 0174 // try to complete the word 0175 QString match = compObj()->makeCompletion(word); 0176 if (!match.isEmpty() && match != word) { 0177 // if the matching text is already existing at this cursor position, 0178 // don't insert it again 0179 if (text.mid(pos).startsWith(match.mid(word.length()))) { 0180 stopCompletion(); 0181 return; 0182 } 0183 0184 QTextCursor cursor = this->textCursor(); 0185 cursor.deletePreviousChar(); // delete the just inserted space 0186 setTextCursor(cursor); 0187 0188 setCompletedText(match); 0189 } else { 0190 stopCompletion(); 0191 } 0192 } else { 0193 stopCompletion(); 0194 } 0195 } 0196 0197 void LogMessageEdit::rotateMatches(KeyBindingType type) 0198 { 0199 KCompletion *completionObj = compObj(); 0200 if (completionObj && m_completing && (type == PrevCompletionMatch || type == NextCompletionMatch)) { 0201 QString match = (type == PrevCompletionMatch) ? completionObj->previousMatch() : completionObj->nextMatch(); 0202 0203 int pos = textCursor().position(); 0204 QString text = toPlainText(); 0205 0206 QString word = text.mid(m_completionStartPos, pos - m_completionStartPos); 0207 0208 if (match.isEmpty() || match == word) 0209 return; 0210 0211 setCompletedText(match); 0212 } 0213 }