source: psi/trunk/src/tabdlg.cpp@ 7

Last change on this file since 7 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 9.6 KB
Line 
1/*
2 * tabdlg.cpp - dialog for handling tabbed chats
3 * Copyright (C) 2005 Kevin Smith
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include "tabdlg.h"
22#include "chatdlg.h"
23#include "iconwidget.h"
24#include "iconset.h"
25#include "common.h"
26#include "psicon.h"
27#include <qmenubar.h>
28#include <qcursor.h>
29#include <qdragobject.h>
30#include "psitabwidget.h"
31
32#ifdef Q_WS_WIN
33#include<windows.h>
34#endif
35
36//----------------------------------------------------------------------------
37// TabDlg
38//----------------------------------------------------------------------------
39TabDlg::TabDlg(PsiCon *psiCon)
40{
41 psi=psiCon;
42
43 //this->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
44
45 tabMenu = new QPopupMenu( this );
46 connect( tabMenu, SIGNAL( aboutToShow() ), SLOT( buildTabMenu() ) );
47
48 tabs = new KTabWidget (this);
49
50 closeCross = new QPushButton(this);
51 //closeCross->setText("x");
52 closeCross->setIconSet(IconsetFactory::icon("psi/closetab").iconSet());
53 closeCross->hide();
54 if (option.usePerTabCloseButton)
55 tabs->setHoverCloseButton(true);
56 else
57 {
58 tabs->setHoverCloseButton(false);
59 tabs->setCornerWidget( closeCross );
60 closeCross->show();
61 }
62
63 tabs->setHoverCloseButtonDelayed(false); //people may want this enabled, but it's currently horribly broken.
64 tabs->setTabReorderingEnabled(true);
65 tabs->setCloseIcon(IconsetFactory::icon("psi/closetab").iconSet());
66 connect (tabs, SIGNAL( mouseDoubleClick( QWidget* ) ), SLOT( detachChat( QWidget* ) ) );
67 connect (tabs, SIGNAL( testCanDecode(const QDragMoveEvent*, bool&) ), SLOT( tabTestCanDecode(const QDragMoveEvent*, bool&) ) );
68 connect (tabs, SIGNAL( receivedDropEvent( QDropEvent* ) ), SLOT( tabReceivedDropEvent( QDropEvent* ) ) );
69 connect (tabs, SIGNAL( receivedDropEvent( QWidget*, QDropEvent* ) ), SLOT( tabReceivedDropEvent( QWidget*, QDropEvent* ) ) );
70 connect (tabs, SIGNAL( initiateDrag( QWidget* ) ), SLOT( startDrag( QWidget* ) ) );
71 connect (tabs, SIGNAL( closeRequest( QWidget* ) ), SLOT( closeChat( QWidget* ) ) );
72
73
74 QVBoxLayout *vert1 = new QVBoxLayout( this, 1);
75 vert1->addWidget(tabs);
76 chats.setAutoDelete( FALSE );
77 X11WM_CLASS("chat");
78
79 connect( closeCross, SIGNAL( clicked() ), SLOT( closeChat() ) );
80 connect( tabs, SIGNAL( currentChanged( QWidget* ) ), SLOT( tabSelected( QWidget* ) ) );
81
82 setAcceptDrops(TRUE);
83
84
85
86
87 setLooks();
88
89 resize(option.sizeTabDlg);
90}
91
92TabDlg::~TabDlg()
93{
94
95}
96
97void TabDlg::resizeEvent(QResizeEvent *e)
98{
99 if(option.keepSizes)
100 option.sizeTabDlg = e->size();
101}
102
103void TabDlg::buildTabMenu()
104{
105 tabMenu->clear();
106 tabMenu->insertItem( tr("Detach Current Tab"), this, SLOT( detachChat() ) );
107 tabMenu->insertItem( tr("Close Current Tab"), this, SLOT( closeChat() ) );
108
109 QPopupMenu* sendTo = new QPopupMenu(tabMenu);
110 for (uint i = 0; i < psi->getTabSets()->count(); ++i)
111 {
112 TabDlg* tabSet= psi->getTabSets()->at(i);
113 sendTo->insertItem( tabSet->getName(), this, SLOT( sendChatTo( tabSet ) ) );
114 }
115 tabMenu->insertItem( tr("Sent Current Tab to"), sendTo);
116}
117
118void TabDlg::sendChatTo(QWidget* chatw, TabDlg* otherTabs)
119{
120 if (otherTabs==this)
121 return;
122 ChatDlg* chat = (ChatDlg*)chatw;
123 closeChat(chat, false);
124 otherTabs->addChat(chat);
125}
126
127void TabDlg::setLooks()
128{
129 //set the widget icon
130#ifndef Q_WS_MAC
131 setIcon(IconsetFactory::icon("psi/start-chat"));
132#endif
133 tabs->setTabPosition(QTabWidget::Top);
134 if (option.putTabsAtBottom)
135 tabs->setTabPosition(QTabWidget::Bottom);
136
137#if QT_VERSION >= 0x030300
138 setWindowOpacity(double(option.chatOpacity)/100);
139#endif
140}
141
142QString TabDlg::getName()
143{
144 return ((ChatDlg*)(tabs->currentPage()))->getDisplayNick();
145}
146
147void TabDlg::tabSelected(QWidget* chat)
148{
149 ((ChatDlg*)chat)->activated(); //is this still necessary?
150 updateCaption();
151}
152
153bool TabDlg::managesChat(ChatDlg* chat)
154{
155 if ( chats.contains(chat) )
156 return true;
157 return false;
158}
159
160bool TabDlg::chatOnTop(ChatDlg* chat)
161{
162 if ( tabs->currentPage() == chat )
163 return true;
164 return false;
165}
166
167void TabDlg::addChat(ChatDlg* chat)
168{
169 chats.append(chat);
170 tabs->addTab(chat, chat->getDisplayNick());
171 tabs->setTabIconSet(chat, IconsetFactory::icon("psi/start-chat"));
172
173 tabs->showPage(chat);
174 connect ( chat, SIGNAL( captionChanged( ChatDlg*) ), SLOT( updateTab( ChatDlg* ) ) );
175 connect ( chat, SIGNAL( contactIsComposing(ChatDlg*, bool) ), SLOT( setTabComposing( ChatDlg*, bool) ) );
176 connect ( chat, SIGNAL( unreadMessageUpdate(ChatDlg*, int) ), SLOT( setTabHasMessages(ChatDlg*, int) ) );
177
178 this->show();
179 updateCaption();
180}
181
182void TabDlg::detachChat()
183{
184 detachChat(tabs->currentPage());
185}
186
187void TabDlg::detachChat(QWidget* chat)
188{
189 //don't detach singleton chats, fix for flyspray #477
190 if (tabs->count()==1)
191 return;
192
193 TabDlg *newTab = psi->newTabs();
194 sendChatTo(chat, newTab);
195}
196
197void TabDlg::closeChat()
198{
199 ChatDlg* chat = (ChatDlg*)(tabs->currentPage());
200 closeChat(chat);
201}
202
203void TabDlg::closeChat(ChatDlg* chat, bool doclose=true)
204{
205 chat->hide();
206 disconnect ( chat, SIGNAL( captionChanged( ChatDlg*) ), this, SLOT( updateTab( ChatDlg* ) ) );
207 disconnect ( chat, SIGNAL( contactIsComposing(ChatDlg*, bool) ), this, SLOT( setTabComposing( ChatDlg*, bool) ) );
208 disconnect ( chat, SIGNAL( unreadMessageUpdate(ChatDlg*, int) ), this, SLOT( setTabHasMessages(ChatDlg*, int) ) );
209 tabs->removePage(chat);
210 tabIsComposing.erase(chat);
211 tabHasMessages.erase(chat);
212 chats.remove(chat);
213 chat->reparent(0,QPoint());
214 if (doclose)
215 chat->close();
216 if (tabs->count()>0)
217 updateCaption();
218 checkHasChats();
219}
220
221void TabDlg::closeChat(QWidget* chat)
222{
223 closeChat((ChatDlg*)chat);
224}
225
226void TabDlg::selectTab(ChatDlg* chat)
227{
228 tabs->showPage(chat);
229}
230
231void TabDlg::checkHasChats()
232{
233 if (tabs->count()>0)
234 return;
235 closeMe();
236}
237
238void TabDlg::windowActivationChange(bool oldstate)
239{
240 QWidget::windowActivationChange(oldstate);
241
242 // if we're bringing it to the front, get rid of the '*' if necessary
243 if( isActiveWindow() ) {
244 activated();
245 }
246}
247
248void TabDlg::activated()
249{
250 updateCaption();
251 doFlash(false);
252}
253
254void TabDlg::updateCaption()
255{
256 QString cap = "";
257 uint pending=0;
258 for ( uint i=0; i<tabHasMessages.count(); ++i)
259 {
260 pending+=tabHasMessages.values()[i];
261 }
262 if(pending > 0) {
263 cap += "* ";
264 if(pending > 1)
265 cap += QString("[%1] ").arg(pending);
266 }
267 cap += getName();
268
269 setCaption(cap);
270}
271
272void TabDlg::closeEvent(QCloseEvent* closeEvent)
273{
274 Q_UNUSED(closeEvent);
275 int count=tabs->count();
276 for (int i=0;i<count;++i) {
277 closeChat();
278 }
279}
280
281void TabDlg::closeMe()
282{
283 emit isDying(this);
284 //we do not delete it here, let the PsiCon do that, they create, they destroy.
285}
286
287ChatDlg* TabDlg::getChatPointer(QString fullJid)
288{
289 for (int i=0; i < tabs->count() ; i++)
290 {
291 if (((ChatDlg*)tabs->page(i))->jid().full()==fullJid)
292 {
293 return (ChatDlg*)(tabs->page(i));
294 }
295 }
296 return false;
297}
298
299void TabDlg::updateTab( ChatDlg* chat)
300{
301 QString label, prefix;
302 int num=tabHasMessages[chat];
303 if (num == 0)
304 {
305 prefix="";
306 }
307 else if (num == 1)
308 {
309 prefix="* ";
310 }
311 else
312 {
313 prefix=QString("[%1] ").arg(num);
314 }
315
316 label=prefix+chat->getDisplayNick();
317 tabs->setTabLabel( chat, label );
318 //now set text colour based upon whether there are new messages/composing etc
319 if (tabIsComposing[chat])
320 tabs->setTabColor( chat, Qt::darkGreen );
321 else if (tabHasMessages[chat])
322 {
323 tabs->setTabColor( chat, Qt::red );
324 doFlash(true);
325 }
326 else
327 tabs->setTabColor( chat, Qt::black );
328 updateCaption();
329}
330
331void TabDlg::setTabComposing(ChatDlg* chat, bool composing)
332{
333 tabIsComposing[chat]=composing;
334 updateTab(chat);
335}
336
337void TabDlg::setTabHasMessages(ChatDlg* chat, int messages)
338{
339 tabHasMessages[chat]=messages;
340 updateTab(chat);
341}
342
343void TabDlg::nextTab()
344{
345 int page = tabs->currentPageIndex()+1;
346 if ( page >= tabs->count() )
347 page = 0;
348 tabs->setCurrentPage( page );
349}
350
351void TabDlg::previousTab()
352{
353 int page = tabs->currentPageIndex()-1;
354 if ( page < 0 )
355 page = tabs->count() - 1;
356 tabs->setCurrentPage( page );
357}
358
359void TabDlg::tabTestCanDecode(const QDragMoveEvent* e, bool &b){
360 QString jid;
361 QCString type;
362 if ( QTextDrag::canDecode(e) && QTextDrag::decode(e, jid, type) && type=="psichatwindow" )
363 {
364 b=true;
365 }
366 else
367 {
368 b=false;
369 }
370}
371
372void TabDlg::tabReceivedDropEvent(QDropEvent* e){
373 ChatDlg* chat;
374 QString jid;
375 QCString type;
376 if ( QTextDrag::decode(e, jid, type) && type=="psichatwindow" ) {
377 chat=psi->getChatInTabs(jid);
378 if (chat)
379 {
380 TabDlg *dlg=psi->getManagingTabs(chat);
381 dlg->sendChatTo(chat, this);
382 }
383 }
384}
385
386void TabDlg::tabReceivedDropEvent(QWidget* w, QDropEvent* e){
387 Q_UNUSED(w);
388 tabReceivedDropEvent(e);
389}
390
391
392void TabDlg::startDrag(QWidget* w)
393{
394 QDragObject *d = new QTextDrag( ((ChatDlg*)w)->jid().full(), this );
395 ((QTextDrag*)d)->setSubtype("psichatwindow");
396 d->dragCopy();
397 // do NOT delete d.
398}
399
400void TabDlg::keyPressEvent(QKeyEvent *e)
401{
402 if (e->key() == Key_Escape)
403 {
404 closeChat();
405 }
406 else if ( e->key() == Key_W && (e->state() & ControlButton) )
407 {
408 closeChat();
409 }
410 else if ( e->key() == Key_PageUp && (e->state() & ControlButton) )
411 {
412 previousTab();
413 }
414 else if ( e->key() == Key_PageDown && (e->state() & ControlButton) )
415 {
416 nextTab();
417 }
418 else
419 e->ignore();
420
421}
422
Note: See TracBrowser for help on using the repository browser.