23 #include "application.h" 
   24 #include "gui/commongui.h" 
   25 #include "gui/irc/ircignoresmanager.h" 
   26 #include "gui/irc/ircsounds.h" 
   27 #include "gui/irc/ircuserlistmodel.h" 
   28 #include "irc/chatlogrotate.h" 
   29 #include "irc/chatlogs.h" 
   30 #include "irc/configuration/chatlogscfg.h" 
   31 #include "irc/configuration/ircconfig.h" 
   32 #include "irc/entities/ircnetworkentity.h" 
   33 #include "irc/ircchanneladapter.h" 
   34 #include "irc/ircdock.h" 
   35 #include "irc/ircglobal.h" 
   36 #include "irc/ircmessageclass.h" 
   37 #include "irc/ircnetworkadapter.h" 
   38 #include "irc/ircnicknamecompleter.h" 
   39 #include "irc/ircuserinfo.h" 
   40 #include "irc/ircuserlist.h" 
   41 #include "irc/ops/ircdelayedoperationignore.h" 
   42 #include "ircdocktabcontents.h" 
   44 #include "ui_ircdocktabcontents.h" 
   51 #include <QStandardItemModel> 
   55 const int IRCDockTabContents::BLINK_TIMER_DELAY_MS = 650;
 
   57 DClass<IRCDockTabContents> : 
public Ui::IRCDockTabContents
 
   61         QDateTime lastMessageDate;
 
   81         QStringList textOutputContents;
 
   82         ::IRCDockTabContents::UserListMenu *userListContextMenu;
 
  104         QAction *openChatWindow;
 
  111 IRCDockTabContents::IRCDockTabContents(
IRCDock *pParentIRCDock)
 
  114         d->lastMessageDate = QDateTime::currentDateTime();
 
  116         d->bBlinkTitle = 
false;
 
  117         d->bIsDestroying = 
false;
 
  118         d->lastMessageClass = 
nullptr;
 
  119         d->userListContextMenu = 
nullptr;
 
  120         this->pIrcAdapter = 
nullptr;
 
  122         this->pParentIRCDock = pParentIRCDock;
 
  125         d->txtOutputWidget->setContextMenuPolicy(Qt::CustomContextMenu);
 
  126         setupNewUserListModel();
 
  130         d->lvUserList->setVisible(
false);
 
  132         this->connect(d->btnSend, SIGNAL(clicked()), SLOT(sendMessage()));
 
  133         this->connect(d->leCommandLine, SIGNAL(returnPressed()), SLOT(sendMessage()));
 
  134         this->connect(gApp, SIGNAL(focusChanged(QWidget*,QWidget*)),
 
  135                 SLOT(onFocusChanged(QWidget*,QWidget*)));
 
  139         d->blinkTimer.setSingleShot(
false);
 
  140         this->connect(&d->blinkTimer, SIGNAL(timeout()),
 
  141                 SLOT(blinkTimerSlot()));
 
  147 IRCDockTabContents::~IRCDockTabContents()
 
  149         d->bIsDestroying = 
true;
 
  151         if (d->lastMessageClass != 
nullptr)
 
  152                 delete d->lastMessageClass;
 
  154         if (d->userListContextMenu != 
nullptr)
 
  155                 delete d->userListContextMenu;
 
  157         if (pIrcAdapter != 
nullptr)
 
  159                 disconnect(pIrcAdapter, 
nullptr, 
nullptr, 
nullptr);
 
  161                 pIrcAdapter = 
nullptr;
 
  166 void IRCDockTabContents::adapterFocusRequest()
 
  171 void IRCDockTabContents::adapterTerminating()
 
  173         if (pIrcAdapter != 
nullptr && !d->bIsDestroying)
 
  176                 disconnect(pIrcAdapter, 
nullptr, 
nullptr, 
nullptr);
 
  177                 pIrcAdapter = 
