X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=gui%2Fchannelwidget.cpp;h=8aeb5926b67bb9e39be5f2b5e8cdb56163b935d9;hp=7ff453728c1445ae0f3a5b264f617d45d6072a7a;hb=3e7ed151306ef44a9be5ca7e3f37c89408d4a6d1;hpb=31d998779868a1b572972168b2e813893d70ab90 diff --git a/gui/channelwidget.cpp b/gui/channelwidget.cpp index 7ff45372..8aeb5926 100644 --- a/gui/channelwidget.cpp +++ b/gui/channelwidget.cpp @@ -20,45 +20,316 @@ #include "channelwidget.h" #include "guiproxy.h" +#include "global.h" +#include "util.h" #include #include -ChannelWidget::ChannelWidget(QWidget *parent) : QWidget(parent) { +ChannelWidget::ChannelWidget(QString netname, QString bufname, QString own, QWidget *parent) : QWidget(parent) { ui.setupUi(this); - //ui.lineEdit->setText("foobar"); - -/* //ui.splitter-> - ui.textBrowser->setHtml("[17:21] --> Dante has joined #quassel (~hurz@p1af2242.dip.t-dialin.net)
" - "[17:21] --> Sput has joined #quassel (~Sput42@vincent.mindpool.net)
" - "[17:23] <Dante> Das sieht ja soweit schonmal Klasse aus!
" - "[17:23] <Sput> Find ich auch... schade dass es noch nix tut :p
" - "[17:24] <Dante> Das wird sich ja gottseidank bald ändern.
" - "[17:24] <Sput> Wollen wir's hoffen :D" - ); - ui.listWidget->addItem("@Dante"); - ui.listWidget->addItem("@Sput"); - */ - //connect(&core, SIGNAL(outputLine( const QString& )), ui.textBrowser, SLOT(insertPlainText(const QString &))); - //connect(ui.lineEdit, SIGNAL( - //connect(&core, SIGNAL(outputLine( const QString& )), this, SLOT(lineReceived(const QString &))); - connect(ui.lineEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed())); - //connect(this, SIGNAL(inputLine( const QString& )), &core, SLOT(inputLine( const QString& ))); - - connect(this, SIGNAL(inputLine(QString)), guiProxy, SLOT(gsUserInput(QString))); - connect(this, SIGNAL(requestConnect(QString, quint16)), guiProxy, SLOT(gsRequestConnect(QString, quint16))); - connect(guiProxy, SIGNAL(csCoreMessage(QString)), this, SLOT(lineReceived(QString))); - - //emit requestConnect("irc.scortum.moep.net", 6668); - emit requestConnect("irc.quakenet.org", 6668); + _networkName = netname; + _bufferName = bufname; + ui.ownNick->clear(); + ui.ownNick->addItem(own); + if(bufname.isEmpty()) { + // Server Buffer + ui.nickTree->hide(); + ui.topicEdit->hide(); + ui.chanSettingsButton->hide(); + } + connect(ui.nickTree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*))); + connect(ui.nickTree, SIGNAL(itemCollapsed(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*))); + connect(ui.inputEdit, SIGNAL(returnPressed()), this, SLOT(enterPressed())); + connect(this, SIGNAL(nickListChanged(QStringList)), ui.inputEdit, SLOT(updateNickList(QStringList))); + ui.inputEdit->setFocus(); + + opsExpanded = voicedExpanded = usersExpanded = true; + + // Define standard colors + stdCol = "black"; + noticeCol = "darkblue"; + serverCol = "darkblue"; + errorCol = "red"; + joinCol = "green"; + quitCol = "firebrick"; + partCol = "firebrick"; + kickCol = "firebrick"; + nickCol = "magenta"; + + completer = 0; } void ChannelWidget::enterPressed() { - emit inputLine(ui.lineEdit->text()); - ui.lineEdit->clear(); + QStringList lines = ui.inputEdit->text().split('\n', QString::SkipEmptyParts); + foreach(QString msg, lines) { + if(msg.isEmpty()) continue; + emit sendInput(networkName(), bufferName(), msg); + } + ui.inputEdit->clear(); +} + +void ChannelWidget::recvMessage(Message msg) { + QString s, n; + QString c = stdCol; + QString user = userFromMask(msg.sender); + QString host = hostFromMask(msg.sender); + QString nick = nickFromMask(msg.sender); + switch(msg.type) { + case Message::Msg: + c = stdCol; n = QString("<%1>").arg(nick); s = msg.msg; + break; + case Message::Server: + c = serverCol; s = msg.msg; + break; + case Message::Error: + c = errorCol; s = msg.msg; + break; + case Message::Join: + c = joinCol; + s = QString(tr("--> %1 (%2@%3) has joined %4")).arg(nick).arg(user).arg(host).arg(bufferName()); + break; + case Message::Part: + c = partCol; + s = QString(tr("<-- %1 (%2@%3) has left %4")).arg(nick).arg(user).arg(host).arg(bufferName()); + if(!msg.msg.isEmpty()) s = QString("%1 (%2)").arg(s).arg(msg.msg); + break; + case Message::Kick: + { c = kickCol; + QString victim = msg.msg.section(" ", 0, 0); + if(victim == ui.ownNick->currentText()) victim = tr("you"); + QString kickmsg = msg.msg.section(" ", 1); + s = QString(tr("--> %1 has kicked %2 from %3")).arg(nick).arg(victim).arg(bufferName()); + if(!kickmsg.isEmpty()) s = QString("%1 (%2)").arg(s).arg(kickmsg); + } + break; + case Message::Quit: + c = quitCol; + s = QString(tr("<-- %1 (%2@%3) has quit")).arg(nick).arg(user).arg(host); + if(!msg.msg.isEmpty()) s = QString("%1 (%2)").arg(s).arg(msg.msg); + break; + case Message::Nick: + c = nickCol; + if(nick == msg.msg) s = QString(tr("<-> You are now known as %1")).arg(msg.msg); + else s = QString(tr("<-> %1 is now known as %2")).arg(nick).arg(msg.msg); + break; + case Message::Mode: + c = serverCol; + if(nick.isEmpty()) s = tr("*** User mode: %1").arg(msg.msg); + else s = tr("*** Mode %1 by %2").arg(msg.msg).arg(nick); + break; + default: + c = stdCol; n = QString("[%1]").arg(msg.sender); s = msg.msg; + break; + } + s.replace('&', "&"); s.replace('<', "<"); s.replace('>', ">"); + QString html = QString("" + "") + .arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")).arg("darkblue"); + if(!n.isEmpty()) + html += QString("") + .arg(n).arg("royalblue"); + html += QString("""
[%1]
%1
%1
").arg(s).arg(c); + ui.chatWidget->append(html); // qDebug() << html; + //ui.chatWidget->append(QString("
%1
%2
 %3
