|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
// File : kvi_userlistview.cpp
|
|
|
|
// Creation date : Tue Aug 1 2000 21:05:22 by Szymon Stefanek
|
|
|
|
//
|
|
|
|
// This file is part of the KVirc irc client distribution
|
|
|
|
// Copyright (C) 2000-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.
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#define __KVIRC__
|
|
|
|
#define _KVI_USERLISTVIEW_CPP_
|
|
|
|
|
|
|
|
#include "kvi_debug.h"
|
|
|
|
#include "kvi_userlistview.h"
|
|
|
|
#include "kvi_settings.h"
|
|
|
|
#include "kvi_locale.h"
|
|
|
|
#include "kvi_options.h"
|
|
|
|
#include "kvi_defaults.h"
|
|
|
|
#include "kvi_iconmanager.h"
|
|
|
|
#include "kvi_regusersdb.h"
|
|
|
|
#include "kvi_parameterlist.h"
|
|
|
|
#include "kvi_window.h"
|
|
|
|
#include "kvi_console.h"
|
|
|
|
#include "kvi_app.h"
|
|
|
|
#include "kvi_useraction.h"
|
|
|
|
#include "kvi_qstring.h"
|
|
|
|
#include "kvi_frame.h"
|
|
|
|
#include "kvi_mdimanager.h"
|
|
|
|
#include "kvi_kvs_eventtriggers.h"
|
|
|
|
#include "kvi_toolwindows_container.h"
|
|
|
|
#include "kvi_doublebuffer.h"
|
|
|
|
#include "kvi_stringconversion.h"
|
|
|
|
#include "kvi_ircconnection.h"
|
|
|
|
#include "kvi_ircconnectionserverinfo.h"
|
|
|
|
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqscrollbar.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqfontmetrics.h>
|
|
|
|
#include <tqdatetime.h>
|
|
|
|
#include <tqmime.h>
|
|
|
|
#include "kvi_styled_controls.h"
|
|
|
|
#include <tqevent.h>
|
|
|
|
|
|
|
|
#ifdef COMPILE_PSEUDO_TRANSPARENCY
|
|
|
|
extern TQPixmap * g_pShadedChildGlobalDesktopBackground;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// kvi_app.cpp (loaded and destroyed by KviIconManager)
|
|
|
|
extern TQPixmap * g_pUserChanStatePixmap;
|
|
|
|
|
|
|
|
// Yet another really complex widget :)
|
|
|
|
|
|
|
|
#define KVI_USERLIST_BORDER_WIDTH 2
|
|
|
|
|
|
|
|
// FIXME: #warning "Button to show/hide avatars"
|
|
|
|
// FIXME: #warning "We want to be able to navigate the list with the keyboard!"
|
|
|
|
|
|
|
|
KviUserListToolTip::KviUserListToolTip(KviUserListView * v,KviUserListViewArea * a)
|
|
|
|
: KviTalToolTip(a)
|
|
|
|
{
|
|
|
|
m_pListView = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
KviUserListToolTip::~KviUserListToolTip()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListToolTip::maybeTip(const TQPoint &pnt)
|
|
|
|
{
|
|
|
|
m_pListView->maybeTip(this,pnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KviUserListEntry::KviUserListEntry(KviUserListView * parent,const TQString &nick,
|
|
|
|
KviIrcUserEntry * e,short int iFlags,bool bJoinTimeUnknown)
|
|
|
|
{
|
|
|
|
m_pListView = parent;
|
|
|
|
m_szNick = nick;
|
|
|
|
m_pGlobalData = e;
|
|
|
|
m_iFlags = iFlags;
|
|
|
|
m_lastActionTime = (kvi_time_t)0;
|
|
|
|
m_joinTime = bJoinTimeUnknown ? (kvi_time_t)0 : kvi_unixTime();
|
|
|
|
m_iTemperature = bJoinTimeUnknown ? 0 : KVI_USERACTION_JOIN;
|
|
|
|
|
|
|
|
m_bSelected = false;
|
|
|
|
|
|
|
|
recalcSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
KviUserListEntry::~KviUserListEntry()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviUserListEntry::color(TQColor& color)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: Unused ?
|
|
|
|
//
|
|
|
|
KviRegisteredUser* pRegisteredUser=m_pListView->m_pKviWindow->connection()->userDataBase()->registeredUser(m_szNick);
|
|
|
|
if(pRegisteredUser)
|
|
|
|
{
|
|
|
|
if(m_pListView->m_pKviWindow->connection()->userDataBase()->haveCustomColor(m_szNick))
|
|
|
|
{
|
|
|
|
color=*(m_pListView->m_pKviWindow->connection()->userDataBase()->customColor(m_szNick));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolUseDifferentColorForOwnNick) && m_pListView->m_pKviWindow->connection())
|
|
|
|
{
|
|
|
|
if(m_szNick==m_pListView->m_pKviWindow->connection()->currentNickName())
|
|
|
|
{
|
|
|
|
color = KVI_OPTION_COLOR(KviOption_colorUserListViewOwnForeground);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(m_iFlags == 0)
|
|
|
|
{
|
|
|
|
color=KVI_OPTION_COLOR(KviOption_colorUserListViewNormalForeground);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
color = KVI_OPTION_COLOR((m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
|
|
|
|
KviOption_colorUserListViewChanOwnerForeground : ((m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
|
|
|
|
KviOption_colorUserListViewChanAdminForeground : ((m_iFlags & KVI_USERFLAG_OP) ? \
|
|
|
|
KviOption_colorUserListViewOpForeground : ((m_iFlags & KVI_USERFLAG_HALFOP) ? \
|
|
|
|
KviOption_colorUserListViewHalfOpForeground : ((m_iFlags & KVI_USERFLAG_VOICE) ? \
|
|
|
|
KviOption_colorUserListViewVoiceForeground : KviOption_colorUserListViewUserOpForeground)))));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListEntry::recalcSize()
|
|
|
|
{
|
|
|
|
KviAvatar * av = m_pGlobalData->avatar();
|
|
|
|
m_iHeight = m_pListView->m_iFontHeight;
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolShowUserChannelIcons) && (m_iHeight < 20))m_iHeight = 20;
|
|
|
|
|
|
|
|
if(!KVI_OPTION_BOOL(KviOption_boolDisableAvatars))//G&N 2005
|
|
|
|
{
|
|
|
|
if(av)
|
|
|
|
{
|
|
|
|
if( KVI_OPTION_BOOL(KviOption_boolScaleAvatars) &&
|
|
|
|
(
|
|
|
|
!KVI_OPTION_BOOL(KviOption_boolDoNotStretchAvatars) ||
|
|
|
|
(av->pixmap()->width() > KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth)) ||
|
|
|
|
(av->pixmap()->height() > KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
TQPixmap * pix = av->scaledPixmap(KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth), KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight));
|
|
|
|
|
|
|
|
m_iHeight += pix->height();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_iHeight += av->pixmap()->height();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_iHeight += 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KviUserListView::KviUserListView(TQWidget * parent,KviWindowToolPageButton* button,KviIrcUserDataBase * db,KviWindow * pWnd,int dictSize,const TQString & label_text,const char * name)
|
|
|
|
: KviWindowToolWidget(parent,button)
|
|
|
|
{
|
|
|
|
setAutoDelete(0);
|
|
|
|
m_pKviWindow = pWnd;
|
|
|
|
m_pEntryDict = new KviPointerHashTable<TQString,KviUserListEntry>(dictSize,false);
|
|
|
|
m_pEntryDict->setAutoDelete(true);
|
|
|
|
|
|
|
|
m_pUsersLabel = new TQLabel(this,"userslabel");
|
|
|
|
KviTalToolTip::add(m_pUsersLabel,label_text);
|
|
|
|
|
|
|
|
m_pViewArea = new KviUserListViewArea(this);
|
|
|
|
m_pToolTip = new KviUserListToolTip(this,m_pViewArea);
|
|
|
|
m_pTopItem = 0;
|
|
|
|
m_pHeadItem = 0;
|
|
|
|
m_pTailItem = 0;
|
|
|
|
m_iOpCount = 0;
|
|
|
|
m_iHalfOpCount = 0;
|
|
|
|
m_iVoiceCount = 0;
|
|
|
|
m_iChanAdminCount = 0;
|
|
|
|
m_iChanOwnerCount = 0;
|
|
|
|
m_iUserOpCount = 0;
|
|
|
|
m_pIrcUserDataBase = db;
|
|
|
|
m_iTotalHeight = 0;
|
|
|
|
m_ibEntries = 0;
|
|
|
|
m_ieEntries = 0;
|
|
|
|
m_iIEntries = 0;
|
|
|
|
m_iSelectedCount = 0;
|
|
|
|
// setBackgroundMode(TQWidget::NoBackground);
|
|
|
|
applyOptions();
|
|
|
|
registerSelf();
|
|
|
|
}
|
|
|
|
|
|
|
|
KviUserListView::~KviUserListView()
|
|
|
|
{
|
|
|
|
removeAllEntries();
|
|
|
|
delete m_pEntryDict;
|
|
|
|
delete m_pToolTip;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::emitRightClick()
|
|
|
|
{
|
|
|
|
int ev = -1;
|
|
|
|
switch(m_pKviWindow->type())
|
|
|
|
{
|
|
|
|
case KVI_WINDOW_TYPE_CHANNEL: ev = KviEvent_OnChannelNickPopupRequest; break;
|
|
|
|
case KVI_WINDOW_TYPE_TQUERY: ev = KviEvent_OnQueryNickPopupRequest; break;
|
|
|
|
case KVI_WINDOW_TYPE_CONSOLE: ev = KviEvent_OnNotifyListPopupRequest; break;
|
|
|
|
default: ev = KviEvent_OnNickLinkPopupRequest; break; // this should actually never happen
|
|
|
|
}
|
|
|
|
if(ev > -1)
|
|
|
|
{
|
|
|
|
if(KviKvsEventManager::instance()->hasAppHandlers(ev))
|
|
|
|
{
|
|
|
|
TQString nicks;
|
|
|
|
appendSelectedNicknames(nicks);
|
|
|
|
KviKvsVariantList vList;
|
|
|
|
vList.append(nicks);
|
|
|
|
KviKvsEventManager::instance()->trigger(ev,m_pKviWindow,&vList);
|
|
|
|
} else {
|
|
|
|
g_pApp->checkSuggestRestoreDefaultScript();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::emitDoubleClick()
|
|
|
|
{
|
|
|
|
int ev = -1;
|
|
|
|
switch(m_pKviWindow->type())
|
|
|
|
{
|
|
|
|
case KVI_WINDOW_TYPE_CHANNEL: ev = KviEvent_OnChannelNickDefaultActionRequest; break;
|
|
|
|
case KVI_WINDOW_TYPE_TQUERY: ev = KviEvent_OnQueryNickDefaultActionRequest; break;
|
|
|
|
case KVI_WINDOW_TYPE_CONSOLE: ev = KviEvent_OnNotifyListDefaultActionRequest; break;
|
|
|
|
default: ev = KviEvent_OnNickLinkDefaultActionRequest; break; // this should actually never happen
|
|
|
|
}
|
|
|
|
if(ev > -1)
|
|
|
|
{
|
|
|
|
if(KviKvsEventManager::instance()->hasAppHandlers(ev))
|
|
|
|
{
|
|
|
|
TQString nicks;
|
|
|
|
appendSelectedNicknames(nicks);
|
|
|
|
KviKvsVariantList vList;
|
|
|
|
vList.append(nicks);
|
|
|
|
KviKvsEventManager::instance()->trigger(ev,m_pKviWindow,&vList);
|
|
|
|
} else {
|
|
|
|
g_pApp->checkSuggestRestoreDefaultScript();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::updateScrollBarRange()
|
|
|
|
{
|
|
|
|
int max = m_iTotalHeight - (m_pViewArea->height() - (KVI_USERLIST_BORDER_WIDTH * 2));
|
|
|
|
m_pViewArea->m_pScrollBar->setRange(0,max > 0 ? max : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::applyOptions()
|
|
|
|
{
|
|
|
|
/* if(!KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel)){
|
|
|
|
m_pUsersLabel->hide();
|
|
|
|
m_pViewArea->setGeometry(0,0,width(),height());
|
|
|
|
}
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel)){
|
|
|
|
m_pUsersLabel->show();
|
|
|
|
updateUsersLabel();
|
|
|
|
}*/
|
|
|
|
setFont(KVI_OPTION_FONT(KviOption_fontUserListView));
|
|
|
|
TQFontMetrics fm(KVI_OPTION_FONT(KviOption_fontUserListView));
|
|
|
|
m_iFontHeight = fm.lineSpacing();
|
|
|
|
KviUserListEntry * e = m_pHeadItem;
|
|
|
|
m_iTotalHeight = 0;
|
|
|
|
while(e)
|
|
|
|
{
|
|
|
|
e->recalcSize();
|
|
|
|
m_iTotalHeight += e->m_iHeight;
|
|
|
|
e = e->m_pNext;
|
|
|
|
}
|
|
|
|
updateScrollBarRange();
|
|
|
|
m_pUsersLabel->setFont(KVI_OPTION_FONT(KviOption_fontUserListView));
|
|
|
|
setMinimumWidth(100);
|
|
|
|
resizeEvent(0); // this will call update() too
|
|
|
|
repaint();
|
|
|
|
}
|
|
|
|
void KviUserListView::updateArea()
|
|
|
|
{
|
|
|
|
bool bEnable = m_pViewArea->isUpdatesEnabled();
|
|
|
|
if(!bEnable) m_pViewArea->setUpdatesEnabled(true);
|
|
|
|
triggerUpdate();
|
|
|
|
if(!bEnable) m_pViewArea->setUpdatesEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::enableUpdates(bool bEnable)
|
|
|
|
{
|
|
|
|
m_pViewArea->setUpdatesEnabled(bEnable);
|
|
|
|
if(bEnable)triggerUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::setMaskEntries(char type, int num)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 'b':
|
|
|
|
m_ibEntries = num;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
m_ieEntries = num;
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
|
|
m_iIEntries = num;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
updateUsersLabel();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::completeNickBashLike(const TQString &begin,KviPointerList<TQString> *l,bool bAppendMask)
|
|
|
|
{
|
|
|
|
KviUserListEntry * entry = m_pHeadItem;
|
|
|
|
|
|
|
|
while(entry)
|
|
|
|
{
|
|
|
|
if(KviTQString::equalCIN(begin,entry->m_szNick,begin.length()))
|
|
|
|
{
|
|
|
|
if(bAppendMask)
|
|
|
|
{
|
|
|
|
TQString * s = new TQString();
|
|
|
|
KviTQString::sprintf(*s,"%Q!%Q@%Q",&(entry->m_szNick),&(entry->m_pGlobalData->user()),&(entry->m_pGlobalData->host()));
|
|
|
|
l->append(s);
|
|
|
|
} else
|
|
|
|
l->append(new TQString(entry->m_szNick));
|
|
|
|
}
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviUserListView::completeNickStandard(const TQString &begin,const TQString &skipAfter,TQString &buffer,bool bAppendMask)
|
|
|
|
{
|
|
|
|
KviUserListEntry * entry = m_pHeadItem;
|
|
|
|
|
|
|
|
if(!skipAfter.isEmpty())
|
|
|
|
{
|
|
|
|
while(entry)
|
|
|
|
{
|
|
|
|
if(KviTQString::equalCI(skipAfter,entry->m_szNick))
|
|
|
|
{
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: completion should skip my own nick or place it as last entry in the chain (?)
|
|
|
|
|
|
|
|
// if(KviConsole * c = m_pKviWindow->console())
|
|
|
|
// {
|
|
|
|
// if(kvi_strEqualCI(entry->m_szNick.ptr(),c->currentNickName())
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Ok...now the real completion
|
|
|
|
while(entry)
|
|
|
|
{
|
|
|
|
if(entry->m_szNick.length() >= begin.length())
|
|
|
|
{
|
|
|
|
int result = KviTQString::cmpCIN(begin,entry->m_szNick,begin.length());
|
|
|
|
if(result == 0)
|
|
|
|
{
|
|
|
|
// This is ok.
|
|
|
|
buffer = entry->m_szNick;
|
|
|
|
if(bAppendMask)
|
|
|
|
{
|
|
|
|
buffer += entry->m_pGlobalData->user();
|
|
|
|
buffer += entry->m_pGlobalData->host();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else if(result < 0)
|
|
|
|
{
|
|
|
|
// No match...begin is lower than the current entry
|
|
|
|
if(entry->m_iFlags == 0)return false;
|
|
|
|
else {
|
|
|
|
int flags = entry->m_iFlags;
|
|
|
|
// skip the current flag
|
|
|
|
while(entry)
|
|
|
|
{
|
|
|
|
if(entry->m_iFlags != flags)break;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviUserListView::insertUserEntry(const TQString &nick,KviUserListEntry * e)
|
|
|
|
{
|
|
|
|
// Complex insertion task :)
|
|
|
|
|
|
|
|
m_pEntryDict->insert(nick,e);
|
|
|
|
m_iTotalHeight += e->m_iHeight;
|
|
|
|
|
|
|
|
bool bGotTopItem = false;
|
|
|
|
|
|
|
|
int flag = 0;
|
|
|
|
if(e->m_iFlags != 0)
|
|
|
|
{
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_USEROP)
|
|
|
|
{
|
|
|
|
flag = KVI_USERFLAG_USEROP;
|
|
|
|
m_iUserOpCount++;
|
|
|
|
}
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_VOICE)
|
|
|
|
{
|
|
|
|
flag = KVI_USERFLAG_VOICE;
|
|
|
|
m_iVoiceCount++;
|
|
|
|
}
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_HALFOP)
|
|
|
|
{
|
|
|
|
flag = KVI_USERFLAG_HALFOP;
|
|
|
|
m_iHalfOpCount++;
|
|
|
|
}
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_OP)
|
|
|
|
{
|
|
|
|
flag = KVI_USERFLAG_OP;
|
|
|
|
m_iOpCount++;
|
|
|
|
}
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_CHANADMIN)
|
|
|
|
{
|
|
|
|
flag = KVI_USERFLAG_CHANADMIN;
|
|
|
|
m_iChanAdminCount++;
|
|
|
|
}
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_CHANOWNER)
|
|
|
|
{
|
|
|
|
flag = KVI_USERFLAG_CHANOWNER;
|
|
|
|
m_iChanOwnerCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(m_pHeadItem)
|
|
|
|
{
|
|
|
|
KviUserListEntry * entry = m_pHeadItem;
|
|
|
|
|
|
|
|
if(!(e->m_iFlags & KVI_USERFLAG_CHANOWNER))
|
|
|
|
{
|
|
|
|
// the new user is not a channel owner...
|
|
|
|
// skip the channel owners
|
|
|
|
while(entry && (entry->m_iFlags & KVI_USERFLAG_CHANOWNER))
|
|
|
|
{
|
|
|
|
if(entry == m_pTopItem)bGotTopItem = true;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(e->m_iFlags & KVI_USERFLAG_CHANADMIN))
|
|
|
|
{
|
|
|
|
// the new user is not a channel admin...
|
|
|
|
// skip chan admins
|
|
|
|
while(entry && (entry->m_iFlags & KVI_USERFLAG_CHANADMIN))
|
|
|
|
{
|
|
|
|
if(entry == m_pTopItem)bGotTopItem = true;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
// is operator ?
|
|
|
|
if(!(e->m_iFlags & KVI_USERFLAG_OP))
|
|
|
|
{
|
|
|
|
// the new user is not an op...
|
|
|
|
// skip ops
|
|
|
|
while(entry && (entry->m_iFlags & KVI_USERFLAG_OP))
|
|
|
|
{
|
|
|
|
if(entry == m_pTopItem)bGotTopItem = true;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
// is half oped ?
|
|
|
|
if(!(e->m_iFlags & KVI_USERFLAG_HALFOP))
|
|
|
|
{
|
|
|
|
// nope , skip halfops
|
|
|
|
while(entry && (entry->m_iFlags & KVI_USERFLAG_HALFOP))
|
|
|
|
{
|
|
|
|
if(entry == m_pTopItem)bGotTopItem = true;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
// is voiced ?
|
|
|
|
if(!(e->m_iFlags & KVI_USERFLAG_VOICE))
|
|
|
|
{
|
|
|
|
// nope , not voiced so skip voiced users
|
|
|
|
while(entry && (entry->m_iFlags & KVI_USERFLAG_VOICE))
|
|
|
|
{
|
|
|
|
if(entry == m_pTopItem)bGotTopItem = true;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
// is userop'd?
|
|
|
|
if(!(e->m_iFlags & KVI_USERFLAG_USEROP))
|
|
|
|
{
|
|
|
|
// nope , skip userops
|
|
|
|
while(entry && (entry->m_iFlags & KVI_USERFLAG_USEROP))
|
|
|
|
{
|
|
|
|
if(entry == m_pTopItem)bGotTopItem = true;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
} // else is userop, ops, halfops, and voiced are skipped
|
|
|
|
} // else it is voiced , ops and halfops are skipped
|
|
|
|
} // else it is halfop , ops are skipped
|
|
|
|
} // else it is op , chan admins are skipped
|
|
|
|
} // else it is chan admin , chan owners are skipped
|
|
|
|
} // else it is chan owner, so nothing to skip: the chan owners are first in the list
|
|
|
|
|
|
|
|
// now strcmp within the current user-flag group...
|
|
|
|
while(entry && (KviTQString::cmpCI(entry->m_szNick,e->m_szNick) < 0) &&
|
|
|
|
((entry->m_iFlags & flag) || (flag == 0)))
|
|
|
|
{
|
|
|
|
if(entry == m_pTopItem)bGotTopItem = true;
|
|
|
|
entry = entry->m_pNext;
|
|
|
|
}
|
|
|
|
if(entry)
|
|
|
|
{
|
|
|
|
// inserting
|
|
|
|
e->m_pNext = entry;
|
|
|
|
e->m_pPrev = entry->m_pPrev;
|
|
|
|
if(e->m_pPrev == 0)m_pHeadItem = e;
|
|
|
|
else e->m_pPrev->m_pNext = e;
|
|
|
|
entry->m_pPrev = e;
|
|
|
|
// need to adjust the item offsets now...
|
|
|
|
// ok... if we're inserting something after
|
|
|
|
// the top item, we move everything down
|
|
|
|
// otherwise we only update the scrollbar values
|
|
|
|
if(!bGotTopItem)
|
|
|
|
{
|
|
|
|
// Inserting BEFORE the top item
|
|
|
|
if((e == m_pHeadItem) && (m_pTopItem == e->m_pNext) && (m_pViewArea->m_iTopItemOffset == 0))
|
|
|
|
{
|
|
|
|
// special case...the top item is the head one
|
|
|
|
// and it has zero offset...change the top item too
|
|
|
|
m_pTopItem = e;
|
|
|
|
triggerUpdate();
|
|
|
|
} else {
|
|
|
|
// invisible insertion
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = true;
|
|
|
|
m_pViewArea->m_iLastScrollBarVal += e->m_iHeight;
|
|
|
|
updateScrollBarRange();
|
|
|
|
m_pViewArea->m_pScrollBar->setValue(m_pViewArea->m_iLastScrollBarVal);
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = false;
|
|
|
|
updateUsersLabel();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
triggerUpdate();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// appending to the end (may be visible)
|
|
|
|
m_pTailItem->m_pNext = e;
|
|
|
|
e->m_pNext = 0;
|
|
|
|
e->m_pPrev = m_pTailItem;
|
|
|
|
m_pTailItem = e;
|
|
|
|
triggerUpdate();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// There were no items (is rather visible)
|
|
|
|
m_pHeadItem = e;
|
|
|
|
m_pTailItem = e;
|
|
|
|
m_pTopItem = e;
|
|
|
|
e->m_pNext = 0;
|
|
|
|
e->m_pPrev = 0;
|
|
|
|
triggerUpdate();
|
|
|
|
}
|
|
|
|
if(e->m_bSelected)
|
|
|
|
{
|
|
|
|
m_iSelectedCount++;
|
|
|
|
if(m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pKviWindow,true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KviUserListEntry * KviUserListView::join(const TQString &nick,const TQString &user,
|
|
|
|
const TQString &host,int iFlags)
|
|
|
|
{
|
|
|
|
// Ok..an user joins the channel
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(nick);
|
|
|
|
if(it == 0)
|
|
|
|
{
|
|
|
|
// add an entry to the global dict
|
|
|
|
KviIrcUserEntry * pGlobalData = m_pIrcUserDataBase->insertUser(nick,user,host);
|
|
|
|
// calculate the flags and update the counters
|
|
|
|
it = new KviUserListEntry(this,nick,pGlobalData,iFlags,(user == TQString()));
|
|
|
|
insertUserEntry(nick,it);
|
|
|
|
} else {
|
|
|
|
// if(!host.isEmpty()) - it can be UHNAMES with host or NAMEX(X) w/o it
|
|
|
|
// {
|
|
|
|
// Ok...the user was already on...
|
|
|
|
// Probably this is a NAMES(X) reply , and the user IS_ME
|
|
|
|
// (already joined after the JOIN message)
|
|
|
|
if(iFlags != it->m_iFlags)
|
|
|
|
{
|
|
|
|
//// FIXME: #warning "Maybe say to the channel that we're oped : and the op is guessed from the names reply"
|
|
|
|
if((iFlags & KVI_USERFLAG_CHANOWNER) != (it->m_iFlags & KVI_USERFLAG_CHANOWNER))setChanOwner(nick,iFlags & KVI_USERFLAG_CHANOWNER);
|
|
|
|
if((iFlags & KVI_USERFLAG_CHANADMIN) != (it->m_iFlags & KVI_USERFLAG_CHANADMIN))setChanAdmin(nick,iFlags & KVI_USERFLAG_CHANADMIN);
|
|
|
|
if((iFlags & KVI_USERFLAG_OP) != (it->m_iFlags & KVI_USERFLAG_OP))op(nick,iFlags & KVI_USERFLAG_OP);
|
|
|
|
if((iFlags & KVI_USERFLAG_HALFOP) != (it->m_iFlags & KVI_USERFLAG_HALFOP))halfop(nick,iFlags & KVI_USERFLAG_HALFOP);
|
|
|
|
if((iFlags & KVI_USERFLAG_VOICE) != (it->m_iFlags & KVI_USERFLAG_VOICE))voice(nick,iFlags & KVI_USERFLAG_VOICE);
|
|
|
|
if((iFlags & KVI_USERFLAG_USEROP) != (it->m_iFlags & KVI_USERFLAG_USEROP))userop(nick,iFlags & KVI_USERFLAG_USEROP);
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::triggerUpdate()
|
|
|
|
{
|
|
|
|
// This stuff is useful on joins only
|
|
|
|
if(m_pViewArea->isUpdatesEnabled())
|
|
|
|
{
|
|
|
|
//m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
|
|
|
|
updateScrollBarRange();
|
|
|
|
m_pViewArea->update();
|
|
|
|
updateUsersLabel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviUserListView::avatarChanged(const TQString &nick)
|
|
|
|
{
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(nick);
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
int oldH = it->m_iHeight;
|
|
|
|
m_iTotalHeight -= it->m_iHeight;
|
|
|
|
it->recalcSize();
|
|
|
|
m_iTotalHeight += it->m_iHeight;
|
|
|
|
// if this was "over" the top item , we must adjust the scrollbar value
|
|
|
|
// otherwise scroll everything down
|
|
|
|
KviUserListEntry * e = m_pHeadItem;
|
|
|
|
bool bGotTopItem = false;
|
|
|
|
while(e != it)
|
|
|
|
{
|
|
|
|
if(e == m_pTopItem)
|
|
|
|
{
|
|
|
|
bGotTopItem = true;
|
|
|
|
e = it;
|
|
|
|
} else e = e->m_pNext;
|
|
|
|
}
|
|
|
|
if(!bGotTopItem && (m_pTopItem != it))
|
|
|
|
{
|
|
|
|
// we're "over" the top item , so over the
|
|
|
|
// upper side of the view...adjust the scroll bar value
|
|
|
|
int hDiff = it->m_iHeight - oldH;
|
|
|
|
m_pViewArea->m_iLastScrollBarVal += hDiff;
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = true;
|
|
|
|
// m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
|
|
|
|
updateScrollBarRange();
|
|
|
|
m_pViewArea->m_pScrollBar->setValue(m_pViewArea->m_iLastScrollBarVal);
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = false;
|
|
|
|
} else {
|
|
|
|
// the item may be visible!
|
|
|
|
// the scroll bar should take care of the case
|
|
|
|
// in that the current value runs out of the allowed
|
|
|
|
// range.... it should set the value to a good one
|
|
|
|
// and emit the signal
|
|
|
|
updateScrollBarRange();
|
|
|
|
// m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
|
|
|
|
m_pViewArea->update();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KviUserListView::userActionVerifyMask(const TQString &nick,const TQString &user,const TQString &host,int actionTemperature,TQString &oldUser,TQString &oldHost)
|
|
|
|
{
|
|
|
|
// This is called when an user "acts" in some visible way
|
|
|
|
// on the channel, so we can keep track of his channeel
|
|
|
|
// idle time.
|
|
|
|
// This particular function version of userAction
|
|
|
|
// will return false if there was a user or hostname
|
|
|
|
// change (unless they were not known at all)
|
|
|
|
// This will also update the username and hostname
|
|
|
|
// if needed.
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(TQString(nick));
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
it->m_lastActionTime = kvi_unixTime();
|
|
|
|
bool bChanged = false;
|
|
|
|
if(!(host.isEmpty() || (KviTQString::equalCS(host,"*"))))
|
|
|
|
{
|
|
|
|
if(!KviTQString::equalCI(it->m_pGlobalData->host(),host))
|
|
|
|
{
|
|
|
|
if(!(it->m_pGlobalData->host().isEmpty() || KviTQString::equalCS(it->m_pGlobalData->host(),"*")))
|
|
|
|
{
|
|
|
|
oldHost = it->m_pGlobalData->host();
|
|
|
|
bChanged = true;
|
|
|
|
}
|
|
|
|
it->m_pGlobalData->setHost(host);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!(user.isEmpty() || (KviTQString::equalCS(user,"*"))))
|
|
|
|
{
|
|
|
|
if(!KviTQString::equalCI(it->m_pGlobalData->user(),user))
|
|
|
|
{
|
|
|
|
if(!(it->m_pGlobalData->user().isEmpty() || KviTQString::equalCS(it->m_pGlobalData->user(),"*")))
|
|
|
|
{
|
|
|
|
oldUser = it->m_pGlobalData->user();
|
|
|
|
bChanged = true;
|
|
|
|
}
|
|
|
|
it->m_pGlobalData->setUser(user);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
it->m_iTemperature += actionTemperature;
|
|
|
|
// Don't allow it to grow too much
|
|
|
|
if(it->m_iTemperature > 300)it->m_iTemperature = 300;
|
|
|
|
else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
|
|
|
|
if(itemVisible(it))triggerUpdate();
|
|
|
|
return !bChanged;
|
|
|
|
}
|
|
|
|
return true; // no such nick so no change
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviUserListView::userAction(const TQString &nick,const TQString &user,const TQString &host,int actionTemperature)
|
|
|
|
{
|
|
|
|
// This is called when an user "acts" in some visible way
|
|
|
|
// on the channel, so we can keep track of his channeel
|
|
|
|
// idle time. This will also update the username and hostname
|
|
|
|
// if needed.
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(TQString(nick));
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
it->m_lastActionTime = kvi_unixTime();
|
|
|
|
if(!(host.isEmpty() || (KviTQString::equalCS(host,"*"))))
|
|
|
|
it->m_pGlobalData->setHost(host);
|
|
|
|
if(!(user.isEmpty() || (KviTQString::equalCS(user,"*"))))
|
|
|
|
it->m_pGlobalData->setUser(user);
|
|
|
|
it->m_iTemperature += actionTemperature;
|
|
|
|
// Don't allow it to grow too much
|
|
|
|
if(it->m_iTemperature > 300)it->m_iTemperature = 300;
|
|
|
|
else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
|
|
|
|
if(itemVisible(it))triggerUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviUserListView::userAction(KviIrcMask *user,int actionTemperature)
|
|
|
|
{
|
|
|
|
// This is called when an user "acts" in some visible way
|
|
|
|
// on the channel, so we can keep track of his channeel
|
|
|
|
// idle time. This will also update the username and hostname
|
|
|
|
// if needed.
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(TQString(user->nick()));
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
it->m_lastActionTime = kvi_unixTime();
|
|
|
|
if(user->hasUser())it->m_pGlobalData->setUser(user->user());
|
|
|
|
if(user->hasHost())it->m_pGlobalData->setHost(user->host());
|
|
|
|
it->m_iTemperature += actionTemperature;
|
|
|
|
// Don't allow it to grow too much
|
|
|
|
if(it->m_iTemperature > 300)it->m_iTemperature = 300;
|
|
|
|
else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
|
|
|
|
if(itemVisible(it))triggerUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::userAction(const TQString &nick,int actionTemperature)
|
|
|
|
{
|
|
|
|
// This is called when an user "acts" in some visible way
|
|
|
|
// on the channel, so we can keep track of his channeel
|
|
|
|
// idle time. This will also update the username and hostname
|
|
|
|
// if needed.
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(nick);
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
it->m_lastActionTime = kvi_unixTime();
|
|
|
|
it->m_iTemperature += actionTemperature;
|
|
|
|
if(it->m_iTemperature > 300)it->m_iTemperature = 300;
|
|
|
|
else if(it->m_iTemperature < -300)it->m_iTemperature = -300;
|
|
|
|
if(itemVisible(it))triggerUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kvi_time_t KviUserListView::getUserJoinTime(const TQString &szNick)
|
|
|
|
{
|
|
|
|
KviUserListEntry * e = m_pEntryDict->find(szNick);
|
|
|
|
if(!e)return (kvi_time_t)0;
|
|
|
|
return e->m_joinTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
kvi_time_t KviUserListView::getUserLastActionTime(const TQString &szNick)
|
|
|
|
{
|
|
|
|
KviUserListEntry * e = m_pEntryDict->find(szNick);
|
|
|
|
if(!e)return (kvi_time_t)0;
|
|
|
|
return e->m_lastActionTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int KviUserListView::getUserModeLevel(const TQString &szNick)
|
|
|
|
{
|
|
|
|
KviUserListEntry * e = m_pEntryDict->find(szNick);
|
|
|
|
if(!e)return 0;
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_MODEMASK)
|
|
|
|
{
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_CHANOWNER)return 60;
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_CHANADMIN)return 50;
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_OP)return 40;
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_HALFOP)return 30;
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_VOICE)return 20;
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_USEROP)return 10;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
char KviUserListView::getUserFlag(KviUserListEntry * e)
|
|
|
|
{
|
|
|
|
if(!e)return 0;
|
|
|
|
return (char)m_pKviWindow->connection()->serverInfo()->modePrefixChar(e->m_iFlags).tqunicode();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::prependUserFlag(const TQString &nick,TQString &buffer)
|
|
|
|
{
|
|
|
|
char uFlag = getUserFlag(nick);
|
|
|
|
if(uFlag)buffer.prepend(uFlag);
|
|
|
|
}
|
|
|
|
|
|
|
|
int KviUserListView::flags(const TQString &nick)
|
|
|
|
{
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(nick);
|
|
|
|
return it ? it->m_iFlags : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SET_FLAG_FUNC(__funcname,__flag) \
|
|
|
|
bool KviUserListView::__funcname(const TQString &nick,bool bYes) \
|
|
|
|
{ \
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(nick); \
|
|
|
|
if(!it)return false; \
|
|
|
|
m_pEntryDict->setAutoDelete(false); \
|
|
|
|
partInternal(nick,false); \
|
|
|
|
m_pEntryDict->setAutoDelete(true); \
|
|
|
|
if(bYes) \
|
|
|
|
{ \
|
|
|
|
if(!(it->m_iFlags & __flag))it->m_iFlags |= __flag; \
|
|
|
|
} else { \
|
|
|
|
if(it->m_iFlags & __flag)it->m_iFlags &= ~__flag; \
|
|
|
|
} \
|
|
|
|
updateScrollBarRange(); \
|
|
|
|
insertUserEntry(nick,it); \
|
|
|
|
m_pViewArea->update(); \
|
|
|
|
return true; \
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_FLAG_FUNC(setChanOwner,KVI_USERFLAG_CHANOWNER)
|
|
|
|
SET_FLAG_FUNC(setChanAdmin,KVI_USERFLAG_CHANADMIN)
|
|
|
|
SET_FLAG_FUNC(op,KVI_USERFLAG_OP)
|
|
|
|
SET_FLAG_FUNC(halfop,KVI_USERFLAG_HALFOP)
|
|
|
|
SET_FLAG_FUNC(userop,KVI_USERFLAG_USEROP)
|
|
|
|
SET_FLAG_FUNC(voice,KVI_USERFLAG_VOICE)
|
|
|
|
|
|
|
|
#define GET_FLAG_FUNC(__funcname,__flag) \
|
|
|
|
bool KviUserListView::__funcname(const TQString &nick,bool bAtLeast) \
|
|
|
|
{ \
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(nick); \
|
|
|
|
return it ? (bAtLeast ? (it->m_iFlags >= __flag) : (it->m_iFlags & __flag)) : false; \
|
|
|
|
}
|
|
|
|
|
|
|
|
GET_FLAG_FUNC(isChanOwner,KVI_USERFLAG_CHANOWNER)
|
|
|
|
GET_FLAG_FUNC(isChanAdmin,KVI_USERFLAG_CHANADMIN)
|
|
|
|
GET_FLAG_FUNC(isOp,KVI_USERFLAG_OP)
|
|
|
|
GET_FLAG_FUNC(isVoice,KVI_USERFLAG_VOICE)
|
|
|
|
GET_FLAG_FUNC(isHalfOp,KVI_USERFLAG_HALFOP)
|
|
|
|
GET_FLAG_FUNC(isUserOp,KVI_USERFLAG_USEROP)
|
|
|
|
|
|
|
|
|
|
|
|
TQString * KviUserListView::firstSelectedNickname()
|
|
|
|
{
|
|
|
|
m_pIterator = m_pHeadItem;
|
|
|
|
while(m_pIterator)
|
|
|
|
{
|
|
|
|
if(m_pIterator->m_bSelected)
|
|
|
|
{
|
|
|
|
TQString * s = &(m_pIterator->m_szNick);
|
|
|
|
m_pIterator = m_pIterator->m_pNext;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
m_pIterator = m_pIterator->m_pNext;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString * KviUserListView::nextSelectedNickname()
|
|
|
|
{
|
|
|
|
while(m_pIterator)
|
|
|
|
{
|
|
|
|
if(m_pIterator->m_bSelected)
|
|
|
|
{
|
|
|
|
TQString * s = &(m_pIterator->m_szNick);
|
|
|
|
m_pIterator = m_pIterator->m_pNext;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
m_pIterator = m_pIterator->m_pNext;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::appendSelectedNicknames(TQString &buffer)
|
|
|
|
{
|
|
|
|
KviUserListEntry * aux = m_pHeadItem;
|
|
|
|
bool bFirst = true;
|
|
|
|
while(aux)
|
|
|
|
{
|
|
|
|
if(aux->m_bSelected)
|
|
|
|
{
|
|
|
|
if(!bFirst)buffer.append(',');
|
|
|
|
else bFirst = false;
|
|
|
|
buffer.append(aux->m_szNick);
|
|
|
|
}
|
|
|
|
aux = aux->m_pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::select(const TQString& nick){
|
|
|
|
KviPointerHashTableIterator<TQString,KviUserListEntry> it(*m_pEntryDict);
|
|
|
|
while(it.current())
|
|
|
|
{
|
|
|
|
((KviUserListEntry *)it.current())->m_bSelected = false;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
KviUserListEntry * entry = m_pEntryDict->find(nick);
|
|
|
|
if(entry)
|
|
|
|
{
|
|
|
|
entry->m_bSelected = true;
|
|
|
|
m_iSelectedCount = 1;
|
|
|
|
} else {
|
|
|
|
m_iSelectedCount = 0;
|
|
|
|
}
|
|
|
|
g_pFrame->childWindowSelectionStateChange(m_pKviWindow,true);
|
|
|
|
m_pViewArea->update();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviUserListView::partInternal(const TQString &nick,bool bRemove)
|
|
|
|
{
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(nick);
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
// so, first of all..check if this item is over, or below the top item
|
|
|
|
KviUserListEntry * e = m_pHeadItem;
|
|
|
|
bool bGotTopItem = false;
|
|
|
|
while(e != it)
|
|
|
|
{
|
|
|
|
if(e == m_pTopItem)
|
|
|
|
{
|
|
|
|
bGotTopItem = true;
|
|
|
|
e = it;
|
|
|
|
} else e = e->m_pNext;
|
|
|
|
}
|
|
|
|
if(bRemove)m_pIrcUserDataBase->removeUser(nick,it->m_pGlobalData);
|
|
|
|
|
|
|
|
// now just remove it
|
|
|
|
if(it->m_iFlags & KVI_USERFLAG_OP)m_iOpCount--;
|
|
|
|
if(it->m_iFlags & KVI_USERFLAG_VOICE)m_iVoiceCount--;
|
|
|
|
if(it->m_iFlags & KVI_USERFLAG_HALFOP)m_iHalfOpCount--;
|
|
|
|
if(it->m_iFlags & KVI_USERFLAG_CHANADMIN)m_iChanAdminCount--;
|
|
|
|
if(it->m_iFlags & KVI_USERFLAG_CHANOWNER)m_iChanOwnerCount--;
|
|
|
|
if(it->m_iFlags & KVI_USERFLAG_USEROP)m_iUserOpCount--;
|
|
|
|
if(it->m_bSelected)
|
|
|
|
{
|
|
|
|
m_iSelectedCount--;
|
|
|
|
if(m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pKviWindow,false);
|
|
|
|
}
|
|
|
|
if(it->m_pPrev)it->m_pPrev->m_pNext = it->m_pNext;
|
|
|
|
if(it->m_pNext)it->m_pNext->m_pPrev = it->m_pPrev;
|
|
|
|
if(m_pTopItem == it)
|
|
|
|
{
|
|
|
|
bGotTopItem = true; //!!! the previous while() does not handle it!
|
|
|
|
m_pTopItem = it->m_pNext;
|
|
|
|
if(m_pTopItem == 0)m_pTopItem = it->m_pPrev;
|
|
|
|
}
|
|
|
|
if(it == m_pHeadItem)m_pHeadItem = it->m_pNext;
|
|
|
|
if(it == m_pTailItem)m_pTailItem = it->m_pPrev;
|
|
|
|
m_iTotalHeight -= it->m_iHeight;
|
|
|
|
|
|
|
|
int iHeight = it->m_iHeight;
|
|
|
|
|
|
|
|
m_pEntryDict->remove(nick);
|
|
|
|
|
|
|
|
if(bGotTopItem)
|
|
|
|
{
|
|
|
|
// removing after (or exactly) the top item, may be visible
|
|
|
|
if(bRemove)triggerUpdate();
|
|
|
|
} else {
|
|
|
|
// removing over (before) the top item...not visible
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = true;
|
|
|
|
m_pViewArea->m_iLastScrollBarVal -= iHeight;
|
|
|
|
m_pViewArea->m_pScrollBar->setValue(m_pViewArea->m_iLastScrollBarVal);
|
|
|
|
// m_pViewArea->m_pScrollBar->setRange(0,m_iTotalHeight);
|
|
|
|
updateScrollBarRange();
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = false;
|
|
|
|
if(bRemove)updateUsersLabel();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviUserListView::nickChange(const TQString &oldNick,const TQString &newNick)
|
|
|
|
{
|
|
|
|
KviUserListEntry * it = m_pEntryDict->find(oldNick);
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
TQString user = it->m_pGlobalData->user();
|
|
|
|
TQString host = it->m_pGlobalData->host();
|
|
|
|
int iFlags = it->m_iFlags;
|
|
|
|
kvi_time_t joint = it->m_joinTime;
|
|
|
|
bool bSelect = it->m_bSelected;
|
|
|
|
KviAvatar * av = it->m_pGlobalData->forgetAvatar();
|
|
|
|
KviIrcUserEntry::Gender gender = it->m_pGlobalData->gender();
|
|
|
|
bool bBot = it->m_pGlobalData->isBot();
|
|
|
|
part(oldNick);
|
|
|
|
__range_invalid(m_pEntryDict->find(oldNick));
|
|
|
|
it = join(newNick,user,host,iFlags);
|
|
|
|
it->m_pGlobalData->setGender(gender);
|
|
|
|
it->m_pGlobalData->setBot(bBot);
|
|
|
|
it->m_joinTime = joint;
|
|
|
|
it->m_lastActionTime = kvi_unixTime();
|
|
|
|
it->m_bSelected = bSelect;
|
|
|
|
it->m_iTemperature += KVI_USERACTION_NICK;
|
|
|
|
if(av)
|
|
|
|
{
|
|
|
|
it->m_pGlobalData->setAvatar(av);
|
|
|
|
avatarChanged(newNick);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviUserListView::updateUsersLabel()
|
|
|
|
{
|
|
|
|
if(!KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel))//G&N 2005
|
|
|
|
{
|
|
|
|
KviStr tmp;
|
|
|
|
tmp.sprintf("<nobr><b>[%u]</b>",m_pEntryDict->count());
|
|
|
|
if(m_iChanOwnerCount)tmp.append(KviStr::Format," q:%d",m_iChanOwnerCount);
|
|
|
|
if(m_iChanAdminCount)tmp.append(KviStr::Format," a:%d",m_iChanAdminCount);
|
|
|
|
if(m_iOpCount)tmp.append(KviStr::Format," o:%d",m_iOpCount);
|
|
|
|
if(m_iHalfOpCount)tmp.append(KviStr::Format," h:%d",m_iHalfOpCount);
|
|
|
|
if(m_iVoiceCount)tmp.append(KviStr::Format," v:%d",m_iVoiceCount);
|
|
|
|
if(m_iUserOpCount)tmp.append(KviStr::Format," u:%d",m_iUserOpCount);
|
|
|
|
if(m_ibEntries)tmp.append(KviStr::Format," b:%d",m_ibEntries);
|
|
|
|
if(m_ieEntries)tmp.append(KviStr::Format," e:%d",m_ieEntries);
|
|
|
|
if(m_iIEntries)tmp.append(KviStr::Format," I:%d",m_iIEntries);
|
|
|
|
tmp.append("</nobr>");
|
|
|
|
m_pUsersLabel->setText(tmp.ptr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: this could be done really better
|
|
|
|
void KviUserListView::partAllButOne(const TQString &whoNot)
|
|
|
|
{
|
|
|
|
TQStringList ll;
|
|
|
|
KviPointerHashTableIterator<TQString,KviUserListEntry> it(*m_pEntryDict);
|
|
|
|
while(it.current())
|
|
|
|
{
|
|
|
|
if(!KviTQString::equalCI(whoNot,it.currentKey()))
|
|
|
|
ll.append(it.currentKey());
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
for(TQStringList::Iterator it2 = ll.begin();it2 != ll.end();it2++)
|
|
|
|
{
|
|
|
|
part(*it2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::removeAllEntries()
|
|
|
|
{
|
|
|
|
KviPointerHashTableIterator<TQString,KviUserListEntry> it(*m_pEntryDict);
|
|
|
|
while(it.current())
|
|
|
|
{
|
|
|
|
m_pIrcUserDataBase->removeUser(it.currentKey(),
|
|
|
|
((KviUserListEntry *)it.current())->m_pGlobalData);
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
m_pEntryDict->clear();
|
|
|
|
m_pHeadItem = 0;
|
|
|
|
m_pTopItem = 0;
|
|
|
|
m_iVoiceCount = 0;
|
|
|
|
m_iHalfOpCount = 0;
|
|
|
|
m_iChanAdminCount = 0;
|
|
|
|
m_iChanOwnerCount = 0;
|
|
|
|
m_iOpCount = 0;
|
|
|
|
m_iUserOpCount = 0;
|
|
|
|
if(m_iSelectedCount != 0)
|
|
|
|
{
|
|
|
|
m_iSelectedCount = 0;
|
|
|
|
g_pFrame->childWindowSelectionStateChange(m_pKviWindow,false);
|
|
|
|
}
|
|
|
|
m_pViewArea->m_iTopItemOffset = 0;
|
|
|
|
m_pViewArea->m_iLastScrollBarVal = 0;
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = true;
|
|
|
|
m_pViewArea->m_pScrollBar->setValue(0);
|
|
|
|
m_iTotalHeight = 0;
|
|
|
|
updateScrollBarRange();
|
|
|
|
m_pViewArea->m_bIgnoreScrollBar = false; // gfgf
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::partAll()
|
|
|
|
{
|
|
|
|
removeAllEntries();
|
|
|
|
triggerUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListView::resizeEvent(TQResizeEvent *)
|
|
|
|
{
|
|
|
|
int hght;
|
|
|
|
if(!KVI_OPTION_BOOL(KviOption_boolDisableUserListLabel))//G&N 2005
|
|
|
|
{
|
|
|
|
hght = m_pUsersLabel->sizeHint().height();
|
|
|
|
if(hght < 16)hght = 16; // at least
|
|
|
|
m_pUsersLabel->setGeometry(0,0,width(),hght);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hght =0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pViewArea->setGeometry(0,hght,width(),height() - hght);
|
|
|
|
|
|
|
|
updateScrollBarRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KviUserListView::itemVisible(KviUserListEntry * e)
|
|
|
|
{
|
|
|
|
KviUserListEntry * le = m_pTopItem;
|
|
|
|
int curTop = KVI_USERLIST_BORDER_WIDTH - m_pViewArea->m_iTopItemOffset;
|
|
|
|
int hght = height();
|
|
|
|
while(le && (curTop < hght))
|
|
|
|
{
|
|
|
|
if(le == e)return true;
|
|
|
|
curTop += le->m_iHeight;
|
|
|
|
le = le->m_pNext;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
KviUserListEntry * KviUserListView::itemAt(const TQPoint &pnt,TQRect * rct)
|
|
|
|
{
|
|
|
|
if(!m_pTopItem)return 0;
|
|
|
|
if(pnt.y() < 0)return 0;
|
|
|
|
int curTop = KVI_USERLIST_BORDER_WIDTH - m_pViewArea->m_iTopItemOffset;
|
|
|
|
KviUserListEntry * e = m_pTopItem;
|
|
|
|
int curBottom = 0;
|
|
|
|
while(e && (curTop <= m_pViewArea->height()))
|
|
|
|
{
|
|
|
|
curBottom = curTop + e->m_iHeight;
|
|
|
|
if((pnt.y() >= curTop) && (pnt.y() < curBottom))
|
|
|
|
{
|
|
|
|
if(rct)
|
|
|
|
{
|
|
|
|
rct->setX(0);
|
|
|
|
rct->setY(curTop);
|
|
|
|
rct->setWidth(m_pViewArea->width());
|
|
|
|
rct->setHeight(e->m_iHeight);
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
curTop = curBottom;
|
|
|
|
e = e->m_pNext;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void KviUserListView::userStats(KviUserListViewUserStats * s)
|
|
|
|
{
|
|
|
|
s->uTotal = m_pEntryDict->count();
|
|
|
|
s->uHot = 0;
|
|
|
|
s->uHotOp = 0;
|
|
|
|
s->uActive = 0;
|
|
|
|
s->uActiveOp = 0;
|
|
|
|
s->uChanAdmin = 0;
|
|
|
|
s->uChanOwner = 0;
|
|
|
|
s->iAvgTemperature = 0;
|
|
|
|
s->uOp = 0;
|
|
|
|
s->uVoiced = 0;
|
|
|
|
s->uHalfOp = 0;
|
|
|
|
s->uUserOp = 0;
|
|
|
|
|
|
|
|
KviUserListEntry * e = m_pHeadItem;
|
|
|
|
|
|
|
|
kvi_time_t curTime = kvi_unixTime();
|
|
|
|
|
|
|
|
while(e)
|
|
|
|
{
|
|
|
|
if(e->m_lastActionTime)
|
|
|
|
{
|
|
|
|
unsigned int uTimeDiff = (((unsigned int)(curTime - e->m_lastActionTime)) >> 6);
|
|
|
|
if(uTimeDiff < 10)
|
|
|
|
{
|
|
|
|
s->uActive++; // the user was alive in the last ~16 mins
|
|
|
|
if(e->m_iFlags & (KVI_USERFLAG_OP | KVI_USERFLAG_CHANADMIN | KVI_USERFLAG_CHANOWNER))
|
|
|
|
{
|
|
|
|
s->uActiveOp++;
|
|
|
|
if(e->m_iTemperature > 0)
|
|
|
|
{
|
|
|
|
s->uHot++;
|
|
|
|
s->uHotOp++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(e->m_iTemperature > 0)s->uHot++;
|
|
|
|
}
|
|
|
|
s->iAvgTemperature += e->m_iTemperature;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_CHANOWNER)s->uChanOwner++;
|
|
|
|
else {
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_CHANADMIN)s->uChanAdmin++;
|
|
|
|
else {
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_OP)s->uOp++;
|
|
|
|
else {
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_HALFOP)s->uHalfOp++;
|
|
|
|
else {
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_VOICE)s->uVoiced++;
|
|
|
|
else {
|
|
|
|
if(e->m_iFlags & KVI_USERFLAG_USEROP)s->uUserOp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
e = e->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(s->uActive > 0)s->iAvgTemperature /= ((int)s->uActive);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KviUserListView::maybeTip(KviUserListToolTip * tip,const TQPoint &pnt)
|
|
|
|
{
|
|
|
|
if(!KVI_OPTION_BOOL(KviOption_boolShowUserListViewToolTips))return;
|
|
|
|
TQRect itRect;
|
|
|
|
KviUserListEntry * it = (KviUserListEntry *)itemAt(pnt,&itRect);
|
|
|
|
if(it)
|
|
|
|
{
|
|
|
|
if(m_pKviWindow->console())
|
|
|
|
{
|
|
|
|
TQString buffer;
|
|
|
|
m_pKviWindow->console()->getUserTipText(it->m_szNick,it->m_pGlobalData,buffer);
|
|
|
|
|
|
|
|
buffer += "<table width=\"100%\">";
|
|
|
|
|
|
|
|
if(it->m_joinTime != 0)
|
|
|
|
{
|
|
|
|
TQDateTime dt;
|
|
|
|
dt.setTime_t(it->m_joinTime);
|
|
|
|
buffer += "<tr><td bgcolor=\"#F0F0F0\"><nobr>";
|
|
|
|
buffer += __tr2qs("Joined on <b>%1</b>").arg(dt.toString());
|
|
|
|
buffer += "</nobr></td></tr>";
|
|
|
|
}
|
|
|
|
|
|
|
|
if(it->m_lastActionTime != 0)
|
|
|
|
{
|
|
|
|
int secs = kvi_unixTime() - it->m_lastActionTime;
|
|
|
|
int mins = secs / 60;
|
|
|
|
secs = secs % 60;
|
|
|
|
int hors = mins / 60;
|
|
|
|
mins = mins % 60;
|
|
|
|
buffer += "<tr><td bgcolor=\"#F0F0F0\"><nobr>";
|
|
|
|
buffer += __tr2qs("Quiet for <b>%1h %2m %3s</b>").arg(hors).arg(mins).arg(secs);
|
|
|
|
buffer += "</nobr></td></tr>";
|
|
|
|
}
|
|
|
|
buffer += "</table>";
|
|
|
|
|
|
|
|
tip->doTip(itRect,buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
KviUserListViewArea::KviUserListViewArea(KviUserListView * par)
|
|
|
|
: TQWidget(par)
|
|
|
|
{
|
|
|
|
m_pListView = par;
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
setAutoFillBackground(false);
|
|
|
|
#else
|
|
|
|
setBackgroundMode(TQWidget::NoBackground);
|
|
|
|
#endif
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
m_pScrollBar = new TQScrollBar(Qt::Vertical,this,"scrollbar");
|
|
|
|
#else
|
|
|
|
m_pScrollBar = new TQScrollBar(Qt::Vertical,this,"scrollbar");
|
|
|
|
#endif
|
|
|
|
m_pScrollBar->setRange(0,0);
|
|
|
|
m_pScrollBar->setValue(0);
|
|
|
|
connect(m_pScrollBar,TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(scrollBarMoved(int)));
|
|
|
|
m_pScrollBar->setPageStep(height());
|
|
|
|
m_pScrollBar->setLineStep(m_pListView->m_iFontHeight);
|
|
|
|
m_iLastScrollBarVal = 0;
|
|
|
|
m_iTopItemOffset = 0;
|
|
|
|
m_bIgnoreScrollBar = false;
|
|
|
|
m_pLastEntryUnderMouse = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
KviUserListViewArea::~KviUserListViewArea()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::scrollBarMoved(int newVal)
|
|
|
|
{
|
|
|
|
if(m_bIgnoreScrollBar)return;
|
|
|
|
int diff = newVal - m_iLastScrollBarVal;
|
|
|
|
if(m_pListView->m_pTopItem)
|
|
|
|
{
|
|
|
|
while(diff > 0)
|
|
|
|
{
|
|
|
|
int nextH = (m_pListView->m_pTopItem->m_iHeight - m_iTopItemOffset);
|
|
|
|
if(diff >= nextH)
|
|
|
|
{
|
|
|
|
// the diff is greater than the top item visible part
|
|
|
|
diff -= nextH;
|
|
|
|
if(m_pListView->m_pTopItem->m_pNext)
|
|
|
|
{
|
|
|
|
// There is a next item (offset to 0)
|
|
|
|
m_pListView->m_pTopItem = m_pListView->m_pTopItem->m_pNext;
|
|
|
|
m_iTopItemOffset = 0;
|
|
|
|
} else {
|
|
|
|
// No next item (rather a bug) (offset to the top item size)
|
|
|
|
m_iTopItemOffset = m_pListView->m_pTopItem->m_iHeight;
|
|
|
|
diff = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// just offset the top item
|
|
|
|
m_iTopItemOffset += diff;
|
|
|
|
diff = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while(diff < 0)
|
|
|
|
{
|
|
|
|
if((-diff) <= m_iTopItemOffset)
|
|
|
|
{
|
|
|
|
// just move the top item
|
|
|
|
m_iTopItemOffset += diff;
|
|
|
|
diff = 0;
|
|
|
|
} else {
|
|
|
|
diff += m_iTopItemOffset;
|
|
|
|
if(m_pListView->m_pTopItem->m_pPrev)
|
|
|
|
{
|
|
|
|
// There is a prev item (offset to 0)
|
|
|
|
m_pListView->m_pTopItem = m_pListView->m_pTopItem->m_pPrev;
|
|
|
|
m_iTopItemOffset = m_pListView->m_pTopItem->m_iHeight;
|
|
|
|
} else {
|
|
|
|
// No prev item (rather a bug) (offset to the top item size)
|
|
|
|
m_iTopItemOffset = 0;
|
|
|
|
diff = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_iLastScrollBarVal = newVal;
|
|
|
|
update();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::paintEvent(TQPaintEvent *ev)
|
|
|
|
{
|
|
|
|
// update the scroll bar
|
|
|
|
|
|
|
|
if(!isVisible())return;
|
|
|
|
|
|
|
|
// if the mdiManager is in SDI mode
|
|
|
|
// and this window is attacched but is not the toplevel one
|
|
|
|
// then it is hidden completely behind the other windows
|
|
|
|
// and we can avoid to paint it :)
|
|
|
|
if(g_pFrame->mdiManager()->isInSDIMode() &&
|
|
|
|
(m_pListView->window()->mdiParent() != g_pFrame->mdiManager()->topChild()) &&
|
|
|
|
(m_pListView->window()->mdiParent()))
|
|
|
|
{
|
|
|
|
return; // totally hidden behind other windows
|
|
|
|
}
|
|
|
|
|
|
|
|
int wdth = width() - m_pScrollBar->width();
|
|
|
|
|
|
|
|
TQRect r = ev->rect();
|
|
|
|
if(r.right() > wdth)r.setRight(wdth);
|
|
|
|
|
|
|
|
//debug("PAINT EVENT %d,%d,%d,%d",r.left(),r.top(),r.width(),r.height());
|
|
|
|
|
|
|
|
KviDoubleBuffer db(width(),height());
|
|
|
|
TQPixmap * pMemBuffer = db.pixmap();
|
|
|
|
|
|
|
|
TQPainter p(pMemBuffer);
|
|
|
|
SET_ANTI_ALIASING(p);
|
|
|
|
p.setFont(KVI_OPTION_FONT(KviOption_fontUserListView));
|
|
|
|
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
TQFontMetrics fm(p.fontMetrics());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef COMPILE_PSEUDO_TRANSPARENCY
|
|
|
|
if(g_pShadedChildGlobalDesktopBackground)
|
|
|
|
{
|
|
|
|
TQPoint pnt = mapToGlobal(TQPoint(r.left(),r.top()));
|
|
|
|
p.drawTiledPixmap(r.left(),r.top(),r.width(),r.height(),*g_pShadedChildGlobalDesktopBackground,pnt.x(),pnt.y());
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
TQPixmap *pix = KVI_OPTION_PIXMAP(KviOption_pixmapUserListViewBackground).pixmap();
|
|
|
|
p.fillRect(r.left(),r.top(),r.width(),r.height(),KVI_OPTION_COLOR(KviOption_colorUserListViewBackground));
|
|
|
|
if(pix)
|
|
|
|
KviPixmapUtils::drawPixmapWithPainter(&p,pix,KVI_OPTION_UINT(KviOption_uintUserListPixmapAlign),r,width(),height());
|
|
|
|
#ifdef COMPILE_PSEUDO_TRANSPARENCY
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
KviUserListEntry * e = m_pListView->m_pTopItem;
|
|
|
|
|
|
|
|
int theY = KVI_USERLIST_BORDER_WIDTH - m_iTopItemOffset;
|
|
|
|
|
|
|
|
kvi_time_t curTime = kvi_unixTime();
|
|
|
|
|
|
|
|
bool bShowIcons = KVI_OPTION_BOOL(KviOption_boolShowUserChannelIcons);
|
|
|
|
bool bShowState = KVI_OPTION_BOOL(KviOption_boolShowUserChannelState);
|
|
|
|
bool bShowGender = KVI_OPTION_BOOL(KviOption_boolDrawGenderIcons);
|
|
|
|
|
|
|
|
while(e && theY <= r.bottom())
|
|
|
|
{
|
|
|
|
int bottom = theY + e->m_iHeight;
|
|
|
|
// theY is our top line
|
|
|
|
// theX is our left corner
|
|
|
|
// bottom is our bottom line
|
|
|
|
// wdth is the width of the whole widget
|
|
|
|
|
|
|
|
if(bottom >= r.top())
|
|
|
|
{
|
|
|
|
TQColor * pClrFore = 0;
|
|
|
|
bool bColorAllocated=0; // FIXME: bool is true or false
|
|
|
|
if(e->m_bSelected)
|
|
|
|
{
|
|
|
|
p.fillRect(0,theY,wdth,e->m_iHeight,KVI_OPTION_COLOR(KviOption_colorUserListViewSelectionBackground));
|
|
|
|
pClrFore = &(KVI_OPTION_COLOR(KviOption_colorUserListViewSelectionForeground));
|
|
|
|
} else if(KVI_OPTION_BOOL(KviOption_boolUseDifferentColorForOwnNick) && m_pListView->m_pKviWindow->connection())
|
|
|
|
{
|
|
|
|
if(e->m_szNick==m_pListView->m_pKviWindow->connection()->currentNickName())
|
|
|
|
pClrFore = &(KVI_OPTION_COLOR(KviOption_colorUserListViewOwnForeground));
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!pClrFore){
|
|
|
|
// FIXME:
|
|
|
|
//
|
|
|
|
// this is slow... VERY slow when one has a lot of registered users.
|
|
|
|
// (this is NOT a simple lookup in the user db... it is a mask match)
|
|
|
|
// if we REALLY need to use custom colors for regged users then
|
|
|
|
// they should be updated ONCE and stored (cached) in the KviUserListEntry structure
|
|
|
|
//
|
|
|
|
if(m_pListView->m_pKviWindow->connection()->userDataBase()->haveCustomColor(e->m_szNick))
|
|
|
|
{
|
|
|
|
pClrFore = m_pListView->m_pKviWindow->connection()->userDataBase()->customColor(e->m_szNick);
|
|
|
|
}
|
|
|
|
if(!pClrFore)
|
|
|
|
{
|
|
|
|
if(e->m_iFlags == 0)
|
|
|
|
{
|
|
|
|
pClrFore = &(KVI_OPTION_COLOR(KviOption_colorUserListViewNormalForeground));
|
|
|
|
} else {
|
|
|
|
pClrFore = &(KVI_OPTION_COLOR((e->m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
|
|
|
|
KviOption_colorUserListViewChanOwnerForeground : ((e->m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
|
|
|
|
KviOption_colorUserListViewChanAdminForeground : ((e->m_iFlags & KVI_USERFLAG_OP) ? \
|
|
|
|
KviOption_colorUserListViewOpForeground : ((e->m_iFlags & KVI_USERFLAG_HALFOP) ? \
|
|
|
|
KviOption_colorUserListViewHalfOpForeground : ((e->m_iFlags & KVI_USERFLAG_VOICE) ? \
|
|
|
|
KviOption_colorUserListViewVoiceForeground : KviOption_colorUserListViewUserOpForeground))))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int theX = KVI_USERLIST_BORDER_WIDTH + 1;
|
|
|
|
|
|
|
|
int iAvatarAndTextX = theX;
|
|
|
|
|
|
|
|
if(bShowGender)iAvatarAndTextX += 11;
|
|
|
|
if(bShowIcons)iAvatarAndTextX += 18;
|
|
|
|
if(bShowState)iAvatarAndTextX += 11;
|
|
|
|
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolUserListViewDrawGrid))
|
|
|
|
{
|
|
|
|
// the grid
|
|
|
|
switch(KVI_OPTION_UINT(KviOption_uintUserListViewGridType))
|
|
|
|
{
|
|
|
|
case KVI_USERLISTVIEW_GRIDTYPE_PLAINGRID:
|
|
|
|
case KVI_USERLISTVIEW_GRIDTYPE_DOTGRID:
|
|
|
|
p.setPen(TQPen(KVI_OPTION_COLOR(KviOption_colorUserListViewGrid),0,
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
(KVI_OPTION_UINT(KviOption_uintUserListViewGridType) == KVI_USERLISTVIEW_GRIDTYPE_DOTGRID) ? TQt::DotLine : TQt::SolidLine));
|
|
|
|
#else
|
|
|
|
(KVI_OPTION_UINT(KviOption_uintUserListViewGridType) == KVI_USERLISTVIEW_GRIDTYPE_DOTGRID) ? TQPen::DotLine : TQPen::SolidLine));
|
|
|
|
#endif
|
|
|
|
p.drawLine(0,bottom - 1,wdth,bottom - 1);
|
|
|
|
if(bShowState || bShowIcons)
|
|
|
|
p.drawLine(iAvatarAndTextX,bottom - 1,iAvatarAndTextX,theY);
|
|
|
|
break;
|
|
|
|
default: // KVI_USERLISTVIEW_GRIDTYPE_3DGRID and KVI_USERLISTVIEW_GRIDTYPE_3DBUTTONS
|
|
|
|
if(!e->m_bSelected)
|
|
|
|
{
|
|
|
|
p.setPen(TQPen(KVI_OPTION_COLOR(KviOption_colorUserListViewGrid),0 /*,TQPen::DotLine*/));
|
|
|
|
if((bShowState || bShowIcons) && (KVI_OPTION_UINT(KviOption_uintUserListViewGridType) == KVI_USERLISTVIEW_GRIDTYPE_3DGRID))
|
|
|
|
p.drawLine(iAvatarAndTextX,bottom - 1,iAvatarAndTextX,theY);
|
|
|
|
p.setPen(colorGroup().shadow());
|
|
|
|
p.drawLine(0,bottom - 1,wdth,bottom - 1);
|
|
|
|
p.setPen(colorGroup().light());
|
|
|
|
p.drawLine(0,theY,wdth,theY);
|
|
|
|
theY--;
|
|
|
|
}
|
|
|
|
theY++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
iAvatarAndTextX += 3;
|
|
|
|
} else {
|
|
|
|
iAvatarAndTextX += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(e->globalData()->isAway())
|
|
|
|
{
|
|
|
|
TQRgb rgb2 = pClrFore->rgb();
|
|
|
|
TQRgb rgb1 = KVI_OPTION_COLOR(KviOption_colorUserListViewAwayForeground).rgb();
|
|
|
|
p.setPen(TQColor(((tqRed(rgb1)*2) + tqRed(rgb2)) / 3,((tqGreen(rgb1)*2) + tqGreen(rgb2)) / 3,((tqBlue(rgb1)*2) + tqBlue(rgb2)) / 3));
|
|
|
|
} else {
|
|
|
|
p.setPen(*pClrFore);
|
|
|
|
}
|
|
|
|
theY+=2;
|
|
|
|
|
|
|
|
if(!KVI_OPTION_BOOL(KviOption_boolDisableAvatars))//G&N 2005
|
|
|
|
{
|
|
|
|
KviAvatar * av = e->m_pGlobalData->avatar();
|
|
|
|
if(av && KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth) && KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight))
|
|
|
|
{
|
|
|
|
TQPixmap * pix;
|
|
|
|
if( KVI_OPTION_BOOL(KviOption_boolScaleAvatars) &&
|
|
|
|
(
|
|
|
|
!KVI_OPTION_BOOL(KviOption_boolDoNotStretchAvatars) ||
|
|
|
|
(av->pixmap()->width() > KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth)) ||
|
|
|
|
(av->pixmap()->height() > KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
pix=av->scaledPixmap(KVI_OPTION_UINT(KviOption_uintAvatarScaleWidth),KVI_OPTION_UINT(KviOption_uintAvatarScaleHeight));
|
|
|
|
else
|
|
|
|
pix=av->pixmap();
|
|
|
|
p.drawPixmap(iAvatarAndTextX,theY,*pix);
|
|
|
|
theY += pix->height() + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bShowGender)
|
|
|
|
{
|
|
|
|
if(e->globalData()->gender()!=KviIrcUserEntry::Unknown)
|
|
|
|
{
|
|
|
|
TQPixmap * ico = g_pIconManager->getBigIcon((e->globalData()->gender()==KviIrcUserEntry::Male) ? "kvi_icon_male.png" : "kvi_icon_female.png");
|
|
|
|
p.drawPixmap(theX,theY+(m_pListView->m_iFontHeight-11)/2,*ico);
|
|
|
|
}
|
|
|
|
if(e->globalData()->isBot())
|
|
|
|
{
|
|
|
|
TQPixmap * ico = g_pIconManager->getBigIcon("kvi_icon_bot.png");
|
|
|
|
p.drawPixmap(theX,theY+(m_pListView->m_iFontHeight-11)/2,*ico);
|
|
|
|
}
|
|
|
|
theX +=11;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bShowState)
|
|
|
|
{
|
|
|
|
if(e->m_lastActionTime)
|
|
|
|
{
|
|
|
|
// the g_pUserChanStatePixmap is 36 x 80 pixels
|
|
|
|
// divided into 6 rows of 5 pixmaps
|
|
|
|
// row 0 is hot , row 5 is cold
|
|
|
|
// left is most active , right is least active
|
|
|
|
// e->m_iTemperature is a signed short , negative values are cold
|
|
|
|
// e->m_lastActionTime is the time of the last action (eventually 0 , if not known)
|
|
|
|
// 6 bit right shift is an aprox division for 64 : really aprox minutes
|
|
|
|
unsigned int uTimeDiff = (((unsigned int)(curTime - e->m_lastActionTime)) >> 6);
|
|
|
|
if(uTimeDiff < 16)
|
|
|
|
{
|
|
|
|
//p.drawRect(theX,theY + 2,10,e->m_iHeight - 4);
|
|
|
|
static int xOffTable[16] =
|
|
|
|
{
|
|
|
|
0 , 8 , 16 , 16 ,
|
|
|
|
24 , 24 , 24 , 24 ,
|
|
|
|
32 , 32 , 32 , 32 ,
|
|
|
|
32 , 32 , 32 , 32
|
|
|
|
};
|
|
|
|
// the temperature now
|
|
|
|
// temp > 100 is hot (offset y = 0)
|
|
|
|
// temp < -100 is cold (offset y = 80)
|
|
|
|
// temp > 30 is half-hot (offset y = 16)
|
|
|
|
// temp < -30 is half-cold (offset y = 64)
|
|
|
|
// temp > 0 is a-bit-hot (offset y = 32)
|
|
|
|
// temp < 0 is a-bit-cold (offset y = 48)
|
|
|
|
|
|
|
|
if(e->m_iTemperature > KVI_MID_TEMPERATURE)
|
|
|
|
{
|
|
|
|
if(e->m_iTemperature > KVI_HALF_HOT_TEMPERATURE)
|
|
|
|
{
|
|
|
|
if(e->m_iTemperature > KVI_HOT_TEMPERATURE)
|
|
|
|
{
|
|
|
|
// hot
|
|
|
|
p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],0,8,16);
|
|
|
|
} else {
|
|
|
|
// half-hot
|
|
|
|
p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],16,8,16);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// bit-hot
|
|
|
|
p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],32,8,16);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(e->m_iTemperature < KVI_HALF_COLD_TEMPERATURE)
|
|
|
|
{
|
|
|
|
if(e->m_iTemperature < KVI_COLD_TEMPERATURE)
|
|
|
|
{
|
|
|
|
// cold
|
|
|
|
p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],80,8,16);
|
|
|
|
} else {
|
|
|
|
// half-cold
|
|
|
|
p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],64,8,16);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// bit-cold
|
|
|
|
p.drawPixmap(theX,theY,*g_pUserChanStatePixmap,xOffTable[uTimeDiff],48,8,16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
theX += 11;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bShowIcons)
|
|
|
|
{
|
|
|
|
//p.drawRect(theX,theY + 2,18,e->m_iHeight - 4);
|
|
|
|
if(e->m_iFlags != 0)
|
|
|
|
{
|
|
|
|
TQPixmap * ico = g_pIconManager->getSmallIcon( \
|
|
|
|
e->globalData()->isAway() ? \
|
|
|
|
( \
|
|
|
|
(e->m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
|
|
|
|
KVI_SMALLICON_CHANOWNERAWAY : ((e->m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
|
|
|
|
KVI_SMALLICON_CHANADMINAWAY : ((e->m_iFlags & KVI_USERFLAG_OP) ? \
|
|
|
|
KVI_SMALLICON_OPAWAY : ((e->m_iFlags & KVI_USERFLAG_HALFOP) ? \
|
|
|
|
KVI_SMALLICON_HALFOPAWAY : ((e->m_iFlags & KVI_USERFLAG_VOICE) ? \
|
|
|
|
KVI_SMALLICON_VOICEAWAY : KVI_SMALLICON_USEROPAWAY))))
|
|
|
|
) \
|
|
|
|
: \
|
|
|
|
( \
|
|
|
|
(e->m_iFlags & KVI_USERFLAG_CHANOWNER) ? \
|
|
|
|
KVI_SMALLICON_CHANOWNER : ((e->m_iFlags & KVI_USERFLAG_CHANADMIN) ? \
|
|
|
|
KVI_SMALLICON_CHANADMIN : ((e->m_iFlags & KVI_USERFLAG_OP) ? \
|
|
|
|
KVI_SMALLICON_OP : ((e->m_iFlags & KVI_USERFLAG_HALFOP) ? \
|
|
|
|
KVI_SMALLICON_HALFOP : ((e->m_iFlags & KVI_USERFLAG_VOICE) ? \
|
|
|
|
KVI_SMALLICON_VOICE : KVI_SMALLICON_USEROP)))) \
|
|
|
|
) \
|
|
|
|
);
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
p.drawPixmap(theX,theY+(fm.lineSpacing()-16/*size of small icon*/)/2,*ico);
|
|
|
|
#else
|
|
|
|
p.drawPixmap(theX,theY+(m_pListView->m_iFontHeight-16/*size of small icon*/)/2,*ico);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
theX +=18;
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
p.drawText(iAvatarAndTextX,theY,wdth - theX,fm.lineSpacing(),TQt::AlignLeft|TQt::AlignVCenter,e->m_szNick);
|
|
|
|
#else
|
|
|
|
p.drawText(iAvatarAndTextX,theY,wdth - theX,m_pListView->m_iFontHeight,TQt::AlignLeft|TQt::AlignVCenter,e->m_szNick);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
|
|
|
|
char flag = m_pListView->getUserFlag(e);
|
|
|
|
if(flag)
|
|
|
|
{
|
|
|
|
TQString ttt = TQChar(flag);
|
|
|
|
ttt += e->m_szNick;
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
p.drawText(iAvatarAndTextX,theY,wdth - theX,fm.lineSpacing(),TQt::AlignLeft|TQt::AlignVCenter,ttt);
|
|
|
|
#else
|
|
|
|
p.drawText(iAvatarAndTextX,theY,wdth - theX,m_pListView->m_iFontHeight,TQt::AlignLeft|TQt::AlignVCenter,ttt);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
p.drawText(iAvatarAndTextX,theY,wdth - theX,fm.lineSpacing(),TQt::AlignLeft|TQt::AlignVCenter,e->m_szNick);
|
|
|
|
#else
|
|
|
|
p.drawText(iAvatarAndTextX,theY,wdth - theX,m_pListView->m_iFontHeight,TQt::AlignLeft|TQt::AlignVCenter,e->m_szNick);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(bColorAllocated) delete pClrFore;
|
|
|
|
}
|
|
|
|
|
|
|
|
theY = bottom;
|
|
|
|
e = e->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
//we really do not need any self-draw borders.
|
|
|
|
//if we will need it, we will draw a better one with system style
|
|
|
|
|
|
|
|
//p.setPen(colorGroup().dark());
|
|
|
|
//p.drawLine(0,0,wdth,0);
|
|
|
|
//p.drawLine(0,0,0,height());
|
|
|
|
//p.setPen(colorGroup().light());
|
|
|
|
//p.drawLine(1,height()-1,wdth,height()-1);
|
|
|
|
//p.drawLine(wdth - 1,1,wdth - 1,height());
|
|
|
|
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
TQPainter qt4SuxBecauseOfThisAdditionalPainter(this);
|
|
|
|
qt4SuxBecauseOfThisAdditionalPainter.drawPixmap(r.left(),r.top(),r.width(),r.height(),*pMemBuffer,r.left(),r.top(),r.width(),r.height());
|
|
|
|
#else
|
|
|
|
bitBlt(TQT_TQPAINTDEVICE(this),r.left(),r.top(),TQT_TQPAINTDEVICE(pMemBuffer),r.left(),r.top(),r.width(),r.height(),TQt::CopyROP,false);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::resizeEvent(TQResizeEvent *)
|
|
|
|
{
|
|
|
|
int iScr = m_pScrollBar->sizeHint().width();
|
|
|
|
m_pScrollBar->setGeometry(width() - iScr,0,iScr,height());
|
|
|
|
m_pScrollBar->setPageStep(height());
|
|
|
|
m_pScrollBar->setLineStep(m_pListView->m_iFontHeight - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::mousePressEvent(TQMouseEvent *e)
|
|
|
|
{
|
|
|
|
setFocus();
|
|
|
|
if(e->button() & Qt::LeftButton)
|
|
|
|
{
|
|
|
|
KviUserListEntry * entry = m_pListView->itemAt(e->pos());
|
|
|
|
if(entry)
|
|
|
|
{
|
|
|
|
if(e->state() & TQt::ShiftButton)
|
|
|
|
{
|
|
|
|
// Multiselect mode
|
|
|
|
if(!entry->m_bSelected)m_pListView->m_iSelectedCount++;
|
|
|
|
entry->m_bSelected = true;
|
|
|
|
if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
update();
|
|
|
|
} else if(e->state() & TQt::ControlButton)
|
|
|
|
{
|
|
|
|
// Invert mode
|
|
|
|
if(!entry->m_bSelected)m_pListView->m_iSelectedCount++;
|
|
|
|
else m_pListView->m_iSelectedCount--;
|
|
|
|
entry->m_bSelected = ! entry->m_bSelected;
|
|
|
|
if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
|
|
|
|
else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
update();
|
|
|
|
} else {
|
|
|
|
// Single select mode
|
|
|
|
bool bThereWasSelection = false;
|
|
|
|
if(m_pListView->m_iSelectedCount > 0)
|
|
|
|
{
|
|
|
|
KviUserListEntry * aux = m_pListView->m_pHeadItem;
|
|
|
|
while(aux)
|
|
|
|
{
|
|
|
|
aux->m_bSelected = false;
|
|
|
|
aux = aux->m_pNext;
|
|
|
|
}
|
|
|
|
bThereWasSelection = true;
|
|
|
|
}
|
|
|
|
entry->m_bSelected = true;
|
|
|
|
m_pListView->m_iSelectedCount = 1;
|
|
|
|
if(!bThereWasSelection)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_pLastEntryUnderMouse = entry;
|
|
|
|
} else if(e->button() & Qt::RightButton)
|
|
|
|
{
|
|
|
|
KviUserListEntry * entry = m_pListView->itemAt(e->pos());
|
|
|
|
if(entry)
|
|
|
|
{
|
|
|
|
if(!entry->m_bSelected){
|
|
|
|
entry->m_bSelected = true;
|
|
|
|
m_pListView->m_iSelectedCount=1;
|
|
|
|
KviPointerHashTableIterator<TQString,KviUserListEntry> it(*(m_pListView->m_pEntryDict));
|
|
|
|
while(it.current())
|
|
|
|
{
|
|
|
|
if(it.current()!=entry)
|
|
|
|
((KviUserListEntry *)it.current())->m_bSelected = false;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(m_pListView->m_iSelectedCount == 1)
|
|
|
|
g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
m_pListView->emitRightClick();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void KviUserListViewArea::keyPressEvent( TQKeyEvent * e )
|
|
|
|
{
|
|
|
|
if(e->key()==TQt::Key_Escape)
|
|
|
|
{
|
|
|
|
if(m_pListView->m_pKviWindow->input())
|
|
|
|
((TQWidget*)(m_pListView->m_pKviWindow->input()))->setFocus();
|
|
|
|
} else {
|
|
|
|
TQString szKey=e->text();
|
|
|
|
if(!szKey.isEmpty())
|
|
|
|
{
|
|
|
|
KviUserListEntry * nick=0;
|
|
|
|
KviUserListEntry * aux = m_pListView->m_pHeadItem;
|
|
|
|
while(aux)
|
|
|
|
{
|
|
|
|
//debug("%s %s %i %s %i",__FILE__,__FUNCTION__,__LINE__,aux->nick().utf8().data(),aux->nick().find(szKey,0,0));
|
|
|
|
if(aux->nick().find(szKey,0,0)==0)
|
|
|
|
{
|
|
|
|
nick=aux;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
aux = aux->m_pNext;
|
|
|
|
}
|
|
|
|
if(nick)
|
|
|
|
{
|
|
|
|
bool bThereWasSelection = false;
|
|
|
|
if(m_pListView->m_iSelectedCount > 0)
|
|
|
|
{
|
|
|
|
aux = m_pListView->m_pHeadItem;
|
|
|
|
while(aux)
|
|
|
|
{
|
|
|
|
aux->m_bSelected = false;
|
|
|
|
aux = aux->m_pNext;
|
|
|
|
}
|
|
|
|
bThereWasSelection = true;
|
|
|
|
}
|
|
|
|
nick->m_bSelected = true;
|
|
|
|
m_pListView->m_iSelectedCount = 1;
|
|
|
|
if(!bThereWasSelection)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::mouseDoubleClickEvent(TQMouseEvent *e)
|
|
|
|
{
|
|
|
|
m_pListView->emitDoubleClick();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::mouseMoveEvent(TQMouseEvent *e)
|
|
|
|
{
|
|
|
|
if(e->state() & Qt::LeftButton)
|
|
|
|
{
|
|
|
|
KviUserListEntry * entry = m_pListView->itemAt(e->pos());
|
|
|
|
if(entry && (entry != m_pLastEntryUnderMouse))
|
|
|
|
{
|
|
|
|
if(e->state() & TQt::ControlButton)
|
|
|
|
{
|
|
|
|
if(entry->m_bSelected)m_pListView->m_iSelectedCount--;
|
|
|
|
else m_pListView->m_iSelectedCount++;
|
|
|
|
entry->m_bSelected = ! entry->m_bSelected;
|
|
|
|
if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
|
|
|
|
else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
} else {
|
|
|
|
if(!entry->m_bSelected)m_pListView->m_iSelectedCount++;
|
|
|
|
entry->m_bSelected = true;
|
|
|
|
if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
m_pLastEntryUnderMouse = entry;
|
|
|
|
} else {
|
|
|
|
// out of the widget ?
|
|
|
|
if(entry == m_pLastEntryUnderMouse)return;
|
|
|
|
if(e->pos().y() < KVI_USERLIST_BORDER_WIDTH)
|
|
|
|
{
|
|
|
|
KviUserListEntry * top = m_pListView->m_pTopItem;
|
|
|
|
if(top)
|
|
|
|
{
|
|
|
|
m_pScrollBar->setValue(m_pScrollBar->value() - top->m_iHeight);
|
|
|
|
if(m_pListView->m_pTopItem != top)
|
|
|
|
{
|
|
|
|
if(e->state() & TQt::ControlButton)
|
|
|
|
{
|
|
|
|
if(m_pListView->m_pTopItem->m_bSelected)m_pListView->m_iSelectedCount--;
|
|
|
|
else m_pListView->m_iSelectedCount++;
|
|
|
|
m_pListView->m_pTopItem->m_bSelected = ! m_pListView->m_pTopItem->m_bSelected;
|
|
|
|
if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
|
|
|
|
else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
} else {
|
|
|
|
if(!m_pListView->m_pTopItem->m_bSelected)m_pListView->m_iSelectedCount++;
|
|
|
|
m_pListView->m_pTopItem->m_bSelected = true;
|
|
|
|
if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_pLastEntryUnderMouse = top;
|
|
|
|
} else if(e->pos().y() > (height() - KVI_USERLIST_BORDER_WIDTH))
|
|
|
|
{
|
|
|
|
KviUserListEntry * bottom = m_pListView->m_pTopItem;
|
|
|
|
if(bottom)
|
|
|
|
{
|
|
|
|
int theY = KVI_USERLIST_BORDER_WIDTH - m_iTopItemOffset;
|
|
|
|
while(bottom && (theY < height()))
|
|
|
|
{
|
|
|
|
theY+= bottom->m_iHeight;
|
|
|
|
bottom = bottom->m_pNext;
|
|
|
|
}
|
|
|
|
if(!bottom)bottom = m_pListView->m_pTailItem;
|
|
|
|
if(bottom)
|
|
|
|
{
|
|
|
|
m_pScrollBar->setValue(m_pScrollBar->value() + bottom->m_iHeight);
|
|
|
|
if(bottom != m_pLastEntryUnderMouse)
|
|
|
|
{
|
|
|
|
if(e->state() & TQt::ControlButton)
|
|
|
|
{
|
|
|
|
if(bottom->m_bSelected)m_pListView->m_iSelectedCount--;
|
|
|
|
else m_pListView->m_iSelectedCount++;
|
|
|
|
bottom->m_bSelected = ! bottom->m_bSelected;
|
|
|
|
if(m_pListView->m_iSelectedCount == 0)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,false);
|
|
|
|
else if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
} else {
|
|
|
|
if(!bottom->m_bSelected)m_pListView->m_iSelectedCount++;
|
|
|
|
bottom->m_bSelected = true;
|
|
|
|
if(m_pListView->m_iSelectedCount == 1)g_pFrame->childWindowSelectionStateChange(m_pListView->m_pKviWindow,true);
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_pLastEntryUnderMouse = bottom;
|
|
|
|
} else m_pLastEntryUnderMouse = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::mouseReleaseEvent(TQMouseEvent *)
|
|
|
|
{
|
|
|
|
m_pLastEntryUnderMouse = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KviUserListViewArea::wheelEvent(TQWheelEvent *e)
|
|
|
|
{
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
static bool bHere = false; // TQt4(<= 4.2.2) has a nasty bug that makes the re-sent wheelEvent to cause infinite recursion
|
|
|
|
if(bHere)return;
|
|
|
|
bHere = true;
|
|
|
|
#endif
|
|
|
|
g_pApp->sendEvent(m_pScrollBar,e);
|
|
|
|
#ifdef COMPILE_USE_QT4
|
|
|
|
bHere = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kvi_userlistview.moc"
|