nullptr;
 
  183 void IRCDockTabContents::alertIfConfigured()
 
  185         if (gIRCConfig.appearance.windowAlertOnImportantChatEvent)
 
  186                 QApplication::alert(gApp->mainWindowAsQWidget());
 
  191         const static QString STYLE_SHEET_BASE_TEMPLATE =
 
  192                 "QListView, QTextEdit, QLineEdit { background: %1; color: %2; } ";
 
  196         QString qtStyleSheet = STYLE_SHEET_BASE_TEMPLATE
 
  197                 .arg(appearance.backgroundColor)
 
  198                 .arg(appearance.defaultTextColor);
 
  200         QColor colorSelectedText(appearance.userListSelectedTextColor);
 
  201         QColor colorSelectedBackground(appearance.userListSelectedBackgroundColor);
 
  202         qtStyleSheet += QString(
"QListView::item:selected { color: %1; background: %2; } ").arg(colorSelectedText.name(), colorSelectedBackground.name());
 
  204         QColor colorHoverText = colorSelectedText.lighter();
 
  205         QColor colorHoverBackground = colorSelectedBackground.lighter();
 
  206         qtStyleSheet += QString(
"QListView::item:hover  { color: %1; background: %2; } ").arg(colorHoverText.name(), colorHoverBackground.name());
 
  208         QString channelActionClassName = IRCMessageClass::toStyleSheetClassName(IRCMessageClass::ChannelAction);
 
  209         QString ctcpClassName = IRCMessageClass::toStyleSheetClassName(IRCMessageClass::Ctcp);
 
  210         QString errorClassName = IRCMessageClass::toStyleSheetClassName(IRCMessageClass::Error);
 
  211         QString networkActionClassName = IRCMessageClass::toStyleSheetClassName(IRCMessageClass::NetworkAction);
 
  213         QString htmlStyleSheetMessageArea = 
"";
 
  214         htmlStyleSheetMessageArea += 
"span { white-space: pre; }";
 
  215         htmlStyleSheetMessageArea += QString(
"a { color: %1; white-space: pre; } ").arg(appearance.urlColor);
 
  216         htmlStyleSheetMessageArea += QString(
"." + channelActionClassName + 
" { color: %1; } ").arg(appearance.channelActionColor);
 
  217         htmlStyleSheetMessageArea += QString(
"." + ctcpClassName + 
" { color: %1; } ").arg(appearance.ctcpColor);
 
  218         htmlStyleSheetMessageArea += QString(
"." + errorClassName + 
" { color: %1; } ").arg(appearance.errorColor);
 
  219         htmlStyleSheetMessageArea += QString(
"." + networkActionClassName + 
" { color: %1; } ").arg(appearance.networkActionColor);
 
  221         d->lvUserList->setStyleSheet(qtStyleSheet);
 
  222         d->lvUserList->setFont(appearance.userListFont);
 
  224         d->leCommandLine->installEventFilter(
this);
 
  225         d->leCommandLine->setStyleSheet(qtStyleSheet);
 
  226         d->leCommandLine->setFont(appearance.mainFont);
 
  228         d->txtOutputWidget->setStyleSheet(qtStyleSheet);
 
  229         d->txtOutputWidget->setFont(appearance.mainFont);
 
  231         d->txtOutputWidget->document()->setDefaultStyleSheet(htmlStyleSheetMessageArea);
 
  232         d->txtOutputWidget->clear();
 
  233         d->txtOutputWidget->insertHtml(d->textOutputContents.join(
""));
 
  234         d->txtOutputWidget->moveCursor(QTextCursor::End);
 
  237 void IRCDockTabContents::blinkTimerSlot()
 
  239         setBlinkTitle(!d->bBlinkTitle);
 
  242 void IRCDockTabContents::completeNickname()
 
  245         if (d->nicknameCompleter->isReset())
 
  246                 result = d->nicknameCompleter->complete(d->leCommandLine->text(), d->leCommandLine->cursorPosition());
 
  248                 result = d->nicknameCompleter->cycleNext();
 
  249         if (result.isValid())
 
  252                 d->leCommandLine->blockSignals(
true);
 
  253                 d->leCommandLine->setText(result.textLine);
 
  254                 d->leCommandLine->setCursorPosition(result.cursorPos);
 
  255                 d->leCommandLine->blockSignals(
false);
 
  259 bool IRCDockTabContents::eventFilter(QObject *watched, QEvent *event)
 
  261         if (watched == d->leCommandLine && event->type() == QEvent::KeyPress)
 
  263                 auto keyEvent = 
