Commit 4cb53cca authored by marco's avatar marco
Browse files

Merge branch 'master' into Customizable-shortcuts

parents beaa4e93 5634b564
<!-- START doctoc generated TOC please keep comment here to allow auto update --> <p align='center'><img src=https://cloud.githubusercontent.com/assets/9874850/7516775/b00b8e36-f4d1-11e4-8da4-3df294d01f86.png></p>
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Cockatrice](#cockatrice) ---
- [Get Involved [![Gitter chat](https://badges.gitter.im/Cockatrice/Cockatrice.png)](https://gitter.im/Cockatrice/Cockatrice)](#get-involved-)
- [Community Resources](#community-resources)
- [Translation Status [![Cockatrice on Transiflex](https://ds0k0en9abmn1.cloudfront.net/static/charts/images/tx-logo-micro.646b0065fce6.png)](https://www.transifex.com/projects/p/cockatrice/)](#translation-status-)
- [Building [![Build Status](https://travis-ci.org/Cockatrice/Cockatrice.svg?branch=master)](https://travis-ci.org/Cockatrice/Cockatrice)](#building-)
- [Building servatrice Docker container](#building-servatrice-docker-container)
- [Running](#running)
- [License](#license)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> **Table of Contents** &nbsp;&nbsp; [Cockatrice](#cockatrice) | [Get Involved] (#get-involved-) | [Community](#community-resources) | [Translation](#translation-status-) | [Building](#building-) | [Running](#running) | [License](#license)
---
# Cockatrice # Cockatrice
Cockatrice is an open-source multiplatform software for playing card games, Cockatrice is an open-source multiplatform software for playing card games,
such as Magic: The Gathering, over a network. It is fully client-server based such as Magic: The Gathering, over a network. It is fully client-server based
to prevent any kind of cheating, though it supports single-player games without to prevent any kind of cheating, though it supports single-player games without
a network interface as well. Both client and server are written in Qt, supporting both Qt4 and Qt5. a network interface as well. Both client and server are written in Qt, supporting both Qt4 and Qt5.<br>
# Get Involved [![Gitter chat](https://badges.gitter.im/Cockatrice/Cockatrice.png)](https://gitter.im/Cockatrice/Cockatrice) # Get Involved [![Gitter chat](https://badges.gitter.im/Cockatrice/Cockatrice.png)](https://gitter.im/Cockatrice/Cockatrice)
Chat with the Cockatrice developers on Gitter. Come here to talk about the application, features, or just to hang out. For support regarding specific servers, please contact that server's admin or forum for support rather than asking here. Chat with the Cockatrice developers on Gitter. Come here to talk about the application, features, or just to hang out. For support regarding specific servers, please contact that server's admin or forum for support rather than asking here.<br>
# Community Resources # Community Resources
- [reddit r/Cockatrice](http://reddit.com/r/cockatrice)
- [Woogerworks Server & Forums](http://www.woogerworks.com)
- [Cockatrice Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki) - [Cockatrice Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki)
- [reddit r/Cockatrice](http://reddit.com/r/cockatrice)
- [Woogerworks](http://www.woogerworks.com) / [Chickatrice] (http://www.chickatrice.net/) / [Poixen](http://www.poixen.com/) (incomplete Serverlist)<br>
# Translation Status [![Cockatrice on Transiflex](https://ds0k0en9abmn1.cloudfront.net/static/charts/images/tx-logo-micro.646b0065fce6.png)](https://www.transifex.com/projects/p/cockatrice/) # Translation Status [![Cockatrice on Transiflex](https://ds0k0en9abmn1.cloudfront.net/static/charts/images/tx-logo-micro.646b0065fce6.png)](https://www.transifex.com/projects/p/cockatrice/)
...@@ -38,26 +34,25 @@ Language statistics for `Cockatrice` *(on the left)* and `Oracle` *(on the right ...@@ -38,26 +34,25 @@ Language statistics for `Cockatrice` *(on the left)* and `Oracle` *(on the right
[![Cockatrice translations](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[![Oracle translations](https://www.transifex.com/projects/p/cockatrice/resource/oracle/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/resource/oracle/) [![Cockatrice translations](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[![Oracle translations](https://www.transifex.com/projects/p/cockatrice/resource/oracle/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/resource/oracle/)
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information! Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information!<br>
# Building [![Build Status](https://travis-ci.org/Cockatrice/Cockatrice.svg?branch=master)](https://travis-ci.org/Cockatrice/Cockatrice) # Building [![Build Status](https://travis-ci.org/Cockatrice/Cockatrice.svg?branch=master)](https://travis-ci.org/Cockatrice/Cockatrice)
**Detailed compiling instructions are on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)** **Detailed compiling instructions are on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
Dependencies: Dependencies:
- [Qt](http://qt-project.org/) - [Qt](http://qt-project.org/)
- [protobuf](http://code.google.com/p/protobuf/) - [protobuf](http://code.google.com/p/protobuf/)
- [CMake](http://www.cmake.org/) - [CMake](http://www.cmake.org/)
Oracle can optionally use zlib to load zipped files: Oracle can optionally use zlib to load zipped files:
- [zlib](http://www.zlib.net/) - [zlib](http://www.zlib.net/)
The server requires an additional dependency when compiled under Qt4: The server requires an additional dependency when compiled under Qt4:
- [libgcrypt](http://www.gnu.org/software/libgcrypt/) - [libgcrypt](http://www.gnu.org/software/libgcrypt/)
To compile: To compile:
mkdir build mkdir build
...@@ -75,15 +70,18 @@ The following flags can be passed to `cmake`: ...@@ -75,15 +70,18 @@ The following flags can be passed to `cmake`:
- `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings. - `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings.
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files. - `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files.
# Building servatrice Docker container #### Building servatrice Docker container
`docker build -t servatrice .` `docker build -t servatrice .`<br>
# Running # Running
`oracle` fetches card data `oracle` fetches card data
`cockatrice` is the game client `cockatrice` is the game client
`servatrice` is the server `servatrice` is the server<br>
# License # License
Cockatrice is free software, licensed under the GPLv2; see COPYING for details. Cockatrice is free software, licensed under the GPLv2; see COPYING for details.<br>
#include <QSettings> #include <QSettings>
#include <QLabel> #include <QLabel>
#include <QCheckBox> #include <QCheckBox>
#include <QComboBox>
#include <QRadioButton>
#include <QGridLayout> #include <QGridLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QDebug> #include <QDebug>
#include <QEvent>
#include <QKeyEvent>
#include <iostream> #include <iostream>
#include "dlg_connect.h" #include "dlg_connect.h"
...@@ -14,8 +18,24 @@ DlgConnect::DlgConnect(QWidget *parent) ...@@ -14,8 +18,24 @@ DlgConnect::DlgConnect(QWidget *parent)
QSettings settings; QSettings settings;
settings.beginGroup("server"); settings.beginGroup("server");
previousHostButton = new QRadioButton(tr("Previous Host"), this);
previousHosts = new QComboBox(this);
previousHosts->installEventFilter(new DeleteHighlightedItemWhenShiftDelPressedEventFilter);
QStringList previousHostList = settings.value("previoushosts").toStringList();
if (previousHostList.isEmpty()) {
previousHostList << "cockatrice.woogerworks.com";
previousHostList << "vps.poixen.com";
previousHostList << "chickatrice.net";
}
previousHosts->addItems(previousHostList);
previousHosts->setCurrentIndex(settings.value("previoushostindex").toInt());
newHostButton = new QRadioButton(tr("New Host"), this);
hostLabel = new QLabel(tr("&Host:")); hostLabel = new QLabel(tr("&Host:"));
hostEdit = new QLineEdit(settings.value("hostname", "cockatrice.woogerworks.com").toString()); hostEdit = new QLineEdit();
hostEdit->setPlaceholderText(tr("Enter host name"));
hostLabel->setBuddy(hostEdit); hostLabel->setBuddy(hostEdit);
portLabel = new QLabel(tr("&Port:")); portLabel = new QLabel(tr("&Port:"));
...@@ -48,16 +68,19 @@ DlgConnect::DlgConnect(QWidget *parent) ...@@ -48,16 +68,19 @@ DlgConnect::DlgConnect(QWidget *parent)
connect(savePasswordCheckBox, SIGNAL(stateChanged(int)), this, SLOT(passwordSaved(int))); connect(savePasswordCheckBox, SIGNAL(stateChanged(int)), this, SLOT(passwordSaved(int)));
QGridLayout *grid = new QGridLayout; QGridLayout *grid = new QGridLayout;
grid->addWidget(hostLabel, 0, 0); grid->addWidget(previousHostButton, 0, 1);
grid->addWidget(hostEdit, 0, 1); grid->addWidget(previousHosts, 1, 1);
grid->addWidget(portLabel, 1, 0); grid->addWidget(newHostButton, 2, 1);
grid->addWidget(portEdit, 1, 1); grid->addWidget(hostLabel, 3, 0);
grid->addWidget(playernameLabel, 2, 0); grid->addWidget(hostEdit, 3, 1);
grid->addWidget(playernameEdit, 2, 1); grid->addWidget(portLabel, 4, 0);
grid->addWidget(passwordLabel, 3, 0); grid->addWidget(portEdit, 4, 1);
grid->addWidget(passwordEdit, 3, 1); grid->addWidget(playernameLabel, 5, 0);
grid->addWidget(savePasswordCheckBox, 4, 0, 1, 2); grid->addWidget(playernameEdit, 5, 1);
grid->addWidget(autoConnectCheckBox, 5, 0, 1, 2); grid->addWidget(passwordLabel, 6, 0);
grid->addWidget(passwordEdit, 6, 1);
grid->addWidget(savePasswordCheckBox, 7, 0, 1, 2);
grid->addWidget(autoConnectCheckBox, 8, 0, 1, 2);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
...@@ -71,8 +94,32 @@ DlgConnect::DlgConnect(QWidget *parent) ...@@ -71,8 +94,32 @@ DlgConnect::DlgConnect(QWidget *parent)
setWindowTitle(tr("Connect to server")); setWindowTitle(tr("Connect to server"));
setFixedHeight(sizeHint().height()); setFixedHeight(sizeHint().height());
setMinimumWidth(300); setMinimumWidth(300);
connect(previousHostButton, SIGNAL(toggled(bool)), this, SLOT(previousHostSelected(bool)));
connect(newHostButton, SIGNAL(toggled(bool)), this, SLOT(newHostSelected(bool)));
if (settings.value("previoushostlogin", 1).toInt())
previousHostButton->setChecked(true);
else
newHostButton->setChecked(true);
}
void DlgConnect::previousHostSelected(bool state) {
if (state) {
hostEdit->setDisabled(true);
previousHosts->setDisabled(false);
}
}
void DlgConnect::newHostSelected(bool state) {
if (state) {
hostEdit->setDisabled(false);
previousHosts->setDisabled(true);
}
} }
void DlgConnect::passwordSaved(int state) void DlgConnect::passwordSaved(int state)
{ {
Q_UNUSED(state); Q_UNUSED(state);
...@@ -88,17 +135,34 @@ void DlgConnect::actOk() ...@@ -88,17 +135,34 @@ void DlgConnect::actOk()
{ {
QSettings settings; QSettings settings;
settings.beginGroup("server"); settings.beginGroup("server");
settings.setValue("hostname", hostEdit->text());
settings.setValue("port", portEdit->text()); settings.setValue("port", portEdit->text());
settings.setValue("playername", playernameEdit->text()); settings.setValue("playername", playernameEdit->text());
settings.setValue("password", savePasswordCheckBox->isChecked() ? passwordEdit->text() : QString()); settings.setValue("password", savePasswordCheckBox->isChecked() ? passwordEdit->text() : QString());
settings.setValue("save_password", savePasswordCheckBox->isChecked() ? 1 : 0); settings.setValue("save_password", savePasswordCheckBox->isChecked() ? 1 : 0);
settings.setValue("auto_connect", autoConnectCheckBox->isChecked() ? 1 : 0); settings.setValue("auto_connect", autoConnectCheckBox->isChecked() ? 1 : 0);
settings.setValue("previoushostlogin", previousHostButton->isChecked() ? 1 : 0);
QStringList hostList;
if (newHostButton->isChecked())
if (!hostEdit->text().trimmed().isEmpty())
hostList << hostEdit->text();
for (int i = 0; i < previousHosts->count(); i++)
if(!previousHosts->itemText(i).trimmed().isEmpty())
hostList << previousHosts->itemText(i);
settings.setValue("previoushosts", hostList);
settings.setValue("previoushostindex", previousHosts->currentIndex());
settings.endGroup(); settings.endGroup();
accept(); accept();
} }
QString DlgConnect::getHost() const {
return previousHostButton->isChecked() ? previousHosts->currentText() : hostEdit->text();
}
void DlgConnect::actCancel() void DlgConnect::actCancel()
{ {
QSettings settings; QSettings settings;
...@@ -109,3 +173,17 @@ void DlgConnect::actCancel() ...@@ -109,3 +173,17 @@ void DlgConnect::actCancel()
reject(); reject();
} }
bool DeleteHighlightedItemWhenShiftDelPressedEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Delete) {
QComboBox* combobox = reinterpret_cast<QComboBox *>(obj);
combobox->removeItem(combobox->currentIndex());
return true;
}
}
return QObject::eventFilter(obj, event);
}
...@@ -7,12 +7,22 @@ ...@@ -7,12 +7,22 @@
class QLabel; class QLabel;
class QPushButton; class QPushButton;
class QCheckBox; class QCheckBox;
class QComboBox;
class QRadioButton;
class DeleteHighlightedItemWhenShiftDelPressedEventFilter : public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
class DlgConnect : public QDialog { class DlgConnect : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
DlgConnect(QWidget *parent = 0); DlgConnect(QWidget *parent = 0);
QString getHost() const { return hostEdit->text(); } QString getHost() const;
int getPort() const { return portEdit->text().toInt(); } int getPort() const { return portEdit->text().toInt(); }
QString getPlayerName() const { return playernameEdit->text(); } QString getPlayerName() const { return playernameEdit->text(); }
QString getPassword() const { return passwordEdit->text(); } QString getPassword() const { return passwordEdit->text(); }
...@@ -20,10 +30,14 @@ private slots: ...@@ -20,10 +30,14 @@ private slots:
void actOk(); void actOk();
void actCancel(); void actCancel();
void passwordSaved(int state); void passwordSaved(int state);
void previousHostSelected(bool state);
void newHostSelected(bool state);
private: private:
QLabel *hostLabel, *portLabel, *playernameLabel, *passwordLabel; QLabel *hostLabel, *portLabel, *playernameLabel, *passwordLabel;
QLineEdit *hostEdit, *portEdit, *playernameEdit, *passwordEdit; QLineEdit *hostEdit, *portEdit, *playernameEdit, *passwordEdit;
QCheckBox *savePasswordCheckBox, *autoConnectCheckBox; QCheckBox *savePasswordCheckBox, *autoConnectCheckBox;
QComboBox *previousHosts;
QRadioButton *newHostButton, *previousHostButton;
}; };
#endif #endif
...@@ -574,6 +574,9 @@ MessagesSettingsPage::MessagesSettingsPage() ...@@ -574,6 +574,9 @@ MessagesSettingsPage::MessagesSettingsPage()
{ {
chatMentionCheckBox.setChecked(settingsCache->getChatMention()); chatMentionCheckBox.setChecked(settingsCache->getChatMention());
connect(&chatMentionCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setChatMention(int))); connect(&chatMentionCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setChatMention(int)));
chatMentionCompleterCheckbox.setChecked(settingsCache->getChatMentionCompleter());
connect(&chatMentionCompleterCheckbox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setChatMentionCompleter(int)));
ignoreUnregUsersMainChat.setChecked(settingsCache->getIgnoreUnregisteredUsers()); ignoreUnregUsersMainChat.setChecked(settingsCache->getIgnoreUnregisteredUsers());
ignoreUnregUserMessages.setChecked(settingsCache->getIgnoreUnregisteredUserMessages()); ignoreUnregUserMessages.setChecked(settingsCache->getIgnoreUnregisteredUserMessages());
...@@ -606,11 +609,12 @@ MessagesSettingsPage::MessagesSettingsPage() ...@@ -606,11 +609,12 @@ MessagesSettingsPage::MessagesSettingsPage()
chatGrid->addWidget(&chatMentionCheckBox, 0, 0); chatGrid->addWidget(&chatMentionCheckBox, 0, 0);
chatGrid->addWidget(&invertMentionForeground, 0, 1); chatGrid->addWidget(&invertMentionForeground, 0, 1);
chatGrid->addWidget(mentionColor, 0, 2); chatGrid->addWidget(mentionColor, 0, 2);
chatGrid->addWidget(&ignoreUnregUsersMainChat, 1, 0); chatGrid->addWidget(&chatMentionCompleterCheckbox, 1, 0);
chatGrid->addWidget(&ignoreUnregUsersMainChat, 2, 0);
chatGrid->addWidget(&hexLabel, 1, 2); chatGrid->addWidget(&hexLabel, 1, 2);
chatGrid->addWidget(&ignoreUnregUserMessages, 2, 0); chatGrid->addWidget(&ignoreUnregUserMessages, 3, 0);
chatGrid->addWidget(&messagePopups, 3, 0); chatGrid->addWidget(&messagePopups, 4, 0);
chatGrid->addWidget(&mentionPopups, 4, 0); chatGrid->addWidget(&mentionPopups, 5, 0);
chatGroupBox = new QGroupBox; chatGroupBox = new QGroupBox;
chatGroupBox->setLayout(chatGrid); chatGroupBox->setLayout(chatGrid);
...@@ -735,6 +739,7 @@ void MessagesSettingsPage::retranslateUi() ...@@ -735,6 +739,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"));
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"));
......
...@@ -168,6 +168,7 @@ private: ...@@ -168,6 +168,7 @@ private:
QAction *aAdd; QAction *aAdd;
QAction *aRemove; QAction *aRemove;
QCheckBox chatMentionCheckBox; QCheckBox chatMentionCheckBox;
QCheckBox chatMentionCompleterCheckbox;
QCheckBox invertMentionForeground; QCheckBox invertMentionForeground;
QCheckBox invertHighlightForeground; QCheckBox invertHighlightForeground;
QCheckBox ignoreUnregUsersMainChat; QCheckBox ignoreUnregUsersMainChat;
......
...@@ -33,7 +33,7 @@ ServerInfo_User LocalServer_DatabaseInterface::getUserData(const QString &name, ...@@ -33,7 +33,7 @@ ServerInfo_User LocalServer_DatabaseInterface::getUserData(const QString &name,
return result; return result;
} }
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler * /* handler */, const QString & /* user */, const QString & /* password */, QString & /* reasonStr */, int & /* secondsLeft */) AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler * /* handler */, const QString & /* user */, const QString & /* password */, const QString & /* clientId */, QString & /* reasonStr */, int & /* secondsLeft */)
{ {
return UnknownUser; return UnknownUser;
} }
...@@ -24,7 +24,7 @@ protected: ...@@ -24,7 +24,7 @@ protected:
ServerInfo_User getUserData(const QString &name, bool withId = false); ServerInfo_User getUserData(const QString &name, bool withId = false);
public: public:
LocalServer_DatabaseInterface(LocalServer *_localServer); LocalServer_DatabaseInterface(LocalServer *_localServer);
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft); AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, const QString &clientId, QString &reasonStr, int &secondsLeft);
int getNextGameId() { return localServer->getNextLocalGameId(); } int getNextGameId() { return localServer->getNextLocalGameId(); }
int getNextReplayId() { return -1; } int getNextReplayId() { return -1; }
int getActiveUserCount() { return 0; } int getActiveUserCount() { return 0; }
......
...@@ -222,8 +222,8 @@ int main(int argc, char *argv[]) ...@@ -222,8 +222,8 @@ int main(int argc, char *argv[])
settingsCache->setClientID(generateClientID()); settingsCache->setClientID(generateClientID());
qDebug() << "ClientID In Cache: " << settingsCache->getClientID(); qDebug() << "ClientID In Cache: " << settingsCache->getClientID();
ui.showMaximized(); ui.show();
qDebug("main(): ui.showMaximized() finished"); qDebug("main(): ui.show() finished");
app.exec(); app.exec();
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "pb/server_message.pb.h" #include "pb/server_message.pb.h"
#include "pb/event_server_identification.pb.h" #include "pb/event_server_identification.pb.h"
#include "settingscache.h" #include "settingscache.h"
#include "main.h"
static const unsigned int protocolVersion = 14; static const unsigned int protocolVersion = 14;
...@@ -78,6 +79,7 @@ void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentifica ...@@ -78,6 +79,7 @@ void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentifica
cmdRegister.set_gender((ServerInfo_User_Gender) gender); cmdRegister.set_gender((ServerInfo_User_Gender) gender);
cmdRegister.set_country(country.toStdString()); cmdRegister.set_country(country.toStdString());
cmdRegister.set_real_name(realName.toStdString()); cmdRegister.set_real_name(realName.toStdString());
cmdRegister.set_clientid(settingsCache->getClientID().toStdString());
PendingCommand *pend = prepareSessionCommand(cmdRegister); PendingCommand *pend = prepareSessionCommand(cmdRegister);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(registerResponse(Response))); connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(registerResponse(Response)));
......
...@@ -78,6 +78,7 @@ SettingsCache::SettingsCache() ...@@ -78,6 +78,7 @@ SettingsCache::SettingsCache()
minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 5).toInt(); minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 5).toInt();
tapAnimation = settings->value("cards/tapanimation", true).toBool(); tapAnimation = settings->value("cards/tapanimation", true).toBool();
chatMention = settings->value("chat/mention", true).toBool(); chatMention = settings->value("chat/mention", true).toBool();
chatMentionCompleter = settings->value("chat/mentioncompleter", true).toBool();
chatMentionForeground = settings->value("chat/mentionforeground", true).toBool(); chatMentionForeground = settings->value("chat/mentionforeground", true).toBool();
chatHighlightForeground = settings->value("chat/highlightforeground", true).toBool(); chatHighlightForeground = settings->value("chat/highlightforeground", true).toBool();
chatMentionColor = settings->value("chat/mentioncolor", "A6120D").toString(); chatMentionColor = settings->value("chat/mentioncolor", "A6120D").toString();
...@@ -361,6 +362,13 @@ void SettingsCache::setChatMention(int _chatMention) { ...@@ -361,6 +362,13 @@ void SettingsCache::setChatMention(int _chatMention) {
settings->setValue("chat/mention", chatMention); settings->setValue("chat/mention", chatMention);
} }
void SettingsCache::setChatMentionCompleter(const int _enableMentionCompleter)
{
chatMentionCompleter = _enableMentionCompleter;
settings->setValue("chat/mentioncompleter", chatMentionCompleter);
emit chatMentionCompleterChanged();
}
void SettingsCache::setChatMentionForeground(int _chatMentionForeground) { void SettingsCache::setChatMentionForeground(int _chatMentionForeground) {
chatMentionForeground = _chatMentionForeground; chatMentionForeground = _chatMentionForeground;
settings->setValue("chat/mentionforeground", chatMentionForeground); settings->setValue("chat/mentionforeground", chatMentionForeground);
......
...@@ -44,6 +44,7 @@ signals: ...@@ -44,6 +44,7 @@ signals:
void ignoreUnregisteredUserMessagesChanged(); void ignoreUnregisteredUserMessagesChanged();
void pixmapCacheSizeChanged(int newSizeInMBs); void pixmapCacheSizeChanged(int newSizeInMBs);
void masterVolumeChanged(int value); void masterVolumeChanged(int value);
void chatMentionCompleterChanged();
private: private:
QSettings *settings; QSettings *settings;
ShortcutsSettings *shortcutsSettings; ShortcutsSettings *shortcutsSettings;
...@@ -66,6 +67,7 @@ private: ...@@ -66,6 +67,7 @@ private:
int minPlayersForMultiColumnLayout; int minPlayersForMultiColumnLayout;
bool tapAnimation; bool tapAnimation;
bool chatMention; bool chatMention;
bool chatMentionCompleter;
QString chatMentionColor; QString chatMentionColor;
QString chatHighlightColor; QString chatHighlightColor;
bool chatMentionForeground; bool chatMentionForeground;
...@@ -137,6 +139,7 @@ public: ...@@ -137,6 +139,7 @@ public:
int getMinPlayersForMultiColumnLayout() const { return minPlayersForMultiColumnLayout; } int getMinPlayersForMultiColumnLayout() const { return minPlayersForMultiColumnLayout; }
bool getTapAnimation() const { return tapAnimation; } bool getTapAnimation() const { return tapAnimation; }
bool getChatMention() const { return chatMention; } bool getChatMention() const { return chatMention; }
bool getChatMentionCompleter() const { return chatMentionCompleter; }
bool getChatMentionForeground() const { return chatMentionForeground; } bool getChatMentionForeground() const { return chatMentionForeground; }
bool getChatHighlightForeground() const { return chatHighlightForeground; } bool getChatHighlightForeground() const { return chatHighlightForeground; }
bool getZoneViewSortByName() const { return zoneViewSortByName; } bool getZoneViewSortByName() const { return zoneViewSortByName; }
...@@ -220,6 +223,7 @@ public slots: ...@@ -220,6 +223,7 @@ public slots:
void setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout); void setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout);
void setTapAnimation(int _tapAnimation); void setTapAnimation(int _tapAnimation);
void setChatMention(int _chatMention); void setChatMention(int _chatMention);
void setChatMentionCompleter(int _chatMentionCompleter);
void setChatMentionForeground(int _chatMentionForeground); void setChatMentionForeground(int _chatMentionForeground);
void setChatHighlightForeground(int _chatHighlightForeground); void setChatHighlightForeground(int _chatHighlightForeground);
void setZoneViewSortByName(int _zoneViewSortByName); void setZoneViewSortByName(int _zoneViewSortByName);
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <QTimer> #include <QTimer>
#include <QDockWidget> #include <QDockWidget>
#include <QPushButton> #include <QPushButton>
#include <QDir>
#include <QDesktopServices>
#include "tab_deck_editor.h" #include "tab_deck_editor.h"
#include "window_sets.h" #include "window_sets.h"
#include "carddatabase.h" #include "carddatabase.h"
...@@ -363,6 +365,7 @@ void TabDeckEditor::createMenus() ...@@ -363,6 +365,7 @@ void TabDeckEditor::createMenus()
#if defined(Q_OS_WIN) || defined(Q_OS_MAC) #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
dbMenu->addSeparator(); dbMenu->addSeparator();
dbMenu->addAction(aOpenCustomFolder); dbMenu->addAction(aOpenCustomFolder);
dbMenu->addAction(aOpenCustomsetsFolder);
#endif #endif
addTabMenu(dbMenu); addTabMenu(dbMenu);
} }
...@@ -573,6 +576,7 @@ void TabDeckEditor::retranslateUi() ...@@ -573,6 +576,7 @@ void TabDeckEditor::retranslateUi()
aPrintDeck->setText(tr("&Print deck...")); aPrintDeck->setText(tr("&Print deck..."));
aAnalyzeDeck->setText(tr("&Analyze deck on deckstats.net")); aAnalyzeDeck->setText(tr("&Analyze deck on deckstats.net"));
aOpenCustomFolder->setText(tr("Open custom image folder")); aOpenCustomFolder->setText(tr("Open custom image folder"));
aOpenCustomsetsFolder->setText(tr("Open custom sets folder"));
aClose->setText(tr("&Close")); aClose->setText(tr("&Close"));
aClose->setShortcuts(settingsCache->shortcuts().getShortcut( aClose->setShortcuts(settingsCache->shortcuts().getShortcut(
"TabDeckEditor/aClose", "TabDeckEditor/aClose",
...@@ -825,6 +829,33 @@ void TabDeckEditor::actOpenCustomFolder() { ...@@ -825,6 +829,33 @@ void TabDeckEditor::actOpenCustomFolder() {
} }
void TabDeckEditor::actOpenCustomsetsFolder() {
#if QT_VERSION < 0x050000
QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#else
QString dataDir = QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
#if defined(Q_OS_MAC)
QStringList scriptArgs;
scriptArgs << QLatin1String("-e");
scriptArgs << QString::fromLatin1("tell application \"Finder\" to open POSIX file \"%1\"").arg(dataDir + "/customsets/");
scriptArgs << QLatin1String("-e");
scriptArgs << QLatin1String("tell application \"Finder\" to activate");
QProcess::execute("/usr/bin/osascript", scriptArgs);
#endif
#if defined(Q_OS_WIN)
QStringList args;
dataDir.append("/customsets");
args << QDir::toNativeSeparators(dataDir);
aOpenCustomsetsFolder->setText(dataDir);
QProcess::startDetached("explorer", args);
#endif
}
void TabDeckEditor::actEditSets() void TabDeckEditor::actEditSets()
{ {
WndSets *w = new WndSets; WndSets *w = new WndSets;
......
...@@ -54,6 +54,7 @@ class TabDeckEditor : public Tab { ...@@ -54,6 +54,7 @@ class TabDeckEditor : public Tab {
void actPrintDeck(); void actPrintDeck();
void actAnalyzeDeck(); void actAnalyzeDeck();
void actOpenCustomFolder(); void actOpenCustomFolder();
void actOpenCustomsetsFolder();
void actEditSets(); void actEditSets();
void actEditTokens(); void actEditTokens();
...@@ -112,7 +113,7 @@ private: ...@@ -112,7 +113,7 @@ private:
QWidget *filterBox; QWidget *filterBox;
QMenu *deckMenu, *dbMenu; QMenu *deckMenu, *dbMenu;
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose, *aOpenCustomFolder; QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aAnalyzeDeck, *aClose, *aOpenCustomFolder, *aOpenCustomsetsFolder;
QAction *aEditSets, *aEditTokens, *aClearFilterAll, *aClearFilterOne; QAction *aEditSets, *aEditTokens, *aClearFilterAll, *aClearFilterOne;
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;// *aUpdatePrices; QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;// *aUpdatePrices;
QAction *aResetLayout; QAction *aResetLayout;
......
...@@ -11,6 +11,14 @@ ...@@ -11,6 +11,14 @@
#include <QSplitter> #include <QSplitter>
#include <QApplication> #include <QApplication>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QCompleter>
#include <QWidget>
#include <QTextCursor>
#include <QAbstractItemView>
#include <QScrollBar>
#include <QStringListModel>
#include <QKeyEvent>
#include <QFocusEvent>
#include "tab_supervisor.h" #include "tab_supervisor.h"
#include "tab_room.h" #include "tab_room.h"
#include "tab_userlists.h" #include "tab_userlists.h"
...@@ -51,8 +59,9 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerI ...@@ -51,8 +59,9 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerI
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
connect(chatView, SIGNAL(addMentionTag(QString)), this, SLOT(addMentionTag(QString))); connect(chatView, SIGNAL(addMentionTag(QString)), this, SLOT(addMentionTag(QString)));
connect(settingsCache, SIGNAL(chatMentionCompleterChanged()), this, SLOT(actCompleterChanged()));
sayLabel = new QLabel; sayLabel = new QLabel;
sayEdit = new QLineEdit; sayEdit = new CustomLineEdit;
sayLabel->setBuddy(sayEdit); sayLabel->setBuddy(sayEdit);
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage())); connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage()));
...@@ -103,13 +112,26 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerI ...@@ -103,13 +112,26 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, ServerI
setLayout(hbox); setLayout(hbox);
const int userListSize = info.user_list_size(); const int userListSize = info.user_list_size();
for (int i = 0; i < userListSize; ++i) for (int i = 0; i < userListSize; ++i){
userList->processUserInfo(info.user_list(i), true); userList->processUserInfo(info.user_list(i), true);
autocompleteUserList.append("@" + QString::fromStdString(info.user_list(i).name()));
}
userList->sortItems(); userList->sortItems();
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);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setMaxVisibleItems(5);
#if QT_VERSION >= 0x050000
completer->setFilterMode(Qt::MatchStartsWith);
#endif
sayEdit->setCompleter(completer);
actCompleterChanged();
} }
TabRoom::~TabRoom() TabRoom::~TabRoom()
...@@ -119,7 +141,7 @@ TabRoom::~TabRoom() ...@@ -119,7 +141,7 @@ TabRoom::~TabRoom()
void TabRoom::retranslateUi() void TabRoom::retranslateUi()
{ {
gameSelector->retranslateUi(); gameSelector->retranslateUi();
chatView->retranslateUi(); chatView->retranslateUi();
userList->retranslateUi(); userList->retranslateUi();
sayLabel->setText(tr("&Say:")); sayLabel->setText(tr("&Say:"));
...@@ -166,16 +188,20 @@ QString TabRoom::sanitizeHtml(QString dirty) const ...@@ -166,16 +188,20 @@ QString TabRoom::sanitizeHtml(QString dirty) const
void TabRoom::sendMessage() void TabRoom::sendMessage()
{ {
if (sayEdit->text().isEmpty()) if (sayEdit->text().isEmpty()){
return; return;
}else if (completer->popup()->isVisible()){
Command_RoomSay cmd; completer->popup()->hide();
cmd.set_message(sayEdit->text().toStdString()); return;
}else{
PendingCommand *pend = prepareRoomCommand(cmd); Command_RoomSay cmd;
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(sayFinished(const Response &))); cmd.set_message(sayEdit->text().toStdString());
sendRoomCommand(pend);
sayEdit->clear(); PendingCommand *pend = prepareRoomCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(sayFinished(const Response &)));
sendRoomCommand(pend);
sayEdit->clear();
}
} }
void TabRoom::sayFinished(const Response &response) void TabRoom::sayFinished(const Response &response)
...@@ -200,6 +226,11 @@ void TabRoom::actOpenChatSettings() { ...@@ -200,6 +226,11 @@ void TabRoom::actOpenChatSettings() {
settings.exec(); settings.exec();
} }
void TabRoom::actCompleterChanged()
{
settingsCache->getChatMentionCompleter() ? completer->setCompletionRole(2) : completer->setCompletionRole(1);
}
void TabRoom::processRoomEvent(const RoomEvent &event) void TabRoom::processRoomEvent(const RoomEvent &event)
{ {
switch (static_cast<RoomEvent::RoomEventType>(getPbExtension(event))) { switch (static_cast<RoomEvent::RoomEventType>(getPbExtension(event))) {
...@@ -222,11 +253,17 @@ void TabRoom::processJoinRoomEvent(const Event_JoinRoom &event) ...@@ -222,11 +253,17 @@ void TabRoom::processJoinRoomEvent(const Event_JoinRoom &event)
{ {
userList->processUserInfo(event.user_info(), true); userList->processUserInfo(event.user_info(), true);
userList->sortItems(); userList->sortItems();
if (!autocompleteUserList.contains("@" + QString::fromStdString(event.user_info().name()))){
autocompleteUserList << "@" + QString::fromStdString(event.user_info().name());
sayEdit->updateCompleterModel(autocompleteUserList);
}
} }
void TabRoom::processLeaveRoomEvent(const Event_LeaveRoom &event) 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()));
sayEdit->updateCompleterModel(autocompleteUserList);
} }
void TabRoom::processRoomSayEvent(const Event_RoomSay &event) void TabRoom::processRoomSayEvent(const Event_RoomSay &event)
...@@ -259,3 +296,124 @@ void TabRoom::sendRoomCommand(PendingCommand *pend) ...@@ -259,3 +296,124 @@ void TabRoom::sendRoomCommand(PendingCommand *pend)
{ {
client->sendCommand(pend); client->sendCommand(pend);
} }
CustomLineEdit::CustomLineEdit(QWidget *parent)
: QLineEdit(parent)
{
}
void CustomLineEdit::focusOutEvent(QFocusEvent * e){
QLineEdit::focusOutEvent(e);
if (c->popup()->isVisible()){
//Remove Popup
c->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(c->completionModel()->index(c->popup()->currentIndex().row(), 0).data().toString() + " ");
//Set focus back to the textbox since tab was pressed
setFocus();
}
}
void CustomLineEdit::keyPressEvent(QKeyEvent * event)
{
switch (event->key()){
case Qt::Key_Return:
case Qt::Key_Enter:
case Qt::Key_Escape:
if (c->popup()->isVisible()){
event->ignore();
//Remove Popup
c->popup()->hide();
//Truncate the line to last space or whole string
QString textValue = text();
int lastIndexof = textValue.lastIndexOf(" ");
QString finalString = textValue.left(lastIndexof);
//Add a space if there's a word
if (finalString != "")
finalString += " ";
setText(finalString);
return;
}
break;
case Qt::Key_Space:
if (c->popup()->isVisible()){
event->ignore();
//Remove Popup
c->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(c->completionModel()->index(c->popup()->currentIndex().row(), 0).data().toString() + " ");
return;
}
break;
default:
break;
}
QLineEdit::keyPressEvent(event);
//Wait until the first character after @
if (!c || text().right(1).contains("@"))
return;
//Set new completion prefix
c->setCompletionPrefix(cursorWord(text()));
if (c->completionPrefix().length() < 1){
c->popup()->hide();
return;
}
//Draw completion box
QRect cr = cursorRect();
cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width());
c->complete(cr);
//Select first item in the completion popup
QItemSelectionModel* sm = new QItemSelectionModel(c->completionModel());
c->popup()->setSelectionModel(sm);
sm->select(c->completionModel()->index(0, 0), QItemSelectionModel::ClearAndSelect);
sm->setCurrentIndex(c->completionModel()->index(0, 0), QItemSelectionModel::NoUpdate);
}
QString CustomLineEdit::cursorWord(const QString &line) const
{
return line.mid(line.left(cursorPosition()).lastIndexOf(" ") + 1,
cursorPosition() - line.left(cursorPosition()).lastIndexOf(" ") - 1);
}
void CustomLineEdit::insertCompletion(QString arg)
{
QString s_arg = arg + " ";
setText(text().replace(text().left(cursorPosition()).lastIndexOf(" ") + 1,
cursorPosition() - text().left(cursorPosition()).lastIndexOf(" ") - 1, s_arg));
}
void CustomLineEdit::setCompleter(QCompleter* completer)
{
c = completer;
c->setWidget(this);
connect(c, SIGNAL(activated(QString)),this, SLOT(insertCompletion(QString)));
}
void CustomLineEdit::updateCompleterModel(QStringList completionList)
{
if (!c || c->popup()->isVisible())
return;
QStringListModel *model;
model = (QStringListModel*)(c->model());
if (model == NULL)
model = new QStringListModel();
QStringList updatedList = completionList;
model->setStringList(updatedList);
}
\ No newline at end of file
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include "tab.h" #include "tab.h"
#include <QGroupBox> #include <QGroupBox>
#include <QMap> #include <QMap>
#include <QLineEdit>
#include <QKeyEvent>
#include <QFocusEvent>
namespace google { namespace protobuf { class Message; } } namespace google { namespace protobuf { class Message; } }
class AbstractClient; class AbstractClient;
...@@ -13,6 +16,7 @@ class ChatView; ...@@ -13,6 +16,7 @@ class ChatView;
class QLineEdit; class QLineEdit;
class QPushButton; class QPushButton;
class QTextTable; class QTextTable;
class QCompleter;
class RoomEvent; class RoomEvent;
class ServerInfo_Room; class ServerInfo_Room;
class ServerInfo_Game; class ServerInfo_Game;
...@@ -24,6 +28,7 @@ class GameSelector; ...@@ -24,6 +28,7 @@ class GameSelector;
class Response; class Response;
class PendingCommand; class PendingCommand;
class ServerInfo_User; class ServerInfo_User;
class CustomLineEdit;
class TabRoom : public Tab { class TabRoom : public Tab {
Q_OBJECT Q_OBJECT
...@@ -38,14 +43,17 @@ private: ...@@ -38,14 +43,17 @@ private:
UserList *userList; UserList *userList;
ChatView *chatView; ChatView *chatView;
QLabel *sayLabel; QLabel *sayLabel;
QLineEdit *sayEdit; CustomLineEdit *sayEdit;
QGroupBox *chatGroupBox; QGroupBox *chatGroupBox;
QMenu *roomMenu; QMenu *roomMenu;
QAction *aLeaveRoom; QAction *aLeaveRoom;
QAction *aOpenChatSettings; QAction *aOpenChatSettings;
QAction * aClearChat; QAction *aClearChat;
QString sanitizeHtml(QString dirty) const; QString sanitizeHtml(QString dirty) const;
QStringList autocompleteUserList;
QCompleter *completer;
signals: signals:
void roomClosing(TabRoom *tab); void roomClosing(TabRoom *tab);
void openMessageDialog(const QString &userName, bool focus); void openMessageDialog(const QString &userName, bool focus);
...@@ -59,7 +67,8 @@ private slots: ...@@ -59,7 +67,8 @@ private slots:
void addMentionTag(QString mentionTag); void addMentionTag(QString mentionTag);
void focusTab(); void focusTab();
void actShowMentionPopup(QString &sender); void actShowMentionPopup(QString &sender);
void actCompleterChanged();
void processListGamesEvent(const Event_ListGames &event); void processListGamesEvent(const Event_ListGames &event);
void processJoinRoomEvent(const Event_JoinRoom &event); void processJoinRoomEvent(const Event_JoinRoom &event);
void processLeaveRoomEvent(const Event_LeaveRoom &event); void processLeaveRoomEvent(const Event_LeaveRoom &event);
...@@ -81,4 +90,21 @@ public: ...@@ -81,4 +90,21 @@ public:
void sendRoomCommand(PendingCommand *pend); void sendRoomCommand(PendingCommand *pend);
}; };
class CustomLineEdit : public QLineEdit
{
Q_OBJECT
private:
QString cursorWord(const QString& line) const;
QCompleter* c;
private slots:
void insertCompletion(QString);
protected:
void keyPressEvent(QKeyEvent * event);
void focusOutEvent(QFocusEvent * e);
public:
explicit CustomLineEdit(QWidget *parent = 0);
void setCompleter(QCompleter*);
void updateCompleterModel(QStringList);
};
#endif #endif
...@@ -99,6 +99,7 @@ void UserContextMenu::banUser_dialogFinished() ...@@ -99,6 +99,7 @@ void UserContextMenu::banUser_dialogFinished()
cmd.set_minutes(dlg->getMinutes()); cmd.set_minutes(dlg->getMinutes());
cmd.set_reason(dlg->getReason().toStdString()); cmd.set_reason(dlg->getReason().toStdString());
cmd.set_visible_reason(dlg->getVisibleReason().toStdString()); cmd.set_visible_reason(dlg->getVisibleReason().toStdString());
cmd.set_clientid(dlg->getBanId().toStdString());
client->sendCommand(client->prepareModeratorCommand(cmd)); client->sendCommand(client->prepareModeratorCommand(cmd));
} }
......
...@@ -36,11 +36,19 @@ BanDialog::BanDialog(const ServerInfo_User &info, QWidget *parent) ...@@ -36,11 +36,19 @@ BanDialog::BanDialog(const ServerInfo_User &info, QWidget *parent)
ipBanCheckBox = new QCheckBox(tr("ban &IP address")); ipBanCheckBox = new QCheckBox(tr("ban &IP address"));
ipBanCheckBox->setChecked(true); ipBanCheckBox->setChecked(true);
ipBanEdit = new QLineEdit(QString::fromStdString(info.address())); ipBanEdit = new QLineEdit(QString::fromStdString(info.address()));
idBanCheckBox = new QCheckBox(tr("ban client I&D"));
idBanCheckBox->setChecked(true);
idBanEdit = new QLineEdit(QString::fromStdString(info.clientid()));
if (QString::fromStdString(info.clientid()).isEmpty())
idBanCheckBox->setChecked(false);
QGridLayout *banTypeGrid = new QGridLayout; QGridLayout *banTypeGrid = new QGridLayout;
banTypeGrid->addWidget(nameBanCheckBox, 0, 0); banTypeGrid->addWidget(nameBanCheckBox, 0, 0);
banTypeGrid->addWidget(nameBanEdit, 0, 1); banTypeGrid->addWidget(nameBanEdit, 0, 1);
banTypeGrid->addWidget(ipBanCheckBox, 1, 0); banTypeGrid->addWidget(ipBanCheckBox, 1, 0);
banTypeGrid->addWidget(ipBanEdit, 1, 1); banTypeGrid->addWidget(ipBanEdit, 1, 1);
banTypeGrid->addWidget(idBanCheckBox, 2, 0);
banTypeGrid->addWidget(idBanEdit, 2, 1);
QGroupBox *banTypeGroupBox = new QGroupBox(tr("Ban type")); QGroupBox *banTypeGroupBox = new QGroupBox(tr("Ban type"));
banTypeGroupBox->setLayout(banTypeGrid); banTypeGroupBox->setLayout(banTypeGrid);
...@@ -110,8 +118,8 @@ BanDialog::BanDialog(const ServerInfo_User &info, QWidget *parent) ...@@ -110,8 +118,8 @@ BanDialog::BanDialog(const ServerInfo_User &info, QWidget *parent)
void BanDialog::okClicked() void BanDialog::okClicked()
{ {
if (!nameBanCheckBox->isChecked() && !ipBanCheckBox->isChecked()) { if (!nameBanCheckBox->isChecked() && !ipBanCheckBox->isChecked() && !idBanCheckBox->isChecked()) {
QMessageBox::critical(this, tr("Error"), tr("You have to select a name-based or IP-based ban, or both.")); QMessageBox::critical(this, tr("Error"), tr("You have to select a name-based, IP-based, clientId based, or some combination of the three to place a ban."));
return; return;
} }
accept(); accept();
...@@ -127,6 +135,11 @@ void BanDialog::enableTemporaryEdits(bool enabled) ...@@ -127,6 +135,11 @@ void BanDialog::enableTemporaryEdits(bool enabled)
minutesEdit->setEnabled(enabled); minutesEdit->setEnabled(enabled);
} }
QString BanDialog::getBanId() const
{
return idBanCheckBox->isChecked() ? idBanEdit->text() : QString();
}
QString BanDialog::getBanName() const QString BanDialog::getBanName() const
{ {
return nameBanCheckBox->isChecked() ? nameBanEdit->text() : QString(); return nameBanCheckBox->isChecked() ? nameBanEdit->text() : QString();
......
...@@ -24,8 +24,8 @@ class BanDialog : public QDialog { ...@@ -24,8 +24,8 @@ class BanDialog : public QDialog {
Q_OBJECT Q_OBJECT
private: private:
QLabel *daysLabel, *hoursLabel, *minutesLabel; QLabel *daysLabel, *hoursLabel, *minutesLabel;
QCheckBox *nameBanCheckBox, *ipBanCheckBox; QCheckBox *nameBanCheckBox, *ipBanCheckBox, *idBanCheckBox;
QLineEdit *nameBanEdit, *ipBanEdit; QLineEdit *nameBanEdit, *ipBanEdit, *idBanEdit;
QSpinBox *daysEdit, *hoursEdit, *minutesEdit; QSpinBox *daysEdit, *hoursEdit, *minutesEdit;
QRadioButton *permanentRadio, *temporaryRadio; QRadioButton *permanentRadio, *temporaryRadio;
QPlainTextEdit *reasonEdit, *visibleReasonEdit; QPlainTextEdit *reasonEdit, *visibleReasonEdit;
...@@ -36,6 +36,7 @@ public: ...@@ -36,6 +36,7 @@ public:
BanDialog(const ServerInfo_User &info, QWidget *parent = 0); BanDialog(const ServerInfo_User &info, QWidget *parent = 0);
QString getBanName() const; QString getBanName() const;
QString getBanIP() const; QString getBanIP() const;
QString getBanId() const;
int getMinutes() const; int getMinutes() const;
QString getReason() const; QString getReason() const;
QString getVisibleReason() const; QString getVisibleReason() const;
......
...@@ -319,6 +319,9 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32 ...@@ -319,6 +319,9 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
case Response::RespClientIdRequired: case Response::RespClientIdRequired:
QMessageBox::critical(this, tr("Error"), tr("This server requires client ID's. Your client is either failing to generate an ID or you are running a modified client.\nPlease close and reopen your client to try again.")); QMessageBox::critical(this, tr("Error"), tr("This server requires client ID's. Your client is either failing to generate an ID or you are running a modified client.\nPlease close and reopen your client to try again."));
break; break;
case Response::RespContextError:
QMessageBox::critical(this, tr("Error"), tr("An internal error has occurred, please try closing and reopening your client and try again. If the error persists try updating your client to the most recent build and if need be contact your software provider."));
break;
case Response::RespAccountNotActivated: { case Response::RespAccountNotActivated: {
bool ok = false; bool ok = false;
QString token = QInputDialog::getText(this, tr("Account activation"), tr("Your account has not been activated yet.\nYou need to provide the activation token received in the activation email"), QLineEdit::Normal, QString(), &ok); QString token = QInputDialog::getText(this, tr("Account activation"), tr("Your account has not been activated yet.\nYou need to provide the activation token received in the activation email"), QLineEdit::Normal, QString(), &ok);
......
...@@ -14,4 +14,5 @@ message Command_BanFromServer { ...@@ -14,4 +14,5 @@ message Command_BanFromServer {
optional uint32 minutes = 3; optional uint32 minutes = 3;
optional string reason = 4; optional string reason = 4;
optional string visible_reason = 5; optional string visible_reason = 5;
optional string clientid = 6;
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment