File indexing completed on 2024-05-19 12:37:36
0001 /* 0002 This file is part of Choqok, the KDE micro-blogging client 0003 0004 SPDX-FileCopyrightText: 2010-2012 Mehrdad Momeny <mehrdad.momeny@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "twitterapitextedit.h" 0010 0011 #include <QAbstractItemView> 0012 #include <QKeyEvent> 0013 #include <QScrollBar> 0014 0015 #include <KIO/Job> 0016 0017 #include "urlutils.h" 0018 0019 #include "twitterapiaccount.h" 0020 #include "twitterapidebug.h" 0021 0022 class TwitterApiTextEdit::Private 0023 { 0024 public: 0025 Private(Choqok::Account *theAccount) 0026 : acc(theAccount), c(nullptr) 0027 {} 0028 Choqok::Account *acc; 0029 QCompleter *c; 0030 }; 0031 0032 TwitterApiTextEdit::TwitterApiTextEdit(Choqok::Account *theAccount, QWidget *parent) 0033 : TextEdit(theAccount->postCharLimit(), parent), d(new Private(theAccount)) 0034 { 0035 qCDebug(CHOQOK); 0036 setTabChangesFocus(false); 0037 } 0038 0039 TwitterApiTextEdit::~TwitterApiTextEdit() 0040 { 0041 delete d; 0042 } 0043 0044 void TwitterApiTextEdit::setCompleter(QCompleter *completer) 0045 { 0046 if (d->c) { 0047 QObject::disconnect(d->c, nullptr, this, nullptr); 0048 } 0049 0050 d->c = completer; 0051 0052 if (!d->c) { 0053 return; 0054 } 0055 0056 d->c->setWidget(this); 0057 d->c->setCompletionMode(QCompleter::PopupCompletion); 0058 d->c->setCaseSensitivity(Qt::CaseInsensitive); 0059 connect(d->c, (void (QCompleter::*)(const QString&))&QCompleter::activated, 0060 this, &TwitterApiTextEdit::insertCompletion); 0061 } 0062 0063 QCompleter *TwitterApiTextEdit::completer() const 0064 { 0065 return d->c; 0066 } 0067 0068 void TwitterApiTextEdit::insertCompletion(const QString &completion) 0069 { 0070 if (d->c->widget() != this) { 0071 return; 0072 } 0073 QString textToInsert = completion + QLatin1Char(' '); 0074 QTextCursor tc = textCursor(); 0075 tc.movePosition(QTextCursor::EndOfWord); 0076 tc.select(QTextCursor::WordUnderCursor); 0077 bool startWithAt = toPlainText()[tc.selectionStart() - 1] != QLatin1Char('@'); 0078 if (startWithAt) { 0079 textToInsert.prepend(QLatin1Char('@')); 0080 } 0081 tc.insertText(textToInsert); 0082 setTextCursor(tc); 0083 } 0084 0085 // QString TwitterApiTextEdit::textUnderCursor() const 0086 // { 0087 // QTextCursor tc = textCursor(); 0088 // tc.select(QTextCursor::WordUnderCursor); 0089 // return tc.selectedText(); 0090 // } 0091 0092 void TwitterApiTextEdit::focusInEvent(QFocusEvent *e) 0093 { 0094 if (d->c) { 0095 d->c->setWidget(this); 0096 } 0097 KTextEdit::focusInEvent(e); 0098 } 0099 0100 void TwitterApiTextEdit::keyPressEvent(QKeyEvent *e) 0101 { 0102 if (d->c && d->c->popup()->isVisible()) { 0103 // The following keys are forwarded by the completer to the widget 0104 switch (e->key()) { 0105 case Qt::Key_Enter: 0106 case Qt::Key_Return: 0107 case Qt::Key_Escape: 0108 // case Qt::Key_Backtab: 0109 e->ignore(); 0110 return; // let the completer do default behavior 0111 default: 0112 // Choqok::UI::TextEdit::keyPressEvent(e); 0113 break; 0114 } 0115 } else if (e->text().isEmpty()) { 0116 Choqok::UI::TextEdit::keyPressEvent(e); 0117 return; 0118 } 0119 if (e->key() == Qt::Key_Tab) { 0120 e->ignore(); 0121 return; 0122 } 0123 // bool isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_Space); // CTRL+E 0124 // if (!d->c )// || !isShortcut) // don't process the shortcut when we have a completer 0125 Choqok::UI::TextEdit::keyPressEvent(e); 0126 0127 const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier | 0128 Qt::MetaModifier); 0129 if (!d->c || (ctrlOrShift && e->text().isEmpty())) { 0130 return; 0131 } 0132 0133 static QString eow(QLatin1String("~!@#$%^&*()+{}|:\"<>?,./;'[]\\-= ")); // end of word 0134 // bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift; 0135 //Implemented internally to get the char before selection :D 0136 QTextCursor tc = textCursor(); 0137 tc.select(QTextCursor::WordUnderCursor); 0138 QString completionPrefix = tc.selectedText(); 0139 QChar charBeforeSelection; 0140 if (completionPrefix.startsWith(QLatin1Char('@'))) { 0141 charBeforeSelection = completionPrefix.at(0); 0142 completionPrefix.remove(0, 1); 0143 } else { 0144 if (!toPlainText().isEmpty() && tc.selectionStart() > 0) { 0145 charBeforeSelection = toPlainText()[tc.selectionStart() - 1]; 0146 } 0147 } 0148 0149 if (!e->text().isEmpty() && (eow.contains(e->text().right(1)) || completionPrefix.length() < 1 || 0150 charBeforeSelection != QLatin1Char('@'))) { 0151 d->c->popup()->hide(); 0152 return; 0153 } else if ((e->key() != Qt::Key_Enter) && (e->key() != Qt::Key_Return)) { 0154 if (textCursor().selectedText().length() && 0155 textCursor().selectedText() != completionPrefix) { 0156 return; 0157 } 0158 0159 if (completionPrefix != d->c->completionPrefix()) { 0160 d->c->setCompletionPrefix(completionPrefix); 0161 d->c->popup()->setCurrentIndex(d->c->completionModel()->index(0, 0)); 0162 } 0163 QRect cr = cursorRect(); 0164 cr.setWidth(d->c->popup()->sizeHintForColumn(0) 0165 + d->c->popup()->verticalScrollBar()->sizeHint().width()); 0166 d->c->complete(cr); // popup it up! 0167 } 0168 } 0169 0170 #include "moc_twitterapitextedit.cpp"