Compare commits

...

1 Commits

Author SHA1 Message Date
poixen
2e0944b7cc card completion 2018-05-13 14:36:18 -04:00
6 changed files with 168 additions and 52 deletions

View File

@@ -791,7 +791,7 @@ void MessagesSettingsPage::retranslateUi()
chatGroupBox->setTitle(tr("Chat settings")); chatGroupBox->setTitle(tr("Chat settings"));
highlightGroupBox->setTitle(tr("Custom alert words")); highlightGroupBox->setTitle(tr("Custom alert words"));
chatMentionCheckBox.setText(tr("Enable chat mentions")); chatMentionCheckBox.setText(tr("Enable chat mentions"));
chatMentionCompleterCheckbox.setText(tr("Enable mention completer")); chatMentionCompleterCheckbox.setText(tr("Enable mention mentionCompleter"));
messageShortcuts->setTitle(tr("In-game message macros")); messageShortcuts->setTitle(tr("In-game message macros"));
ignoreUnregUsersMainChat.setText(tr("Ignore chat room messages sent by unregistered users")); ignoreUnregUsersMainChat.setText(tr("Ignore chat room messages sent by unregistered users"));
ignoreUnregUserMessages.setText(tr("Ignore private messages sent by unregistered users")); ignoreUnregUserMessages.setText(tr("Ignore private messages sent by unregistered users"));

View File

