You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kvirc/src/kvirc/ui/kvi_channel.cpp

1629 lines
47 KiB

//=============================================================================
//
// File : kvi_channel.cpp
// Creation date : Tue Aug 1 2000 02:20:22 by Szymon Stefanek
//
// This file is part of the KVirc irc client distribution
// Copyright (C) 1999-2004 Szymon Stefanek (pragma at kvirc dot net)
//
// This program is FREE software. You can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your opinion) any later version.
//
// This program is distributed in the HOPE that it will be USEFUL,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, write to the Free Software Foundation,
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================
//
// Channel widget : abstraction of an IRC channel
//
#define __KVIRC__
#include "kvi_toolwindows_container.h"
#include "kvi_styled_controls.h"
#include "kvi_channel.h"
#include "kvi_console.h"
#include "kvi_iconmanager.h"
#include "kvi_ircview.h"
#include "kvi_input.h"
#include "kvi_options.h"
#include "kvi_locale.h"
#include "kvi_topicw.h"
#include "kvi_ircsocket.h"
#include "kvi_out.h"
#include "kvi_malloc.h"
#include "kvi_taskbar.h"
#include "kvi_frame.h"
#include "kvi_config.h"
#include "kvi_themedlabel.h"
#include "kvi_maskeditor.h"
#include "kvi_mirccntrl.h"
#include "kvi_settings.h"
#include "kvi_parameterlist.h"
#include "kvi_modeeditor.h"
#include "kvi_app.h"
#include "kvi_useraction.h"
#include "kvi_ircconnection.h"
#include "kvi_ircconnectionserverinfo.h"
#include "kvi_defaults.h"
#include "kvi_sparser.h"
#include "kvi_modew.h"
#include "kvi_mirccntrl.h"
#ifdef COMPILE_CRYPT_SUPPORT
#include "kvi_crypt.h"
#include "kvi_cryptcontroller.h"
#endif
#include "kvi_kvs_script.h"
#include "kvi_kvs_eventtriggers.h"
#include <time.h>
#include <tqsplitter.h>
#include <tqtoolbutton.h>
#include <tqlabel.h>
#include <tqevent.h>
#include <tqpalette.h>
#include "kvi_tal_popupmenu.h"
#include "kvi_pointerhashtable.h"
#include <tqmessagebox.h>
#include "kvi_tal_widgetstack.h"
#ifndef AVERAGE_CHANNEL_USERS
#define AVERAGE_CHANNEL_USERS 101
#endif
// FIXME: #warning "+a Anonymous channel mode!"
// FIXME: #warning "+r channel mode (reop)"
// FIXME: #warning "OnChannelFlood event...."
KviChannel::KviChannel(KviFrame * lpFrm,KviConsole * lpConsole,const char * name)
: KviWindow(KVI_WINDOW_TYPE_CHANNEL,lpFrm,name,lpConsole)
{
// Init some member variables
m_pInput = 0;
m_iStateFlags = 0;
m_pBanList = new KviPointerList<KviMaskEntry>;
m_pBanList->setAutoDelete(true);
m_pBanExceptionList = new KviPointerList<KviMaskEntry>;
m_pBanExceptionList->setAutoDelete(true);
m_pInviteList = new KviPointerList<KviMaskEntry>;
m_pInviteList->setAutoDelete(true);
m_pActionHistory = new KviPointerList<KviChannelAction>;
m_pActionHistory->setAutoDelete(true);
m_uActionHistoryHotActionCount = 0;
m_pTmpHighLighted = new KviPointerHashTable<const char *,TQString>();
m_pTmpHighLighted->setAutoDelete(true);
// Register ourselves
connection()->registerChannel(this);
// And create the widgets tqlayout
// Button box
m_pButtonBox = new KviTalHBox(this);
m_pTopSplitter = new TQSplitter(Qt::Horizontal,m_pButtonBox);
m_pButtonBox->setStretchFactor(m_pTopSplitter,1);
m_pButtonContainer = new KviTalHBox(m_pButtonBox);
// Topic widget on the left
m_pTopicWidget = new KviTopicWidget(m_pTopSplitter,"topic_widget");
connect(m_pTopicWidget,TQT_SIGNAL(topicSelected(const TQString &)),
this,TQT_SLOT(topicSelected(const TQString &)));
// mode label follows the topic widget
m_pModeWidget = new KviModeWidget(m_pTopSplitter,this,"mode_");
KviTalToolTip::add(m_pModeWidget,__tr2qs("Channel mode"));
createTextEncodingButton(m_pButtonContainer);
// Central splitter
m_pSplitter = new TQSplitter(Qt::Horizontal,this);
#ifdef COMPILE_USE_QT4
m_pSplitter->setObjectName(name);
#else
m_pSplitter->setName(name);
#endif
m_pSplitter->setOpaqueResize(false);
// Spitted vertially on the left
m_pVertSplitter = new TQSplitter(Qt::Vertical,m_pSplitter);
m_pVertSplitter->setOpaqueResize(false);
// With the IRC view over
m_pIrcView = new KviIrcView(m_pVertSplitter,lpFrm,this);
#ifdef COMPILE_USE_QT4
m_pIrcView->setObjectName(name);
#else
m_pIrcView->setName(name);
#endif
connect(m_pIrcView,TQT_SIGNAL(rightClicked()),this,TQT_SLOT(textViewRightClicked()));
// And the double view (that may be unused)
m_pMessageView = 0;
// The userlist on the right
//m_pEditorsContainer= new KviToolWindowsContainer(m_pSplitter);
// and the related buttons
m_pDoubleViewButton = createToolButton(m_pButtonContainer,"double_view_button",KVI_SMALLICON_HIDEDOUBLEVIEW,KVI_SMALLICON_SHOWDOUBLEVIEW,__tr2qs("Split View"),false);
connect(m_pDoubleViewButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleDoubleView()));
m_pListViewButton = new KviWindowToolPageButton(KVI_SMALLICON_HIDELISTVIEW,KVI_SMALLICON_SHOWLISTVIEW,__tr2qs("User List"),buttonContainer(),true,"list_view_button");
connect(m_pListViewButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleListView()));
m_pBanEditorButton = new KviWindowToolPageButton(KVI_SMALLICON_UNBAN,KVI_SMALLICON_BAN,__tr2qs("Ban Editor"),buttonContainer(),false,"ban_editor_button");
connect(m_pBanEditorButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleBanEditor()));
if(m_pConsole->connection()->serverInfo()->supportedListModes().contains('e'))
{
m_pBanExceptionEditorButton =new KviWindowToolPageButton(KVI_SMALLICON_BANUNEXCEPT,KVI_SMALLICON_BANEXCEPT,__tr2qs("Ban Exception Editor"),buttonContainer(),false,"ban_exception_editor_button");
connect(m_pBanExceptionEditorButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleBanExceptionEditor()));
} else {
m_pBanExceptionEditorButton=0;
}
if(m_pConsole->connection()->serverInfo()->supportedListModes().contains('I'))
{
m_pInviteEditorButton =new KviWindowToolPageButton(KVI_SMALLICON_INVITEUNEXCEPT,KVI_SMALLICON_INVITEEXCEPT,__tr2qs("Invite Exception Editor"),buttonContainer(),false,"invite_exception_editor_button");
connect(m_pInviteEditorButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleInviteEditor()));
} else {
m_pInviteEditorButton = 0;
}
m_pModeEditorButton = new KviWindowToolPageButton(KVI_SMALLICON_CHANMODEHIDE,KVI_SMALLICON_CHANMODE,__tr2qs("Mode Editor"),buttonContainer(),false,"mode_editor_button");
connect(m_pModeEditorButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleModeEditor()));
m_pModeEditor = 0;
#ifdef COMPILE_CRYPT_SUPPORT
createCryptControllerButton(m_pButtonContainer);
#endif
m_pHideToolsButton = new KviStyledToolButton(m_pButtonBox,"hide_container_button");
#ifndef COMPILE_USE_QT4
m_pHideToolsButton->setUsesBigPixmap(false);
#else
m_pHideToolsButton->setAutoRaise(true);
#endif
m_pHideToolsButton->setFixedWidth(10);
if(g_pIconManager->getBigIcon("kvi_horizontal_left.png"))
m_pHideToolsButton->setPixmap(*(g_pIconManager->getBigIcon("kvi_horizontal_left.png")));
connect(m_pHideToolsButton,TQT_SIGNAL(clicked()),this,TQT_SLOT(toggleToolButtons()));
m_pUserListView = new KviUserListView(m_pSplitter,m_pListViewButton,connection()->userDataBase(),this,
AVERAGE_CHANNEL_USERS,__tr2qs("User List"),"user_list_view");
// m_pEditorsContainer->addWidget(m_pUserListView);
// m_pEditorsContainer->raiseWidget(m_pUserListView);
// And finally the input line on the bottom
m_pInput = new KviInput(this,m_pUserListView);
// no mask editors yet
m_pBanEditor = 0;
m_pBanExceptionEditor = 0;
m_pInviteEditor = 0;
// Ensure proper focusing
//setFocusHandler(m_pInput,this);
// And turn on the secondary IRC view if needed
if(KVI_OPTION_BOOL(KviOption_boolAutoLogChannels))m_pIrcView->startLogging();
applyOptions();
m_joinTime = TQDateTime::currentDateTime();
m_tLastReceivedWhoReply = (kvi_time_t)m_joinTime.toTime_t();
}
KviChannel::~KviChannel()
{
// Unregister ourself
if(type() == KVI_WINDOW_TYPE_DEADCHANNEL)context()->unregisterDeadChannel(this);
else connection()->unregisterChannel(this);
// Then remove all the users and free mem
m_pUserListView->enableUpdates(false);
m_pUserListView->partAll();
delete m_pActionHistory;
delete m_pBanList;
delete m_pBanExceptionList;
delete m_pInviteList;
delete m_pTmpHighLighted;
}
void KviChannel::toggleToolButtons()
{
if(!buttonContainer()) return;
toggleButtonContainer();
TQPixmap* pix= buttonContainer()->isVisible() ?
g_pIconManager->getBigIcon("kvi_horizontal_left.png") :
g_pIconManager->getBigIcon("kvi_horizontal_right.png");
if(pix)
m_pHideToolsButton->setPixmap(*pix);
}
void KviChannel::triggerCreationEvents()
{
KVS_TRIGGER_EVENT_0(KviEvent_OnChannelWindowCreated,this);
}
void KviChannel::textViewRightClicked()
{
KVS_TRIGGER_EVENT_0(KviEvent_OnChannelPopupRequest,this);
}
void KviChannel::getBaseLogFileName(TQString &buffer)
{
TQString szChan(windowName());
szChan.replace(".","%2e");
if (console()->connection())
{
buffer=szChan;
buffer.append(".");
buffer.append(console()->currentNetworkName());
} else {
buffer=szChan;
buffer.append(".");
buffer.append(console()->ircContextId());
}
}
void KviChannel::applyOptions()
{
m_pUserListView->applyOptions();
m_pTopicWidget->applyOptions();
if(m_pMessageView)m_pMessageView->applyOptions();
m_pModeWidget->applyOptions();
// this applies options for IrcView and Input and forces the window to retqlayout
KviWindow::applyOptions();
}
void KviChannel::getConfigGroupName(TQString &buf)
{
buf = windowName();
}
void KviChannel::saveProperties(KviConfig *cfg)
{
KviWindow::saveProperties(cfg);
cfg->writeEntry("TopSplitter",m_pTopSplitter->sizes());
cfg->writeEntry("Splitter",m_pSplitter->sizes());
#ifdef COMPILE_USE_QT4
TQList<int> tmp = m_pVertSplitter->sizes();
KviValueList<int> tmp2;
for(TQList<int>::Iterator it = tmp.begin();it != tmp.end();++it)
tmp2.append(*it);
cfg->writeEntry("VertSplitter",m_pMessageView ? tmp2 : m_VertSplitterSizesList);
#else
cfg->writeEntry("VertSplitter",m_pMessageView ? m_pVertSplitter->sizes() : m_VertSplitterSizesList);
#endif
cfg->writeEntry("PrivateBackground",m_privateBackground);
cfg->writeEntry("DoubleView",m_pMessageView ? true : false);
if(m_pUserListView)
cfg->writeEntry("UserListHidden",m_pUserListView->isHidden());
cfg->writeEntry("ToolButtonsHidden",buttonContainer()->isHidden());
}
void KviChannel::loadProperties(KviConfig *cfg)
{
int w = width();
KviValueList<int> def;
def.append((w * 75) / 100);
def.append((w * 15) / 100);
def.append((w * 10) / 100);
m_pTopSplitter->setSizes(cfg->readIntListEntry("TopSplitter",def));
def.clear();
def.append((w * 82) / 100);
def.append((w * 18) / 100);
m_pSplitter->setSizes(cfg->readIntListEntry("Splitter",def));
//debug("SETTING DEFAULT SIZES");
def.clear();
def.append((w * 60) / 100);
def.append((w * 40) / 100);
m_VertSplitterSizesList=cfg->readIntListEntry("VertSplitter",def);
showDoubleView(cfg->readBoolEntry("DoubleView",false));
//def.append((w * 50) / 100);
//def.append((w * 50) / 100);
m_privateBackground = cfg->readPixmapEntry("PrivateBackground",KviPixmap());
if(m_privateBackground.pixmap())
{
m_pIrcView->setPrivateBackgroundPixmap(*(m_privateBackground.pixmap()));
if(m_pMessageView)m_pMessageView->setPrivateBackgroundPixmap(*(m_privateBackground.pixmap()));
}
KviWindow::loadProperties(cfg);
if(m_pUserListView)
{
bool bHidden=cfg->readBoolEntry("UserListHidden",0);
m_pUserListView->setHidden(bHidden);
resizeEvent(0);
}
if(cfg->readBoolEntry("ToolButtonsHidden",KVI_OPTION_BOOL(KviOption_boolHideWindowToolButtons))!=buttonContainer()->isHidden())
toggleToolButtons();
}
void KviChannel::showDoubleView(bool bShow)
{
if(m_pMessageView)
{
if(bShow)return;
m_pIrcView->joinMessagesFrom(m_pMessageView);
m_VertSplitterSizesList=m_pVertSplitter->sizes();
delete m_pMessageView;
m_pMessageView = 0;
if(m_pDoubleViewButton->isOn())m_pDoubleViewButton->setOn(false);
} else {
if(!bShow)return;
m_pMessageView = new KviIrcView(m_pVertSplitter,m_pFrm,this);
m_pVertSplitter->setSizes(m_VertSplitterSizesList);
//setFocusHandler(m_pInput,m_pMessageView); //socket it!
if(!(m_pDoubleViewButton->isOn()))m_pDoubleViewButton->setOn(true);
if(m_privateBackground.pixmap())
{
m_pMessageView->setPrivateBackgroundPixmap(*(m_privateBackground.pixmap()));
}
connect(m_pMessageView,TQT_SIGNAL(rightClicked()),this,TQT_SLOT(textViewRightClicked()));
m_pMessageView->setMasterView(m_pIrcView);
m_pIrcView->splitMessagesTo(m_pMessageView);
m_pMessageView->show();
}
}
void KviChannel::toggleDoubleView()
{
showDoubleView(!m_pMessageView);
}
void KviChannel::toggleListView()
{
if(m_pUserListView->isVisible())
{
m_pUserListView->hide();
if(m_pListViewButton->isOn())m_pListViewButton->setOn(false);
} else {
m_pUserListView->show();
if(!(m_pListViewButton->isOn()))m_pListViewButton->setOn(true);
}
}
void KviChannel::toggleModeEditor()
{
if(m_pModeEditor)
{
delete m_pModeEditor;
m_pModeEditor = 0;
m_pSplitter->setMinimumHeight(20); //gfgf
if(m_pModeEditorButton->isOn()) m_pModeEditorButton->setOn(false);
resizeEvent(0);
} else {
m_pModeEditor = new KviModeEditor(m_pSplitter,m_pModeEditorButton,"mode_editor",console(),m_szChannelMode,m_szChannelKey,m_szChannelLimit.ptr());
connect(m_pModeEditor,TQT_SIGNAL(setMode(const char *)),this,TQT_SLOT(setMode(const char *)));
connect(m_pModeEditor,TQT_SIGNAL(done()),this,TQT_SLOT(modeSelectorDone()));
m_pModeEditor->show();
//setFocusHandlerNoClass(m_pInput,m_pModeEditor,TQLINEEDIT_OBJECT_NAME_STRING);
if(!m_pModeEditorButton->isOn())m_pModeEditorButton->setOn(true);
}
}
void KviChannel::modeSelectorDone()
{
if(m_pModeEditor)toggleModeEditor();
}
void KviChannel::setMode(const char * mode)
{
if(!connection())return;
KviTQCString tmp = connection()->encodeText(m_szName);
connection()->sendFmtData("MODE %s %s",tmp.data(),mode);
}
void KviChannel::toggleBanEditor()
{
toggleEditor(&m_pBanEditor,&m_pBanEditorButton,
m_pBanList,'b',"ban_editor");
}
void KviChannel::toggleBanExceptionEditor()
{
toggleEditor(&m_pBanExceptionEditor,&m_pBanExceptionEditorButton,
m_pBanExceptionList,'e',"ban_exception_editor");
}
void KviChannel::toggleInviteEditor()
{
toggleEditor(&m_pInviteEditor,&m_pInviteEditorButton,
m_pInviteList,'I',"invite_exception_editor");
}
void KviChannel::toggleEditor(KviMaskEditor ** ppEd,KviWindowToolPageButton ** ppBtn,KviPointerList<KviMaskEntry> *l,char flag,const char *edName)
{
if(*ppEd)
{
delete *ppEd;
*ppEd = 0;
if(!(*ppBtn))return;
if((*ppBtn)->isOn()) (*ppBtn)->setOn(false);
} else {
bool bHasList = true;
switch(flag)
{
case 'b':
if(!(bHasList = hasBanList()))
{
m_pBanList->clear();
setSentBanListRequest();
}
break;
case 'e':
if(!(bHasList = hasBanExceptionList()))
{
m_pBanExceptionList->clear();
setSentBanExceptionListRequest();
}
break;
case 'I':
if(!(bHasList = hasInviteList()))
{
m_pInviteList->clear();
setSentInviteListRequest();
}
break;
}
if(!bHasList)
{
if(connection())
{
KviTQCString szName = connection()->encodeText(m_szName);
connection()->sendFmtData("MODE %s %c",szName.data(),flag);
}
}
*ppEd = new KviMaskEditor(m_pSplitter,*ppBtn,l,flag,edName);
connect(*ppEd,TQT_SIGNAL(removeMasks(KviMaskEditor *,KviPointerList<KviMaskEntry> *)),
this,TQT_SLOT(removeMasks(KviMaskEditor *,KviPointerList<KviMaskEntry> *)));
//setFocusHandler(m_pInput,*ppEd); //socket it!
(*ppEd)->show();
if(!(*ppBtn))return;
if(!((*ppBtn)->isOn()))(*ppBtn)->setOn(true);
}
}
void KviChannel::removeMasks(KviMaskEditor *ed,KviPointerList<KviMaskEntry> *l)
{
KviStr masks;
KviStr flags;
unsigned int count = 0;
for(KviMaskEntry * e = l->first();e;e = l->next())
{
if(masks.hasData())masks.append(' ');
masks.append(e->szMask);
flags.append(ed->flag());
count++;
if(count == connection()->serverInfo()->maxModeChanges())
{
if(connection())
{
KviTQCString szName = connection()->encodeText(m_szName);
connection()->sendFmtData("MODE %s -%s %s",szName.data(),flags.ptr(),connection()->encodeText(TQString(masks)).data());
}
flags = "";
masks = "";
count = 0;
}
}
if(masks.hasData())
{
if(connection())
{
KviTQCString szName = connection()->encodeText(m_szName);
connection()->sendFmtData("MODE %s -%s %s",szName.data(),flags.ptr(),connection()->encodeText(TQString(masks)).data());
}
}
}
TQPixmap * KviChannel::myIconPtr()
{
return g_pIconManager->getSmallIcon((m_iStateFlags & KVI_CHANNEL_STATE_DEADCHAN) ? KVI_SMALLICON_DEADCHANNEL : KVI_SMALLICON_CHANNEL);
}
void KviChannel::resizeEvent(TQResizeEvent *e)
{
#ifdef COMPILE_USE_QT4
int hght = m_pInput->heightHint();
int hght2 = m_pTopicWidget->sizeHint().height();
m_pButtonBox->setGeometry(0,0,width(),hght2);
m_pSplitter->setGeometry(0,hght2,width(),height() - (hght + hght2));
m_pInput->setGeometry(0,height() - hght,width(),hght);
#else
int hght = m_pInput->heightHint();
int hght2 = m_pButtonBox->sizeHint().height();
m_pButtonBox->setGeometry(0,0,width(),hght2);
m_pSplitter->setGeometry(0,hght2,width(),height() - (hght + hght2));
m_pInput->setGeometry(0,height() - hght,width(),hght);
#endif
}
TQSize KviChannel::sizeHint() const
{
TQSize ret(m_pSplitter->sizeHint().width(),
m_pIrcView->sizeHint().height() + m_pInput->heightHint() + m_pButtonBox->sizeHint().height());
return ret;
}
void KviChannel::setChannelMode(char mode,bool bAdd)
{
if(!m_pConsole->connection()->serverInfo()->supportedListModes().contains(mode)){
if(bAdd)
{
if(!(m_szChannelMode.contains(mode)))m_szChannelMode.append(mode);
} else {
if(m_szChannelMode.contains(mode))
{
m_szChannelMode.replace(mode,"");
}
}
updateModeLabel();
updateCaption();
}
}
void KviChannel::setChannelKey(const char * key)
{
m_szChannelKey = key;
updateModeLabel();
updateCaption();
}
void KviChannel::setChannelLimit(const char * limit)
{
m_szChannelLimit = limit;
updateModeLabel();
updateCaption();
}
void KviChannel::addHighlightedUser(const char * nick)
{
if(!m_pUserListView->findEntry(nick))return;
else
m_pTmpHighLighted->replace(nick,new TQString());
}
void KviChannel::removeHighlightedUser(const char * nick)
{
m_pTmpHighLighted->remove(nick);
}
void KviChannel::getChannelModeString(TQString &buffer)
{
buffer = m_szChannelMode;
if(!m_szChannelKey.isEmpty())buffer.append('k');
if(m_szChannelLimit.hasData())buffer.append('l');
}
void KviChannel::setDeadChan()
{
m_iStateFlags |= KVI_CHANNEL_STATE_DEADCHAN;
m_iStateFlags &= ~(KVI_CHANNEL_STATE_NOCLOSEONPART | KVI_CHANNEL_STATE_SENTSYNCWHOREQUEST);
m_pUserListView->enableUpdates(false);
m_pUserListView->partAll();
m_pUserListView->enableUpdates(true);
m_pUserListView->setUserDataBase(0);
m_pBanList->clear();
m_pBanExceptionList->clear();
m_pInviteList->clear();
m_pActionHistory->clear();
m_uActionHistoryHotActionCount = 0;
m_szChannelMode = "";
m_szChannelKey = "";
m_szChannelLimit = "";
// this should be moved to irc context!
connection()->unregisterChannel(this);
context()->registerDeadChannel(this);
setType(KVI_WINDOW_TYPE_DEADCHANNEL);
updateIcon();
updateModeLabel();
updateCaption();
}
void KviChannel::setAliveChan()
{
// Rise like phoenix!
m_iStateFlags = 0;
setType(KVI_WINDOW_TYPE_CHANNEL);
m_pUserListView->setUserDataBase(connection()->userDataBase());
m_joinTime = TQDateTime::currentDateTime();
context()->unregisterDeadChannel(this);
connection()->registerChannel(this);
// Update log file name
if(m_pIrcView->isLogging())m_pIrcView->startLogging();
updateIcon();
updateCaption();
m_pTopicWidget->reset(); // reset the topic (fixes bug #20 signaled by Klaus Weidenbach)
}
void KviChannel::getTalkingUsersStats(TQString &buffer,TQStringList &l,bool bPast)
{
if(l.count() < 1)return;
if(l.count() == 1)
{
buffer += "<b>";
buffer += l.first();
buffer += "</b>";
buffer += " ";
buffer += bPast ? __tr2qs("said something recently") : __tr2qs("is talking");
} else if(l.count() == 2)
{
buffer += "<b>";
buffer += l.first();
buffer += "</b> ";
buffer += __tr2qs("and");
buffer += " <b>";
l.remove(l.begin());
buffer += l.first();
buffer += "</b> ";
buffer += bPast ? __tr2qs("were talking recently") : __tr2qs("are talking");
} else {
buffer += "<b>";
buffer += l.first();
buffer += "</b>, <b>";
l.remove(l.begin());
buffer += l.first();
if(l.count() == 2)
{
buffer += "</b> ";
buffer += __tr2qs("and");
buffer += " <b>";
l.remove(l.begin());
buffer += l.first();
buffer += "</b>";
} else {
// (l.count() - 1) is > 1
buffer += "</b> ";
buffer += __tr2qs("and other %1 users").tqarg(l.count() - 1);
}
buffer += " ";
buffer += bPast ? __tr2qs("were talking recently") : __tr2qs("are talking");
}
}
void KviChannel::getTaskBarTipText(TQString &buffer)
{
static TQString html_bold("<b>");
static TQString html_tab("&nbsp;&nbsp;");
static TQString html_eofbold("</b> ");
static TQString p5(" (");
// p6 == p4
static TQString p7(" (");
static TQString p8(": ");
static TQString p9(")");
static TQString p10("<br>");
static TQString end_of_doc = "</table></body></html>";
static TQString end_of_fontboldrow = END_TABLE_BOLD_ROW;
static TQString start_of_row = "<tr><td>";
static TQString end_of_row = "</td></tr>";
buffer = "<html>" \
"<body>" \
"<table width=\"100%\">"\
START_TABLE_BOLD_ROW;
if(m_iStateFlags & KVI_CHANNEL_STATE_DEADCHAN)
{
buffer += __tr2qs("Dead channel");
buffer += end_of_fontboldrow;
buffer += end_of_doc;
return;
}
KviUserListViewUserStats s;
m_pUserListView->userStats(&s);
buffer += m_szPlainTextCaption;
buffer += end_of_fontboldrow;
buffer += start_of_row;
TQString op = __tr2qs("operator");
TQString ops = __tr2qs("operators");
//////////////////////
buffer += html_tab;
buffer += html_bold;
TQString num;
num.setNum(s.uActive);
buffer += num;
buffer += html_eofbold;
buffer += (s.uActive == 1 ? __tr2qs("active user") : __tr2qs("active users"));
buffer += p5;
buffer += html_bold;
num.setNum(s.uActiveOp);
buffer += num;
buffer += html_eofbold;
buffer += (s.uActiveOp == 1 ? op : ops);
buffer += p9;
/*
* #warning FIXME: What is this supposed to mean?
buffer += "<font size=\"-1\">";
buffer += p7;
buffer += __tr2qs("humanity");
buffer += p8;
buffer += html_bold;
num.setNum(s.iAvgTemperature);
buffer += num;
buffer += "</bold>";
buffer += p9;
*/
buffer += p10;
buffer += "</font>";
//////////////////////
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uHot);
buffer += num;
buffer += html_eofbold;
buffer += (s.uHot == 1 ? __tr2qs("hot user") : __tr2qs("hot users"));
buffer += p5;
buffer += html_bold;
num.setNum(s.uHotOp);
buffer += num;
buffer += html_eofbold;
buffer += (s.uHotOp == 1 ? op : ops);
buffer += p9;
/////////////
buffer += end_of_row;
buffer += start_of_row;
///////////////////
if(s.uChanOwner > 0)
{
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uChanOwner);
buffer += num;
buffer += html_eofbold;
buffer += (s.uChanOwner == 1 ? __tr2qs("channel owner") : __tr2qs("channel owners"));
buffer += p10;
}
if(s.uChanAdmin > 0)
{
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uChanAdmin);
buffer += num;
buffer += html_eofbold;
buffer += (s.uChanAdmin == 1 ? __tr2qs("channel administrator") : __tr2qs("channel administrators"));
buffer += p10;
}
if(s.uOp > 0)
{
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uOp);
buffer += num;
buffer += html_eofbold;
buffer += (s.uOp == 1 ? op : ops);
buffer += p10;
}
if(s.uHalfOp > 0)
{
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uHalfOp);
buffer += num;
buffer += html_eofbold;
buffer += (s.uHalfOp == 1 ? __tr2qs("half-operator") : __tr2qs("half-operators"));
buffer += p10;
}
if(s.uVoiced > 0)
{
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uVoiced);
buffer += num;
buffer += html_eofbold;
buffer += (s.uVoiced == 1 ? __tr2qs("voiced user") : __tr2qs("voiced users"));
buffer += p10;
}
if(s.uUserOp > 0)
{
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uUserOp);
buffer += num;
buffer += html_eofbold;
buffer += (s.uUserOp == 1 ? __tr2qs("user-operator") : __tr2qs("user-operators"));
buffer += p10;
}
buffer += html_tab;
buffer += html_bold;
num.setNum(s.uTotal);
buffer += num;
buffer += html_eofbold;
buffer += (s.uTotal == 1 ? __tr2qs("user total") : __tr2qs("users total"));
buffer += end_of_row;
KviChannelActivityStats cas;
getChannelActivityStats(&cas);
if(cas.lTalkingUsers.count() > 0)
{
if((cas.lTalkingUsers.count() < 3) && (cas.lWereTalkingUsers.count() > 0))
{
buffer += "<tr><td bgcolor=\"#E0E0E0\">";
getTalkingUsersStats(buffer,cas.lWereTalkingUsers,true);
buffer += end_of_row;
}
buffer += "<tr><td bgcolor=\"#E0E0E0\">";
getTalkingUsersStats(buffer,cas.lTalkingUsers,false);
buffer += end_of_row;
} else {
if(cas.lWereTalkingUsers.count() > 0)
{
buffer += "<tr><td bgcolor=\"#E0E0E0\">";
getTalkingUsersStats(buffer,cas.lWereTalkingUsers,true);
buffer += end_of_row;
}
}
buffer += "<tr><td bgcolor=\"#A0A0A0\"><b>";
if(cas.dActionsPerMinute < 0.1)buffer += __tr2qs("No activity");
else if(cas.dActionsPerMinute < 0.3)buffer += __tr2qs("Minimal activity");
else if(cas.dActionsPerMinute < 1.0)buffer += __tr2qs("Very low activity");
else if(cas.dActionsPerMinute < 3.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be low activity") : __tr2qs("Low activity");
else if(cas.dActionsPerMinute < 10.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be medium activity") : __tr2qs("Medium activity");
else if(cas.dActionsPerMinute < 30.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be high activity") : __tr2qs("High activity");
else if(cas.dActionsPerMinute < 60.0)buffer += cas.bStatsInaccurate ? __tr2qs("Might be very high activity") : __tr2qs("Very high activity");
else buffer += cas.bStatsInaccurate ? __tr2qs("Might be flooded with messages") : __tr2qs("Flooded with messages");
if(cas.dActionsPerMinute >= 0.1)
{
TQString num;
num.sprintf(" [%u%% ",cas.uHotActionPercent);
buffer += num;
buffer += __tr2qs("human");
buffer += "]";
}
buffer += "</b></td></tr>";
buffer += end_of_doc;
}
void KviChannel::fillCaptionBuffers()
{
static TQString begin("<nobr><font color=\"");
static TQString boldbegin("\"><b>");
static TQString endofbold("</b></font> <font color=\"");
static TQString endoffont("\">");
static TQString end("</font></nobr>");
if(!connection())
{
TQString dead = __tr2qs("[Dead channel]");
m_szNameWithUserFlag = m_szName;
m_szPlainTextCaption = m_szName;
m_szPlainTextCaption += " : ";
m_szPlainTextCaption += dead;
m_szHtmlActiveCaption = begin;
m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
m_szHtmlActiveCaption += boldbegin;
m_szHtmlActiveCaption += m_szName;
m_szHtmlActiveCaption += endofbold;
m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name();
m_szHtmlActiveCaption += endoffont;
m_szHtmlActiveCaption += dead;
m_szHtmlActiveCaption += end;
m_szHtmlInactiveCaption = begin;
m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
m_szHtmlInactiveCaption += boldbegin;
m_szHtmlInactiveCaption += m_szName;
m_szHtmlInactiveCaption += endofbold;
m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name();
m_szHtmlInactiveCaption += endoffont;
m_szHtmlInactiveCaption += dead;
m_szHtmlInactiveCaption += end;
return;
}
char uFlag = getUserFlag(connection()->currentNickName());
if(uFlag)
{
m_szNameWithUserFlag = TQChar(uFlag);
m_szNameWithUserFlag += m_szName;
} else {
m_szNameWithUserFlag = m_szName;
}
TQString szChanMode;
getChannelModeString(szChanMode);
m_szPlainTextCaption = m_szNameWithUserFlag;
if(!szChanMode.isEmpty())
{
m_szPlainTextCaption += " (+";
m_szPlainTextCaption += szChanMode;
m_szPlainTextCaption += TQChar(')');
}
TQString szNickOnServer = TQChar('[');
szNickOnServer += connection()->currentNickName();
szNickOnServer += __tr2qs(" on ");
szNickOnServer += connection()->currentServerName();
szNickOnServer += TQChar(']');
m_szPlainTextCaption += TQChar(' ');
m_szPlainTextCaption += szNickOnServer;
m_szHtmlActiveCaption = begin;
m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name();
m_szHtmlActiveCaption += boldbegin;
m_szHtmlActiveCaption += m_szNameWithUserFlag;
m_szHtmlActiveCaption += endofbold;
m_szHtmlActiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextActive2).name();
m_szHtmlActiveCaption += endoffont;
m_szHtmlActiveCaption += szNickOnServer;
m_szHtmlActiveCaption += end;
m_szHtmlInactiveCaption = begin;
m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name();
m_szHtmlInactiveCaption += boldbegin;
m_szHtmlInactiveCaption += m_szNameWithUserFlag;
m_szHtmlInactiveCaption += endofbold;
m_szHtmlInactiveCaption += KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive2).name();
m_szHtmlInactiveCaption += endoffont;
m_szHtmlInactiveCaption += szNickOnServer;
m_szHtmlInactiveCaption += end;
}
void KviChannel::ownMessage(const TQString &buffer)
{
if(!connection())return;
KviTQCString szName = connection()->encodeText(windowName());
KviTQCString szData = encodeText(buffer);
const char * d = szData.data();
if(!d)return;
#ifdef COMPILE_CRYPT_SUPPORT
if(cryptSessionInfo())
{
if(cryptSessionInfo()->bDoEncrypt)
{
if(*d != KVI_TEXT_CRYPTESCAPE)
{
KviStr encrypted;
cryptSessionInfo()->pEngine->setMaxEncryptLen(500 - szName.length());
switch(cryptSessionInfo()->pEngine->encrypt(d,encrypted))
{
case KviCryptEngine::Encrypted:
if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),encrypted.ptr()))return;
m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSGCRYPTED,
TQString(),TQString(),TQString(),buffer,KviConsole::NoNotifications);
break;
case KviCryptEngine::Encoded:
{
if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),encrypted.ptr()))return;
// ugly ,but we must redecode here
TQString szRedecoded = decodeText(encrypted.ptr());
m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,
TQString(),TQString(),TQString(),szRedecoded,KviConsole::NoNotifications);
}
break;
default: // also case KviCryptEngine::EncryptError
{
TQString szEngineError = cryptSessionInfo()->pEngine->lastError();
output(KVI_OUT_SYSTEMERROR,
__tr2qs("The crypto engine was unable to encrypt the current message (%Q): %Q, no data sent to the server"),
&buffer,&szEngineError);
}
break;
}
userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
return;
} else {
d++; //eat the escape code
TQString tmp = buffer.right(buffer.length() - 1);
if(!connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),d))return;
m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,TQString(),TQString(),TQString(),tmp,KviConsole::NoNotifications);
userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
return;
}
}
}
#endif
if(connection()->sendFmtData("PRIVMSG %s :%s",szName.data(),d))
{
m_pConsole->outputPrivmsg(this,KVI_OUT_OWNPRIVMSG,TQString(),TQString(),TQString(),buffer,KviConsole::NoNotifications);
userAction(connection()->currentNickName(),KVI_USERACTION_PRIVMSG);
}
}
void KviChannel::ownAction(const TQString &buffer)
{
if(!connection())return;
KviTQCString szName = connection()->encodeText(m_szName);
KviTQCString szData = encodeText(buffer);
const char * d = szData.data();
if(!d)return;
if(!connection()->sendFmtData("PRIVMSG %s :%cACTION %s%c",szName.data(),0x01,d,0x01))return;
if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnMeAction,this,TQString(d)))return;
TQString szBuffer = "\r!nc\r";
szBuffer += connection()->currentNickName();
szBuffer += "\r ";
szBuffer += buffer;
outputMessage(KVI_OUT_ACTION,szBuffer);
userAction(connection()->currentNickName(),KVI_USERACTION_ACTION);
}
bool KviChannel::nickChange(const TQString &oldNick,const TQString &newNick)
{
bool bWasHere = m_pUserListView->nickChange(oldNick,newNick);
if(bWasHere)channelAction(newNick,KVI_USERACTION_NICK,kvi_getUserActionTemperature(KVI_USERACTION_NICK));
return bWasHere;
}
bool KviChannel::part(const TQString &nick)
{
bool bWasHere = m_pUserListView->part(nick);
if(bWasHere)channelAction(nick,KVI_USERACTION_PART,kvi_getUserActionTemperature(KVI_USERACTION_PART));
return bWasHere;
}
#define KVI_CHANACTIVITY_LIMIT_ICE 5
#define KVI_CHANACTIVITY_LIMIT_VERYCOLD 10
#define KVI_CHANACTIVITY_LIMIT_COLD 20
#define KVI_CHANACTIVITY_LIMIT_UNDEFINED 30
#define KVI_CHANACTIVITY_LIMIT_HOT 50
#define KVI_CHANACTIVITY_LIMIT_VERYHOT 70
bool KviChannel::activityMeter(unsigned int * puActivityValue,unsigned int * puActivityTemperature)
{
fixActionHistory();
unsigned int uHotActionPercent;
double dActionsPerMinute;
if(m_pActionHistory->count() < 1)
{
// nothing is happening
uHotActionPercent = 0;
dActionsPerMinute = 0;
} else {
kvi_time_t tNow = kvi_unixTime();
KviChannelAction * a = m_pActionHistory->last();
double dSpan = (double)(tNow - a->tTime);
if(m_pActionHistory->count() < KVI_CHANNEL_ACTION_HISTORY_MAX_COUNT)
{
if(m_joinTime.secsTo(TQDateTime::currentDateTime()) < KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN)
{
// we can't exactly estimate
if(dSpan < 60.0)dSpan = 60.0;
} else {
// there are less actions at all or they have been pushed out because of the timespan
dSpan = KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN;
}
} // else the actions have been pushed out of the history because they were too much
if(dSpan > 0.0)
dActionsPerMinute = (((double)(m_pActionHistory->count())) / (dSpan)) * 60.0;
else
dActionsPerMinute = (double)(m_pActionHistory->count()); // ???
uHotActionPercent = (m_uActionHistoryHotActionCount * 100) / (m_pActionHistory->count());
}
if(dActionsPerMinute < 0.3)*puActivityValue = KVI_ACTIVITY_NONE;
else if(dActionsPerMinute < 1.0)*puActivityValue = KVI_ACTIVITY_VERYLOW;
else if(dActionsPerMinute < 4.0)*puActivityValue = KVI_ACTIVITY_LOW;
else if(dActionsPerMinute < 10.0)*puActivityValue = KVI_ACTIVITY_MEDIUM;
else if(dActionsPerMinute < 30.0)*puActivityValue = KVI_ACTIVITY_HIGH;
else *puActivityValue = KVI_ACTIVITY_VERYHIGH;
if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_ICE)*puActivityTemperature = KVI_ACTIVITY_ICE;
else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_VERYCOLD)*puActivityTemperature = KVI_ACTIVITY_VERYCOLD;
else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_COLD)*puActivityTemperature = KVI_ACTIVITY_COLD;
else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_UNDEFINED)*puActivityTemperature = KVI_ACTIVITY_UNDEFINED;
else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_HOT)*puActivityTemperature = KVI_ACTIVITY_HOT;
else if(uHotActionPercent < KVI_CHANACTIVITY_LIMIT_VERYHOT)*puActivityTemperature = KVI_ACTIVITY_VERYHOT;
else *puActivityTemperature = KVI_ACTIVITY_FIRE;
return true;
}
void KviChannel::channelAction(const TQString &nick,unsigned int uActionType,int iTemperature)
{
KviChannelAction * a = new KviChannelAction;
a->tTime = kvi_unixTime();
a->uActionType = uActionType;
a->iTemperature = iTemperature;
a->szNick = nick;
if(iTemperature > 0)m_uActionHistoryHotActionCount++;
m_pActionHistory->append(a);
fixActionHistory();
}
void KviChannel::fixActionHistory()
{
while(m_pActionHistory->count() > KVI_CHANNEL_ACTION_HISTORY_MAX_COUNT)m_pActionHistory->removeFirst();
KviChannelAction * a = m_pActionHistory->last();
if(!a)return;
kvi_time_t tMinimum = a->tTime - KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN;
KviChannelAction * act = m_pActionHistory->first();
while(act && (act->tTime < tMinimum))
{
if(act->iTemperature > 0)m_uActionHistoryHotActionCount--;
m_pActionHistory->removeFirst();
act = m_pActionHistory->first();
}
}
void KviChannel::lostUserFocus()
{
KviWindow::lostUserFocus();
if(!m_pMessageView)return;
if(m_pMessageView->hasLineMark())m_pMessageView->clearLineMark(true);
}
void KviChannel::getChannelActivityStats(KviChannelActivityStats * s)
{
fixActionHistory();
s->uActionCount = m_pActionHistory->count();
s->iAverageActionTemperature = 0;
s->uActionsInTheLastMinute = 0;
s->uHotActionCount = 0;
s->uHotActionPercent = 0;
s->bStatsInaccurate = false;
if(s->uActionCount < 1)
{
// nothing is happening
s->uLastActionTimeSpan = 0;
s->uFirstActionTimeSpan = 0;
s->dActionsPerMinute = 0;
return;
}
kvi_time_t tNow = kvi_unixTime();
KviChannelAction * a = m_pActionHistory->last();
s->uLastActionTimeSpan = tNow - a->tTime;
a = m_pActionHistory->first();
s->uFirstActionTimeSpan = tNow - a->tTime;
double dSpan = (double)s->uFirstActionTimeSpan;
if(s->uActionCount < KVI_CHANNEL_ACTION_HISTORY_MAX_COUNT)
{
if(m_joinTime.secsTo(TQDateTime::currentDateTime()) < KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN)
{
// we can't exactly estimate
s->bStatsInaccurate = true;
if(dSpan < 60.0)dSpan = 60.0;
} else {
// there are less actions at all or they have been pushed out because of the timespan
dSpan = KVI_CHANNEL_ACTION_HISTORY_MAX_TIMESPAN;
}
} // else the actions have been pushed out of the history because they were too much
if(dSpan > 0.0)
s->dActionsPerMinute = (((double)s->uActionCount) / (dSpan)) * 60.0;
else
s->dActionsPerMinute = (double)s->uActionCount; // ???
kvi_time_t tTwoMinsAgo = tNow;
tTwoMinsAgo-= 120;
tNow -= 60;
KviPointerHashTable<TQString,int> userDict;
userDict.setAutoDelete(false);
int fake;
s->lTalkingUsers.clear();
s->lWereTalkingUsers.clear();
for(a = m_pActionHistory->last();a;a = m_pActionHistory->prev())
{
if(a->tTime >= tNow)s->uActionsInTheLastMinute++;
if(a->iTemperature > 0)s->uHotActionCount++;
s->iAverageActionTemperature += a->iTemperature;
if((a->uActionType == KVI_USERACTION_PRIVMSG) ||
(a->uActionType == KVI_USERACTION_NOTICE) ||
(a->uActionType == KVI_USERACTION_ACTION))
{
if(!userDict.find(a->szNick))
{
if(isOn(a->szNick.ascii()))
{
if(a->tTime >= tTwoMinsAgo)s->lTalkingUsers.append(a->szNick);
else s->lWereTalkingUsers.append(a->szNick);
userDict.insert(a->szNick,&fake);
}
}
}
}
s->iAverageActionTemperature = s->iAverageActionTemperature / (int)s->uActionCount;
s->uHotActionPercent = (s->uHotActionCount * 100) / s->uActionCount;
}
void KviChannel::userAction(const TQString &nick,const TQString &user,const TQString &host,unsigned int uActionType)
{
int iTemperature = kvi_getUserActionTemperature(uActionType);
channelAction(nick,uActionType,iTemperature);
m_pUserListView->userAction(nick,user,host,iTemperature);
}
void KviChannel::userAction(const TQString &nick,unsigned int uActionType)
{
int iTemperature = kvi_getUserActionTemperature(uActionType);
channelAction(nick,uActionType,iTemperature);
m_pUserListView->userAction(nick,iTemperature);
}
void KviChannel::userAction(KviIrcMask * user,unsigned int uActionType)
{
int iTemperature = kvi_getUserActionTemperature(uActionType);
channelAction(user->nick(),uActionType,iTemperature);
m_pUserListView->userAction(user,iTemperature);
}
void KviChannel::topicSelected(const TQString & topic)
{
if(!connection())return;
KviTQCString szEncoded = encodeText(topic);
KviTQCString szName = connection()->encodeText(m_szName);
connection()->sendFmtData("TOPIC %s :%s",szName.data(),szEncoded.length() ? szEncoded.data() : "");
}
void KviChannel::closeEvent(TQCloseEvent *e)
{
if((m_iStateFlags & KVI_CHANNEL_STATE_SENTPART) || (m_iStateFlags & KVI_CHANNEL_STATE_DEADCHAN) || !(m_pConsole->isConnected()))
{
m_pContext->unregisterDeadChannel(this);
KviWindow::closeEvent(e);
} else {
e->ignore();
// FIXME: #warning "THIS PART SHOULD BECOME A COMMAND /PART $option()..so the identifiers are parsed"
if(connection())
{
TQString tmp = KVI_OPTION_STRING(KviOption_stringPartMessage);
tmp.replace(";","\\;");
tmp.replace("\n"," ");
KviKvsVariant vRet;
if(KviKvsScript::evaluate(tmp,this,0,&vRet))vRet.asString(tmp);
KviTQCString dat = encodeText(tmp);
partMessageSent();
KviTQCString szName = connection()->encodeText(m_szName);
connection()->sendFmtData("PART %s :%s",szName.data(),dat.data() ? dat.data() : "");
// be sure to not reference ourselves here.. we could be disconnected!
} else {
partMessageSent(); // huh ?
}
}
}
void KviChannel::partMessageSent(bool bCloseOnPart,bool bShowMessage)
{
m_iStateFlags |= KVI_CHANNEL_STATE_SENTPART;
if(!bCloseOnPart)m_iStateFlags |= KVI_CHANNEL_STATE_NOCLOSEONPART;
if(bShowMessage)outputNoFmt(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Sent part request, waiting for reply..."));
}
#define IS_FNC(__name,__ulvname) \
bool KviChannel::__name(bool bAtLeast) \
{ \
if(!connection())return false; \
return m_pUserListView->__ulvname(connection()->currentNickName(),bAtLeast); \
}
IS_FNC(isMeChanOwner,isChanOwner)
IS_FNC(isMeChanAdmin,isChanAdmin)
IS_FNC(isMeOp,isOp)
IS_FNC(isMeVoice,isVoice)
IS_FNC(isMeHalfOp,isHalfOp)
IS_FNC(isMeUserOp,isUserOp)
int KviChannel::myFlags()
{
if(!connection())return 0;
return m_pUserListView->flags(connection()->currentNickName());
}
void KviChannel::setMask(char flag, const TQString &mask,bool bAdd,const TQString &setBy,unsigned int setAt)
{
if(!connection())return;
KviPointerList<KviMaskEntry> * list = m_pBanList;
KviMaskEditor * editor = m_pBanEditor;
switch(flag)
{
case 'b':
m_iStateFlags ^= KVI_CHANNEL_STATE_HAVEBANLIST;
break;
case 'e':
m_iStateFlags ^= KVI_CHANNEL_STATE_HAVEBANEXCEPTIONLIST;
list = m_pBanExceptionList;
editor = m_pBanExceptionEditor;
break;
case 'I':
m_iStateFlags ^= KVI_CHANNEL_STATE_HAVEINVITELIST;
list = m_pInviteList;
editor = m_pInviteEditor;
break;
}
internalMask(mask,bAdd,setBy,setAt,list,&editor);
m_pUserListView->setMaskEntries(flag,(int)list->count());
}
void KviChannel::internalMask(const TQString &mask,bool bAdd,const TQString &setBy,unsigned int setAt,KviPointerList<KviMaskEntry> *l,KviMaskEditor **ppEd)
{
KviMaskEntry * e = 0;
if(bAdd)
{
for(e = l->first();e;e = l->next())
{
if(KviTQString::equalCI(e->szMask,mask))return; //already there
}
e = new KviMaskEntry;
e->szMask = mask;
e->szSetBy = (!setBy.isEmpty()) ? setBy : __tr2qs("(Unknown)");
e->uSetAt = setAt;
l->append(e);
if(*ppEd)(*ppEd)->addMask(e);
} else {
for(e = l->first();e;e = l->next())
{
if(KviTQString::equalCI(e->szMask,mask))break;
}
if(e)
{
if(*ppEd)(*ppEd)->removeMask(e);
l->removeRef(e);
}
}
}
void KviChannel::updateModeLabel()
{
TQString tmp = m_szChannelMode;
TQString tip = __tr2qs("<b>Channel mode:</b>");
//const char * aux = m_szChannelMode.utf8().data(); leaks memory and will not work with getChannelModeDescription() (can channel modes be multibyte ?)
KviStr mod = m_szChannelMode;
const char * aux = mod.ptr();
while(*aux)
{
KviTQString::appendFormatted(tip,"<br>%c: %Q",*aux,&(m_pConsole->connection()->serverInfo()->getChannelModeDescription(*aux)));
++aux;
}
if(!m_szChannelKey.isEmpty())
{
if(!tmp.isEmpty())tmp.append(' ');
KviTQString::appendFormatted(tmp,"k:%s",m_szChannelKey.utf8().data());
KviTQString::appendFormatted(tip,__tr2qs("<br><b>Key:</b> %s"),m_szChannelKey.utf8().data());
}
if(m_szChannelLimit.hasData())
{
if(!tmp.isEmpty())tmp.append(' ');
KviTQString::appendFormatted(tmp,"l:%s",m_szChannelLimit.ptr());
KviTQString::appendFormatted(tip,__tr2qs("<br><b>Limit:</b> %s"),m_szChannelLimit.ptr());
}
m_pModeWidget->refreshModes();
KviTalToolTip::remove(m_pModeWidget);
KviTalToolTip::add(m_pModeWidget,tip);
}
/*
void KviChannel::outputMessage(int msg_type,const char *format,...)
{
kvi_wchar_t txt_ptr[512]; //It should be enough for all outputs...
kvi_va_list list;
kvi_va_start(list,format);
if(kvi_wvsnprintcf(txt_ptr,512,format,list) < 0){
//Just in case...
kvi_va_end(list);
int len = 512;
kvi_wchar_t *long_txt_ptr = 0;
int result;
do{
len += 512;
//first time long_txt_ptr == 0 so it is equivalent to malloc
//At least the man page says that...
long_txt_ptr = (kvi_wchar_t *)kvi_realloc((void *)long_txt_ptr,len * sizeof(kvi_wchar_t));
kvi_va_start(list,format);
result = kvi_wvsnprintcf(long_txt_ptr,len,format,list);
kvi_va_end(list);
} while(result < 0);
internalOutput(m_pMessageView ? m_pMessageView : m_pIrcView,msg_type,long_txt_ptr);
kvi_free((void *)long_txt_ptr);
} else {
//Succesful vsnprintf
kvi_va_end(list);
internalOutput(m_pMessageView ? m_pMessageView : m_pIrcView,msg_type,txt_ptr);
}
}
*/
void KviChannel::outputMessage(int msg_type,const TQString &msg)
{
TQString szBuf(msg);
preprocessMessage(szBuf);
const TQChar * pC = KviTQString::nullTerminatedArray(szBuf);
if(!pC)return;
internalOutput(m_pMessageView ? m_pMessageView : m_pIrcView,msg_type,(const kvi_wchar_t *)pC);
}
void KviChannel::checkChannelSync()
{
if(m_iStateFlags & KVI_CHANNEL_STATE_SYNCHRONIZED)return;
if(m_iStateFlags & KVI_CHANNEL_STATE_SENTWHOREQUEST)
{
if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEWHOLIST))return;
}
if(m_iStateFlags & KVI_CHANNEL_STATE_SENTBANLISTREQUEST)
{
if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEBANLIST))return;
}
if(m_iStateFlags & KVI_CHANNEL_STATE_SENTBANEXCEPTIONLISTREQUEST)
{
if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEBANEXCEPTIONLIST))return;
}
if(m_iStateFlags & KVI_CHANNEL_STATE_SENTINVITELISTREQUEST)
{
if(!(m_iStateFlags & KVI_CHANNEL_STATE_HAVEINVITELIST))return;
}
m_iStateFlags |= KVI_CHANNEL_STATE_SYNCHRONIZED;
// we already have all the spontaneous server replies
// (so probably mode, topic (or no topic is set),names)
// we have already received the I and e lists (if requested)
kvs_int_t iSyncTime = m_joinTime.time().msecsTo(TQTime::currentTime());
if(iSyncTime < 0)iSyncTime += 86400000;
bool bStop = KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnChannelSync,this,iSyncTime);
if(!bStop && KVI_OPTION_BOOL(KviOption_boolShowChannelSyncTime))
{
output(KVI_OUT_SYSTEMMESSAGE,__tr2qs("Channel synchronized in %d.%d seconds"),iSyncTime / 1000,iSyncTime % 1000);
}
}
bool KviChannel::eventFilter(TQObject * o, TQEvent * e)
{
if(e->type() == TQEvent::FocusOut && TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(m_pTopicWidget) && \
m_pTopicWidget->isVisible())
m_pTopicWidget->deactivate();
return KviWindow::eventFilter(o, e);
}
void KviChannel::preprocessMessage(TQString & szMessage)
{
TQStringList strings = TQStringList::split(" ",szMessage, TRUE);
for ( TQStringList::Iterator it = strings.begin(); it != strings.end(); ++it ) {
if((*it).contains('\r')) continue;
TQString tmp = KviMircCntrl::stripControlBytes(*it);
if( findEntry(*it) ) *it=TQString("\r!n\r%1\r").tqarg(*it);
if(m_pConsole)
if(m_pConsole->connection())
if(m_pConsole->connection()->serverInfo()->supportedChannelTypes().contains(tmp[0]))
if((*it)==tmp)
*it=TQString("\r!c\r%1\r").tqarg(*it);
else
*it=TQString("\r!c%1\r%2\r").tqarg(tmp).tqarg(*it);
}
szMessage=strings.join(" ");
}
void KviChannel::unhighlight()
{
if(!m_pTaskBarItem)return;
m_pTaskBarItem->unhighlight();
}
#include "kvi_channel.moc"