added completer to MimeTextEdit and ChatWidget (Patch from Phenom)

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6475 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2013-07-04 19:36:12 +00:00
parent 33f4e5b779
commit 90e7a3cd54
4 changed files with 218 additions and 2 deletions

View File

@ -31,6 +31,7 @@
#include <QTextCodec>
#include <QTimer>
#include <QTextDocumentFragment>
#include <QStringListModel>
#include "ChatWidget.h"
#include "ui_ChatWidget.h"
@ -127,6 +128,16 @@ ChatWidget::ChatWidget(QWidget *parent) :
#endif
resetStatusBar();
completer = new QCompleter(this);
completer->setModel(modelFromPeers());
completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setWrapAround(false);
ui->chatTextEdit->setCompleter(completer);
ui->chatTextEdit->setCompleterKeyModifiers(Qt::ControlModifier);
ui->chatTextEdit->setCompleterKey(Qt::Key_Space);
}
ChatWidget::~ChatWidget()
@ -245,6 +256,13 @@ bool ChatWidget::eventFilter(QObject *obj, QEvent *event)
completionWord.clear();
}
}
if ((keyEvent->modifiers() & ui->chatTextEdit->getCompleterKeyModifiers()) && keyEvent->key() == ui->chatTextEdit->getCompleterKey()) {
completer->setModel(modelFromPeers());
}
if (keyEvent->text()=="@") {
ui->chatTextEdit->forceCompleterShowNextKeyEvent("@");
completer->setModel(modelFromPeers());
}
if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
// Enter pressed
if (Settings->getChatSendMessageWithCtrlReturn()) {
@ -397,6 +415,45 @@ void ChatWidget::completeNickname(bool reverse)
cursor.endEditBlock();
}
QAbstractItemModel *ChatWidget::modelFromPeers()
{
// Find lobby we belong to
const ChatLobbyInfo *lobby = NULL;
std::list<ChatLobbyInfo> lobbies;
rsMsgs->getChatLobbyList(lobbies);
std::list<ChatLobbyInfo>::const_iterator lobbyIt;
for (lobbyIt = lobbies.begin(); lobbyIt != lobbies.end(); ++lobbyIt) {
std::string vpid;
if (rsMsgs->getVirtualPeerId(lobbyIt->lobby_id, vpid)) {
if (vpid == peerId) {
lobby = &*lobbyIt;
break;
}
}
}
if (!lobby)
return new QStringListModel(completer);
#ifndef QT_NO_CURSOR
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
#endif
// Get participants list
QStringList participants;
for ( std::map<std::string,time_t>::const_iterator it = lobby->nick_names.begin();
it != lobby->nick_names.end();
it++) {
participants.push_front(QString::fromUtf8(it->first.c_str()));
}
#ifndef QT_NO_CURSOR
QApplication::restoreOverrideCursor();
#endif
return new QStringListModel(participants, completer);
}
void ChatWidget::addToolsAction(QAction *action)
{
ui->pushtoolsButton->menu()->addAction(action);

View File

@ -24,7 +24,7 @@
#define CHATWIDGET_H
#include <QWidget>
#include <QCompleter>
#include "gui/common/HashBox.h"
#include "ChatStyle.h"
#include "gui/style/RSStyle.h"
@ -137,6 +137,7 @@ private:
void processSettings(bool load);
void completeNickname(bool reverse);
QAbstractItemModel *modelFromPeers();
std::string peerId;
QString title;
@ -164,6 +165,8 @@ private:
TransferRequestFlags mDefaultExtraFileFlags ; // flags for extra files shared in this chat. Will be 0 by default, but might be ANONYMOUS for chat lobbies.
QCompleter *completer;
Ui::ChatWidget *ui;
};

View File