static_cast<QKeyEvent *
>(event);
 
  264                 if (keyEvent->key() == Qt::Key_Tab)
 
  273 QStandardItem *IRCDockTabContents::findUserListItem(
const QString &nickname)
 
  275         auto pModel = (QStandardItemModel *)d->lvUserList->model();
 
  278         for (
int i = 0; i < pModel->rowCount(); ++i)
 
  280                 QStandardItem *pItem = pModel->item(i);
 
  281                 if (userInfo == 
IRCUserInfo(pItem->text(), network()))
 
  288 IRCDockTabContents::UserListMenu &IRCDockTabContents::getUserListContextMenu()
 
  290         if (d->userListContextMenu == 
nullptr)
 
  291                 d->userListContextMenu = 
new UserListMenu();
 
  293         return *d->userListContextMenu;
 
  299         d->blinkTimer.stop();
 
  300         setBlinkTitle(
false);
 
  302         d->leCommandLine->setFocus();
 
  305 bool IRCDockTabContents::hasTabFocus()
 const 
  307         return this->pParentIRCDock->hasTabFocus(
this);
 
  310 QIcon IRCDockTabContents::icon()
 const 
  312         if (pIrcAdapter == 
nullptr)
 
  317         case IRCAdapterBase::ChannelAdapter:
 
  318                 return QIcon(
":/icons/irc_channel.png");
 
  320         case IRCAdapterBase::NetworkAdapter:
 
  321                 return QIcon(
":/flags/lan-small");
 
  323         case IRCAdapterBase::PrivAdapter:
 
  324                 return QIcon(
":/icons/person.png");
 
  331 void IRCDockTabContents::insertMessage(
const IRCMessageClass &messageClass, 
const QString &htmlString)
 
  333         if (d->lastMessageClass == 
nullptr)
 
  335         *d->lastMessageClass = messageClass;
 
  337         d->textOutputContents << htmlString;
 
  343         QTextCursor cursor = d->txtOutputWidget->textCursor();
 
  344         cursor.movePosition(QTextCursor::End);
 
  345         cursor.insertHtml(htmlString);
 
  347         if (!d->btnPauseTextArea->isChecked())
 
  348                 d->txtOutputWidget->moveCursor(QTextCursor::End);
 
  350         emit newMessagePrinted();
 
  353 void IRCDockTabContents::markDate()
 
  355         QDateTime previousMessageDate = d->lastMessageDate;
 
  356         QDateTime nowDate = QDateTime::currentDateTime();
 
  357         d->lastMessageDate = nowDate;
 
  358         if (previousMessageDate.daysTo(nowDate) != 0)
 
  360                 receiveMessageWithClass(tr(
"<<<DATE>>> Date on this computer changes to %1").arg(
 
  361                         nowDate.toString()), IRCMessageClass::NetworkAction);
 
  365 void IRCDockTabContents::myNicknameUsedSlot()
 
  370                 d->blinkTimer.start(BLINK_TIMER_DELAY_MS);
 
  373 void IRCDockTabContents::nameAdded(
const IRCUserInfo &userInfo)
 
  375         auto pModel = (QStandardItemModel *)d->lvUserList->model();
 
  376         QStandardItem *pItem = 
new QStandardItem(userInfo.
prefixedName());
 
  377         pItem->setData(userInfo.
cleanNickname(), IRCUserListModel::RoleCleanNickname);
 
  380         for (
int i = 0; i < pModel->rowCount(); ++i)
 
  382                 QStandardItem *pExistingItem = pModel->item(i);
 
  383                 QString existingNickname = pExistingItem->text();
 
  385                 if (userInfo <= 
IRCUserInfo(existingNickname, network()))
 
  387                         pModel->insertRow(i, pItem);
 
  394         pModel->appendRow(pItem);
 
  397 void IRCDockTabContents::nameListUpdated(
const IRCUserList &userList)
 
  399         setupNewUserListModel();
 
  401         for (
unsigned i = 0; i < userList.size(); ++i)
 
  402                 nameAdded(*userList[i]);
 
  405 void IRCDockTabContents::nameRemoved(
const IRCUserInfo &userInfo)
 
  407         auto pModel = (QStandardItemModel *)d->lvUserList->model();
 
  408         for (
int i = 0; i < pModel->rowCount(); ++i)
 
  410                 QStandardItem *pItem = pModel->item(i);
 
  413                         pModel->removeRow(i);
 
  419 void IRCDockTabContents::nameUpdated(
const IRCUserInfo &userInfo)
 
  421         nameRemoved(userInfo);
 
  427         return ircAdapter()->
