Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 93052
Collapse All | Expand All

(-)../work-orig/kopete-3.4.0/kopete/kopete/chatwindow/chatmessagepart.cpp (-9 / +64 lines)
Lines 23-31 Link Here
23
#include <qtooltip.h>
23
#include <qtooltip.h>
24
#include <qrect.h>
24
#include <qrect.h>
25
#include <qcursor.h>
25
#include <qcursor.h>
26
#include <qtextcodec.h> 
26
27
27
#include <dom/dom_doc.h>
28
#include <dom/dom_doc.h>
28
#include <dom/dom_text.h>
29
#include <dom/dom_text.h>
30
#include <dom/dom_string.h>
29
#include <dom/dom_element.h>
31
#include <dom/dom_element.h>
30
#include <dom/html_base.h>
32
#include <dom/html_base.h>
31
#include <dom/html_document.h>
33
#include <dom/html_document.h>
Lines 162-168 ChatMessagePart::ChatMessagePart( Kopete Link Here
162
{
164
{
163
	d->xsltParser = new Kopete::XSLT( KopetePrefs::prefs()->styleContents() );
165
	d->xsltParser = new Kopete::XSLT( KopetePrefs::prefs()->styleContents() );
164
	d->transformAllMessages = ( d->xsltParser->flags() & Kopete::XSLT::TransformAllMessages );
166
	d->transformAllMessages = ( d->xsltParser->flags() & Kopete::XSLT::TransformAllMessages );
165
167
        codepage="Unicode";
166
	backgroundFile = 0;
168
	backgroundFile = 0;
167
	root = 0;
169
	root = 0;
168
	messageId = 0;
170
	messageId = 0;
Lines 176-187 ChatMessagePart::ChatMessagePart( Kopete Link Here
176
	setMetaRefreshEnabled( false );
178
	setMetaRefreshEnabled( false );
177
179
178
	begin();
180
	begin();
179
	write( QString::fromLatin1( "<html><head>\n"
181
        write( QString::fromLatin1( "<html><head>\n"
180
		"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=") +
182
			"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=") +
181
		encoding() + QString::fromLatin1("\">\n<style>") + styleHTML() +
183
			encoding() + QString::fromLatin1("\">\n<style>") + styleHTML() +
182
		QString::fromLatin1("</style></head><body></body></html>") );
184
	QString::fromLatin1("</style></head><body></body></html>") );
183
	end();
185
	end();
184
185
	view()->setFocusPolicy( QWidget::NoFocus );
186
	view()->setFocusPolicy( QWidget::NoFocus );
186
187
187
	new ToolTip( this );
188
	new ToolTip( this );
Lines 338-344 void ChatMessagePart::slotAppearanceChan Link Here
338
	slotRefreshNodes();
339
	slotRefreshNodes();
339
}
340
}
340
341
341
void ChatMessagePart::appendMessage( Kopete::Message &message )
342
void ChatMessagePart::appendMessage( Kopete::Message &message,bool encode)
342
{
343
{
343
	//parse emoticons and URL now.
344
	//parse emoticons and URL now.
344
	message.setBody( message.parsedBody() , Kopete::Message::ParsedHTML );
345
	message.setBody( message.parsedBody() , Kopete::Message::ParsedHTML );
Lines 348-354 void ChatMessagePart::appendMessage( Kop Link Here
348
	message.setRtfOverride( d->rtfOverride );
349
	message.setRtfOverride( d->rtfOverride );
349
350
350
	messageMap.append(  message.asXML().toString() );
351
	messageMap.append(  message.asXML().toString() );
351
352
	uint bufferLen = (uint)KopetePrefs::prefs()->chatViewBufferSize();
352
	uint bufferLen = (uint)KopetePrefs::prefs()->chatViewBufferSize();
353
353
354
	// transform all messages every time. needed for Adium style.
354
	// transform all messages every time. needed for Adium style.
Lines 364-370 void ChatMessagePart::appendMessage( Kop Link Here
364
		QDomDocument domMessage = message.asXML();
364
		QDomDocument domMessage = message.asXML();
365
		domMessage.documentElement().setAttribute( QString::fromLatin1( "id" ), QString::number( messageId ) );
365
		domMessage.documentElement().setAttribute( QString::fromLatin1( "id" ), QString::number( messageId ) );
366
		QString resultHTML = addNickLinks( d->xsltParser->transform( domMessage.toString() ) );
366
		QString resultHTML = addNickLinks( d->xsltParser->transform( domMessage.toString() ) );
367
367
		if(encode && (codepage != "Unicode"))
368
		{
369
			QCString locallyEncoded = resultHTML.ascii();
370
			QTextCodec *codec = QTextCodec::codecForName(codepage.ascii());
371
			if(codec)
372
			   resultHTML = codec->toUnicode( locallyEncoded );
373
		}
368
		QString direction = ( message.plainBody().isRightToLeft() ? QString::fromLatin1("rtl") : QString::fromLatin1("ltr") );
374
		QString direction = ( message.plainBody().isRightToLeft() ? QString::fromLatin1("rtl") : QString::fromLatin1("ltr") );
369
		DOM::HTMLElement newNode = document().createElement( QString::fromLatin1("span") );
375
		DOM::HTMLElement newNode = document().createElement( QString::fromLatin1("span") );
370
		newNode.setAttribute( QString::fromLatin1("dir"), direction );
376
		newNode.setAttribute( QString::fromLatin1("dir"), direction );
Lines 891-893 void ChatMessagePart::emitTooltipEvent( Link Here
891
897
892
// vim: set noet ts=4 sts=4 sw=4:
898
// vim: set noet ts=4 sts=4 sw=4:
893
899
900
void ChatMessagePart::slotConvert(const QString& string)
901
{
902
903
    
904
    DOM::DOMString text=htmlDocument().body().innerHTML();
905
    if(codepage!="Unicode")
906
    {
907
	QCString locallyEncoded;
908
	QTextCodec *codec = QTextCodec::codecForName(codepage.ascii());
909
	if(!codec)
910
	{
911
		kdDebug()<<"codec for this name not exisit\n";
912
		return;	
913
	}
914
	locallyEncoded=codec->fromUnicode(text.string());
915
	if(string!="Unicode")
916
	{
917
		QTextCodec *codec = QTextCodec::codecForName(string.ascii());
918
		if(!codec)
919
		{
920
			kdDebug()<<"codec for this name not exisit\n";
921
			return;	
922
		}
923
		text=codec->toUnicode(locallyEncoded);
924
	}
925
	else 
926
	    text=QString(locallyEncoded);
927
    }
928
    else
929
    {
930
	if(string!="Unicode")
931
	{
932
		QTextCodec *codec = QTextCodec::codecForName(string.ascii());
933
		if(!codec)
934
		{
935
			kdDebug()<<"codec for this name not exisit\n";
936
			return;	
937
		}
938
		text=codec->toUnicode(text.string().ascii());
939
	}
940
    }
941
    htmlDocument().body().setInnerHTML(text);
942
    setCodepage(string);    
943
}
944
945
void ChatMessagePart::setCodepage(const QString& page)
946
{
947
    codepage=page;
948
}
(-)../work-orig/kopete-3.4.0/kopete/kopete/chatwindow/chatmessagepart.h (-1 / +4 lines)
Lines 55-60 public: Link Here
55
	 * use 
55
	 * use 
56
	 */
56
	 */
57
	void keepScrolledDown();
57
	void keepScrolledDown();
58
    void setCodepage(const QString& page);
58
59
59
public slots:
60
public slots:
60
	/**
61
	/**
Lines 91-97 public slots: Link Here
91
	 * Appends a message to the messave view
92
	 * Appends a message to the messave view
92
	 * @param message The message to be appended
93
	 * @param message The message to be appended
93
	 */
94
	 */
94
	void appendMessage( Kopete::Message &message );
95
	void appendMessage( Kopete::Message &message,bool encode=true );
96
        void slotConvert(const QString& string);
95
97
96
signals:
98
signals:
97
	/**
99
	/**
Lines 157-162 private: Link Here
157
	KAction *printAction;
159
	KAction *printAction;
158
	KAction *closeAction;
160
	KAction *closeAction;
159
	KAction *copyURLAction;
161
	KAction *copyURLAction;
162
	QString codepage;
160
163
161
	void readOverrides();
164
	void readOverrides();
162
165
(-)../work-orig/kopete-3.4.0/kopete/kopete/chatwindow/chatview.cpp (-2 / +5 lines)
Lines 693-700 void ChatView::setCaption( const QString Link Here
693
void ChatView::appendMessage(Kopete::Message &message)
693
void ChatView::appendMessage(Kopete::Message &message)
694
{
694
{
695
	remoteTyping( message.from(), false );
695
	remoteTyping( message.from(), false );
696
696
	
697
	messagePart()->appendMessage( message );
697
	if ( message.direction() != Kopete::Message::Inbound )
698
	   messagePart()->appendMessage( message,false);
699
	else
700
		messagePart()->appendMessage(message);		
698
	if( !d->isActive )
701
	if( !d->isActive )
699
	{
702
	{
700
		switch ( message.importance() )
703
		switch ( message.importance() )
(-)../work-orig/kopete-3.4.0/kopete/kopete/chatwindow/kopetechatwindow.cpp (+122 lines)
Lines 31-36 Link Here
31
#include <klocale.h>
31
#include <klocale.h>
32
#include <kmenubar.h>
32
#include <kmenubar.h>
33
#include <kconfig.h>
33
#include <kconfig.h>
34
#include <kcombobox.h>
34
#include <kpopupmenu.h>
35
#include <kpopupmenu.h>
35
#include <kiconloader.h>
36
#include <kiconloader.h>
36
#include <kdebug.h>
37
#include <kdebug.h>
Lines 48-53 Link Here
48
#include <kstdaccel.h>
49
#include <kstdaccel.h>
49
50
50
#include "chatmessagepart.h"
51
#include "chatmessagepart.h"
52
#include "chatmemberslistwidget.h"
51
#include "chattexteditpart.h"
53
#include "chattexteditpart.h"
52
#include "chatview.h"
54
#include "chatview.h"
53
#include "../kopeteapplication.h"
55
#include "../kopeteapplication.h"
Lines 163-168 KopeteChatWindow *KopeteChatWindow::wind Link Here
163
	return myWindow;
165
	return myWindow;
164
}
166
}
165
167
168
/**
169
 * 
170
 * @param parent 
171
 * @param name 
172
 * @return 
173
 */
166
KopeteChatWindow::KopeteChatWindow( QWidget *parent, const char* name )
174
KopeteChatWindow::KopeteChatWindow( QWidget *parent, const char* name )
167
	: KParts::MainWindow( parent, name )
175
	: KParts::MainWindow( parent, name )
168
{
176
{
Lines 215-220 KopeteChatWindow::KopeteChatWindow( QWid Link Here
215
223
216
	KGlobal::config()->setGroup( QString::fromLatin1("ChatWindowSettings") );
224
	KGlobal::config()->setGroup( QString::fromLatin1("ChatWindowSettings") );
217
	m_alwaysShowTabs = KGlobal::config()->readBoolEntry( QString::fromLatin1("AlwaysShowTabs"), false );
225
	m_alwaysShowTabs = KGlobal::config()->readBoolEntry( QString::fromLatin1("AlwaysShowTabs"), false );
226
	kdDebug(14010)<<"creating toolbar"<<endl;
227
	m_encoding=new KComboBox(toolBar("convert"));
228
	initEncodings();
229
	
230
218
//	kdDebug( 14010 ) << k_funcinfo << "Open Windows: " << windows.count() << endl;
231
//	kdDebug( 14010 ) << k_funcinfo << "Open Windows: " << windows.count() << endl;
219
	kapp->ref();
232
	kapp->ref();
220
}
233
}
Lines 802-807 void KopeteChatWindow::setActiveView( QW Link Here
802
	{
815
	{
803
		disconnect( m_activeView, SIGNAL( canSendChanged(bool) ), this, SLOT( slotUpdateSendEnabled() ) );
816
		disconnect( m_activeView, SIGNAL( canSendChanged(bool) ), this, SLOT( slotUpdateSendEnabled() ) );
804
		guiFactory()->removeClient(m_activeView->msgManager());
817
		guiFactory()->removeClient(m_activeView->msgManager());
818
		disconnect(m_encoding,SIGNAL(activated( const QString&)),
819
		m_activeView->messagePart(),SLOT(slotConvert( const QString&)));
820
		disconnect(m_encoding,SIGNAL(activated( const QString&)),
821
		this,SLOT(slotEncodingSelected( const QString&)));
822
805
	}
823
	}
806
824
807
	guiFactory()->addClient(view->msgManager());
825
	guiFactory()->addClient(view->msgManager());
Lines 812-822 void KopeteChatWindow::setActiveView( QW Link Here
812
830
813
	m_activeView = view;
831
	m_activeView = view;
814
832
833
834
	
815
	if( !chatViewList.contains( view ) )
835
	if( !chatViewList.contains( view ) )
816
		attachChatView( view );
836
		attachChatView( view );
817
837
818
	connect( m_activeView, SIGNAL( canSendChanged(bool) ), this, SLOT( slotUpdateSendEnabled() ) );
838
	connect( m_activeView, SIGNAL( canSendChanged(bool) ), this, SLOT( slotUpdateSendEnabled() ) );
819
839
840
	Kopete::ContactPtrList cList;
841
	cList=m_activeView->membersList()->session()->members();
842
	Kopete::Contact* ct;	
843
	ct=cList.first();
844
	QString uid;
845
	if(ct)
846
	{
847
	        KConfig* cf=KGlobal::config();
848
		uid=ct->contactId();
849
		QString gr=cf->group();
850
		cf->setGroup("Encodings");
851
		QString enc=cf->readEntry(uid,"Unicode");	
852
		cf->setGroup(gr);
853
		m_activeView->messagePart()->slotConvert(enc);
854
		int i;
855
		for(i=0;i<m_encoding->maxCount();i++)
856
		{
857
		    if(m_encoding->text(i)==enc)
858
		    {
859
		         m_encoding->setCurrentItem(i);
860
		         break;
861
		    }
862
		}	
863
	}
864
865
	connect(m_encoding,SIGNAL(activated( const QString&)),
866
	m_activeView->messagePart(),SLOT(slotConvert( const QString&)));
867
	connect(m_encoding,SIGNAL(activated( const QString&)),
868
	this,SLOT(slotEncodingSelected( const QString&)));
869
		
820
	//Tell it it is active
870
	//Tell it it is active
821
	m_activeView->setActive( true );
871
	m_activeView->setActive( true );
822
872
Lines 1120-1125 void KopeteChatWindow::slotConfKeys() Link Here
1120
	dlg.configure();
1170
	dlg.configure();
1121
}
1171
}
1122
1172
1173
/**
1174
 * 
1175
 */
1123
void KopeteChatWindow::slotConfToolbar()
1176
void KopeteChatWindow::slotConfToolbar()
1124
{
1177
{
1125
	saveMainWindowSettings(KGlobal::config(), QString::fromLatin1( "KopeteChatWindow" ));
1178
	saveMainWindowSettings(KGlobal::config(), QString::fromLatin1( "KopeteChatWindow" ));
Lines 1142-1144 void KopeteChatWindow::slotConfToolbar() Link Here
1142
1195
1143
// vim: set noet ts=4 sts=4 sw=4:
1196
// vim: set noet ts=4 sts=4 sw=4:
1144
1197
1198
1199
1200
void KopeteChatWindow::initEncodings()
1201
{
1202
	QStringList lst=QStringList::split('\n',
1203
"Unicode\n\
1204
Big5\n\
1205
Big5-HKSCS\n\
1206
eucJP\n\
1207
eucKR\n\
1208
GB2312\n\
1209
GBK\n\
1210
GB18030\n\
1211
JIS7\n\
1212
Shift-JIS\n\
1213
TSCII\n\
1214
KOI8-R\n\
1215
KOI8-U\n\
1216
ISO8859-1\n\
1217
ISO8859-2\n\
1218
ISO8859-3\n\
1219
ISO8859-4\n\
1220
ISO8859-5\n\
1221
ISO8859-6\n\
1222
ISO8859-7\n\
1223
ISO8859-8\n\
1224
ISO8859-8-i\n\
1225
ISO8859-9\n\
1226
ISO8859-10\n\
1227
ISO8859-13\n\
1228
ISO8859-14\n\
1229
ISO8859-15\n\
1230
IBM 850\n\
1231
IBM 866\n\
1232
CP874\n\
1233
CP1250\n\
1234
CP1251\n\
1235
CP1252\n\
1236
CP1253\n\
1237
CP1254\n\
1238
CP1255\n\
1239
CP1256\n\
1240
CP1257\n\
1241
CP1258\n\
1242
Apple Roman\n\
1243
TIS-620");
1244
	m_encoding->insertStringList(lst);
1245
}
1246
1247
1248
void KopeteChatWindow::slotEncodingSelected(const QString& string)
1249
{
1250
        if(!m_activeView)
1251
		return;
1252
	Kopete::ContactPtrList cList;
1253
	cList=m_activeView->membersList()->session()->members();
1254
	Kopete::Contact* ct;	
1255
	ct=cList.first();
1256
	QString uid;
1257
	if(ct)
1258
	{
1259
	        KConfig* cf=KGlobal::config();
1260
		uid=ct->contactId();
1261
		QString gr=cf->group();
1262
		cf->setGroup("Encodings");
1263
		cf->writeEntry(uid,string);	
1264
		cf->setGroup(gr);
1265
	}
1266
}
(-)../work-orig/kopete-3.4.0/kopete/kopete/chatwindow/kopetechatwindow.cpp.orig (+1144 lines)
Line 0 Link Here
1
/*
2
    kopetechatwindow.cpp - Chat Window
3
4
    Copyright (c) 2002-2005 by Olivier Goffart       <ogoffart@ kde.org>
5
    Copyright (c) 2003-2004 by Richard Smith         <kde@metafoo.co.uk>
6
    Copyright (C) 2002      by James Grant
7
    Copyright (c) 2002      by Stefan Gehn           <metz AT gehn.net>
8
    Copyright (c) 2002-2004 by Martijn Klingens      <klingens@kde.org>
9
10
    Kopete    (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
11
12
    *************************************************************************
13
    *                                                                       *
14
    * This program is free software; you can redistribute it and/or modify  *
15
    * it under the terms of the GNU General Public License as published by  *
16
    * the Free Software Foundation; either version 2 of the License, or     *
17
    * (at your option) any later version.                                   *
18
    *                                                                       *
19
    *************************************************************************
20
*/
21
22
#include <qtimer.h>
23
#include <qhbox.h>
24
#include <qvbox.h>
25
#include <qlayout.h>
26
#include <qtooltip.h>
27
#include <qfileinfo.h>
28
29
#include <kapplication.h>
30
#include <kcursor.h>
31
#include <klocale.h>
32
#include <kmenubar.h>
33
#include <kconfig.h>
34
#include <kpopupmenu.h>
35
#include <kiconloader.h>
36
#include <kdebug.h>
37
#include <kwin.h>
38
#include <ktempfile.h>
39
#include <kkeydialog.h>
40
#include <kedittoolbar.h>
41
#include <kstatusbar.h>
42
#include <kpushbutton.h>
43
#include <ktabwidget.h>
44
#include <kstandarddirs.h>
45
#include <kdialog.h>
46
#include <kstringhandler.h>
47
#include <ksqueezedtextlabel.h>
48
#include <kstdaccel.h>
49
50
#include "chatmessagepart.h"
51
#include "chattexteditpart.h"
52
#include "chatview.h"
53
#include "../kopeteapplication.h"
54
#include "kopetechatwindow.h"
55
#include "kopeteemoticonaction.h"
56
#include "kopetegroup.h"
57
#include "kopetemessagemanager.h"
58
#include "kopetemetacontact.h"
59
#include "kopetepluginmanager.h"
60
#include "kopeteprefs.h"
61
#include "kopeteprotocol.h"
62
#include "kopetestdaction.h"
63
#include "kopeteviewmanager.h"
64
65
#include <qtoolbutton.h>
66
#include <kactionclasses.h>
67
68
typedef QMap<Kopete::Account*,KopeteChatWindow*> AccountMap;
69
typedef QMap<Kopete::Group*,KopeteChatWindow*> GroupMap;
70
typedef QMap<Kopete::MetaContact*,KopeteChatWindow*> MetaContactMap;
71
typedef QPtrList<KopeteChatWindow> WindowList;
72
73
namespace
74
{
75
	AccountMap accountMap;
76
	GroupMap groupMap;
77
	MetaContactMap mcMap;
78
	WindowList windows;
79
}
80
81
KopeteChatWindow *KopeteChatWindow::window( Kopete::ChatSession *manager )
82
{
83
	bool windowCreated = false;
84
	KopeteChatWindow *myWindow;
85
86
	//Take the first and the first? What else?
87
	Kopete::Group *group = 0L;
88
	Kopete::ContactPtrList members = manager->members();
89
	Kopete::MetaContact *metaContact = members.first()->metaContact();
90
91
	if ( metaContact )
92
	{
93
		Kopete::GroupList gList = metaContact->groups();
94
		group = gList.first();
95
	}
96
97
	switch( KopetePrefs::prefs()->chatWindowPolicy() )
98
	{
99
		case GROUP_BY_ACCOUNT: //Open chats from the same protocol in the same window
100
			if( accountMap.contains( manager->account() ) )
101
				myWindow = accountMap[ manager->account() ];
102
			else
103
				windowCreated = true;
104
			break;
105
106
		case GROUP_BY_GROUP: //Open chats from the same group in the same window
107
			if( group && groupMap.contains( group ) )
108
				myWindow = groupMap[ group ];
109
			else
110
				windowCreated = true;
111
			break;
112
113
		case GROUP_BY_METACONTACT: //Open chats from the same metacontact in the same window
114
			if( mcMap.contains( metaContact ) )
115
				myWindow = mcMap[ metaContact ];
116
			else
117
				windowCreated = true;
118
			break;
119
120
		case GROUP_ALL: //Open all chats in the same window
121
			if( windows.isEmpty() )
122
				windowCreated = true;
123
			else
124
			{
125
				//Here we are finding the window with the most tabs and
126
				//putting it there. Need this for the cases where config changes
127
				//midstream
128
129
				int viewCount = -1;
130
				for ( KopeteChatWindow *thisWindow = windows.first(); thisWindow; thisWindow = windows.next() )
131
				{
132
					if( thisWindow->chatViewCount() > viewCount )
133
					{
134
						myWindow = thisWindow;
135
						viewCount = thisWindow->chatViewCount();
136
					}
137
				}
138
			}
139
			break;
140
141
		case NEW_WINDOW: //Open every chat in a new window
142
		default:
143
			windowCreated = true;
144
			break;
145
	}
146
147
	if ( windowCreated )
148
	{
149
		myWindow = new KopeteChatWindow();
150
151
		if ( !accountMap.contains( manager->account() ) )
152
			accountMap.insert( manager->account(), myWindow );
153
154
		if ( !mcMap.contains( metaContact ) )
155
			mcMap.insert( metaContact, myWindow );
156
157
		if ( group && !groupMap.contains( group ) )
158
			groupMap.insert( group, myWindow );
159
	}
160
161
//	kdDebug( 14010 ) << k_funcinfo << "Open Windows: " << windows.count() << endl;
162
163
	return myWindow;
164
}
165
166
KopeteChatWindow::KopeteChatWindow( QWidget *parent, const char* name )
167
	: KParts::MainWindow( parent, name )
168
{
169
	m_activeView = 0L;
170
	m_popupView = 0L;
171
	backgroundFile = 0L;
172
	updateBg = true;
173
	m_tabBar = 0L;
174
175
	initActions();
176
177
	QVBox *vBox = new QVBox( this );
178
	vBox->setLineWidth( 0 );
179
	vBox->setSpacing( 0 );
180
	vBox->setFrameStyle( QFrame::NoFrame );
181
	// set default window size.  This could be removed by fixing the size hints of the contents
182
	resize( 500, 500 );
183
	setCentralWidget( vBox );
184
185
	mainArea = new QFrame( vBox );
186
	mainArea->setLineWidth( 0 );
187
	mainArea->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
188
	mainLayout = new QVBoxLayout( mainArea );
189
190
	if ( KopetePrefs::prefs()->chatWShowSend() )
191
	{
192
		//Send Button
193
		m_button_send = new KPushButton( i18n("Send"), statusBar() );
194
		m_button_send->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
195
		m_button_send->setEnabled( false );
196
		m_button_send->setFont( statusBar()->font() );
197
		m_button_send->setFixedHeight( statusBar()->sizeHint().height() );
198
		connect( m_button_send, SIGNAL( clicked() ), this, SLOT( slotSendMessage() ) );
199
		statusBar()->addWidget( m_button_send, 0, true );
200
	}
201
	else
202
		m_button_send = 0L;
203
204
	m_status_text = new KSqueezedTextLabel( i18n("Ready."), statusBar(), "m_status_text" );
205
	m_status_text->setAlignment( AlignLeft | AlignVCenter );
206
	m_status_text->setFont( statusBar()->font() );
207
	m_status_text->setFixedHeight( statusBar()->sizeHint().height() );
208
	statusBar()->addWidget( m_status_text, 1 );
209
210
	readOptions();
211
	setWFlags( Qt::WDestructiveClose );
212
213
	windows.append( this );
214
	windowListChanged();
215
216
	KGlobal::config()->setGroup( QString::fromLatin1("ChatWindowSettings") );
217
	m_alwaysShowTabs = KGlobal::config()->readBoolEntry( QString::fromLatin1("AlwaysShowTabs"), false );
218
//	kdDebug( 14010 ) << k_funcinfo << "Open Windows: " << windows.count() << endl;
219
	kapp->ref();
220
}
221
222
KopeteChatWindow::~KopeteChatWindow()
223
{
224
	//	kdDebug( 14010 ) << k_funcinfo << endl;
225
226
	emit( closing( this ) );
227
228
	for( AccountMap::Iterator it = accountMap.begin(); it != accountMap.end(); )
229
	{
230
		AccountMap::Iterator mayDeleteIt = it;
231
		++it;
232
		if( mayDeleteIt.data() == this )
233
			accountMap.remove( mayDeleteIt.key() );
234
	}
235
236
	for( GroupMap::Iterator it = groupMap.begin(); it != groupMap.end(); )
237
	{
238
		GroupMap::Iterator mayDeleteIt = it;
239
		++it;
240
		if( mayDeleteIt.data() == this )
241
			groupMap.remove( mayDeleteIt.key() );
242
	}
243
244
	for( MetaContactMap::Iterator it = mcMap.begin(); it != mcMap.end(); )
245
	{
246
		MetaContactMap::Iterator mayDeleteIt = it;
247
		++it;
248
		if( mayDeleteIt.data() == this )
249
			mcMap.remove( mayDeleteIt.key() );
250
	}
251
252
	windows.remove( this );
253
	windowListChanged();
254
255
//	kdDebug( 14010 ) << "Open Windows: " << windows.count() << endl;
256
257
	saveOptions();
258
259
	if( backgroundFile )
260
	{
261
		backgroundFile->close();
262
		backgroundFile->unlink();
263
		delete backgroundFile;
264
	}
265
266
	delete anim;
267
	kapp->deref();
268
}
269
270
void KopeteChatWindow::windowListChanged()
271
{
272
	// update all windows' Move Tab to Window action
273
	for ( QPtrListIterator<KopeteChatWindow> it( windows ); *it; ++it )
274
		(*it)->checkDetachEnable();
275
}
276
277
void KopeteChatWindow::slotNickComplete()
278
{
279
	if( m_activeView )
280
		m_activeView->nickComplete();
281
}
282
283
void KopeteChatWindow::slotTabContextMenu( QWidget *tab, const QPoint &pos )
284
{
285
	m_popupView = static_cast<ChatView*>( tab );
286
287
	KPopupMenu *popup = new KPopupMenu;
288
	popup->insertTitle( KStringHandler::rsqueeze( m_popupView->caption() ) );
289
290
	actionContactMenu->plug( popup );
291
	popup->insertSeparator();
292
	actionTabPlacementMenu->plug( popup );
293
	tabDetach->plug( popup );
294
	actionDetachMenu->plug( popup );
295
	tabClose->plug( popup );
296
	popup->exec( pos );
297
298
	delete popup;
299
	m_popupView = 0;
300
}
301
302
ChatView *KopeteChatWindow::activeView()
303
{
304
	return m_activeView;
305
}
306
307
void KopeteChatWindow::initActions(void)
308
{
309
	KActionCollection *coll = actionCollection();
310
311
	createStandardStatusBarAction();
312
313
	chatSend = new KAction( i18n( "&Send Message" ), QString::fromLatin1( "mail_send" ), 0,
314
		this, SLOT( slotSendMessage() ), coll, "chat_send" );
315
	//Default to 'Return' for sending messages
316
	chatSend->setShortcut( QKeySequence(Key_Return) );
317
	chatSend->setEnabled( false );
318
319
 	KStdAction::save ( this, SLOT(slotChatSave()), coll );
320
 	KStdAction::print ( this, SLOT(slotChatPrint()), coll );
321
	KStdAction::quit ( this, SLOT(close()), coll );
322
323
	tabClose = KStdAction::close ( this, SLOT(slotChatClosed()), coll, "tabs_close" );
324
325
	tabRight=new KAction( i18n( "&Activate Next Tab" ), 0, KStdAccel::tabNext(),
326
		this, SLOT( slotNextTab() ), coll, "tabs_right" );
327
	tabLeft=new KAction( i18n( "&Activate Previous Tab" ), 0, KStdAccel::tabPrev(),
328
		this, SLOT( slotPreviousTab() ), coll, "tabs_left" );
329
	tabLeft->setEnabled( false );
330
	tabRight->setEnabled( false );
331
332
	nickComplete = new KAction( i18n( "Nic&k Completion" ), QString::null, 0, this, SLOT( slotNickComplete() ), coll , "nick_compete");
333
	nickComplete->setShortcut( QKeySequence( Key_Tab ) );
334
335
	tabDetach = new KAction( i18n( "&Detach Chat" ), QString::fromLatin1( "tab_breakoff" ), 0,
336
		this, SLOT( slotDetachChat() ), coll, "tabs_detach" );
337
	tabDetach->setEnabled( false );
338
339
	actionDetachMenu = new KActionMenu( i18n( "&Move Tab to Window" ), QString::fromLatin1( "tab_breakoff" ), coll, "tabs_detachmove" );
340
	actionDetachMenu->setDelayed( false );
341
342
	connect ( actionDetachMenu->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotPrepareDetachMenu()) );
343
	connect ( actionDetachMenu->popupMenu(), SIGNAL(activated(int)), this, SLOT(slotDetachChat(int)) );
344
345
	actionTabPlacementMenu = new KActionMenu( i18n( "&Tab Placement" ), coll, "tabs_placement" );
346
	connect ( actionTabPlacementMenu->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotPreparePlacementMenu()) );
347
	connect ( actionTabPlacementMenu->popupMenu(), SIGNAL(activated(int)), this, SLOT(slotPlaceTabs(int)) );
348
349
	tabDetach->setShortcut( QKeySequence(CTRL + SHIFT + Key_B) );
350
351
	KStdAction::cut( this, SLOT(slotCut()), coll);
352
	KStdAction::copy( this, SLOT(slotCopy()), coll);
353
	KStdAction::paste( this, SLOT(slotPaste()), coll);
354
355
	new KAction( i18n( "Set Default &Font..." ), QString::fromLatin1( "charset" ), 0, this, SLOT( slotSetFont() ), coll, "format_font" );
356
	new KAction( i18n( "Set Default Text &Color..." ), QString::fromLatin1( "pencil" ), 0, this, SLOT( slotSetFgColor() ), coll, "format_fgcolor" );
357
	new KAction( i18n( "Set &Background Color..." ), QString::fromLatin1( "fill" ), 0, this, SLOT( slotSetBgColor() ), coll, "format_bgcolor" );
358
359
	historyUp = new KAction( i18n( "Previous History" ), QString::null, 0,
360
		this, SLOT( slotHistoryUp() ), coll, "history_up" );
361
	historyUp->setShortcut( QKeySequence(CTRL + Key_Up) );
362
363
	historyDown = new KAction( i18n( "Next History" ), QString::null, 0,
364
		this, SLOT( slotHistoryDown() ), coll, "history_down" );
365
	historyDown->setShortcut( QKeySequence(CTRL + Key_Down) );
366
367
	KStdAction::prior( this, SLOT( slotPageUp() ), coll, "scroll_up" );
368
	KStdAction::next( this, SLOT( slotPageDown() ), coll, "scroll_down" );
369
370
	KStdAction::showMenubar( this, SLOT(slotViewMenuBar()), coll );
371
372
	membersLeft = new KToggleAction( i18n( "Place to Left of Chat Area" ), QString::null, 0,
373
		this, SLOT( slotViewMembersLeft() ), coll, "options_membersleft" );
374
	membersRight = new KToggleAction( i18n( "Place to Right of Chat Area" ), QString::null, 0,
375
		this, SLOT( slotViewMembersRight() ), coll, "options_membersright" );
376
	toggleMembers = new KToggleAction( i18n( "Show" ), QString::null, 0,
377
		this, SLOT( slotToggleViewMembers() ), coll, "options_togglemembers" );
378
#if KDE_IS_VERSION(3,2,90)
379
	toggleMembers->setCheckedState(i18n("Hide"));
380
#endif
381
382
	actionSmileyMenu = new KopeteEmoticonAction( coll, "format_smiley" );
383
	actionSmileyMenu->setDelayed( false );
384
	connect(actionSmileyMenu, SIGNAL(activated(const QString &)), this, SLOT(slotSmileyActivated(const QString &)));
385
386
	actionContactMenu = new KActionMenu(i18n("Co&ntacts"), coll, "contacts_menu" );
387
	actionContactMenu->setDelayed( false );
388
	connect ( actionContactMenu->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(slotPrepareContactMenu()) );
389
390
	// add configure key bindings menu item
391
#if KDE_IS_VERSION(3, 2, 90)
392
	KStdAction::keyBindings( guiFactory(), SLOT( configureShortcuts() ), coll );
393
#else  // when we will drop the KDE 3.2 compatibility, do not forget to remove  slotConfKeys
394
	KStdAction::keyBindings( this, SLOT( slotConfKeys() ), coll );
395
	#endif
396
397
398
	KStdAction::configureToolbars(this, SLOT(slotConfToolbar()), coll);
399
	KopeteStdAction::preferences( coll , "settings_prefs" );
400
401
	//The Sending movie
402
	normalIcon = QPixmap( BarIcon( QString::fromLatin1( "kopete" ) ) );
403
	animIcon = KGlobal::iconLoader()->loadMovie( QString::fromLatin1( "newmessage" ), KIcon::Toolbar);
404
405
	// Pause the animation because otherwise it's running even when we're not
406
	// showing it. This eats resources, and also triggers a pixmap leak in
407
	// QMovie in at least Qt 3.1, Qt 3.2 and the current Qt 3.3 beta
408
	if( !animIcon.isNull() )  //and another QT bug:  it crash if we pause a null movie
409
		animIcon.pause();
410
411
	// we can't set the tool bar as parent, if we do, it will be deleted when we configure toolbars
412
	anim = new QLabel( QString::null, 0L ,"kde toolbar widget" );
413
	anim->setMargin(5);
414
	anim->setPixmap( normalIcon );
415
416
417
	new KWidgetAction( anim , i18n("Toolbar Animation") , 0, 0 , 0 , coll , "toolbar_animation");
418
419
	//toolBar()->insertWidget( 99, anim->width(), anim );
420
	//toolBar()->alignItemRight( 99 );
421
	setStandardToolBarMenuEnabled( true );
422
423
	setXMLFile( QString::fromLatin1( "kopetechatwindow.rc" ) );
424
	createGUI( 0L );
425
426
#if !KDE_IS_VERSION( 3, 1, 90 )
427
	mStatusbarAction->setChecked(!statusBar()->isHidden());
428
#endif
429
}
430
431
const QString KopeteChatWindow::fileContents( const QString &path ) const
432
{
433
 	QString contents;
434
	QFile file( path );
435
	if ( file.open( IO_ReadOnly ) )
436
	{
437
		QTextStream stream( &file );
438
		contents = stream.read();
439
		file.close();
440
	}
441
442
	return contents;
443
}
444
445
void KopeteChatWindow::slotStopAnimation( ChatView* view )
446
{
447
	if( view == m_activeView )
448
		anim->setPixmap( normalIcon );
449
}
450
451
void KopeteChatWindow::slotUpdateSendEnabled()
452
{
453
	if ( !m_activeView ) return;
454
455
	bool enabled = m_activeView->canSend();
456
	chatSend->setEnabled( enabled );
457
	if(m_button_send)
458
		m_button_send->setEnabled( enabled );
459
}
460
461
void KopeteChatWindow::updateMembersActions()
462
{
463
	if( m_activeView )
464
	{
465
		const KDockWidget::DockPosition pos = m_activeView->membersListPosition();
466
		bool visibleMembers = m_activeView->visibleMembersList();
467
		membersLeft->setChecked( pos == KDockWidget::DockLeft  );
468
		membersLeft->setEnabled( visibleMembers );
469
		membersRight->setChecked( pos == KDockWidget::DockRight );
470
		membersRight->setEnabled( visibleMembers );
471
		toggleMembers->setChecked( visibleMembers );
472
	}
473
}
474
475
void KopeteChatWindow::slotViewMembersLeft()
476
{
477
	m_activeView->placeMembersList( KDockWidget::DockLeft );
478
	updateMembersActions();
479
}
480
481
void KopeteChatWindow::slotViewMembersRight()
482
{
483
	m_activeView->placeMembersList( KDockWidget::DockRight );
484
	updateMembersActions();
485
}
486
487
void KopeteChatWindow::slotToggleViewMembers()
488
{
489
	m_activeView->toggleMembersVisibility();
490
	updateMembersActions();
491
}
492
493
void KopeteChatWindow::slotHistoryUp()
494
{
495
	if( m_activeView )
496
		m_activeView->editPart()->historyUp();
497
}
498
499
void KopeteChatWindow::slotHistoryDown()
500
{
501
	if( m_activeView )
502
		m_activeView->editPart()->historyDown();
503
}
504
505
void KopeteChatWindow::slotPageUp()
506
{
507
	if( m_activeView )
508
		m_activeView->messagePart()->pageUp();
509
}
510
511
void KopeteChatWindow::slotPageDown()
512
{
513
	if( m_activeView )
514
		m_activeView->messagePart()->pageDown();
515
}
516
517
void KopeteChatWindow::slotCut()
518
{
519
	m_activeView->cut();
520
}
521
522
void KopeteChatWindow::slotCopy()
523
{
524
	m_activeView->copy();
525
}
526
527
void KopeteChatWindow::slotPaste()
528
{
529
	m_activeView->paste();
530
}
531
532
533
void KopeteChatWindow::slotSetFont()
534
{
535
	m_activeView->setFont();
536
}
537
538
void KopeteChatWindow::slotSetFgColor()
539
{
540
	m_activeView->setFgColor();
541
}
542
543
void KopeteChatWindow::slotSetBgColor()
544
{
545
	m_activeView->setBgColor();
546
}
547
548
void KopeteChatWindow::setStatus(const QString &text)
549
{
550
	m_status_text->setText(text);
551
}
552
553
void KopeteChatWindow::createTabBar()
554
{
555
	if( !m_tabBar )
556
	{
557
		KGlobal::config()->setGroup( QString::fromLatin1("ChatWindowSettings") );
558
559
		m_tabBar = new KTabWidget( mainArea );
560
		m_tabBar->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
561
		m_tabBar->setHoverCloseButton(KGlobal::config()->readBoolEntry( QString::fromLatin1("HoverClose"), false ));
562
		m_tabBar->setTabReorderingEnabled(true);
563
		m_tabBar->setAutomaticResizeTabs(true);
564
		connect( m_tabBar, SIGNAL( closeRequest( QWidget* )), this, SLOT( slotCloseChat( QWidget* ) ) );
565
566
		QToolButton* m_rightWidget = new QToolButton( m_tabBar );
567
		connect( m_rightWidget, SIGNAL( clicked() ), this, SLOT( slotChatClosed() ) );
568
		m_rightWidget->setIconSet( SmallIcon( "tab_remove" ) );
569
		m_rightWidget->adjustSize();
570
		QToolTip::add( m_rightWidget, i18n("Close the current tab"));
571
		m_tabBar->setCornerWidget( m_rightWidget, QWidget::TopRight );
572
573
		mainLayout->addWidget( m_tabBar );
574
		m_tabBar->show();
575
		connect ( m_tabBar, SIGNAL(currentChanged(QWidget *)), this, SLOT(setActiveView(QWidget *)) );
576
		connect ( m_tabBar, SIGNAL(contextMenu(QWidget *, const QPoint & )), this, SLOT(slotTabContextMenu( QWidget *, const QPoint & )) );
577
578
		for( ChatView *view = chatViewList.first(); view; view = chatViewList.next() )
579
			addTab( view );
580
581
		if( m_activeView )
582
			m_tabBar->showPage( m_activeView );
583
		else
584
			setActiveView( chatViewList.first() );
585
586
		int tabPosition = KGlobal::config()->readNumEntry( QString::fromLatin1("Tab Placement") , 0 );
587
		slotPlaceTabs( tabPosition );
588
	}
589
}
590
591
void KopeteChatWindow::slotCloseChat( QWidget *chatView )
592
{
593
	static_cast<ChatView*>( chatView )->closeView();
594
}
595
596
void KopeteChatWindow::addTab( ChatView *view )
597
{
598
	QPtrList<Kopete::Contact> chatMembers=view->msgManager()->members();
599
	Kopete::Contact *c=0L;
600
	for ( Kopete::Contact *contact = chatMembers.first(); contact; contact = chatMembers.next() )
601
	{
602
		if(!c || c->onlineStatus() < contact->onlineStatus())
603
			c=contact;
604
	}
605
	QPixmap pluginIcon = c ? view->msgManager()->contactOnlineStatus( c ).iconFor( c) : SmallIcon( view->msgManager()->protocol()->pluginIcon() );
606
607
	view->reparent( m_tabBar, 0, QPoint(), true );
608
	m_tabBar->addTab( view, pluginIcon, QString::null );
609
	view->setTabBar( m_tabBar );
610
	if( view == m_activeView )
611
		view->show();
612
	else
613
		view->hide();
614
	view->setCaption( view->caption(), false );
615
}
616
617
void KopeteChatWindow::setPrimaryChatView( ChatView *view )
618
{
619
	//TODO figure out what else we have to save here besides the font
620
	//reparent clears a lot of stuff out
621
	QFont savedFont = view->font();
622
	view->reparent( mainArea, 0, QPoint(), true );
623
	view->setTabBar( 0L );
624
	view->setFont( savedFont );
625
	view->show();
626
627
	mainLayout->addWidget( view );
628
	setActiveView( view );
629
}
630
631
void KopeteChatWindow::deleteTabBar()
632
{
633
	if( m_tabBar )
634
	{
635
		disconnect ( m_tabBar, SIGNAL(currentChanged(QWidget *)), this, SLOT(setActiveView(QWidget *)) );
636
		disconnect ( m_tabBar, SIGNAL(contextMenu(QWidget *, const QPoint & )), this, SLOT(slotTabContextMenu( QWidget *, const QPoint & )) );
637
638
		if( !chatViewList.isEmpty() )
639
			setPrimaryChatView( chatViewList.first() );
640
641
		m_tabBar->deleteLater();
642
		m_tabBar = 0L;
643
	}
644
}
645
646
void KopeteChatWindow::attachChatView( ChatView* newView )
647
{
648
	chatViewList.append( newView );
649
650
	if ( !m_alwaysShowTabs && chatViewList.count() == 1 )
651
		setPrimaryChatView( newView );
652
	else
653
	{
654
		if ( !m_tabBar )
655
			createTabBar();
656
		else
657
			addTab( newView );
658
		newView->setActive( false );
659
	}
660
661
	newView->setMainWindow( this );
662
	newView->editWidget()->installEventFilter( this );
663
664
	KCursor::setAutoHideCursor( newView->editWidget(), true, true );
665
	connect( newView, SIGNAL(captionChanged( bool)), this, SLOT(slotSetCaption(bool)) );
666
	connect( newView, SIGNAL(messageSuccess( ChatView* )), this, SLOT(slotStopAnimation( ChatView* )) );
667
	connect( newView, SIGNAL(updateStatusIcon( const ChatView* )), this, SLOT(slotUpdateCaptionIcons( const ChatView* )) );
668
669
	checkDetachEnable();
670
}
671
672
void KopeteChatWindow::checkDetachEnable()
673
{
674
	bool haveTabs = (chatViewList.count() > 1);
675
	tabDetach->setEnabled( haveTabs );
676
	tabLeft->setEnabled( haveTabs );
677
	tabRight->setEnabled( haveTabs );
678
	actionTabPlacementMenu->setEnabled( m_tabBar != 0 );
679
680
	bool otherWindows = (windows.count() > 1);
681
	actionDetachMenu->setEnabled( otherWindows );
682
}
683
684
void KopeteChatWindow::detachChatView( ChatView *view )
685
{
686
	if( !chatViewList.removeRef( view ) )
687
		return;
688
689
	disconnect( view, SIGNAL(captionChanged( bool)), this, SLOT(slotSetCaption(bool)) );
690
	disconnect( view, SIGNAL(updateStatusIcon( const ChatView *)), this, SLOT(slotUpdateCaptionIcons( const ChatView * )) );
691
	view->editWidget()->removeEventFilter( this );
692
693
	if( m_tabBar )
694
	{
695
		int curPage = m_tabBar->currentPageIndex();
696
		QWidget *page = m_tabBar->page( curPage );
697
698
		// if the current view is to be detached, switch to a different one
699
		if( page == view )
700
		{
701
			if( curPage > 0 )
702
				m_tabBar->setCurrentPage( curPage - 1 );
703
			else
704
				m_tabBar->setCurrentPage( curPage + 1 );
705
		}
706
707
		view->setTabBar( 0L );
708
		m_tabBar->removePage( view );
709
710
		if( m_tabBar->currentPage() )
711
			setActiveView( static_cast<ChatView*>(m_tabBar->currentPage()) );
712
	}
713
714
	if( chatViewList.isEmpty() )
715
		close();
716
	else if( !m_alwaysShowTabs && chatViewList.count() == 1)
717
		deleteTabBar();
718
719
	checkDetachEnable();
720
}
721
722
void KopeteChatWindow::slotDetachChat( int newWindowIndex )
723
{
724
	KopeteChatWindow *newWindow = 0L;
725
	ChatView *detachedView;
726
727
	if( m_popupView )
728
		detachedView = m_popupView;
729
	else
730
		detachedView = m_activeView;
731
732
	if( !detachedView )
733
		return;
734
735
	//if we don't do this, we might crash
736
	createGUI(0L);
737
	guiFactory()->removeClient(detachedView->msgManager());
738
739
	if( newWindowIndex == -1 )
740
		newWindow = new KopeteChatWindow();
741
	else
742
		newWindow = windows.at( newWindowIndex );
743
744
	newWindow->show();
745
	newWindow->raise();
746
747
	detachChatView( detachedView );
748
	newWindow->attachChatView( detachedView );
749
}
750
751
void KopeteChatWindow::slotPreviousTab()
752
{
753
	int curPage = m_tabBar->currentPageIndex();
754
	if( curPage > 0 )
755
		m_tabBar->setCurrentPage( curPage - 1 );
756
	else
757
		m_tabBar->setCurrentPage( m_tabBar->count() - 1 );
758
}
759
760
void KopeteChatWindow::slotNextTab()
761
{
762
	int curPage = m_tabBar->currentPageIndex();
763
	if( curPage == ( m_tabBar->count() - 1 ) )
764
		m_tabBar->setCurrentPage( 0 );
765
	else
766
		m_tabBar->setCurrentPage( curPage + 1 );
767
}
768
769
void KopeteChatWindow::slotSetCaption( bool active )
770
{
771
	if( active && m_activeView )
772
	{
773
		setCaption( m_activeView->caption(), false );
774
	}
775
}
776
777
void KopeteChatWindow::updateBackground( const QPixmap &pm )
778
{
779
	if( updateBg )
780
	{
781
		updateBg = false;
782
		if( backgroundFile != 0L )
783
		{
784
			backgroundFile->close();
785
			backgroundFile->unlink();
786
		}
787
788
		backgroundFile = new KTempFile( QString::null, QString::fromLatin1( ".bmp" ) );
789
		pm.save( backgroundFile->name(), "BMP" );
790
		QTimer::singleShot( 100, this, SLOT( slotEnableUpdateBg() ) );
791
	}
792
}
793
794
void KopeteChatWindow::setActiveView( QWidget *widget )
795
{
796
	ChatView *view = static_cast<ChatView*>(widget);
797
798
	if( m_activeView == view )
799
		return;
800
801
	if(m_activeView)
802
	{
803
		disconnect( m_activeView, SIGNAL( canSendChanged(bool) ), this, SLOT( slotUpdateSendEnabled() ) );
804
		guiFactory()->removeClient(m_activeView->msgManager());
805
	}
806
807
	guiFactory()->addClient(view->msgManager());
808
	createGUI( view->part() );
809
810
	if( m_activeView )
811
		m_activeView->setActive( false );
812
813
	m_activeView = view;
814
815
	if( !chatViewList.contains( view ) )
816
		attachChatView( view );
817
818
	connect( m_activeView, SIGNAL( canSendChanged(bool) ), this, SLOT( slotUpdateSendEnabled() ) );
819
820
	//Tell it it is active
821
	m_activeView->setActive( true );
822
823
	//Update icons to match
824
	slotUpdateCaptionIcons( m_activeView );
825
826
	//Update chat members actions
827
	updateMembersActions();
828
829
	if ( m_activeView->sendInProgress() && !animIcon.isNull() )
830
	{
831
		anim->setMovie( animIcon );
832
		animIcon.unpause();
833
	}
834
	else
835
	{
836
		anim->setPixmap( normalIcon );
837
		if( !animIcon.isNull() )
838
			animIcon.pause();
839
	}
840
841
	if ( m_alwaysShowTabs || chatViewList.count() > 1 )
842
	{
843
		if( !m_tabBar )
844
			createTabBar();
845
846
		m_tabBar->showPage( m_activeView );
847
	}
848
849
	setCaption( m_activeView->caption() );
850
	setStatus( m_activeView->statusText() );
851
	m_activeView->setFocus();
852
853
	slotUpdateSendEnabled();
854
}
855
856
void KopeteChatWindow::slotUpdateCaptionIcons( const ChatView *view )
857
{
858
	if(!view||!m_activeView||view!=m_activeView )
859
		return; //(pas de charité)
860
	QPtrList<Kopete::Contact> chatMembers=view->msgManager()->members();
861
	Kopete::Contact *c=0L;
862
	for ( Kopete::Contact *contact = chatMembers.first(); contact; contact = chatMembers.next() )
863
	{
864
		if(!c || c->onlineStatus() < contact->onlineStatus())
865
			c=contact;
866
	}
867
	QPixmap icon16 = c ? view->msgManager()->contactOnlineStatus( c ).iconFor( c , 16) : SmallIcon( view->msgManager()->protocol()->pluginIcon() );
868
	QPixmap icon32 = c ? view->msgManager()->contactOnlineStatus( c ).iconFor( c , 32) : SmallIcon( view->msgManager()->protocol()->pluginIcon() );
869
870
	KWin::setIcons( winId(), icon32, icon16 );
871
}
872
873
void KopeteChatWindow::slotChatClosed()
874
{
875
	if( m_popupView )
876
		m_popupView->closeView();
877
	else
878
		m_activeView->closeView();
879
}
880
881
void KopeteChatWindow::slotPrepareDetachMenu(void)
882
{
883
	QPopupMenu *detachMenu = actionDetachMenu->popupMenu();
884
	detachMenu->clear();
885
886
	for ( unsigned id=0; id < windows.count(); id++ )
887
	{
888
		KopeteChatWindow *win = windows.at( id );
889
		if( win != this )
890
			detachMenu->insertItem( win->caption(), id );
891
	}
892
}
893
894
void KopeteChatWindow::slotSendMessage()
895
{
896
	if ( m_activeView && m_activeView->canSend() )
897
	{
898
		if( !animIcon.isNull() )
899
		{
900
			anim->setMovie( animIcon );
901
			animIcon.unpause();
902
		}
903
		m_activeView->sendMessage();
904
	}
905
}
906
907
void KopeteChatWindow::slotPrepareContactMenu(void)
908
{
909
	QPopupMenu *contactsMenu = actionContactMenu->popupMenu();
910
	contactsMenu->clear();
911
912
	Kopete::Contact *contact;
913
	Kopete::ContactPtrList m_them;
914
915
	if( m_popupView )
916
		m_them = m_popupView->msgManager()->members();
917
	else
918
		m_them = m_activeView->msgManager()->members();
919
920
	//TODO: don't display a menu with one contact in it, display that
921
	// contact's menu instead. Will require changing text and icon of
922
	// 'Contacts' action, or something cleverer.
923
	uint contactCount = 0;
924
925
	for ( contact = m_them.first(); contact; contact = m_them.next() )
926
	{
927
		KPopupMenu *p = contact->popupMenu();
928
		connect ( actionContactMenu->popupMenu(), SIGNAL(aboutToHide()),
929
			p, SLOT(deleteLater() ) );
930
931
		if( contact->metaContact() )
932
			contactsMenu->insertItem( contact->onlineStatus().iconFor( contact ) , contact->metaContact()->displayName(), p );
933
		else
934
			contactsMenu->insertItem( contact->onlineStatus().iconFor( contact ) , contact->contactId(), p );
935
936
		//FIXME: This number should be a config option
937
		if( ++contactCount == 15 && contact != m_them.getLast() )
938
		{
939
			KActionMenu *moreMenu = new KActionMenu( i18n("More..."),
940
				 QString::fromLatin1("folder_open"), contactsMenu );
941
			connect ( actionContactMenu->popupMenu(), SIGNAL(aboutToHide()),
942
				moreMenu, SLOT(deleteLater() ) );
943
			moreMenu->plug( contactsMenu );
944
			contactsMenu = moreMenu->popupMenu();
945
			contactCount = 0;
946
		}
947
	}
948
}
949
950
void KopeteChatWindow::slotPreparePlacementMenu()
951
{
952
	QPopupMenu *placementMenu = actionTabPlacementMenu->popupMenu();
953
	placementMenu->clear();
954
955
	placementMenu->insertItem( i18n("Top"), 0 );
956
	placementMenu->insertItem( i18n("Bottom"), 1 );
957
}
958
959
void KopeteChatWindow::slotPlaceTabs( int placement )
960
{
961
	if( m_tabBar )
962
	{
963
964
		if( placement == 0 )
965
			m_tabBar->setTabPosition( QTabWidget::Top );
966
		else
967
			m_tabBar->setTabPosition( QTabWidget::Bottom );
968
969
		saveOptions();
970
	}
971
}
972
973
void KopeteChatWindow::readOptions()
974
{
975
	// load and apply config file settings affecting the appearance of the UI
976
//	kdDebug(14010) << k_funcinfo << endl;
977
	KConfig *config = KGlobal::config();
978
	applyMainWindowSettings( config, QString::fromLatin1( "KopeteChatWindow" ) );
979
	config->setGroup( QString::fromLatin1("ChatWindowSettings") );
980
}
981
982
void KopeteChatWindow::saveOptions()
983
{
984
//	kdDebug(14010) << k_funcinfo << endl;
985
986
	KConfig *config = KGlobal::config();
987
988
	// saves menubar,toolbar and statusbar setting
989
	saveMainWindowSettings( config, QString::fromLatin1( "KopeteChatWindow" ) );
990
	config->setGroup( QString::fromLatin1("ChatWindowSettings") );
991
	if( m_tabBar )
992
		config->writeEntry ( QString::fromLatin1("Tab Placement"), m_tabBar->tabPosition() );
993
994
	config->sync();
995
}
996
997
void KopeteChatWindow::slotChatSave()
998
{
999
//	kdDebug(14010) << "KopeteChatWindow::slotChatSave()" << endl;
1000
	if( isActiveWindow() && m_activeView )
1001
		m_activeView->messagePart()->save();
1002
}
1003
1004
void KopeteChatWindow::windowActivationChange( bool )
1005
{
1006
	if( isActiveWindow() && m_activeView )
1007
		m_activeView->setActive( true );
1008
}
1009
1010
void KopeteChatWindow::slotChatPrint()
1011
{
1012
	m_activeView->messagePart()->print();
1013
}
1014
1015
void KopeteChatWindow::slotToggleStatusBar()
1016
{
1017
	if (statusBar()->isVisible())
1018
		statusBar()->hide();
1019
	else
1020
		statusBar()->show();
1021
}
1022
1023
void KopeteChatWindow::slotViewMenuBar()
1024
{
1025
	if( !menuBar()->isHidden() )
1026
		menuBar()->hide();
1027
	else
1028
		menuBar()->show();
1029
}
1030
1031
void KopeteChatWindow::slotSmileyActivated(const QString &sm)
1032
{
1033
	if ( !sm.isNull() )
1034
		m_activeView->addText( sm );
1035
}
1036
1037
bool KopeteChatWindow::queryClose()
1038
{
1039
	bool canClose = true;
1040
1041
//	kdDebug( 14010 ) << " Windows left open:" << endl;
1042
//	for( QPtrListIterator<ChatView> it( chatViewList ); it; ++it)
1043
//		kdDebug( 14010 ) << "  " << *it << " (" << (*it)->caption() << ")" << endl;
1044
1045
	for( QPtrListIterator<ChatView> it( chatViewList ); it; )
1046
	{
1047
		ChatView *view = *it;
1048
		// move out of the way before view is removed
1049
		++it;
1050
1051
		// FIXME: This should only check if it *can* close
1052
		// and not start closing if the close can be aborted halfway, it would
1053
		// leave us with half the chats open and half of them closed. - Martijn
1054
1055
		// if the view is closed, it is removed from chatViewList for us
1056
		if ( !view->closeView() )
1057
		{
1058
			kdDebug() << k_funcinfo << "Closing view failed!" << endl;
1059
			canClose = false;
1060
		}
1061
	}
1062
	return canClose;
1063
}
1064
1065
bool KopeteChatWindow::queryExit()
1066
{
1067
	KopeteApplication *app = static_cast<KopeteApplication *>( kapp );
1068
 	if ( app->sessionSaving()
1069
		|| app->isShuttingDown() /* only set if KopeteApplication::quitKopete() or
1070
									KopeteApplication::commitData() called */
1071
		|| !KopetePrefs::prefs()->showTray() /* also close if our tray icon is hidden! */
1072
		|| !isShown() )
1073
	{
1074
		Kopete::PluginManager::self()->shutdown();
1075
		return true;
1076
	}
1077
	else 
1078
		return false;
1079
}
1080
1081
void KopeteChatWindow::closeEvent( QCloseEvent * e )
1082
{
1083
	// if there's a system tray applet and we are not shutting down then just do what needs to be done if a
1084
	// window is closed.
1085
	KopeteApplication *app = static_cast<KopeteApplication *>( kapp );
1086
	if ( KopetePrefs::prefs()->showTray() && !app->isShuttingDown() && !app->sessionSaving() ) {
1087
		// BEGIN of code borrowed from KMainWindow::closeEvent
1088
		// Save settings if auto-save is enabled, and settings have changed
1089
		if ( settingsDirty() && autoSaveSettings() )
1090
			saveAutoSaveSettings();
1091
	
1092
		if ( queryClose() ) {
1093
			e->accept();
1094
		}
1095
		// END of code borrowed from KMainWindow::closeEvent
1096
	}
1097
	else
1098
		KMainWindow::closeEvent( e );
1099
}
1100
1101
void KopeteChatWindow::slotConfKeys()
1102
{
1103
	KKeyDialog dlg( false, this );
1104
	dlg.insert( actionCollection() );
1105
	if( m_activeView )
1106
	{
1107
		dlg.insert(m_activeView->msgManager()->actionCollection() , i18n("Plugin Actions") );
1108
		QPtrListIterator<KXMLGUIClient> it( *m_activeView->msgManager()->childClients() );
1109
		KXMLGUIClient *c = 0;
1110
		while( (c = it.current()) != 0 )
1111
		{
1112
			dlg.insert( c->actionCollection() /*, i18n("Plugin Actions")*/ );
1113
			++it;
1114
		}
1115
1116
		if( m_activeView->part() )
1117
			dlg.insert( m_activeView->part()->actionCollection(), m_activeView->part()->name() );
1118
	}
1119
1120
	dlg.configure();
1121
}
1122
1123
void KopeteChatWindow::slotConfToolbar()
1124
{
1125
	saveMainWindowSettings(KGlobal::config(), QString::fromLatin1( "KopeteChatWindow" ));
1126
	KEditToolbar *dlg = new KEditToolbar(factory(), this );
1127
	if (dlg->exec())
1128
	{
1129
		if( m_activeView )
1130
		{
1131
			createGUI( m_activeView->part() );
1132
			//guiFactory()->addClient(m_activeView->msgManager());
1133
		}
1134
		else
1135
			createGUI( 0L );
1136
		applyMainWindowSettings(KGlobal::config(), QString::fromLatin1( "KopeteChatWindow" ));
1137
	}
1138
	delete dlg;
1139
}
1140
1141
#include "kopetechatwindow.moc"
1142
1143
// vim: set noet ts=4 sts=4 sw=4:
1144
(-)../work-orig/kopete-3.4.0/kopete/kopete/chatwindow/kopetechatwindow.h (+4 lines)
Lines 28-33 class KAction; Link Here
28
class KToggleAction;
28
class KToggleAction;
29
class KActionMenu;
29
class KActionMenu;
30
class KTempFile;
30
class KTempFile;
31
class KComboBox;
31
class QPixmap;
32
class QPixmap;
32
class QTabWidget;
33
class QTabWidget;
33
class KSqueezedTextLabel;
34
class KSqueezedTextLabel;
Lines 123-128 private: Link Here
123
	void addTab( ChatView* );
124
	void addTab( ChatView* );
124
	void setPrimaryChatView( ChatView* );
125
	void setPrimaryChatView( ChatView* );
125
	const QString fileContents( const QString &file ) const;
126
	const QString fileContents( const QString &file ) const;
127
    void initEncodings();
126
128
127
	ChatView *m_activeView;
129
	ChatView *m_activeView;
128
	ChatView *m_popupView;
130
	ChatView *m_popupView;
Lines 136-141 private: Link Here
136
	QLabel *anim;
138
	QLabel *anim;
137
	QMovie animIcon;
139
	QMovie animIcon;
138
	QPixmap normalIcon;
140
	QPixmap normalIcon;
141
	KComboBox* m_encoding;
139
142
140
	KAction *chatSend;
143
	KAction *chatSend;
141
	KAction *historyUp;
144
	KAction *historyUp;
Lines 217-222 private slots: Link Here
217
	void slotStopAnimation( ChatView* );
220
	void slotStopAnimation( ChatView* );
218
	void slotNickComplete();
221
	void slotNickComplete();
219
	void slotCloseChat( QWidget* );
222
	void slotCloseChat( QWidget* );
223
    void slotEncodingSelected(const QString& string);
220
224
221
protected:
225
protected:
222
	virtual void closeEvent( QCloseEvent *e );
226
	virtual void closeEvent( QCloseEvent *e );
(-)../work-orig/kopete-3.4.0/kopete/kopete/chatwindow/kopetechatwindow.h.orig (+229 lines)
Line 0 Link Here
1
/*
2
    kopetechatwindow.h - Chat Window
3
4
    Copyright (c) 2002      by Olivier Goffart        <ogoffart@tiscalinet.be>
5
    Copyright (c) 2004      by Martijn Klingens       <klingens@kde.org>
6
7
    Kopete    (c) 2002-2004 by the Kopete developers  <kopete-devel@kde.org>
8
9
    *************************************************************************
10
    *                                                                       *
11
    * This program is free software; you can redistribute it and/or modify  *
12
    * it under the terms of the GNU General Public License as published by  *
13
    * the Free Software Foundation; either version 2 of the License, or     *
14
    * (at your option) any later version.                                   *
15
    *                                                                       *
16
    *************************************************************************
17
*/
18
19
#ifndef KOPETECHATWINDOW_H
20
#define KOPETECHATWINDOW_H
21
22
#include <kparts/mainwindow.h>
23
#include <qmovie.h>
24
#include "kopetecontact.h"
25
#include "kdeversion.h"
26
27
class KAction;
28
class KToggleAction;
29
class KActionMenu;
30
class KTempFile;
31
class QPixmap;
32
class QTabWidget;
33
class KSqueezedTextLabel;
34
class KPushButton;
35
class QVBox;
36
class QVBoxLayout;
37
class QFrame;
38
class KTabWidget;
39
class QLabel;
40
class KopeteEmoticonAction;
41
class KopeteView;
42
class KSelectAction;
43
class ChatView;
44
45
namespace Kopete
46
{
47
class Message;
48
class ChatSession;
49
class Contact;
50
class Protocol;
51
typedef QPtrList<Contact>  ContactPtrList;
52
}
53
54
class KopeteChatWindow : public KParts::MainWindow
55
{
56
	Q_OBJECT
57
58
	enum {NEW_WINDOW, GROUP_BY_ACCOUNT, GROUP_ALL, GROUP_BY_GROUP, GROUP_BY_METACONTACT};
59
60
public:
61
	/**
62
	 * Find the appropriate window for a ChatView of the given protocol to
63
	 * dock into. If no such window exists, create one.
64
	 * @param protocol The protocol we are creating a view for
65
	 * @return A KopeteChatWindow suitable for docking a ChatView into. Guaranteed
66
	 *  to be a valid pointer.
67
	 */
68
	static KopeteChatWindow *window( Kopete::ChatSession *manager );
69
	~KopeteChatWindow();
70
71
	/**
72
	 * Attach an unattached chatview to this window
73
	 * @param chat The chat view to attach
74
	 */
75
	void attachChatView( ChatView *chat );
76
77
	/**
78
	 * Detach a chat view from this window
79
	 * @param chat The chat view to detach
80
	 */
81
	void detachChatView( ChatView *chat );
82
83
	/**
84
	 * Returns the number of chat views attached to this window
85
	 */
86
	const int chatViewCount() { return chatViewList.count(); }
87
88
	/**
89
	 * Returns the chatview in the currently active tab, or the only chat view
90
	 * if chatViewCount() == 1
91
	 */
92
	ChatView *activeView();
93
94
	void updateMembersActions();
95
	void setStatus( const QString & );
96
97
	/** 
98
	 * Reimplemented from KMainWindow - asks each ChatView in the window if it is ok to close the window 
99
	 * @return true if no ChatView objects to closing.
100
	 */
101
	virtual bool queryClose();
102
	virtual bool queryExit();
103
104
	KTempFile *backgroundFile;
105
	QPtrList<ChatView> chatViewList;
106
107
private:
108
	// All KopeteChatWindows are created by the findWindow function
109
	KopeteChatWindow( QWidget *parent = 0, const char* name = "KopeteChatWindow" );
110
111
	/**
112
	 * The window list has changed:
113
	 * For each chat window, update it's Move Tab to Window action
114
	 */
115
	static void windowListChanged();
116
117
	void initActions(void);
118
	void saveOptions(void);
119
	void readOptions(void);
120
	void checkDetachEnable();
121
	void createTabBar();
122
	void deleteTabBar();
123
	void addTab( ChatView* );
124
	void setPrimaryChatView( ChatView* );
125
	const QString fileContents( const QString &file ) const;
126
127
	ChatView *m_activeView;
128
	ChatView *m_popupView;
129
	bool m_alwaysShowTabs;
130
	bool updateBg;
131
	KTabWidget *m_tabBar;
132
	KPushButton *m_button_send;
133
	KSqueezedTextLabel *m_status_text;
134
	QVBoxLayout *mainLayout;
135
	QFrame *mainArea;
136
	QLabel *anim;
137
	QMovie animIcon;
138
	QPixmap normalIcon;
139
140
	KAction *chatSend;
141
	KAction *historyUp;
142
	KAction *historyDown;
143
	KAction *nickComplete;
144
145
#if !KDE_IS_VERSION( 3, 1, 90 )
146
	KToggleAction *mStatusbarAction;
147
#endif
148
149
	KAction *tabLeft;
150
	KAction *tabRight;
151
	KAction *tabDetach;
152
	KAction* tabClose;
153
154
	KToggleAction* membersLeft;
155
	KToggleAction* membersRight;
156
	KToggleAction* toggleMembers;
157
158
	KopeteEmoticonAction *actionSmileyMenu;
159
	KActionMenu *actionActionMenu;
160
	KActionMenu *actionContactMenu;
161
	KActionMenu *actionDetachMenu;
162
	KActionMenu *actionTabPlacementMenu;
163
	QString statusMsg;
164
165
signals:
166
	void closing( KopeteChatWindow* );
167
168
public slots:
169
	void slotSmileyActivated( const QString & );
170
	void setActiveView( QWidget *active );
171
	void updateBackground( const QPixmap &pm );
172
173
private slots:
174
//	void slotPrepareSmileyMenu();
175
	void slotPrepareContactMenu();
176
	void slotPrepareDetachMenu();
177
	void slotPreparePlacementMenu();
178
	void slotUpdateSendEnabled();
179
180
	void slotCut();
181
	void slotCopy();
182
	void slotPaste();
183
184
	void slotSetBgColor();
185
	void slotSetFgColor();
186
	void slotSetFont();
187
188
	void slotHistoryUp();
189
	void slotHistoryDown();
190
	void slotPageUp();
191
	void slotPageDown();
192
193
	void slotSendMessage();
194
	void slotChatSave();
195
	void slotChatPrint();
196
197
	void slotPreviousTab();
198
	void slotNextTab();
199
	void slotDetachChat( int newWindowIndex = -1 );
200
	void slotPlaceTabs( int tabPlacement );
201
202
	void slotViewMenuBar();
203
	void slotToggleStatusBar();
204
205
	void slotConfKeys();
206
	void slotConfToolbar();
207
208
	void slotViewMembersLeft();
209
	void slotViewMembersRight();
210
	void slotToggleViewMembers();
211
	void slotEnableUpdateBg() { updateBg = true; }
212
213
	void slotSetCaption( bool );
214
	void slotUpdateCaptionIcons( const ChatView * );
215
	void slotChatClosed();
216
	void slotTabContextMenu( QWidget*, const QPoint & );
217
	void slotStopAnimation( ChatView* );
218
	void slotNickComplete();
219
	void slotCloseChat( QWidget* );
220
221
protected:
222
	virtual void closeEvent( QCloseEvent *e );
223
	virtual void windowActivationChange( bool );
224
};
225
226
#endif
227
228
// vim: set noet ts=4 sts=4 sw=4:
229
(-)../work-orig/kopete-3.4.0/kopete/kopete/kopeteiface.cpp (-1 lines)
Lines 84-90 QStringList KopeteIface::contactFileProt Link Here
84
{
84
{
85
	return Kopete::ContactList::self()->contactFileProtocols(displayName);
85
	return Kopete::ContactList::self()->contactFileProtocols(displayName);
86
}
86
}
87
88
QString KopeteIface::messageContact( const QString &contactId, const QString &messageText )
87
QString KopeteIface::messageContact( const QString &contactId, const QString &messageText )
89
{
88
{
90
	Kopete::MetaContact *mc = Kopete::ContactList::self()->findMetaContactByContactId( contactId );
89
	Kopete::MetaContact *mc = Kopete::ContactList::self()->findMetaContactByContactId( contactId );
(-)../work-orig/kopete-3.4.0/kopete/kopete/systemtray.cpp (-1 / +20 lines)
Lines 19-24 Link Here
19
19
20
#include "systemtray.h"
20
#include "systemtray.h"
21
21
22
#include <qtextcodec.h> 
22
#include <qtimer.h>
23
#include <qtimer.h>
23
#include <qtooltip.h>
24
#include <qtooltip.h>
24
#include <qregexp.h>
25
#include <qregexp.h>
Lines 29-34 Link Here
29
#include <kapplication.h>
30
#include <kapplication.h>
30
#include <kdebug.h>
31
#include <kdebug.h>
31
#include <kiconloader.h>
32
#include <kiconloader.h>
33
#include <kconfig.h>
34
32
#include "kopeteuiglobal.h"
35
#include "kopeteuiglobal.h"
33
#include "kopetemessagemanagerfactory.h"
36
#include "kopetemessagemanagerfactory.h"
34
#include "kopeteballoon.h"
37
#include "kopeteballoon.h"
Lines 258-267 void KopeteSystemTray::addBalloon() Link Here
258
				msgFrom = msg.from()->metaContact()->displayName();
261
				msgFrom = msg.from()->metaContact()->displayName();
259
			else
262
			else
260
				msgFrom = msg.from()->contactId();
263
				msgFrom = msg.from()->contactId();
261
264
			
265
			KConfig* cf=KGlobal::config();
266
			QString uid=msg.from()->contactId();
267
			QString gr=cf->group();
268
			cf->setGroup("Encodings");
269
			QString codepage=cf->readEntry(uid,"Unicode");	
270
			cf->setGroup(gr);
271
			if(codepage != "Unicode")
272
			{
273
				QCString locallyEncoded = msgText.ascii();
274
				QTextCodec *codec = QTextCodec::codecForName(codepage.ascii());
275
				if(codec)
276
				msgText=codec->toUnicode( locallyEncoded );
277
			}
278
				
262
			m_balloon = new KopeteBalloon(
279
			m_balloon = new KopeteBalloon(
263
				i18n( "<qt><nobr><b>New Message from %1:</b></nobr><br><nobr>\"%2\"</nobr></qt>" )
280
				i18n( "<qt><nobr><b>New Message from %1:</b></nobr><br><nobr>\"%2\"</nobr></qt>" )
264
					.arg( msgFrom, msgText ), QString::null );
281
					.arg( msgFrom, msgText ), QString::null );
282
			kdDebug()<<"baloon from "<<msgFrom<<" with test "<<
283
			msgText<<endl;
265
			connect(m_balloon, SIGNAL(signalBalloonClicked()), mEventList.first() , SLOT(apply()));
284
			connect(m_balloon, SIGNAL(signalBalloonClicked()), mEventList.first() , SLOT(apply()));
266
			connect(m_balloon, SIGNAL(signalButtonClicked()), mEventList.first() , SLOT(apply()));
285
			connect(m_balloon, SIGNAL(signalButtonClicked()), mEventList.first() , SLOT(apply()));
267
			connect(m_balloon, SIGNAL(signalIgnoreButtonClicked()), mEventList.first() , SLOT(ignore()));
286
			connect(m_balloon, SIGNAL(signalIgnoreButtonClicked()), mEventList.first() , SLOT(ignore()));
(-)../work-orig/kopete-3.4.0/kopete/kopete/systemtray.cpp.orig (+393 lines)
Line 0 Link Here
1
/*
2
    systemtray.cpp  -  Kopete Tray Dock Icon
3
4
    Copyright (c) 2002      by Nick Betcher           <nbetcher@kde.org>
5
    Copyright (c) 2002-2003 by Martijn Klingens       <klingens@kde.org>
6
    Copyright (c) 2003-2004 by Olivier Goffart        <ogoffart@tiscalinet.be>
7
8
    Kopete    (c) 2002-2004 by the Kopete developers  <kopete-devel@kde.org>
9
10
    *************************************************************************
11
    *                                                                       *
12
    * This program is free software; you can redistribute it and/or modify  *
13
    * it under the terms of the GNU General Public License as published by  *
14
    * the Free Software Foundation; either version 2 of the License, or     *
15
    * (at your option) any later version.                                   *
16
    *                                                                       *
17
    *************************************************************************
18
*/
19
20
#include "systemtray.h"
21
22
#include <qtimer.h>
23
#include <qtooltip.h>
24
#include <qregexp.h>
25
26
#include <kwin.h>
27
#include <kaboutdata.h>
28
#include <kactioncollection.h>
29
#include <kapplication.h>
30
#include <kdebug.h>
31
#include <kiconloader.h>
32
#include "kopeteuiglobal.h"
33
#include "kopetemessagemanagerfactory.h"
34
#include "kopeteballoon.h"
35
#include "kopeteprefs.h"
36
#include "kopetemetacontact.h"
37
#include "kopeteaccount.h"
38
#include "kopeteaccountmanager.h"
39
#include "kopetecontact.h"
40
#include "kopetewindow.h"
41
42
KopeteSystemTray* KopeteSystemTray::s_systemTray = 0L;
43
44
KopeteSystemTray* KopeteSystemTray::systemTray( QWidget *parent, const char* name )
45
{
46
	if( !s_systemTray )
47
		s_systemTray = new KopeteSystemTray( parent, name );
48
49
	return s_systemTray;
50
}
51
52
KopeteSystemTray::KopeteSystemTray(QWidget* parent, const char* name)
53
	: KSystemTray(parent,name)
54
{
55
//	kdDebug(14010) << "Creating KopeteSystemTray" << endl;
56
	QToolTip::add( this, kapp->aboutData()->shortDescription() );
57
58
	mIsBlinkIcon = false;
59
	mIsBlinking = false;
60
	mBlinkTimer = new QTimer(this, "mBlinkTimer");
61
62
	mKopeteIcon = loadIcon("kopete");
63
64
	connect(mBlinkTimer, SIGNAL(timeout()), this, SLOT(slotBlink()));
65
	connect(Kopete::ChatSessionManager::self() , SIGNAL(newEvent(Kopete::MessageEvent*)),
66
		this, SLOT(slotNewEvent(Kopete::MessageEvent*)));
67
	connect(KopetePrefs::prefs(), SIGNAL(saved()), this, SLOT(slotConfigChanged()));
68
69
	connect(Kopete::AccountManager::self(),
70
		SIGNAL(accountOnlineStatusChanged(Kopete::Account *,
71
		const Kopete::OnlineStatus &, const Kopete::OnlineStatus &)),
72
	this, SLOT(slotReevaluateAccountStates()));
73
74
	// the slot called by default by the quit action, KSystemTray::maybeQuit(),
75
	// just closes the parent window, which is hard to distinguish in that window's closeEvent()
76
	// from a click on the window's close widget
77
	// in the quit case, we want to quit the application
78
 	// in the close widget click case, we only want to hide the parent window
79
	// so instead, we make it call our general purpose quit slot on the window, which causes a window close and everything else we need
80
	// KDE4 - app will have to listen for quitSelected instead
81
	KAction *quit = actionCollection()->action( "file_quit" );
82
	quit->disconnect();
83
	KopeteWindow *myParent = static_cast<KopeteWindow *>( parent );
84
    connect( quit, SIGNAL( activated() ), myParent, SLOT( slotQuit() ) );
85
86
	//setPixmap(mKopeteIcon);
87
	slotReevaluateAccountStates();
88
	slotConfigChanged();
89
90
	m_balloon=0l;
91
}
92
93
KopeteSystemTray::~KopeteSystemTray()
94
{
95
//	kdDebug(14010) << "[KopeteSystemTray] ~KopeteSystemTray" << endl;
96
//	delete mBlinkTimer;
97
	Kopete::UI::Global::setSysTrayWId( 0 );
98
}
99
100
void KopeteSystemTray::mousePressEvent( QMouseEvent *me )
101
{
102
	if (
103
		(me->button() == QEvent::MidButton || me->button() == QEvent::LeftButton) &&
104
		mIsBlinking )
105
	{
106
		mouseDoubleClickEvent( me );
107
		return;
108
	}
109
110
	KSystemTray::mousePressEvent( me );
111
}
112
113
void KopeteSystemTray::mouseDoubleClickEvent( QMouseEvent *me )
114
{
115
	if ( !mIsBlinking )
116
	{
117
		KSystemTray::mousePressEvent( me );
118
	}
119
	else
120
	{
121
		if(!mEventList.isEmpty())
122
			mEventList.first()->apply();
123
	}
124
}
125
126
void KopeteSystemTray::contextMenuAboutToShow( KPopupMenu *me )
127
{
128
	//kdDebug(14010) << k_funcinfo << "Called." << endl;
129
	emit aboutToShowMenu( me );
130
}
131
132
void KopeteSystemTray::startBlink( const QString &icon )
133
{
134
	startBlink( KGlobal::iconLoader()->loadIcon( icon , KIcon::Panel ) );
135
}
136
137
void KopeteSystemTray::startBlink( const QPixmap &icon )
138
{
139
	mBlinkIcon = icon;
140
	if ( mBlinkTimer->isActive() == false )
141
	{
142
		mIsBlinkIcon = true;
143
		mIsBlinking = true;
144
		mBlinkTimer->start( 1000, false );
145
	}
146
	else
147
	{
148
		mBlinkTimer->stop();
149
		mIsBlinkIcon = true;
150
		mIsBlinking = true;
151
		mBlinkTimer->start( 1000, false );
152
	}
153
}
154
155
void KopeteSystemTray::startBlink( const QMovie &movie )
156
{
157
	//kdDebug( 14010 ) << k_funcinfo << "starting movie." << endl;
158
	const_cast<QMovie &>( movie ).unpause();
159
	setMovie( movie );
160
	mIsBlinking = true;
161
}
162
163
void KopeteSystemTray::startBlink()
164
{
165
	if ( mMovie.isNull() )
166
		mMovie = KGlobal::iconLoader()->loadMovie( QString::fromLatin1( "newmessage" ), KIcon::Panel );
167
168
	startBlink( mMovie );
169
}
170
171
void KopeteSystemTray::stopBlink()
172
{
173
	if ( movie() )
174
		kdDebug( 14010 ) << k_funcinfo << "stopping movie." << endl;
175
	else if ( mBlinkTimer->isActive() )
176
		mBlinkTimer->stop();
177
178
	if ( !mMovie.isNull() )
179
		mMovie.pause();
180
181
	mIsBlinkIcon = false;
182
	mIsBlinking = false;
183
	//setPixmap( mKopeteIcon );
184
	slotReevaluateAccountStates();
185
}
186
187
void KopeteSystemTray::slotBlink()
188
{
189
	setPixmap( mIsBlinkIcon ? mKopeteIcon : mBlinkIcon );
190
191
	mIsBlinkIcon = !mIsBlinkIcon;
192
}
193
194
void KopeteSystemTray::slotNewEvent( Kopete::MessageEvent *event )
195
{
196
	mEventList.append( event );
197
	connect(event, SIGNAL(done(Kopete::MessageEvent*)),
198
		this, SLOT(slotEventDone(Kopete::MessageEvent*)));
199
200
	if( event->message().manager() != 0 )
201
	{
202
		if( event->message().manager()->account() )
203
		{
204
			if( !event->message().manager()->account()->isAway() ||
205
				KopetePrefs::prefs()->soundIfAway() )
206
			{
207
				addBalloon();
208
			}
209
			else
210
			{
211
				kdDebug(14000) << k_funcinfo << "Supressing balloon, account is away" << endl;
212
			}
213
		}
214
	}
215
	else
216
		kdDebug(14000) << k_funcinfo << "NULL message().manager()!" << endl;
217
218
	// tray animation
219
	if ( KopetePrefs::prefs()->trayflashNotify() )
220
		startBlink();
221
}
222
223
void KopeteSystemTray::slotEventDone(Kopete::MessageEvent *event)
224
{
225
	bool current= event==mEventList.first();
226
	mEventList.remove(event);
227
228
	if(current && m_balloon)
229
	{
230
		m_balloon->deleteLater();
231
		m_balloon=0l;
232
		if(!mEventList.isEmpty())
233
			addBalloon();
234
	}
235
236
	if(mEventList.isEmpty())
237
		stopBlink();
238
}
239
240
void KopeteSystemTray::addBalloon()
241
{
242
	/*kdDebug(14010) << k_funcinfo <<
243
		m_balloon << ":" << KopetePrefs::prefs()->showTray() <<
244
		":" << KopetePrefs::prefs()->balloonNotify()
245
		<< ":" << !mEventList.isEmpty() << endl;*/
246
247
	if( !m_balloon && KopetePrefs::prefs()->showTray() && KopetePrefs::prefs()->balloonNotify() && !mEventList.isEmpty() )
248
	{
249
		Kopete::Message msg = mEventList.first()->message();
250
251
		if ( msg.from() )
252
		{
253
			QString msgText = squashMessage( msg );
254
			kdDebug(14010) << k_funcinfo << "msg text=" << msgText << endl;
255
256
			QString msgFrom;
257
			if( msg.from()->metaContact() )
258
				msgFrom = msg.from()->metaContact()->displayName();
259
			else
260
				msgFrom = msg.from()->contactId();
261
262
			m_balloon = new KopeteBalloon(
263
				i18n( "<qt><nobr><b>New Message from %1:</b></nobr><br><nobr>\"%2\"</nobr></qt>" )
264
					.arg( msgFrom, msgText ), QString::null );
265
			connect(m_balloon, SIGNAL(signalBalloonClicked()), mEventList.first() , SLOT(apply()));
266
			connect(m_balloon, SIGNAL(signalButtonClicked()), mEventList.first() , SLOT(apply()));
267
			connect(m_balloon, SIGNAL(signalIgnoreButtonClicked()), mEventList.first() , SLOT(ignore()));
268
			m_balloon->setAnchor(mapToGlobal(pos()));
269
			m_balloon->show();
270
			KWin::setOnAllDesktops(m_balloon->winId(), true);
271
		}
272
	}
273
}
274
275
void KopeteSystemTray::slotConfigChanged()
276
{
277
//	kdDebug(14010) << k_funcinfo << "called." << endl;
278
	if ( KopetePrefs::prefs()->showTray() )
279
		show();
280
	else
281
		hide(); // for users without kicker or a similar docking app
282
}
283
284
void KopeteSystemTray::slotReevaluateAccountStates()
285
{
286
	// If there is a pending message, we don't need to refresh the system tray now.
287
	// This function will even be called when the animation will stop.
288
	if ( mIsBlinking )
289
		return;
290
291
	
292
	//kdDebug(14010) << k_funcinfo << endl;
293
	bool bOnline = false;
294
	bool bAway = false;
295
	bool bOffline = false;
296
	Kopete::Contact *c = 0;
297
298
	for (QPtrListIterator<Kopete::Account> it(Kopete::AccountManager::self()->accounts()); it.current(); ++it)
299
	{
300
		c = it.current()->myself();
301
		if (!c)
302
			continue;
303
304
		if (c->onlineStatus().status() == Kopete::OnlineStatus::Online)
305
		{
306
			bOnline = true; // at least one contact is online
307
		}
308
		else if (c->onlineStatus().status() == Kopete::OnlineStatus::Away
309
		      || c->onlineStatus().status() == Kopete::OnlineStatus::Invisible)
310
		{
311
			bAway = true; // at least one contact is away or invisible
312
		}
313
		else // this account must be offline (or unknown, which I don't know how to handle)
314
		{
315
			bOffline = true;
316
		}
317
	}
318
319
	if (!bOnline && !bAway && !bOffline) // special case, no accounts defined (yet)
320
		bOffline = true;
321
322
	if (bAway)
323
	{
324
		if (!bOnline && !bOffline) // none online and none offline -> all away
325
			setPixmap(loadIcon("kopete_all_away"));
326
		else
327
			setPixmap(loadIcon("kopete_some_away"));
328
	}
329
	else if(bOnline)
330
	{
331
		/*if(bOffline) // at least one offline and at least one online -> some accounts online
332
			setPixmap(loadIcon("kopete_some_online"));
333
		else*/ // none offline and none away -> all online
334
			setPixmap(mKopeteIcon);
335
	}
336
	else // none away and none online -> all offline
337
	{
338
		//kdDebug(14010) << k_funcinfo << "All Accounts offline!" << endl;
339
		setPixmap(loadIcon("kopete_offline"));
340
	}
341
}
342
343
344
QString KopeteSystemTray::squashMessage( const Kopete::Message& msg )
345
{
346
	QString msgText = msg.parsedBody();
347
348
	QRegExp rx( "(<a.*>((http://)?(.+))</a>)" );
349
	rx.setMinimal( true );
350
	if ( rx.search( msgText ) == -1 )
351
	{
352
		// no URLs in text, just pick the first 30 chars of
353
		// the parsed text if necessary. We used parsed text
354
		// so that things like "<knuff>" show correctly
355
		//  Escape it after snipping it to not snip entities
356
		msgText =msg.plainBody() ;
357
		if( msgText.length() > 30 )
358
			msgText = msgText.left( 30 ) + QString::fromLatin1( " ..." );
359
		msgText=Kopete::Message::escape(msgText);
360
	}
361
	else
362
	{
363
		QString plainText = msg.plainBody();
364
		if ( plainText.length() > 30 )
365
		{
366
			QString fullUrl = rx.cap( 2 );
367
			QString shorterUrl;
368
			if ( fullUrl.length() > 30 )
369
			{
370
				QString urlWithoutProtocol = rx.cap( 4 );
371
				shorterUrl = urlWithoutProtocol.left( 27 )
372
						+ QString::fromLatin1( "... " );
373
			}
374
			else
375
			{
376
				shorterUrl = fullUrl.left( 27 )
377
						+ QString::fromLatin1( "... " );
378
			}
379
			// remove message text
380
			msgText = QString::fromLatin1( "... " ) +
381
					rx.cap( 1 ) +
382
					QString::fromLatin1( " ..." );
383
			// find last occurrence of URL (the one inside the <a> tag)
384
			int revUrlOffset = msgText.findRev( fullUrl );
385
			msgText.replace( revUrlOffset,
386
						fullUrl.length(), shorterUrl );
387
		}
388
	}
389
	return msgText;
390
}
391
392
#include "systemtray.moc"
393
// vim: set noet ts=4 sts=4 sw=4:

Return to bug 93052