@ -23,10 +23,16 @@
#include <QTextDocumentFragment>
#include "MimeTextEdit.h"
#include "util/HandleRichText.h"
#include <QCompleter>
#include <QAbstractItemView>
#include <QKeyEvent>
#include <QScrollBar>
MimeTextEdit::MimeTextEdit(QWidget *parent)
: QTextEdit(parent)
: QTextEdit(parent), mCompleter(0)
{
mCompleterKeyModifiers=Qt::ControlModifier;
mCompleterKey=Qt::Key_Space;
}
bool MimeTextEdit::canInsertFromMimeData(const QMimeData* source) const
@ -65,3 +71,128 @@ void MimeTextEdit::insertFromMimeData(const QMimeData* source)
return QTextEdit::insertFromMimeData(source);
}
void MimeTextEdit::setCompleter(QCompleter *completer)
{
if (mCompleter)
QObject::disconnect(mCompleter, 0, this, 0);
mCompleter = completer;
if (!mCompleter)
return;
mCompleter->setWidget(this);
mCompleter->setCompletionMode(QCompleter::PopupCompletion);
mCompleter->setCaseSensitivity(Qt::CaseInsensitive);
QObject::connect(mCompleter, SIGNAL(activated(QString)),
this, SLOT(insertCompletion(QString)));
}
QCompleter *MimeTextEdit::completer() const
{
return mCompleter;
}
void MimeTextEdit::insertCompletion(const QString& completion)
{
if (mCompleter->widget() != this)
return;
QTextCursor tc = textCursor();
if (mCompleter->completionPrefix().length()>0) {
tc.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
}
tc.removeSelectedText();
tc.insertText(mCompleterStartString+completion);
mCompleterStartString="";
setTextCursor(tc);
}
QString MimeTextEdit::textUnderCursor() const
{
QTextCursor tc = textCursor();
tc.select(QTextCursor::WordUnderCursor);
return tc.selectedText();
}
void MimeTextEdit::focusInEvent(QFocusEvent *e)
{
if (mCompleter)
mCompleter->setWidget(this);
QTextEdit::focusInEvent(e);
}
void MimeTextEdit::keyPressEvent(QKeyEvent *e)
{
if (mCompleter && mCompleter->popup()->isVisible()) {
// The following keys are forwarded by the completer to the widget
switch (e->key()) {
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Escape:
case Qt::Key_Tab:
case Qt::Key_Backtab:
mCompleter->popup()->hide();
mForceCompleterShowNextKeyEvent=false;
e->ignore();
return; // let the completer do default behavior
default:
break;
}
}
bool isShortcut = ((e->modifiers() & mCompleterKeyModifiers) && e->key() == mCompleterKey);
if (isShortcut && !mForceCompleterShowNextKeyEvent) {
mCompleterStartString="";
}
isShortcut |= mForceCompleterShowNextKeyEvent;
if (!mCompleter || !isShortcut) // do not process the shortcut when we have a completer
QTextEdit::keyPressEvent(e);
if (!isShortcut && (mCompleter && !mCompleter->popup()->isVisible())) {
return;
}
if (!mForceCompleterShowNextKeyEvent) {
static QString eow(" ~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word
if (!isShortcut && ( e->text().isEmpty() || eow.contains(e->text().right(1)))){
mCompleter->popup()->hide();
return;
}
}
QString completionPrefix = textUnderCursor();
if (completionPrefix != mCompleter->completionPrefix()) {
mCompleter->setCompletionPrefix(completionPrefix);
mCompleter->popup()->setCurrentIndex(mCompleter->completionModel()->index(0, 0));
}
QRect cr = cursorRect();
cr.setWidth(mCompleter->popup()->sizeHintForColumn(0)
+ mCompleter->popup()->verticalScrollBar()->sizeHint().width());
mCompleter->complete(cr); // popup it up!
mForceCompleterShowNextKeyEvent=false;
}
void MimeTextEdit::setCompleterKeyModifiers(Qt::KeyboardModifier modifiers)
{
mCompleterKeyModifiers=modifiers;
}
Qt::KeyboardModifier MimeTextEdit::getCompleterKeyModifiers() const
{
return mCompleterKeyModifiers;
}
void MimeTextEdit::setCompleterKey(Qt::Key key)
{
mCompleterKey=key;
}
Qt::Key MimeTextEdit::getCompleterKey() const
{
return mCompleterKey;
}
void MimeTextEdit::forceCompleterShowNextKeyEvent(QString startString="")
{
mForceCompleterShowNextKeyEvent=true;
mCompleterStartString=startString;
}

View File

@ -23,6 +23,7 @@
#define MIMETEXTEDIT_H
#include <QTextEdit>
#include <QCompleter>
class MimeTextEdit : public QTextEdit
{
@ -31,9 +32,33 @@ class MimeTextEdit : public QTextEdit
public:
MimeTextEdit(QWidget *parent = 0);
//Form here: http://qt-project.org/doc/qt-4.8/tools-customcompleter.html
void setCompleter(QCompleter *completer);
QCompleter *completer() const;
void setCompleterKeyModifiers(Qt::KeyboardModifier modifiers);
Qt::KeyboardModifier getCompleterKeyModifiers() const;
void setCompleterKey(Qt::Key key);
Qt::Key getCompleterKey() const;
void forceCompleterShowNextKeyEvent(QString startString);
protected:
virtual bool canInsertFromMimeData(const QMimeData* source) const;
virtual void insertFromMimeData(const QMimeData* source);
void keyPressEvent(QKeyEvent *e);
void focusInEvent(QFocusEvent *e);
private slots:
void insertCompletion(const QString &completion);
private:
QString textUnderCursor() const;
private:
QCompleter *mCompleter;
Qt::KeyboardModifier mCompleterKeyModifiers;
Qt::Key mCompleterKey;
bool mForceCompleterShowNextKeyEvent;
QString mCompleterStartString;
};