~ubuntu-branches/ubuntu/maverick/psi/maverick

« back to all changes in this revision

Viewing changes to src/tabdlg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2006-01-20 00:20:36 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060120002036-7nw6yo6totip0ee5
Tags: 0.10-2
* Added upstream changelog (Closes: Bug#327748)
* Mention --no-gpg and --no-gpg-agent in manpage (Closes: Bug#204416)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
//----------------------------------------------------------------------------
 
39
TabDlg::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
 
 
92
TabDlg::~TabDlg()
 
93
{
 
94
 
 
95
}
 
96
 
 
97
void TabDlg::resizeEvent(QResizeEvent *e)
 
98
{
 
99
  if(option.keepSizes)
 
100
        option.sizeTabDlg = e->size();
 
101
}
 
102
 
 
103
void 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
 
 
118
void 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
 
 
127
void 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
 
 
142
QString TabDlg::getName()
 
143
{
 
144
        return ((ChatDlg*)(tabs->currentPage()))->getDisplayNick();
 
145
}
 
146
 
 
147
void TabDlg::tabSelected(QWidget* chat)
 
148
{
 
149
        ((ChatDlg*)chat)->activated(); //is this still necessary?
 
150
        updateCaption();
 
151
}
 
152
 
 
153
bool TabDlg::managesChat(ChatDlg* chat)
 
154
{
 
155
        if ( chats.contains(chat) )
 
156
                        return true;
 
157
        return false;
 
158
}
 
159
 
 
160
bool TabDlg::chatOnTop(ChatDlg* chat)
 
161
{
 
162
        if ( tabs->currentPage() == chat )
 
163
                return true;
 
164
        return false;
 
165
}
 
166
 
 
167
void 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
 
 
182
void TabDlg::detachChat()
 
183
{
 
184
        detachChat(tabs->currentPage());
 
185
}
 
186
 
 
187
void 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
 
 
197
void TabDlg::closeChat()
 
198
{
 
199
        ChatDlg* chat = (ChatDlg*)(tabs->currentPage());
 
200
        closeChat(chat);
 
201
}
 
202
 
 
203
void 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
 
 
221
void TabDlg::closeChat(QWidget* chat)
 
222
{
 
223
        closeChat((ChatDlg*)chat);
 
224
}
 
225
 
 
226
void TabDlg::selectTab(ChatDlg* chat)
 
227
{
 
228
        tabs->showPage(chat);
 
229
}
 
230
 
 
231
void TabDlg::checkHasChats()
 
232
{
 
233
        if (tabs->count()>0)
 
234
                return;
 
235
        closeMe();
 
236
}
 
237
 
 
238
void 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
 
 
248
void TabDlg::activated()
 
249
{
 
250
        updateCaption();
 
251
        doFlash(false);
 
252
}
 
253
 
 
254
void 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
 
 
272
void 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
 
 
281
void 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
 
 
287
ChatDlg* 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
 
 
299
void 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
 
 
331
void TabDlg::setTabComposing(ChatDlg* chat, bool composing)
 
332
{
 
333
        tabIsComposing[chat]=composing;
 
334
        updateTab(chat);
 
335
}
 
336
 
 
337
void TabDlg::setTabHasMessages(ChatDlg* chat, int messages)
 
338
{
 
339
        tabHasMessages[chat]=messages;
 
340
        updateTab(chat);
 
341
}
 
342
 
 
343
void TabDlg::nextTab()
 
344
{
 
345
        int page = tabs->currentPageIndex()+1;
 
346
        if ( page >= tabs->count() )
 
347
                page = 0;
 
348
        tabs->setCurrentPage( page );
 
349
}
 
350
 
 
351
void TabDlg::previousTab()
 
352
{
 
353
        int page = tabs->currentPageIndex()-1;
 
354
        if ( page < 0 )
 
355
                page = tabs->count() - 1;
 
356
        tabs->setCurrentPage( page );
 
357
}
 
358
 
 
359
void 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
 
 
372
void 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
 
 
386
void TabDlg::tabReceivedDropEvent(QWidget* w, QDropEvent* e){
 
387
        Q_UNUSED(w);
 
388
        tabReceivedDropEvent(e);
 
389
}
 
390
 
 
391
 
 
392
void 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
 
 
400
void 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