") + //.arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")).arg(nick).arg(s)); + ui.chatWidget->ensureCursorVisible(); +} + +void ChannelWidget::recvStatusMsg(QString msg) { + ui.chatWidget->insertPlainText(QString("[STATUS] %1").arg(msg)); + ui.chatWidget->ensureCursorVisible(); +} + +void ChannelWidget::setTopic(QString topic) { + ui.topicEdit->setText(topic); +} + +void ChannelWidget::setNicks(QStringList nicks) { + + +} + +void ChannelWidget::addNick(QString nick, VarMap props) { + nicks[nick] = props; + updateNickList(); + if(completer) delete completer; + completer = new QCompleter(nicks.keys()); + ui.inputEdit->setCompleter(completer); +} + +void ChannelWidget::updateNick(QString nick, VarMap props) { + nicks[nick] = props; + updateNickList(); +} + +void ChannelWidget::renameNick(QString oldnick, QString newnick) { + QVariant v = nicks.take(oldnick); + nicks[newnick] = v; + updateNickList(); +} + +void ChannelWidget::removeNick(QString nick) { + nicks.remove(nick); + updateNickList(); +} + +void ChannelWidget::setOwnNick(QString nick) { + ui.ownNick->clear(); + ui.ownNick->addItem(nick); +} + +void ChannelWidget::updateNickList() { + ui.nickTree->clear(); + if(nicks.count() != 1) ui.nickTree->setHeaderLabel(tr("%1 Users").arg(nicks.count())); + else ui.nickTree->setHeaderLabel(tr("1 User")); + QTreeWidgetItem *ops = new QTreeWidgetItem(); + QTreeWidgetItem *voiced = new QTreeWidgetItem(); + QTreeWidgetItem *users = new QTreeWidgetItem(); + // To sort case-insensitive, we have to put all nicks in a map which is sorted by (lowercase) key... + QMap sorted; + foreach(QString n, nicks.keys()) { sorted[n.toLower()] = n; } + foreach(QString n, sorted.keys()) { + QString nick = sorted[n]; + QString mode = nicks[nick].toMap()["Channels"].toMap()[bufferName()].toMap()["Mode"].toString(); + if(mode.contains('o')) { new QTreeWidgetItem(ops, QStringList(QString("@%1").arg(nick))); } + else if(mode.contains('v')) { new QTreeWidgetItem(voiced, QStringList(QString("+%1").arg(nick))); } + else new QTreeWidgetItem(users, QStringList(nick)); + } + if(ops->childCount()) { + ops->setText(0, tr("%1 Operators").arg(ops->childCount())); + ui.nickTree->addTopLevelItem(ops); + ops->setExpanded(opsExpanded); + } else delete ops; + if(voiced->childCount()) { + voiced->setText(0, tr("%1 Voiced").arg(voiced->childCount())); + ui.nickTree->addTopLevelItem(voiced); + voiced->setExpanded(voicedExpanded); + } else delete voiced; + if(users->childCount()) { + users->setText(0, tr("%1 Users").arg(users->childCount())); + ui.nickTree->addTopLevelItem(users); + users->setExpanded(usersExpanded); + } else delete users; +} + +void ChannelWidget::itemExpansionChanged(QTreeWidgetItem *item) { + if(item->child(0)->text(0).startsWith('@')) opsExpanded = item->isExpanded(); + else if(item->child(0)->text(0).startsWith('+')) voicedExpanded = item->isExpanded(); + else usersExpanded = item->isExpanded(); +} + +/**********************************************************************************************/ + + +IrcWidget::IrcWidget(QWidget *parent) : QWidget(parent) { + ui.setupUi(this); + ui.tabWidget->removeTab(0); + + connect(guiProxy, SIGNAL(csDisplayMsg(QString, QString, Message)), this, SLOT(recvMessage(QString, QString, Message))); + connect(guiProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); + connect(guiProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString))); + connect(guiProxy, SIGNAL(csSetNicks(QString, QString, QStringList)), this, SLOT(setNicks(QString, QString, QStringList))); + connect(guiProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap))); + connect(guiProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString))); + connect(guiProxy, SIGNAL(csNickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString))); + connect(guiProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap))); + connect(guiProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString))); + connect(this, SIGNAL(sendInput( QString, QString, QString )), guiProxy, SLOT(gsUserInput(QString, QString, QString))); +} + +ChannelWidget * IrcWidget::getBuffer(QString net, QString buf) { + QString key = net + buf; + if(!buffers.contains(key)) { + ChannelWidget *cw = new ChannelWidget(net, buf, ownNick[net]); + connect(cw, SIGNAL(sendInput(QString, QString, QString)), this, SLOT(userInput(QString, QString, QString))); + ui.tabWidget->addTab(cw, net+buf); + ui.tabWidget->setCurrentWidget(cw); + cw->setFocus(); + buffers[key] = cw; + } + return buffers[key]; +} + + +void IrcWidget::recvMessage(QString net, QString buf, Message msg) { + ChannelWidget *cw = getBuffer(net, buf); + cw->recvMessage(msg); +} + +void IrcWidget::recvStatusMsg(QString net, QString msg) { + recvMessage(net, "", Message(Message::Server, QString("[STATUS] %1").arg(msg))); + +} + +void IrcWidget::userInput(QString net, QString buf, QString msg) { + emit sendInput(net, buf, msg); +} + +void IrcWidget::setTopic(QString net, QString buf, QString topic) { + ChannelWidget *cw = getBuffer(net, buf); + cw->setTopic(topic); +} + +void IrcWidget::setNicks(QString net, QString buf, QStringList nicks) { + ChannelWidget *cw = getBuffer(net, buf); + cw->setNicks(nicks); +} + +void IrcWidget::addNick(QString net, QString nick, VarMap props) { + VarMap netnicks = nicks[net].toMap(); + netnicks[nick] = props; + nicks[net] = netnicks; + VarMap chans = props["Channels"].toMap(); + QStringList c = chans.keys(); + foreach(QString bufname, c) { + getBuffer(net, bufname)->addNick(nick, props); + } } -void ChannelWidget::lineReceived(QString s) { - ui.textBrowser->insertPlainText(s + "\n"); - ui.textBrowser->ensureCursorVisible(); +void IrcWidget::renameNick(QString net, QString oldnick, QString newnick) { + VarMap netnicks = nicks[net].toMap(); + qDebug() << "renNICK:"<renameNick(oldnick, newnick); + } + QVariant v = netnicks.take(oldnick); + netnicks[newnick] = v; + nicks[net] = netnicks; } + +void IrcWidget::updateNick(QString net, QString nick, VarMap props) { + QStringList oldchans = nicks[net].toMap()[nick].toMap()["Channels"].toMap().keys(); + QStringList newchans = props["Channels"].toMap().keys(); + foreach(QString c, newchans) { + if(oldchans.contains(c)) getBuffer(net, c)->updateNick(nick, props); + else getBuffer(net, c)->addNick(nick, props); + } + foreach(QString c, oldchans) { + if(!newchans.contains(c)) getBuffer(net, c)->removeNick(nick); + } + VarMap netnicks = nicks[net].toMap(); + netnicks[nick] = props; + nicks[net] = netnicks; +} + +void IrcWidget::removeNick(QString net, QString nick) { + VarMap chans = nicks[net].toMap()[nick].toMap()["Channels"].toMap(); + foreach(QString bufname, chans.keys()) { + getBuffer(net, bufname)->removeNick(nick); + } + VarMap netnicks = nicks[net].toMap(); + netnicks.remove(nick); + nicks[net] = netnicks; +} + +void IrcWidget::setOwnNick(QString net, QString nick) { + ownNick[net] = nick; + foreach(ChannelWidget *cw, buffers.values()) { + if(cw->networkName() == net) cw->setOwnNick(nick); + } +} +