117
const QString MainWindow::defaultStyleSheet = QLatin1String(".log-channel{text-decoration:none;}.log-user{text-decoration:none;}");
113
119
MainWindow::MainWindow(QWidget *p) : QMainWindow(p) {
114
120
qiIconMuteSelf.addFile(QLatin1String("skin:muted_self.svg"));
115
121
qiIconMuteServer.addFile(QLatin1String("skin:muted_server.svg"));
116
122
qiIconMuteSuppressed.addFile(QLatin1String("skin:muted_suppressed.svg"));
117
123
qiIconDeafSelf.addFile(QLatin1String("skin:deafened_self.svg"));
118
124
qiIconDeafServer.addFile(QLatin1String("skin:deafened_server.svg"));
125
qiTalkingOff.addFile(QLatin1String("skin:talking_off.svg"));
126
qiTalkingOn.addFile(QLatin1String("skin:talking_on.svg"));
127
qiTalkingWhisperChannel.addFile(QLatin1String("skin:talking_alt.svg"));
128
qiTalkingWhisper.addFile(QLatin1String("skin:talking_whisper.svg"));
120
130
qiIcon.addFile(QLatin1String("skin:mumble.svg"));
164
177
on_qmUser_aboutToShow();
165
178
on_qmConfig_aboutToShow();
167
setOnTop(g.s.bAlwaysOnTop);
180
setOnTop(g.s.aotbAlwaysOnTop == Settings::OnTopAlways ||
181
(g.s.bMinimalView && g.s.aotbAlwaysOnTop == Settings::OnTopInMinimal) ||
182
(!g.s.bMinimalView && g.s.aotbAlwaysOnTop == Settings::OnTopInNormal));
168
184
#ifdef NO_UPDATE_CHECK
169
185
delete qaHelpVersionCheck;
250
266
pmModel = new UserModel(qtvUsers);
251
267
qtvUsers->setModel(pmModel);
252
268
qtvUsers->setRowHidden(0, QModelIndex(), true);
269
qtvUsers->ensurePolished();
254
271
qaServerConnect->setShortcuts(QKeySequence::Open);
255
272
qaServerDisconnect->setShortcuts(QKeySequence::Close);
276
293
dtbChatDockTitle = new DockTitleBar();
277
294
qdwChat->setTitleBarWidget(dtbChatDockTitle);
278
295
qdwChat->installEventFilter(dtbChatDockTitle);
279
qleChat->setDefaultText(tr("Not connected"));
296
qleChat->setDefaultText(tr("Not connected"), true);
280
297
qleChat->setEnabled(false);
282
299
connect(qtvUsers->selectionModel(),
290
307
else if (! g.s.bMinimalView && ! g.s.qbaMainWindowGeometry.isNull())
291
308
restoreGeometry(g.s.qbaMainWindowGeometry);
310
Settings::WindowLayout wlTmp = g.s.wlWindowLayout;
293
311
restoreState(g.s.qbaMainWindowState);
294
qtvUsers->header()->restoreState(g.s.qbaHeaderState);
312
g.s.wlWindowLayout = wlTmp;
296
314
setupView(false);
375
393
qstiIcon->setIcon(qiIconMuteServer);
376
394
} else if (p && p->bSuppress) {
377
395
qstiIcon->setIcon(qiIconMuteSuppressed);
396
} else if (p && g.s.bStateInTray) {
397
switch (p->tsState) {
398
case ClientUser::Talking:
399
qstiIcon->setIcon(qiTalkingOn);
401
case ClientUser::TalkingWhisper:
402
qstiIcon->setIcon(qiTalkingWhisper);
404
case ClientUser::TalkingWhisperChannel:
405
qstiIcon->setIcon(qiTalkingWhisperChannel);
407
case ClientUser::TalkingOff:
409
qstiIcon->setIcon(qiTalkingOff);
379
413
qstiIcon->setIcon(qiIcon);
417
Channel *MainWindow::getContextMenuChannel() {
419
return Channel::get(cmCid);
421
return pmModel->getChannel(qtvUsers->currentIndex());
424
ClientUser *MainWindow::getContextMenuUser() {
426
return ClientUser::get(cmUid);
428
return pmModel->getUser(qtvUsers->currentIndex());
431
bool MainWindow::handleSpecialContextMenu(const QUrl &url, const QPoint &_pos, bool focus) {
432
if (url.scheme() == QString::fromLatin1("clientid")) {
434
QString x(url.host());
435
if (x.length() == 40) {
436
ClientUser *cu = ClientUser::getByHash(x);
438
cmUid = ClientUser::getUiSession(cu);
442
QByteArray qbaServerDigest = QByteArray::fromBase64(url.path().remove(0, 1).toLatin1());
443
cmUid = url.host().toInt(&ok, 10);
444
ok = ok && (qbaServerDigest == g.sh->qbaDigest);
446
if (ok && ClientUser::isValid(cmUid)) {
448
qtvUsers->setCurrentIndex(pmModel->index(ClientUser::get(cmUid)));
450
qmUser->exec(_pos, NULL);
453
} else if (url.scheme() == QString::fromLatin1("channelid")) {
455
QByteArray qbaServerDigest = QByteArray::fromBase64(url.path().remove(0, 1).toLatin1());
456
cmCid = url.host().toInt(&ok, 10);
457
ok = ok && (qbaServerDigest == g.sh->qbaDigest);
460
qtvUsers->setCurrentIndex(pmModel->index(Channel::get(cmCid)));
462
qmChannel->exec(_pos, NULL);
383
471
void MainWindow::on_qteLog_customContextMenuRequested(const QPoint &mpos) {
472
QString link = qteLog->anchorAt(mpos);
473
if (! link.isEmpty()) {
476
if (handleSpecialContextMenu(l, qteLog->mapToGlobal(mpos)))
384
480
#if QT_VERSION >= 0x040400
385
481
QMenu *menu = qteLog->createStandardContextMenu(mpos);
479
575
if (g.sh && g.sh->isRunning()) {
480
576
on_qaServerDisconnect_triggered();
578
QCoreApplication::instance()->processEvents();
484
581
rtLast = MumbleProto::Reject_RejectType_None;
485
582
qaServerDisconnect->setEnabled(true);
486
g.l->log(Log::Information, tr("Connecting to server %1.").arg(host));
583
g.l->log(Log::Information, tr("Connecting to server %1.").arg(Log::msgColor(host, Log::Server)));
487
584
g.sh->setConnectionInfo(host, port, user, pw);
488
585
g.sh->start(QThread::TimeCriticalPriority);
567
664
if (g.s.bShowChatbar) qdwChat->show();
570
iTmp = Settings::LayoutCustom;
667
wlTmp = Settings::LayoutCustom;
573
g.s.iWindowLayout = iTmp;
670
g.s.wlWindowLayout = wlTmp;
575
672
QRect geom = frameGeometry();
594
if (g.s.bAlwaysOnTop)
691
if (g.s.aotbAlwaysOnTop == Settings::OnTopAlways ||
692
(g.s.bMinimalView && g.s.aotbAlwaysOnTop == Settings::OnTopInMinimal) ||
693
(!g.s.bMinimalView && g.s.aotbAlwaysOnTop == Settings::OnTopInNormal))
595
694
f |= Qt::WindowStaysOnTopHint;
597
696
setWindowFlags(f);
599
698
qdwLog->setVisible(showit);
600
699
qdwChat->setVisible(showit && g.s.bShowChatbar);
601
qtvUsers->header()->setVisible(showit);
602
700
menuBar()->setVisible(showit);
604
702
if (toggle_minimize) {
629
727
if (g.sh && g.sh->isRunning() && res == QDialog::Accepted) {
630
728
on_qaServerDisconnect_triggered();
730
QCoreApplication::instance()->processEvents();
634
733
if (res == QDialog::Accepted) {
635
734
qsDesiredChannel = QString();
636
735
rtLast = MumbleProto::Reject_RejectType_None;
637
736
qaServerDisconnect->setEnabled(true);
638
g.l->log(Log::Information, tr("Connecting to server %1.").arg(cd->qsServer));
737
g.l->log(Log::Information, tr("Connecting to server %1.").arg(Log::msgColor(cd->qsServer, Log::Server)));
639
738
g.sh->setConnectionInfo(cd->qsServer, cd->usPort, cd->qsUsername, cd->qsPassword);
640
739
g.sh->start(QThread::TimeCriticalPriority);
820
920
qmUser->addAction(qaUserMute);
821
921
qmUser->addAction(qaUserDeaf);
822
922
qmUser->addAction(qaUserLocalMute);
823
qmUser->addAction(qaUserComment);
925
qmUser->addAction(qaUserComment);
927
qmUser->addAction(qaUserCommentView);
928
qmUser->addAction(qaUserCommentReset);
824
931
qmUser->addAction(qaUserTextMessage);
826
933
if (p && (p->iId < 0) && (g.pPermissions & ((self ? ChanACL::SelfRegister : ChanACL::Register) | ChanACL::Write))) {
863
970
qaUserKick->setEnabled(false);
864
971
qaUserBan->setEnabled(false);
865
972
qaUserMute->setEnabled(false);
866
qaUserLocalMute->setEnabled(false);
867
973
qaUserDeaf->setEnabled(false);
868
974
qaUserTextMessage->setEnabled(false);
975
qaUserLocalMute->setEnabled(false);
976
qaUserComment->setEnabled(false);
977
qaUserCommentReset->setEnabled(false);
978
qaUserCommentView->setEnabled(false);
870
980
qaUserKick->setEnabled(! self);
871
981
qaUserBan->setEnabled(! self);
873
983
qaUserDeaf->setEnabled(! self || p->bDeaf);
874
984
qaUserTextMessage->setEnabled(true);
875
985
qaUserLocalMute->setEnabled(! self);
876
qaUserComment->setEnabled(self || (g.pPermissions & (ChanACL::Move | ChanACL::Write)));
986
qaUserComment->setEnabled(self);
987
qaUserCommentReset->setEnabled(!p->qsComment.isEmpty() && (g.pPermissions & (ChanACL::Move | ChanACL::Write)));
988
qaUserCommentView->setEnabled(! p->qsComment.isEmpty());
878
990
qaUserMute->setChecked(p->bMute || p->bSuppress);
879
991
qaUserDeaf->setChecked(p->bDeaf);
1035
1147
mptm.add_session(p->uiSession);
1036
1148
mptm.set_message(u8(msg));
1037
1149
g.sh->sendMessage(mptm);
1038
g.l->log(Log::TextMessage, tr("To %1: %2").arg(p->qsName).arg(texm->message()), tr("Message to %1").arg(p->qsName));
1150
g.l->log(Log::TextMessage, tr("To %1: %2").arg(Log::msgColor(p->qsName, Log::Target)).arg(texm->message()), tr("Message to %1").arg(p->qsName));
1044
1156
void MainWindow::on_qaUserComment_triggered() {
1045
User *p = pmModel->getUser(qtvUsers->currentIndex());
1157
ClientUser *p = getContextMenuUser();
1180
void MainWindow::on_qaUserCommentView_triggered() {
1181
ClientUser *p = getContextMenuUser();
1186
::TextMessage *texm = new ::TextMessage(this, tr("View comment on user %1").arg(p->qsName));
1188
texm->rteMessage->setText(p->qsComment, true);
1189
texm->setAttribute(Qt::WA_DeleteOnClose, true);
1193
void MainWindow::on_qaUserCommentReset_triggered() {
1194
ClientUser *p = getContextMenuUser();
1199
unsigned int session = p->uiSession;
1201
int ret = QMessageBox::question(this, tr("Mumble"),
1202
tr("Are you sure you want to reset the comment of user %1?").arg(p->qsName),
1203
QMessageBox::Yes, QMessageBox::No);
1204
if (ret == QMessageBox::Yes) {
1205
MumbleProto::UserState mpus;
1206
mpus.set_session(session);
1207
mpus.set_comment(std::string());
1208
g.sh->sendMessage(mpus);
1068
1212
void MainWindow::on_qaQuit_triggered() {
1069
1213
bSuppressAskOnQuit = true;
1073
1217
void MainWindow::on_qleChat_returnPressed() {
1074
1218
if (qleChat->text().isEmpty() || g.uiSession == 0) return; // Check if text & connection is available
1076
User *p = pmModel->getUser(qtvUsers->currentIndex());
1220
ClientUser *p = pmModel->getUser(qtvUsers->currentIndex());
1077
1221
Channel *c = pmModel->getChannel(qtvUsers->currentIndex());
1079
1223
MumbleProto::TextMessage mptm;
1092
1236
c = ClientUser::get(g.uiSession)->cChannel;
1094
1238
mptm.add_channel_id(c->iId);
1095
g.l->log(Log::TextMessage, tr("To channel %1: %2").arg(c->qsName).arg(qsText), tr("Message to channel %1").arg(c->qsName));
1239
g.l->log(Log::TextMessage, tr("To %1: %2").arg(Log::formatChannel(c)).arg(qsText), tr("Message to channel %1").arg(c->qsName));
1097
1241
// User message
1098
1242
mptm.add_session(p->uiSession);
1099
g.l->log(Log::TextMessage, tr("To %1: %2").arg(p->qsName).arg(qsText), tr("Message to %1").arg(p->qsName));
1243
g.l->log(Log::TextMessage, tr("To %1: %2").arg(Log::formatClientUser(p, Log::Target)).arg(qsText), tr("Message to %1").arg(p->qsName));
1102
1246
g.sh->sendMessage(mptm);
1129
1273
void MainWindow::on_qmChannel_aboutToShow() {
1130
QModelIndex idx = qtvUsers->currentIndex();
1132
1274
qmChannel->clear();
1276
if (cmCid >= 0 && g.uiSession != 0 && cmCid != ClientUser::get(g.uiSession)->cChannel->iId) {
1277
qmChannel->addAction(qaChannelJoin);
1278
qmChannel->addSeparator();
1133
1280
qmChannel->addAction(qaChannelAdd);
1134
1281
qmChannel->addAction(qaChannelACL);
1135
1282
qmChannel->addAction(qaChannelRemove);
1195
1342
updateMenuPermissions();
1345
void MainWindow::on_qaChannelJoin_triggered() {
1346
Channel *c = getContextMenuChannel();
1349
MumbleProto::UserState mpus;
1350
mpus.set_session(g.uiSession);
1351
mpus.set_channel_id(c->iId);
1352
g.sh->sendMessage(mpus);
1198
1356
void MainWindow::on_qaChannelAdd_triggered() {
1199
Channel *c = pmModel->getChannel(qtvUsers->currentIndex());
1357
Channel *c = getContextMenuChannel();
1201
1359
aclEdit->reject();
1202
1360
delete aclEdit;
1307
1465
g.sh->sendMessage(mptm);
1309
1467
if (texm->bTreeMessage)
1310
g.l->log(Log::TextMessage, tr("To tree %1: %2").arg(c->qsName).arg(texm->message()), tr("Message to tree %1").arg(c->qsName));
1468
g.l->log(Log::TextMessage, tr("(Tree) %1: %2").arg(Log::formatChannel(c)).arg(texm->message()), tr("Message to tree %1").arg(c->qsName));
1312
g.l->log(Log::TextMessage, tr("To channel %1: %2").arg(c->qsName).arg(texm->message()), tr("Message to channel %1").arg(c->qsName));
1470
g.l->log(Log::TextMessage, tr("%1: %2").arg(Log::formatChannel(c)).arg(texm->message()), tr("Message to channel %1").arg(c->qsName));
1317
1475
void MainWindow::updateMenuPermissions() {
1318
Channel *c = g.uiSession ? pmModel->getChannel(qtvUsers->currentIndex()) : NULL;
1476
ClientUser *cu = getContextMenuUser();
1477
Channel *c = g.uiSession ? (cu ? cu->cChannel : getContextMenuChannel()) : NULL;
1319
1478
ChanACL::Permissions p = static_cast<ChanACL::Permissions>(c ? c->uiPermissions : ChanACL::None);
1321
1480
if (c && ! p) {
1377
1536
qleChat->setEnabled(p & (ChanACL::Write | ChanACL::TextMessage));
1539
void MainWindow::talkingChanged() {
1540
if (g.s.bAttenuateOthersOnTalk) {
1541
ClientUser *p=ClientUser::get(g.uiSession);
1542
switch (p->tsState) {
1543
case ClientUser::Talking:
1544
case ClientUser::TalkingWhisper:
1545
case ClientUser::TalkingWhisperChannel:
1546
g.bAttenuateOthers = true;
1548
case ClientUser::TalkingOff:
1550
g.bAttenuateOthers = false;
1555
if (g.s.bStateInTray)
1380
1559
void MainWindow::on_qaAudioReset_triggered() {
1381
1560
AudioInputPtr ai = g.ai;
1743
1926
mpus.set_self_deaf(g.s.bDeaf);
1744
1927
g.sh->sendMessage(mpus);
1931
TaskList::addToRecentList(g.s.qsLastServer, host, port);
1935
static QString getPathToChannel(Channel *c) {
1942
while (tmp->cParent) {
1943
// skip root channel
1947
out.prepend(QString::fromLatin1("/"));
1948
out.prepend(tmp->qsName);
1748
1956
void MainWindow::serverDisconnected(QAbstractSocket::SocketError err, QString reason) {
1958
qsDesiredChannel = getPathToChannel(ClientUser::get(g.uiSession)->cChannel);
1749
1960
g.uiSession = 0;
1750
1961
g.pPermissions = ChanACL::None;
1751
1962
qaServerDisconnect->setEnabled(false);
1978
2189
Channel *c = pmModel->getChannel(qtvUsers->currentIndex());
1980
2191
if (g.uiSession == 0) {
1981
qleChat->setDefaultText(tr("Not connected"));
2192
qleChat->setDefaultText(tr("Not connected"), true);
1982
2193
} else if (p == NULL || p->uiSession == g.uiSession) {
1983
2194
// Channel tree target
1984
2195
if (c == NULL) // If no channel selected fallback to current one
2029
2240
#undef MUMBLE_MH_MSG
2032
2244
void MainWindow::on_qteLog_anchorClicked(const QUrl &url) {
2033
QDesktopServices::openUrl(url);
2245
if (!handleSpecialContextMenu(url, QCursor::pos(), true)) {
2246
if (url.scheme() != QLatin1String("file")
2247
&& url.scheme() != QLatin1String("qrc")
2248
&& !url.isRelative())
2249
QDesktopServices::openUrl(url);
2036
2253
void MainWindow::on_qteLog_highlighted(const QUrl &url) {
2254
if (url.scheme() == QString::fromLatin1("clientid") || url.scheme() == QString::fromLatin1("channelid"))
2037
2257
if (! url.isValid())
2038
2258
QToolTip::hideText();
2043
2263
void MainWindow::on_qdwChat_dockLocationChanged(Qt::DockWidgetArea) {
2044
g.s.iWindowLayout = Settings::LayoutCustom;
2264
g.s.wlWindowLayout = Settings::LayoutCustom;
2047
2267
void MainWindow::on_qdwLog_dockLocationChanged(Qt::DockWidgetArea) {
2048
g.s.iWindowLayout = Settings::LayoutCustom;
2268
g.s.wlWindowLayout = Settings::LayoutCustom;
2051
2271
void MainWindow::context_triggered() {