network();
 
  432         return ircAdapter()->networkEntity();
 
  439         pParentIRCDock->addIRCAdapter(pAdapter);
 
  442 void IRCDockTabContents::onFocusChanged(QWidget *old, QWidget *now)
 
  444         if (old == d->lvUserList && now != d->userListContextMenu)
 
  445                 d->lvUserList->clearSelection();
 
  448 bool IRCDockTabContents::openLog()
 
  452         if (!logs.mkLogDir(networkEntity()))
 
  454                 receiveMessageWithClass(tr(
"Failed to create chat log directory:\n'%1'").arg(
 
  455                         logs.networkDirPath(networkEntity())), IRCMessageClass::Error);
 
  458         d->log.setFileName(
ChatLogs().logFilePath(networkEntity(), recipient()));
 
  459         d->log.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
 
  460         d->log.write(tr(
"<<<DATE>>> Chat log started on %1\n\n").arg(QDateTime::currentDateTime().toString()).toUtf8());
 
  464 void IRCDockTabContents::rotateOldLog()
 
  466         assert(!d->log.isOpen());
 
  471                 cfg.isRestoreChatFromLogs() ? cfg.oldLogsRemovalDaysThreshold() : -1);
 
  472         logRotate.rotate(networkEntity(), recipient());
 
  475 void IRCDockTabContents::printToSendersNetworksCurrentChatBox(
const QString &text, 
const IRCMessageClass &msgClass)
 
  480                 tab->ircAdapter()->emitMessageWithClass(text, msgClass);
 
  482                 adapter->emitMessageWithClass(text, msgClass);
 
  485 void IRCDockTabContents::receiveError(
const QString &error)
 
  487         receiveMessageWithClass(tr(
"Error: %1").arg(error), IRCMessageClass::Error);
 
  490 void IRCDockTabContents::receiveMessage(
const QString &message)
 
  495 void IRCDockTabContents::receiveMessageWithClass(
const QString &message, 
const IRCMessageClass &messageClass)
 
  499         QString messageHtmlEscaped = message;
 
  501         if (gIRCConfig.appearance.timestamps)
 
  503                 QString timestamp = Strings::timestamp(
"[hh:mm:ss] ");
 
  505                 messageHtmlEscaped = timestamp + messageHtmlEscaped;
 
  509                 messageHtmlEscaped = messageHtmlEscaped.replace(
"\n", 
"\n" + timestamp);
 
  515         messageHtmlEscaped += 
"\n";
 
  517         writeLog(messageHtmlEscaped);
 
  519         messageHtmlEscaped = wrapTextWithMetaTags(messageHtmlEscaped, messageClass);
 
  522         if (pIrcAdapter->
adapterType() == IRCAdapterBase::PrivAdapter)
 
  525                 pParentIRCDock->sounds().
playIfAvailable(IRCSounds::PrivateMessageReceived);
 
  529                         d->blinkTimer.start(BLINK_TIMER_DELAY_MS);
 
  532         this->insertMessage(messageClass, messageHtmlEscaped);
 
  535 QString IRCDockTabContents::recipient()
 const 
  537         return pIrcAdapter->recipient();
 
  540 void IRCDockTabContents::resetNicknameCompletion()
 
  542         d->nicknameCompleter->reset();
 
  545 bool IRCDockTabContents::restoreLog()
 
  548         QFile file(logs.logFilePath(networkEntity(), recipient()));
 
  549         if (file.open(QIODevice::ReadOnly | QIODevice::Text))
 
  551                 QByteArray contents = file.readAll();
 
  552                 QStringList lines = QString::fromUtf8(contents, contents.size()).split(
"\n");
 
  553                 int line = lines.size() - 1000;
 
  554                 lines = lines.mid((line > 0) ? line : 0);
 
  559                 receiveMessageWithClass(tr(
"---- All lines above were loaded from log ----"),
 
  560                         IRCMessageClass::NetworkAction);
 
  566 QString IRCDockTabContents::selectedNickname()
 
  568         QModelIndexList selectedIndexes = d->lvUserList->selectionModel()->selectedRows();
 
  570         if (!selectedIndexes.isEmpty())
 
  572                 int row = selectedIndexes[0].row();
 
  573                 auto pModel = (QStandardItemModel *)d->lvUserList->model();
 
  574                 QStandardItem *pItem = pModel->item(row);
 
  576                 return pItem->text();
 
  582 void IRCDockTabContents::sendCtcpPing(
const QString &nickname)
 
  584         network()->sendCtcp(nickname, QString(
"PING %1").arg(QDateTime::currentMSecsSinceEpoch()));
 
  587 void IRCDockTabContents::sendCtcpTime(
const QString &nickname)
 
  589         network()->sendCtcp(nickname, QString(
"TIME"));
 
  592 void IRCDockTabContents::sendCtcpVersion(
const QString &nickname)
 
  594         network()->sendCtcp(nickname, QString(
"VERSION"));
 
  597 void IRCDockTabContents::sendMessage()
 
  599         QString message = d->leCommandLine->text();
 
  600         d->leCommandLine->setText(
"");
 
  602         if (!message.trimmed().isEmpty())
 
  603                 pIrcAdapter->sendMessage(message);
 
  606 void IRCDockTabContents::sendWhois(
const QString &nickname)
 
  608         network()->sendMessage(QString(
"/WHOIS %1").arg(nickname));
 
  611 void IRCDockTabContents::setBlinkTitle(
bool b)
 
  614         if (d->bBlinkTitle != b)
 
  623                 emit titleBlinkRequested();
 
  628         assert(pIrcAdapter == 
nullptr);
 
  629         pIrcAdapter = pAdapter;
 
  632         if (cfg.isRestoreChatFromLogs())
 
  634         if (cfg.isStoreLogs())
 
  637         connect(pIrcAdapter, SIGNAL(error(
const QString&)), SLOT(receiveError(
const QString&)));
 
  638         connect(pIrcAdapter, SIGNAL(
focusRequest()), SLOT(adapterFocusRequest()));
 
  639         connect(pIrcAdapter, SIGNAL(message(
const QString&)), SLOT(receiveMessage(
const QString&)));
 
  640         connect(pIrcAdapter, SIGNAL(messageWithClass(
const QString&,
const IRCMessageClass&)), SLOT(receiveMessageWithClass(
const QString&,
const IRCMessageClass&)));
 
  641         connect(pIrcAdapter, SIGNAL(terminating()), SLOT(adapterTerminating()));
 
  642         connect(pIrcAdapter, SIGNAL(
titleChange()), SLOT(adapterTitleChange()));
 
  643         connect(pIrcAdapter, SIGNAL(messageToNetworksCurrentChatBox(QString,
IRCMessageClass)),
 
  648         case IRCAdapterBase::NetworkAdapter:
 
  655         case IRCAdapterBase::ChannelAdapter:
 
  658                 connect(pChannelAdapter, SIGNAL(myNicknameUsed()), SLOT(myNicknameUsedSlot()));
 
  660                 connect(pChannelAdapter, SIGNAL(nameListUpdated(
const IRCUserList&)), SLOT(nameListUpdated(
const IRCUserList&)));
 
  664                 d->lvUserList->setVisible(
true);
 
  665                 connect(d->lvUserList, SIGNAL(customContextMenuRequested(
const QPoint&)),
 
  666                         SLOT(userListCustomContextMenuRequested(
const QPoint&)));
 
  668                 connect(d->lvUserList, SIGNAL(doubleClicked(
const QModelIndex&)),
 
  669                         SLOT(userListDoubleClicked()));
 
  671                 d->lvUserList->setContextMenuPolicy(Qt::CustomContextMenu);
 
  676         case IRCAdapterBase::PrivAdapter:
 
  683                 receiveError(
"Doomseeker error: Unknown IRCAdapterBase*");
 
  689 void IRCDockTabContents::setupNewUserListModel()
 
  691         d->lvUserList->setModel(
new QStandardItemModel(d->lvUserList));
 
  692         d->nicknameCompleter->setModel(d->lvUserList->model());
 
  695 void IRCDockTabContents::showChatContextMenu(
const QPoint &pos)
 
  697         QMenu *menu = d->txtOutputWidget->createStandardContextMenu(pos);
 
  698         if (ircAdapter()->adapterType() == IRCAdapterBase::PrivAdapter)
 
  700                 menu->addSeparator();
 
  701                 appendPrivChatContextMenuOptions(menu);
 
  703         menu->addSeparator();
 
  704         appendGeneralChatContextMenuOptions(menu);
 
  705         menu->exec(d->txtOutputWidget->mapToGlobal(pos));
 
  709 void IRCDockTabContents::appendGeneralChatContextMenuOptions(QMenu *menu)
 
  711         QAction *manageIgnores = menu->addAction(tr(
"Manage ignores"));
 
  712         this->connect(manageIgnores, SIGNAL(triggered()), SLOT(showIgnoresManager()));
 
  715 void IRCDockTabContents::appendPrivChatContextMenuOptions(QMenu *menu)
 
  717         appendPrivChatContextMenuAction(menu, tr(
"Whois"), PrivWhois);
 
  718         appendPrivChatContextMenuAction(menu, tr(
"CTCP Ping"), PrivCtcpPing);
 
  719         appendPrivChatContextMenuAction(menu, tr(
"CTCP Time"), PrivCtcpTime);
 
  720         appendPrivChatContextMenuAction(menu, tr(
"CTCP Version"), PrivCtcpVersion);
 
  721         appendPrivChatContextMenuAction(menu, tr(
"Ignore"), PrivIgnore);
 
  724 void IRCDockTabContents::appendPrivChatContextMenuAction(QMenu *menu,
 
  725         const QString &text, PrivChatMenu type)
 
  727         QAction *action = menu->addAction(text);
 
  728         action->setData(type);
 
  729         this->connect(action, SIGNAL(triggered()), SLOT(onPrivChatActionTriggered()));
 
  732 void IRCDockTabContents::onPrivChatActionTriggered()
 
  734         QString nickname = ircAdapter()->recipient();
 
  736         auto action = 
static_cast<QAction *
>(sender());
 
  737         switch (action->data().toInt())
 
  740                 sendWhois(cleanNickname);
 
  743                 sendCtcpPing(cleanNickname);
 
  746                 sendCtcpTime(cleanNickname);
 
  748         case PrivCtcpVersion:
 
  749                 sendCtcpVersion(cleanNickname);
 
  752                 startIgnoreOperation(cleanNickname);
 
  755                 assert(0 && 
"Unsupported priv chat action");
 
  756                 qDebug() << 
"Unsupported priv chat action: " << action->data();
 
  761 void IRCDockTabContents::showIgnoresManager()
 
  764         connect(dialog, SIGNAL(accepted()), network(), SLOT(reloadNetworkEntityFromConfig()));
 
  765         dialog->setAttribute(Qt::WA_DeleteOnClose);
 
  769 void IRCDockTabContents::startIgnoreOperation(
const QString &nickname)
 
  772         op->setShowPatternPopup(
true);
 
  776 QString IRCDockTabContents::title()
 const 
  778         return pIrcAdapter->
title();
 
  781 QString IRCDockTabContents::titleColor()
 const 
  783         if (d->lastMessageClass != 
nullptr && !this->hasTabFocus())
 
  790                         color = d->lastMessageClass->colorFromConfig();
 
  796                         int rInverted = 0xff - c.red();
 
  797                         int gInverted = 0xff - c.green();
 
  798                         int bInverted = 0xff - c.blue();
 
  800                         QColor inverted(rInverted, gInverted, bInverted);
 
  802                         return inverted.name();
 
  811 void IRCDockTabContents::userListCustomContextMenuRequested(
const QPoint &pos)
 
  813         if (this->pIrcAdapter->
adapterType() != IRCAdapterBase::ChannelAdapter)
 
  819         QString nickname = this->selectedNickname();
 
  820         if (nickname.isEmpty())
 
  828         const QString &channel = pAdapter->recipient();
 
  830         UserListMenu &menu = this->getUserListContextMenu();
 
  831         QPoint posGlobal = d->lvUserList->mapToGlobal(pos);
 
  833         QAction *pAction = menu.exec(posGlobal);
 
  835         if (pAction == 
nullptr)
 
  838         if (pAction == menu.ban)
 
  842                 QString reason = 
CommonGUI::askString(tr(
"Ban user"), tr(
"Input reason for banning user %1 from channel %2").arg(nickname, channel), &bOk);
 
  844                         pAdapter->banUser(cleanNickname, reason);
 
  846         else if (pAction == menu.ctcpTime)
 
  847                 sendCtcpTime(cleanNickname);
 
  848         else if (pAction == menu.ctcpPing)
 
  849                 sendCtcpPing(cleanNickname);
 
  850         else if (pAction == menu.ctcpVersion)
 
  851                 sendCtcpVersion(cleanNickname);
 
  852         else if (pAction == menu.deop)
 
  853                 pAdapter->setOp(cleanNickname, 
false);
 
  854         else if (pAction == menu.dehalfOp)
 
  855                 pAdapter->setHalfOp(cleanNickname, 
false);
 
  856         else if (pAction == menu.devoice)
 
  857                 pAdapter->setVoiced(cleanNickname, 
false);
 
  858         else if (pAction == menu.halfOp)
 
  859                 pAdapter->setHalfOp(cleanNickname, 
true);
 
  860         else if (pAction == menu.ignore)
 
  861                 startIgnoreOperation(cleanNickname);
 
  862         else if (pAction == menu.kick)
 
  866                 QString reason = 
CommonGUI::askString(tr(
"Kick user"), tr(
"Input reason for kicking user %1 from channel %2").arg(nickname, channel), &bOk);
 
  868                         pAdapter->kickUser(cleanNickname, reason);
 
  870         else if (pAction == menu.op)
 
  871                 pAdapter->setOp(cleanNickname, 
true);
 
  872         else if (pAction == menu.openChatWindow)
 
  873                 pAdapter->network()->openNewAdapter(cleanNickname);
 
  874         else if (pAction == menu.voice)
 
  875                 pAdapter->setVoiced(cleanNickname, 
true);
 
  876         else if (pAction == menu.whois)
 
  877                 sendWhois(cleanNickname);
 
  880 void IRCDockTabContents::userListDoubleClicked()
 
  882         if (this->pIrcAdapter->
adapterType() != IRCAdapterBase::ChannelAdapter)
 
  888         QString nickname = this->selectedNickname();
 
  889         if (nickname.isEmpty())
 
  899 QString IRCDockTabContents::wrapTextWithMetaTags(
const QString &text,
 
  902         QString result = text;
 
  903         result.replace(
"<", 
"<").replace(
">", 
">");
 
  906         QString className = messageClass.toStyleSheetClassName();
 
  907         if (className.isEmpty())
 
  908                 result = 
"<span>" + result + 
"</span>";
 
  910                 result = (
"<span class='" + className + 
"'>" + result + 
"</span>");
 
  914 bool IRCDockTabContents::writeLog(
const QString &text)
 
  917         if (d->log.isOpen() && cfg.isStoreLogs())
 
  919                 d->log.write(text.toUtf8());
 
  927 IRCDockTabContents::UserListMenu::UserListMenu()
 
  929         this->openChatWindow = this->addAction(tr(
"Open chat window"));
 
  930         this->addSeparator();
 
  931         this->whois = this->addAction(tr(
"Whois"));
 
  932         this->ctcpTime = this->addAction(tr(
"CTCP Time"));
 
  933         this->ctcpPing = this->addAction(tr(
"CTCP Ping"));
 
  934         this->ctcpVersion = this->addAction(tr(
"CTCP Version"));
 
  935         this->addSeparator();
 
  936         this->op = this->addAction(tr(
"Op"));
 
  937         this->deop = this->addAction(tr(
"Deop"));
 
  938         this->halfOp = this->addAction(tr(
"Half op"));
 
  939         this->dehalfOp = this->addAction(tr(
"De half op"));
 
  940         this->voice = this->addAction(tr(
"Voice"));
 
  941         this->devoice = this->addAction(tr(
"Devoice"));
 
  942         this->addSeparator();
 
  943         this->ignore = this->addAction(tr(
"Ignore"));
 
  944         this->kick = this->addAction(tr(
"Kick"));
 
  945         this->ban = this->addAction(tr(
"Ban"));
 
  947         this->bIsOperator = 
false;