diff --git a/icons/tango/status/text-missing.svg b/icons/tango/status/text-missing.svg
new file mode 100644
index 000000000..d5587e525
--- /dev/null
+++ b/icons/tango/status/text-missing.svg
@@ -0,0 +1,416 @@
+
+
+
+
diff --git a/src/mumble/Audio.cpp b/src/mumble/Audio.cpp
index b8456b096..43908379f 100644
--- a/src/mumble/Audio.cpp
+++ b/src/mumble/Audio.cpp
@@ -316,7 +316,7 @@ LoopUser::LoopUser() {
uiSession = 0;
iId = 0;
bMute = bDeaf = bSuppress = false;
- bLocalMute = bSelfDeaf = false;
+ bLocalIgnore = bLocalMute = bSelfDeaf = false;
tsState = Settings::Passive;
cChannel = NULL;
qtTicker.start();
diff --git a/src/mumble/ClientUser.cpp b/src/mumble/ClientUser.cpp
index 3e89ea11f..d2c2dc077 100644
--- a/src/mumble/ClientUser.cpp
+++ b/src/mumble/ClientUser.cpp
@@ -42,6 +42,7 @@ QReadWriteLock ClientUser::c_qrwlTalking;
ClientUser::ClientUser(QObject *p) : QObject(p),
tsState(Settings::Passive),
tLastTalkStateChange(false),
+ bLocalIgnore(false),
bLocalMute(false),
fPowerMin(0.0f),
fPowerMax(0.0f),
@@ -150,6 +151,8 @@ QString ClientUser::getFlagsString() const {
flags << ClientUser::tr("Muted (server)");
if (bDeaf)
flags << ClientUser::tr("Deafened (server)");
+ if (bLocalIgnore)
+ flags << ClientUser::tr("Local Ignore (Text messages)");
if (bLocalMute)
flags << ClientUser::tr("Local Mute");
if (bSelfMute)
@@ -199,6 +202,13 @@ void ClientUser::setSuppress(bool suppress) {
emit muteDeafChanged();
}
+void ClientUser::setLocalIgnore(bool ignore) {
+ if (bLocalIgnore == ignore)
+ return;
+ bLocalIgnore = ignore;
+ emit muteDeafChanged();
+}
+
void ClientUser::setLocalMute(bool mute) {
if (bLocalMute == mute)
return;
diff --git a/src/mumble/ClientUser.h b/src/mumble/ClientUser.h
index 2c7abcdf3..ba196e2c3 100644
--- a/src/mumble/ClientUser.h
+++ b/src/mumble/ClientUser.h
@@ -48,6 +48,7 @@ class ClientUser : public QObject, public User {
Settings::TalkState tsState;
Timer tLastTalkStateChange;
+ bool bLocalIgnore;
bool bLocalMute;
float fPowerMin, fPowerMax;
@@ -97,6 +98,7 @@ class ClientUser : public QObject, public User {
void setMute(bool mute);
void setDeaf(bool deaf);
void setSuppress(bool suppress);
+ void setLocalIgnore(bool ignore);
void setLocalMute(bool mute);
void setSelfMute(bool mute);
void setSelfDeaf(bool deaf);
diff --git a/src/mumble/Database.cpp b/src/mumble/Database.cpp
index 8c3854fd2..0624e8eba 100644
--- a/src/mumble/Database.cpp
+++ b/src/mumble/Database.cpp
@@ -128,6 +128,9 @@ Database::Database() {
query.exec(QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `friends_name` ON `friends`(`name`)"));
query.exec(QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `friends_hash` ON `friends`(`hash`)"));
+ query.exec(QLatin1String("CREATE TABLE IF NOT EXISTS `ignored` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT)"));
+ query.exec(QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `ignored_hash` ON `ignored`(`hash`)"));
+
query.exec(QLatin1String("CREATE TABLE IF NOT EXISTS `muted` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT)"));
query.exec(QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `muted_hash` ON `muted`(`hash`)"));
@@ -193,6 +196,29 @@ void Database::setFavorites(const QList &servers) {
QSqlDatabase::database().commit();
}
+bool Database::isLocalIgnored(const QString &hash) {
+ QSqlQuery query;
+
+ query.prepare(QLatin1String("SELECT `hash` FROM `ignored` WHERE `hash` = ?"));
+ query.addBindValue(hash);
+ query.exec();
+ while (query.next()) {
+ return true;
+ }
+ return false;
+}
+
+void Database::setLocalIgnored(const QString &hash, bool ignored) {
+ QSqlQuery query;
+
+ if (ignored)
+ query.prepare(QLatin1String("INSERT INTO `ignored` (`hash`) VALUES (?)"));
+ else
+ query.prepare(QLatin1String("DELETE FROM `ignored` WHERE `hash` = ?"));
+ query.addBindValue(hash);
+ query.exec();
+}
+
bool Database::isLocalMuted(const QString &hash) {
QSqlQuery query;
diff --git a/src/mumble/Database.h b/src/mumble/Database.h
index 357f6a5c1..075258e78 100644
--- a/src/mumble/Database.h
+++ b/src/mumble/Database.h
@@ -55,6 +55,9 @@ class Database : public QObject {
static void setPassword(const QString &host, unsigned short port, const QString &user, const QString &pw);
static bool fuzzyMatch(QString &name, QString &user, QString &pw, QString &host, unsigned short port);
+ static bool isLocalIgnored(const QString &hash);
+ static void setLocalIgnored(const QString &hash, bool ignored);
+
static bool isLocalMuted(const QString &hash);
static void setLocalMuted(const QString &hash, bool muted);
diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp
index 8e65be08a..36bb4bba1 100644
--- a/src/mumble/MainWindow.cpp
+++ b/src/mumble/MainWindow.cpp
@@ -1192,6 +1192,7 @@ void MainWindow::qmUser_aboutToShow() {
if (g.sh && g.sh->uiVersion >= 0x010203)
qmUser->addAction(qaUserPrioritySpeaker);
qmUser->addAction(qaUserLocalMute);
+ qmUser->addAction(qaUserLocalIgnore);
if (self)
qmUser->addAction(qaSelfComment);
@@ -1247,6 +1248,7 @@ void MainWindow::qmUser_aboutToShow() {
qaUserBan->setEnabled(false);
qaUserTextMessage->setEnabled(false);
qaUserLocalMute->setEnabled(false);
+ qaUserLocalIgnore->setEnabled(false);
qaUserCommentReset->setEnabled(false);
qaUserCommentView->setEnabled(false);
} else {
@@ -1254,6 +1256,7 @@ void MainWindow::qmUser_aboutToShow() {
qaUserBan->setEnabled(! self);
qaUserTextMessage->setEnabled(true);
qaUserLocalMute->setEnabled(! self);
+ qaUserLocalIgnore->setEnabled(! self);
qaUserCommentReset->setEnabled(! p->qbaCommentHash.isEmpty() && (g.pPermissions & (ChanACL::Move | ChanACL::Write)));
qaUserCommentView->setEnabled(! p->qbaCommentHash.isEmpty());
@@ -1261,6 +1264,7 @@ void MainWindow::qmUser_aboutToShow() {
qaUserDeaf->setChecked(p->bDeaf);
qaUserPrioritySpeaker->setChecked(p->bPrioritySpeaker);
qaUserLocalMute->setChecked(p->bLocalMute);
+ qaUserLocalIgnore->setChecked(p->bLocalIgnore);
}
updateMenuPermissions();
}
@@ -1295,6 +1299,18 @@ void MainWindow::on_qaUserLocalMute_triggered() {
Database::setLocalMuted(p->qsHash, muted);
}
+void MainWindow::on_qaUserLocalIgnore_triggered() {
+ ClientUser *p = getContextMenuUser();
+ if (!p)
+ return;
+
+ bool ignored = qaUserLocalIgnore->isChecked();
+
+ p->setLocalIgnore(ignored);
+ if (! p->qsHash.isEmpty())
+ Database::setLocalIgnored(p->qsHash, ignored);
+}
+
void MainWindow::on_qaUserDeaf_triggered() {
ClientUser *p = getContextMenuUser();
if (!p)
@@ -1765,7 +1781,6 @@ void MainWindow::on_qaChannelCopyURL_triggered() {
return;
g.sh->getConnectionInfo(host, port, uname, pw);
-
// walk back up the channel list to build the URL.
while (c->cParent != NULL) {
channel.prepend(c->qsName);
diff --git a/src/mumble/MainWindow.h b/src/mumble/MainWindow.h
index 4bd18fa37..0769bac47 100644
--- a/src/mumble/MainWindow.h
+++ b/src/mumble/MainWindow.h
@@ -175,6 +175,7 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin
void on_qaUserDeaf_triggered();
void on_qaSelfPrioritySpeaker_triggered();
void on_qaUserPrioritySpeaker_triggered();
+ void on_qaUserLocalIgnore_triggered();
void on_qaUserLocalMute_triggered();
void on_qaUserTextMessage_triggered();
void on_qaUserRegister_triggered();
diff --git a/src/mumble/MainWindow.ui b/src/mumble/MainWindow.ui
index 6703274be..6c881fabf 100644
--- a/src/mumble/MainWindow.ui
+++ b/src/mumble/MainWindow.ui
@@ -316,6 +316,20 @@
Deafen or undeafen user on server. Deafening a user will also mute them.
+
+
+ true
+
+
+ Ignore Messages
+
+
+ Locally ignore user's text chat messages.
+
+
+ Silently drops all text messages from the user.
+
+
true
diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp
index 5fb8ab80d..04766d9e5 100644
--- a/src/mumble/Messages.cpp
+++ b/src/mumble/Messages.cpp
@@ -262,6 +262,8 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) {
pmModel->setFriendName(pDst, name);
if (Database::isLocalMuted(pDst->qsHash))
pDst->setLocalMute(true);
+ if (Database::isLocalIgnored(pDst->qsHash))
+ pDst->setLocalIgnore(true);
}
if (bNewUser)
@@ -569,6 +571,11 @@ void MainWindow::msgChannelRemove(const MumbleProto::ChannelRemove &msg) {
void MainWindow::msgTextMessage(const MumbleProto::TextMessage &msg) {
ACTOR_INIT;
QString target;
+
+ // Silently drop the message if this user is set to "ignore"
+ if (pSrc->bLocalIgnore)
+ return;
+
const QString &plainName = pSrc ? pSrc->qsName : tr("Server", "message from");
const QString &name = pSrc ? Log::formatClientUser(pSrc, Log::Source) : tr("Server", "message from");
diff --git a/src/mumble/UserModel.cpp b/src/mumble/UserModel.cpp
index 2a29c1d9b..24fd31d02 100644
--- a/src/mumble/UserModel.cpp
+++ b/src/mumble/UserModel.cpp
@@ -220,6 +220,7 @@ UserModel::UserModel(QObject *p) : QAbstractItemModel(p) {
qiMutedSelf=QIcon(QLatin1String("skin:muted_self.svg"));
qiMutedServer=QIcon(QLatin1String("skin:muted_server.svg"));
qiMutedLocal=QIcon(QLatin1String("skin:muted_local.svg"));
+ qiIgnoredLocal=QIcon(QLatin1String("skin:status/text-missing.svg"));
qiMutedSuppressed=QIcon(QLatin1String("skin:muted_suppressed.svg"));
qiDeafenedSelf=QIcon(QLatin1String("skin:deafened_self.svg"));
qiDeafenedServer=QIcon(QLatin1String("skin:deafened_server.svg"));
@@ -408,6 +409,8 @@ QVariant UserModel::data(const QModelIndex &idx, int role) const {
l << qiMutedSelf;
if (p->bLocalMute)
l << qiMutedLocal;
+ if (p->bLocalIgnore)
+ l << qiIgnoredLocal;
if (p->bDeaf)
l << qiDeafenedServer;
if (p->bSelfDeaf)
@@ -611,13 +614,15 @@ QVariant UserModel::otherRoles(const QModelIndex &idx, int role) const {
" | %9 |
"
" | %10 |
"
" | %11 |
"
+ " | %12 |
"
"").arg(tr("This shows the flags the user has on the server, if any:"),
tr("On your friend list"),
tr("Authenticated user"),
tr("Muted (manually muted by self)"),
tr("Muted (manually muted by admin)"),
tr("Muted (not allowed to speak in current channel)"),
- tr("Muted (muted by you, only on your machine)")
+ tr("Muted (muted by you, only on your machine)"),
+ tr("Ignoring Text Messages")
).arg(
tr("Deafened (by self)"),
tr("Deafened (by admin)"),
diff --git a/src/mumble/UserModel.h b/src/mumble/UserModel.h
index 09429fc41..9310535b0 100644
--- a/src/mumble/UserModel.h
+++ b/src/mumble/UserModel.h
@@ -84,7 +84,7 @@ class UserModel : public QAbstractItemModel {
Q_DISABLE_COPY(UserModel)
protected:
QIcon qiTalkingOn, qiTalkingWhisper, qiTalkingShout, qiTalkingOff;
- QIcon qiMutedSelf, qiMutedServer, qiMutedLocal, qiMutedSuppressed;
+ QIcon qiMutedSelf, qiMutedServer, qiMutedLocal, qiIgnoredLocal, qiMutedSuppressed;
QIcon qiPrioritySpeaker;
QIcon qiRecording;
QIcon qiDeafenedSelf, qiDeafenedServer;
diff --git a/src/mumble/mumble_tango.qrc b/src/mumble/mumble_tango.qrc
index 7fd06e770..d00edc2e5 100644
--- a/src/mumble/mumble_tango.qrc
+++ b/src/mumble/mumble_tango.qrc
@@ -15,5 +15,6 @@
../../icons/tango/places/network-workgroup.svg
../../icons/tango/mimetypes/image-x-generic.svg
../../icons/tango/mimetypes/text-html.svg
+ ../../icons/tango/status/text-missing.svg