@@ -9,16 +9,16 @@
#include <QTextCursor> #include <QTextCursor>
#include <QWidget> #include <QWidget>
LineEditCompleter::LineEditCompleter(QWidget *parent) : QLineEdit(parent), c(nullptr) LineEditCompleter::LineEditCompleter(QWidget *parent) : QLineEdit(parent)
{ {
} }
void LineEditCompleter::focusOutEvent(QFocusEvent *e) void LineEditCompleter::focusOutEvent(QFocusEvent *e)
{ {
QLineEdit::focusOutEvent(e); QLineEdit::focusOutEvent(e);
if (c->popup()->isVisible()) { if (mentionCompleter->popup()->isVisible()) {
// Remove Popup // Remove Popup
c->popup()->hide(); mentionCompleter->popup()->hide();
// Truncate the line to last space or whole string // Truncate the line to last space or whole string
QString textValue = text(); QString textValue = text();
int lastIndex = textValue.length(); int lastIndex = textValue.length();
@@ -26,7 +26,28 @@ void LineEditCompleter::focusOutEvent(QFocusEvent *e)
int leftShift = qMin(lastIndex, lastWordStartIndex); int leftShift = qMin(lastIndex, lastWordStartIndex);
setText(textValue.left(leftShift)); setText(textValue.left(leftShift));
// Insert highlighted line from popup // Insert highlighted line from popup
insert(c->completionModel()->index(c->popup()->currentIndex().row(), 0).data().toString() + " "); insert(mentionCompleter->completionModel()
->index(mentionCompleter->popup()->currentIndex().row(), 0)
.data()
.toString() +
" ");
// Set focus back to the textbox since tab was pressed
setFocus();
}
if (cardCompleter->popup()->isVisible()) {
// Remove Popup
cardCompleter->popup()->hide();
// Truncate the line to last space or whole string
QString textValue = text();
int lastIndex = textValue.length();
int lastWordStartIndex = textValue.lastIndexOf(" ") + 1;
int leftShift = qMin(lastIndex, lastWordStartIndex);
setText(textValue.left(leftShift));
// Insert highlighted line from popup
insert(
cardCompleter->completionModel()->index(cardCompleter->popup()->currentIndex().row(), 0).data().toString() +
" ");
// Set focus back to the textbox since tab was pressed // Set focus back to the textbox since tab was pressed
setFocus(); setFocus();
} }
@@ -38,10 +59,24 @@ void LineEditCompleter::keyPressEvent(QKeyEvent *event)
case Qt::Key_Return: case Qt::Key_Return:
case Qt::Key_Enter: case Qt::Key_Enter:
case Qt::Key_Escape: case Qt::Key_Escape:
if (c->popup()->isVisible()) { if (mentionCompleter->popup()->isVisible()) {
event->ignore(); event->ignore();
// Remove Popup // Remove Popup
c->popup()->hide(); mentionCompleter->popup()->hide();
// Truncate the line to last space or whole string
QString textValue = text();
int lastIndexof = qMax(0, textValue.lastIndexOf(" "));
QString finalString = textValue.left(lastIndexof);
// Add a space if there's a word
if (finalString != "")
finalString += " ";
setText(finalString);
return;
}
if (cardCompleter->popup()->isVisible()) {
event->ignore();
// Remove Popup
cardCompleter->popup()->hide();
// Truncate the line to last space or whole string // Truncate the line to last space or whole string
QString textValue = text(); QString textValue = text();
int lastIndexof = qMax(0, textValue.lastIndexOf(" ")); int lastIndexof = qMax(0, textValue.lastIndexOf(" "));
@@ -54,10 +89,10 @@ void LineEditCompleter::keyPressEvent(QKeyEvent *event)
} }
break; break;
case Qt::Key_Space: case Qt::Key_Space:
if (c->popup()->isVisible()) { if (mentionCompleter->popup()->isVisible()) {
event->ignore(); event->ignore();
// Remove Popup // Remove Popup
c->popup()->hide(); mentionCompleter->popup()->hide();
// Truncate the line to last space or whole string // Truncate the line to last space or whole string
QString textValue = text(); QString textValue = text();
int lastIndex = textValue.length(); int lastIndex = textValue.length();
@@ -65,7 +100,29 @@ void LineEditCompleter::keyPressEvent(QKeyEvent *event)
int leftShift = qMin(lastIndex, lastWordStartIndex); int leftShift = qMin(lastIndex, lastWordStartIndex);
setText(textValue.left(leftShift)); setText(textValue.left(leftShift));
// Insert highlighted line from popup // Insert highlighted line from popup
insert(c->completionModel()->index(c->popup()->currentIndex().row(), 0).data().toString() + " "); insert(mentionCompleter->completionModel()
->index(mentionCompleter->popup()->currentIndex().row(), 0)
.data()
.toString() +
" ");
return;
}
if (cardCompleter->popup()->isVisible()) {
event->ignore();
// Remove Popup
cardCompleter->popup()->hide();
// Truncate the line to last space or whole string
QString textValue = text();
int lastIndex = textValue.length();
int lastWordStartIndex = textValue.lastIndexOf(" ") + 1;
int leftShift = qMin(lastIndex, lastWordStartIndex);
setText(textValue.left(leftShift));
// Insert highlighted line from popup
insert(cardCompleter->completionModel()
->index(cardCompleter->popup()->currentIndex().row(), 0)
.data()
.toString() +
" ");
return; return;
} }
break; break;
@@ -74,30 +131,59 @@ void LineEditCompleter::keyPressEvent(QKeyEvent *event)
} }
QLineEdit::keyPressEvent(event); QLineEdit::keyPressEvent(event);
// return if the completer is null or if the most recently typed char was '@'.
// return if the mentionCompleter is null or if the most recently typed char was '@'.
// Only want the popup AFTER typing the first char of the mention. // Only want the popup AFTER typing the first char of the mention.
if (!c || text().right(1).contains("@")) { if (mentionCompleter && !text().right(1).contains("@")) {
c->popup()->hide(); processMention();
} else {
mentionCompleter->popup()->hide();
}
if (cardCompleter && !text().right(2).contains("[[")) {
processCard();
} else {
cardCompleter->popup()->hide();
}
return; return;
} }
void LineEditCompleter::processMention() const
{
// Set new completion prefix // Set new completion prefix
c->setCompletionPrefix(cursorWord(text())); mentionCompleter->setCompletionPrefix(cursorWord(text()));
if (c->completionPrefix().length() < 1) { if (mentionCompleter->completionPrefix().length() < 1) {
c->popup()->hide(); mentionCompleter->popup()->hide();
return;
}
// Select first item in the completion popup
QItemSelectionModel *sm = new QItemSelectionModel(mentionCompleter->completionModel());
mentionCompleter->popup()->setSelectionModel(sm);
sm->select(mentionCompleter->completionModel()->index(0, 0), QItemSelectionModel::ClearAndSelect);
sm->setCurrentIndex(mentionCompleter->completionModel()->index(0, 0), QItemSelectionModel::NoUpdate);
}
void LineEditCompleter::processCard() const
{
cardCompleter->setCompletionPrefix(cursorWord(text()));
if (cardCompleter->completionPrefix().length() < 2) {
cardCompleter->popup()->hide();
return; return;
} }
// Draw completion box // Draw completion box
QRect cr = cursorRect(); QRect cr = cursorRect();
cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width()); cr.setWidth(cardCompleter->popup()->sizeHintForColumn(0) +
c->complete(cr); cardCompleter->popup()->verticalScrollBar()->sizeHint().width());
cardCompleter->complete(cr);
// Select first item in the completion popup // Select first item in the completion popup
QItemSelectionModel *sm = new QItemSelectionModel(c->completionModel()); QItemSelectionModel *sm = new QItemSelectionModel(cardCompleter->completionModel());
c->popup()->setSelectionModel(sm); cardCompleter->popup()->setSelectionModel(sm);
sm->select(c->completionModel()->index(0, 0), QItemSelectionModel::ClearAndSelect); sm->select(cardCompleter->completionModel()->index(0, 0), QItemSelectionModel::ClearAndSelect);
sm->setCurrentIndex(c->completionModel()->index(0, 0), QItemSelectionModel::NoUpdate); sm->setCurrentIndex(cardCompleter->completionModel()->index(0, 0), QItemSelectionModel::NoUpdate);
} }
QString LineEditCompleter::cursorWord(const QString &line) const QString LineEditCompleter::cursorWord(const QString &line) const
@@ -113,20 +199,27 @@ void LineEditCompleter::insertCompletion(QString arg)
cursorPosition() - text().left(cursorPosition()).lastIndexOf(" ") - 1, s_arg)); cursorPosition() - text().left(cursorPosition()).lastIndexOf(" ") - 1, s_arg));
} }
void LineEditCompleter::setCompleter(QCompleter *completer) void LineEditCompleter::setMentionCompleter(QCompleter *completer)
{ {
c = completer; mentionCompleter = completer;
c->setWidget(this); mentionCompleter->setWidget(this);
connect(c, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString))); connect(mentionCompleter, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString)));
} }
void LineEditCompleter::setCompletionList(QStringList completionList) void LineEditCompleter::setCardCompleter(QCompleter *completer)
{ {
if (!c || c->popup()->isVisible()) cardCompleter = completer;
cardCompleter->setWidget(this);
connect(cardCompleter, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString)));
}
void LineEditCompleter::setMentionCompletionList(QStringList completionList)
{
if (!mentionCompleter || mentionCompleter->popup()->isVisible())
return; return;
QStringListModel *model; QStringListModel *model;
model = (QStringListModel *)(c->model()); model = (QStringListModel *)(mentionCompleter->model());
if (model == NULL) if (model == NULL)
model = new QStringListModel(); model = new QStringListModel();
model->setStringList(completionList); model->setStringList(completionList);

View File

@@ -11,7 +11,10 @@ class LineEditCompleter : public QLineEdit
Q_OBJECT Q_OBJECT
private: private:
QString cursorWord(const QString &line) const; QString cursorWord(const QString &line) const;
QCompleter *c; void processMention() const;
void processCard() const;
QCompleter *mentionCompleter;
QCompleter *cardCompleter;
private slots: private slots:
void insertCompletion(QString); void insertCompletion(QString);
@@ -21,8 +24,9 @@ protected:
public: public:
explicit LineEditCompleter(QWidget *parent = 0); explicit LineEditCompleter(QWidget *parent = 0);
void setCompleter(QCompleter *); void setMentionCompleter(QCompleter *mentionCompleter);
void setCompletionList(QStringList); void setCardCompleter(QCompleter *cardCompleter);
void setMentionCompletionList(QStringList completionList);
}; };
#endif #endif

View File

@@ -718,7 +718,7 @@ Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
QString newPlayerName = "@" + newPlayer->getName(); QString newPlayerName = "@" + newPlayer->getName();
if (sayEdit && !autocompleteUserList.contains(newPlayerName)) { if (sayEdit && !autocompleteUserList.contains(newPlayerName)) {
autocompleteUserList << newPlayerName; autocompleteUserList << newPlayerName;
sayEdit->setCompletionList(autocompleteUserList); sayEdit->setMentionCompletionList(autocompleteUserList);
} }
scene->addPlayer(newPlayer); scene->addPlayer(newPlayer);
@@ -942,8 +942,9 @@ void TabGame::eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, c
void TabGame::eventSpectatorLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext & /*context*/) void TabGame::eventSpectatorLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext & /*context*/)
{ {
QString playerName = "@" + QString::fromStdString(spectators.value(eventPlayerId).name()); QString playerName = "@" + QString::fromStdString(spectators.value(eventPlayerId).name());
if (sayEdit && autocompleteUserList.removeOne(playerName)) if (sayEdit && autocompleteUserList.removeOne(playerName)) {
sayEdit->setCompletionList(autocompleteUserList); sayEdit->setMentionCompletionList(autocompleteUserList);
}
messageLog->logLeaveSpectator(QString::fromStdString(spectators.value(eventPlayerId).name()), messageLog->logLeaveSpectator(QString::fromStdString(spectators.value(eventPlayerId).name()),
getLeaveReason(event.reason())); getLeaveReason(event.reason()));
playerListWidget->removePlayer(eventPlayerId); playerListWidget->removePlayer(eventPlayerId);
@@ -964,7 +965,7 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event,
QString playerName = "@" + QString::fromStdString(prop.user_info().name()); QString playerName = "@" + QString::fromStdString(prop.user_info().name());
if (sayEdit && !autocompleteUserList.contains(playerName)) { if (sayEdit && !autocompleteUserList.contains(playerName)) {
autocompleteUserList << playerName; autocompleteUserList << playerName;
sayEdit->setCompletionList(autocompleteUserList); sayEdit->setMentionCompletionList(autocompleteUserList);
} }
if (prop.spectator()) { if (prop.spectator()) {
if (!spectators.contains(playerId)) { if (!spectators.contains(playerId)) {
@@ -1078,7 +1079,7 @@ void TabGame::eventJoin(const Event_Join &event, int /*eventPlayerId*/, const Ga
QString playerName = QString::fromStdString(playerInfo.user_info().name()); QString playerName = QString::fromStdString(playerInfo.user_info().name());
if (sayEdit && !autocompleteUserList.contains("@" + playerName)) { if (sayEdit && !autocompleteUserList.contains("@" + playerName)) {
autocompleteUserList << "@" + playerName; autocompleteUserList << "@" + playerName;
sayEdit->setCompletionList(autocompleteUserList); sayEdit->setMentionCompletionList(autocompleteUserList);
} }
if (players.contains(playerId)) if (players.contains(playerId))
@@ -1120,8 +1121,9 @@ void TabGame::eventLeave(const Event_Leave &event, int eventPlayerId, const Game
return; return;
QString playerName = "@" + player->getName(); QString playerName = "@" + player->getName();
if (sayEdit && autocompleteUserList.removeOne(playerName)) if (sayEdit && autocompleteUserList.removeOne(playerName)) {
sayEdit->setCompletionList(autocompleteUserList); sayEdit->setMentionCompletionList(autocompleteUserList);
}
messageLog->logLeave(player, getLeaveReason(event.reason())); messageLog->logLeave(player, getLeaveReason(event.reason()));
playerListWidget->removePlayer(eventPlayerId); playerListWidget->removePlayer(eventPlayerId);

View File

@@ -1,5 +1,6 @@
#include "tab_room.h" #include "tab_room.h"
#include "abstractclient.h" #include "abstractclient.h"
#include "carddatabase.h"
#include "chatview/chatview.h" #include "chatview/chatview.h"
#include "dlg_settings.h" #include "dlg_settings.h"
#include "gameselector.h" #include "gameselector.h"
@@ -110,16 +111,26 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
} }
userList->sortItems(); userList->sortItems();
foreach (CardInfoPtr cardInfo, db->getCardList()) {
autocompleteCardList.append("[[" + cardInfo->getCorrectedName() + "]]");
}
const int gameListSize = info.game_list_size(); const int gameListSize = info.game_list_size();
for (int i = 0; i < gameListSize; ++i) for (int i = 0; i < gameListSize; ++i)
gameSelector->processGameInfo(info.game_list(i)); gameSelector->processGameInfo(info.game_list(i));
completer = new QCompleter(autocompleteUserList, sayEdit); mentionCompleter = new QCompleter(autocompleteUserList, sayEdit);
completer->setCaseSensitivity(Qt::CaseInsensitive); mentionCompleter->setCaseSensitivity(Qt::CaseInsensitive);
completer->setMaxVisibleItems(5); mentionCompleter->setMaxVisibleItems(5);
completer->setFilterMode(Qt::MatchStartsWith); mentionCompleter->setFilterMode(Qt::MatchStartsWith);
sayEdit->setMentionCompleter(mentionCompleter);
cardCompleter = new QCompleter(autocompleteCardList, sayEdit);
cardCompleter->setCaseSensitivity(Qt::CaseInsensitive);
cardCompleter->setMaxVisibleItems(5);
cardCompleter->setFilterMode(Qt::MatchStartsWith);
sayEdit->setCardCompleter(cardCompleter);
sayEdit->setCompleter(completer);
actCompleterChanged(); actCompleterChanged();
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts())); connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
refreshShortcuts(); refreshShortcuts();
@@ -186,8 +197,9 @@ void TabRoom::sendMessage()
{ {
if (sayEdit->text().isEmpty()) { if (sayEdit->text().isEmpty()) {
return; return;
} else if (completer->popup()->isVisible()) { } else if (mentionCompleter->popup()->isVisible() || cardCompleter->popup()->isVisible()) {
completer->popup()->hide(); mentionCompleter->popup()->hide();
cardCompleter->popup()->hide();
return; return;
} else { } else {
Command_RoomSay cmd; Command_RoomSay cmd;
@@ -227,7 +239,8 @@ void TabRoom::actOpenChatSettings()
void TabRoom::actCompleterChanged() void TabRoom::actCompleterChanged()
{ {
settingsCache->getChatMentionCompleter() ? completer->setCompletionRole(2) : completer->setCompletionRole(1); settingsCache->getChatMentionCompleter() ? mentionCompleter->setCompletionRole(2)
: mentionCompleter->setCompletionRole(1);
} }
void TabRoom::processRoomEvent(const RoomEvent &event) void TabRoom::processRoomEvent(const RoomEvent &event)
@@ -262,7 +275,7 @@ void TabRoom::processJoinRoomEvent(const Event_JoinRoom &event)
userList->sortItems(); userList->sortItems();
if (!autocompleteUserList.contains("@" + QString::fromStdString(event.user_info().name()))) { if (!autocompleteUserList.contains("@" + QString::fromStdString(event.user_info().name()))) {
autocompleteUserList << "@" + QString::fromStdString(event.user_info().name()); autocompleteUserList << "@" + QString::fromStdString(event.user_info().name());
sayEdit->setCompletionList(autocompleteUserList); sayEdit->setMentionCompletionList(autocompleteUserList);
} }
} }
@@ -270,7 +283,7 @@ void TabRoom::processLeaveRoomEvent(const Event_LeaveRoom &event)
{ {
userList->deleteUser(QString::fromStdString(event.name())); userList->deleteUser(QString::fromStdString(event.name()));
autocompleteUserList.removeOne("@" + QString::fromStdString(event.name())); autocompleteUserList.removeOne("@" + QString::fromStdString(event.name()));
sayEdit->setCompletionList(autocompleteUserList); sayEdit->setMentionCompletionList(autocompleteUserList);
} }
void TabRoom::processRoomSayEvent(const Event_RoomSay &event) void TabRoom::processRoomSayEvent(const Event_RoomSay &event)
@@ -294,11 +307,12 @@ void TabRoom::processRoomSayEvent(const Event_RoomSay &event)
if (event.message_type() == Event_RoomSay::ChatHistory && !settingsCache->getRoomHistory()) if (event.message_type() == Event_RoomSay::ChatHistory && !settingsCache->getRoomHistory())
return; return;
if (event.message_type() == Event_RoomSay::ChatHistory) if (event.message_type() == Event_RoomSay::ChatHistory) {
message = message =
"[" + "[" +
QString(QDateTime::fromMSecsSinceEpoch(event.time_of()).toLocalTime().toString("d MMM yyyy HH:mm:ss")) + QString(QDateTime::fromMSecsSinceEpoch(event.time_of()).toLocalTime().toString("d MMM yyyy HH:mm:ss")) +
"] " + message; "] " + message;
}
chatView->appendMessage(message, event.message_type(), senderName, userLevel, userPrivLevel, true); chatView->appendMessage(message, event.message_type(), senderName, userLevel, userPrivLevel, true);
emit userEvent(false); emit userEvent(false);

View File

@@ -61,7 +61,10 @@ private:
QString sanitizeHtml(QString dirty) const; QString sanitizeHtml(QString dirty) const;
QStringList autocompleteUserList; QStringList autocompleteUserList;
QCompleter *completer; QStringList autocompleteCardList;
QCompleter *mentionCompleter;
QCompleter *cardCompleter;
signals: signals:
void roomClosing(TabRoom *tab); void roomClosing(TabRoom *tab);
void openMessageDialog(const QString &userName, bool focus); void openMessageDialog(const QString &userName, bool focus);